@rovela-ai/sdk 0.1.25 → 0.1.27

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.
Files changed (115) hide show
  1. package/dist/admin/components/CategoryForm.d.ts.map +1 -1
  2. package/dist/admin/components/CategoryForm.js +2 -2
  3. package/dist/admin/components/CategoryForm.js.map +1 -1
  4. package/dist/admin/components/ProductForm.d.ts.map +1 -1
  5. package/dist/admin/components/ProductForm.js +3 -35
  6. package/dist/admin/components/ProductForm.js.map +1 -1
  7. package/dist/admin/components/ProductTable.d.ts.map +1 -1
  8. package/dist/admin/components/ProductTable.js +6 -1
  9. package/dist/admin/components/ProductTable.js.map +1 -1
  10. package/dist/admin/server/admin-service.d.ts +3 -3
  11. package/dist/admin/server/admin-service.d.ts.map +1 -1
  12. package/dist/admin/server/admin-service.js +12 -22
  13. package/dist/admin/server/admin-service.js.map +1 -1
  14. package/dist/auth/server/customer-service.d.ts +2 -2
  15. package/dist/auth/server/customer-service.d.ts.map +1 -1
  16. package/dist/auth/server/customer-service.js +11 -20
  17. package/dist/auth/server/customer-service.js.map +1 -1
  18. package/dist/auth/server/password-reset-service.d.ts +1 -0
  19. package/dist/auth/server/password-reset-service.d.ts.map +1 -1
  20. package/dist/auth/server/password-reset-service.js +5 -7
  21. package/dist/auth/server/password-reset-service.js.map +1 -1
  22. package/dist/auth/server/verification-service.d.ts +1 -0
  23. package/dist/auth/server/verification-service.d.ts.map +1 -1
  24. package/dist/auth/server/verification-service.js +6 -9
  25. package/dist/auth/server/verification-service.js.map +1 -1
  26. package/dist/core/db/client.d.ts +2 -44
  27. package/dist/core/db/client.d.ts.map +1 -1
  28. package/dist/core/db/client.js +2 -106
  29. package/dist/core/db/client.js.map +1 -1
  30. package/dist/core/db/index.d.ts +1 -1
  31. package/dist/core/db/index.d.ts.map +1 -1
  32. package/dist/core/db/index.js +2 -2
  33. package/dist/core/db/index.js.map +1 -1
  34. package/dist/core/db/queries.d.ts +18 -35
  35. package/dist/core/db/queries.d.ts.map +1 -1
  36. package/dist/core/db/queries.js +69 -110
  37. package/dist/core/db/queries.js.map +1 -1
  38. package/dist/core/db/schema.d.ts +1 -137
  39. package/dist/core/db/schema.d.ts.map +1 -1
  40. package/dist/core/db/schema.js +6 -23
  41. package/dist/core/db/schema.js.map +1 -1
  42. package/dist/core/server/index.d.ts +1 -1
  43. package/dist/core/server/index.d.ts.map +1 -1
  44. package/dist/core/server/index.js +1 -3
  45. package/dist/core/server/index.js.map +1 -1
  46. package/dist/core/types.d.ts +0 -5
  47. package/dist/core/types.d.ts.map +1 -1
  48. package/dist/emails/config.d.ts.map +1 -1
  49. package/dist/emails/config.js +11 -17
  50. package/dist/emails/config.js.map +1 -1
  51. package/dist/media/api/delete.d.ts +44 -0
  52. package/dist/media/api/delete.d.ts.map +1 -0
  53. package/dist/media/api/delete.js +134 -0
  54. package/dist/media/api/delete.js.map +1 -0
  55. package/dist/media/api/index.d.ts +17 -0
  56. package/dist/media/api/index.d.ts.map +1 -0
  57. package/dist/media/api/index.js +17 -0
  58. package/dist/media/api/index.js.map +1 -0
  59. package/dist/media/api/presign.d.ts +39 -0
  60. package/dist/media/api/presign.d.ts.map +1 -0
  61. package/dist/media/api/presign.js +138 -0
  62. package/dist/media/api/presign.js.map +1 -0
  63. package/dist/media/components/DropZone.d.ts +18 -0
  64. package/dist/media/components/DropZone.d.ts.map +1 -0
  65. package/dist/media/components/DropZone.js +112 -0
  66. package/dist/media/components/DropZone.js.map +1 -0
  67. package/dist/media/components/ImageGalleryUpload.d.ts +18 -0
  68. package/dist/media/components/ImageGalleryUpload.d.ts.map +1 -0
  69. package/dist/media/components/ImageGalleryUpload.js +156 -0
  70. package/dist/media/components/ImageGalleryUpload.js.map +1 -0
  71. package/dist/media/components/ImageUpload.d.ts +17 -0
  72. package/dist/media/components/ImageUpload.d.ts.map +1 -0
  73. package/dist/media/components/ImageUpload.js +95 -0
  74. package/dist/media/components/ImageUpload.js.map +1 -0
  75. package/dist/media/components/index.d.ts +10 -0
  76. package/dist/media/components/index.d.ts.map +1 -0
  77. package/dist/media/components/index.js +9 -0
  78. package/dist/media/components/index.js.map +1 -0
  79. package/dist/media/config.d.ts +57 -0
  80. package/dist/media/config.d.ts.map +1 -0
  81. package/dist/media/config.js +142 -0
  82. package/dist/media/config.js.map +1 -0
  83. package/dist/media/hooks/index.d.ts +8 -0
  84. package/dist/media/hooks/index.d.ts.map +1 -0
  85. package/dist/media/hooks/index.js +7 -0
  86. package/dist/media/hooks/index.js.map +1 -0
  87. package/dist/media/hooks/useUpload.d.ts +32 -0
  88. package/dist/media/hooks/useUpload.d.ts.map +1 -0
  89. package/dist/media/hooks/useUpload.js +258 -0
  90. package/dist/media/hooks/useUpload.js.map +1 -0
  91. package/dist/media/index.d.ts +57 -0
  92. package/dist/media/index.d.ts.map +1 -0
  93. package/dist/media/index.js +68 -0
  94. package/dist/media/index.js.map +1 -0
  95. package/dist/media/server/delete.d.ts +59 -0
  96. package/dist/media/server/delete.d.ts.map +1 -0
  97. package/dist/media/server/delete.js +176 -0
  98. package/dist/media/server/delete.js.map +1 -0
  99. package/dist/media/server/index.d.ts +10 -0
  100. package/dist/media/server/index.d.ts.map +1 -0
  101. package/dist/media/server/index.js +13 -0
  102. package/dist/media/server/index.js.map +1 -0
  103. package/dist/media/server/presign.d.ts +57 -0
  104. package/dist/media/server/presign.d.ts.map +1 -0
  105. package/dist/media/server/presign.js +112 -0
  106. package/dist/media/server/presign.js.map +1 -0
  107. package/dist/media/server/r2-client.d.ts +30 -0
  108. package/dist/media/server/r2-client.d.ts.map +1 -0
  109. package/dist/media/server/r2-client.js +76 -0
  110. package/dist/media/server/r2-client.js.map +1 -0
  111. package/dist/media/types.d.ts +271 -0
  112. package/dist/media/types.d.ts.map +1 -0
  113. package/dist/media/types.js +52 -0
  114. package/dist/media/types.js.map +1 -0
  115. package/package.json +15 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../../src/media/server/delete.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AASlD;;;;;;;;;;;;GAYG;AACH,wBAAsB,UAAU,CAC9B,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,kBAAkB,GAC1B,OAAO,CAAC,OAAO,CAAC,CA+BlB;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,kBAAkB,GAC1B,OAAO,CAAC,OAAO,CAAC,CAuBlB;AAMD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EAAE,EACd,MAAM,CAAC,EAAE,kBAAkB,GAC1B,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAoEpD;AAMD;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,kBAAkB,GAC1B,OAAO,CAAC,OAAO,CAAC,CAMlB"}
