@dcd-sdk/storage-client 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.js DELETED
@@ -1,178 +0,0 @@
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;
@@ -1 +0,0 @@
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/types.d.ts DELETED
@@ -1,67 +0,0 @@
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
@@ -1 +0,0 @@
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 DELETED
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });