@constructive-io/bucket-provisioner 0.2.0 → 0.2.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.
@@ -85,6 +85,10 @@ export declare class BucketProvisioner {
85
85
  bucketExists(bucketName: string): Promise<boolean>;
86
86
  /**
87
87
  * Configure S3 Block Public Access settings.
88
+ *
89
+ * Gracefully skips if the S3-compatible backend (e.g. MinIO) does not
90
+ * support PutPublicAccessBlock — the operation is best-effort since
91
+ * not all providers implement this AWS-specific API.
88
92
  */
89
93
  setPublicAccessBlock(bucketName: string, config: PublicAccessBlockConfig): Promise<void>;
90
94
  /**
@@ -93,10 +97,17 @@ export declare class BucketProvisioner {
93
97
  setBucketPolicy(bucketName: string, policy: BucketPolicyDocument): Promise<void>;
94
98
  /**
95
99
  * Delete an S3 bucket policy (used to clear leftover public policies).
100
+ *
101
+ * Gracefully handles backends that don't support this operation or have
102
+ * no policy to delete.
96
103
  */
97
104
  deleteBucketPolicy(bucketName: string): Promise<void>;
98
105
  /**
99
106
  * Set CORS configuration on an S3 bucket.
107
+ *
108
+ * Gracefully skips if the S3-compatible backend (e.g. older MinIO) does
109
+ * not support PutBucketCors — CORS is best-effort since not all providers
110
+ * implement this API via the same endpoint path.
100
111
  */
101
112
  setCors(bucketName: string, rules: CorsRule[]): Promise<void>;
102
113
  /**
@@ -168,6 +168,10 @@ export class BucketProvisioner {
168
168
  }
169
169
  /**
170
170
  * Configure S3 Block Public Access settings.
171
+ *
172
+ * Gracefully skips if the S3-compatible backend (e.g. MinIO) does not
173
+ * support PutPublicAccessBlock — the operation is best-effort since
174
+ * not all providers implement this AWS-specific API.
171
175
  */
172
176
  async setPublicAccessBlock(bucketName, config) {
173
177
  try {
@@ -177,6 +181,18 @@ export class BucketProvisioner {
177
181
  }));
178
182
  }
179
183
  catch (err) {
184
+ // Some S3-compatible backends (e.g. older MinIO) don't support
185
+ // PutPublicAccessBlock. Treat XML parse errors or "not implemented"
186
+ // responses as non-fatal — the bucket is still usable.
187
+ if (err.Code === 'XmlParseException' ||
188
+ err.name === 'XmlParseException' ||
189
+ err.Code === 'NotImplemented' ||
190
+ err.name === 'NotImplemented' ||
191
+ err.message?.includes('not well-formed') ||
192
+ err.message?.includes('not implemented') ||
193
+ err.message?.includes('PublicAccessBlockConfiguration')) {
194
+ return;
195
+ }
180
196
  throw new ProvisionerError('POLICY_FAILED', `Failed to set public access block on '${bucketName}': ${err.message}`, err);
181
197
  }
182
198
  }
@@ -196,6 +212,9 @@ export class BucketProvisioner {
196
212
  }
197
213
  /**
198
214
  * Delete an S3 bucket policy (used to clear leftover public policies).
215
+ *
216
+ * Gracefully handles backends that don't support this operation or have
217
+ * no policy to delete.
199
218
  */
