@opensaas/stack-storage 0.1.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.
Files changed (61) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/CHANGELOG.md +11 -0
  3. package/CLAUDE.md +426 -0
  4. package/LICENSE +21 -0
  5. package/README.md +425 -0
  6. package/dist/config/index.d.ts +19 -0
  7. package/dist/config/index.d.ts.map +1 -0
  8. package/dist/config/index.js +25 -0
  9. package/dist/config/index.js.map +1 -0
  10. package/dist/config/types.d.ts +113 -0
  11. package/dist/config/types.d.ts.map +1 -0
  12. package/dist/config/types.js +2 -0
  13. package/dist/config/types.js.map +1 -0
  14. package/dist/fields/index.d.ts +111 -0
  15. package/dist/fields/index.d.ts.map +1 -0
  16. package/dist/fields/index.js +237 -0
  17. package/dist/fields/index.js.map +1 -0
  18. package/dist/index.d.ts +6 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +11 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/providers/index.d.ts +2 -0
  23. package/dist/providers/index.d.ts.map +1 -0
  24. package/dist/providers/index.js +2 -0
  25. package/dist/providers/index.js.map +1 -0
  26. package/dist/providers/local.d.ts +22 -0
  27. package/dist/providers/local.d.ts.map +1 -0
  28. package/dist/providers/local.js +64 -0
  29. package/dist/providers/local.js.map +1 -0
  30. package/dist/runtime/index.d.ts +75 -0
  31. package/dist/runtime/index.d.ts.map +1 -0
  32. package/dist/runtime/index.js +157 -0
  33. package/dist/runtime/index.js.map +1 -0
  34. package/dist/utils/image.d.ts +18 -0
  35. package/dist/utils/image.d.ts.map +1 -0
  36. package/dist/utils/image.js +82 -0
  37. package/dist/utils/image.js.map +1 -0
  38. package/dist/utils/index.d.ts +3 -0
  39. package/dist/utils/index.d.ts.map +1 -0
  40. package/dist/utils/index.js +3 -0
  41. package/dist/utils/index.js.map +1 -0
  42. package/dist/utils/upload.d.ts +56 -0
  43. package/dist/utils/upload.d.ts.map +1 -0
  44. package/dist/utils/upload.js +74 -0
  45. package/dist/utils/upload.js.map +1 -0
  46. package/package.json +50 -0
  47. package/src/config/index.ts +30 -0
  48. package/src/config/types.ts +127 -0
  49. package/src/fields/index.ts +347 -0
  50. package/src/index.ts +14 -0
  51. package/src/providers/index.ts +1 -0
  52. package/src/providers/local.ts +85 -0
  53. package/src/runtime/index.ts +243 -0
  54. package/src/utils/image.ts +111 -0
  55. package/src/utils/index.ts +2 -0
  56. package/src/utils/upload.ts +122 -0
  57. package/tests/image-utils.test.ts +498 -0
  58. package/tests/local-provider.test.ts +349 -0
  59. package/tests/upload-utils.test.ts +313 -0
  60. package/tsconfig.json +9 -0
  61. package/vitest.config.ts +14 -0
