@scalemule/nextjs 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +175 -153
- package/dist/index.d.ts +175 -153
- package/dist/index.js +7 -5
- package/dist/index.mjs +7 -5
- package/package.json +3 -2
package/dist/index.d.mts
CHANGED
|
@@ -1,14 +1,156 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ApiError, RealtimeService, StorageService, PhotoService, VideoService, FileStatus } from '@scalemule/sdk';
|
|
2
3
|
import * as React from 'react';
|
|
3
4
|
import { ReactNode, ReactElement } from 'react';
|
|
4
5
|
import { MoneyClient } from '@scalemule/money';
|
|
5
6
|
export { MoneyClient, MoneyClientConfig, createMoneyClient } from '@scalemule/money';
|
|
6
|
-
import { RealtimeService, StorageService, PhotoService, VideoService, ApiError as ApiError$1, FileStatus } from '@scalemule/sdk';
|
|
7
7
|
import { ScaleMuleClient } from './client.mjs';
|
|
8
8
|
export { ClientConfig, RequestOptions, createClient } from './client.mjs';
|
|
9
|
-
import { S as ScaleMuleConfig, U as User, L as LoginResponse, A as ApiError, a as UseAuthReturn, b as UseBillingReturn, c as ListFilesParams, d as UseContentReturn, e as UseUserReturn, f as UseAnalyticsOptions, g as UseAnalyticsReturn } from './index-BIIUrnPr.mjs';
|
|
9
|
+
import { S as ScaleMuleConfig, U as User, L as LoginResponse, A as ApiError$1, a as UseAuthReturn, b as UseBillingReturn, c as ListFilesParams, d as UseContentReturn, e as UseUserReturn, f as UseAnalyticsOptions, g as UseAnalyticsReturn } from './index-BIIUrnPr.mjs';
|
|
10
10
|
export { h as AccountBalance, i as AnalyticsEvent, j as ApiResponse, B as BatchTrackRequest, k as BillingPayment, l as BillingPayout, m as BillingRefund, n as BillingTransaction, C as ChangeEmailRequest, o as ChangePasswordRequest, p as ClientContext, q as ConnectedAccount, D as DeviceFingerprint, r as DeviceInfo, E as EnhancedAnalyticsEvent, F as ForgotPasswordRequest, K as KnownAccountInfo, s as LinkedAccount, t as ListFilesResponse, u as LoginDeviceInfo, v as LoginRequest, w as LoginResponseWithMFA, x as LoginRiskInfo, M as MFAChallengeResponse, y as MFAMethod, z as MFASMSSetupResponse, G as MFASetupRequest, H as MFAStatus, I as MFATOTPSetupResponse, J as MFAVerifyRequest, O as OAuthCallbackRequest, N as OAuthCallbackResponse, P as OAuthConfig, Q as OAuthProvider, R as OAuthStartResponse, T as PageViewData, V as PayoutSchedule, W as PhoneLoginRequest, X as PhoneSendCodeRequest, Y as PhoneVerifyRequest, Z as Profile, _ as RefreshResponse, $ as RegisterRequest, a0 as ResetPasswordRequest, a1 as ScaleMuleApiError, a2 as ScaleMuleEnvironment, a3 as Session, a4 as SignedUploadCompleteRequest, a5 as SignedUploadRequest, a6 as SignedUploadResponse, a7 as SignedUploadUrl, a8 as StorageAdapter, a9 as StorageFile, aa as TrackEventResponse, ab as TransactionSummary, ac as UTMParams, ad as UpdateProfileRequest, ae as UploadOptions, af as UploadResponse, ag as VerifyEmailRequest } from './index-BIIUrnPr.mjs';
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Result of a single {@link useMedia} upload call.
|
|
14
|
+
*
|
|
15
|
+
* The shape is normalized regardless of MIME type — `optimized_url_promise`
|
|
16
|
+
* resolves on image uploads after the photo optimizer finishes; for non-image
|
|
17
|
+
* uploads it resolves to `null` immediately. (Video / audio branches will
|
|
18
|
+
* populate `hls_url_promise` in later phases — today they fall through to
|
|
19
|
+
* generic storage and that field stays `null`.)
|
|
20
|
+
*/
|
|
21
|
+
interface MediaUploadResult {
|
|
22
|
+
/** Storage file_id — store this in chat-attachment metadata. */
|
|
23
|
+
file_id: string;
|
|
24
|
+
/** Photo service id — null for non-image uploads or when register() failed. */
|
|
25
|
+
photo_id: string | null;
|
|
26
|
+
/** Short-lived signed URL to the original bytes (private uploads) or
|
|
27
|
+
* a public CDN URL (when caller passed `is_public: true`). */
|
|
28
|
+
original_view_url: string | null;
|
|
29
|
+
/** Resolves once the photo optimizer finishes. `null` for non-image
|
|
30
|
+
* MIME types or when register() failed. */
|
|
31
|
+
optimized_url_promise: Promise<string | null>;
|
|
32
|
+
/** Resolves once the video transcoder finishes (Phase 2 / S5b). `null` today. */
|
|
33
|
+
hls_url_promise: Promise<string | null>;
|
|
34
|
+
/** The file's MIME type — preserved from the input File / Blob. */
|
|
35
|
+
mime_type: string;
|
|
36
|
+
/** Whether the resulting storage object is public-readable. */
|
|
37
|
+
is_public: boolean;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Per-app media-pipeline policy. Drives release-gating + processing
|
|
41
|
+
* behavior. **Orthogonal to `is_public`.** See
|
|
42
|
+
* `docs/MEDIA-UPLOADS.md` and ADR-2026-04-26 for the full taxonomy.
|
|
43
|
+
*
|
|
44
|
+
* Today's behavior (Phase 4 v1):
|
|
45
|
+
* - `fast_trusted` / `safe_visible` (default): upload promise resolves
|
|
46
|
+
* as soon as the file is uploaded + registered. The post-processing
|
|
47
|
+
* (scan, optimize, transcode) runs async; callers can observe via
|
|
48
|
+
* `useFileStatus`.
|
|
49
|
+
* - `safe_public` / `moderated`: upload promise *waits* for the
|
|
50
|
+
* optimized image variant (image MIME) or HLS playlist (video MIME)
|
|
51
|
+
* to become ready before resolving. Acts as the release-gate for
|
|
52
|
+
* UGC-style apps that should not publish raw bytes.
|
|
53
|
+
* - `compliance`: today behaves as `safe_public`; Phase 4+ adds the
|
|
54
|
+
* audit-log + signed-with-purpose URL semantics.
|
|
55
|
+
*/
|
|
56
|
+
type MediaPolicy = 'fast_trusted' | 'safe_visible' | 'safe_public' | 'moderated' | 'compliance';
|
|
57
|
+
interface UseMediaUploadOptions {
|
|
58
|
+
/** Whether the resulting storage object should be public-readable.
|
|
59
|
+
* Default: `false` (private). Public is opt-in for surfaces that
|
|
60
|
+
* genuinely need it (avatars, public listings). Chat / DM uploads
|
|
61
|
+
* should always be private. */
|
|
62
|
+
is_public?: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Per-call media-policy override. Defaults to `safe_visible` (visible
|
|
65
|
+
* immediately at original fidelity; optimized variants swap in async).
|
|
66
|
+
* Set to `safe_public` to make the upload promise *await* the optimized
|
|
67
|
+
* variant (image) or HLS playlist (video) before resolving — useful for
|
|
68
|
+
* broadcast / UGC apps that gate publication on processing complete.
|
|
69
|
+
*
|
|
70
|
+
* The per-app default lives in `application_storage_settings.media_policy`
|
|
71
|
+
* (Phase 4 / P3, live in prod 2026-04-26). Reading the per-app default
|
|
72
|
+
* into `useMedia` defaults lands in a follow-up; today the option is
|
|
73
|
+
* caller-provided per call.
|
|
74
|
+
*/
|
|
75
|
+
policy?: MediaPolicy;
|
|
76
|
+
/** Display filename (sanitized server-side). */
|
|
77
|
+
filename?: string;
|
|
78
|
+
/** Custom metadata attached to the file. */
|
|
79
|
+
metadata?: Record<string, unknown>;
|
|
80
|
+
/** Upload progress callback (0-100). */
|
|
81
|
+
onProgress?: (percent: number) => void;
|
|
82
|
+
/** AbortSignal for cancellation. */
|
|
83
|
+
signal?: AbortSignal;
|
|
84
|
+
/** Force a non-photo path even for image MIME types — useful for
|
|
85
|
+
* generic file uploads where you don't want the photo optimizer
|
|
86
|
+
* to register the file. Default: `false`. */
|
|
87
|
+
skipPhotoRegister?: boolean;
|
|
88
|
+
}
|
|
89
|
+
interface UseMediaReturn {
|
|
90
|
+
/** Upload a file. MIME-aware: images go through photo register +
|
|
91
|
+
* optimization; everything else goes through generic storage. */
|
|
92
|
+
upload: (file: File | Blob, options?: UseMediaUploadOptions) => Promise<MediaUploadResult>;
|
|
93
|
+
/** Cancel an upload by its `file_id`. Deletes the storage object so
|
|
94
|
+
* it doesn't orphan in S3 — useful when a chat composer accepts a
|
|
95
|
+
* file but the user removes it before sending. Idempotent. */
|
|
96
|
+
cancelUpload: (fileId: string) => Promise<void>;
|
|
97
|
+
/** Last error from `upload` or `cancelUpload`. */
|
|
98
|
+
error: ApiError | null;
|
|
99
|
+
/** True while an upload is in progress. */
|
|
100
|
+
uploading: boolean;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Opinionated, MIME-aware media upload hook.
|
|
104
|
+
*
|
|
105
|
+
* `useMedia()` is the canonical upload primitive for chat / progressive
|
|
106
|
+
* media use. It branches by MIME type:
|
|
107
|
+
* - `image/*` → `client.photo.uploadViaStorage()` — upload to storage,
|
|
108
|
+
* then register with the photo service so the on-demand transform
|
|
109
|
+
* endpoint resolves to optimized variants. The returned
|
|
110
|
+
* `optimized_url_promise` resolves once the optimizer finishes.
|
|
111
|
+
* - everything else → `client.storage.uploadPrivate()` — a private,
|
|
112
|
+
* uncompressed, fail-closed upload to generic storage.
|
|
113
|
+
*
|
|
114
|
+
* **Default visibility is `is_public: false`.** Public is opt-in per call.
|
|
115
|
+
* `useMedia()` does not expose `is_public` via app-level config — visibility
|
|
116
|
+
* is always an explicit per-call surface choice.
|
|
117
|
+
*
|
|
118
|
+
* Compared to `useContent()`:
|
|
119
|
+
* - `useContent()` is a thin wrapper over generic storage and does not
|
|
120
|
+
* register photos / videos with their typed services. Use it for plain
|
|
121
|
+
* file uploads where you don't need optimization or transcoding.
|
|
122
|
+
* - `useMedia()` defaults to private + no compression, integrates with the
|
|
123
|
+
* typed media services automatically, and is the right primitive for
|
|
124
|
+
* anything chat- or media-shaped.
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```tsx
|
|
128
|
+
* 'use client';
|
|
129
|
+
*
|
|
130
|
+
* import { useMedia, ScaleMuleMedia } from '@scalemule/nextjs';
|
|
131
|
+
*
|
|
132
|
+
* function ChatComposer({ onAttach }) {
|
|
133
|
+
* const { upload, uploading } = useMedia();
|
|
134
|
+
*
|
|
135
|
+
* async function handlePick(file: File) {
|
|
136
|
+
* const result = await upload(file);
|
|
137
|
+
* onAttach({
|
|
138
|
+
* file_id: result.file_id,
|
|
139
|
+
* mime_type: result.mime_type,
|
|
140
|
+
* optimized_url_promise: result.optimized_url_promise,
|
|
141
|
+
* });
|
|
142
|
+
* }
|
|
143
|
+
*
|
|
144
|
+
* return <input type="file" disabled={uploading}
|
|
145
|
+
* onChange={(e) => e.target.files?.[0] && handlePick(e.target.files[0])} />;
|
|
146
|
+
* }
|
|
147
|
+
* ```
|
|
148
|
+
*
|
|
149
|
+
* See `docs/MEDIA-UPLOADS.md` in the platform repo for the decision
|
|
150
|
+
* tree and the full anti-patterns list.
|
|
151
|
+
*/
|
|
152
|
+
declare function useMedia(): UseMediaReturn;
|
|
153
|
+
|
|
12
154
|
interface ScaleMuleContextValue {
|
|
13
155
|
/** The API client instance */
|
|
14
156
|
client: ScaleMuleClient;
|
|
@@ -22,6 +164,12 @@ interface ScaleMuleContextValue {
|
|
|
22
164
|
photo: PhotoService;
|
|
23
165
|
/** Base SDK video service — exposed for `useMedia()` and `video.uploadViaStorage()` */
|
|
24
166
|
video: VideoService;
|
|
167
|
+
/**
|
|
168
|
+
* Default media policy for `useMedia()` calls. Set via
|
|
169
|
+
* `<ScaleMuleProvider mediaPolicy="…">`; per-call overrides win.
|
|
170
|
+
* Undefined falls back to `useMedia()`'s built-in `safe_visible` default.
|
|
171
|
+
*/
|
|
172
|
+
mediaPolicy?: MediaPolicy;
|
|
25
173
|
/** Current authenticated user */
|
|
26
174
|
user: User | null;
|
|
27
175
|
/** Set the current user */
|
|
@@ -29,9 +177,9 @@ interface ScaleMuleContextValue {
|
|
|
29
177
|
/** Whether the SDK is initializing */
|
|
30
178
|
initializing: boolean;
|
|
31
179
|
/** Last error */
|
|
32
|
-
error: ApiError | null;
|
|
180
|
+
error: ApiError$1 | null;
|
|
33
181
|
/** Set error */
|
|
34
|
-
setError: (error: ApiError | null) => void;
|
|
182
|
+
setError: (error: ApiError$1 | null) => void;
|
|
35
183
|
/** Analytics proxy URL (when set, SDK sends events here instead of ScaleMule) */
|
|
36
184
|
analyticsProxyUrl?: string;
|
|
37
185
|
/** Auth proxy URL (when set, auth operations route through this proxy) */
|
|
@@ -56,11 +204,27 @@ interface ScaleMuleProviderProps extends ScaleMuleConfig {
|
|
|
56
204
|
/** Called when user logs out */
|
|
57
205
|
onLogout?: () => void;
|
|
58
206
|
/** Called on authentication error */
|
|
59
|
-
onAuthError?: (error: ApiError) => void;
|
|
207
|
+
onAuthError?: (error: ApiError$1) => void;
|
|
60
208
|
/** Server-evaluated flag values to bootstrap the client (eliminates loading flash) */
|
|
61
209
|
bootstrapFlags?: Record<string, unknown>;
|
|
210
|
+
/**
|
|
211
|
+
* Default media-pipeline policy applied to `useMedia()` calls when no
|
|
212
|
+
* per-call `policy` override is given. Five modes — see
|
|
213
|
+
* `docs/MEDIA-UPLOADS.md` and the {@link import('./hooks/useMedia').MediaPolicy} type.
|
|
214
|
+
*
|
|
215
|
+
* The platform stores the per-app policy in
|
|
216
|
+
* `application_storage_settings.media_policy` (Phase 4 / P3, live in
|
|
217
|
+
* prod). That endpoint is `MemberOnly` admin-auth, so end-user-context
|
|
218
|
+
* provider can't fetch it directly — apps that want policy-driven
|
|
219
|
+
* defaults should declare the value here, mirroring whatever the
|
|
220
|
+
* platform admin set.
|
|
221
|
+
*
|
|
222
|
+
* Default: undefined → `useMedia()` falls back to its built-in
|
|
223
|
+
* `safe_visible` default.
|
|
224
|
+
*/
|
|
225
|
+
mediaPolicy?: MediaPolicy;
|
|
62
226
|
}
|
|
63
|
-
declare function ScaleMuleProvider({ apiKey, applicationId, environment, gatewayUrl, debug, storage, analyticsProxyUrl, authProxyUrl, publishableKey, enableAccountSwitcher, accountSwitcherPrivacy, children, onLogin, onLogout, onAuthError, bootstrapFlags, }: ScaleMuleProviderProps): react_jsx_runtime.JSX.Element;
|
|
227
|
+
declare function ScaleMuleProvider({ apiKey, applicationId, environment, gatewayUrl, debug, storage, analyticsProxyUrl, authProxyUrl, publishableKey, enableAccountSwitcher, accountSwitcherPrivacy, children, onLogin, onLogout, onAuthError, bootstrapFlags, mediaPolicy, }: ScaleMuleProviderProps): react_jsx_runtime.JSX.Element;
|
|
64
228
|
declare function useScaleMule(): ScaleMuleContextValue;
|
|
65
229
|
declare function useScaleMuleClient(): ScaleMuleClient;
|
|
66
230
|
declare function useMoneyClient(): MoneyClient;
|
|
@@ -158,148 +322,6 @@ interface UseContentOptions {
|
|
|
158
322
|
*/
|
|
159
323
|
declare function useContent(options?: UseContentOptions): UseContentReturn;
|
|
160
324
|
|
|
161
|
-
/**
|
|
162
|
-
* Result of a single {@link useMedia} upload call.
|
|
163
|
-
*
|
|
164
|
-
* The shape is normalized regardless of MIME type — `optimized_url_promise`
|
|
165
|
-
* resolves on image uploads after the photo optimizer finishes; for non-image
|
|
166
|
-
* uploads it resolves to `null` immediately. (Video / audio branches will
|
|
167
|
-
* populate `hls_url_promise` in later phases — today they fall through to
|
|
168
|
-
* generic storage and that field stays `null`.)
|
|
169
|
-
*/
|
|
170
|
-
interface MediaUploadResult {
|
|
171
|
-
/** Storage file_id — store this in chat-attachment metadata. */
|
|
172
|
-
file_id: string;
|
|
173
|
-
/** Photo service id — null for non-image uploads or when register() failed. */
|
|
174
|
-
photo_id: string | null;
|
|
175
|
-
/** Short-lived signed URL to the original bytes (private uploads) or
|
|
176
|
-
* a public CDN URL (when caller passed `is_public: true`). */
|
|
177
|
-
original_view_url: string | null;
|
|
178
|
-
/** Resolves once the photo optimizer finishes. `null` for non-image
|
|
179
|
-
* MIME types or when register() failed. */
|
|
180
|
-
optimized_url_promise: Promise<string | null>;
|
|
181
|
-
/** Resolves once the video transcoder finishes (Phase 2 / S5b). `null` today. */
|
|
182
|
-
hls_url_promise: Promise<string | null>;
|
|
183
|
-
/** The file's MIME type — preserved from the input File / Blob. */
|
|
184
|
-
mime_type: string;
|
|
185
|
-
/** Whether the resulting storage object is public-readable. */
|
|
186
|
-
is_public: boolean;
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Per-app media-pipeline policy. Drives release-gating + processing
|
|
190
|
-
* behavior. **Orthogonal to `is_public`.** See
|
|
191
|
-
* `docs/MEDIA-UPLOADS.md` and ADR-2026-04-26 for the full taxonomy.
|
|
192
|
-
*
|
|
193
|
-
* Today's behavior (Phase 4 v1):
|
|
194
|
-
* - `fast_trusted` / `safe_visible` (default): upload promise resolves
|
|
195
|
-
* as soon as the file is uploaded + registered. The post-processing
|
|
196
|
-
* (scan, optimize, transcode) runs async; callers can observe via
|
|
197
|
-
* `useFileStatus`.
|
|
198
|
-
* - `safe_public` / `moderated`: upload promise *waits* for the
|
|
199
|
-
* optimized image variant (image MIME) or HLS playlist (video MIME)
|
|
200
|
-
* to become ready before resolving. Acts as the release-gate for
|
|
201
|
-
* UGC-style apps that should not publish raw bytes.
|
|
202
|
-
* - `compliance`: today behaves as `safe_public`; Phase 4+ adds the
|
|
203
|
-
* audit-log + signed-with-purpose URL semantics.
|
|
204
|
-
*/
|
|
205
|
-
type MediaPolicy = 'fast_trusted' | 'safe_visible' | 'safe_public' | 'moderated' | 'compliance';
|
|
206
|
-
interface UseMediaUploadOptions {
|
|
207
|
-
/** Whether the resulting storage object should be public-readable.
|
|
208
|
-
* Default: `false` (private). Public is opt-in for surfaces that
|
|
209
|
-
* genuinely need it (avatars, public listings). Chat / DM uploads
|
|
210
|
-
* should always be private. */
|
|
211
|
-
is_public?: boolean;
|
|
212
|
-
/**
|
|
213
|
-
* Per-call media-policy override. Defaults to `safe_visible` (visible
|
|
214
|
-
* immediately at original fidelity; optimized variants swap in async).
|
|
215
|
-
* Set to `safe_public` to make the upload promise *await* the optimized
|
|
216
|
-
* variant (image) or HLS playlist (video) before resolving — useful for
|
|
217
|
-
* broadcast / UGC apps that gate publication on processing complete.
|
|
218
|
-
*
|
|
219
|
-
* The per-app default lives in `application_storage_settings.media_policy`
|
|
220
|
-
* (Phase 4 / P3, live in prod 2026-04-26). Reading the per-app default
|
|
221
|
-
* into `useMedia` defaults lands in a follow-up; today the option is
|
|
222
|
-
* caller-provided per call.
|
|
223
|
-
*/
|
|
224
|
-
policy?: MediaPolicy;
|
|
225
|
-
/** Display filename (sanitized server-side). */
|
|
226
|
-
filename?: string;
|
|
227
|
-
/** Custom metadata attached to the file. */
|
|
228
|
-
metadata?: Record<string, unknown>;
|
|
229
|
-
/** Upload progress callback (0-100). */
|
|
230
|
-
onProgress?: (percent: number) => void;
|
|
231
|
-
/** AbortSignal for cancellation. */
|
|
232
|
-
signal?: AbortSignal;
|
|
233
|
-
/** Force a non-photo path even for image MIME types — useful for
|
|
234
|
-
* generic file uploads where you don't want the photo optimizer
|
|
235
|
-
* to register the file. Default: `false`. */
|
|
236
|
-
skipPhotoRegister?: boolean;
|
|
237
|
-
}
|
|
238
|
-
interface UseMediaReturn {
|
|
239
|
-
/** Upload a file. MIME-aware: images go through photo register +
|
|
240
|
-
* optimization; everything else goes through generic storage. */
|
|
241
|
-
upload: (file: File | Blob, options?: UseMediaUploadOptions) => Promise<MediaUploadResult>;
|
|
242
|
-
/** Cancel an upload by its `file_id`. Deletes the storage object so
|
|
243
|
-
* it doesn't orphan in S3 — useful when a chat composer accepts a
|
|
244
|
-
* file but the user removes it before sending. Idempotent. */
|
|
245
|
-
cancelUpload: (fileId: string) => Promise<void>;
|
|
246
|
-
/** Last error from `upload` or `cancelUpload`. */
|
|
247
|
-
error: ApiError$1 | null;
|
|
248
|
-
/** True while an upload is in progress. */
|
|
249
|
-
uploading: boolean;
|
|
250
|
-
}
|
|
251
|
-
/**
|
|
252
|
-
* Opinionated, MIME-aware media upload hook.
|
|
253
|
-
*
|
|
254
|
-
* `useMedia()` is the canonical upload primitive for chat / progressive
|
|
255
|
-
* media use. It branches by MIME type:
|
|
256
|
-
* - `image/*` → `client.photo.uploadViaStorage()` — upload to storage,
|
|
257
|
-
* then register with the photo service so the on-demand transform
|
|
258
|
-
* endpoint resolves to optimized variants. The returned
|
|
259
|
-
* `optimized_url_promise` resolves once the optimizer finishes.
|
|
260
|
-
* - everything else → `client.storage.uploadPrivate()` — a private,
|
|
261
|
-
* uncompressed, fail-closed upload to generic storage.
|
|
262
|
-
*
|
|
263
|
-
* **Default visibility is `is_public: false`.** Public is opt-in per call.
|
|
264
|
-
* `useMedia()` does not expose `is_public` via app-level config — visibility
|
|
265
|
-
* is always an explicit per-call surface choice.
|
|
266
|
-
*
|
|
267
|
-
* Compared to `useContent()`:
|
|
268
|
-
* - `useContent()` is a thin wrapper over generic storage and does not
|
|
269
|
-
* register photos / videos with their typed services. Use it for plain
|
|
270
|
-
* file uploads where you don't need optimization or transcoding.
|
|
271
|
-
* - `useMedia()` defaults to private + no compression, integrates with the
|
|
272
|
-
* typed media services automatically, and is the right primitive for
|
|
273
|
-
* anything chat- or media-shaped.
|
|
274
|
-
*
|
|
275
|
-
* @example
|
|
276
|
-
* ```tsx
|
|
277
|
-
* 'use client';
|
|
278
|
-
*
|
|
279
|
-
* import { useMedia, ScaleMuleMedia } from '@scalemule/nextjs';
|
|
280
|
-
*
|
|
281
|
-
* function ChatComposer({ onAttach }) {
|
|
282
|
-
* const { upload, uploading } = useMedia();
|
|
283
|
-
*
|
|
284
|
-
* async function handlePick(file: File) {
|
|
285
|
-
* const result = await upload(file);
|
|
286
|
-
* onAttach({
|
|
287
|
-
* file_id: result.file_id,
|
|
288
|
-
* mime_type: result.mime_type,
|
|
289
|
-
* optimized_url_promise: result.optimized_url_promise,
|
|
290
|
-
* });
|
|
291
|
-
* }
|
|
292
|
-
*
|
|
293
|
-
* return <input type="file" disabled={uploading}
|
|
294
|
-
* onChange={(e) => e.target.files?.[0] && handlePick(e.target.files[0])} />;
|
|
295
|
-
* }
|
|
296
|
-
* ```
|
|
297
|
-
*
|
|
298
|
-
* See `docs/MEDIA-UPLOADS.md` in the platform repo for the decision
|
|
299
|
-
* tree and the full anti-patterns list.
|
|
300
|
-
*/
|
|
301
|
-
declare function useMedia(): UseMediaReturn;
|
|
302
|
-
|
|
303
325
|
interface UseFileStatusOptions {
|
|
304
326
|
/** Storage file_id to read status for. */
|
|
305
327
|
fileId: string | null | undefined;
|
|
@@ -326,7 +348,7 @@ interface UseFileStatusReturn {
|
|
|
326
348
|
/** True while a fetch is in flight. */
|
|
327
349
|
loading: boolean;
|
|
328
350
|
/** Last error, or null. */
|
|
329
|
-
error: ApiError
|
|
351
|
+
error: ApiError | null;
|
|
330
352
|
/**
|
|
331
353
|
* Convenience: scan is clean. For images/videos, this means the file
|
|
332
354
|
* is *safe to render*; the optimized / HLS variants may still be
|
|
@@ -586,7 +608,7 @@ interface UseFeatureFlagsOptions {
|
|
|
586
608
|
interface UseFeatureFlagsReturn {
|
|
587
609
|
flags: Record<string, FeatureFlagEvaluation>;
|
|
588
610
|
loading: boolean;
|
|
589
|
-
error: ApiError | null;
|
|
611
|
+
error: ApiError$1 | null;
|
|
590
612
|
refresh: () => Promise<void>;
|
|
591
613
|
isEnabled: (flagKey: string, fallback?: boolean) => boolean;
|
|
592
614
|
getFlag: <T = unknown>(flagKey: string, fallback?: T) => T;
|
|
@@ -613,7 +635,7 @@ interface UsePushNotificationsReturn {
|
|
|
613
635
|
/** Whether an operation is in progress */
|
|
614
636
|
isLoading: boolean;
|
|
615
637
|
/** Last error */
|
|
616
|
-
error: ApiError | null;
|
|
638
|
+
error: ApiError$1 | null;
|
|
617
639
|
/** Request permission and subscribe to push notifications */
|
|
618
640
|
subscribe: () => Promise<void>;
|
|
619
641
|
/** Unsubscribe from push notifications */
|
|
@@ -714,7 +736,7 @@ interface UseFeedbackResult {
|
|
|
714
736
|
/** End-user's own feedback items for the current tenant. Empty when not signed in. */
|
|
715
737
|
items: FeedbackItem[];
|
|
716
738
|
loading: boolean;
|
|
717
|
-
error: ApiError | null;
|
|
739
|
+
error: ApiError$1 | null;
|
|
718
740
|
/** Submit a new feedback item. Returns the persisted item on success. */
|
|
719
741
|
submit: (input: FeedbackItemInput) => Promise<FeedbackItem>;
|
|
720
742
|
/** Re-fetch the list. */
|
|
@@ -926,4 +948,4 @@ declare function createSafeLogger(prefix: string): {
|
|
|
926
948
|
error: (message: string, data?: unknown) => void;
|
|
927
949
|
};
|
|
928
950
|
|
|
929
|
-
export { ApiError, 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, 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, useAuth, useBilling, useContent, useFeatureFlags, useFeedback, useFileStatus, useMedia, useMoney, useMoneyClient, usePushNotifications, useRealtime, useScaleMule, useScaleMuleClient, useShare, useUser, validateForm, validators };
|
|
951
|
+
export { ApiError$1 as ApiError, 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, 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, useAuth, useBilling, useContent, useFeatureFlags, useFeedback, useFileStatus, useMedia, useMoney, useMoneyClient, usePushNotifications, useRealtime, useScaleMule, useScaleMuleClient, useShare, useUser, validateForm, validators };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,156 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ApiError, RealtimeService, StorageService, PhotoService, VideoService, FileStatus } from '@scalemule/sdk';
|
|
2
3
|
import * as React from 'react';
|
|
3
4
|
import { ReactNode, ReactElement } from 'react';
|
|
4
5
|
import { MoneyClient } from '@scalemule/money';
|
|
5
6
|
export { MoneyClient, MoneyClientConfig, createMoneyClient } from '@scalemule/money';
|
|
6
|
-
import { RealtimeService, StorageService, PhotoService, VideoService, ApiError as ApiError$1, FileStatus } from '@scalemule/sdk';
|
|
7
7
|
import { ScaleMuleClient } from './client.js';
|
|
8
8
|
export { ClientConfig, RequestOptions, createClient } from './client.js';
|
|
9
|
-
import { S as ScaleMuleConfig, U as User, L as LoginResponse, A as ApiError, a as UseAuthReturn, b as UseBillingReturn, c as ListFilesParams, d as UseContentReturn, e as UseUserReturn, f as UseAnalyticsOptions, g as UseAnalyticsReturn } from './index-BIIUrnPr.js';
|
|
9
|
+
import { S as ScaleMuleConfig, U as User, L as LoginResponse, A as ApiError$1, a as UseAuthReturn, b as UseBillingReturn, c as ListFilesParams, d as UseContentReturn, e as UseUserReturn, f as UseAnalyticsOptions, g as UseAnalyticsReturn } from './index-BIIUrnPr.js';
|
|
10
10
|
export { h as AccountBalance, i as AnalyticsEvent, j as ApiResponse, B as BatchTrackRequest, k as BillingPayment, l as BillingPayout, m as BillingRefund, n as BillingTransaction, C as ChangeEmailRequest, o as ChangePasswordRequest, p as ClientContext, q as ConnectedAccount, D as DeviceFingerprint, r as DeviceInfo, E as EnhancedAnalyticsEvent, F as ForgotPasswordRequest, K as KnownAccountInfo, s as LinkedAccount, t as ListFilesResponse, u as LoginDeviceInfo, v as LoginRequest, w as LoginResponseWithMFA, x as LoginRiskInfo, M as MFAChallengeResponse, y as MFAMethod, z as MFASMSSetupResponse, G as MFASetupRequest, H as MFAStatus, I as MFATOTPSetupResponse, J as MFAVerifyRequest, O as OAuthCallbackRequest, N as OAuthCallbackResponse, P as OAuthConfig, Q as OAuthProvider, R as OAuthStartResponse, T as PageViewData, V as PayoutSchedule, W as PhoneLoginRequest, X as PhoneSendCodeRequest, Y as PhoneVerifyRequest, Z as Profile, _ as RefreshResponse, $ as RegisterRequest, a0 as ResetPasswordRequest, a1 as ScaleMuleApiError, a2 as ScaleMuleEnvironment, a3 as Session, a4 as SignedUploadCompleteRequest, a5 as SignedUploadRequest, a6 as SignedUploadResponse, a7 as SignedUploadUrl, a8 as StorageAdapter, a9 as StorageFile, aa as TrackEventResponse, ab as TransactionSummary, ac as UTMParams, ad as UpdateProfileRequest, ae as UploadOptions, af as UploadResponse, ag as VerifyEmailRequest } from './index-BIIUrnPr.js';
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Result of a single {@link useMedia} upload call.
|
|
14
|
+
*
|
|
15
|
+
* The shape is normalized regardless of MIME type — `optimized_url_promise`
|
|
16
|
+
* resolves on image uploads after the photo optimizer finishes; for non-image
|
|
17
|
+
* uploads it resolves to `null` immediately. (Video / audio branches will
|
|
18
|
+
* populate `hls_url_promise` in later phases — today they fall through to
|
|
19
|
+
* generic storage and that field stays `null`.)
|
|
20
|
+
*/
|
|
21
|
+
interface MediaUploadResult {
|
|
22
|
+
/** Storage file_id — store this in chat-attachment metadata. */
|
|
23
|
+
file_id: string;
|
|
24
|
+
/** Photo service id — null for non-image uploads or when register() failed. */
|
|
25
|
+
photo_id: string | null;
|
|
26
|
+
/** Short-lived signed URL to the original bytes (private uploads) or
|
|
27
|
+
* a public CDN URL (when caller passed `is_public: true`). */
|
|
28
|
+
original_view_url: string | null;
|
|
29
|
+
/** Resolves once the photo optimizer finishes. `null` for non-image
|
|
30
|
+
* MIME types or when register() failed. */
|
|
31
|
+
optimized_url_promise: Promise<string | null>;
|
|
32
|
+
/** Resolves once the video transcoder finishes (Phase 2 / S5b). `null` today. */
|
|
33
|
+
hls_url_promise: Promise<string | null>;
|
|
34
|
+
/** The file's MIME type — preserved from the input File / Blob. */
|
|
35
|
+
mime_type: string;
|
|
36
|
+
/** Whether the resulting storage object is public-readable. */
|
|
37
|
+
is_public: boolean;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Per-app media-pipeline policy. Drives release-gating + processing
|
|
41
|
+
* behavior. **Orthogonal to `is_public`.** See
|
|
42
|
+
* `docs/MEDIA-UPLOADS.md` and ADR-2026-04-26 for the full taxonomy.
|
|
43
|
+
*
|
|
44
|
+
* Today's behavior (Phase 4 v1):
|
|
45
|
+
* - `fast_trusted` / `safe_visible` (default): upload promise resolves
|
|
46
|
+
* as soon as the file is uploaded + registered. The post-processing
|
|
47
|
+
* (scan, optimize, transcode) runs async; callers can observe via
|
|
48
|
+
* `useFileStatus`.
|
|
49
|
+
* - `safe_public` / `moderated`: upload promise *waits* for the
|
|
50
|
+
* optimized image variant (image MIME) or HLS playlist (video MIME)
|
|
51
|
+
* to become ready before resolving. Acts as the release-gate for
|
|
52
|
+
* UGC-style apps that should not publish raw bytes.
|
|
53
|
+
* - `compliance`: today behaves as `safe_public`; Phase 4+ adds the
|
|
54
|
+
* audit-log + signed-with-purpose URL semantics.
|
|
55
|
+
*/
|
|
56
|
+
type MediaPolicy = 'fast_trusted' | 'safe_visible' | 'safe_public' | 'moderated' | 'compliance';
|
|
57
|
+
interface UseMediaUploadOptions {
|
|
58
|
+
/** Whether the resulting storage object should be public-readable.
|
|
59
|
+
* Default: `false` (private). Public is opt-in for surfaces that
|
|
60
|
+
* genuinely need it (avatars, public listings). Chat / DM uploads
|
|
61
|
+
* should always be private. */
|
|
62
|
+
is_public?: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Per-call media-policy override. Defaults to `safe_visible` (visible
|
|
65
|
+
* immediately at original fidelity; optimized variants swap in async).
|
|
66
|
+
* Set to `safe_public` to make the upload promise *await* the optimized
|
|
67
|
+
* variant (image) or HLS playlist (video) before resolving — useful for
|
|
68
|
+
* broadcast / UGC apps that gate publication on processing complete.
|
|
69
|
+
*
|
|
70
|
+
* The per-app default lives in `application_storage_settings.media_policy`
|
|
71
|
+
* (Phase 4 / P3, live in prod 2026-04-26). Reading the per-app default
|
|
72
|
+
* into `useMedia` defaults lands in a follow-up; today the option is
|
|
73
|
+
* caller-provided per call.
|
|
74
|
+
*/
|
|
75
|
+
policy?: MediaPolicy;
|
|
76
|
+
/** Display filename (sanitized server-side). */
|
|
77
|
+
filename?: string;
|
|
78
|
+
/** Custom metadata attached to the file. */
|
|
79
|
+
metadata?: Record<string, unknown>;
|
|
80
|
+
/** Upload progress callback (0-100). */
|
|
81
|
+
onProgress?: (percent: number) => void;
|
|
82
|
+
/** AbortSignal for cancellation. */
|
|
83
|
+
signal?: AbortSignal;
|
|
84
|
+
/** Force a non-photo path even for image MIME types — useful for
|
|
85
|
+
* generic file uploads where you don't want the photo optimizer
|
|
86
|
+
* to register the file. Default: `false`. */
|
|
87
|
+
skipPhotoRegister?: boolean;
|
|
88
|
+
}
|
|
89
|
+
interface UseMediaReturn {
|
|
90
|
+
/** Upload a file. MIME-aware: images go through photo register +
|
|
91
|
+
* optimization; everything else goes through generic storage. */
|
|
92
|
+
upload: (file: File | Blob, options?: UseMediaUploadOptions) => Promise<MediaUploadResult>;
|
|
93
|
+
/** Cancel an upload by its `file_id`. Deletes the storage object so
|
|
94
|
+
* it doesn't orphan in S3 — useful when a chat composer accepts a
|
|
95
|
+
* file but the user removes it before sending. Idempotent. */
|
|
96
|
+
cancelUpload: (fileId: string) => Promise<void>;
|
|
97
|
+
/** Last error from `upload` or `cancelUpload`. */
|
|
98
|
+
error: ApiError | null;
|
|
99
|
+
/** True while an upload is in progress. */
|
|
100
|
+
uploading: boolean;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Opinionated, MIME-aware media upload hook.
|
|
104
|
+
*
|
|
105
|
+
* `useMedia()` is the canonical upload primitive for chat / progressive
|
|
106
|
+
* media use. It branches by MIME type:
|
|
107
|
+
* - `image/*` → `client.photo.uploadViaStorage()` — upload to storage,
|
|
108
|
+
* then register with the photo service so the on-demand transform
|
|
109
|
+
* endpoint resolves to optimized variants. The returned
|
|
110
|
+
* `optimized_url_promise` resolves once the optimizer finishes.
|
|
111
|
+
* - everything else → `client.storage.uploadPrivate()` — a private,
|
|
112
|
+
* uncompressed, fail-closed upload to generic storage.
|
|
113
|
+
*
|
|
114
|
+
* **Default visibility is `is_public: false`.** Public is opt-in per call.
|
|
115
|
+
* `useMedia()` does not expose `is_public` via app-level config — visibility
|
|
116
|
+
* is always an explicit per-call surface choice.
|
|
117
|
+
*
|
|
118
|
+
* Compared to `useContent()`:
|
|
119
|
+
* - `useContent()` is a thin wrapper over generic storage and does not
|
|
120
|
+
* register photos / videos with their typed services. Use it for plain
|
|
121
|
+
* file uploads where you don't need optimization or transcoding.
|
|
122
|
+
* - `useMedia()` defaults to private + no compression, integrates with the
|
|
123
|
+
* typed media services automatically, and is the right primitive for
|
|
124
|
+
* anything chat- or media-shaped.
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```tsx
|
|
128
|
+
* 'use client';
|
|
129
|
+
*
|
|
130
|
+
* import { useMedia, ScaleMuleMedia } from '@scalemule/nextjs';
|
|
131
|
+
*
|
|
132
|
+
* function ChatComposer({ onAttach }) {
|
|
133
|
+
* const { upload, uploading } = useMedia();
|
|
134
|
+
*
|
|
135
|
+
* async function handlePick(file: File) {
|
|
136
|
+
* const result = await upload(file);
|
|
137
|
+
* onAttach({
|
|
138
|
+
* file_id: result.file_id,
|
|
139
|
+
* mime_type: result.mime_type,
|
|
140
|
+
* optimized_url_promise: result.optimized_url_promise,
|
|
141
|
+
* });
|
|
142
|
+
* }
|
|
143
|
+
*
|
|
144
|
+
* return <input type="file" disabled={uploading}
|
|
145
|
+
* onChange={(e) => e.target.files?.[0] && handlePick(e.target.files[0])} />;
|
|
146
|
+
* }
|
|
147
|
+
* ```
|
|
148
|
+
*
|
|
149
|
+
* See `docs/MEDIA-UPLOADS.md` in the platform repo for the decision
|
|
150
|
+
* tree and the full anti-patterns list.
|
|
151
|
+
*/
|
|
152
|
+
declare function useMedia(): UseMediaReturn;
|
|
153
|
+
|
|
12
154
|
interface ScaleMuleContextValue {
|
|
13
155
|
/** The API client instance */
|
|
14
156
|
client: ScaleMuleClient;
|
|
@@ -22,6 +164,12 @@ interface ScaleMuleContextValue {
|
|
|
22
164
|
photo: PhotoService;
|
|
23
165
|
/** Base SDK video service — exposed for `useMedia()` and `video.uploadViaStorage()` */
|
|
24
166
|
video: VideoService;
|
|
167
|
+
/**
|
|
168
|
+
* Default media policy for `useMedia()` calls. Set via
|
|
169
|
+
* `<ScaleMuleProvider mediaPolicy="…">`; per-call overrides win.
|
|
170
|
+
* Undefined falls back to `useMedia()`'s built-in `safe_visible` default.
|
|
171
|
+
*/
|
|
172
|
+
mediaPolicy?: MediaPolicy;
|
|
25
173
|
/** Current authenticated user */
|
|
26
174
|
user: User | null;
|
|
27
175
|
/** Set the current user */
|
|
@@ -29,9 +177,9 @@ interface ScaleMuleContextValue {
|
|
|
29
177
|
/** Whether the SDK is initializing */
|
|
30
178
|
initializing: boolean;
|
|
31
179
|
/** Last error */
|
|
32
|
-
error: ApiError | null;
|
|
180
|
+
error: ApiError$1 | null;
|
|
33
181
|
/** Set error */
|
|
34
|
-
setError: (error: ApiError | null) => void;
|
|
182
|
+
setError: (error: ApiError$1 | null) => void;
|
|
35
183
|
/** Analytics proxy URL (when set, SDK sends events here instead of ScaleMule) */
|
|
36
184
|
analyticsProxyUrl?: string;
|
|
37
185
|
/** Auth proxy URL (when set, auth operations route through this proxy) */
|
|
@@ -56,11 +204,27 @@ interface ScaleMuleProviderProps extends ScaleMuleConfig {
|
|
|
56
204
|
/** Called when user logs out */
|
|
57
205
|
onLogout?: () => void;
|
|
58
206
|
/** Called on authentication error */
|
|
59
|
-
onAuthError?: (error: ApiError) => void;
|
|
207
|
+
onAuthError?: (error: ApiError$1) => void;
|
|
60
208
|
/** Server-evaluated flag values to bootstrap the client (eliminates loading flash) */
|
|
61
209
|
bootstrapFlags?: Record<string, unknown>;
|
|
210
|
+
/**
|
|
211
|
+
* Default media-pipeline policy applied to `useMedia()` calls when no
|
|
212
|
+
* per-call `policy` override is given. Five modes — see
|
|
213
|
+
* `docs/MEDIA-UPLOADS.md` and the {@link import('./hooks/useMedia').MediaPolicy} type.
|
|
214
|
+
*
|
|
215
|
+
* The platform stores the per-app policy in
|
|
216
|
+
* `application_storage_settings.media_policy` (Phase 4 / P3, live in
|
|
217
|
+
* prod). That endpoint is `MemberOnly` admin-auth, so end-user-context
|
|
218
|
+
* provider can't fetch it directly — apps that want policy-driven
|
|
219
|
+
* defaults should declare the value here, mirroring whatever the
|
|
220
|
+
* platform admin set.
|
|
221
|
+
*
|
|
222
|
+
* Default: undefined → `useMedia()` falls back to its built-in
|
|
223
|
+
* `safe_visible` default.
|
|
224
|
+
*/
|
|
225
|
+
mediaPolicy?: MediaPolicy;
|
|
62
226
|
}
|
|
63
|
-
declare function ScaleMuleProvider({ apiKey, applicationId, environment, gatewayUrl, debug, storage, analyticsProxyUrl, authProxyUrl, publishableKey, enableAccountSwitcher, accountSwitcherPrivacy, children, onLogin, onLogout, onAuthError, bootstrapFlags, }: ScaleMuleProviderProps): react_jsx_runtime.JSX.Element;
|
|
227
|
+
declare function ScaleMuleProvider({ apiKey, applicationId, environment, gatewayUrl, debug, storage, analyticsProxyUrl, authProxyUrl, publishableKey, enableAccountSwitcher, accountSwitcherPrivacy, children, onLogin, onLogout, onAuthError, bootstrapFlags, mediaPolicy, }: ScaleMuleProviderProps): react_jsx_runtime.JSX.Element;
|
|
64
228
|
declare function useScaleMule(): ScaleMuleContextValue;
|
|
65
229
|
declare function useScaleMuleClient(): ScaleMuleClient;
|
|
66
230
|
declare function useMoneyClient(): MoneyClient;
|
|
@@ -158,148 +322,6 @@ interface UseContentOptions {
|
|
|
158
322
|
*/
|
|
159
323
|
declare function useContent(options?: UseContentOptions): UseContentReturn;
|
|
160
324
|
|
|
161
|
-
/**
|
|
162
|
-
* Result of a single {@link useMedia} upload call.
|
|
163
|
-
*
|
|
164
|
-
* The shape is normalized regardless of MIME type — `optimized_url_promise`
|
|
165
|
-
* resolves on image uploads after the photo optimizer finishes; for non-image
|
|
166
|
-
* uploads it resolves to `null` immediately. (Video / audio branches will
|
|
167
|
-
* populate `hls_url_promise` in later phases — today they fall through to
|
|
168
|
-
* generic storage and that field stays `null`.)
|
|
169
|
-
*/
|
|
170
|
-
interface MediaUploadResult {
|
|
171
|
-
/** Storage file_id — store this in chat-attachment metadata. */
|
|
172
|
-
file_id: string;
|
|
173
|
-
/** Photo service id — null for non-image uploads or when register() failed. */
|
|
174
|
-
photo_id: string | null;
|
|
175
|
-
/** Short-lived signed URL to the original bytes (private uploads) or
|
|
176
|
-
* a public CDN URL (when caller passed `is_public: true`). */
|
|
177
|
-
original_view_url: string | null;
|
|
178
|
-
/** Resolves once the photo optimizer finishes. `null` for non-image
|
|
179
|
-
* MIME types or when register() failed. */
|
|
180
|
-
optimized_url_promise: Promise<string | null>;
|
|
181
|
-
/** Resolves once the video transcoder finishes (Phase 2 / S5b). `null` today. */
|
|
182
|
-
hls_url_promise: Promise<string | null>;
|
|
183
|
-
/** The file's MIME type — preserved from the input File / Blob. */
|
|
184
|
-
mime_type: string;
|
|
185
|
-
/** Whether the resulting storage object is public-readable. */
|
|
186
|
-
is_public: boolean;
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Per-app media-pipeline policy. Drives release-gating + processing
|
|
190
|
-
* behavior. **Orthogonal to `is_public`.** See
|
|
191
|
-
* `docs/MEDIA-UPLOADS.md` and ADR-2026-04-26 for the full taxonomy.
|
|
192
|
-
*
|
|
193
|
-
* Today's behavior (Phase 4 v1):
|
|
194
|
-
* - `fast_trusted` / `safe_visible` (default): upload promise resolves
|
|
195
|
-
* as soon as the file is uploaded + registered. The post-processing
|
|
196
|
-
* (scan, optimize, transcode) runs async; callers can observe via
|
|
197
|
-
* `useFileStatus`.
|
|
198
|
-
* - `safe_public` / `moderated`: upload promise *waits* for the
|
|
199
|
-
* optimized image variant (image MIME) or HLS playlist (video MIME)
|
|
200
|
-
* to become ready before resolving. Acts as the release-gate for
|
|
201
|
-
* UGC-style apps that should not publish raw bytes.
|
|
202
|
-
* - `compliance`: today behaves as `safe_public`; Phase 4+ adds the
|
|
203
|
-
* audit-log + signed-with-purpose URL semantics.
|
|
204
|
-
*/
|
|
205
|
-
type MediaPolicy = 'fast_trusted' | 'safe_visible' | 'safe_public' | 'moderated' | 'compliance';
|
|
206
|
-
interface UseMediaUploadOptions {
|
|
207
|
-
/** Whether the resulting storage object should be public-readable.
|
|
208
|
-
* Default: `false` (private). Public is opt-in for surfaces that
|
|
209
|
-
* genuinely need it (avatars, public listings). Chat / DM uploads
|
|
210
|
-
* should always be private. */
|
|
211
|
-
is_public?: boolean;
|
|
212
|
-
/**
|
|
213
|
-
* Per-call media-policy override. Defaults to `safe_visible` (visible
|
|
214
|
-
* immediately at original fidelity; optimized variants swap in async).
|
|
215
|
-
* Set to `safe_public` to make the upload promise *await* the optimized
|
|
216
|
-
* variant (image) or HLS playlist (video) before resolving — useful for
|
|
217
|
-
* broadcast / UGC apps that gate publication on processing complete.
|
|
218
|
-
*
|
|
219
|
-
* The per-app default lives in `application_storage_settings.media_policy`
|
|
220
|
-
* (Phase 4 / P3, live in prod 2026-04-26). Reading the per-app default
|
|
221
|
-
* into `useMedia` defaults lands in a follow-up; today the option is
|
|
222
|
-
* caller-provided per call.
|
|
223
|
-
*/
|
|
224
|
-
policy?: MediaPolicy;
|
|
225
|
-
/** Display filename (sanitized server-side). */
|
|
226
|
-
filename?: string;
|
|
227
|
-
/** Custom metadata attached to the file. */
|
|
228
|
-
metadata?: Record<string, unknown>;
|
|
229
|
-
/** Upload progress callback (0-100). */
|
|
230
|
-
onProgress?: (percent: number) => void;
|
|
231
|
-
/** AbortSignal for cancellation. */
|
|
232
|
-
signal?: AbortSignal;
|
|
233
|
-
/** Force a non-photo path even for image MIME types — useful for
|
|
234
|
-
* generic file uploads where you don't want the photo optimizer
|
|
235
|
-
* to register the file. Default: `false`. */
|
|
236
|
-
skipPhotoRegister?: boolean;
|
|
237
|
-
}
|
|
238
|
-
interface UseMediaReturn {
|
|
239
|
-
/** Upload a file. MIME-aware: images go through photo register +
|
|
240
|
-
* optimization; everything else goes through generic storage. */
|
|
241
|
-
upload: (file: File | Blob, options?: UseMediaUploadOptions) => Promise<MediaUploadResult>;
|
|
242
|
-
/** Cancel an upload by its `file_id`. Deletes the storage object so
|
|
243
|
-
* it doesn't orphan in S3 — useful when a chat composer accepts a
|
|
244
|
-
* file but the user removes it before sending. Idempotent. */
|
|
245
|
-
cancelUpload: (fileId: string) => Promise<void>;
|
|
246
|
-
/** Last error from `upload` or `cancelUpload`. */
|
|
247
|
-
error: ApiError$1 | null;
|
|
248
|
-
/** True while an upload is in progress. */
|
|
249
|
-
uploading: boolean;
|
|
250
|
-
}
|
|
251
|
-
/**
|
|
252
|
-
* Opinionated, MIME-aware media upload hook.
|
|
253
|
-
*
|
|
254
|
-
* `useMedia()` is the canonical upload primitive for chat / progressive
|
|
255
|
-
* media use. It branches by MIME type:
|
|
256
|
-
* - `image/*` → `client.photo.uploadViaStorage()` — upload to storage,
|
|
257
|
-
* then register with the photo service so the on-demand transform
|
|
258
|
-
* endpoint resolves to optimized variants. The returned
|
|
259
|
-
* `optimized_url_promise` resolves once the optimizer finishes.
|
|
260
|
-
* - everything else → `client.storage.uploadPrivate()` — a private,
|
|
261
|
-
* uncompressed, fail-closed upload to generic storage.
|
|
262
|
-
*
|
|
263
|
-
* **Default visibility is `is_public: false`.** Public is opt-in per call.
|
|
264
|
-
* `useMedia()` does not expose `is_public` via app-level config — visibility
|
|
265
|
-
* is always an explicit per-call surface choice.
|
|
266
|
-
*
|
|
267
|
-
* Compared to `useContent()`:
|
|
268
|
-
* - `useContent()` is a thin wrapper over generic storage and does not
|
|
269
|
-
* register photos / videos with their typed services. Use it for plain
|
|
270
|
-
* file uploads where you don't need optimization or transcoding.
|
|
271
|
-
* - `useMedia()` defaults to private + no compression, integrates with the
|
|
272
|
-
* typed media services automatically, and is the right primitive for
|
|
273
|
-
* anything chat- or media-shaped.
|
|
274
|
-
*
|
|
275
|
-
* @example
|
|
276
|
-
* ```tsx
|
|
277
|
-
* 'use client';
|
|
278
|
-
*
|
|
279
|
-
* import { useMedia, ScaleMuleMedia } from '@scalemule/nextjs';
|
|
280
|
-
*
|
|
281
|
-
* function ChatComposer({ onAttach }) {
|
|
282
|
-
* const { upload, uploading } = useMedia();
|
|
283
|
-
*
|
|
284
|
-
* async function handlePick(file: File) {
|
|
285
|
-
* const result = await upload(file);
|
|
286
|
-
* onAttach({
|
|
287
|
-
* file_id: result.file_id,
|
|
288
|
-
* mime_type: result.mime_type,
|
|
289
|
-
* optimized_url_promise: result.optimized_url_promise,
|
|
290
|
-
* });
|
|
291
|
-
* }
|
|
292
|
-
*
|
|
293
|
-
* return <input type="file" disabled={uploading}
|
|
294
|
-
* onChange={(e) => e.target.files?.[0] && handlePick(e.target.files[0])} />;
|
|
295
|
-
* }
|
|
296
|
-
* ```
|
|
297
|
-
*
|
|
298
|
-
* See `docs/MEDIA-UPLOADS.md` in the platform repo for the decision
|
|
299
|
-
* tree and the full anti-patterns list.
|
|
300
|
-
*/
|
|
301
|
-
declare function useMedia(): UseMediaReturn;
|
|
302
|
-
|
|
303
325
|
interface UseFileStatusOptions {
|
|
304
326
|
/** Storage file_id to read status for. */
|
|
305
327
|
fileId: string | null | undefined;
|
|
@@ -326,7 +348,7 @@ interface UseFileStatusReturn {
|
|
|
326
348
|
/** True while a fetch is in flight. */
|
|
327
349
|
loading: boolean;
|
|
328
350
|
/** Last error, or null. */
|
|
329
|
-
error: ApiError
|
|
351
|
+
error: ApiError | null;
|
|
330
352
|
/**
|
|
331
353
|
* Convenience: scan is clean. For images/videos, this means the file
|
|
332
354
|
* is *safe to render*; the optimized / HLS variants may still be
|
|
@@ -586,7 +608,7 @@ interface UseFeatureFlagsOptions {
|
|
|
586
608
|
interface UseFeatureFlagsReturn {
|
|
587
609
|
flags: Record<string, FeatureFlagEvaluation>;
|
|
588
610
|
loading: boolean;
|
|
589
|
-
error: ApiError | null;
|
|
611
|
+
error: ApiError$1 | null;
|
|
590
612
|
refresh: () => Promise<void>;
|
|
591
613
|
isEnabled: (flagKey: string, fallback?: boolean) => boolean;
|
|
592
614
|
getFlag: <T = unknown>(flagKey: string, fallback?: T) => T;
|
|
@@ -613,7 +635,7 @@ interface UsePushNotificationsReturn {
|
|
|
613
635
|
/** Whether an operation is in progress */
|
|
614
636
|
isLoading: boolean;
|
|
615
637
|
/** Last error */
|
|
616
|
-
error: ApiError | null;
|
|
638
|
+
error: ApiError$1 | null;
|
|
617
639
|
/** Request permission and subscribe to push notifications */
|
|
618
640
|
subscribe: () => Promise<void>;
|
|
619
641
|
/** Unsubscribe from push notifications */
|
|
@@ -714,7 +736,7 @@ interface UseFeedbackResult {
|
|
|
714
736
|
/** End-user's own feedback items for the current tenant. Empty when not signed in. */
|
|
715
737
|
items: FeedbackItem[];
|
|
716
738
|
loading: boolean;
|
|
717
|
-
error: ApiError | null;
|
|
739
|
+
error: ApiError$1 | null;
|
|
718
740
|
/** Submit a new feedback item. Returns the persisted item on success. */
|
|
719
741
|
submit: (input: FeedbackItemInput) => Promise<FeedbackItem>;
|
|
720
742
|
/** Re-fetch the list. */
|
|
@@ -926,4 +948,4 @@ declare function createSafeLogger(prefix: string): {
|
|
|
926
948
|
error: (message: string, data?: unknown) => void;
|
|
927
949
|
};
|
|
928
950
|
|
|
929
|
-
export { ApiError, 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, 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, useAuth, useBilling, useContent, useFeatureFlags, useFeedback, useFileStatus, useMedia, useMoney, useMoneyClient, usePushNotifications, useRealtime, useScaleMule, useScaleMuleClient, useShare, useUser, validateForm, validators };
|
|
951
|
+
export { ApiError$1 as ApiError, 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, 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, useAuth, useBilling, useContent, useFeatureFlags, useFeedback, useFileStatus, useMedia, useMoney, useMoneyClient, usePushNotifications, useRealtime, useScaleMule, useScaleMuleClient, useShare, useUser, validateForm, validators };
|
package/dist/index.js
CHANGED
|
@@ -7445,7 +7445,8 @@ function ScaleMuleProvider({
|
|
|
7445
7445
|
onLogin,
|
|
7446
7446
|
onLogout,
|
|
7447
7447
|
onAuthError,
|
|
7448
|
-
bootstrapFlags
|
|
7448
|
+
bootstrapFlags,
|
|
7449
|
+
mediaPolicy
|
|
7449
7450
|
}) {
|
|
7450
7451
|
const [user, setUser] = React.useState(null);
|
|
7451
7452
|
const [initializing, setInitializing] = React.useState(true);
|
|
@@ -7584,6 +7585,7 @@ function ScaleMuleProvider({
|
|
|
7584
7585
|
storage: baseClient.storage,
|
|
7585
7586
|
photo: baseClient.photo,
|
|
7586
7587
|
video: baseClient.video,
|
|
7588
|
+
mediaPolicy,
|
|
7587
7589
|
user,
|
|
7588
7590
|
setUser: handleSetUser,
|
|
7589
7591
|
initializing,
|
|
@@ -7598,7 +7600,7 @@ function ScaleMuleProvider({
|
|
|
7598
7600
|
accountSwitcherPrivacy,
|
|
7599
7601
|
bootstrapFlags
|
|
7600
7602
|
}),
|
|
7601
|
-
[client, money$1, baseClient, user, handleSetUser, initializing, error, analyticsProxyUrl, authProxyUrl, publishableKey, resolvedGatewayUrl, environment, enableAccountSwitcher, accountSwitcherPrivacy, bootstrapFlags]
|
|
7603
|
+
[client, money$1, baseClient, user, handleSetUser, initializing, error, analyticsProxyUrl, authProxyUrl, publishableKey, resolvedGatewayUrl, environment, enableAccountSwitcher, accountSwitcherPrivacy, bootstrapFlags, mediaPolicy]
|
|
7602
7604
|
);
|
|
7603
7605
|
return /* @__PURE__ */ jsxRuntime.jsx(ScaleMuleContext.Provider, { value, children });
|
|
7604
7606
|
}
|
|
@@ -8897,7 +8899,7 @@ function useContent(options = {}) {
|
|
|
8897
8899
|
);
|
|
8898
8900
|
}
|
|
8899
8901
|
function useMedia() {
|
|
8900
|
-
const { storage, photo, video } = useScaleMule();
|
|
8902
|
+
const { storage, photo, video, mediaPolicy: providerDefaultPolicy } = useScaleMule();
|
|
8901
8903
|
const [uploading, setUploading] = React.useState(false);
|
|
8902
8904
|
const [error, setError] = React.useState(null);
|
|
8903
8905
|
const upload = React.useCallback(
|
|
@@ -8906,7 +8908,7 @@ function useMedia() {
|
|
|
8906
8908
|
setError(null);
|
|
8907
8909
|
const isPublic = options?.is_public ?? false;
|
|
8908
8910
|
const mimeType = file.type || "application/octet-stream";
|
|
8909
|
-
const policy = options?.policy ?? "safe_visible";
|
|
8911
|
+
const policy = options?.policy ?? providerDefaultPolicy ?? "safe_visible";
|
|
8910
8912
|
const gateOnPipeline = policy === "safe_public" || policy === "moderated" || policy === "compliance";
|
|
8911
8913
|
const sharedOpts = {
|
|
8912
8914
|
filename: options?.filename,
|
|
@@ -8993,7 +8995,7 @@ function useMedia() {
|
|
|
8993
8995
|
setUploading(false);
|
|
8994
8996
|
}
|
|
8995
8997
|
},
|
|
8996
|
-
[storage, photo]
|
|
8998
|
+
[storage, photo, video, providerDefaultPolicy]
|
|
8997
8999
|
);
|
|
8998
9000
|
const cancelUpload = React.useCallback(
|
|
8999
9001
|
async (fileId) => {
|
package/dist/index.mjs
CHANGED
|
@@ -7425,7 +7425,8 @@ function ScaleMuleProvider({
|
|
|
7425
7425
|
onLogin,
|
|
7426
7426
|
onLogout,
|
|
7427
7427
|
onAuthError,
|
|
7428
|
-
bootstrapFlags
|
|
7428
|
+
bootstrapFlags,
|
|
7429
|
+
mediaPolicy
|
|
7429
7430
|
}) {
|
|
7430
7431
|
const [user, setUser] = useState(null);
|
|
7431
7432
|
const [initializing, setInitializing] = useState(true);
|
|
@@ -7564,6 +7565,7 @@ function ScaleMuleProvider({
|
|
|
7564
7565
|
storage: baseClient.storage,
|
|
7565
7566
|
photo: baseClient.photo,
|
|
7566
7567
|
video: baseClient.video,
|
|
7568
|
+
mediaPolicy,
|
|
7567
7569
|
user,
|
|
7568
7570
|
setUser: handleSetUser,
|
|
7569
7571
|
initializing,
|
|
@@ -7578,7 +7580,7 @@ function ScaleMuleProvider({
|
|
|
7578
7580
|
accountSwitcherPrivacy,
|
|
7579
7581
|
bootstrapFlags
|
|
7580
7582
|
}),
|
|
7581
|
-
[client, money, baseClient, user, handleSetUser, initializing, error, analyticsProxyUrl, authProxyUrl, publishableKey, resolvedGatewayUrl, environment, enableAccountSwitcher, accountSwitcherPrivacy, bootstrapFlags]
|
|
7583
|
+
[client, money, baseClient, user, handleSetUser, initializing, error, analyticsProxyUrl, authProxyUrl, publishableKey, resolvedGatewayUrl, environment, enableAccountSwitcher, accountSwitcherPrivacy, bootstrapFlags, mediaPolicy]
|
|
7582
7584
|
);
|
|
7583
7585
|
return /* @__PURE__ */ jsx(ScaleMuleContext.Provider, { value, children });
|
|
7584
7586
|
}
|
|
@@ -8877,7 +8879,7 @@ function useContent(options = {}) {
|
|
|
8877
8879
|
);
|
|
8878
8880
|
}
|
|
8879
8881
|
function useMedia() {
|
|
8880
|
-
const { storage, photo, video } = useScaleMule();
|
|
8882
|
+
const { storage, photo, video, mediaPolicy: providerDefaultPolicy } = useScaleMule();
|
|
8881
8883
|
const [uploading, setUploading] = useState(false);
|
|
8882
8884
|
const [error, setError] = useState(null);
|
|
8883
8885
|
const upload = useCallback(
|
|
@@ -8886,7 +8888,7 @@ function useMedia() {
|
|
|
8886
8888
|
setError(null);
|
|
8887
8889
|
const isPublic = options?.is_public ?? false;
|
|
8888
8890
|
const mimeType = file.type || "application/octet-stream";
|
|
8889
|
-
const policy = options?.policy ?? "safe_visible";
|
|
8891
|
+
const policy = options?.policy ?? providerDefaultPolicy ?? "safe_visible";
|
|
8890
8892
|
const gateOnPipeline = policy === "safe_public" || policy === "moderated" || policy === "compliance";
|
|
8891
8893
|
const sharedOpts = {
|
|
8892
8894
|
filename: options?.filename,
|
|
@@ -8973,7 +8975,7 @@ function useMedia() {
|
|
|
8973
8975
|
setUploading(false);
|
|
8974
8976
|
}
|
|
8975
8977
|
},
|
|
8976
|
-
[storage, photo]
|
|
8978
|
+
[storage, photo, video, providerDefaultPolicy]
|
|
8977
8979
|
);
|
|
8978
8980
|
const cancelUpload = useCallback(
|
|
8979
8981
|
async (fileId) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scalemule/nextjs",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "ScaleMule SDK for Next.js applications - authentication, storage, and user management",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -49,7 +49,8 @@
|
|
|
49
49
|
"test:watch": "vitest",
|
|
50
50
|
"type-check": "tsc --noEmit",
|
|
51
51
|
"lint": "tsc --noEmit",
|
|
52
|
-
"clean": "rm -rf dist"
|
|
52
|
+
"clean": "rm -rf dist",
|
|
53
|
+
"prepublishOnly": "node -e \"const v=require('./package.json').version; if(!/^0\\.(0|1)\\.\\d+$/.test(v)){console.error('ERR: SDK '+v+' violates patch-only policy (0.0.x or 0.1.x only). See CONTRIBUTING.md SDK versioning section.');process.exit(1)}\""
|
|
53
54
|
},
|
|
54
55
|
"dependencies": {
|
|
55
56
|
"@scalemule/money": "^0.0.1",
|