200
219
  async deleteBucketPolicy(bucketName) {
201
220
  try {
@@ -203,7 +222,14 @@ export class BucketProvisioner {
203
222
  }
204
223
  catch (err) {
205
224
  // No policy to delete — that's fine
206
- if (err.name === 'NoSuchBucketPolicy' || err.$metadata?.httpStatusCode === 404) {
225
+ if (err.name === 'NoSuchBucketPolicy' ||
226
+ err.$metadata?.httpStatusCode === 404 ||
227
+ err.Code === 'XmlParseException' ||
228
+ err.name === 'XmlParseException' ||
229
+ err.Code === 'NotImplemented' ||
230
+ err.name === 'NotImplemented' ||
231
+ err.message?.includes('not well-formed') ||
232
+ err.message?.includes('not implemented')) {
207
233
  return;
208
234
  }
209
235
  throw new ProvisionerError('POLICY_FAILED', `Failed to delete bucket policy on '${bucketName}': ${err.message}`, err);
@@ -211,6 +237,10 @@ export class BucketProvisioner {
211
237
  }
212
238
  /**
213
239
  * Set CORS configuration on an S3 bucket.
240
+ *
241
+ * Gracefully skips if the S3-compatible backend (e.g. older MinIO) does
242
+ * not support PutBucketCors — CORS is best-effort since not all providers
243
+ * implement this API via the same endpoint path.
214
244
  */
215
245
  async setCors(bucketName, rules) {
216
246
  try {
@@ -228,6 +258,18 @@ export class BucketProvisioner {
228
258
  }));
229
259
  }
230
260
  catch (err) {
261
+ // Some S3-compatible backends (e.g. older MinIO) don't support
262
+ // PutBucketCors via the standard path. Treat XML parse errors or
263
+ // "not implemented" responses as non-fatal.
264
+ if (err.Code === 'XmlParseException' ||
265
+ err.name === 'XmlParseException' ||
266
+ err.Code === 'NotImplemented' ||
267
+ err.name === 'NotImplemented' ||
268
+ err.message?.includes('not well-formed') ||
269
+ err.message?.includes('not implemented') ||
270
+ err.message?.includes('CORSConfiguration')) {
271
+ return;
272
+ }
231
273
  throw new ProvisionerError('CORS_FAILED', `Failed to set CORS on '${bucketName}': ${err.message}`, err);
232
274
  }
233
275
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constructive-io/bucket-provisioner",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "author": "Constructive <developers@constructive.io>",
5
5
  "description": "S3-compatible bucket provisioning library — create buckets, configure privacy policies, CORS, and access controls",
6
6
  "main": "index.js",
@@ -43,5 +43,5 @@
43
43
  "storage",
44
44
  "constructive"
45
45
  ],
46
- "gitHead": "fe60f7b81252eea53dce227bb581d5ae2ef0ec36"
46
+ "gitHead": "79cd3e66871804a22c672c7ca2fa5e2105d4b368"
47
47
  }
package/provisioner.d.ts CHANGED
@@ -85,6 +85,10 @@ export declare class BucketProvisioner {
85
85
  bucketExists(bucketName: string): Promise<boolean>;
86
86
  /**
87
87
  * Configure S3 Block Public Access settings.
88
+ *
89
+ * Gracefully skips if the S3-compatible backend (e.g. MinIO) does not
90
+ * support PutPublicAccessBlock — the operation is best-effort since
91
+ * not all providers implement this AWS-specific API.
88
92
  */
89
93
  setPublicAccessBlock(bucketName: string, config: PublicAccessBlockConfig): Promise<void>;
90
94
  /**
@@ -93,10 +97,17 @@ export declare class BucketProvisioner {
93
97
  setBucketPolicy(bucketName: string, policy: BucketPolicyDocument): Promise<void>;
94
98
  /**
95
99
  * Delete an S3 bucket policy (used to clear leftover public policies).
100
+ *
101
+ * Gracefully handles backends that don't support this operation or have
102
+ * no policy to delete.
96
103
  */
97
104
  deleteBucketPolicy(bucketName: string): Promise<void>;
98
105
  /**
99
106
  * Set CORS configuration on an S3 bucket.
107
+ *
108
+ * Gracefully skips if the S3-compatible backend (e.g. older MinIO) does
109
+ * not support PutBucketCors — CORS is best-effort since not all providers
110
+ * implement this API via the same endpoint path.
100
111
  */
101
112
  setCors(bucketName: string, rules: CorsRule[]): Promise<void>;
102
113
  /**
package/provisioner.js CHANGED
@@ -171,6 +171,10 @@ class BucketProvisioner {
171
171
  }
172
172
  /**
173
173
  * Configure S3 Block Public Access settings.
174
+ *
175
+ * Gracefully skips if the S3-compatible backend (e.g. MinIO) does not
176
+ * support PutPublicAccessBlock — the operation is best-effort since
177
+ * not all providers implement this AWS-specific API.
174
178
  */
175
179
  async setPublicAccessBlock(bucketName, config) {
176
180
  try {
@@ -180,6 +184,18 @@ class BucketProvisioner {
180
184
  }));
181
185
  }
182
186
  catch (err) {
187
+ // Some S3-compatible backends (e.g. older MinIO) don't support
188
+ // PutPublicAccessBlock. Treat XML parse errors or "not implemented"
189
+ // responses as non-fatal — the bucket is still usable.
190
+ if (err.Code === 'XmlParseException' ||
191
+ err.name === 'XmlParseException' ||
192
+ err.Code === 'NotImplemented' ||
193
+ err.name === 'NotImplemented' ||
194
+ err.message?.includes('not well-formed') ||
195
+ err.message?.includes('not implemented') ||
196
+ err.message?.includes('PublicAccessBlockConfiguration')) {
197
+ return;
198
+ }
183
199
  throw new types_1.ProvisionerError('POLICY_FAILED', `Failed to set public access block on '${bucketName}': ${err.message}`, err);
184
200
  }
185
201
  }