@@ -0,0 +1,176 @@
1
+ /**
2
+ * @rovela-ai/sdk/media/server/delete
3
+ *
4
+ * File deletion from R2 storage.
5
+ * Server-side only - do not import in client components.
6
+ */
7
+ import { DeleteObjectCommand, DeleteObjectsCommand } from '@aws-sdk/client-s3';
8
+ import { extractKeyFromUrl, requireMediaConfig } from '../config';
9
+ import { getR2Client, getBucketName, getPublicUrlBase } from './r2-client';
10
+ import { validateStoreUrl } from './presign';
11
+ // =============================================================================
12
+ // Single File Deletion
13
+ // =============================================================================
14
+ /**
15
+ * Delete a file from R2 storage.
16
+ *
17
+ * @param url - Public URL of the file to delete
18
+ * @param config - Optional storage configuration override
19
+ * @returns True if deletion was successful
20
+ * @throws Error if URL is invalid or doesn't belong to this store
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * await deleteFile('https://pub-xxx.r2.dev/stores/abc123/products/img.jpg');
25
+ * ```
26
+ */
27
+ export async function deleteFile(url, config) {
28
+ const resolvedConfig = config || requireMediaConfig();
29
+ // Validate URL belongs to this store
30
+ if (!validateStoreUrl(url, resolvedConfig)) {
31
+ throw new Error('Invalid URL: does not belong to this store');
32
+ }
33
+ // Extract key from URL
34
+ const publicUrlBase = getPublicUrlBase(resolvedConfig);
35
+ const key = extractKeyFromUrl(publicUrlBase, url);
36
+ if (!key) {
37
+ throw new Error('Invalid URL: could not extract storage key');
38
+ }
39
+ const client = getR2Client(resolvedConfig);
40
+ const bucketName = getBucketName(resolvedConfig);
41
+ try {
42
+ await client.send(new DeleteObjectCommand({
43
+ Bucket: bucketName,
44
+ Key: key,
45
+ }));
46
+ return true;
47
+ }
48
+ catch (error) {
49
+ console.error('[Media] Delete failed:', error);
50
+ throw new Error('Failed to delete file');
51
+ }
52
+ }
53
+ /**
54
+ * Delete a file by its storage key.
55
+ * Use this when you have the key directly instead of the URL.
56
+ *
57
+ * @param key - Storage key of the file
58
+ * @param config - Optional storage configuration override
59
+ * @returns True if deletion was successful
60
+ */
61
+ export async function deleteFileByKey(key, config) {
62
+ const resolvedConfig = config || requireMediaConfig();
63
+ const client = getR2Client(resolvedConfig);
64
+ const bucketName = getBucketName(resolvedConfig);
65
+ // Validate key belongs to this store
66
+ const expectedPrefix = `stores/${resolvedConfig.storeId}/`;
67
+ if (!key.startsWith(expectedPrefix)) {
68
+ throw new Error('Invalid key: does not belong to this store');
69
+ }
70
+ try {
71
+ await client.send(new DeleteObjectCommand({
72
+ Bucket: bucketName,
73
+ Key: key,
74
+ }));
75
+ return true;
76
+ }
77
+ catch (error) {
78
+ console.error('[Media] Delete by key failed:', error);
79
+ throw new Error('Failed to delete file');
80
+ }
81
+ }
82
+ // =============================================================================
83
+ // Batch Deletion
84
+ // =============================================================================
85
+ /**
86
+ * Delete multiple files from R2 storage.
87
+ *
88
+ * @param urls - Array of public URLs to delete
89
+ * @param config - Optional storage configuration override
90
+ * @returns Object with results for each URL
91
+ *
92
+ * @example
93
+ * ```typescript
94
+ * const results = await deleteFiles([
95
+ * 'https://pub-xxx.r2.dev/stores/abc123/products/img1.jpg',
96
+ * 'https://pub-xxx.r2.dev/stores/abc123/products/img2.jpg',
97
+ * ]);
98
+ * // { succeeded: ['url1', 'url2'], failed: [] }
99
+ * ```
100
+ */
101
+ export async function deleteFiles(urls, config) {
102
+ const resolvedConfig = config || requireMediaConfig();
103
+ const publicUrlBase = getPublicUrlBase(resolvedConfig);
104
+ // Filter and extract keys
105
+ const validEntries = [];
106
+ const invalidUrls = [];
107
+ for (const url of urls) {
108
+ if (!validateStoreUrl(url, resolvedConfig)) {
109
+ invalidUrls.push(url);
110
+ continue;
111
+ }
112
+ const key = extractKeyFromUrl(publicUrlBase, url);
113
+ if (!key) {
114
+ invalidUrls.push(url);
115
+ continue;
116
+ }
117
+ validEntries.push({ url, key });
118
+ }
119
+ if (validEntries.length === 0) {
120
+ return { succeeded: [], failed: urls };
121
+ }
122
+ const client = getR2Client(resolvedConfig);
123
+ const bucketName = getBucketName(resolvedConfig);
124
+ try {
125
+ // Use batch delete for efficiency
126
+ await client.send(new DeleteObjectsCommand({
127
+ Bucket: bucketName,
128
+ Delete: {
129
+ Objects: validEntries.map(({ key }) => ({ Key: key })),
130
+ Quiet: true,
131
+ },
132
+ }));
133
+ return {
134
+ succeeded: validEntries.map(({ url }) => url),
135
+ failed: invalidUrls,
136
+ };
137
+ }
138
+ catch (error) {
139
+ console.error('[Media] Batch delete failed:', error);
140
+ // On error, try to delete individually
141
+ const succeeded = [];
142
+ const failed = [...invalidUrls];
143
+ for (const { url, key } of validEntries) {
144
+ try {
145
+ await client.send(new DeleteObjectCommand({
146
+ Bucket: bucketName,
147
+ Key: key,
148
+ }));
149
+ succeeded.push(url);
150
+ }
151
+ catch {
152
+ failed.push(url);
153
+ }
154
+ }
155
+ return { succeeded, failed };
156
+ }
157
+ }
158
+ // =============================================================================
159
+ // Safe Deletion (with existence check)
160
+ // =============================================================================
161
+ /**
162
+ * Safely delete a file - returns false instead of throwing if file doesn't exist.
163
+ *
164
+ * @param url - Public URL of the file to delete
165
+ * @param config - Optional storage configuration override
166
+ * @returns True if deleted, false if not found or invalid
167
+ */
168
+ export async function safeDeleteFile(url, config) {
169
+ try {
170
+ return await deleteFile(url, config);
171
+ }
172
+ catch {
173
+ return false;
174
+ }
175
+ }
176
+ //# sourceMappingURL=delete.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete.js","sourceRoot":"","sources":["../../../src/media/server/delete.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAE9E,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AACjE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAE5C,gFAAgF;AAChF,uBAAuB;AACvB,gFAAgF;AAEhF;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,GAAW,EACX,MAA2B;IAE3B,MAAM,cAAc,GAAG,MAAM,IAAI,kBAAkB,EAAE,CAAA;IAErD,qCAAqC;IACrC,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,cAAc,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAA;IAC/D,CAAC;IAED,uBAAuB;IACvB,MAAM,aAAa,GAAG,gBAAgB,CAAC,cAAc,CAAC,CAAA;IACtD,MAAM,GAAG,GAAG,iBAAiB,CAAC,aAAa,EAAE,GAAG,CAAC,CAAA;IAEjD,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAA;IAC/D,CAAC;IAED,MAAM,MAAM,GAAG,WAAW,CAAC,cAAc,CAAC,CAAA;IAC1C,MAAM,UAAU,GAAG,aAAa,CAAC,cAAc,CAAC,CAAA;IAEhD,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,CACf,IAAI,mBAAmB,CAAC;YACtB,MAAM,EAAE,UAAU;YAClB,GAAG,EAAE,GAAG;SACT,CAAC,CACH,CAAA;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAA;QAC9C,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAA;IAC1C,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,GAAW,EACX,MAA2B;IAE3B,MAAM,cAAc,GAAG,MAAM,IAAI,kBAAkB,EAAE,CAAA;IACrD,MAAM,MAAM,GAAG,WAAW,CAAC,cAAc,CAAC,CAAA;IAC1C,MAAM,UAAU,GAAG,aAAa,CAAC,cAAc,CAAC,CAAA;IAEhD,qCAAqC;IACrC,MAAM,cAAc,GAAG,UAAU,cAAc,CAAC,OAAO,GAAG,CAAA;IAC1D,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAA;IAC/D,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,CACf,IAAI,mBAAmB,CAAC;YACtB,MAAM,EAAE,UAAU;YAClB,GAAG,EAAE,GAAG;SACT,CAAC,CACH,CAAA;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAA;QACrD,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAA;IAC1C,CAAC;AACH,CAAC;AAED,gFAAgF;AAChF,iBAAiB;AACjB,gFAAgF;AAEhF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAc,EACd,MAA2B;IAE3B,MAAM,cAAc,GAAG,MAAM,IAAI,kBAAkB,EAAE,CAAA;IACrD,MAAM,aAAa,GAAG,gBAAgB,CAAC,cAAc,CAAC,CAAA;IAEtD,0BAA0B;IAC1B,MAAM,YAAY,GAAmC,EAAE,CAAA;IACvD,MAAM,WAAW,GAAa,EAAE,CAAA;IAEhC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,cAAc,CAAC,EAAE,CAAC;YAC3C,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACrB,SAAQ;QACV,CAAC;QAED,MAAM,GAAG,GAAG,iBAAiB,CAAC,aAAa,EAAE,GAAG,CAAC,CAAA;QACjD,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACrB,SAAQ;QACV,CAAC;QAED,YAAY,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAA;IACjC,CAAC;IAED,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAA;IACxC,CAAC;IAED,MAAM,MAAM,GAAG,WAAW,CAAC,cAAc,CAAC,CAAA;IAC1C,MAAM,UAAU,GAAG,aAAa,CAAC,cAAc,CAAC,CAAA;IAEhD,IAAI,CAAC;QACH,kCAAkC;QAClC,MAAM,MAAM,CAAC,IAAI,CACf,IAAI,oBAAoB,CAAC;YACvB,MAAM,EAAE,UAAU;YAClB,MAAM,EAAE;gBACN,OAAO,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;gBACtD,KAAK,EAAE,IAAI;aACZ;SACF,CAAC,CACH,CAAA;QAED,OAAO;YACL,SAAS,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC;YAC7C,MAAM,EAAE,WAAW;SACpB,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAA;QACpD,uCAAuC;QACvC,MAAM,SAAS,GAAa,EAAE,CAAA;QAC9B,MAAM,MAAM,GAAa,CAAC,GAAG,WAAW,CAAC,CAAA;QAEzC,KAAK,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,YAAY,EAAE,CAAC;YACxC,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,IAAI,CACf,IAAI,mBAAmB,CAAC;oBACtB,MAAM,EAAE,UAAU;oBAClB,GAAG,EAAE,GAAG;iBACT,CAAC,CACH,CAAA;gBACD,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACrB,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YAClB,CAAC;QACH,CAAC;QAED,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,CAAA;IAC9B,CAAC;AACH,CAAC;AAED,gFAAgF;AAChF,uCAAuC;AACvC,gFAAgF;AAEhF;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,GAAW,EACX,MAA2B;IAE3B,IAAI,CAAC;QACH,OAAO,MAAM,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @rovela-ai/sdk/media/server
3
+ *
4
+ * Server-side media utilities.
5
+ * Only import this in server components and API routes.
6
+ */
7
+ export { getR2Client, clearR2ClientCache, getBucketName, getPublicUrlBase, getStoreId } from './r2-client';
8
+ export { generatePresignedUrl, generatePresignedUrls, isR2Url, validateStoreUrl, type GeneratePresignedUrlOptions, } from './presign';
9
+ export { deleteFile, deleteFileByKey, deleteFiles, safeDeleteFile } from './delete';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/media/server/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,aAAa,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAG1G,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,OAAO,EACP,gBAAgB,EAChB,KAAK,2BAA2B,GACjC,MAAM,WAAW,CAAA;AAGlB,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @rovela-ai/sdk/media/server
3
+ *
4
+ * Server-side media utilities.
5
+ * Only import this in server components and API routes.
6
+ */
7
+ // R2 Client
8
+ export { getR2Client, clearR2ClientCache, getBucketName, getPublicUrlBase, getStoreId } from './r2-client';
9
+ // Presigned URLs
10
+ export { generatePresignedUrl, generatePresignedUrls, isR2Url, validateStoreUrl, } from './presign';
11
+ // File Deletion
12
+ export { deleteFile, deleteFileByKey, deleteFiles, safeDeleteFile } from './delete';
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/media/server/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,YAAY;AACZ,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,aAAa,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAE1G,iBAAiB;AACjB,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,OAAO,EACP,gBAAgB,GAEjB,MAAM,WAAW,CAAA;AAElB,gBAAgB;AAChB,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * @rovela-ai/sdk/media/server/presign
3
+ *
4
+ * Presigned URL generation for direct browser uploads to R2.
5
+ * Server-side only - do not import in client components.
6
+ */
7
+ import type { PresignedUrlRequest, PresignedUrlResponse, MediaStorageConfig } from '../types';
8
+ /**
9
+ * Options for generating a presigned URL
10
+ */
11
+ export interface GeneratePresignedUrlOptions {
12
+ /** URL expiration time in seconds (default: 300 = 5 minutes) */
13
+ expiresIn?: number;
14
+ /** Optional storage config override */
15
+ config?: MediaStorageConfig;
16
+ }
17
+ /**
18
+ * Generate a presigned URL for uploading a file to R2.
19
+ *
20
+ * The presigned URL allows the browser to upload directly to R2
21
+ * without the file passing through your server.
22
+ *
23
+ * @param request - Upload request details
24
+ * @param options - Optional configuration
25
+ * @returns Presigned URL response with upload URL and final public URL
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * const result = await generatePresignedUrl({
30
+ * filename: 'product-image.jpg',
31
+ * contentType: 'image/jpeg',
32
+ * folder: 'products',
33
+ * entityId: 'prod_abc123',
34
+ * });
35
+ *
36
+ * // Client uploads directly to result.uploadUrl
37
+ * // After upload, image is accessible at result.publicUrl
38
+ * ```
39
+ */
40
+ export declare function generatePresignedUrl(request: PresignedUrlRequest, options?: GeneratePresignedUrlOptions): Promise<PresignedUrlResponse>;
41
+ /**
42
+ * Generate presigned URLs for multiple files at once.
43
+ *
44
+ * @param requests - Array of upload request details
45
+ * @param options - Optional configuration
46
+ * @returns Array of presigned URL responses
47
+ */
48
+ export declare function generatePresignedUrls(requests: PresignedUrlRequest[], options?: GeneratePresignedUrlOptions): Promise<PresignedUrlResponse[]>;
49
+ /**
50
+ * Check if a URL is from this store's R2 storage
51
+ */
52
+ export declare function isR2Url(url: string, config?: MediaStorageConfig): boolean;
53
+ /**
54
+ * Validate that a URL belongs to this store's storage prefix
55
+ */
56
+ export declare function validateStoreUrl(url: string, config?: MediaStorageConfig): boolean;
57
+ //# sourceMappingURL=presign.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presign.d.ts","sourceRoot":"","sources":["../../../src/media/server/presign.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EACnB,MAAM,UAAU,CAAA;AAcjB;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,uCAAuC;IACvC,MAAM,CAAC,EAAE,kBAAkB,CAAA;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,mBAAmB,EAC5B,OAAO,GAAE,2BAAgC,GACxC,OAAO,CAAC,oBAAoB,CAAC,CAwC/B;AAED;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,mBAAmB,EAAE,EAC/B,OAAO,GAAE,2BAAgC,GACxC,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAEjC;AAMD;;GAEG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAGzE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAiBlF"}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * @rovela-ai/sdk/media/server/presign
3
+ *
4
+ * Presigned URL generation for direct browser uploads to R2.
5
+ * Server-side only - do not import in client components.
6
+ */
7
+ import { PutObjectCommand } from '@aws-sdk/client-s3';
8
+ import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
9
+ import { generateUniqueFilename } from '../types';
10
+ import { buildStorageKey, buildPublicUrl, requireMediaConfig } from '../config';
11
+ import { getR2Client, getBucketName, getPublicUrlBase, getStoreId } from './r2-client';
12
+ // =============================================================================
13
+ // Presigned URL Generation
14
+ // =============================================================================
15
+ /**
16
+ * Default presigned URL expiration time in seconds (5 minutes)
17
+ */
18
+ const DEFAULT_EXPIRES_IN = 5 * 60;
19
+ /**
20
+ * Generate a presigned URL for uploading a file to R2.
21
+ *
22
+ * The presigned URL allows the browser to upload directly to R2
23
+ * without the file passing through your server.
24
+ *
25
+ * @param request - Upload request details
26
+ * @param options - Optional configuration
27
+ * @returns Presigned URL response with upload URL and final public URL
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * const result = await generatePresignedUrl({
32
+ * filename: 'product-image.jpg',
33
+ * contentType: 'image/jpeg',
34
+ * folder: 'products',
35
+ * entityId: 'prod_abc123',
36
+ * });
37
+ *
38
+ * // Client uploads directly to result.uploadUrl
39
+ * // After upload, image is accessible at result.publicUrl
40
+ * ```
41
+ */
42
+ export async function generatePresignedUrl(request, options = {}) {
43
+ const { expiresIn = DEFAULT_EXPIRES_IN, config } = options;
44
+ // Get configuration
45
+ const resolvedConfig = config || requireMediaConfig();
46
+ const client = getR2Client(resolvedConfig);
47
+ const bucketName = getBucketName(resolvedConfig);
48
+ const publicUrlBase = getPublicUrlBase(resolvedConfig);
49
+ const storeId = getStoreId(resolvedConfig);
50
+ // Generate unique filename to prevent overwrites
51
+ const uniqueFilename = generateUniqueFilename(request.filename);
52
+ // Build the storage key (path)
53
+ const key = buildStorageKey(storeId, request.folder, uniqueFilename, request.entityId);
54
+ // Create the PutObject command
55
+ const command = new PutObjectCommand({
56
+ Bucket: bucketName,
57
+ Key: key,
58
+ ContentType: request.contentType,
59
+ });
60
+ // Generate presigned URL
61
+ const uploadUrl = await getSignedUrl(client, command, {
62
+ expiresIn,
63
+ });
64
+ // Calculate expiration time
65
+ const expiresAt = new Date(Date.now() + expiresIn * 1000);
66
+ // Build public URL
67
+ const publicUrl = buildPublicUrl(publicUrlBase, key);
68
+ return {
69
+ uploadUrl,
70
+ publicUrl,
71
+ key,
72
+ expiresAt,
73
+ };
74
+ }
75
+ /**
76
+ * Generate presigned URLs for multiple files at once.
77
+ *
78
+ * @param requests - Array of upload request details
79
+ * @param options - Optional configuration
80
+ * @returns Array of presigned URL responses
81
+ */
82
+ export async function generatePresignedUrls(requests, options = {}) {
83
+ return Promise.all(requests.map((request) => generatePresignedUrl(request, options)));
84
+ }
85
+ // =============================================================================
86
+ // URL Validation
87
+ // =============================================================================
88
+ /**
89
+ * Check if a URL is from this store's R2 storage
90
+ */
91
+ export function isR2Url(url, config) {
92
+ const resolvedConfig = config || requireMediaConfig();
93
+ return url.startsWith(resolvedConfig.publicUrl);
94
+ }
95
+ /**
96
+ * Validate that a URL belongs to this store's storage prefix
97
+ */
98
+ export function validateStoreUrl(url, config) {
99
+ const resolvedConfig = config || requireMediaConfig();
100
+ if (!isR2Url(url, resolvedConfig)) {
101
+ return false;
102
+ }
103
+ // Extract key from URL and check prefix
104
+ const baseUrl = resolvedConfig.publicUrl.endsWith('/')
105
+ ? resolvedConfig.publicUrl.slice(0, -1)
106
+ : resolvedConfig.publicUrl;
107
+ const key = url.slice(baseUrl.length + 1);
108
+ // Key should start with stores/{storeId}/
109
+ const expectedPrefix = `stores/${resolvedConfig.storeId}/`;
110
+ return key.startsWith(expectedPrefix);
111
+ }
112
+ //# sourceMappingURL=presign.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presign.js","sourceRoot":"","sources":["../../../src/media/server/presign.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @rovela-ai/sdk/media/server/r2-client
3
+ *
4
+ * S3-compatible client for Cloudflare R2 storage.
5
+ * Server-side only - do not import in client components.
6
+ */
7
+ import { S3Client } from '@aws-sdk/client-s3';
8
+ import type { MediaStorageConfig } from '../types';
9
+ /**
10
+ * Get or create the S3 client for R2.
11
+ * Caches the client instance for reuse.
12
+ */
13
+ export declare function getR2Client(config?: MediaStorageConfig): S3Client;
14
+ /**
15
+ * Clear the cached client (useful for testing)
16
+ */
17
+ export declare function clearR2ClientCache(): void;
18
+ /**
19
+ * Get the configured bucket name
20
+ */
21
+ export declare function getBucketName(config?: MediaStorageConfig): string;
22
+ /**
23
+ * Get the public URL base for the bucket
24
+ */
25
+ export declare function getPublicUrlBase(config?: MediaStorageConfig): string;
26
+ /**
27
+ * Get the store ID for path prefixing
28
+ */
29
+ export declare function getStoreId(config?: MediaStorageConfig): string;
30
+ //# sourceMappingURL=r2-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"r2-client.d.ts","sourceRoot":"","sources":["../../../src/media/server/r2-client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAoBlD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,QAAQ,CAsBjE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAGzC;AAMD;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,MAAM,CAGjE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,MAAM,CAGpE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,MAAM,CAG9D"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * @rovela-ai/sdk/media/server/r2-client
3
+ *
4
+ * S3-compatible client for Cloudflare R2 storage.
5
+ * Server-side only - do not import in client components.
6
+ */
7
+ import { S3Client } from '@aws-sdk/client-s3';
8
+ import { requireMediaConfig } from '../config';
9
+ // =============================================================================
10
+ // Client Instance Management
11
+ // =============================================================================
12
+ /** Cached S3 client instance */
13
+ let cachedClient = null;
14
+ /** Cached config used to create the client */
15
+ let cachedConfigHash = null;
16
+ /**
17
+ * Create a hash of the config for cache invalidation
18
+ */
19
+ function hashConfig(config) {
20
+ return `${config.accountId}:${config.bucketName}:${config.accessKeyId.slice(0, 8)}`;
21
+ }
22
+ /**
23
+ * Get or create the S3 client for R2.
24
+ * Caches the client instance for reuse.
25
+ */
26
+ export function getR2Client(config) {
27
+ const resolvedConfig = config || requireMediaConfig();
28
+ const configHash = hashConfig(resolvedConfig);
29
+ // Return cached client if config hasn't changed
30
+ if (cachedClient && cachedConfigHash === configHash) {
31
+ return cachedClient;
32
+ }
33
+ // Create new client
34
+ cachedClient = new S3Client({
35
+ region: 'auto',
36
+ endpoint: `https://${resolvedConfig.accountId}.r2.cloudflarestorage.com`,
37
+ credentials: {
38
+ accessKeyId: resolvedConfig.accessKeyId,
39
+ secretAccessKey: resolvedConfig.secretAccessKey,
40
+ },
41
+ });
42
+ cachedConfigHash = configHash;
43
+ return cachedClient;
44
+ }
45
+ /**
46
+ * Clear the cached client (useful for testing)
47
+ */
48
+ export function clearR2ClientCache() {
49
+ cachedClient = null;
50
+ cachedConfigHash = null;
51
+ }
52
+ // =============================================================================
53
+ // Bucket Operations
54
+ // =============================================================================
55
+ /**
56
+ * Get the configured bucket name
57
+ */
58
+ export function getBucketName(config) {
59
+ const resolvedConfig = config || requireMediaConfig();
60
+ return resolvedConfig.bucketName;
61
+ }
62
+ /**
63
+ * Get the public URL base for the bucket
64
+ */
65
+ export function getPublicUrlBase(config) {
66
+ const resolvedConfig = config || requireMediaConfig();
67
+ return resolvedConfig.publicUrl;
68
+ }
69
+ /**
70
+ * Get the store ID for path prefixing
71
+ */
72
+ export function getStoreId(config) {
73
+ const resolvedConfig = config || requireMediaConfig();
74
+ return resolvedConfig.storeId;
75
+ }
76
+ //# sourceMappingURL=r2-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"r2-client.js","sourceRoot":"","sources":["../../../src/media/server/r2-client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAE7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAE9C,gFAAgF;AAChF,6BAA6B;AAC7B,gFAAgF;AAEhF,gCAAgC;AAChC,IAAI,YAAY,GAAoB,IAAI,CAAA;AAExC,8CAA8C;AAC9C,IAAI,gBAAgB,GAAkB,IAAI,CAAA;AAE1C;;GAEG;AACH,SAAS,UAAU,CAAC,MAA0B;IAC5C,OAAO,GAAG,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAA;AACrF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,MAA2B;IACrD,MAAM,cAAc,GAAG,MAAM,IAAI,kBAAkB,EAAE,CAAA;IACrD,MAAM,UAAU,GAAG,UAAU,CAAC,cAAc,CAAC,CAAA;IAE7C,gDAAgD;IAChD,IAAI,YAAY,IAAI,gBAAgB,KAAK,UAAU,EAAE,CAAC;QACpD,OAAO,YAAY,CAAA;IACrB,CAAC;IAED,oBAAoB;IACpB,YAAY,GAAG,IAAI,QAAQ,CAAC;QAC1B,MAAM,EAAE,MAAM;QACd,QAAQ,EAAE,WAAW,cAAc,CAAC,SAAS,2BAA2B;QACxE,WAAW,EAAE;YACX,WAAW,EAAE,cAAc,CAAC,WAAW;YACvC,eAAe,EAAE,cAAc,CAAC,eAAe;SAChD;KACF,CAAC,CAAA;IAEF,gBAAgB,GAAG,UAAU,CAAA;IAE7B,OAAO,YAAY,CAAA;AACrB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,YAAY,GAAG,IAAI,CAAA;IACnB,gBAAgB,GAAG,IAAI,CAAA;AACzB,CAAC;AAED,gFAAgF;AAChF,oBAAoB;AACpB,gFAAgF;AAEhF;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,MAA2B;IACvD,MAAM,cAAc,GAAG,MAAM,IAAI,kBAAkB,EAAE,CAAA;IACrD,OAAO,cAAc,CAAC,UAAU,CAAA;AAClC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAA2B;IAC1D,MAAM,cAAc,GAAG,MAAM,IAAI,kBAAkB,EAAE,CAAA;IACrD,OAAO,cAAc,CAAC,SAAS,CAAA;AACjC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,MAA2B;IACpD,MAAM,cAAc,GAAG,MAAM,IAAI,kBAAkB,EAAE,CAAA;IACrD,OAAO,cAAc,CAAC,OAAO,CAAA;AAC/B,CAAC"}