@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/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 { type S3Client } from '@aws-sdk/client-s3';
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,KAAK,QAAQ,EACd,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"}
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.2.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 .",