@pushflodev/sdk 1.0.6 → 1.0.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/dist/server.cjs CHANGED
@@ -4,8 +4,10 @@
4
4
 
5
5
  // src/utils/constants.ts
6
6
  var DEFAULTS = {
7
- /** Default PushFlo API base URL */
7
+ /** Default PushFlo Realtime API base URL */
8
8
  BASE_URL: "https://api.pushflo.dev",
9
+ /** Default PushFlo Console API base URL (for channel management) */
10
+ CONSOLE_URL: "https://console.pushflo.dev",
9
11
  /** API version prefix */
10
12
  API_VERSION: "/api/v1",
11
13
  /** Connection timeout in milliseconds */
@@ -451,6 +453,9 @@ var RestClient = class {
451
453
  try {
452
454
  const json = await response.json();
453
455
  if (json && typeof json === "object" && "success" in json && "data" in json) {
456
+ if ("pagination" in json) {
457
+ return { data: json.data, pagination: json.pagination };
458
+ }
454
459
  return json.data;
455
460
  }
456
461
  return json;
@@ -493,7 +498,7 @@ var ValidationError = class _ValidationError extends PushFloError {
493
498
  };
494
499
 
495
500
  // src/utils/validation.ts
496
- var MAX_SLUG_LENGTH = 64;
501
+ var MAX_SLUG_LENGTH = 128;
497
502
  var MIN_SLUG_LENGTH = 1;
498
503
  var SLUG_REGEX = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;
499
504
  function isValidChannelSlug(slug) {
@@ -573,7 +578,10 @@ function validateChannelSlug(slug) {
573
578
 
574
579
  // src/server/PushFloServer.ts
575
580
  var PushFloServer = class {
576
- client;
581
+ /** Client for Realtime API (publish, message history) */
582
+ realtimeClient;
583
+ /** Client for Console API (channel CRUD) */
584
+ consoleClient;
577
585
  constructor(options) {
578
586
  if (!options.secretKey) {
579
587
  throw new AuthenticationError(
@@ -584,59 +592,70 @@ var PushFloServer = class {
584
592
  if (!options.secretKey.startsWith("sec_") && !options.secretKey.startsWith("mgmt_")) {
585
593
  throw AuthenticationError.invalidKey("secret");
586
594
  }
587
- this.client = new RestClient({
595
+ this.realtimeClient = new RestClient({
596
+ apiKey: options.secretKey,
597
+ baseUrl: options.baseUrl || DEFAULTS.BASE_URL,
598
+ timeout: options.timeout,
599
+ retryAttempts: options.retryAttempts,
600
+ debug: options.debug
601
+ });
602
+ this.consoleClient = new RestClient({
588
603
  apiKey: options.secretKey,
589
- baseUrl: options.baseUrl,
604
+ baseUrl: options.consoleUrl || DEFAULTS.CONSOLE_URL,
590
605
  timeout: options.timeout,
591
606
  retryAttempts: options.retryAttempts,
592
607
  debug: options.debug
593
608
  });
594
609
  }
595
610
  // ============================================
596
- // Channel Management
611
+ // Channel Management (Console API)
597
612
  // ============================================
598
613
  /**
599
614
  * List all channels
615
+ * @note Requires mgmt_ key. Uses Console API.
600
616
  */
601
617
  async listChannels(options = {}) {
602
- const response = await this.client.get(API_PATHS.CHANNELS, {
618
+ const response = await this.consoleClient.get(API_PATHS.CHANNELS, {
603
619
  page: options.page,
604
620
  pageSize: options.pageSize ?? DEFAULTS.PAGE_SIZE
605
621
  });
606
622
  return {
607
- channels: response.channels,
623
+ channels: response.data,
608
624
  pagination: response.pagination
609
625
  };
610
626
  }
611
627
  /**
612
628
  * Get a channel by slug
629
+ * @note Requires mgmt_ key. Uses Console API.
613
630
  */
614
631
  async getChannel(slug) {
615
632
  this.validateSlug(slug);
616
- return this.client.get(API_PATHS.CHANNEL(slug));
633
+ return this.consoleClient.get(API_PATHS.CHANNEL(slug));
617
634
  }
618
635
  /**
619
636
  * Create a new channel
620
- *
637
+ * @note Requires mgmt_ key. Uses Console API.
621
638
  * @throws {ValidationError} If the channel slug is invalid
622
639
  */
623
640
  async createChannel(input) {
624
641
  this.validateSlug(input.slug);
625
- return this.client.post(API_PATHS.CHANNELS, input);
642
+ return this.consoleClient.post(API_PATHS.CHANNELS, input);
626
643
  }
627
644
  /**
628
645
  * Update an existing channel
646
+ * @note Requires mgmt_ key. Uses Console API.
629
647
  */
630
648
  async updateChannel(slug, input) {
631
649
  this.validateSlug(slug);
632
- return this.client.patch(API_PATHS.CHANNEL(slug), input);
650
+ return this.consoleClient.patch(API_PATHS.CHANNEL(slug), input);
633
651
  }
634
652
  /**
635
653
  * Delete a channel
654
+ * @note Requires mgmt_ key. Uses Console API.
636
655
  */
637
656
  async deleteChannel(slug) {
638
657
  this.validateSlug(slug);
639
- await this.client.delete(API_PATHS.CHANNEL(slug));
658
+ await this.consoleClient.delete(API_PATHS.CHANNEL(slug));
640
659
  }
641
660
  /**
642
661
  * Validate a channel slug and throw if invalid
@@ -652,28 +671,28 @@ var PushFloServer = class {
652
671
  }
653
672
  }
654
673
  // ============================================
655
- // Message Publishing
674
+ // Message Publishing (Realtime API)
656
675
  // ============================================
657
676
  /**
658
677
  * Publish a message to a channel
659
- *
678
+ * @note Uses Realtime API. Works with sec_ or mgmt_ key.
660
679
  * @throws {ValidationError} If the channel slug is invalid
661
680
  */
662
681
  async publish(channel, content, options = {}) {
663
682
  this.validateSlug(channel);
664
- return this.client.post(API_PATHS.CHANNEL_MESSAGES(channel), {
683
+ return this.realtimeClient.post(API_PATHS.CHANNEL_MESSAGES(channel), {
665
684
  content,
666
685
  eventType: options.eventType ?? "message"
667
686
  });
668
687
  }
669
688
  /**
670
689
  * Get message history for a channel
671
- *
690
+ * @note Uses Realtime API. Works with sec_ or mgmt_ key.
672
691
  * @throws {ValidationError} If the channel slug is invalid
673
692
  */
674
693
  async getMessageHistory(channel, options = {}) {
675
694
  this.validateSlug(channel);
676
- const response = await this.client.get(
695
+ const response = await this.realtimeClient.get(
677
696
  API_PATHS.CHANNEL_MESSAGES(channel),
678
697
  {
679
698
  page: options.page,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/constants.ts","../src/utils/retry.ts","../src/utils/logger.ts","../src/errors/PushFloError.ts","../src/errors/AuthenticationError.ts","../src/errors/NetworkError.ts","../src/server/RestClient.ts","../src/errors/ValidationError.ts","../src/utils/validation.ts","../src/server/PushFloServer.ts"],"names":[],"mappings":"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","file":"server.cjs","sourcesContent":["/**\n * Default configuration values\n */\nexport const DEFAULTS = {\n /** Default PushFlo API base URL */\n BASE_URL: 'https://api.pushflo.dev',\n\n /** WebSocket endpoint path */\n WS_PATH: '/ws',\n\n /** API version prefix */\n API_VERSION: '/api/v1',\n\n /** Connection timeout in milliseconds */\n CONNECTION_TIMEOUT: 30000,\n\n /** Heartbeat interval in milliseconds */\n HEARTBEAT_INTERVAL: 25000,\n\n /** Initial reconnection delay in milliseconds */\n RECONNECT_DELAY: 1000,\n\n /** Maximum reconnection delay in milliseconds */\n MAX_RECONNECT_DELAY: 30000,\n\n /** Reconnection delay multiplier for exponential backoff */\n RECONNECT_MULTIPLIER: 1.5,\n\n /** Maximum number of reconnection attempts (0 = infinite) */\n MAX_RECONNECT_ATTEMPTS: 0,\n\n /** Default page size for list operations */\n PAGE_SIZE: 25,\n} as const;\n\n/**\n * API endpoint paths\n */\nexport const API_PATHS = {\n AUTH_TOKEN: '/auth/token',\n CHANNELS: '/channels',\n CHANNEL: (slug: string) => `/channels/${encodeURIComponent(slug)}`,\n CHANNEL_MESSAGES: (slug: string) => `/channels/${encodeURIComponent(slug)}/messages`,\n} as const;\n\n/**\n * WebSocket message types (client -> server)\n */\nexport const WS_CLIENT_MESSAGES = {\n SUBSCRIBE: 'subscribe',\n UNSUBSCRIBE: 'unsubscribe',\n PING: 'ping',\n ACK: 'ack',\n} as const;\n\n/**\n * WebSocket message types (server -> client)\n */\nexport const WS_SERVER_MESSAGES = {\n CONNECTED: 'connected',\n SUBSCRIBED: 'subscribed',\n UNSUBSCRIBED: 'unsubscribed',\n MESSAGE: 'message',\n ERROR: 'error',\n PONG: 'pong',\n} as const;\n\n/**\n * Error codes\n */\nexport const ERROR_CODES = {\n // Connection errors\n CONNECTION_FAILED: 'CONNECTION_FAILED',\n CONNECTION_TIMEOUT: 'CONNECTION_TIMEOUT',\n CONNECTION_CLOSED: 'CONNECTION_CLOSED',\n\n // Authentication errors\n INVALID_API_KEY: 'INVALID_API_KEY',\n UNAUTHORIZED: 'UNAUTHORIZED',\n FORBIDDEN: 'FORBIDDEN',\n\n // Network errors\n NETWORK_ERROR: 'NETWORK_ERROR',\n REQUEST_TIMEOUT: 'REQUEST_TIMEOUT',\n\n // API errors\n NOT_FOUND: 'NOT_FOUND',\n VALIDATION_ERROR: 'VALIDATION_ERROR',\n RATE_LIMITED: 'RATE_LIMITED',\n SERVER_ERROR: 'SERVER_ERROR',\n\n // Client errors\n INVALID_STATE: 'INVALID_STATE',\n ALREADY_CONNECTED: 'ALREADY_CONNECTED',\n NOT_CONNECTED: 'NOT_CONNECTED',\n CHANNEL_NOT_FOUND: 'CHANNEL_NOT_FOUND',\n} as const;\n","import { DEFAULTS } from './constants.js';\n\nexport interface RetryOptions {\n /** Maximum number of retry attempts (0 = infinite) */\n maxAttempts?: number;\n /** Initial delay in milliseconds */\n initialDelay?: number;\n /** Maximum delay in milliseconds */\n maxDelay?: number;\n /** Delay multiplier for exponential backoff */\n multiplier?: number;\n /** Function to determine if error is retryable */\n isRetryable?: (error: unknown) => boolean;\n /** Callback for each retry attempt */\n onRetry?: (attempt: number, delay: number, error: unknown) => void;\n /** Abort signal for cancellation */\n signal?: AbortSignal;\n}\n\n/**\n * Calculate delay with exponential backoff and jitter\n */\nexport function calculateBackoff(\n attempt: number,\n options: {\n initialDelay?: number;\n maxDelay?: number;\n multiplier?: number;\n } = {}\n): number {\n const {\n initialDelay = DEFAULTS.RECONNECT_DELAY,\n maxDelay = DEFAULTS.MAX_RECONNECT_DELAY,\n multiplier = DEFAULTS.RECONNECT_MULTIPLIER,\n } = options;\n\n // Exponential backoff\n const exponentialDelay = initialDelay * Math.pow(multiplier, attempt);\n\n // Cap at max delay\n const cappedDelay = Math.min(exponentialDelay, maxDelay);\n\n // Add jitter (±25%)\n const jitter = cappedDelay * 0.25 * (Math.random() * 2 - 1);\n\n return Math.floor(cappedDelay + jitter);\n}\n\n/**\n * Sleep for a given duration (cancellable)\n */\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(new DOMException('Aborted', 'AbortError'));\n return;\n }\n\n const timeoutId = setTimeout(resolve, ms);\n\n signal?.addEventListener(\n 'abort',\n () => {\n clearTimeout(timeoutId);\n reject(new DOMException('Aborted', 'AbortError'));\n },\n { once: true }\n );\n });\n}\n\n/**\n * Retry a function with exponential backoff\n */\nexport async function retry<T>(\n fn: () => Promise<T>,\n options: RetryOptions = {}\n): Promise<T> {\n const {\n maxAttempts = 3,\n initialDelay = DEFAULTS.RECONNECT_DELAY,\n maxDelay = DEFAULTS.MAX_RECONNECT_DELAY,\n multiplier = DEFAULTS.RECONNECT_MULTIPLIER,\n isRetryable = () => true,\n onRetry,\n signal,\n } = options;\n\n let lastError: unknown;\n let attempt = 0;\n\n while (maxAttempts === 0 || attempt < maxAttempts) {\n try {\n if (signal?.aborted) {\n throw new DOMException('Aborted', 'AbortError');\n }\n return await fn();\n } catch (error) {\n lastError = error;\n\n // Don't retry abort errors\n if (error instanceof DOMException && error.name === 'AbortError') {\n throw error;\n }\n\n // Check if we should retry\n if (!isRetryable(error)) {\n throw error;\n }\n\n // Check if we've exhausted attempts\n if (maxAttempts !== 0 && attempt >= maxAttempts - 1) {\n throw error;\n }\n\n // Calculate delay\n const delay = calculateBackoff(attempt, { initialDelay, maxDelay, multiplier });\n\n // Notify retry callback\n onRetry?.(attempt + 1, delay, error);\n\n // Wait before next attempt\n await sleep(delay, signal);\n\n attempt++;\n }\n }\n\n throw lastError;\n}\n\n/**\n * Create a retry function with preset options\n */\nexport function createRetry(defaultOptions: RetryOptions) {\n return <T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T> => {\n return retry(fn, { ...defaultOptions, ...options });\n };\n}\n","export type LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\nexport interface LoggerOptions {\n /** Enable debug logging */\n debug?: boolean;\n /** Custom log prefix */\n prefix?: string;\n /** Minimum log level */\n level?: LogLevel;\n}\n\nconst LOG_LEVELS: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\n/**\n * Simple logger with debug mode support\n */\nexport class Logger {\n private enabled: boolean;\n private prefix: string;\n private minLevel: number;\n\n constructor(options: LoggerOptions = {}) {\n this.enabled = options.debug ?? false;\n this.prefix = options.prefix ?? '[PushFlo]';\n this.minLevel = LOG_LEVELS[options.level ?? 'debug'];\n }\n\n /**\n * Enable or disable logging\n */\n setEnabled(enabled: boolean): void {\n this.enabled = enabled;\n }\n\n /**\n * Set minimum log level\n */\n setLevel(level: LogLevel): void {\n this.minLevel = LOG_LEVELS[level];\n }\n\n /**\n * Log a debug message\n */\n debug(message: string, ...args: unknown[]): void {\n this.log('debug', message, ...args);\n }\n\n /**\n * Log an info message\n */\n info(message: string, ...args: unknown[]): void {\n this.log('info', message, ...args);\n }\n\n /**\n * Log a warning message\n */\n warn(message: string, ...args: unknown[]): void {\n this.log('warn', message, ...args);\n }\n\n /**\n * Log an error message\n */\n error(message: string, ...args: unknown[]): void {\n this.log('error', message, ...args);\n }\n\n private log(level: LogLevel, message: string, ...args: unknown[]): void {\n if (!this.enabled && level !== 'error') {\n return;\n }\n\n if (LOG_LEVELS[level] < this.minLevel) {\n return;\n }\n\n const timestamp = new Date().toISOString();\n const formattedMessage = `${this.prefix} ${timestamp} [${level.toUpperCase()}] ${message}`;\n\n switch (level) {\n case 'debug':\n console.debug(formattedMessage, ...args);\n break;\n case 'info':\n console.info(formattedMessage, ...args);\n break;\n case 'warn':\n console.warn(formattedMessage, ...args);\n break;\n case 'error':\n console.error(formattedMessage, ...args);\n break;\n }\n }\n}\n\n/**\n * Create a child logger with a custom prefix\n */\nexport function createLogger(options: LoggerOptions = {}): Logger {\n return new Logger(options);\n}\n","/**\n * Base error class for all PushFlo SDK errors\n */\nexport class PushFloError extends Error {\n /** Error code for programmatic handling */\n readonly code: string;\n\n /** Whether this error is potentially recoverable through retry */\n readonly retryable: boolean;\n\n /** Original error that caused this error, if any */\n readonly cause?: Error;\n\n constructor(\n message: string,\n code: string,\n options: { retryable?: boolean; cause?: Error } = {}\n ) {\n super(message);\n this.name = 'PushFloError';\n this.code = code;\n this.retryable = options.retryable ?? false;\n this.cause = options.cause;\n\n // Maintain proper stack trace in V8 environments\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n\n /**\n * Convert error to JSON-serializable object\n */\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n retryable: this.retryable,\n stack: this.stack,\n cause: this.cause?.message,\n };\n }\n\n /**\n * Create a string representation\n */\n toString(): string {\n return `${this.name} [${this.code}]: ${this.message}`;\n }\n}\n","import { PushFloError } from './PushFloError.js';\nimport { ERROR_CODES } from '../utils/constants.js';\n\n/**\n * Error thrown when authentication fails\n */\nexport class AuthenticationError extends PushFloError {\n constructor(\n message: string,\n code: string = ERROR_CODES.UNAUTHORIZED,\n options: { retryable?: boolean; cause?: Error } = {}\n ) {\n // Authentication errors are generally not retryable\n super(message, code, { retryable: false, ...options });\n this.name = 'AuthenticationError';\n }\n\n /**\n * Create an invalid API key error\n */\n static invalidKey(keyType?: string): AuthenticationError {\n const message = keyType\n ? `Invalid ${keyType} API key`\n : 'Invalid API key';\n return new AuthenticationError(message, ERROR_CODES.INVALID_API_KEY);\n }\n\n /**\n * Create an unauthorized error\n */\n static unauthorized(reason?: string): AuthenticationError {\n return new AuthenticationError(\n reason ?? 'Unauthorized - check your API key',\n ERROR_CODES.UNAUTHORIZED\n );\n }\n\n /**\n * Create a forbidden error\n */\n static forbidden(action?: string): AuthenticationError {\n const message = action\n ? `Access forbidden: insufficient permissions for ${action}`\n : 'Access forbidden: insufficient permissions';\n return new AuthenticationError(message, ERROR_CODES.FORBIDDEN);\n }\n}\n","import { PushFloError } from './PushFloError.js';\nimport { ERROR_CODES } from '../utils/constants.js';\n\n/**\n * Error thrown for network-related failures\n */\nexport class NetworkError extends PushFloError {\n /** HTTP status code, if applicable */\n readonly statusCode?: number;\n\n constructor(\n message: string,\n code: string = ERROR_CODES.NETWORK_ERROR,\n options: { retryable?: boolean; cause?: Error; statusCode?: number } = {}\n ) {\n super(message, code, { retryable: true, ...options });\n this.name = 'NetworkError';\n this.statusCode = options.statusCode;\n }\n\n /**\n * Create a network error from fetch failure\n */\n static fromFetch(cause: Error): NetworkError {\n return new NetworkError(\n `Network request failed: ${cause.message}`,\n ERROR_CODES.NETWORK_ERROR,\n { retryable: true, cause }\n );\n }\n\n /**\n * Create a request timeout error\n */\n static timeout(timeoutMs: number): NetworkError {\n return new NetworkError(\n `Request timed out after ${timeoutMs}ms`,\n ERROR_CODES.REQUEST_TIMEOUT,\n { retryable: true }\n );\n }\n\n /**\n * Create an error from HTTP status code\n */\n static fromStatus(statusCode: number, message?: string): NetworkError {\n const defaultMessage = NetworkError.getStatusMessage(statusCode);\n\n // Determine if retryable based on status\n const retryable = statusCode >= 500 || statusCode === 429;\n\n // Map status to error code\n let code: string = ERROR_CODES.SERVER_ERROR;\n if (statusCode === 404) {\n code = ERROR_CODES.NOT_FOUND;\n } else if (statusCode === 422 || statusCode === 400) {\n code = ERROR_CODES.VALIDATION_ERROR;\n } else if (statusCode === 429) {\n code = ERROR_CODES.RATE_LIMITED;\n }\n\n return new NetworkError(\n message ?? defaultMessage,\n code,\n { retryable, statusCode }\n );\n }\n\n private static getStatusMessage(statusCode: number): string {\n const messages: Record<number, string> = {\n 400: 'Bad request',\n 404: 'Resource not found',\n 422: 'Validation error',\n 429: 'Rate limit exceeded',\n 500: 'Internal server error',\n 502: 'Bad gateway',\n 503: 'Service unavailable',\n 504: 'Gateway timeout',\n };\n return messages[statusCode] ?? `HTTP error ${statusCode}`;\n }\n\n toJSON(): Record<string, unknown> {\n return {\n ...super.toJSON(),\n statusCode: this.statusCode,\n };\n }\n}\n","import { DEFAULTS } from '../utils/constants.js';\nimport { retry, type RetryOptions } from '../utils/retry.js';\nimport { createLogger, type Logger } from '../utils/logger.js';\nimport { AuthenticationError } from '../errors/AuthenticationError.js';\nimport { NetworkError } from '../errors/NetworkError.js';\nimport type { ApiErrorResponse } from '../types/api.js';\n\nexport interface RestClientOptions {\n /** API key (secret or management key) */\n apiKey: string;\n\n /** Base URL for the API */\n baseUrl?: string;\n\n /** Request timeout in milliseconds */\n timeout?: number;\n\n /** Number of retry attempts */\n retryAttempts?: number;\n\n /** Enable debug logging */\n debug?: boolean;\n}\n\n/**\n * HTTP client for PushFlo REST API\n */\nexport class RestClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n private readonly retryAttempts: number;\n private readonly logger: Logger;\n\n constructor(options: RestClientOptions) {\n this.apiKey = options.apiKey;\n this.baseUrl = (options.baseUrl ?? DEFAULTS.BASE_URL).replace(/\\/$/, '');\n this.timeout = options.timeout ?? DEFAULTS.CONNECTION_TIMEOUT;\n this.retryAttempts = options.retryAttempts ?? 3;\n this.logger = createLogger({ debug: options.debug, prefix: '[PushFlo REST]' });\n }\n\n /**\n * Make an HTTP request to the API\n */\n async request<T>(\n method: string,\n path: string,\n options: {\n body?: unknown;\n query?: Record<string, string | number | undefined>;\n retryOptions?: Partial<RetryOptions>;\n } = {}\n ): Promise<T> {\n const url = this.buildUrl(path, options.query);\n\n this.logger.debug(`${method} ${url}`);\n\n const retryOpts: RetryOptions = {\n maxAttempts: this.retryAttempts,\n isRetryable: (error) => {\n if (error instanceof NetworkError) {\n return error.retryable;\n }\n return false;\n },\n onRetry: (attempt, delay, error) => {\n this.logger.warn(`Request failed, retrying (${attempt}/${this.retryAttempts}) in ${delay}ms`, error);\n },\n ...options.retryOptions,\n };\n\n return retry(async () => {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method,\n headers: this.getHeaders(),\n body: options.body ? JSON.stringify(options.body) : undefined,\n signal: controller.signal,\n });\n\n return await this.handleResponse<T>(response);\n } catch (error) {\n if (error instanceof AuthenticationError || error instanceof NetworkError) {\n throw error;\n }\n\n if (error instanceof DOMException && error.name === 'AbortError') {\n throw NetworkError.timeout(this.timeout);\n }\n\n if (error instanceof TypeError) {\n throw NetworkError.fromFetch(error);\n }\n\n throw error;\n } finally {\n clearTimeout(timeoutId);\n }\n }, retryOpts);\n }\n\n /**\n * Make a GET request\n */\n get<T>(path: string, query?: Record<string, string | number | undefined>): Promise<T> {\n return this.request<T>('GET', path, { query });\n }\n\n /**\n * Make a POST request\n */\n post<T>(path: string, body?: unknown): Promise<T> {\n return this.request<T>('POST', path, { body });\n }\n\n /**\n * Make a PATCH request\n */\n patch<T>(path: string, body?: unknown): Promise<T> {\n return this.request<T>('PATCH', path, { body });\n }\n\n /**\n * Make a DELETE request\n */\n delete<T>(path: string): Promise<T> {\n return this.request<T>('DELETE', path);\n }\n\n private buildUrl(path: string, query?: Record<string, string | number | undefined>): string {\n const fullPath = `${DEFAULTS.API_VERSION}${path}`;\n const url = new URL(fullPath, this.baseUrl);\n\n if (query) {\n Object.entries(query).forEach(([key, value]) => {\n if (value !== undefined) {\n url.searchParams.set(key, String(value));\n }\n });\n }\n\n return url.toString();\n }\n\n private getHeaders(): Record<string, string> {\n return {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n };\n }\n\n private async handleResponse<T>(response: Response): Promise<T> {\n // Handle authentication errors\n if (response.status === 401) {\n throw AuthenticationError.unauthorized();\n }\n\n if (response.status === 403) {\n throw AuthenticationError.forbidden();\n }\n\n // Handle other errors\n if (!response.ok) {\n let errorMessage: string | undefined;\n\n try {\n const errorBody = (await response.json()) as ApiErrorResponse;\n errorMessage = errorBody.error;\n } catch {\n // Ignore JSON parse errors\n }\n\n throw NetworkError.fromStatus(response.status, errorMessage);\n }\n\n // Handle empty responses\n if (response.status === 204) {\n return undefined as T;\n }\n\n // Parse JSON response\n try {\n const json = await response.json();\n // Handle wrapped responses: {success: true, data: ...}\n if (json && typeof json === 'object' && 'success' in json && 'data' in json) {\n return json.data as T;\n }\n return json as T;\n } catch {\n throw new NetworkError('Failed to parse response', 'PARSE_ERROR', { retryable: false });\n }\n }\n}\n","import { PushFloError } from './PushFloError.js';\n\n/**\n * Error thrown when input validation fails\n */\nexport class ValidationError extends PushFloError {\n /** The field that failed validation */\n readonly field?: string;\n\n constructor(message: string, field?: string) {\n super(message, 'VALIDATION_ERROR', { retryable: false });\n this.name = 'ValidationError';\n this.field = field;\n }\n\n /**\n * Create an error for an invalid channel slug\n */\n static invalidChannelSlug(slug: string): ValidationError {\n return new ValidationError(\n `Invalid channel slug '${slug}': must be 1-64 characters, lowercase alphanumeric with hyphens, cannot start or end with a hyphen`,\n 'slug'\n );\n }\n\n /**\n * Create an error for a required field\n */\n static required(field: string): ValidationError {\n return new ValidationError(`${field} is required`, field);\n }\n\n toJSON(): Record<string, unknown> {\n return {\n ...super.toJSON(),\n field: this.field,\n };\n }\n}\n","/**\n * Channel slug validation utilities\n *\n * Channel slugs must follow these rules:\n * - 1-64 characters long\n * - Lowercase letters (a-z), numbers (0-9), and hyphens (-) only\n * - Cannot start or end with a hyphen\n * - Cannot have consecutive hyphens\n */\n\n/** Maximum length for a channel slug */\nexport const MAX_SLUG_LENGTH = 64;\n\n/** Minimum length for a channel slug */\nexport const MIN_SLUG_LENGTH = 1;\n\n/**\n * Regular expression for validating channel slugs\n * Matches: lowercase alphanumeric, can contain hyphens but not at start/end\n */\nconst SLUG_REGEX = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;\n\n/**\n * Check if a channel slug is valid\n *\n * @param slug - The channel slug to validate\n * @returns true if the slug is valid, false otherwise\n *\n * @example\n * ```typescript\n * isValidChannelSlug('my-channel') // true\n * isValidChannelSlug('channel-123') // true\n * isValidChannelSlug('a') // true\n * isValidChannelSlug('My-Channel') // false (uppercase)\n * isValidChannelSlug('-channel') // false (starts with hyphen)\n * isValidChannelSlug('channel:name') // false (contains colon)\n * isValidChannelSlug('channel_name') // false (contains underscore)\n * ```\n */\nexport function isValidChannelSlug(slug: string): boolean {\n if (!slug || typeof slug !== 'string') {\n return false;\n }\n\n if (slug.length < MIN_SLUG_LENGTH || slug.length > MAX_SLUG_LENGTH) {\n return false;\n }\n\n // Check for consecutive hyphens\n if (slug.includes('--')) {\n return false;\n }\n\n return SLUG_REGEX.test(slug);\n}\n\n/**\n * Convert a string to a valid channel slug\n *\n * @param str - The string to convert\n * @returns A valid channel slug\n *\n * @example\n * ```typescript\n * toChannelSlug('My Channel') // 'my-channel'\n * toChannelSlug('Hello World!') // 'hello-world'\n * toChannelSlug('user:123:messages') // 'user-123-messages'\n * toChannelSlug('___test___') // 'test'\n * ```\n */\nexport function toChannelSlug(str: string): string {\n return str\n .toLowerCase()\n .trim()\n .replace(/[^a-z0-9]+/g, '-') // Replace non-alphanumeric with hyphens\n .replace(/^-+|-+$/g, '') // Remove leading/trailing hyphens\n .replace(/-{2,}/g, '-') // Replace consecutive hyphens with single\n .slice(0, MAX_SLUG_LENGTH); // Truncate to max length\n}\n\n/**\n * Validation result with detailed error information\n */\nexport interface SlugValidationResult {\n valid: boolean;\n error?: string;\n suggestion?: string;\n}\n\n/**\n * Validate a channel slug with detailed error messages\n *\n * @param slug - The channel slug to validate\n * @returns Validation result with error details and suggestions\n */\nexport function validateChannelSlug(slug: string): SlugValidationResult {\n if (!slug || typeof slug !== 'string') {\n return {\n valid: false,\n error: 'Channel slug is required',\n };\n }\n\n if (slug.length < MIN_SLUG_LENGTH) {\n return {\n valid: false,\n error: 'Channel slug cannot be empty',\n };\n }\n\n if (slug.length > MAX_SLUG_LENGTH) {\n return {\n valid: false,\n error: `Channel slug cannot exceed ${MAX_SLUG_LENGTH} characters (got ${slug.length})`,\n suggestion: toChannelSlug(slug),\n };\n }\n\n if (slug !== slug.toLowerCase()) {\n return {\n valid: false,\n error: 'Channel slug must be lowercase',\n suggestion: toChannelSlug(slug),\n };\n }\n\n if (slug.startsWith('-')) {\n return {\n valid: false,\n error: 'Channel slug cannot start with a hyphen',\n suggestion: toChannelSlug(slug),\n };\n }\n\n if (slug.endsWith('-')) {\n return {\n valid: false,\n error: 'Channel slug cannot end with a hyphen',\n suggestion: toChannelSlug(slug),\n };\n }\n\n if (slug.includes('--')) {\n return {\n valid: false,\n error: 'Channel slug cannot contain consecutive hyphens',\n suggestion: toChannelSlug(slug),\n };\n }\n\n const invalidChars = slug.match(/[^a-z0-9-]/g);\n if (invalidChars) {\n const uniqueChars = [...new Set(invalidChars)].join(', ');\n return {\n valid: false,\n error: `Channel slug contains invalid characters: ${uniqueChars}. Only lowercase letters, numbers, and hyphens are allowed.`,\n suggestion: toChannelSlug(slug),\n };\n }\n\n return { valid: true };\n}\n","import { RestClient } from './RestClient.js';\nimport { API_PATHS, DEFAULTS } from '../utils/constants.js';\nimport { AuthenticationError } from '../errors/AuthenticationError.js';\nimport { ValidationError } from '../errors/ValidationError.js';\nimport { validateChannelSlug } from '../utils/validation.js';\nimport type { ServerOptions } from '../types/connection.js';\nimport type {\n Channel,\n ChannelInput,\n ChannelUpdateInput,\n ListChannelsOptions,\n} from '../types/channel.js';\nimport type {\n Message,\n PublishOptions,\n PublishResult,\n MessageHistoryOptions,\n} from '../types/message.js';\nimport type { Pagination } from '../types/api.js';\n\ninterface ChannelsResponse {\n channels: Channel[];\n pagination: Pagination;\n}\n\ninterface MessagesResponse {\n items: Message[];\n pagination: Pagination;\n}\n\n/**\n * Server-side PushFlo client for publishing messages and managing channels\n */\nexport class PushFloServer {\n private readonly client: RestClient;\n\n constructor(options: ServerOptions) {\n if (!options.secretKey) {\n throw new AuthenticationError(\n 'Secret key is required',\n 'MISSING_SECRET_KEY'\n );\n }\n\n if (!options.secretKey.startsWith('sec_') && !options.secretKey.startsWith('mgmt_')) {\n throw AuthenticationError.invalidKey('secret');\n }\n\n this.client = new RestClient({\n apiKey: options.secretKey,\n baseUrl: options.baseUrl,\n timeout: options.timeout,\n retryAttempts: options.retryAttempts,\n debug: options.debug,\n });\n }\n\n // ============================================\n // Channel Management\n // ============================================\n\n /**\n * List all channels\n */\n async listChannels(\n options: ListChannelsOptions = {}\n ): Promise<{ channels: Channel[]; pagination: Pagination }> {\n const response = await this.client.get<ChannelsResponse>(API_PATHS.CHANNELS, {\n page: options.page,\n pageSize: options.pageSize ?? DEFAULTS.PAGE_SIZE,\n });\n\n return {\n channels: response.channels,\n pagination: response.pagination,\n };\n }\n\n /**\n * Get a channel by slug\n */\n async getChannel(slug: string): Promise<Channel> {\n this.validateSlug(slug);\n return this.client.get<Channel>(API_PATHS.CHANNEL(slug));\n }\n\n /**\n * Create a new channel\n *\n * @throws {ValidationError} If the channel slug is invalid\n */\n async createChannel(input: ChannelInput): Promise<Channel> {\n this.validateSlug(input.slug);\n return this.client.post<Channel>(API_PATHS.CHANNELS, input);\n }\n\n /**\n * Update an existing channel\n */\n async updateChannel(slug: string, input: ChannelUpdateInput): Promise<Channel> {\n this.validateSlug(slug);\n return this.client.patch<Channel>(API_PATHS.CHANNEL(slug), input);\n }\n\n /**\n * Delete a channel\n */\n async deleteChannel(slug: string): Promise<void> {\n this.validateSlug(slug);\n await this.client.delete<void>(API_PATHS.CHANNEL(slug));\n }\n\n /**\n * Validate a channel slug and throw if invalid\n */\n private validateSlug(slug: string): void {\n const result = validateChannelSlug(slug);\n if (!result.valid) {\n const error = ValidationError.invalidChannelSlug(slug);\n if (result.suggestion) {\n error.message += `. Suggested: '${result.suggestion}'`;\n }\n throw error;\n }\n }\n\n // ============================================\n // Message Publishing\n // ============================================\n\n /**\n * Publish a message to a channel\n *\n * @throws {ValidationError} If the channel slug is invalid\n */\n async publish(\n channel: string,\n content: Record<string, unknown>,\n options: PublishOptions = {}\n ): Promise<PublishResult> {\n this.validateSlug(channel);\n return this.client.post<PublishResult>(API_PATHS.CHANNEL_MESSAGES(channel), {\n content,\n eventType: options.eventType ?? 'message',\n });\n }\n\n /**\n * Get message history for a channel\n *\n * @throws {ValidationError} If the channel slug is invalid\n */\n async getMessageHistory(\n channel: string,\n options: MessageHistoryOptions = {}\n ): Promise<{ messages: Message[]; pagination: Pagination }> {\n this.validateSlug(channel);\n const response = await this.client.get<MessagesResponse>(\n API_PATHS.CHANNEL_MESSAGES(channel),\n {\n page: options.page,\n pageSize: options.pageSize ?? DEFAULTS.PAGE_SIZE,\n eventType: options.eventType,\n after: options.after,\n before: options.before,\n }\n );\n\n return {\n messages: response.items,\n pagination: response.pagination,\n };\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/utils/constants.ts","../src/utils/retry.ts","../src/utils/logger.ts","../src/errors/PushFloError.ts","../src/errors/AuthenticationError.ts","../src/errors/NetworkError.ts","../src/server/RestClient.ts","../src/errors/ValidationError.ts","../src/utils/validation.ts","../src/server/PushFloServer.ts"],"names":[],"mappings":"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","file":"server.cjs","sourcesContent":["/**\n * Default configuration values\n */\nexport const DEFAULTS = {\n /** Default PushFlo Realtime API base URL */\n BASE_URL: 'https://api.pushflo.dev',\n\n /** Default PushFlo Console API base URL (for channel management) */\n CONSOLE_URL: 'https://console.pushflo.dev',\n\n /** WebSocket endpoint path */\n WS_PATH: '/ws',\n\n /** API version prefix */\n API_VERSION: '/api/v1',\n\n /** Connection timeout in milliseconds */\n CONNECTION_TIMEOUT: 30000,\n\n /** Heartbeat interval in milliseconds */\n HEARTBEAT_INTERVAL: 25000,\n\n /** Initial reconnection delay in milliseconds */\n RECONNECT_DELAY: 1000,\n\n /** Maximum reconnection delay in milliseconds */\n MAX_RECONNECT_DELAY: 30000,\n\n /** Reconnection delay multiplier for exponential backoff */\n RECONNECT_MULTIPLIER: 1.5,\n\n /** Maximum number of reconnection attempts (0 = infinite) */\n MAX_RECONNECT_ATTEMPTS: 0,\n\n /** Default page size for list operations */\n PAGE_SIZE: 25,\n} as const;\n\n/**\n * API endpoint paths\n */\nexport const API_PATHS = {\n AUTH_TOKEN: '/auth/token',\n CHANNELS: '/channels',\n CHANNEL: (slug: string) => `/channels/${encodeURIComponent(slug)}`,\n CHANNEL_MESSAGES: (slug: string) => `/channels/${encodeURIComponent(slug)}/messages`,\n} as const;\n\n/**\n * WebSocket message types (client -> server)\n */\nexport const WS_CLIENT_MESSAGES = {\n SUBSCRIBE: 'subscribe',\n UNSUBSCRIBE: 'unsubscribe',\n PING: 'ping',\n ACK: 'ack',\n} as const;\n\n/**\n * WebSocket message types (server -> client)\n */\nexport const WS_SERVER_MESSAGES = {\n CONNECTED: 'connected',\n SUBSCRIBED: 'subscribed',\n UNSUBSCRIBED: 'unsubscribed',\n MESSAGE: 'message',\n ERROR: 'error',\n PONG: 'pong',\n} as const;\n\n/**\n * Error codes\n */\nexport const ERROR_CODES = {\n // Connection errors\n CONNECTION_FAILED: 'CONNECTION_FAILED',\n CONNECTION_TIMEOUT: 'CONNECTION_TIMEOUT',\n CONNECTION_CLOSED: 'CONNECTION_CLOSED',\n\n // Authentication errors\n INVALID_API_KEY: 'INVALID_API_KEY',\n UNAUTHORIZED: 'UNAUTHORIZED',\n FORBIDDEN: 'FORBIDDEN',\n\n // Network errors\n NETWORK_ERROR: 'NETWORK_ERROR',\n REQUEST_TIMEOUT: 'REQUEST_TIMEOUT',\n\n // API errors\n NOT_FOUND: 'NOT_FOUND',\n VALIDATION_ERROR: 'VALIDATION_ERROR',\n RATE_LIMITED: 'RATE_LIMITED',\n SERVER_ERROR: 'SERVER_ERROR',\n\n // Client errors\n INVALID_STATE: 'INVALID_STATE',\n ALREADY_CONNECTED: 'ALREADY_CONNECTED',\n NOT_CONNECTED: 'NOT_CONNECTED',\n CHANNEL_NOT_FOUND: 'CHANNEL_NOT_FOUND',\n} as const;\n","import { DEFAULTS } from './constants.js';\n\nexport interface RetryOptions {\n /** Maximum number of retry attempts (0 = infinite) */\n maxAttempts?: number;\n /** Initial delay in milliseconds */\n initialDelay?: number;\n /** Maximum delay in milliseconds */\n maxDelay?: number;\n /** Delay multiplier for exponential backoff */\n multiplier?: number;\n /** Function to determine if error is retryable */\n isRetryable?: (error: unknown) => boolean;\n /** Callback for each retry attempt */\n onRetry?: (attempt: number, delay: number, error: unknown) => void;\n /** Abort signal for cancellation */\n signal?: AbortSignal;\n}\n\n/**\n * Calculate delay with exponential backoff and jitter\n */\nexport function calculateBackoff(\n attempt: number,\n options: {\n initialDelay?: number;\n maxDelay?: number;\n multiplier?: number;\n } = {}\n): number {\n const {\n initialDelay = DEFAULTS.RECONNECT_DELAY,\n maxDelay = DEFAULTS.MAX_RECONNECT_DELAY,\n multiplier = DEFAULTS.RECONNECT_MULTIPLIER,\n } = options;\n\n // Exponential backoff\n const exponentialDelay = initialDelay * Math.pow(multiplier, attempt);\n\n // Cap at max delay\n const cappedDelay = Math.min(exponentialDelay, maxDelay);\n\n // Add jitter (±25%)\n const jitter = cappedDelay * 0.25 * (Math.random() * 2 - 1);\n\n return Math.floor(cappedDelay + jitter);\n}\n\n/**\n * Sleep for a given duration (cancellable)\n */\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(new DOMException('Aborted', 'AbortError'));\n return;\n }\n\n const timeoutId = setTimeout(resolve, ms);\n\n signal?.addEventListener(\n 'abort',\n () => {\n clearTimeout(timeoutId);\n reject(new DOMException('Aborted', 'AbortError'));\n },\n { once: true }\n );\n });\n}\n\n/**\n * Retry a function with exponential backoff\n */\nexport async function retry<T>(\n fn: () => Promise<T>,\n options: RetryOptions = {}\n): Promise<T> {\n const {\n maxAttempts = 3,\n initialDelay = DEFAULTS.RECONNECT_DELAY,\n maxDelay = DEFAULTS.MAX_RECONNECT_DELAY,\n multiplier = DEFAULTS.RECONNECT_MULTIPLIER,\n isRetryable = () => true,\n onRetry,\n signal,\n } = options;\n\n let lastError: unknown;\n let attempt = 0;\n\n while (maxAttempts === 0 || attempt < maxAttempts) {\n try {\n if (signal?.aborted) {\n throw new DOMException('Aborted', 'AbortError');\n }\n return await fn();\n } catch (error) {\n lastError = error;\n\n // Don't retry abort errors\n if (error instanceof DOMException && error.name === 'AbortError') {\n throw error;\n }\n\n // Check if we should retry\n if (!isRetryable(error)) {\n throw error;\n }\n\n // Check if we've exhausted attempts\n if (maxAttempts !== 0 && attempt >= maxAttempts - 1) {\n throw error;\n }\n\n // Calculate delay\n const delay = calculateBackoff(attempt, { initialDelay, maxDelay, multiplier });\n\n // Notify retry callback\n onRetry?.(attempt + 1, delay, error);\n\n // Wait before next attempt\n await sleep(delay, signal);\n\n attempt++;\n }\n }\n\n throw lastError;\n}\n\n/**\n * Create a retry function with preset options\n */\nexport function createRetry(defaultOptions: RetryOptions) {\n return <T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T> => {\n return retry(fn, { ...defaultOptions, ...options });\n };\n}\n","export type LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\nexport interface LoggerOptions {\n /** Enable debug logging */\n debug?: boolean;\n /** Custom log prefix */\n prefix?: string;\n /** Minimum log level */\n level?: LogLevel;\n}\n\nconst LOG_LEVELS: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\n/**\n * Simple logger with debug mode support\n */\nexport class Logger {\n private enabled: boolean;\n private prefix: string;\n private minLevel: number;\n\n constructor(options: LoggerOptions = {}) {\n this.enabled = options.debug ?? false;\n this.prefix = options.prefix ?? '[PushFlo]';\n this.minLevel = LOG_LEVELS[options.level ?? 'debug'];\n }\n\n /**\n * Enable or disable logging\n */\n setEnabled(enabled: boolean): void {\n this.enabled = enabled;\n }\n\n /**\n * Set minimum log level\n */\n setLevel(level: LogLevel): void {\n this.minLevel = LOG_LEVELS[level];\n }\n\n /**\n * Log a debug message\n */\n debug(message: string, ...args: unknown[]): void {\n this.log('debug', message, ...args);\n }\n\n /**\n * Log an info message\n */\n info(message: string, ...args: unknown[]): void {\n this.log('info', message, ...args);\n }\n\n /**\n * Log a warning message\n */\n warn(message: string, ...args: unknown[]): void {\n this.log('warn', message, ...args);\n }\n\n /**\n * Log an error message\n */\n error(message: string, ...args: unknown[]): void {\n this.log('error', message, ...args);\n }\n\n private log(level: LogLevel, message: string, ...args: unknown[]): void {\n if (!this.enabled && level !== 'error') {\n return;\n }\n\n if (LOG_LEVELS[level] < this.minLevel) {\n return;\n }\n\n const timestamp = new Date().toISOString();\n const formattedMessage = `${this.prefix} ${timestamp} [${level.toUpperCase()}] ${message}`;\n\n switch (level) {\n case 'debug':\n console.debug(formattedMessage, ...args);\n break;\n case 'info':\n console.info(formattedMessage, ...args);\n break;\n case 'warn':\n console.warn(formattedMessage, ...args);\n break;\n case 'error':\n console.error(formattedMessage, ...args);\n break;\n }\n }\n}\n\n/**\n * Create a child logger with a custom prefix\n */\nexport function createLogger(options: LoggerOptions = {}): Logger {\n return new Logger(options);\n}\n","/**\n * Base error class for all PushFlo SDK errors\n */\nexport class PushFloError extends Error {\n /** Error code for programmatic handling */\n readonly code: string;\n\n /** Whether this error is potentially recoverable through retry */\n readonly retryable: boolean;\n\n /** Original error that caused this error, if any */\n readonly cause?: Error;\n\n constructor(\n message: string,\n code: string,\n options: { retryable?: boolean; cause?: Error } = {}\n ) {\n super(message);\n this.name = 'PushFloError';\n this.code = code;\n this.retryable = options.retryable ?? false;\n this.cause = options.cause;\n\n // Maintain proper stack trace in V8 environments\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n\n /**\n * Convert error to JSON-serializable object\n */\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n retryable: this.retryable,\n stack: this.stack,\n cause: this.cause?.message,\n };\n }\n\n /**\n * Create a string representation\n */\n toString(): string {\n return `${this.name} [${this.code}]: ${this.message}`;\n }\n}\n","import { PushFloError } from './PushFloError.js';\nimport { ERROR_CODES } from '../utils/constants.js';\n\n/**\n * Error thrown when authentication fails\n */\nexport class AuthenticationError extends PushFloError {\n constructor(\n message: string,\n code: string = ERROR_CODES.UNAUTHORIZED,\n options: { retryable?: boolean; cause?: Error } = {}\n ) {\n // Authentication errors are generally not retryable\n super(message, code, { retryable: false, ...options });\n this.name = 'AuthenticationError';\n }\n\n /**\n * Create an invalid API key error\n */\n static invalidKey(keyType?: string): AuthenticationError {\n const message = keyType\n ? `Invalid ${keyType} API key`\n : 'Invalid API key';\n return new AuthenticationError(message, ERROR_CODES.INVALID_API_KEY);\n }\n\n /**\n * Create an unauthorized error\n */\n static unauthorized(reason?: string): AuthenticationError {\n return new AuthenticationError(\n reason ?? 'Unauthorized - check your API key',\n ERROR_CODES.UNAUTHORIZED\n );\n }\n\n /**\n * Create a forbidden error\n */\n static forbidden(action?: string): AuthenticationError {\n const message = action\n ? `Access forbidden: insufficient permissions for ${action}`\n : 'Access forbidden: insufficient permissions';\n return new AuthenticationError(message, ERROR_CODES.FORBIDDEN);\n }\n}\n","import { PushFloError } from './PushFloError.js';\nimport { ERROR_CODES } from '../utils/constants.js';\n\n/**\n * Error thrown for network-related failures\n */\nexport class NetworkError extends PushFloError {\n /** HTTP status code, if applicable */\n readonly statusCode?: number;\n\n constructor(\n message: string,\n code: string = ERROR_CODES.NETWORK_ERROR,\n options: { retryable?: boolean; cause?: Error; statusCode?: number } = {}\n ) {\n super(message, code, { retryable: true, ...options });\n this.name = 'NetworkError';\n this.statusCode = options.statusCode;\n }\n\n /**\n * Create a network error from fetch failure\n */\n static fromFetch(cause: Error): NetworkError {\n return new NetworkError(\n `Network request failed: ${cause.message}`,\n ERROR_CODES.NETWORK_ERROR,\n { retryable: true, cause }\n );\n }\n\n /**\n * Create a request timeout error\n */\n static timeout(timeoutMs: number): NetworkError {\n return new NetworkError(\n `Request timed out after ${timeoutMs}ms`,\n ERROR_CODES.REQUEST_TIMEOUT,\n { retryable: true }\n );\n }\n\n /**\n * Create an error from HTTP status code\n */\n static fromStatus(statusCode: number, message?: string): NetworkError {\n const defaultMessage = NetworkError.getStatusMessage(statusCode);\n\n // Determine if retryable based on status\n const retryable = statusCode >= 500 || statusCode === 429;\n\n // Map status to error code\n let code: string = ERROR_CODES.SERVER_ERROR;\n if (statusCode === 404) {\n code = ERROR_CODES.NOT_FOUND;\n } else if (statusCode === 422 || statusCode === 400) {\n code = ERROR_CODES.VALIDATION_ERROR;\n } else if (statusCode === 429) {\n code = ERROR_CODES.RATE_LIMITED;\n }\n\n return new NetworkError(\n message ?? defaultMessage,\n code,\n { retryable, statusCode }\n );\n }\n\n private static getStatusMessage(statusCode: number): string {\n const messages: Record<number, string> = {\n 400: 'Bad request',\n 404: 'Resource not found',\n 422: 'Validation error',\n 429: 'Rate limit exceeded',\n 500: 'Internal server error',\n 502: 'Bad gateway',\n 503: 'Service unavailable',\n 504: 'Gateway timeout',\n };\n return messages[statusCode] ?? `HTTP error ${statusCode}`;\n }\n\n toJSON(): Record<string, unknown> {\n return {\n ...super.toJSON(),\n statusCode: this.statusCode,\n };\n }\n}\n","import { DEFAULTS } from '../utils/constants.js';\nimport { retry, type RetryOptions } from '../utils/retry.js';\nimport { createLogger, type Logger } from '../utils/logger.js';\nimport { AuthenticationError } from '../errors/AuthenticationError.js';\nimport { NetworkError } from '../errors/NetworkError.js';\nimport type { ApiErrorResponse } from '../types/api.js';\n\nexport interface RestClientOptions {\n /** API key (secret or management key) */\n apiKey: string;\n\n /** Base URL for the API */\n baseUrl?: string;\n\n /** Request timeout in milliseconds */\n timeout?: number;\n\n /** Number of retry attempts */\n retryAttempts?: number;\n\n /** Enable debug logging */\n debug?: boolean;\n}\n\n/**\n * HTTP client for PushFlo REST API\n */\nexport class RestClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n private readonly retryAttempts: number;\n private readonly logger: Logger;\n\n constructor(options: RestClientOptions) {\n this.apiKey = options.apiKey;\n this.baseUrl = (options.baseUrl ?? DEFAULTS.BASE_URL).replace(/\\/$/, '');\n this.timeout = options.timeout ?? DEFAULTS.CONNECTION_TIMEOUT;\n this.retryAttempts = options.retryAttempts ?? 3;\n this.logger = createLogger({ debug: options.debug, prefix: '[PushFlo REST]' });\n }\n\n /**\n * Make an HTTP request to the API\n */\n async request<T>(\n method: string,\n path: string,\n options: {\n body?: unknown;\n query?: Record<string, string | number | undefined>;\n retryOptions?: Partial<RetryOptions>;\n } = {}\n ): Promise<T> {\n const url = this.buildUrl(path, options.query);\n\n this.logger.debug(`${method} ${url}`);\n\n const retryOpts: RetryOptions = {\n maxAttempts: this.retryAttempts,\n isRetryable: (error) => {\n if (error instanceof NetworkError) {\n return error.retryable;\n }\n return false;\n },\n onRetry: (attempt, delay, error) => {\n this.logger.warn(`Request failed, retrying (${attempt}/${this.retryAttempts}) in ${delay}ms`, error);\n },\n ...options.retryOptions,\n };\n\n return retry(async () => {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method,\n headers: this.getHeaders(),\n body: options.body ? JSON.stringify(options.body) : undefined,\n signal: controller.signal,\n });\n\n return await this.handleResponse<T>(response);\n } catch (error) {\n if (error instanceof AuthenticationError || error instanceof NetworkError) {\n throw error;\n }\n\n if (error instanceof DOMException && error.name === 'AbortError') {\n throw NetworkError.timeout(this.timeout);\n }\n\n if (error instanceof TypeError) {\n throw NetworkError.fromFetch(error);\n }\n\n throw error;\n } finally {\n clearTimeout(timeoutId);\n }\n }, retryOpts);\n }\n\n /**\n * Make a GET request\n */\n get<T>(path: string, query?: Record<string, string | number | undefined>): Promise<T> {\n return this.request<T>('GET', path, { query });\n }\n\n /**\n * Make a POST request\n */\n post<T>(path: string, body?: unknown): Promise<T> {\n return this.request<T>('POST', path, { body });\n }\n\n /**\n * Make a PATCH request\n */\n patch<T>(path: string, body?: unknown): Promise<T> {\n return this.request<T>('PATCH', path, { body });\n }\n\n /**\n * Make a DELETE request\n */\n delete<T>(path: string): Promise<T> {\n return this.request<T>('DELETE', path);\n }\n\n private buildUrl(path: string, query?: Record<string, string | number | undefined>): string {\n const fullPath = `${DEFAULTS.API_VERSION}${path}`;\n const url = new URL(fullPath, this.baseUrl);\n\n if (query) {\n Object.entries(query).forEach(([key, value]) => {\n if (value !== undefined) {\n url.searchParams.set(key, String(value));\n }\n });\n }\n\n return url.toString();\n }\n\n private getHeaders(): Record<string, string> {\n return {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n };\n }\n\n private async handleResponse<T>(response: Response): Promise<T> {\n // Handle authentication errors\n if (response.status === 401) {\n throw AuthenticationError.unauthorized();\n }\n\n if (response.status === 403) {\n throw AuthenticationError.forbidden();\n }\n\n // Handle other errors\n if (!response.ok) {\n let errorMessage: string | undefined;\n\n try {\n const errorBody = (await response.json()) as ApiErrorResponse;\n errorMessage = errorBody.error;\n } catch {\n // Ignore JSON parse errors\n }\n\n throw NetworkError.fromStatus(response.status, errorMessage);\n }\n\n // Handle empty responses\n if (response.status === 204) {\n return undefined as T;\n }\n\n // Parse JSON response\n try {\n const json = await response.json();\n // Handle wrapped responses: {success: true, data: ...}\n if (json && typeof json === 'object' && 'success' in json && 'data' in json) {\n // If pagination exists alongside data, preserve both for paginated responses\n if ('pagination' in json) {\n return { data: json.data, pagination: json.pagination } as T;\n }\n return json.data as T;\n }\n return json as T;\n } catch {\n throw new NetworkError('Failed to parse response', 'PARSE_ERROR', { retryable: false });\n }\n }\n}\n","import { PushFloError } from './PushFloError.js';\n\n/**\n * Error thrown when input validation fails\n */\nexport class ValidationError extends PushFloError {\n /** The field that failed validation */\n readonly field?: string;\n\n constructor(message: string, field?: string) {\n super(message, 'VALIDATION_ERROR', { retryable: false });\n this.name = 'ValidationError';\n this.field = field;\n }\n\n /**\n * Create an error for an invalid channel slug\n */\n static invalidChannelSlug(slug: string): ValidationError {\n return new ValidationError(\n `Invalid channel slug '${slug}': must be 1-64 characters, lowercase alphanumeric with hyphens, cannot start or end with a hyphen`,\n 'slug'\n );\n }\n\n /**\n * Create an error for a required field\n */\n static required(field: string): ValidationError {\n return new ValidationError(`${field} is required`, field);\n }\n\n toJSON(): Record<string, unknown> {\n return {\n ...super.toJSON(),\n field: this.field,\n };\n }\n}\n","/**\n * Channel slug validation utilities\n *\n * Channel slugs must follow these rules:\n * - 1-128 characters long\n * - Lowercase letters (a-z), numbers (0-9), and hyphens (-) only\n * - Cannot start or end with a hyphen\n * - Cannot have consecutive hyphens\n */\n\n/** Maximum length for a channel slug */\nexport const MAX_SLUG_LENGTH = 128;\n\n/** Minimum length for a channel slug */\nexport const MIN_SLUG_LENGTH = 1;\n\n/**\n * Regular expression for validating channel slugs\n * Matches: lowercase alphanumeric, can contain hyphens but not at start/end\n */\nconst SLUG_REGEX = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;\n\n/**\n * Check if a channel slug is valid\n *\n * @param slug - The channel slug to validate\n * @returns true if the slug is valid, false otherwise\n *\n * @example\n * ```typescript\n * isValidChannelSlug('my-channel') // true\n * isValidChannelSlug('channel-123') // true\n * isValidChannelSlug('a') // true\n * isValidChannelSlug('My-Channel') // false (uppercase)\n * isValidChannelSlug('-channel') // false (starts with hyphen)\n * isValidChannelSlug('channel:name') // false (contains colon)\n * isValidChannelSlug('channel_name') // false (contains underscore)\n * ```\n */\nexport function isValidChannelSlug(slug: string): boolean {\n if (!slug || typeof slug !== 'string') {\n return false;\n }\n\n if (slug.length < MIN_SLUG_LENGTH || slug.length > MAX_SLUG_LENGTH) {\n return false;\n }\n\n // Check for consecutive hyphens\n if (slug.includes('--')) {\n return false;\n }\n\n return SLUG_REGEX.test(slug);\n}\n\n/**\n * Convert a string to a valid channel slug\n *\n * @param str - The string to convert\n * @returns A valid channel slug\n *\n * @example\n * ```typescript\n * toChannelSlug('My Channel') // 'my-channel'\n * toChannelSlug('Hello World!') // 'hello-world'\n * toChannelSlug('user:123:messages') // 'user-123-messages'\n * toChannelSlug('___test___') // 'test'\n * ```\n */\nexport function toChannelSlug(str: string): string {\n return str\n .toLowerCase()\n .trim()\n .replace(/[^a-z0-9]+/g, '-') // Replace non-alphanumeric with hyphens\n .replace(/^-+|-+$/g, '') // Remove leading/trailing hyphens\n .replace(/-{2,}/g, '-') // Replace consecutive hyphens with single\n .slice(0, MAX_SLUG_LENGTH); // Truncate to max length\n}\n\n/**\n * Validation result with detailed error information\n */\nexport interface SlugValidationResult {\n valid: boolean;\n error?: string;\n suggestion?: string;\n}\n\n/**\n * Validate a channel slug with detailed error messages\n *\n * @param slug - The channel slug to validate\n * @returns Validation result with error details and suggestions\n */\nexport function validateChannelSlug(slug: string): SlugValidationResult {\n if (!slug || typeof slug !== 'string') {\n return {\n valid: false,\n error: 'Channel slug is required',\n };\n }\n\n if (slug.length < MIN_SLUG_LENGTH) {\n return {\n valid: false,\n error: 'Channel slug cannot be empty',\n };\n }\n\n if (slug.length > MAX_SLUG_LENGTH) {\n return {\n valid: false,\n error: `Channel slug cannot exceed ${MAX_SLUG_LENGTH} characters (got ${slug.length})`,\n suggestion: toChannelSlug(slug),\n };\n }\n\n if (slug !== slug.toLowerCase()) {\n return {\n valid: false,\n error: 'Channel slug must be lowercase',\n suggestion: toChannelSlug(slug),\n };\n }\n\n if (slug.startsWith('-')) {\n return {\n valid: false,\n error: 'Channel slug cannot start with a hyphen',\n suggestion: toChannelSlug(slug),\n };\n }\n\n if (slug.endsWith('-')) {\n return {\n valid: false,\n error: 'Channel slug cannot end with a hyphen',\n suggestion: toChannelSlug(slug),\n };\n }\n\n if (slug.includes('--')) {\n return {\n valid: false,\n error: 'Channel slug cannot contain consecutive hyphens',\n suggestion: toChannelSlug(slug),\n };\n }\n\n const invalidChars = slug.match(/[^a-z0-9-]/g);\n if (invalidChars) {\n const uniqueChars = [...new Set(invalidChars)].join(', ');\n return {\n valid: false,\n error: `Channel slug contains invalid characters: ${uniqueChars}. Only lowercase letters, numbers, and hyphens are allowed.`,\n suggestion: toChannelSlug(slug),\n };\n }\n\n return { valid: true };\n}\n","import { RestClient } from './RestClient.js';\nimport { API_PATHS, DEFAULTS } from '../utils/constants.js';\nimport { AuthenticationError } from '../errors/AuthenticationError.js';\nimport { ValidationError } from '../errors/ValidationError.js';\nimport { validateChannelSlug } from '../utils/validation.js';\nimport type { ServerOptions } from '../types/connection.js';\nimport type {\n Channel,\n ChannelInput,\n ChannelUpdateInput,\n ListChannelsOptions,\n} from '../types/channel.js';\nimport type {\n Message,\n PublishOptions,\n PublishResult,\n MessageHistoryOptions,\n} from '../types/message.js';\nimport type { Pagination } from '../types/api.js';\n\ninterface ChannelsResponse {\n data: Channel[];\n pagination: Pagination;\n}\n\ninterface MessagesResponse {\n items: Message[];\n pagination: Pagination;\n}\n\n/**\n * Server-side PushFlo client for publishing messages and managing channels\n *\n * Uses two different APIs:\n * - Realtime API (api.pushflo.dev): publish messages, message history\n * - Console API (console.pushflo.dev): channel CRUD operations\n */\nexport class PushFloServer {\n /** Client for Realtime API (publish, message history) */\n private readonly realtimeClient: RestClient;\n /** Client for Console API (channel CRUD) */\n private readonly consoleClient: RestClient;\n\n constructor(options: ServerOptions) {\n if (!options.secretKey) {\n throw new AuthenticationError(\n 'Secret key is required',\n 'MISSING_SECRET_KEY'\n );\n }\n\n if (!options.secretKey.startsWith('sec_') && !options.secretKey.startsWith('mgmt_')) {\n throw AuthenticationError.invalidKey('secret');\n }\n\n // Realtime API client for publish and message history\n this.realtimeClient = new RestClient({\n apiKey: options.secretKey,\n baseUrl: options.baseUrl || DEFAULTS.BASE_URL,\n timeout: options.timeout,\n retryAttempts: options.retryAttempts,\n debug: options.debug,\n });\n\n // Console API client for channel management\n this.consoleClient = new RestClient({\n apiKey: options.secretKey,\n baseUrl: options.consoleUrl || DEFAULTS.CONSOLE_URL,\n timeout: options.timeout,\n retryAttempts: options.retryAttempts,\n debug: options.debug,\n });\n }\n\n // ============================================\n // Channel Management (Console API)\n // ============================================\n\n /**\n * List all channels\n * @note Requires mgmt_ key. Uses Console API.\n */\n async listChannels(\n options: ListChannelsOptions = {}\n ): Promise<{ channels: Channel[]; pagination: Pagination }> {\n const response = await this.consoleClient.get<ChannelsResponse>(API_PATHS.CHANNELS, {\n page: options.page,\n pageSize: options.pageSize ?? DEFAULTS.PAGE_SIZE,\n });\n\n return {\n channels: response.data,\n pagination: response.pagination,\n };\n }\n\n /**\n * Get a channel by slug\n * @note Requires mgmt_ key. Uses Console API.\n */\n async getChannel(slug: string): Promise<Channel> {\n this.validateSlug(slug);\n return this.consoleClient.get<Channel>(API_PATHS.CHANNEL(slug));\n }\n\n /**\n * Create a new channel\n * @note Requires mgmt_ key. Uses Console API.\n * @throws {ValidationError} If the channel slug is invalid\n */\n async createChannel(input: ChannelInput): Promise<Channel> {\n this.validateSlug(input.slug);\n return this.consoleClient.post<Channel>(API_PATHS.CHANNELS, input);\n }\n\n /**\n * Update an existing channel\n * @note Requires mgmt_ key. Uses Console API.\n */\n async updateChannel(slug: string, input: ChannelUpdateInput): Promise<Channel> {\n this.validateSlug(slug);\n return this.consoleClient.patch<Channel>(API_PATHS.CHANNEL(slug), input);\n }\n\n /**\n * Delete a channel\n * @note Requires mgmt_ key. Uses Console API.\n */\n async deleteChannel(slug: string): Promise<void> {\n this.validateSlug(slug);\n await this.consoleClient.delete<void>(API_PATHS.CHANNEL(slug));\n }\n\n /**\n * Validate a channel slug and throw if invalid\n */\n private validateSlug(slug: string): void {\n const result = validateChannelSlug(slug);\n if (!result.valid) {\n const error = ValidationError.invalidChannelSlug(slug);\n if (result.suggestion) {\n error.message += `. Suggested: '${result.suggestion}'`;\n }\n throw error;\n }\n }\n\n // ============================================\n // Message Publishing (Realtime API)\n // ============================================\n\n /**\n * Publish a message to a channel\n * @note Uses Realtime API. Works with sec_ or mgmt_ key.\n * @throws {ValidationError} If the channel slug is invalid\n */\n async publish(\n channel: string,\n content: Record<string, unknown>,\n options: PublishOptions = {}\n ): Promise<PublishResult> {\n this.validateSlug(channel);\n return this.realtimeClient.post<PublishResult>(API_PATHS.CHANNEL_MESSAGES(channel), {\n content,\n eventType: options.eventType ?? 'message',\n });\n }\n\n /**\n * Get message history for a channel\n * @note Uses Realtime API. Works with sec_ or mgmt_ key.\n * @throws {ValidationError} If the channel slug is invalid\n */\n async getMessageHistory(\n channel: string,\n options: MessageHistoryOptions = {}\n ): Promise<{ messages: Message[]; pagination: Pagination }> {\n this.validateSlug(channel);\n const response = await this.realtimeClient.get<MessagesResponse>(\n API_PATHS.CHANNEL_MESSAGES(channel),\n {\n page: options.page,\n pageSize: options.pageSize ?? DEFAULTS.PAGE_SIZE,\n eventType: options.eventType,\n after: options.after,\n before: options.before,\n }\n );\n\n return {\n messages: response.items,\n pagination: response.pagination,\n };\n }\n}\n"]}
package/dist/server.d.cts CHANGED
@@ -1,16 +1,24 @@
1
- import { g as ServerOptions, P as PublishOptions, d as PublishResult, c as MessageHistoryOptions, M as Message } from './ValidationError-izGOr1dF.cjs';
2
- export { A as AuthenticationError, N as NetworkError, e as PushFloError, V as ValidationError } from './ValidationError-izGOr1dF.cjs';
3
- import { L as ListChannelsOptions, C as Channel, P as Pagination, a as ChannelInput, b as ChannelUpdateInput } from './api-DKISn33_.cjs';
4
- export { M as MAX_SLUG_LENGTH, c as MIN_SLUG_LENGTH, S as SlugValidationResult, i as isValidChannelSlug, t as toChannelSlug, v as validateChannelSlug } from './api-DKISn33_.cjs';
1
+ import { g as ServerOptions, P as PublishOptions, d as PublishResult, c as MessageHistoryOptions, M as Message } from './ValidationError-CDHx9EHH.cjs';
2
+ export { A as AuthenticationError, N as NetworkError, e as PushFloError, V as ValidationError } from './ValidationError-CDHx9EHH.cjs';
3
+ import { L as ListChannelsOptions, C as Channel, P as Pagination, a as ChannelInput, b as ChannelUpdateInput } from './api-CkP76uCc.cjs';
4
+ export { M as MAX_SLUG_LENGTH, c as MIN_SLUG_LENGTH, S as SlugValidationResult, i as isValidChannelSlug, t as toChannelSlug, v as validateChannelSlug } from './api-CkP76uCc.cjs';
5
5
 
6
6
  /**
7
7
  * Server-side PushFlo client for publishing messages and managing channels
8
+ *
9
+ * Uses two different APIs:
10
+ * - Realtime API (api.pushflo.dev): publish messages, message history
11
+ * - Console API (console.pushflo.dev): channel CRUD operations
8
12
  */
9
13
  declare class PushFloServer {
10
- private readonly client;
14
+ /** Client for Realtime API (publish, message history) */
15
+ private readonly realtimeClient;
16
+ /** Client for Console API (channel CRUD) */
17
+ private readonly consoleClient;
11
18
  constructor(options: ServerOptions);
12
19
  /**
13
20
  * List all channels
21
+ * @note Requires mgmt_ key. Uses Console API.
14
22
  */
15
23
  listChannels(options?: ListChannelsOptions): Promise<{
16
24
  channels: Channel[];
@@ -18,20 +26,23 @@ declare class PushFloServer {
18
26
  }>;
19
27
  /**
20
28
  * Get a channel by slug
29
+ * @note Requires mgmt_ key. Uses Console API.
21
30
  */
22
31
  getChannel(slug: string): Promise<Channel>;
23
32
  /**
24
33
  * Create a new channel
25
- *
34
+ * @note Requires mgmt_ key. Uses Console API.
26
35
  * @throws {ValidationError} If the channel slug is invalid
27
36
  */
28
37
  createChannel(input: ChannelInput): Promise<Channel>;
29
38
  /**
30
39
  * Update an existing channel
40
+ * @note Requires mgmt_ key. Uses Console API.
31
41
  */
32
42
  updateChannel(slug: string, input: ChannelUpdateInput): Promise<Channel>;
33
43
  /**
34
44
  * Delete a channel
45
+ * @note Requires mgmt_ key. Uses Console API.
35
46
  */
36
47
  deleteChannel(slug: string): Promise<void>;
37
48
  /**
@@ -40,13 +51,13 @@ declare class PushFloServer {
40
51
  private validateSlug;
41
52
  /**
42
53
  * Publish a message to a channel
43
- *
54
+ * @note Uses Realtime API. Works with sec_ or mgmt_ key.
44
55
  * @throws {ValidationError} If the channel slug is invalid
45
56
  */
46
57
  publish(channel: string, content: Record<string, unknown>, options?: PublishOptions): Promise<PublishResult>;
47
58
  /**
48
59
  * Get message history for a channel
49
- *
60
+ * @note Uses Realtime API. Works with sec_ or mgmt_ key.
50
61
  * @throws {ValidationError} If the channel slug is invalid
51
62
  */
52
63
  getMessageHistory(channel: string, options?: MessageHistoryOptions): Promise<{
package/dist/server.d.ts CHANGED
@@ -1,16 +1,24 @@
1
- import { g as ServerOptions, P as PublishOptions, d as PublishResult, c as MessageHistoryOptions, M as Message } from './ValidationError-izGOr1dF.js';
2
- export { A as AuthenticationError, N as NetworkError, e as PushFloError, V as ValidationError } from './ValidationError-izGOr1dF.js';
3
- import { L as ListChannelsOptions, C as Channel, P as Pagination, a as ChannelInput, b as ChannelUpdateInput } from './api-DKISn33_.js';
4
- export { M as MAX_SLUG_LENGTH, c as MIN_SLUG_LENGTH, S as SlugValidationResult, i as isValidChannelSlug, t as toChannelSlug, v as validateChannelSlug } from './api-DKISn33_.js';
1
+ import { g as ServerOptions, P as PublishOptions, d as PublishResult, c as MessageHistoryOptions, M as Message } from './ValidationError-CDHx9EHH.js';
2
+ export { A as AuthenticationError, N as NetworkError, e as PushFloError, V as ValidationError } from './ValidationError-CDHx9EHH.js';
3
+ import { L as ListChannelsOptions, C as Channel, P as Pagination, a as ChannelInput, b as ChannelUpdateInput } from './api-CkP76uCc.js';
4
+ export { M as MAX_SLUG_LENGTH, c as MIN_SLUG_LENGTH, S as SlugValidationResult, i as isValidChannelSlug, t as toChannelSlug, v as validateChannelSlug } from './api-CkP76uCc.js';
5
5
 
6
6
  /**
7
7
  * Server-side PushFlo client for publishing messages and managing channels
8
+ *
9
+ * Uses two different APIs:
10
+ * - Realtime API (api.pushflo.dev): publish messages, message history
11
+ * - Console API (console.pushflo.dev): channel CRUD operations
8
12
  */
9
13
  declare class PushFloServer {
10
- private readonly client;
14
+ /** Client for Realtime API (publish, message history) */
15
+ private readonly realtimeClient;
16
+ /** Client for Console API (channel CRUD) */
17
+ private readonly consoleClient;
11
18
  constructor(options: ServerOptions);
12
19
  /**
13
20
  * List all channels
21
+ * @note Requires mgmt_ key. Uses Console API.
14
22
  */
15
23
  listChannels(options?: ListChannelsOptions): Promise<{
16
24
  channels: Channel[];
@@ -18,20 +26,23 @@ declare class PushFloServer {
18
26
  }>;
19
27
  /**
20
28
  * Get a channel by slug
29
+ * @note Requires mgmt_ key. Uses Console API.
21
30
  */
22
31
  getChannel(slug: string): Promise<Channel>;
23
32
  /**
24
33
  * Create a new channel
25
- *
34
+ * @note Requires mgmt_ key. Uses Console API.
26
35
  * @throws {ValidationError} If the channel slug is invalid
27
36
  */
28
37
  createChannel(input: ChannelInput): Promise<Channel>;
29
38
  /**
30
39
  * Update an existing channel
40
+ * @note Requires mgmt_ key. Uses Console API.
31
41
  */
32
42
  updateChannel(slug: string, input: ChannelUpdateInput): Promise<Channel>;
33
43
  /**
34
44
  * Delete a channel
45
+ * @note Requires mgmt_ key. Uses Console API.
35
46
  */
36
47
  deleteChannel(slug: string): Promise<void>;
37
48
  /**
@@ -40,13 +51,13 @@ declare class PushFloServer {
40
51
  private validateSlug;
41
52
  /**
42
53
  * Publish a message to a channel
43
- *
54
+ * @note Uses Realtime API. Works with sec_ or mgmt_ key.
44
55
  * @throws {ValidationError} If the channel slug is invalid
45
56
  */
46
57
  publish(channel: string, content: Record<string, unknown>, options?: PublishOptions): Promise<PublishResult>;
47
58
  /**
48
59
  * Get message history for a channel
49
- *
60
+ * @note Uses Realtime API. Works with sec_ or mgmt_ key.
50
61
  * @throws {ValidationError} If the channel slug is invalid
51
62
  */
52
63
  getMessageHistory(channel: string, options?: MessageHistoryOptions): Promise<{