@dcd-sdk/storage-client 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,101 @@
1
- # Temporary Holding Version
1
+ # @dcd-sdk/storage-client
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Official Node.js & TypeScript Client SDK for DevCloudDesk Storage Engine.
4
+
5
+ High-performance, Cloudinary-style on-the-fly media transformations and ultra-fast direct asset delivery backed by your DevCloudDesk storage clusters.
6
+
7
+ [![npm version](https://img.shields.io/npm/v/@dcd-sdk/storage-client?color=blue)](https://www.npmjs.com/package/@dcd-sdk/storage-client)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
+
10
+ ---
11
+
12
+ ## 📦 Installation
13
+
14
+ ```bash
15
+ # npm
16
+ npm install @dcd-sdk/storage-client
17
+
18
+ # pnpm
19
+ pnpm add @dcd-sdk/storage-client
20
+
21
+ # yarn
22
+ yarn add @dcd-sdk/storage-client
23
+ ```
24
+
25
+ ---
26
+
27
+ ## 🚀 Quickstart
28
+
29
+ ### 1. Initialize the Client
30
+
31
+ ```typescript
32
+ import { createBucketClient } from '@dcd-sdk/storage-client';
33
+
34
+ const bucket = createBucketClient({
35
+ endpoint: 'http://YOUR_SERVER_IP:7100', // or your custom domain https://storage.yourdomain.com
36
+ apiKey: process.env.STORAGE_API_KEY, // API Key from DevCloudDesk Dashboard
37
+ });
38
+ ```
39
+
40
+ ### 2. Uploading Files (Node.js or Browser)
41
+
42
+ ```typescript
43
+ // Upload from Buffer, File, or local file path
44
+ const asset = await bucket.upload(fileBuffer, {
45
+ folder: 'avatars',
46
+ filename: 'user-profile.png',
47
+ onProgress: (percent) => {
48
+ console.log(`Upload progress: ${percent}%`);
49
+ },
50
+ });
51
+
52
+ console.log('Public ID:', asset.publicId);
53
+ console.log('CDN URL:', asset.url);
54
+ ```
55
+
56
+ ### 3. Dynamic On-The-Fly Transformations
57
+
58
+ Generate real-time optimized WebP/AVIF images with automatic resizing:
59
+
60
+ ```typescript
61
+ const avatarUrl = bucket
62
+ .url(asset.publicId)
63
+ .resize({ width: 400, height: 400, crop: 'cover' })
64
+ .format('webp')
65
+ .quality(80)
66
+ .build();
67
+
68
+ // Output: http://YOUR_SERVER_IP:7100/v1/image/w_400,h_400,c_cover,f_webp,q_80/avatars/user-profile.png
69
+ ```
70
+
71
+ ### 4. Client-Side Uploads via Signed Tokens (Zero Secret Exposure)
72
+
73
+ Keep your master API keys safely on your backend server. Generate short-lived, tamper-proof signed upload tokens for your frontend React/Next.js/Mobile apps:
74
+
75
+ ```typescript
76
+ // Backend endpoint:
77
+ app.post('/api/get-upload-token', async (req, res) => {
78
+ const tokenData = await bucket.createSignedUploadToken({
79
+ folder: 'user-uploads',
80
+ expiresInSeconds: 300, // 5 minutes
81
+ maxBytes: 10 * 1024 * 1024, // 10 MB limit
82
+ });
83
+ res.json(tokenData);
84
+ });
85
+
86
+ // Frontend client:
87
+ const { token } = await res.json();
88
+ await bucket.uploadWithToken(file, token);
89
+ ```
90
+
91
+ ### 5. Deleting Files
92
+
93
+ ```typescript
94
+ await bucket.delete(asset.publicId);
95
+ ```
96
+
97
+ ---
98
+
99
+ ## 📄 License
100
+
101
+ MIT © [DevCloudDesk](https://devclouddesk.com)
@@ -0,0 +1,31 @@
1
+ import type { CropMode, OutputFormat } from './types.js';
2
+ export declare class TransformationBuilder {
3
+ private endpoint;
4
+ private publicId;
5
+ private options;
6
+ constructor(endpoint: string, publicId: string);
7
+ width(w: number): this;
8
+ height(h: number): this;
9
+ resize(params: {
10
+ width?: number;
11
+ height?: number;
12
+ crop?: CropMode;
13
+ }): this;
14
+ crop(mode: CropMode): this;
15
+ format(fmt: OutputFormat): this;
16
+ quality(q: number | 'auto'): this;
17
+ blur(sigma?: number): this;
18
+ grayscale(enable?: boolean): this;
19
+ sharpen(enable?: boolean): this;
20
+ rotation(rot: number | 'auto'): this;
21
+ /**
22
+ * Builds the formatted transformation string (e.g. w_400,h_300,c_fill,f_auto)
23
+ */
24
+ toParamsString(): string;
25
+ /**
26
+ * Returns the final full URL string
27
+ */
28
+ build(): string;
29
+ toString(): string;
30
+ }
31
+ //# sourceMappingURL=builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../src/builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAyB,MAAM,YAAY,CAAC;AAEhF,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAA6B;gBAEhC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAK9C,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAKtB,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAKvB,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,IAAI;IAO1E,IAAI,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI;IAK1B,MAAM,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI;IAK/B,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAKjC,IAAI,CAAC,KAAK,SAAI,GAAG,IAAI;IAKrB,SAAS,CAAC,MAAM,UAAO,GAAG,IAAI;IAK9B,OAAO,CAAC,MAAM,UAAO,GAAG,IAAI;IAK5B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAKpC;;OAEG;IACH,cAAc,IAAI,MAAM;IAgBxB;;OAEG;IACH,KAAK,IAAI,MAAM;IAQf,QAAQ,IAAI,MAAM;CAGnB"}
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TransformationBuilder = void 0;
4
+ class TransformationBuilder {
5
+ constructor(endpoint, publicId) {
6
+ this.options = {};
7
+ this.endpoint = endpoint.replace(/\/+$/, '');
8
+ this.publicId = publicId.replace(/^\/+/, '');
9
+ }
10
+ width(w) {
11
+ this.options.width = Math.round(w);
12
+ return this;
13
+ }
14
+ height(h) {
15
+ this.options.height = Math.round(h);
16
+ return this;
17
+ }
18
+ resize(params) {
19
+ if (params.width)
20
+ this.options.width = Math.round(params.width);
21
+ if (params.height)
22
+ this.options.height = Math.round(params.height);
23
+ if (params.crop)
24
+ this.options.crop = params.crop;
25
+ return this;
26
+ }
27
+ crop(mode) {
28
+ this.options.crop = mode;
29
+ return this;
30
+ }
31
+ format(fmt) {
32
+ this.options.format = fmt;
33
+ return this;
34
+ }
35
+ quality(q) {
36
+ this.options.quality = q;
37
+ return this;
38
+ }
39
+ blur(sigma = 5) {
40
+ this.options.blur = sigma;
41
+ return this;
42
+ }
43
+ grayscale(enable = true) {
44
+ this.options.grayscale = enable;
45
+ return this;
46
+ }
47
+ sharpen(enable = true) {
48
+ this.options.sharpen = enable;
49
+ return this;
50
+ }
51
+ rotation(rot) {
52
+ this.options.rotation = rot;
53
+ return this;
54
+ }
55
+ /**
56
+ * Builds the formatted transformation string (e.g. w_400,h_300,c_fill,f_auto)
57
+ */
58
+ toParamsString() {
59
+ const parts = [];
60
+ if (this.options.width)
61
+ parts.push(`w_${this.options.width}`);
62
+ if (this.options.height)
63
+ parts.push(`h_${this.options.height}`);
64
+ if (this.options.crop)
65
+ parts.push(`c_${this.options.crop}`);
66
+ if (this.options.format)
67
+ parts.push(`f_${this.options.format}`);
68
+ if (this.options.quality)
69
+ parts.push(`q_${this.options.quality}`);
70
+ if (this.options.blur)
71
+ parts.push(`e_blur_${this.options.blur}`);
72
+ if (this.options.grayscale)
73
+ parts.push('e_gray');
74
+ if (this.options.sharpen)
75
+ parts.push('e_sharp');
76
+ if (this.options.rotation)
77
+ parts.push(`r_${this.options.rotation}`);
78
+ return parts.length > 0 ? parts.join(',') : 'original';
79
+ }
80
+ /**
81
+ * Returns the final full URL string
82
+ */
83
+ build() {
84
+ const params = this.toParamsString();
85
+ if (params === 'original') {
86
+ return `${this.endpoint}/v1/image/${this.publicId}`;
87
+ }
88
+ return `${this.endpoint}/v1/image/${params}/${this.publicId}`;
89
+ }
90
+ toString() {
91
+ return this.build();
92
+ }
93
+ }
94
+ exports.TransformationBuilder = TransformationBuilder;
@@ -0,0 +1,38 @@
1
+ import { TransformationBuilder } from './builder.js';
2
+ import type { AssetResult, SignedUploadResult, SignUploadOptions, StorageClientConfig, UploadOptions } from './types.js';
3
+ export declare class StorageClient {
4
+ private endpoint;
5
+ private apiKey;
6
+ constructor(config: StorageClientConfig);
7
+ /**
8
+ * Initializes a fluent URL builder for the specified asset public ID
9
+ */
10
+ url(publicId: string): TransformationBuilder;
11
+ /**
12
+ * Generates a short-lived cryptographically signed upload token for safe client-side browser/mobile uploads.
13
+ * Keeps master API keys strictly on backend servers.
14
+ */
15
+ createSignedUploadToken(options?: SignUploadOptions): Promise<SignedUploadResult>;
16
+ /**
17
+ * Directly uploads a file to the storage server.
18
+ * Supports File/Blob in browser environments and Buffer/ReadStream in Node.js environments.
19
+ * Supports both Master API Key and Client Signed Upload Tokens (dcd_sig_...).
20
+ */
21
+ upload(file: any, options?: UploadOptions): Promise<AssetResult>;
22
+ /**
23
+ * Helper method for frontend clients to upload using only a signed upload token (zero API key)
24
+ */
25
+ uploadWithToken(file: any, token: string, options?: Omit<UploadOptions, 'token'>): Promise<AssetResult>;
26
+ /**
27
+ * Permanently deletes a storage asset (requires API key with delete role)
28
+ */
29
+ delete(publicId: string): Promise<boolean>;
30
+ }
31
+ export declare function createStorageClient(config: StorageClientConfig): StorageClient;
32
+ export declare const BucketClient: typeof StorageClient;
33
+ export type BucketClient = StorageClient;
34
+ export declare const createBucketClient: typeof createStorageClient;
35
+ export declare const MediaClient: typeof StorageClient;
36
+ export type MediaClient = StorageClient;
37
+ export declare const createMediaClient: typeof createStorageClient;
38
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EACV,WAAW,EACX,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,aAAa,EACd,MAAM,YAAY,CAAC;AAEpB,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,mBAAmB;IAQvC;;OAEG;IACH,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,qBAAqB;IAI5C;;;OAGG;IACG,uBAAuB,CAAC,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAuB3F;;;;OAIG;IACG,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,WAAW,CAAC;IAqG1E;;OAEG;IACG,eAAe,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,IAAI,CAAC,aAAa,EAAE,OAAO,CAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAIjH;;OAEG;IACG,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAajD;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,aAAa,CAE9E;AAGD,eAAO,MAAM,YAAY,sBAAgB,CAAC;AAC1C,MAAM,MAAM,YAAY,GAAG,aAAa,CAAC;AACzC,eAAO,MAAM,kBAAkB,4BAAsB,CAAC;AAGtD,eAAO,MAAM,WAAW,sBAAgB,CAAC;AACzC,MAAM,MAAM,WAAW,GAAG,aAAa,CAAC;AACxC,eAAO,MAAM,iBAAiB,4BAAsB,CAAC"}
package/dist/client.js ADDED
@@ -0,0 +1,178 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createMediaClient = exports.MediaClient = exports.createBucketClient = exports.BucketClient = exports.StorageClient = void 0;
4
+ exports.createStorageClient = createStorageClient;
5
+ const builder_js_1 = require("./builder.js");
6
+ class StorageClient {
7
+ constructor(config) {
8
+ if (!config.endpoint) {
9
+ throw new Error('StorageClient: endpoint is required');
10
+ }
11
+ this.endpoint = config.endpoint.replace(/\/+$/, '');
12
+ this.apiKey = (config.apiKey || '').trim();
13
+ }
14
+ /**
15
+ * Initializes a fluent URL builder for the specified asset public ID
16
+ */
17
+ url(publicId) {
18
+ return new builder_js_1.TransformationBuilder(this.endpoint, publicId);
19
+ }
20
+ /**
21
+ * Generates a short-lived cryptographically signed upload token for safe client-side browser/mobile uploads.
22
+ * Keeps master API keys strictly on backend servers.
23
+ */
24
+ async createSignedUploadToken(options = {}) {
25
+ if (!this.apiKey) {
26
+ throw new Error('StorageClient: API key is required on backend to generate signed upload tokens.');
27
+ }
28
+ const signUrl = `${this.endpoint}/v1/upload/sign`;
29
+ const response = await fetch(signUrl, {
30
+ method: 'POST',
31
+ headers: {
32
+ 'Content-Type': 'application/json',
33
+ Authorization: `Bearer ${this.apiKey}`,
34
+ },
35
+ body: JSON.stringify(options),
36
+ });
37
+ const data = await response.json();
38
+ if (!response.ok) {
39
+ throw new Error(data.error?.message || `Failed to generate signed upload token with status ${response.status}`);
40
+ }
41
+ return data;
42
+ }
43
+ /**
44
+ * Directly uploads a file to the storage server.
45
+ * Supports File/Blob in browser environments and Buffer/ReadStream in Node.js environments.
46
+ * Supports both Master API Key and Client Signed Upload Tokens (dcd_sig_...).
47
+ */
48
+ async upload(file, options = {}) {
49
+ const uploadUrl = `${this.endpoint}/v1/upload`;
50
+ const formData = new FormData();
51
+ let fileToAppend = file;
52
+ let filename = options.filename;
53
+ if (typeof file === 'string') {
54
+ if (typeof process !== 'undefined' && process.versions?.node) {
55
+ try {
56
+ const fs = await import('node:fs');
57
+ const path = await import('node:path');
58
+ if (fs.existsSync(file)) {
59
+ const buf = fs.readFileSync(file);
60
+ filename = filename || path.basename(file);
61
+ fileToAppend = new Blob([new Uint8Array(buf)]);
62
+ }
63
+ }
64
+ catch {
65
+ // ignore
66
+ }
67
+ }
68
+ }
69
+ else if (typeof Buffer !== 'undefined' && Buffer.isBuffer(file)) {
70
+ fileToAppend = new Blob([new Uint8Array(file)]);
71
+ filename = filename || 'upload.bin';
72
+ }
73
+ if (filename) {
74
+ formData.append('file', fileToAppend, filename);
75
+ }
76
+ else {
77
+ formData.append('file', fileToAppend);
78
+ }
79
+ if (options.folder)
80
+ formData.append('folder', options.folder);
81
+ if (options.publicId)
82
+ formData.append('public_id', options.publicId);
83
+ if (options.overwrite !== undefined)
84
+ formData.append('overwrite', String(options.overwrite));
85
+ if (options.uniqueFilename !== undefined)
86
+ formData.append('unique_filename', String(options.uniqueFilename));
87
+ // Determine auth header: Use options.token if provided, otherwise this.apiKey
88
+ const headers = {};
89
+ if (options.token) {
90
+ headers['X-Upload-Token'] = options.token;
91
+ }
92
+ else if (this.apiKey) {
93
+ headers['Authorization'] = `Bearer ${this.apiKey}`;
94
+ }
95
+ else {
96
+ throw new Error('StorageClient: Either apiKey or a signed upload token must be provided to upload.');
97
+ }
98
+ // Browser upload with progress tracking via XMLHttpRequest
99
+ if (typeof XMLHttpRequest !== 'undefined' && options.onProgress) {
100
+ return new Promise((resolve, reject) => {
101
+ const xhr = new XMLHttpRequest();
102
+ xhr.open('POST', uploadUrl, true);
103
+ for (const [k, v] of Object.entries(headers)) {
104
+ xhr.setRequestHeader(k, v);
105
+ }
106
+ xhr.upload.onprogress = (e) => {
107
+ if (e.lengthComputable && options.onProgress) {
108
+ const percent = Math.round((e.loaded / e.total) * 100);
109
+ options.onProgress(percent);
110
+ }
111
+ };
112
+ xhr.onload = () => {
113
+ if (xhr.status >= 200 && xhr.status < 300) {
114
+ try {
115
+ const res = JSON.parse(xhr.responseText);
116
+ resolve(res.asset);
117
+ }
118
+ catch {
119
+ reject(new Error('Invalid response from storage server'));
120
+ }
121
+ }
122
+ else {
123
+ try {
124
+ const errData = JSON.parse(xhr.responseText);
125
+ reject(new Error(errData.error?.message || `Upload failed with status ${xhr.status}`));
126
+ }
127
+ catch {
128
+ reject(new Error(`Upload failed with status ${xhr.status}`));
129
+ }
130
+ }
131
+ };
132
+ xhr.onerror = () => reject(new Error('Network error during file upload'));
133
+ xhr.send(formData);
134
+ });
135
+ }
136
+ // Standard fetch upload (Browser or Node.js)
137
+ const response = await fetch(uploadUrl, {
138
+ method: 'POST',
139
+ headers,
140
+ body: formData,
141
+ });
142
+ const data = await response.json();
143
+ if (!response.ok) {
144
+ throw new Error(data.error?.message || `Upload failed with status ${response.status}`);
145
+ }
146
+ return data.asset;
147
+ }
148
+ /**
149
+ * Helper method for frontend clients to upload using only a signed upload token (zero API key)
150
+ */
151
+ async uploadWithToken(file, token, options = {}) {
152
+ return this.upload(file, { ...options, token });
153
+ }
154
+ /**
155
+ * Permanently deletes a storage asset (requires API key with delete role)
156
+ */
157
+ async delete(publicId) {
158
+ const cleanPublicId = publicId.replace(/^\/+/, '');
159
+ const deleteUrl = `${this.endpoint}/v1/admin/files/${cleanPublicId}`;
160
+ const response = await fetch(deleteUrl, {
161
+ method: 'DELETE',
162
+ headers: {
163
+ Authorization: `Bearer ${this.apiKey}`,
164
+ },
165
+ });
166
+ return response.ok;
167
+ }
168
+ }
169
+ exports.StorageClient = StorageClient;
170
+ function createStorageClient(config) {
171
+ return new StorageClient(config);
172
+ }
173
+ // Bucket modern API aliases
174
+ exports.BucketClient = StorageClient;
175
+ exports.createBucketClient = createStorageClient;
176
+ // Backward compatibility aliases
177
+ exports.MediaClient = StorageClient;
178
+ exports.createMediaClient = createStorageClient;
@@ -0,0 +1,4 @@
1
+ export { TransformationBuilder } from './builder.js';
2
+ export { StorageClient, createStorageClient, BucketClient, createBucketClient, MediaClient, createMediaClient, } from './client.js';
3
+ export type { AssetResult, StorageAssetResult, BucketAssetResult, CropMode, OutputFormat, StorageClientConfig, BucketClientConfig, MediaClientConfig, TransformationOptions, UploadOptions, } from './types.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,iBAAiB,GAClB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,WAAW,EACX,kBAAkB,EAClB,iBAAiB,EACjB,QAAQ,EACR,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,GACd,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createMediaClient = exports.MediaClient = exports.createBucketClient = exports.BucketClient = exports.createStorageClient = exports.StorageClient = exports.TransformationBuilder = void 0;
4
+ var builder_js_1 = require("./builder.js");
5
+ Object.defineProperty(exports, "TransformationBuilder", { enumerable: true, get: function () { return builder_js_1.TransformationBuilder; } });
6
+ var client_js_1 = require("./client.js");
7
+ Object.defineProperty(exports, "StorageClient", { enumerable: true, get: function () { return client_js_1.StorageClient; } });
8
+ Object.defineProperty(exports, "createStorageClient", { enumerable: true, get: function () { return client_js_1.createStorageClient; } });
9
+ Object.defineProperty(exports, "BucketClient", { enumerable: true, get: function () { return client_js_1.BucketClient; } });
10
+ Object.defineProperty(exports, "createBucketClient", { enumerable: true, get: function () { return client_js_1.createBucketClient; } });
11
+ Object.defineProperty(exports, "MediaClient", { enumerable: true, get: function () { return client_js_1.MediaClient; } });
12
+ Object.defineProperty(exports, "createMediaClient", { enumerable: true, get: function () { return client_js_1.createMediaClient; } });
@@ -0,0 +1,67 @@
1
+ export type CropMode = 'fill' | 'fit' | 'crop' | 'scale';
2
+ export type OutputFormat = 'auto' | 'webp' | 'avif' | 'jpeg' | 'png';
3
+ export interface StorageClientConfig {
4
+ /** The base URL of the storage engine cluster (e.g. 'https://storage.mycoolapp.com' or 'http://192.168.1.50:7100') */
5
+ endpoint: string;
6
+ /** Public API key (dcd_pk_...), Secret key (dcd_sk_...), or Live key */
7
+ apiKey?: string;
8
+ }
9
+ export type MediaClientConfig = StorageClientConfig;
10
+ export type BucketClientConfig = StorageClientConfig;
11
+ export interface TransformationOptions {
12
+ width?: number;
13
+ height?: number;
14
+ crop?: CropMode;
15
+ format?: OutputFormat;
16
+ quality?: number | 'auto';
17
+ blur?: number;
18
+ grayscale?: boolean;
19
+ sharpen?: boolean;
20
+ rotation?: number | 'auto';
21
+ }
22
+ export interface UploadOptions {
23
+ folder?: string;
24
+ publicId?: string;
25
+ filename?: string;
26
+ overwrite?: boolean;
27
+ uniqueFilename?: boolean;
28
+ /** Optional client signed upload token (dcd_sig_...) to upload without API key */
29
+ token?: string;
30
+ tags?: string[];
31
+ onProgress?: (percent: number) => void;
32
+ }
33
+ export interface SignUploadOptions {
34
+ folder?: string;
35
+ maxBytes?: number;
36
+ expiresInSeconds?: number;
37
+ }
38
+ export interface SignedUploadResult {
39
+ success: boolean;
40
+ token: string;
41
+ uploadUrl: string;
42
+ expiresInSeconds: number;
43
+ folder?: string | null;
44
+ maxBytes?: number | null;
45
+ }
46
+ export interface AssetResult {
47
+ public_id: string;
48
+ publicId: string;
49
+ filename: string;
50
+ format: string;
51
+ resource_type?: string;
52
+ resourceType?: string;
53
+ width?: number;
54
+ height?: number;
55
+ bytes: number;
56
+ storageDriver: string;
57
+ etag: string;
58
+ url: string;
59
+ secure_url: string;
60
+ secureUrl: string;
61
+ rawUrl?: string;
62
+ created_at: number;
63
+ createdAt: number;
64
+ }
65
+ export type StorageAssetResult = AssetResult;
66
+ export type BucketAssetResult = AssetResult;
67
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;AACzD,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AAErE,MAAM,WAAW,mBAAmB;IAClC,sHAAsH;IACtH,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAGD,MAAM,MAAM,iBAAiB,GAAG,mBAAmB,CAAC;AACpD,MAAM,MAAM,kBAAkB,GAAG,mBAAmB,CAAC;AAErD,MAAM,WAAW,qBAAqB;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kFAAkF;IAClF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAGD,MAAM,MAAM,kBAAkB,GAAG,WAAW,CAAC;AAC7C,MAAM,MAAM,iBAAiB,GAAG,WAAW,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json CHANGED
@@ -1,6 +1,38 @@
1
1
  {
2
2
  "name": "@dcd-sdk/storage-client",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.0.0",
4
+ "description": "Official Node.js & TypeScript client SDK for DevCloudDesk Storage Engine",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "main": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js",
14
+ "require": "./dist/index.js",
15
+ "default": "./dist/index.js"
16
+ },
17
+ "./package.json": "./package.json"
18
+ },
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "scripts": {
23
+ "build": "tsc",
24
+ "test": "vitest run"
25
+ },
26
+ "devDependencies": {
27
+ "@types/node": "^20.17.19",
28
+ "typescript": "^5.7.3",
29
+ "vitest": "^5.0.5"
30
+ },
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "https://github.com/devclouddesk/dcd-sdk.git",
34
+ "directory": "packages/storage-client"
35
+ },
36
+ "homepage": "https://devclouddesk.com",
37
+ "license": "MIT"
38
+ }