@maroonedsoftware/storage 0.2.0 → 0.3.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 +16 -2
- package/dist/chunk-UBT2CAIO.js +71 -0
- package/dist/chunk-UBT2CAIO.js.map +1 -0
- package/dist/gcs.d.ts +2 -0
- package/dist/gcs.d.ts.map +1 -0
- package/dist/gcs.js +182 -0
- package/dist/gcs.js.map +1 -0
- package/dist/gcs.storage.provider.d.ts +1 -1
- package/dist/gcs.storage.provider.d.ts.map +1 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -451
- package/dist/index.js.map +1 -1
- package/dist/s3.d.ts +2 -0
- package/dist/s3.d.ts.map +1 -0
- package/dist/s3.js +222 -0
- package/dist/s3.js.map +1 -0
- package/dist/s3.storage.provider.d.ts +1 -1
- package/dist/s3.storage.provider.d.ts.map +1 -1
- package/package.json +17 -2
package/dist/s3.js
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import {
|
|
2
|
+
StorageAccessDeniedError,
|
|
3
|
+
StorageObjectNotFoundError,
|
|
4
|
+
StorageProvider,
|
|
5
|
+
__name
|
|
6
|
+
} from "./chunk-UBT2CAIO.js";
|
|
7
|
+
|
|
8
|
+
// src/s3.storage.provider.ts
|
|
9
|
+
import { Injectable } from "injectkit";
|
|
10
|
+
import { Readable } from "stream";
|
|
11
|
+
import { DateTime } from "luxon";
|
|
12
|
+
import { CopyObjectCommand, DeleteObjectCommand, GetObjectCommand, HeadObjectCommand, ListObjectsV2Command, PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
|
|
13
|
+
import { Upload } from "@aws-sdk/lib-storage";
|
|
14
|
+
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
|
|
15
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
16
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
17
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
18
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
19
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
20
|
+
}
|
|
21
|
+
__name(_ts_decorate, "_ts_decorate");
|
|
22
|
+
function _ts_metadata(k, v) {
|
|
23
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
24
|
+
}
|
|
25
|
+
__name(_ts_metadata, "_ts_metadata");
|
|
26
|
+
var S3StorageProviderOptions = class {
|
|
27
|
+
static {
|
|
28
|
+
__name(this, "S3StorageProviderOptions");
|
|
29
|
+
}
|
|
30
|
+
/** Name of the bucket all keys live in. */
|
|
31
|
+
bucket;
|
|
32
|
+
constructor(init) {
|
|
33
|
+
this.bucket = init.bucket;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
var S3StorageProvider = class extends StorageProvider {
|
|
37
|
+
static {
|
|
38
|
+
__name(this, "S3StorageProvider");
|
|
39
|
+
}
|
|
40
|
+
client;
|
|
41
|
+
options;
|
|
42
|
+
constructor(client, options) {
|
|
43
|
+
super(), this.client = client, this.options = options;
|
|
44
|
+
}
|
|
45
|
+
async write(key, body, options) {
|
|
46
|
+
const shared = {
|
|
47
|
+
Bucket: this.options.bucket,
|
|
48
|
+
Key: key,
|
|
49
|
+
ContentType: options?.contentType,
|
|
50
|
+
ContentLength: options?.contentLength,
|
|
51
|
+
CacheControl: options?.cacheControl,
|
|
52
|
+
Metadata: options?.metadata
|
|
53
|
+
};
|
|
54
|
+
if (body instanceof Readable) {
|
|
55
|
+
const upload = new Upload({
|
|
56
|
+
client: this.client,
|
|
57
|
+
params: {
|
|
58
|
+
...shared,
|
|
59
|
+
Body: body
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
await upload.done();
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
await this.client.send(new PutObjectCommand({
|
|
66
|
+
...shared,
|
|
67
|
+
Body: body
|
|
68
|
+
}));
|
|
69
|
+
}
|
|
70
|
+
async read(key, options) {
|
|
71
|
+
try {
|
|
72
|
+
const response = await this.client.send(new GetObjectCommand({
|
|
73
|
+
Bucket: this.options.bucket,
|
|
74
|
+
Key: key,
|
|
75
|
+
Range: toRangeHeader(options?.range)
|
|
76
|
+
}));
|
|
77
|
+
return response.Body;
|
|
78
|
+
} catch (error) {
|
|
79
|
+
throw this.mapError(key, error);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
async stat(key) {
|
|
83
|
+
try {
|
|
84
|
+
const head = await this.client.send(new HeadObjectCommand({
|
|
85
|
+
Bucket: this.options.bucket,
|
|
86
|
+
Key: key
|
|
87
|
+
}));
|
|
88
|
+
return {
|
|
89
|
+
key,
|
|
90
|
+
size: head.ContentLength ?? 0,
|
|
91
|
+
contentType: head.ContentType,
|
|
92
|
+
etag: head.ETag,
|
|
93
|
+
lastModified: head.LastModified ? DateTime.fromJSDate(head.LastModified) : void 0,
|
|
94
|
+
metadata: head.Metadata
|
|
95
|
+
};
|
|
96
|
+
} catch (error) {
|
|
97
|
+
throw this.mapError(key, error);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async exists(key) {
|
|
101
|
+
try {
|
|
102
|
+
await this.client.send(new HeadObjectCommand({
|
|
103
|
+
Bucket: this.options.bucket,
|
|
104
|
+
Key: key
|
|
105
|
+
}));
|
|
106
|
+
return true;
|
|
107
|
+
} catch (error) {
|
|
108
|
+
if (isNotFound(error)) {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
throw this.mapError(key, error);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
async delete(key) {
|
|
115
|
+
await this.client.send(new DeleteObjectCommand({
|
|
116
|
+
Bucket: this.options.bucket,
|
|
117
|
+
Key: key
|
|
118
|
+
}));
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Server-side copy via `CopyObjectCommand`.
|
|
122
|
+
*
|
|
123
|
+
* Note: S3's single-request `CopyObject` is capped at 5 GB. Copying a larger
|
|
124
|
+
* object requires a multipart copy (`UploadPartCopy`), which this provider
|
|
125
|
+
* does not yet implement — such copies will fail. {@link move} inherits the
|
|
126
|
+
* same limit since it delegates to `copy`.
|
|
127
|
+
*/
|
|
128
|
+
async copy(sourceKey, destinationKey) {
|
|
129
|
+
try {
|
|
130
|
+
await this.client.send(new CopyObjectCommand({
|
|
131
|
+
Bucket: this.options.bucket,
|
|
132
|
+
Key: destinationKey,
|
|
133
|
+
// CopySource must be the URL-encoded `bucket/key` of the source object.
|
|
134
|
+
CopySource: `${this.options.bucket}/${encodeURIComponent(sourceKey)}`
|
|
135
|
+
}));
|
|
136
|
+
} catch (error) {
|
|
137
|
+
throw this.mapError(sourceKey, error);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
async move(sourceKey, destinationKey) {
|
|
141
|
+
await this.copy(sourceKey, destinationKey);
|
|
142
|
+
await this.delete(sourceKey);
|
|
143
|
+
}
|
|
144
|
+
async list(options) {
|
|
145
|
+
const response = await this.client.send(new ListObjectsV2Command({
|
|
146
|
+
Bucket: this.options.bucket,
|
|
147
|
+
Prefix: options?.prefix,
|
|
148
|
+
MaxKeys: options?.limit,
|
|
149
|
+
ContinuationToken: options?.cursor
|
|
150
|
+
}));
|
|
151
|
+
const objects = (response.Contents ?? []).map((item) => ({
|
|
152
|
+
key: item.Key ?? "",
|
|
153
|
+
size: item.Size ?? 0,
|
|
154
|
+
etag: item.ETag,
|
|
155
|
+
lastModified: item.LastModified ? DateTime.fromJSDate(item.LastModified) : void 0
|
|
156
|
+
}));
|
|
157
|
+
return {
|
|
158
|
+
objects,
|
|
159
|
+
cursor: response.IsTruncated ? response.NextContinuationToken : void 0
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
async getSignedUrl(key, options) {
|
|
163
|
+
const command = options.operation === "write" ? new PutObjectCommand({
|
|
164
|
+
Bucket: this.options.bucket,
|
|
165
|
+
Key: key,
|
|
166
|
+
ContentType: options.contentType
|
|
167
|
+
}) : new GetObjectCommand({
|
|
168
|
+
Bucket: this.options.bucket,
|
|
169
|
+
Key: key
|
|
170
|
+
});
|
|
171
|
+
return getSignedUrl(this.client, command, {
|
|
172
|
+
expiresIn: Math.round(options.expiresIn.as("seconds"))
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
mapError(key, error) {
|
|
176
|
+
if (isNotFound(error)) {
|
|
177
|
+
return new StorageObjectNotFoundError(key, {
|
|
178
|
+
cause: error
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
if (isAccessDenied(error)) {
|
|
182
|
+
return new StorageAccessDeniedError(key, {
|
|
183
|
+
cause: error
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
return error;
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
S3StorageProvider = _ts_decorate([
|
|
190
|
+
Injectable(),
|
|
191
|
+
_ts_metadata("design:type", Function),
|
|
192
|
+
_ts_metadata("design:paramtypes", [
|
|
193
|
+
typeof S3Client === "undefined" ? Object : S3Client,
|
|
194
|
+
typeof S3StorageProviderOptions === "undefined" ? Object : S3StorageProviderOptions
|
|
195
|
+
])
|
|
196
|
+
], S3StorageProvider);
|
|
197
|
+
function errorName(error) {
|
|
198
|
+
return typeof error === "object" && error !== null ? error.name : void 0;
|
|
199
|
+
}
|
|
200
|
+
__name(errorName, "errorName");
|
|
201
|
+
function statusCode(error) {
|
|
202
|
+
return typeof error === "object" && error !== null ? error.$metadata?.httpStatusCode : void 0;
|
|
203
|
+
}
|
|
204
|
+
__name(statusCode, "statusCode");
|
|
205
|
+
function isNotFound(error) {
|
|
206
|
+
const name = errorName(error);
|
|
207
|
+
return name === "NoSuchKey" || name === "NotFound" || statusCode(error) === 404;
|
|
208
|
+
}
|
|
209
|
+
__name(isNotFound, "isNotFound");
|
|
210
|
+
function isAccessDenied(error) {
|
|
211
|
+
return errorName(error) === "AccessDenied" || statusCode(error) === 403;
|
|
212
|
+
}
|
|
213
|
+
__name(isAccessDenied, "isAccessDenied");
|
|
214
|
+
function toRangeHeader(range) {
|
|
215
|
+
return range ? `bytes=${range.start}-${range.end ?? ""}` : void 0;
|
|
216
|
+
}
|
|
217
|
+
__name(toRangeHeader, "toRangeHeader");
|
|
218
|
+
export {
|
|
219
|
+
S3StorageProvider,
|
|
220
|
+
S3StorageProviderOptions
|
|
221
|
+
};
|
|
222
|
+
//# sourceMappingURL=s3.js.map
|
package/dist/s3.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/s3.storage.provider.ts"],"sourcesContent":["import { Injectable } from 'injectkit';\nimport { Readable } from 'node:stream';\nimport { DateTime } from 'luxon';\nimport {\n CopyObjectCommand,\n DeleteObjectCommand,\n GetObjectCommand,\n HeadObjectCommand,\n ListObjectsV2Command,\n PutObjectCommand,\n S3Client,\n} from '@aws-sdk/client-s3';\nimport { Upload } from '@aws-sdk/lib-storage';\nimport { getSignedUrl } from '@aws-sdk/s3-request-presigner';\nimport { StorageAccessDeniedError, StorageObjectNotFoundError } from './storage.errors.js';\nimport type {\n SignedUrlOptions,\n StorageListOptions,\n StorageListResult,\n StorageObjectMetadata,\n StorageReadOptions,\n StorageWriteOptions,\n} from './storage.provider.js';\nimport { StorageProvider } from './storage.provider.js';\n\n/**\n * Construction options for {@link S3StorageProvider}.\n *\n * A class (not an interface) so it can serve as an InjectKit token — register\n * an instance and the container can construct {@link S3StorageProvider}.\n */\nexport class S3StorageProviderOptions {\n /** Name of the bucket all keys live in. */\n readonly bucket: string;\n\n constructor(init: { bucket: string }) {\n this.bucket = init.bucket;\n }\n}\n\n/**\n * {@link StorageProvider} backed by an AWS S3 (or S3-compatible) bucket.\n *\n * Streaming writes go through `@aws-sdk/lib-storage`'s multipart `Upload`;\n * buffer/string writes use a single `PutObject`. Signed URLs are produced with\n * `@aws-sdk/s3-request-presigner`.\n */\n@Injectable()\nexport class S3StorageProvider extends StorageProvider {\n constructor(\n private readonly client: S3Client,\n private readonly options: S3StorageProviderOptions,\n ) {\n super();\n }\n\n async write(key: string, body: Readable | Buffer | string, options?: StorageWriteOptions): Promise<void> {\n const shared = {\n Bucket: this.options.bucket,\n Key: key,\n ContentType: options?.contentType,\n ContentLength: options?.contentLength,\n CacheControl: options?.cacheControl,\n Metadata: options?.metadata,\n };\n\n if (body instanceof Readable) {\n // lib-storage streams the body, automatically switching to multipart for large objects.\n const upload = new Upload({ client: this.client, params: { ...shared, Body: body } });\n await upload.done();\n return;\n }\n\n await this.client.send(new PutObjectCommand({ ...shared, Body: body }));\n }\n\n async read(key: string, options?: StorageReadOptions): Promise<Readable> {\n try {\n const response = await this.client.send(\n new GetObjectCommand({ Bucket: this.options.bucket, Key: key, Range: toRangeHeader(options?.range) }),\n );\n return response.Body as Readable;\n } catch (error) {\n throw this.mapError(key, error);\n }\n }\n\n async stat(key: string): Promise<StorageObjectMetadata> {\n try {\n const head = await this.client.send(new HeadObjectCommand({ Bucket: this.options.bucket, Key: key }));\n return {\n key,\n size: head.ContentLength ?? 0,\n contentType: head.ContentType,\n etag: head.ETag,\n lastModified: head.LastModified ? DateTime.fromJSDate(head.LastModified) : undefined,\n metadata: head.Metadata,\n };\n } catch (error) {\n throw this.mapError(key, error);\n }\n }\n\n async exists(key: string): Promise<boolean> {\n try {\n await this.client.send(new HeadObjectCommand({ Bucket: this.options.bucket, Key: key }));\n return true;\n } catch (error) {\n if (isNotFound(error)) {\n return false;\n }\n // A 403 is a permission failure, not absence — surface it.\n throw this.mapError(key, error);\n }\n }\n\n async delete(key: string): Promise<void> {\n // S3 DeleteObject is idempotent — deleting a missing key succeeds.\n await this.client.send(new DeleteObjectCommand({ Bucket: this.options.bucket, Key: key }));\n }\n\n /**\n * Server-side copy via `CopyObjectCommand`.\n *\n * Note: S3's single-request `CopyObject` is capped at 5 GB. Copying a larger\n * object requires a multipart copy (`UploadPartCopy`), which this provider\n * does not yet implement — such copies will fail. {@link move} inherits the\n * same limit since it delegates to `copy`.\n */\n async copy(sourceKey: string, destinationKey: string): Promise<void> {\n try {\n await this.client.send(\n new CopyObjectCommand({\n Bucket: this.options.bucket,\n Key: destinationKey,\n // CopySource must be the URL-encoded `bucket/key` of the source object.\n CopySource: `${this.options.bucket}/${encodeURIComponent(sourceKey)}`,\n }),\n );\n } catch (error) {\n throw this.mapError(sourceKey, error);\n }\n }\n\n async move(sourceKey: string, destinationKey: string): Promise<void> {\n // S3 has no native move — copy then delete the source.\n await this.copy(sourceKey, destinationKey);\n await this.delete(sourceKey);\n }\n\n async list(options?: StorageListOptions): Promise<StorageListResult> {\n const response = await this.client.send(\n new ListObjectsV2Command({\n Bucket: this.options.bucket,\n Prefix: options?.prefix,\n MaxKeys: options?.limit,\n ContinuationToken: options?.cursor,\n }),\n );\n\n const objects: StorageObjectMetadata[] = (response.Contents ?? []).map(item => ({\n key: item.Key ?? '',\n size: item.Size ?? 0,\n etag: item.ETag,\n lastModified: item.LastModified ? DateTime.fromJSDate(item.LastModified) : undefined,\n }));\n\n return {\n objects,\n cursor: response.IsTruncated ? response.NextContinuationToken : undefined,\n };\n }\n\n async getSignedUrl(key: string, options: SignedUrlOptions): Promise<string> {\n const command =\n options.operation === 'write'\n ? new PutObjectCommand({ Bucket: this.options.bucket, Key: key, ContentType: options.contentType })\n : new GetObjectCommand({ Bucket: this.options.bucket, Key: key });\n return getSignedUrl(this.client, command, { expiresIn: Math.round(options.expiresIn.as('seconds')) });\n }\n\n private mapError(key: string, error: unknown): unknown {\n if (isNotFound(error)) {\n return new StorageObjectNotFoundError(key, { cause: error });\n }\n if (isAccessDenied(error)) {\n return new StorageAccessDeniedError(key, { cause: error });\n }\n return error;\n }\n}\n\nfunction errorName(error: unknown): string | undefined {\n return typeof error === 'object' && error !== null ? (error as { name?: string }).name : undefined;\n}\n\nfunction statusCode(error: unknown): number | undefined {\n return typeof error === 'object' && error !== null ? (error as { $metadata?: { httpStatusCode?: number } }).$metadata?.httpStatusCode : undefined;\n}\n\nfunction isNotFound(error: unknown): boolean {\n const name = errorName(error);\n return name === 'NoSuchKey' || name === 'NotFound' || statusCode(error) === 404;\n}\n\nfunction isAccessDenied(error: unknown): boolean {\n return errorName(error) === 'AccessDenied' || statusCode(error) === 403;\n}\n\n/** Build an HTTP `Range` header (`bytes=start-end`) from an inclusive byte range. */\nfunction toRangeHeader(range?: { start: number; end?: number }): string | undefined {\n return range ? `bytes=${range.start}-${range.end ?? ''}` : undefined;\n}\n"],"mappings":"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","names":["Injectable","Readable","DateTime","CopyObjectCommand","DeleteObjectCommand","GetObjectCommand","HeadObjectCommand","ListObjectsV2Command","PutObjectCommand","S3Client","Upload","getSignedUrl","S3StorageProviderOptions","bucket","init","S3StorageProvider","StorageProvider","client","options","write","key","body","shared","Bucket","Key","ContentType","contentType","ContentLength","contentLength","CacheControl","cacheControl","Metadata","metadata","Readable","upload","Upload","params","Body","done","send","PutObjectCommand","read","response","GetObjectCommand","Range","toRangeHeader","range","error","mapError","stat","head","HeadObjectCommand","size","etag","ETag","lastModified","LastModified","DateTime","fromJSDate","undefined","exists","isNotFound","delete","DeleteObjectCommand","copy","sourceKey","destinationKey","CopyObjectCommand","CopySource","encodeURIComponent","move","list","ListObjectsV2Command","Prefix","prefix","MaxKeys","limit","ContinuationToken","cursor","objects","Contents","map","item","Size","IsTruncated","NextContinuationToken","getSignedUrl","command","operation","expiresIn","Math","round","as","StorageObjectNotFoundError","cause","isAccessDenied","StorageAccessDeniedError","errorName","name","statusCode","$metadata","httpStatusCode","start","end"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Readable } from 'node:stream';
|
|
2
|
-
import {
|
|
2
|
+
import { S3Client } from '@aws-sdk/client-s3';
|
|
3
3
|
import type { SignedUrlOptions, StorageListOptions, StorageListResult, StorageObjectMetadata, StorageReadOptions, StorageWriteOptions } from './storage.provider.js';
|
|
4
4
|
import { StorageProvider } from './storage.provider.js';
|
|
5
5
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"s3.storage.provider.d.ts","sourceRoot":"","sources":["../src/s3.storage.provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,OAAO,EAOL,
|
|
1
|
+
{"version":3,"file":"s3.storage.provider.d.ts","sourceRoot":"","sources":["../src/s3.storage.provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,OAAO,EAOL,QAAQ,EACT,MAAM,oBAAoB,CAAC;AAI5B,OAAO,KAAK,EACV,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD;;;;;GAKG;AACH,qBAAa,wBAAwB;IACnC,2CAA2C;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE;CAGrC;AAED;;;;;;GAMG;AACH,qBACa,iBAAkB,SAAQ,eAAe;IAElD,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBADP,MAAM,EAAE,QAAQ,EAChB,OAAO,EAAE,wBAAwB;IAK9C,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBlG,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAWlE,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAgBjD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAarC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKxC;;;;;;;OAOG;IACG,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAe9D,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM9D,IAAI,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAuB9D,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC;IAQ3E,OAAO,CAAC,QAAQ;CASjB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maroonedsoftware/storage",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Storage utilities for ServerKit.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Marooned Software",
|
|
@@ -25,6 +25,21 @@
|
|
|
25
25
|
"main": "./dist/index.js",
|
|
26
26
|
"module": "./dist/index.js",
|
|
27
27
|
"types": "./dist/index.d.ts",
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"import": "./dist/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./s3": {
|
|
34
|
+
"types": "./dist/s3.d.ts",
|
|
35
|
+
"import": "./dist/s3.js"
|
|
36
|
+
},
|
|
37
|
+
"./gcs": {
|
|
38
|
+
"types": "./dist/gcs.d.ts",
|
|
39
|
+
"import": "./dist/gcs.js"
|
|
40
|
+
},
|
|
41
|
+
"./package.json": "./package.json"
|
|
42
|
+
},
|
|
28
43
|
"license": "MIT",
|
|
29
44
|
"files": [
|
|
30
45
|
"dist/**"
|
|
@@ -66,7 +81,7 @@
|
|
|
66
81
|
"@repo/config-eslint": "0.2.1"
|
|
67
82
|
},
|
|
68
83
|
"scripts": {
|
|
69
|
-
"build": "tsup src/index.ts --format esm --sourcemap && tsc --emitDeclarationOnly --declaration",
|
|
84
|
+
"build": "tsup src/index.ts src/s3.ts src/gcs.ts --format esm --sourcemap && tsc --emitDeclarationOnly --declaration",
|
|
70
85
|
"build:ci": "eslint --max-warnings=0 && pnpm run build",
|
|
71
86
|
"lint": "eslint --fix",
|
|
72
87
|
"format": "prettier --write .",
|