@everystack/server 0.2.5 → 0.2.6

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.
Files changed (3) hide show
  1. package/README.md +15 -1
  2. package/package.json +1 -1
  3. package/src/image.ts +43 -4
package/README.md CHANGED
@@ -156,7 +156,7 @@ interface ImageHandlerConfig {
156
156
  bucket: string; // S3 bucket name
157
157
  region?: string; // AWS region (default: AWS_REGION env)
158
158
  pathPrefix?: string; // URL prefix (default: '/media/')
159
- cacheControl?: string; // Cache-Control header (default: 'public, max-age=60, s-maxage=2592000, stale-while-revalidate=5')
159
+ cacheControl?: string; // Cache-Control header (default: 'public, max-age=86400, s-maxage=31536000, stale-while-revalidate=60')
160
160
  validateKey?: (key: string) => boolean | Promise<boolean>; // Optional key validator
161
161
  s3Cache?: { // Persist rendered images to S3 (skip Sharp on repeat requests)
162
162
  enabled: boolean;
@@ -185,6 +185,20 @@ const deleted = await deleteImageCache('my-bucket', 'uploads/photo.jpg');
185
185
 
186
186
  Options: `{ region?: string; prefix?: string }` (prefix defaults to `'cache/'`).
187
187
 
188
+ ### `purgeImage(bucket, key, options?)`
189
+
190
+ Delete all S3 cached renders and invalidate CloudFront cache for an image. Combines `deleteImageCache` with KVS path invalidation.
191
+
192
+ ```typescript
193
+ import { purgeImage } from '@everystack/server/image';
194
+
195
+ const { deleted, invalidated } = await purgeImage('my-bucket', 'uploads/photo.jpg', {
196
+ kvsArn: process.env.KVS_ARN,
197
+ });
198
+ ```
199
+
200
+ Options: `{ region?: string; prefix?: string; kvsArn?: string; pathPrefix?: string }`. KVS invalidation is skipped when `kvsArn` is omitted.
201
+
188
202
  ### `parseParams(query)`
189
203
 
190
204
  Validates URL query params into transform options:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@everystack/server",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
4
4
  "description": "Server runtime primitives for Lambda — event adapters, routing, SSR, image processing",
5
5
  "license": "AGPL-3.0-only",
6
6
  "publishConfig": {
package/src/image.ts CHANGED
@@ -30,8 +30,8 @@ export interface ImageHandlerConfig {
30
30
  region?: string;
31
31
  /** URL path prefix to strip (defaults to '/media/') */
32
32
  pathPrefix?: string;
33
- /** Cache-Control for image responses.
34
- * Default: 'public, max-age=60, s-maxage=2592000, stale-while-revalidate=5' */
33
+ /** Cache-Control for image responses and S3 cached renders.
34
+ * Default: 'public, max-age=86400, s-maxage=31536000, stale-while-revalidate=60' */
35
35
  cacheControl?: string;
36
36
  /**
37
37
  * Optional key validator. Called before fetching from S3.
@@ -246,7 +246,7 @@ export function createImageHandler(
246
246
  const client = new S3Client({ region });
247
247
 
248
248
  const cacheHeaders = {
249
- 'Cache-Control': config.cacheControl ?? 'public, max-age=60, s-maxage=2592000, stale-while-revalidate=5',
249
+ 'Cache-Control': config.cacheControl ?? 'public, max-age=86400, s-maxage=31536000, stale-while-revalidate=60',
250
250
  'Vary': 'Accept',
251
251
  };
252
252
 
@@ -405,7 +405,7 @@ export function createImageHandler(
405
405
  Key: s3CacheKey,
406
406
  Body: processed.data,
407
407
  ContentType: processed.contentType,
408
- CacheControl: 'public, max-age=2592000',
408
+ CacheControl: cacheHeaders['Cache-Control'],
409
409
  })
410
410
  )
411
411
  .catch((err: unknown) => {
@@ -478,3 +478,42 @@ export async function deleteImageCache(
478
478
 
479
479
  return deleted;
480
480
  }
481
+
482
+ /**
483
+ * Purge an image: delete all S3 cached renders and invalidate CloudFront.
484
+ *
485
+ * Call this when an original image is deleted or replaced. Combines
486
+ * `deleteImageCache()` (S3 cleanup) with KVS path invalidation
487
+ * (CloudFront cache expiry for all variants of the image).
488
+ *
489
+ * KVS invalidation is optional — when `kvsArn` is omitted, only S3
490
+ * cached renders are deleted.
491
+ */
492
+ export async function purgeImage(
493
+ bucket: string,
494
+ key: string,
495
+ options?: {
496
+ region?: string;
497
+ /** S3 cache prefix. Default: 'cache/' */
498
+ prefix?: string;
499
+ /** CloudFront KVS ARN. When provided, invalidates CDN cache. */
500
+ kvsArn?: string;
501
+ /** URL path prefix for CDN invalidation. Default: '/media/' */
502
+ pathPrefix?: string;
503
+ }
504
+ ): Promise<{ deleted: number; invalidated: boolean }> {
505
+ const deleted = await deleteImageCache(bucket, key, {
506
+ region: options?.region,
507
+ prefix: options?.prefix,
508
+ });
509
+
510
+ let invalidated = false;
511
+ if (options?.kvsArn) {
512
+ const { invalidateKvsPaths } = await import('./kvs.js');
513
+ const mediaPath = (options.pathPrefix ?? '/media/') + key;
514
+ await invalidateKvsPaths(options.kvsArn, [mediaPath]);
515
+ invalidated = true;
516
+ }
517
+
518
+ return { deleted, invalidated };
519
+ }