@@ -199,6 +215,9 @@ class BucketProvisioner {
199
215
  }
200
216
  /**
201
217
  * Delete an S3 bucket policy (used to clear leftover public policies).
218
+ *
219
+ * Gracefully handles backends that don't support this operation or have
220
+ * no policy to delete.
202
221
  */
203
222
  async deleteBucketPolicy(bucketName) {
204
223
  try {
@@ -206,7 +225,14 @@ class BucketProvisioner {
206
225
  }
207
226
  catch (err) {
208
227
  // No policy to delete — that's fine
209
- if (err.name === 'NoSuchBucketPolicy' || err.$metadata?.httpStatusCode === 404) {
228
+ if (err.name === 'NoSuchBucketPolicy' ||
229
+ err.$metadata?.httpStatusCode === 404 ||
230
+ err.Code === 'XmlParseException' ||
231
+ err.name === 'XmlParseException' ||
232
+ err.Code === 'NotImplemented' ||
233
+ err.name === 'NotImplemented' ||
234
+ err.message?.includes('not well-formed') ||
235
+ err.message?.includes('not implemented')) {
210
236
  return;
211
237
  }
212
238
  throw new types_1.ProvisionerError('POLICY_FAILED', `Failed to delete bucket policy on '${bucketName}': ${err.message}`, err);
@@ -214,6 +240,10 @@ class BucketProvisioner {
214
240
  }
215
241
  /**
216
242
  * Set CORS configuration on an S3 bucket.
243
+ *
244
+ * Gracefully skips if the S3-compatible backend (e.g. older MinIO) does
245
+ * not support PutBucketCors — CORS is best-effort since not all providers
246
+ * implement this API via the same endpoint path.
217
247
  */
218
248
  async setCors(bucketName, rules) {
219
249
  try {
@@ -231,6 +261,18 @@ class BucketProvisioner {
231
261
  }));
232
262
  }
233
263
  catch (err) {
264
+ // Some S3-compatible backends (e.g. older MinIO) don't support
265
+ // PutBucketCors via the standard path. Treat XML parse errors or
266
+ // "not implemented" responses as non-fatal.
267
+ if (err.Code === 'XmlParseException' ||
268
+ err.name === 'XmlParseException' ||
269
+ err.Code === 'NotImplemented' ||
270
+ err.name === 'NotImplemented' ||
271
+ err.message?.includes('not well-formed') ||
272
+ err.message?.includes('not implemented') ||
273
+ err.message?.includes('CORSConfiguration')) {
274
+ return;
275
+ }
234
276
  throw new types_1.ProvisionerError('CORS_FAILED', `Failed to set CORS on '${bucketName}': ${err.message}`, err);
235
277
  }
236
278
  }