@sanvika/cloudinary 0.1.4 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +207 -56
- package/package.json +7 -3
package/dist/index.js
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
// src/cloudinaryCore.js
|
|
2
|
-
import { v2 as cloudinary } from "cloudinary";
|
|
3
|
-
|
|
4
1
|
// src/cloudinaryErrors.js
|
|
5
2
|
var CloudinaryError = class extends Error {
|
|
6
3
|
constructor(message, operation, details = {}, originalError = null) {
|
|
@@ -111,37 +108,128 @@ var TRANSFORM_PRESETS = {
|
|
|
111
108
|
responsive: { w: "auto", dpr: "auto", q: "auto", f: "auto" }
|
|
112
109
|
};
|
|
113
110
|
|
|
111
|
+
// src/gatewayClient.js
|
|
112
|
+
function isProxyMode() {
|
|
113
|
+
return Boolean(process.env.CLOUDINARY_GATEWAY_URL && process.env.CLOUDINARY_TOKEN);
|
|
114
|
+
}
|
|
115
|
+
function requireProxyEnv() {
|
|
116
|
+
const base = process.env.CLOUDINARY_GATEWAY_URL;
|
|
117
|
+
const token = process.env.CLOUDINARY_TOKEN;
|
|
118
|
+
if (!base || !token) {
|
|
119
|
+
throw new CloudinaryError(
|
|
120
|
+
"Proxy gateway env missing. Set CLOUDINARY_GATEWAY_URL and CLOUDINARY_TOKEN.",
|
|
121
|
+
"gateway_env"
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
return { base: base.replace(/\/+$/, ""), token };
|
|
125
|
+
}
|
|
126
|
+
async function handleResponse(operation, res) {
|
|
127
|
+
let body = null;
|
|
128
|
+
const text = await res.text();
|
|
129
|
+
try {
|
|
130
|
+
body = text ? JSON.parse(text) : null;
|
|
131
|
+
} catch {
|
|
132
|
+
body = { raw: text };
|
|
133
|
+
}
|
|
134
|
+
if (!res.ok) {
|
|
135
|
+
const msg = (body == null ? void 0 : body.error) || (body == null ? void 0 : body.message) || `Gateway returned ${res.status}`;
|
|
136
|
+
throw new CloudinaryError(msg, operation, { status: res.status, body });
|
|
137
|
+
}
|
|
138
|
+
return body;
|
|
139
|
+
}
|
|
140
|
+
async function gatewayPost(pathname, jsonBody) {
|
|
141
|
+
const { base, token } = requireProxyEnv();
|
|
142
|
+
const res = await fetch(`${base}${pathname}`, {
|
|
143
|
+
method: "POST",
|
|
144
|
+
headers: {
|
|
145
|
+
Authorization: `Bearer ${token}`,
|
|
146
|
+
"Content-Type": "application/json"
|
|
147
|
+
},
|
|
148
|
+
body: JSON.stringify(jsonBody || {})
|
|
149
|
+
});
|
|
150
|
+
return handleResponse(`POST ${pathname}`, res);
|
|
151
|
+
}
|
|
152
|
+
async function gatewayGet(pathname, query) {
|
|
153
|
+
const { base, token } = requireProxyEnv();
|
|
154
|
+
const qs = query ? `?${new URLSearchParams(query).toString()}` : "";
|
|
155
|
+
const res = await fetch(`${base}${pathname}${qs}`, {
|
|
156
|
+
method: "GET",
|
|
157
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
158
|
+
});
|
|
159
|
+
return handleResponse(`GET ${pathname}`, res);
|
|
160
|
+
}
|
|
161
|
+
async function gatewayUpload(bufferOrBlob, options = {}) {
|
|
162
|
+
const { base, token } = requireProxyEnv();
|
|
163
|
+
const form = new FormData();
|
|
164
|
+
let blob;
|
|
165
|
+
if (bufferOrBlob instanceof Blob) {
|
|
166
|
+
blob = bufferOrBlob;
|
|
167
|
+
} else if (Buffer.isBuffer(bufferOrBlob)) {
|
|
168
|
+
blob = new Blob([bufferOrBlob]);
|
|
169
|
+
} else if (typeof bufferOrBlob === "string") {
|
|
170
|
+
return gatewayPost("/api/v1/upload?mode=source", { source: bufferOrBlob, options });
|
|
171
|
+
} else {
|
|
172
|
+
throw new CloudinaryError("Unsupported upload input", "upload", { type: typeof bufferOrBlob });
|
|
173
|
+
}
|
|
174
|
+
form.append("file", blob, options.filename || "asset");
|
|
175
|
+
form.append("options", JSON.stringify(options || {}));
|
|
176
|
+
const res = await fetch(`${base}/api/v1/upload`, {
|
|
177
|
+
method: "POST",
|
|
178
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
179
|
+
body: form
|
|
180
|
+
});
|
|
181
|
+
return handleResponse("upload", res);
|
|
182
|
+
}
|
|
183
|
+
|
|
114
184
|
// src/cloudinaryCore.js
|
|
115
185
|
var _appName = null;
|
|
116
186
|
var _configured = false;
|
|
117
|
-
|
|
118
|
-
|
|
187
|
+
var _cloudinary = null;
|
|
188
|
+
async function loadLegacyCloudinary() {
|
|
189
|
+
if (_cloudinary) return _cloudinary;
|
|
190
|
+
const mod = await import("cloudinary");
|
|
191
|
+
_cloudinary = mod.v2;
|
|
192
|
+
return _cloudinary;
|
|
193
|
+
}
|
|
194
|
+
async function configureSanvikaCloudinary({ appName, cloudName, apiKey, apiSecret } = {}) {
|
|
195
|
+
const resolvedApp = appName || process.env.CLOUDINARY_APP_NAME;
|
|
196
|
+
if (!resolvedApp) throw new Error("appName is required for configureSanvikaCloudinary");
|
|
197
|
+
_appName = resolvedApp;
|
|
198
|
+
if (isProxyMode()) {
|
|
199
|
+
_configured = true;
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
119
202
|
const cn = cloudName || process.env.CLOUDINARY_CLOUD_NAME || process.env.CLOUDINARY_NAME;
|
|
120
203
|
const ak = apiKey || process.env.CLOUDINARY_API_KEY;
|
|
121
204
|
const as = apiSecret || process.env.CLOUDINARY_API_SECRET;
|
|
122
205
|
if (!cn || !ak || !as) {
|
|
123
|
-
throw new Error(
|
|
206
|
+
throw new Error(
|
|
207
|
+
"Cloudinary credentials missing. Either use proxy mode (CLOUDINARY_GATEWAY_URL + CLOUDINARY_TOKEN) or legacy env (CLOUDINARY_CLOUD_NAME, CLOUDINARY_API_KEY, CLOUDINARY_API_SECRET)."
|
|
208
|
+
);
|
|
124
209
|
}
|
|
210
|
+
const cloudinary = await loadLegacyCloudinary();
|
|
125
211
|
cloudinary.config({ cloud_name: cn, api_key: ak, api_secret: as, secure: true });
|
|
126
|
-
_appName = appName;
|
|
127
212
|
_configured = true;
|
|
128
213
|
}
|
|
129
|
-
function ensureConfigured() {
|
|
130
|
-
if (
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
214
|
+
async function ensureConfigured() {
|
|
215
|
+
if (_configured) return;
|
|
216
|
+
if (isProxyMode()) {
|
|
217
|
+
_appName = _appName || process.env.CLOUDINARY_APP_NAME || "sanvika-app";
|
|
218
|
+
_configured = true;
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
if (process.env.CLOUDINARY_APP_NAME) {
|
|
222
|
+
await configureSanvikaCloudinary({ appName: process.env.CLOUDINARY_APP_NAME });
|
|
223
|
+
return;
|
|
137
224
|
}
|
|
225
|
+
throw new Error("Call configureSanvikaCloudinary({ appName }) before using SDK operations.");
|
|
138
226
|
}
|
|
139
|
-
function getAppName() {
|
|
140
|
-
ensureConfigured();
|
|
227
|
+
async function getAppName() {
|
|
228
|
+
await ensureConfigured();
|
|
141
229
|
return _appName;
|
|
142
230
|
}
|
|
143
231
|
async function uploadImage(fileOrBuffer, options = {}) {
|
|
144
|
-
ensureConfigured();
|
|
232
|
+
await ensureConfigured();
|
|
145
233
|
const {
|
|
146
234
|
folder,
|
|
147
235
|
resourceType = "image",
|
|
@@ -158,6 +246,28 @@ async function uploadImage(fileOrBuffer, options = {}) {
|
|
|
158
246
|
timeout,
|
|
159
247
|
maxAttempts = 3
|
|
160
248
|
} = options;
|
|
249
|
+
const eagerValue = eager || transforms;
|
|
250
|
+
const uploadOptions = {
|
|
251
|
+
folder: folder || "",
|
|
252
|
+
resourceType,
|
|
253
|
+
tags: [_appName, ...tags],
|
|
254
|
+
eager: eagerValue,
|
|
255
|
+
eagerAsync,
|
|
256
|
+
eagerNotificationUrl,
|
|
257
|
+
publicId,
|
|
258
|
+
overwrite,
|
|
259
|
+
notificationUrl,
|
|
260
|
+
chunked,
|
|
261
|
+
chunkSize,
|
|
262
|
+
timeout
|
|
263
|
+
};
|
|
264
|
+
if (isProxyMode()) {
|
|
265
|
+
return withRetry(() => gatewayUpload(fileOrBuffer, uploadOptions), {
|
|
266
|
+
operationName: "uploadImage",
|
|
267
|
+
maxAttempts
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
const cloudinary = await loadLegacyCloudinary();
|
|
161
271
|
const uploadFolder = getFolderPath(_appName, folder);
|
|
162
272
|
const uploadOpts = {
|
|
163
273
|
folder: uploadFolder,
|
|
@@ -166,7 +276,6 @@ async function uploadImage(fileOrBuffer, options = {}) {
|
|
|
166
276
|
tags: [_appName, ...tags]
|
|
167
277
|
};
|
|
168
278
|
if (publicId) uploadOpts.public_id = publicId;
|
|
169
|
-
const eagerValue = eager || transforms;
|
|
170
279
|
if (eagerValue) uploadOpts.eager = eagerValue;
|
|
171
280
|
if (eagerAsync) uploadOpts.eager_async = true;
|
|
172
281
|
if (eagerNotificationUrl) uploadOpts.eager_notification_url = eagerNotificationUrl;
|
|
@@ -174,9 +283,7 @@ async function uploadImage(fileOrBuffer, options = {}) {
|
|
|
174
283
|
if (timeout) uploadOpts.timeout = timeout;
|
|
175
284
|
const fileSize = Buffer.isBuffer(fileOrBuffer) ? fileOrBuffer.length : null;
|
|
176
285
|
const useChunked = chunked || resourceType === "video" && fileSize !== null && fileSize > 10 * 1024 * 1024;
|
|
177
|
-
if (useChunked)
|
|
178
|
-
uploadOpts.chunk_size = chunkSize;
|
|
179
|
-
}
|
|
286
|
+
if (useChunked) uploadOpts.chunk_size = chunkSize;
|
|
180
287
|
return withRetry(
|
|
181
288
|
() => {
|
|
182
289
|
if (Buffer.isBuffer(fileOrBuffer)) {
|
|
@@ -210,11 +317,18 @@ async function uploadImages(files, options = {}) {
|
|
|
210
317
|
return Promise.all(files.map((file) => uploadImage(file, options)));
|
|
211
318
|
}
|
|
212
319
|
async function uploadRawFile(buffer, options = {}) {
|
|
213
|
-
ensureConfigured();
|
|
320
|
+
await ensureConfigured();
|
|
214
321
|
const { folder, filename, tags = [] } = options;
|
|
215
322
|
if (!buffer || !Buffer.isBuffer(buffer)) throw new Error("Buffer is required for uploadRawFile");
|
|
216
|
-
const uploadFolder = getFolderPath(_appName, folder);
|
|
217
323
|
const baseName = filename ? filename.replace(/\.[^.]+$/, "") : "file";
|
|
324
|
+
if (isProxyMode()) {
|
|
325
|
+
return withRetry(
|
|
326
|
+
() => gatewayUpload(buffer, { folder: folder || "", resourceType: "raw", tags: ["raw", _appName, ...tags], publicId: baseName, overwrite: true, filename }),
|
|
327
|
+
{ operationName: "uploadRawFile", maxAttempts: 3 }
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
const cloudinary = await loadLegacyCloudinary();
|
|
331
|
+
const uploadFolder = getFolderPath(_appName, folder);
|
|
218
332
|
return withRetry(
|
|
219
333
|
() => new Promise((resolve, reject) => {
|
|
220
334
|
const stream = cloudinary.uploader.upload_stream(
|
|
@@ -236,8 +350,14 @@ async function uploadRawFile(buffer, options = {}) {
|
|
|
236
350
|
);
|
|
237
351
|
}
|
|
238
352
|
async function deleteImage(urlOrPublicId, options = {}) {
|
|
239
|
-
|
|
353
|
+
var _a;
|
|
354
|
+
await ensureConfigured();
|
|
240
355
|
const { resourceType = "image" } = options;
|
|
356
|
+
if (isProxyMode()) {
|
|
357
|
+
const result = await gatewayPost("/api/v1/delete", { urls: [urlOrPublicId], options: { resourceType } });
|
|
358
|
+
return ((_a = result == null ? void 0 : result.results) == null ? void 0 : _a[0]) || result;
|
|
359
|
+
}
|
|
360
|
+
const cloudinary = await loadLegacyCloudinary();
|
|
241
361
|
const publicId = isCloudinaryUrl(urlOrPublicId) ? extractPublicId(urlOrPublicId) : urlOrPublicId;
|
|
242
362
|
if (!publicId) throw new CloudinaryError("Cannot extract public ID", "deleteImage", { urlOrPublicId });
|
|
243
363
|
return withRetry(
|
|
@@ -246,14 +366,22 @@ async function deleteImage(urlOrPublicId, options = {}) {
|
|
|
246
366
|
);
|
|
247
367
|
}
|
|
248
368
|
async function deleteImages(urls, options = {}) {
|
|
249
|
-
ensureConfigured();
|
|
369
|
+
await ensureConfigured();
|
|
250
370
|
const { fast = false, resourceType = "image" } = options;
|
|
251
|
-
if (!Array.isArray(urls) || urls.length === 0)
|
|
371
|
+
if (!Array.isArray(urls) || urls.length === 0) {
|
|
372
|
+
return { success: true, total: 0, successful: 0, failed: 0 };
|
|
373
|
+
}
|
|
374
|
+
if (isProxyMode()) {
|
|
375
|
+
return gatewayPost("/api/v1/delete", { urls, options: { fast, resourceType } });
|
|
376
|
+
}
|
|
377
|
+
const cloudinary = await loadLegacyCloudinary();
|
|
252
378
|
const BATCH_SIZE = fast ? 15 : 10;
|
|
253
379
|
const DELAY = fast ? 100 : 500;
|
|
254
380
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
255
381
|
const publicIds = urls.map((u) => isCloudinaryUrl(u) ? extractPublicId(u) : u).filter(Boolean);
|
|
256
|
-
if (publicIds.length === 0)
|
|
382
|
+
if (publicIds.length === 0) {
|
|
383
|
+
return { success: true, total: urls.length, successful: 0, failed: 0, invalidUrls: urls.length };
|
|
384
|
+
}
|
|
257
385
|
const allResults = [];
|
|
258
386
|
for (let i = 0; i < publicIds.length; i += BATCH_SIZE) {
|
|
259
387
|
const batch = publicIds.slice(i, i + BATCH_SIZE);
|
|
@@ -275,15 +403,21 @@ async function deleteImages(urls, options = {}) {
|
|
|
275
403
|
return { success: failed === 0, total: urls.length, processed: allResults.length, successful, failed };
|
|
276
404
|
}
|
|
277
405
|
async function pingCloudinary() {
|
|
278
|
-
ensureConfigured();
|
|
406
|
+
await ensureConfigured();
|
|
407
|
+
if (isProxyMode()) return gatewayGet("/api/v1/ping");
|
|
408
|
+
const cloudinary = await loadLegacyCloudinary();
|
|
279
409
|
return cloudinary.api.ping();
|
|
280
410
|
}
|
|
281
411
|
async function getCloudinaryUsage(options = {}) {
|
|
282
|
-
ensureConfigured();
|
|
412
|
+
await ensureConfigured();
|
|
283
413
|
const { resourceType } = options;
|
|
414
|
+
if (isProxyMode()) return gatewayGet("/api/v1/usage", resourceType ? { resourceType } : void 0);
|
|
415
|
+
const cloudinary = await loadLegacyCloudinary();
|
|
284
416
|
return cloudinary.api.usage(resourceType ? { resource_type: resourceType } : {});
|
|
285
417
|
}
|
|
286
|
-
function getCloudinarySdkVersion() {
|
|
418
|
+
async function getCloudinarySdkVersion() {
|
|
419
|
+
if (isProxyMode()) return "gateway";
|
|
420
|
+
const cloudinary = await loadLegacyCloudinary();
|
|
287
421
|
return cloudinary.CLOUDINARY_VERSION;
|
|
288
422
|
}
|
|
289
423
|
|
|
@@ -291,9 +425,7 @@ function getCloudinarySdkVersion() {
|
|
|
291
425
|
import crypto from "crypto";
|
|
292
426
|
function testCloudinaryWebhookSignature(apiSecret, options = {}) {
|
|
293
427
|
try {
|
|
294
|
-
if (!apiSecret) {
|
|
295
|
-
return { success: false, error: "apiSecret is required" };
|
|
296
|
-
}
|
|
428
|
+
if (!apiSecret) return { success: false, error: "apiSecret is required" };
|
|
297
429
|
const testPayload = { test: "data", timestamp: Math.floor(Date.now() / 1e3) };
|
|
298
430
|
const testPayloadString = JSON.stringify(testPayload);
|
|
299
431
|
const testTimestamp = testPayload.timestamp.toString();
|
|
@@ -304,10 +436,7 @@ function testCloudinaryWebhookSignature(apiSecret, options = {}) {
|
|
|
304
436
|
testPayload,
|
|
305
437
|
testTimestamp,
|
|
306
438
|
signature,
|
|
307
|
-
headers: {
|
|
308
|
-
"X-Cld-Timestamp": testTimestamp,
|
|
309
|
-
"X-Cld-Signature": signature
|
|
310
|
-
},
|
|
439
|
+
headers: { "X-Cld-Timestamp": testTimestamp, "X-Cld-Signature": signature },
|
|
311
440
|
testEndpoint: options.testEndpoint || "/api/webhooks/cloudinary/debug"
|
|
312
441
|
};
|
|
313
442
|
} catch (error) {
|
|
@@ -315,15 +444,15 @@ function testCloudinaryWebhookSignature(apiSecret, options = {}) {
|
|
|
315
444
|
}
|
|
316
445
|
}
|
|
317
446
|
async function runCloudinaryDiagnostics(options = {}) {
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
} = options;
|
|
447
|
+
if (isProxyMode()) {
|
|
448
|
+
return gatewayPost("/api/v1/diagnostics", options || {});
|
|
449
|
+
}
|
|
450
|
+
const { testWebhook = false, webhookSecret, testFolder = "diagnostics" } = options;
|
|
323
451
|
const report = {
|
|
324
452
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
325
|
-
cloudinaryVersion: getCloudinarySdkVersion(),
|
|
453
|
+
cloudinaryVersion: await getCloudinarySdkVersion(),
|
|
326
454
|
nodeVersion: process.version,
|
|
455
|
+
mode: "legacy",
|
|
327
456
|
configuration: {
|
|
328
457
|
cloudName: process.env.CLOUDINARY_CLOUD_NAME || process.env.CLOUDINARY_NAME ? "set" : "missing",
|
|
329
458
|
apiKey: process.env.CLOUDINARY_API_KEY ? "set" : "missing",
|
|
@@ -344,18 +473,8 @@ async function runCloudinaryDiagnostics(options = {}) {
|
|
|
344
473
|
publicId: `diagnostic_${Date.now()}`,
|
|
345
474
|
overwrite: true
|
|
346
475
|
}).then(
|
|
347
|
-
(result) => ({
|
|
348
|
-
|
|
349
|
-
publicId: result.public_id,
|
|
350
|
-
url: result.secure_url,
|
|
351
|
-
bytes: result.bytes
|
|
352
|
-
}),
|
|
353
|
-
(error) => ({
|
|
354
|
-
success: false,
|
|
355
|
-
error: error.message,
|
|
356
|
-
httpCode: error.http_code,
|
|
357
|
-
name: error.name
|
|
358
|
-
})
|
|
476
|
+
(result) => ({ success: true, publicId: result.public_id, url: result.secure_url, bytes: result.bytes }),
|
|
477
|
+
(error) => ({ success: false, error: error.message, httpCode: error.http_code, name: error.name })
|
|
359
478
|
);
|
|
360
479
|
report.tests.videoLimits = await getCloudinaryUsage({ resourceType: "video" }).then(
|
|
361
480
|
(result) => ({ success: true, result }),
|
|
@@ -366,6 +485,33 @@ async function runCloudinaryDiagnostics(options = {}) {
|
|
|
366
485
|
}
|
|
367
486
|
return report;
|
|
368
487
|
}
|
|
488
|
+
|
|
489
|
+
// src/webhookSignature.js
|
|
490
|
+
import crypto2 from "crypto";
|
|
491
|
+
function verifySanvikaWebhookSignature({ headers, rawBody, secret, toleranceSec = 300 } = {}) {
|
|
492
|
+
const getHeader = (name) => {
|
|
493
|
+
if (!headers) return "";
|
|
494
|
+
if (typeof headers.get === "function") return headers.get(name) || headers.get(name.toLowerCase()) || "";
|
|
495
|
+
return headers[name] || headers[name.toLowerCase()] || "";
|
|
496
|
+
};
|
|
497
|
+
const sig = String(getHeader("x-sanvika-signature") || "").trim();
|
|
498
|
+
const ts = String(getHeader("x-sanvika-timestamp") || "").trim();
|
|
499
|
+
const token = secret || process.env.CLOUDINARY_TOKEN;
|
|
500
|
+
if (!token) return { valid: false, reason: "missing_secret" };
|
|
501
|
+
if (!sig) return { valid: false, reason: "missing_signature" };
|
|
502
|
+
if (!ts) return { valid: false, reason: "missing_timestamp" };
|
|
503
|
+
const tsNum = Number(ts);
|
|
504
|
+
if (!Number.isFinite(tsNum)) return { valid: false, reason: "invalid_timestamp" };
|
|
505
|
+
const nowSec = Math.floor(Date.now() / 1e3);
|
|
506
|
+
if (Math.abs(nowSec - tsNum) > toleranceSec) return { valid: false, reason: "stale_timestamp" };
|
|
507
|
+
const body = Buffer.isBuffer(rawBody) ? rawBody.toString("utf8") : String(rawBody || "");
|
|
508
|
+
const expected = crypto2.createHmac("sha256", token).update(ts + body).digest("hex");
|
|
509
|
+
const a = Buffer.from(sig, "hex");
|
|
510
|
+
const b = Buffer.from(expected, "hex");
|
|
511
|
+
if (a.length !== b.length) return { valid: false, reason: "length_mismatch" };
|
|
512
|
+
const ok = crypto2.timingSafeEqual(a, b);
|
|
513
|
+
return { valid: ok, reason: ok ? void 0 : "signature_mismatch" };
|
|
514
|
+
}
|
|
369
515
|
export {
|
|
370
516
|
CloudinaryError,
|
|
371
517
|
TRANSFORM_PRESETS,
|
|
@@ -373,12 +519,16 @@ export {
|
|
|
373
519
|
deleteImage,
|
|
374
520
|
deleteImages,
|
|
375
521
|
extractPublicId,
|
|
522
|
+
gatewayGet,
|
|
523
|
+
gatewayPost,
|
|
524
|
+
gatewayUpload,
|
|
376
525
|
getAppName,
|
|
377
526
|
getCloudinarySdkVersion,
|
|
378
527
|
getCloudinaryUsage,
|
|
379
528
|
getFolderPath,
|
|
380
529
|
getOptimizedUrl,
|
|
381
530
|
isCloudinaryUrl,
|
|
531
|
+
isProxyMode,
|
|
382
532
|
isRetriableError,
|
|
383
533
|
pingCloudinary,
|
|
384
534
|
runCloudinaryDiagnostics,
|
|
@@ -388,5 +538,6 @@ export {
|
|
|
388
538
|
uploadRawFile,
|
|
389
539
|
uploadVideo,
|
|
390
540
|
validatePublicId,
|
|
541
|
+
verifySanvikaWebhookSignature,
|
|
391
542
|
withRetry
|
|
392
543
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanvika/cloudinary",
|
|
3
|
-
"version": "0.1
|
|
4
|
-
"description": "Centralized Cloudinary SDK for the Sanvika ecosystem —
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "Centralized Cloudinary SDK for the Sanvika ecosystem — proxy gateway mode (zero credentials) + legacy direct mode",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"module": "./dist/index.js",
|
|
@@ -34,7 +34,8 @@
|
|
|
34
34
|
"license": "MIT",
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"react": ">=18.0.0",
|
|
37
|
-
"react-dom": ">=18.0.0"
|
|
37
|
+
"react-dom": ">=18.0.0",
|
|
38
|
+
"cloudinary": "^2.5.0"
|
|
38
39
|
},
|
|
39
40
|
"peerDependenciesMeta": {
|
|
40
41
|
"react": {
|
|
@@ -42,6 +43,9 @@
|
|
|
42
43
|
},
|
|
43
44
|
"react-dom": {
|
|
44
45
|
"optional": true
|
|
46
|
+
},
|
|
47
|
+
"cloudinary": {
|
|
48
|
+
"optional": true
|
|
45
49
|
}
|
|
46
50
|
},
|
|
47
51
|
"engines": {
|