@scalemule/nextjs 0.1.18 → 0.1.19

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 CHANGED
@@ -34,6 +34,8 @@ This creates all auth endpoints automatically:
34
34
 
35
35
  API keys never reach the browser. Session tokens are HTTP-only cookies.
36
36
 
37
+ Need the cookie/header lifecycle or the proxy-vs-direct decision tree? See [`docs/AUTH_PROXY_PATTERN.md`](./docs/AUTH_PROXY_PATTERN.md).
38
+
37
39
  ## Environment Variables
38
40
 
39
41
  ```bash
@@ -295,7 +297,7 @@ export const { GET, POST, DELETE, PATCH } = createAuthRoutes({
295
297
 
296
298
  ```ts
297
299
  // Read CSRF token from cookie and include in requests
298
- const csrfToken = document.cookie.match(/csrf_token=([^;]+)/)?.[1]
300
+ const csrfToken = document.cookie.match(/sm_csrf=([^;]+)/)?.[1]
299
301
 
300
302
  fetch('/api/auth/login', {
301
303
  method: 'POST',
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { ApiError, RealtimeService, StorageService, PhotoService, VideoService, AudioService, FileStatus } from '@scalemule/sdk';
2
+ import { ApiError, RealtimeService, StorageService, PhotoService, VideoService, AudioService, TtsService, TtsJobStatus, FileStatus } from '@scalemule/sdk';
3
3
  import * as React from 'react';
4
4
  import { ReactNode, ReactElement } from 'react';
5
5
  import { MoneyClient } from '@scalemule/money';
@@ -166,6 +166,8 @@ interface ScaleMuleContextValue {
166
166
  video: VideoService;
167
167
  /** Base SDK audio service — exposed for `useMedia()` and `audio.uploadViaStorage()` */
168
168
  audio: AudioService;
169
+ /** Base SDK TTS service — exposed for `useTtsJob()` and direct narration requests */
170
+ tts: TtsService;
169
171
  /**
170
172
  * Default media policy for `useMedia()` calls. Set via
171
173
  * `<ScaleMuleProvider mediaPolicy="…">`; per-call overrides win.
@@ -360,6 +362,18 @@ interface UseAudioReturn {
360
362
  }
361
363
  declare function useAudio(): UseAudioReturn;
362
364
 
365
+ interface UseTtsJobOptions {
366
+ enabled?: boolean;
367
+ pollIntervalMs?: number;
368
+ }
369
+ interface UseTtsJobReturn {
370
+ job: TtsJobStatus | null;
371
+ loading: boolean;
372
+ error: ApiError | null;
373
+ refresh: () => Promise<TtsJobStatus | null>;
374
+ }
375
+ declare function useTtsJob(jobId: string | null | undefined, options?: UseTtsJobOptions): UseTtsJobReturn;
376
+
363
377
  /**
364
378
  * Conversation kinds recognized by the chat realtime channel naming scheme.
365
379
  * Matches `broadcast_to_conversation` in `ms/scalemule-chat/src/realtime.rs`.
@@ -1032,4 +1046,4 @@ declare function createSafeLogger(prefix: string): {
1032
1046
  error: (message: string, data?: unknown) => void;
1033
1047
  };
1034
1048
 
1035
- export { ApiError$1 as ApiError, type AudioFile, type AudioUploadResult, type ConversationKind, type FeatureFlagEvaluation, type FeatureFlagEvaluation as FeatureFlagResult, type FeedbackItem, type FeedbackItemInput, type FeedbackPriority, type FeedbackStatus, type FeedbackType, FeedbackWidget, type FeedbackWidgetConfig, type FeedbackWidgetProps, ListFilesParams, LoginResponse, type MediaPolicy, type MediaUploadResult, type PasswordValidationResult, type PhoneCountry, type PhoneValidationResult, type RealtimeEvent, type RealtimeMessage, type RealtimeStatus, ScaleMuleClient, ScaleMuleConfig, ScaleMuleMedia, type ScaleMuleMediaProps, ScaleMuleProvider, type ScaleMuleProviderProps, UseAnalyticsOptions, UseAnalyticsReturn, type UseAudioReturn, type UseAudioUploadOptions, UseAuthReturn, UseBillingReturn, UseContentReturn, type UseFeatureFlagsOptions, type UseFeatureFlagsReturn, type UseFeedbackOptions, type UseFeedbackResult, type UseFileStatusOptions, type UseFileStatusReturn, type UseFeatureFlagsOptions as UseFlagsOptions, type UseFeatureFlagsReturn as UseFlagsReturn, type UseMediaReturn, type UseMediaUploadOptions, type UsePushNotificationsOptions, type UsePushNotificationsReturn, type UseRealtimeOptions, type UseRealtimeReturn, type UseShareOptions, type UseShareReturn, UseUserReturn, User, type UsernameValidationResult, composePhone, createSafeLogger, normalizePhone, phoneCountries, sanitizeForLog, useAnalytics, useAudio, useAuth, useBilling, useContent, useFeatureFlags, useFeedback, useFileStatus, useMedia, useMoney, useMoneyClient, usePushNotifications, useRealtime, useScaleMule, useScaleMuleClient, useShare, useUser, validateForm, validators };
1049
+ export { ApiError$1 as ApiError, type AudioFile, type AudioUploadResult, type ConversationKind, type FeatureFlagEvaluation, type FeatureFlagEvaluation as FeatureFlagResult, type FeedbackItem, type FeedbackItemInput, type FeedbackPriority, type FeedbackStatus, type FeedbackType, FeedbackWidget, type FeedbackWidgetConfig, type FeedbackWidgetProps, ListFilesParams, LoginResponse, type MediaPolicy, type MediaUploadResult, type PasswordValidationResult, type PhoneCountry, type PhoneValidationResult, type RealtimeEvent, type RealtimeMessage, type RealtimeStatus, ScaleMuleClient, ScaleMuleConfig, ScaleMuleMedia, type ScaleMuleMediaProps, ScaleMuleProvider, type ScaleMuleProviderProps, UseAnalyticsOptions, UseAnalyticsReturn, type UseAudioReturn, type UseAudioUploadOptions, UseAuthReturn, UseBillingReturn, UseContentReturn, type UseFeatureFlagsOptions, type UseFeatureFlagsReturn, type UseFeedbackOptions, type UseFeedbackResult, type UseFileStatusOptions, type UseFileStatusReturn, type UseFeatureFlagsOptions as UseFlagsOptions, type UseFeatureFlagsReturn as UseFlagsReturn, type UseMediaReturn, type UseMediaUploadOptions, type UsePushNotificationsOptions, type UsePushNotificationsReturn, type UseRealtimeOptions, type UseRealtimeReturn, type UseShareOptions, type UseShareReturn, type UseTtsJobOptions, type UseTtsJobReturn, UseUserReturn, User, type UsernameValidationResult, composePhone, createSafeLogger, normalizePhone, phoneCountries, sanitizeForLog, useAnalytics, useAudio, useAuth, useBilling, useContent, useFeatureFlags, useFeedback, useFileStatus, useMedia, useMoney, useMoneyClient, usePushNotifications, useRealtime, useScaleMule, useScaleMuleClient, useShare, useTtsJob, useUser, validateForm, validators };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { ApiError, RealtimeService, StorageService, PhotoService, VideoService, AudioService, FileStatus } from '@scalemule/sdk';
2
+ import { ApiError, RealtimeService, StorageService, PhotoService, VideoService, AudioService, TtsService, TtsJobStatus, FileStatus } from '@scalemule/sdk';
3
3
  import * as React from 'react';
4
4
  import { ReactNode, ReactElement } from 'react';
5
5
  import { MoneyClient } from '@scalemule/money';
@@ -166,6 +166,8 @@ interface ScaleMuleContextValue {
166
166
  video: VideoService;
167
167
  /** Base SDK audio service — exposed for `useMedia()` and `audio.uploadViaStorage()` */
168
168
  audio: AudioService;
169
+ /** Base SDK TTS service — exposed for `useTtsJob()` and direct narration requests */
170
+ tts: TtsService;
169
171
  /**
170
172
  * Default media policy for `useMedia()` calls. Set via
171
173
  * `<ScaleMuleProvider mediaPolicy="…">`; per-call overrides win.
@@ -360,6 +362,18 @@ interface UseAudioReturn {
360
362
  }
361
363
  declare function useAudio(): UseAudioReturn;
362
364
 
365
+ interface UseTtsJobOptions {
366
+ enabled?: boolean;
367
+ pollIntervalMs?: number;
368
+ }
369
+ interface UseTtsJobReturn {
370
+ job: TtsJobStatus | null;
371
+ loading: boolean;
372
+ error: ApiError | null;
373
+ refresh: () => Promise<TtsJobStatus | null>;
374
+ }
375
+ declare function useTtsJob(jobId: string | null | undefined, options?: UseTtsJobOptions): UseTtsJobReturn;
376
+
363
377
  /**
364
378
  * Conversation kinds recognized by the chat realtime channel naming scheme.
365
379
  * Matches `broadcast_to_conversation` in `ms/scalemule-chat/src/realtime.rs`.
@@ -1032,4 +1046,4 @@ declare function createSafeLogger(prefix: string): {
1032
1046
  error: (message: string, data?: unknown) => void;
1033
1047
  };
1034
1048
 
1035
- export { ApiError$1 as ApiError, type AudioFile, type AudioUploadResult, type ConversationKind, type FeatureFlagEvaluation, type FeatureFlagEvaluation as FeatureFlagResult, type FeedbackItem, type FeedbackItemInput, type FeedbackPriority, type FeedbackStatus, type FeedbackType, FeedbackWidget, type FeedbackWidgetConfig, type FeedbackWidgetProps, ListFilesParams, LoginResponse, type MediaPolicy, type MediaUploadResult, type PasswordValidationResult, type PhoneCountry, type PhoneValidationResult, type RealtimeEvent, type RealtimeMessage, type RealtimeStatus, ScaleMuleClient, ScaleMuleConfig, ScaleMuleMedia, type ScaleMuleMediaProps, ScaleMuleProvider, type ScaleMuleProviderProps, UseAnalyticsOptions, UseAnalyticsReturn, type UseAudioReturn, type UseAudioUploadOptions, UseAuthReturn, UseBillingReturn, UseContentReturn, type UseFeatureFlagsOptions, type UseFeatureFlagsReturn, type UseFeedbackOptions, type UseFeedbackResult, type UseFileStatusOptions, type UseFileStatusReturn, type UseFeatureFlagsOptions as UseFlagsOptions, type UseFeatureFlagsReturn as UseFlagsReturn, type UseMediaReturn, type UseMediaUploadOptions, type UsePushNotificationsOptions, type UsePushNotificationsReturn, type UseRealtimeOptions, type UseRealtimeReturn, type UseShareOptions, type UseShareReturn, UseUserReturn, User, type UsernameValidationResult, composePhone, createSafeLogger, normalizePhone, phoneCountries, sanitizeForLog, useAnalytics, useAudio, useAuth, useBilling, useContent, useFeatureFlags, useFeedback, useFileStatus, useMedia, useMoney, useMoneyClient, usePushNotifications, useRealtime, useScaleMule, useScaleMuleClient, useShare, useUser, validateForm, validators };
1049
+ export { ApiError$1 as ApiError, type AudioFile, type AudioUploadResult, type ConversationKind, type FeatureFlagEvaluation, type FeatureFlagEvaluation as FeatureFlagResult, type FeedbackItem, type FeedbackItemInput, type FeedbackPriority, type FeedbackStatus, type FeedbackType, FeedbackWidget, type FeedbackWidgetConfig, type FeedbackWidgetProps, ListFilesParams, LoginResponse, type MediaPolicy, type MediaUploadResult, type PasswordValidationResult, type PhoneCountry, type PhoneValidationResult, type RealtimeEvent, type RealtimeMessage, type RealtimeStatus, ScaleMuleClient, ScaleMuleConfig, ScaleMuleMedia, type ScaleMuleMediaProps, ScaleMuleProvider, type ScaleMuleProviderProps, UseAnalyticsOptions, UseAnalyticsReturn, type UseAudioReturn, type UseAudioUploadOptions, UseAuthReturn, UseBillingReturn, UseContentReturn, type UseFeatureFlagsOptions, type UseFeatureFlagsReturn, type UseFeedbackOptions, type UseFeedbackResult, type UseFileStatusOptions, type UseFileStatusReturn, type UseFeatureFlagsOptions as UseFlagsOptions, type UseFeatureFlagsReturn as UseFlagsReturn, type UseMediaReturn, type UseMediaUploadOptions, type UsePushNotificationsOptions, type UsePushNotificationsReturn, type UseRealtimeOptions, type UseRealtimeReturn, type UseShareOptions, type UseShareReturn, type UseTtsJobOptions, type UseTtsJobReturn, UseUserReturn, User, type UsernameValidationResult, composePhone, createSafeLogger, normalizePhone, phoneCountries, sanitizeForLog, useAnalytics, useAudio, useAuth, useBilling, useContent, useFeatureFlags, useFeedback, useFileStatus, useMedia, useMoney, useMoneyClient, usePushNotifications, useRealtime, useScaleMule, useScaleMuleClient, useShare, useTtsJob, useUser, validateForm, validators };
package/dist/index.js CHANGED
@@ -7804,6 +7804,7 @@ function ScaleMuleProvider({
7804
7804
  photo: baseClient.photo,
7805
7805
  video: baseClient.video,
7806
7806
  audio: baseClient.audio,
7807
+ tts: baseClient.tts,
7807
7808
  mediaPolicy: effectiveMediaPolicy,
7808
7809
  user,
7809
7810
  setUser: handleSetUser,
@@ -9192,7 +9193,7 @@ function useAudio() {
9192
9193
  return null;
9193
9194
  }
9194
9195
  try {
9195
- const details = await client.get(`/v1/audios/${audioId}`);
9196
+ const details = await client.get(`/v1/audio/${audioId}`);
9196
9197
  if (details.status === "ready" && details.url) {
9197
9198
  return details.url;
9198
9199
  }
@@ -9254,7 +9255,7 @@ function useAudio() {
9254
9255
  const enriched = await Promise.all(
9255
9256
  audioFiles.map(async (file) => {
9256
9257
  try {
9257
- const details = await client.get(`/v1/audios/${file.id}`);
9258
+ const details = await client.get(`/v1/audio/${file.id}`);
9258
9259
  return {
9259
9260
  audio_id: details.id,
9260
9261
  file_id: file.id,
@@ -9290,7 +9291,7 @@ function useAudio() {
9290
9291
  setError(null);
9291
9292
  try {
9292
9293
  const [audioDeleteResult, storageDeleteResult] = await Promise.allSettled([
9293
- client.delete(`/v1/audios/${fileId}`),
9294
+ client.delete(`/v1/audio/${fileId}`),
9294
9295
  client.delete(`/v1/storage/files/${fileId}`)
9295
9296
  ]);
9296
9297
  if (storageDeleteResult.status === "rejected" && !isNotFoundError(storageDeleteResult.reason)) {
@@ -9317,6 +9318,63 @@ function useAudio() {
9317
9318
  loading
9318
9319
  };
9319
9320
  }
9321
+ var DEFAULT_POLL_INTERVAL_MS = 2e3;
9322
+ var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["ready", "failed"]);
9323
+ function useTtsJob(jobId, options) {
9324
+ const { tts } = useScaleMule();
9325
+ const [job, setJob] = React.useState(null);
9326
+ const [loading, setLoading] = React.useState(false);
9327
+ const [error, setError] = React.useState(null);
9328
+ const refresh = React.useCallback(async () => {
9329
+ if (!jobId) {
9330
+ setJob(null);
9331
+ return null;
9332
+ }
9333
+ setLoading(true);
9334
+ setError(null);
9335
+ try {
9336
+ const result = await tts.getJob(jobId);
9337
+ if (!result) {
9338
+ const apiError = { code: "tts_job_error", message: "Failed to load TTS job", status: 500 };
9339
+ setError(apiError);
9340
+ return null;
9341
+ }
9342
+ if (result.error || !result.data) {
9343
+ const apiError = result.error ?? { code: "tts_job_error", message: "Failed to load TTS job", status: 500 };
9344
+ setError(apiError);
9345
+ return null;
9346
+ }
9347
+ setJob(result.data);
9348
+ return result.data;
9349
+ } finally {
9350
+ setLoading(false);
9351
+ }
9352
+ }, [jobId, tts]);
9353
+ React.useEffect(() => {
9354
+ if (!jobId || options?.enabled === false) {
9355
+ setJob(null);
9356
+ setLoading(false);
9357
+ return;
9358
+ }
9359
+ let cancelled = false;
9360
+ let timeoutId = null;
9361
+ const poll = async () => {
9362
+ const next = await refresh();
9363
+ if (cancelled || !next || TERMINAL_STATUSES.has(next.status)) {
9364
+ return;
9365
+ }
9366
+ timeoutId = window.setTimeout(poll, options?.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS);
9367
+ };
9368
+ poll();
9369
+ return () => {
9370
+ cancelled = true;
9371
+ if (timeoutId != null) {
9372
+ window.clearTimeout(timeoutId);
9373
+ }
9374
+ };
9375
+ }, [jobId, options?.enabled, options?.pollIntervalMs, refresh]);
9376
+ return { job, loading, error, refresh };
9377
+ }
9320
9378
  function useMedia() {
9321
9379
  const { storage, photo, video, audio, mediaPolicy: providerDefaultPolicy } = useScaleMule();
9322
9380
  const [uploading, setUploading] = React.useState(false);
@@ -11557,6 +11615,7 @@ exports.useRealtime = useRealtime;
11557
11615
  exports.useScaleMule = useScaleMule;
11558
11616
  exports.useScaleMuleClient = useScaleMuleClient;
11559
11617
  exports.useShare = useShare;
11618
+ exports.useTtsJob = useTtsJob;
11560
11619
  exports.useUser = useUser;
11561
11620
  exports.validateForm = validateForm;
11562
11621
  exports.validators = validators;
package/dist/index.mjs CHANGED
@@ -7784,6 +7784,7 @@ function ScaleMuleProvider({
7784
7784
  photo: baseClient.photo,
7785
7785
  video: baseClient.video,
7786
7786
  audio: baseClient.audio,
7787
+ tts: baseClient.tts,
7787
7788
  mediaPolicy: effectiveMediaPolicy,
7788
7789
  user,
7789
7790
  setUser: handleSetUser,
@@ -9172,7 +9173,7 @@ function useAudio() {
9172
9173
  return null;
9173
9174
  }
9174
9175
  try {
9175
- const details = await client.get(`/v1/audios/${audioId}`);
9176
+ const details = await client.get(`/v1/audio/${audioId}`);
9176
9177
  if (details.status === "ready" && details.url) {
9177
9178
  return details.url;
9178
9179
  }
@@ -9234,7 +9235,7 @@ function useAudio() {
9234
9235
  const enriched = await Promise.all(
9235
9236
  audioFiles.map(async (file) => {
9236
9237
  try {
9237
- const details = await client.get(`/v1/audios/${file.id}`);
9238
+ const details = await client.get(`/v1/audio/${file.id}`);
9238
9239
  return {
9239
9240
  audio_id: details.id,
9240
9241
  file_id: file.id,
@@ -9270,7 +9271,7 @@ function useAudio() {
9270
9271
  setError(null);
9271
9272
  try {
9272
9273
  const [audioDeleteResult, storageDeleteResult] = await Promise.allSettled([
9273
- client.delete(`/v1/audios/${fileId}`),
9274
+ client.delete(`/v1/audio/${fileId}`),
9274
9275
  client.delete(`/v1/storage/files/${fileId}`)
9275
9276
  ]);
9276
9277
  if (storageDeleteResult.status === "rejected" && !isNotFoundError(storageDeleteResult.reason)) {
@@ -9297,6 +9298,63 @@ function useAudio() {
9297
9298
  loading
9298
9299
  };
9299
9300
  }
9301
+ var DEFAULT_POLL_INTERVAL_MS = 2e3;
9302
+ var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["ready", "failed"]);
9303
+ function useTtsJob(jobId, options) {
9304
+ const { tts } = useScaleMule();
9305
+ const [job, setJob] = useState(null);
9306
+ const [loading, setLoading] = useState(false);
9307
+ const [error, setError] = useState(null);
9308
+ const refresh = useCallback(async () => {
9309
+ if (!jobId) {
9310
+ setJob(null);
9311
+ return null;
9312
+ }
9313
+ setLoading(true);
9314
+ setError(null);
9315
+ try {
9316
+ const result = await tts.getJob(jobId);
9317
+ if (!result) {
9318
+ const apiError = { code: "tts_job_error", message: "Failed to load TTS job", status: 500 };
9319
+ setError(apiError);
9320
+ return null;
9321
+ }
9322
+ if (result.error || !result.data) {
9323
+ const apiError = result.error ?? { code: "tts_job_error", message: "Failed to load TTS job", status: 500 };
9324
+ setError(apiError);
9325
+ return null;
9326
+ }
9327
+ setJob(result.data);
9328
+ return result.data;
9329
+ } finally {
9330
+ setLoading(false);
9331
+ }
9332
+ }, [jobId, tts]);
9333
+ useEffect(() => {
9334
+ if (!jobId || options?.enabled === false) {
9335
+ setJob(null);
9336
+ setLoading(false);
9337
+ return;
9338
+ }
9339
+ let cancelled = false;
9340
+ let timeoutId = null;
9341
+ const poll = async () => {
9342
+ const next = await refresh();
9343
+ if (cancelled || !next || TERMINAL_STATUSES.has(next.status)) {
9344
+ return;
9345
+ }
9346
+ timeoutId = window.setTimeout(poll, options?.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS);
9347
+ };
9348
+ poll();
9349
+ return () => {
9350
+ cancelled = true;
9351
+ if (timeoutId != null) {
9352
+ window.clearTimeout(timeoutId);
9353
+ }
9354
+ };
9355
+ }, [jobId, options?.enabled, options?.pollIntervalMs, refresh]);
9356
+ return { job, loading, error, refresh };
9357
+ }
9300
9358
  function useMedia() {
9301
9359
  const { storage, photo, video, audio, mediaPolicy: providerDefaultPolicy } = useScaleMule();
9302
9360
  const [uploading, setUploading] = useState(false);
@@ -11502,4 +11560,4 @@ function createSafeLogger(prefix) {
11502
11560
  };
11503
11561
  }
11504
11562
 
11505
- export { FeedbackWidget, ScaleMuleApiError, ScaleMuleClient2 as ScaleMuleClient, ScaleMuleMedia, ScaleMuleProvider, composePhone, createClient, createSafeLogger, normalizePhone, phoneCountries, sanitizeForLog, useAnalytics, useAudio, useAuth, useBilling, useContent, useFeatureFlags, useFeedback, useFileStatus, useMedia, useMoney, useMoneyClient, usePushNotifications, useRealtime, useScaleMule, useScaleMuleClient, useShare, useUser, validateForm, validators };
11563
+ export { FeedbackWidget, ScaleMuleApiError, ScaleMuleClient2 as ScaleMuleClient, ScaleMuleMedia, ScaleMuleProvider, composePhone, createClient, createSafeLogger, normalizePhone, phoneCountries, sanitizeForLog, useAnalytics, useAudio, useAuth, useBilling, useContent, useFeatureFlags, useFeedback, useFileStatus, useMedia, useMoney, useMoneyClient, usePushNotifications, useRealtime, useScaleMule, useScaleMuleClient, useShare, useTtsJob, useUser, validateForm, validators };