@@ -0,0 +1,111 @@
1
+ import type { BaseFieldConfig } from '@opensaas/stack-core';
2
+ import type { ComponentType } from 'react';
3
+ import type { FileMetadata, ImageMetadata, ImageTransformationConfig } from '../config/types.js';
4
+ import type { FileValidationOptions } from '../utils/upload.js';
5
+ /**
6
+ * File field configuration
7
+ */
8
+ export interface FileFieldConfig extends BaseFieldConfig<FileMetadata | null, FileMetadata | null> {
9
+ type: 'file';
10
+ /** Name of the storage provider from config.storage */
11
+ storage: string;
12
+ /** File validation options */
13
+ validation?: FileValidationOptions;
14
+ /** Automatically delete file from storage when record is deleted */
15
+ cleanupOnDelete?: boolean;
16
+ /** Automatically delete old file from storage when replaced with new file */
17
+ cleanupOnReplace?: boolean;
18
+ /** UI options */
19
+ ui?: {
20
+ /** Custom component to use for rendering this field */
21
+ component?: ComponentType<unknown>;
22
+ /** Custom field type name for component registry lookup */
23
+ fieldType?: string;
24
+ /** Label for the field */
25
+ label?: string;
26
+ /** Help text shown below the field */
27
+ helpText?: string;
28
+ /** Placeholder text */
29
+ placeholder?: string;
30
+ /** Additional UI options passed through to component */
31
+ [key: string]: unknown;
32
+ };
33
+ }
34
+ /**
35
+ * Image field configuration
36
+ */
37
+ export interface ImageFieldConfig extends BaseFieldConfig<ImageMetadata | null, ImageMetadata | null> {
38
+ type: 'image';
39
+ /** Name of the storage provider from config.storage */
40
+ storage: string;
41
+ /** Image transformations to generate on upload */
42
+ transformations?: Record<string, ImageTransformationConfig>;
43
+ /** File validation options */
44
+ validation?: FileValidationOptions;
45
+ /** Automatically delete file from storage when record is deleted */
46
+ cleanupOnDelete?: boolean;
47
+ /** Automatically delete old file from storage when replaced with new file */
48
+ cleanupOnReplace?: boolean;
49
+ /** UI options */
50
+ ui?: {
51
+ /** Custom component to use for rendering this field */
52
+ component?: ComponentType<unknown>;
53
+ /** Custom field type name for component registry lookup */
54
+ fieldType?: string;
55
+ /** Label for the field */
56
+ label?: string;
57
+ /** Help text shown below the field */
58
+ helpText?: string;
59
+ /** Placeholder text */
60
+ placeholder?: string;
61
+ /** Show image preview */
62
+ showPreview?: boolean;
63
+ /** Preview size (width in pixels) */
64
+ previewSize?: number;
65
+ /** Additional UI options passed through to component */
66
+ [key: string]: unknown;
67
+ };
68
+ }
69
+ /**
70
+ * Creates a file upload field
71
+ *
72
+ * Uses JSON field backing to store file metadata including filename, URL, size, MIME type, etc.
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * fields: {
77
+ * resume: file({
78
+ * storage: 'documents',
79
+ * validation: {
80
+ * maxFileSize: 10 * 1024 * 1024, // 10MB
81
+ * acceptedMimeTypes: ['application/pdf']
82
+ * }
83
+ * })
84
+ * }
85
+ * ```
86
+ */
87
+ export declare function file(options: Omit<FileFieldConfig, 'type'>): FileFieldConfig;
88
+ /**
89
+ * Creates an image upload field with optional transformations
90
+ *
91
+ * Uses JSON field backing to store image metadata including dimensions, transformations, etc.
92
+ *
93
+ * @example
94
+ * ```typescript
95
+ * fields: {
96
+ * avatar: image({
97
+ * storage: 'avatars',
98
+ * transformations: {
99
+ * thumbnail: { width: 100, height: 100, fit: 'cover' },
100
+ * profile: { width: 400, height: 400, fit: 'cover' }
101
+ * },
102
+ * validation: {
103
+ * maxFileSize: 5 * 1024 * 1024, // 5MB
104
+ * acceptedMimeTypes: ['image/jpeg', 'image/png', 'image/webp']
105
+ * }
106
+ * })
107
+ * }
108
+ * ```
109
+ */
110
+ export declare function image(options: Omit<ImageFieldConfig, 'type'>): ImageFieldConfig;
111
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fields/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAE3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAA;AAChG,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAE/D;;GAEG;AACH,MAAM,WAAW,eAAgB,SAAQ,eAAe,CAAC,YAAY,GAAG,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;IAChG,IAAI,EAAE,MAAM,CAAA;IACZ,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAA;IACf,8BAA8B;IAC9B,UAAU,CAAC,EAAE,qBAAqB,CAAA;IAClC,oEAAoE;IACpE,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,iBAAiB;IACjB,EAAE,CAAC,EAAE;QACH,uDAAuD;QACvD,SAAS,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAA;QAClC,2DAA2D;QAC3D,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,0BAA0B;QAC1B,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,sCAAsC;QACtC,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,uBAAuB;QACvB,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,wDAAwD;QACxD,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KACvB,CAAA;CACF;AAED;;GAEG;AACH,MAAM,WAAW,gBACf,SAAQ,eAAe,CAAC,aAAa,GAAG,IAAI,EAAE,aAAa,GAAG,IAAI,CAAC;IACnE,IAAI,EAAE,OAAO,CAAA;IACb,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAA;IACf,kDAAkD;IAClD,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAA;IAC3D,8BAA8B;IAC9B,UAAU,CAAC,EAAE,qBAAqB,CAAA;IAClC,oEAAoE;IACpE,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,iBAAiB;IACjB,EAAE,CAAC,EAAE;QACH,uDAAuD;QACvD,SAAS,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAA;QAClC,2DAA2D;QAC3D,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,0BAA0B;QAC1B,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,sCAAsC;QACtC,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,uBAAuB;QACvB,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,yBAAyB;QACzB,WAAW,CAAC,EAAE,OAAO,CAAA;QACrB,qCAAqC;QACrC,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,wDAAwD;QACxD,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KACvB,CAAA;CACF;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC,GAAG,eAAe,CAuG5E;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,MAAM,CAAC,GAAG,gBAAgB,CAgI/E"}
@@ -0,0 +1,237 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Creates a file upload field
4
+ *
5
+ * Uses JSON field backing to store file metadata including filename, URL, size, MIME type, etc.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * fields: {
10
+ * resume: file({
11
+ * storage: 'documents',
12
+ * validation: {
13
+ * maxFileSize: 10 * 1024 * 1024, // 10MB
14
+ * acceptedMimeTypes: ['application/pdf']
15
+ * }
16
+ * })
17
+ * }
18
+ * ```
19
+ */
20
+ export function file(options) {
21
+ const fieldConfig = {
22
+ type: 'file',
23
+ ...options,
24
+ hooks: {
25
+ resolveInput: async ({ inputValue, context, item, fieldName }) => {
26
+ // If null/undefined, return as-is (deletion or no change)
27
+ if (inputValue === null || inputValue === undefined) {
28
+ return inputValue;
29
+ }
30
+ // If already FileMetadata, keep existing (edit mode - no new file uploaded)
31
+ if (typeof inputValue === 'object' && 'filename' in inputValue && 'url' in inputValue) {
32
+ return inputValue;
33
+ }
34
+ // If File object, upload it
35
+ // Check if it's a File-like object (has arrayBuffer method)
36
+ if (typeof inputValue === 'object' &&
37
+ 'arrayBuffer' in inputValue &&
38
+ typeof inputValue.arrayBuffer === 'function') {
39
+ // Convert File to buffer
40
+ const fileObj = inputValue;
41
+ const arrayBuffer = await fileObj.arrayBuffer();
42
+ const buffer = Buffer.from(arrayBuffer);
43
+ // Upload file using context.storage utilities
44
+ const metadata = (await context.storage.uploadFile(fieldConfig.storage, fileObj, buffer, {
45
+ validation: fieldConfig.validation,
46
+ }));
47
+ // If cleanupOnReplace is enabled and there was an old file, delete it
48
+ if (fieldConfig.cleanupOnReplace && item && fieldName) {
49
+ const oldMetadata = item[fieldName];
50
+ if (oldMetadata && oldMetadata.filename) {
51
+ try {
52
+ await context.storage.deleteFile(oldMetadata.storageProvider, oldMetadata.filename);
53
+ }
54
+ catch (error) {
55
+ // Log error but don't fail the operation
56
+ console.error(`Failed to cleanup old file: ${oldMetadata.filename}`, error);
57
+ }
58
+ }
59
+ }
60
+ return metadata;
61
+ }
62
+ // Unknown type - return as-is and let validation catch it
63
+ return inputValue;
64
+ },
65
+ afterOperation: async ({ operation, item, fieldName, context }) => {
66
+ // Only cleanup on delete if enabled
67
+ if (operation === 'delete' && fieldConfig.cleanupOnDelete) {
68
+ const fileMetadata = item[fieldName];
69
+ if (fileMetadata && fileMetadata.filename) {
70
+ try {
71
+ await context.storage.deleteFile(fileMetadata.storageProvider, fileMetadata.filename);
72
+ }
73
+ catch (error) {
74
+ // Log error but don't fail the operation
75
+ console.error(`Failed to cleanup file on delete: ${fileMetadata.filename}`, error);
76
+ }
77
+ }
78
+ }
79
+ },
80
+ },
81
+ getZodSchema: (_fieldName, _operation) => {
82
+ // File metadata follows the FileMetadata schema
83
+ const fileMetadataSchema = z.object({
84
+ filename: z.string(),
85
+ originalFilename: z.string(),
86
+ url: z.string(), // Accept both absolute URLs and relative paths
87
+ mimeType: z.string(),
88
+ size: z.number(),
89
+ uploadedAt: z.string(),
90
+ storageProvider: z.string(),
91
+ metadata: z.record(z.string(), z.unknown()).optional(),
92
+ });
93
+ // Allow null or undefined values
94
+ return z.union([fileMetadataSchema, z.null(), z.undefined()]);
95
+ },
96
+ getPrismaType: (_fieldName) => {
97
+ // Store as JSON in database
98
+ return { type: 'Json', modifiers: '?' };
99
+ },
100
+ getTypeScriptType: () => {
101
+ // TypeScript type is FileMetadata | null
102
+ return {
103
+ type: 'import("@opensaas/stack-storage").FileMetadata | null',
104
+ optional: true,
105
+ };
106
+ },
107
+ };
108
+ return fieldConfig;
109
+ }
110
+ /**
111
+ * Creates an image upload field with optional transformations
112
+ *
113
+ * Uses JSON field backing to store image metadata including dimensions, transformations, etc.
114
+ *
115
+ * @example
116
+ * ```typescript
117
+ * fields: {
118
+ * avatar: image({
119
+ * storage: 'avatars',
120
+ * transformations: {
121
+ * thumbnail: { width: 100, height: 100, fit: 'cover' },
122
+ * profile: { width: 400, height: 400, fit: 'cover' }
123
+ * },
124
+ * validation: {
125
+ * maxFileSize: 5 * 1024 * 1024, // 5MB
126
+ * acceptedMimeTypes: ['image/jpeg', 'image/png', 'image/webp']
127
+ * }
128
+ * })
129
+ * }
130
+ * ```
131
+ */
132
+ export function image(options) {
133
+ const fieldConfig = {
134
+ type: 'image',
135
+ ...options,
136
+ hooks: {
137
+ resolveInput: async ({ inputValue, context, item, fieldName }) => {
138
+ // If null/undefined, return as-is (deletion or no change)
139
+ if (inputValue === null || inputValue === undefined) {
140
+ return inputValue;
141
+ }
142
+ // If already ImageMetadata, keep existing (edit mode - no new file uploaded)
143
+ if (typeof inputValue === 'object' &&
144
+ 'filename' in inputValue &&
145
+ 'url' in inputValue &&
146
+ 'width' in inputValue &&
147
+ 'height' in inputValue) {
148
+ return inputValue;
149
+ }
150
+ // If File object, upload it
151
+ // Check if it's a File-like object (has arrayBuffer method)
152
+ if (typeof inputValue === 'object' &&
153
+ 'arrayBuffer' in inputValue &&
154
+ typeof inputValue.arrayBuffer === 'function') {
155
+ // Convert File to buffer
156
+ const fileObj = inputValue;
157
+ const arrayBuffer = await fileObj.arrayBuffer();
158
+ const buffer = Buffer.from(arrayBuffer);
159
+ // Upload image using context.storage utilities
160
+ const metadata = (await context.storage.uploadImage(fieldConfig.storage, fileObj, buffer, {
161
+ validation: fieldConfig.validation,
162
+ transformations: fieldConfig.transformations,
163
+ }));
164
+ // If cleanupOnReplace is enabled and there was an old file, delete it
165
+ if (fieldConfig.cleanupOnReplace && item && fieldName) {
166
+ const oldMetadata = item[fieldName];
167
+ if (oldMetadata && oldMetadata.filename) {
168
+ try {
169
+ await context.storage.deleteImage(oldMetadata);
170
+ }
171
+ catch (error) {
172
+ // Log error but don't fail the operation
173
+ console.error(`Failed to cleanup old image: ${oldMetadata.filename}`, error);
174
+ }
175
+ }
176
+ }
177
+ return metadata;
178
+ }
179
+ // Unknown type - return as-is and let validation catch it
180
+ return inputValue;
181
+ },
182
+ afterOperation: async ({ operation, item, fieldName, context }) => {
183
+ // Only cleanup on delete if enabled
184
+ if (operation === 'delete' && fieldConfig.cleanupOnDelete) {
185
+ const imageMetadata = item[fieldName];
186
+ if (imageMetadata && imageMetadata.filename) {
187
+ try {
188
+ await context.storage.deleteImage(imageMetadata);
189
+ }
190
+ catch (error) {
191
+ // Log error but don't fail the operation
192
+ console.error(`Failed to cleanup image on delete: ${imageMetadata.filename}`, error);
193
+ }
194
+ }
195
+ }
196
+ },
197
+ },
198
+ getZodSchema: (_fieldName, _operation) => {
199
+ // Image metadata follows the ImageMetadata schema (extends FileMetadata)
200
+ const imageMetadataSchema = z.object({
201
+ filename: z.string(),
202
+ originalFilename: z.string(),
203
+ url: z.string(), // Accept both absolute URLs and relative paths
204
+ mimeType: z.string(),
205
+ size: z.number(),
206
+ width: z.number(),
207
+ height: z.number(),
208
+ uploadedAt: z.string(),
209
+ storageProvider: z.string(),
210
+ metadata: z.record(z.string(), z.unknown()).optional(),
211
+ transformations: z
212
+ .record(z.string(), z.object({
213
+ url: z.string(), // Accept both absolute URLs and relative paths
214
+ width: z.number(),
215
+ height: z.number(),
216
+ size: z.number(),
217
+ }))
218
+ .optional(),
219
+ });
220
+ // Allow null or undefined values
221
+ return z.union([imageMetadataSchema, z.null(), z.undefined()]);
222
+ },
223
+ getPrismaType: (_fieldName) => {
224
+ // Store as JSON in database
225
+ return { type: 'Json', modifiers: '?' };
226
+ },
227
+ getTypeScriptType: () => {
228
+ // TypeScript type is ImageMetadata | null
229
+ return {
230
+ type: 'import("@opensaas/stack-storage").ImageMetadata | null',
231
+ optional: true,
232
+ };
233
+ },
234
+ };
235
+ return fieldConfig;
236
+ }
237
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/fields/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAwEvB;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,IAAI,CAAC,OAAsC;IACzD,MAAM,WAAW,GAAoB;QACnC,IAAI,EAAE,MAAM;QACZ,GAAG,OAAO;QAEV,KAAK,EAAE;YACL,YAAY,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE;gBAC/D,0DAA0D;gBAC1D,IAAI,UAAU,KAAK,IAAI,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;oBACpD,OAAO,UAAU,CAAA;gBACnB,CAAC;gBAED,4EAA4E;gBAC5E,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,IAAI,UAAU,IAAI,KAAK,IAAI,UAAU,EAAE,CAAC;oBACtF,OAAO,UAA0B,CAAA;gBACnC,CAAC;gBAED,4BAA4B;gBAC5B,4DAA4D;gBAC5D,IACE,OAAO,UAAU,KAAK,QAAQ;oBAC9B,aAAa,IAAI,UAAU;oBAC3B,OAAQ,UAAwC,CAAC,WAAW,KAAK,UAAU,EAC3E,CAAC;oBACD,yBAAyB;oBACzB,MAAM,OAAO,GAAG,UAAkB,CAAA;oBAClC,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE,CAAA;oBAC/C,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;oBAEvC,8CAA8C;oBAC9C,MAAM,QAAQ,GAAG,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE;wBACvF,UAAU,EAAE,WAAW,CAAC,UAAU;qBACnC,CAAC,CAAiB,CAAA;oBAEnB,sEAAsE;oBACtE,IAAI,WAAW,CAAC,gBAAgB,IAAI,IAAI,IAAI,SAAS,EAAE,CAAC;wBACtD,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAwB,CAAA;wBAC1D,IAAI,WAAW,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;4BACxC,IAAI,CAAC;gCACH,MAAM,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,eAAe,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAA;4BACrF,CAAC;4BAAC,OAAO,KAAK,EAAE,CAAC;gCACf,yCAAyC;gCACzC,OAAO,CAAC,KAAK,CAAC,+BAA+B,WAAW,CAAC,QAAQ,EAAE,EAAE,KAAK,CAAC,CAAA;4BAC7E,CAAC;wBACH,CAAC;oBACH,CAAC;oBAED,OAAO,QAAQ,CAAA;gBACjB,CAAC;gBAED,0DAA0D;gBAC1D,OAAO,UAAU,CAAA;YACnB,CAAC;YAED,cAAc,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,EAAE;gBAChE,oCAAoC;gBACpC,IAAI,SAAS,KAAK,QAAQ,IAAI,WAAW,CAAC,eAAe,EAAE,CAAC;oBAC1D,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAwB,CAAA;oBAE3D,IAAI,YAAY,IAAI,YAAY,CAAC,QAAQ,EAAE,CAAC;wBAC1C,IAAI,CAAC;4BACH,MAAM,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,eAAe,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;wBACvF,CAAC;wBAAC,OAAO,KAAK,EAAE,CAAC;4BACf,yCAAyC;4BACzC,OAAO,CAAC,KAAK,CAAC,qCAAqC,YAAY,CAAC,QAAQ,EAAE,EAAE,KAAK,CAAC,CAAA;wBACpF,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;SACF;QAED,YAAY,EAAE,CAAC,UAAkB,EAAE,UAA+B,EAAE,EAAE;YACpE,gDAAgD;YAChD,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;gBAClC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;gBACpB,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE;gBAC5B,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,+CAA+C;gBAChE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;gBACpB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;gBAChB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;gBACtB,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE;gBAC3B,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE;aACvD,CAAC,CAAA;YAEF,iCAAiC;YACjC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,kBAAkB,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAA;QAC/D,CAAC;QAED,aAAa,EAAE,CAAC,UAAkB,EAAE,EAAE;YACpC,4BAA4B;YAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,CAAA;QACzC,CAAC;QAED,iBAAiB,EAAE,GAAG,EAAE;YACtB,yCAAyC;YACzC,OAAO;gBACL,IAAI,EAAE,uDAAuD;gBAC7D,QAAQ,EAAE,IAAI;aACf,CAAA;QACH,CAAC;KACF,CAAA;IAED,OAAO,WAAW,CAAA;AACpB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,KAAK,CAAC,OAAuC;IAC3D,MAAM,WAAW,GAAqB;QACpC,IAAI,EAAE,OAAO;QACb,GAAG,OAAO;QAEV,KAAK,EAAE;YACL,YAAY,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE;gBAC/D,0DAA0D;gBAC1D,IAAI,UAAU,KAAK,IAAI,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;oBACpD,OAAO,UAAU,CAAA;gBACnB,CAAC;gBAED,6EAA6E;gBAC7E,IACE,OAAO,UAAU,KAAK,QAAQ;oBAC9B,UAAU,IAAI,UAAU;oBACxB,KAAK,IAAI,UAAU;oBACnB,OAAO,IAAI,UAAU;oBACrB,QAAQ,IAAI,UAAU,EACtB,CAAC;oBACD,OAAO,UAA2B,CAAA;gBACpC,CAAC;gBAED,4BAA4B;gBAC5B,4DAA4D;gBAC5D,IACE,OAAO,UAAU,KAAK,QAAQ;oBAC9B,aAAa,IAAI,UAAU;oBAC3B,OAAQ,UAAwC,CAAC,WAAW,KAAK,UAAU,EAC3E,CAAC;oBACD,yBAAyB;oBACzB,MAAM,OAAO,GAAG,UAAkB,CAAA;oBAClC,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE,CAAA;oBAC/C,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;oBAEvC,+CAA+C;oBAC/C,MAAM,QAAQ,GAAG,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC,WAAW,CACjD,WAAW,CAAC,OAAO,EACnB,OAAO,EACP,MAAM,EACN;wBACE,UAAU,EAAE,WAAW,CAAC,UAAU;wBAClC,eAAe,EAAE,WAAW,CAAC,eAAe;qBAC7C,CACF,CAAkB,CAAA;oBAEnB,sEAAsE;oBACtE,IAAI,WAAW,CAAC,gBAAgB,IAAI,IAAI,IAAI,SAAS,EAAE,CAAC;wBACtD,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAyB,CAAA;wBAC3D,IAAI,WAAW,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;4BACxC,IAAI,CAAC;gCACH,MAAM,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,CAAA;4BAChD,CAAC;4BAAC,OAAO,KAAK,EAAE,CAAC;gCACf,yCAAyC;gCACzC,OAAO,CAAC,KAAK,CAAC,gCAAgC,WAAW,CAAC,QAAQ,EAAE,EAAE,KAAK,CAAC,CAAA;4BAC9E,CAAC;wBACH,CAAC;oBACH,CAAC;oBAED,OAAO,QAAQ,CAAA;gBACjB,CAAC;gBAED,0DAA0D;gBAC1D,OAAO,UAAU,CAAA;YACnB,CAAC;YAED,cAAc,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,EAAE;gBAChE,oCAAoC;gBACpC,IAAI,SAAS,KAAK,QAAQ,IAAI,WAAW,CAAC,eAAe,EAAE,CAAC;oBAC1D,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAyB,CAAA;oBAE7D,IAAI,aAAa,IAAI,aAAa,CAAC,QAAQ,EAAE,CAAC;wBAC5C,IAAI,CAAC;4BACH,MAAM,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,aAAa,CAAC,CAAA;wBAClD,CAAC;wBAAC,OAAO,KAAK,EAAE,CAAC;4BACf,yCAAyC;4BACzC,OAAO,CAAC,KAAK,CAAC,sCAAsC,aAAa,CAAC,QAAQ,EAAE,EAAE,KAAK,CAAC,CAAA;wBACtF,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;SACF;QAED,YAAY,EAAE,CAAC,UAAkB,EAAE,UAA+B,EAAE,EAAE;YACpE,yEAAyE;YACzE,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;gBACnC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;gBACpB,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE;gBAC5B,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,+CAA+C;gBAChE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;gBACpB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;gBAChB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;gBACjB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;gBAClB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;gBACtB,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE;gBAC3B,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE;gBACtD,eAAe,EAAE,CAAC;qBACf,MAAM,CACL,CAAC,CAAC,MAAM,EAAE,EACV,CAAC,CAAC,MAAM,CAAC;oBACP,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,+CAA+C;oBAChE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;oBACjB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;oBAClB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;iBACjB,CAAC,CACH;qBACA,QAAQ,EAAE;aACd,CAAC,CAAA;YAEF,iCAAiC;YACjC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,mBAAmB,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAA;QAChE,CAAC;QAED,aAAa,EAAE,CAAC,UAAkB,EAAE,EAAE;YACpC,4BAA4B;YAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,CAAA;QACzC,CAAC;QAED,iBAAiB,EAAE,GAAG,EAAE;YACtB,0CAA0C;YAC1C,OAAO;gBACL,IAAI,EAAE,wDAAwD;gBAC9D,QAAQ,EAAE,IAAI;aACf,CAAA;QACH,CAAC;KACF,CAAA;IAED,OAAO,WAAW,CAAA;AACpB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export * from './config/index.js';
2
+ export * from './fields/index.js';
3
+ export * from './providers/index.js';
4
+ export * from './runtime/index.js';
5
+ export * from './utils/index.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,mBAAmB,CAAA;AAGjC,cAAc,mBAAmB,CAAA;AAGjC,cAAc,sBAAsB,CAAA;AAGpC,cAAc,oBAAoB,CAAA;AAGlC,cAAc,kBAAkB,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ // Config and types
2
+ export * from './config/index.js';
3
+ // Field builders
4
+ export * from './fields/index.js';
5
+ // Storage providers
6
+ export * from './providers/index.js';
7
+ // Runtime utilities
8
+ export * from './runtime/index.js';
9
+ // Upload utilities
10
+ export * from './utils/index.js';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mBAAmB;AACnB,cAAc,mBAAmB,CAAA;AAEjC,iBAAiB;AACjB,cAAc,mBAAmB,CAAA;AAEjC,oBAAoB;AACpB,cAAc,sBAAsB,CAAA;AAEpC,oBAAoB;AACpB,cAAc,oBAAoB,CAAA;AAElC,mBAAmB;AACnB,cAAc,kBAAkB,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { LocalStorageProvider } from './local.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { LocalStorageProvider } from './local.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA"}
@@ -0,0 +1,22 @@
1
+ import type { StorageProvider, UploadOptions, UploadResult, LocalStorageConfig } from '../config/types.js';
2
+ /**
3
+ * Local filesystem storage provider
4
+ * Stores files on the local filesystem
5
+ */
6
+ export declare class LocalStorageProvider implements StorageProvider {
7
+ private config;
8
+ constructor(config: LocalStorageConfig);
9
+ /**
10
+ * Ensures the upload directory exists
11
+ */
12
+ private ensureUploadDir;
13
+ /**
14
+ * Generates a unique filename if configured
15
+ */
16
+ private generateFilename;
17
+ upload(file: Buffer | Uint8Array, filename: string, options?: UploadOptions): Promise<UploadResult>;
18
+ download(filename: string): Promise<Buffer>;
19
+ delete(filename: string): Promise<void>;
20
+ getUrl(filename: string): string;
21
+ }
22
+ //# sourceMappingURL=local.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../src/providers/local.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,eAAe,EACf,aAAa,EACb,YAAY,EACZ,kBAAkB,EACnB,MAAM,oBAAoB,CAAA;AAE3B;;;GAGG;AACH,qBAAa,oBAAqB,YAAW,eAAe;IAC1D,OAAO,CAAC,MAAM,CAAoB;gBAEtB,MAAM,EAAE,kBAAkB;IAItC;;OAEG;YACW,eAAe;IAQ7B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAWlB,MAAM,CACV,IAAI,EAAE,MAAM,GAAG,UAAU,EACzB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,YAAY,CAAC;IAqBlB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAK3C,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK7C,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;CAGjC"}
@@ -0,0 +1,64 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { randomBytes } from 'node:crypto';
4
+ /**
5
+ * Local filesystem storage provider
6
+ * Stores files on the local filesystem
7
+ */
8
+ export class LocalStorageProvider {
9
+ config;
10
+ constructor(config) {
11
+ this.config = config;
12
+ }
13
+ /**
14
+ * Ensures the upload directory exists
15
+ */
16
+ async ensureUploadDir() {
17
+ try {
18
+ await fs.access(this.config.uploadDir);
19
+ }
20
+ catch {
21
+ await fs.mkdir(this.config.uploadDir, { recursive: true });
22
+ }
23
+ }
24
+ /**
25
+ * Generates a unique filename if configured
26
+ */
27
+ generateFilename(originalFilename) {
28
+ if (this.config.generateUniqueFilenames === false) {
29
+ return originalFilename;
30
+ }
31
+ const ext = path.extname(originalFilename);
32
+ const uniqueId = randomBytes(16).toString('hex');
33
+ const timestamp = Date.now();
34
+ return `${timestamp}-${uniqueId}${ext}`;
35
+ }
36
+ async upload(file, filename, options) {
37
+ await this.ensureUploadDir();
38
+ const generatedFilename = this.generateFilename(filename);
39
+ const filePath = path.join(this.config.uploadDir, generatedFilename);
40
+ // Write file to disk
41
+ await fs.writeFile(filePath, file);
42
+ // Get file stats for size
43
+ const stats = await fs.stat(filePath);
44
+ return {
45
+ filename: generatedFilename,
46
+ url: `${this.config.serveUrl}/${generatedFilename}`,
47
+ size: stats.size,
48
+ contentType: options?.contentType || 'application/octet-stream',
49
+ metadata: options?.metadata,
50
+ };
51
+ }
52
+ async download(filename) {
53
+ const filePath = path.join(this.config.uploadDir, filename);
54
+ return await fs.readFile(filePath);
55
+ }
56
+ async delete(filename) {
57
+ const filePath = path.join(this.config.uploadDir, filename);
58
+ await fs.unlink(filePath);
59
+ }
60
+ getUrl(filename) {
61
+ return `${this.config.serveUrl}/${filename}`;
62
+ }
63
+ }
64
+ //# sourceMappingURL=local.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local.js","sourceRoot":"","sources":["../../src/providers/local.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAA;AACjC,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAQzC;;;GAGG;AACH,MAAM,OAAO,oBAAoB;IACvB,MAAM,CAAoB;IAElC,YAAY,MAA0B;QACpC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;IACtB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,eAAe;QAC3B,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;QACxC,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAC5D,CAAC;IACH,CAAC;IAED;;OAEG;IACK,gBAAgB,CAAC,gBAAwB;QAC/C,IAAI,IAAI,CAAC,MAAM,CAAC,uBAAuB,KAAK,KAAK,EAAE,CAAC;YAClD,OAAO,gBAAgB,CAAA;QACzB,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAA;QAC1C,MAAM,QAAQ,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;QAChD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAC5B,OAAO,GAAG,SAAS,IAAI,QAAQ,GAAG,GAAG,EAAE,CAAA;IACzC,CAAC;IAED,KAAK,CAAC,MAAM,CACV,IAAyB,EACzB,QAAgB,EAChB,OAAuB;QAEvB,MAAM,IAAI,CAAC,eAAe,EAAE,CAAA;QAE5B,MAAM,iBAAiB,GAAG,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAA;QACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAA;QAEpE,qBAAqB;QACrB,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;QAElC,0BAA0B;QAC1B,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QAErC,OAAO;YACL,QAAQ,EAAE,iBAAiB;YAC3B,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,iBAAiB,EAAE;YACnD,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,WAAW,EAAE,OAAO,EAAE,WAAW,IAAI,0BAA0B;YAC/D,QAAQ,EAAE,OAAO,EAAE,QAAQ;SAC5B,CAAA;IACH,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,QAAgB;QAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;QAC3D,OAAO,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IACpC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,QAAgB;QAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;QAC3D,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IAC3B,CAAC;IAED,MAAM,CAAC,QAAgB;QACrB,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,QAAQ,EAAE,CAAA;IAC9C,CAAC;CACF"}
@@ -0,0 +1,75 @@
1
+ import type { OpenSaasConfig } from '@opensaas/stack-core';
2
+ import type { StorageProvider, FileMetadata, ImageMetadata, ImageTransformationConfig } from '../config/types.js';
3
+ import { type FileValidationOptions } from '../utils/upload.js';
4
+ /**
5
+ * Creates a storage provider instance from config
6
+ */
7
+ export declare function createStorageProvider(config: OpenSaasConfig, providerName: string): StorageProvider;
8
+ /**
9
+ * Options for uploading a file
10
+ */
11
+ export interface UploadFileOptions {
12
+ /** Validation options */
13
+ validation?: FileValidationOptions;
14
+ /** Custom metadata */
15
+ metadata?: Record<string, string>;
16
+ }
17
+ /**
18
+ * Options for uploading an image with transformations
19
+ */
20
+ export interface UploadImageOptions extends UploadFileOptions {
21
+ /** Image transformations to apply */
22
+ transformations?: Record<string, ImageTransformationConfig>;
23
+ }
24
+ /**
25
+ * Uploads a file to the specified storage provider
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * const metadata = await uploadFile(config, 'documents', {
30
+ * file,
31
+ * buffer,
32
+ * validation: {
33
+ * maxFileSize: 10 * 1024 * 1024, // 10MB
34
+ * acceptedMimeTypes: ['application/pdf']
35
+ * }
36
+ * })
37
+ * ```
38
+ */
39
+ export declare function uploadFile(config: OpenSaasConfig, storageProviderName: string, data: {
40
+ file: File;
41
+ buffer: Buffer;
42
+ }, options?: UploadFileOptions): Promise<FileMetadata>;
43
+ /**
44
+ * Uploads an image with optional transformations
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * const metadata = await uploadImage(config, 'avatars', {
49
+ * file,
50
+ * buffer,
51
+ * validation: {
52
+ * maxFileSize: 5 * 1024 * 1024, // 5MB
53
+ * acceptedMimeTypes: ['image/jpeg', 'image/png', 'image/webp']
54
+ * },
55
+ * transformations: {
56
+ * thumbnail: { width: 100, height: 100, fit: 'cover' },
57
+ * profile: { width: 400, height: 400, fit: 'cover' }
58
+ * }
59
+ * })
60
+ * ```
61
+ */
62
+ export declare function uploadImage(config: OpenSaasConfig, storageProviderName: string, data: {
63
+ file: File;
64
+ buffer: Buffer;
65
+ }, options?: UploadImageOptions): Promise<ImageMetadata>;
66
+ /**
67
+ * Deletes a file from storage
68
+ */
69
+ export declare function deleteFile(config: OpenSaasConfig, storageProviderName: string, filename: string): Promise<void>;
70
+ /**
71
+ * Deletes an image and all its transformations from storage
72
+ */
73
+ export declare function deleteImage(config: OpenSaasConfig, metadata: ImageMetadata): Promise<void>;
74
+ export { parseFileFromFormData } from '../utils/upload.js';
75
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,KAAK,EACV,eAAe,EAEf,YAAY,EACZ,aAAa,EACb,yBAAyB,EAC1B,MAAM,oBAAoB,CAAA;AAE3B,OAAO,EAA6B,KAAK,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAG1F;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,cAAc,EACtB,YAAY,EAAE,MAAM,GACnB,eAAe,CAajB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,yBAAyB;IACzB,UAAU,CAAC,EAAE,qBAAqB,CAAA;IAClC,sBAAsB;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC3D,qCAAqC;IACrC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAA;CAC5D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,cAAc,EACtB,mBAAmB,EAAE,MAAM,EAC3B,IAAI,EAAE;IACJ,IAAI,EAAE,IAAI,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;CACf,EACD,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,YAAY,CAAC,CA0CvB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,cAAc,EACtB,mBAAmB,EAAE,MAAM,EAC3B,IAAI,EAAE;IACJ,IAAI,EAAE,IAAI,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;CACf,EACD,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,aAAa,CAAC,CA8DxB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,cAAc,EACtB,mBAAmB,EAAE,MAAM,EAC3B,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAGf;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBhG;AAED,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA"}