@awsless/awsless 0.0.491 → 0.0.493

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/bin.js CHANGED
@@ -1679,41 +1679,11 @@ var StoresSchema = z33.union([
1679
1679
  // src/feature/images/schema.ts
1680
1680
  import { z as z34 } from "zod";
1681
1681
  var transformationOptionsSchema = z34.object({
1682
- // Resize options
1683
1682
  width: z34.number().int().positive().optional(),
1684
1683
  height: z34.number().int().positive().optional(),
1685
1684
  fit: z34.enum(["cover", "contain", "fill", "inside", "outside"]).optional(),
1686
1685
  position: z34.enum(["top", "right top", "right", "right bottom", "bottom", "left bottom", "left", "left top", "center"]).optional(),
1687
- // Format options
1688
- quality: z34.number().int().min(1).max(100).optional(),
1689
- progressive: z34.boolean().optional(),
1690
- // Processing options
1691
- rotate: z34.number().optional(),
1692
- flip: z34.boolean().optional(),
1693
- flop: z34.boolean().optional(),
1694
- blur: z34.number().min(0.3).max(1e3).optional(),
1695
- sharpen: z34.boolean().optional(),
1696
- grayscale: z34.boolean().optional(),
1697
- normalize: z34.boolean().optional()
1698
- });
1699
- var extensionOptionsSchema = z34.object({
1700
- // WebP specific
1701
- effort: z34.number().int().min(0).max(6).optional(),
1702
- lossless: z34.boolean().optional(),
1703
- nearLossless: z34.boolean().optional(),
1704
- // smartSubsample: z.boolean().optional(),
1705
- // JPEG specific
1706
- mozjpeg: z34.boolean().optional(),
1707
- // trellisQuantisation: z.boolean().optional(),
1708
- // overshootDeringing: z.boolean().optional(),
1709
- // optimiseScans: z.boolean().optional(),
1710
- // PNG specific
1711
- compressionLevel: z34.number().int().min(0).max(9).optional(),
1712
- adaptiveFiltering: z34.boolean().optional(),
1713
- // palette: z.boolean().optional(),
1714
- // AVIF specific
1715
- speed: z34.number().int().min(0).max(9).optional()
1716
- // chromaSubsampling: z.string().optional(),
1686
+ quality: z34.number().int().min(1).max(100).optional()
1717
1687
  });
1718
1688
  var staticOriginSchema = LocalDirectorySchema.describe(
1719
1689
  "Specifies the path to a image directory that will be uploaded in S3."
@@ -1726,8 +1696,24 @@ var ImagesSchema = z34.record(
1726
1696
  z34.object({
1727
1697
  domain: ResourceIdSchema.describe("The domain id to link your site with.").optional(),
1728
1698
  subDomain: z34.string().optional(),
1699
+ log: LogSchema.optional(),
1729
1700
  presets: z34.record(z34.string(), transformationOptionsSchema).describe("Named presets for image transformations"),
1730
- extensions: z34.record(z34.enum(["jpeg", "jpg", "png", "webp"]), extensionOptionsSchema).describe("Format-specific optimization options"),
1701
+ extensions: z34.object({
1702
+ jpeg: z34.object({
1703
+ mozjpeg: z34.boolean().optional(),
1704
+ progressive: z34.boolean().optional()
1705
+ }).optional(),
1706
+ webp: z34.object({
1707
+ effort: z34.number().int().min(0).max(6).optional(),
1708
+ lossless: z34.boolean().optional(),
1709
+ nearLossless: z34.boolean().optional()
1710
+ }).optional(),
1711
+ png: z34.object({
1712
+ compressionLevel: z34.number().int().min(0).max(9).optional()
1713
+ }).optional()
1714
+ }).refine((data) => {
1715
+ return Object.keys(data).length > 0;
1716
+ }, "At least one extension must be defined.").describe("Image format-specific options for transformations"),
1731
1717
  origin: z34.union([
1732
1718
  z34.object({
1733
1719
  static: staticOriginSchema,
@@ -1743,7 +1729,8 @@ var ImagesSchema = z34.record(
1743
1729
  })
1744
1730
  ]).describe(
1745
1731
  "Image transformation will be applied from a base image. Base images orginates from a local directory that will be uploaded to S3 or from a lambda function."
1746
- )
1732
+ ),
1733
+ version: z34.number().int().min(1).optional().describe("Version of the image configuration.")
1747
1734
  // postprocess: FunctionSchema.optional()
1748
1735
  })
1749
1736
  ).optional().describe("Define image CDN & transformations in your stack.");
@@ -2645,7 +2632,7 @@ var configFeature = defineFeature({
2645
2632
  import { $ as $4, Group as Group4 } from "@awsless/formation";
2646
2633
 
2647
2634
  // src/feature/function/util.ts
2648
- import { $ as $3, Future, resolveInputs } from "@awsless/formation";
2635
+ import { $ as $3, Future, Group as Group3, resolveInputs } from "@awsless/formation";
2649
2636
  import { generateFileHash } from "@awsless/ts-file-cache";
2650
2637
  import deepmerge from "deepmerge";
2651
2638
  import { basename as basename3 } from "path";
@@ -2934,9 +2921,10 @@ var zipBundle = async ({ directory }) => {
2934
2921
  };
2935
2922
 
2936
2923
  // src/feature/function/util.ts
2937
- var createLambdaFunction = (group, ctx, ns, id, local) => {
2924
+ var createLambdaFunction = (parentGroup, ctx, ns, id, local) => {
2938
2925
  let name;
2939
2926
  let shortName;
2927
+ const group = new Group3(parentGroup, "function", ns);
2940
2928
  if ("stack" in ctx) {
2941
2929
  name = formatLocalResourceName({
2942
2930
  appName: ctx.app.name,
@@ -2944,12 +2932,7 @@ var createLambdaFunction = (group, ctx, ns, id, local) => {
2944
2932
  resourceType: ns,
2945
2933
  resourceName: id
2946
2934
  });
2947
- shortName = formatLocalResourceName({
2948
- appName: ctx.app.name,
2949
- stackName: ctx.stack.name,
2950
- resourceType: ns,
2951
- resourceName: shortId(`${id}:${ctx.appId}`)
2952
- });
2935
+ shortName = shortId(`${ctx.app.name}:${ctx.stack.name}:${ns}:${id}:${ctx.appId}`);
2953
2936
  } else {
2954
2937
  name = formatGlobalResourceName({
2955
2938
  appName: ctx.app.name,
@@ -3197,7 +3180,7 @@ var createLambdaFunction = (group, ctx, ns, id, local) => {
3197
3180
  if (props.warm) {
3198
3181
  const rule = new $3.aws.cloudwatch.EventRule(group, "warm", {
3199
3182
  name: `${shortName}--warm`,
3200
- description: `Lambda Warm ${id}`,
3183
+ description: name,
3201
3184
  scheduleExpression: "rate(5 minutes)",
3202
3185
  isEnabled: true
3203
3186
  });
@@ -3222,6 +3205,7 @@ var createLambdaFunction = (group, ctx, ns, id, local) => {
3222
3205
  lambda,
3223
3206
  policy,
3224
3207
  code,
3208
+ group,
3225
3209
  setEnvironment(name2, value) {
3226
3210
  variables[name2] = value;
3227
3211
  },
@@ -4109,6 +4093,10 @@ var createPrebuildLambdaFunction = (group, ctx, ns, id, props) => {
4109
4093
  })
4110
4094
  });
4111
4095
  const variables = {};
4096
+ const logFormats = {
4097
+ text: "Text",
4098
+ json: "JSON"
4099
+ };
4112
4100
  const lambda = new $12.aws.lambda.Function(group, `function`, {
4113
4101
  functionName: name,
4114
4102
  role: role.arn,
@@ -4133,9 +4121,10 @@ var createPrebuildLambdaFunction = (group, ctx, ns, id, props) => {
4133
4121
  variables
4134
4122
  },
4135
4123
  loggingConfig: {
4136
- logFormat: "JSON",
4137
- applicationLogLevel: "ERROR",
4138
- systemLogLevel: "WARN"
4124
+ logGroup: `/aws/lambda/${name}`,
4125
+ logFormat: logFormats[props.log && "format" in props.log && props.log.format || "json"],
4126
+ applicationLogLevel: props.log && "format" in props.log && props.log.format === "json" ? props.log.level?.toUpperCase() : void 0,
4127
+ systemLogLevel: props.log && "format" in props.log && props.log.format === "json" ? props.log.system?.toUpperCase() : void 0
4139
4128
  }
4140
4129
  });
4141
4130
  ctx.onEnv((name2, value) => {
@@ -5845,18 +5834,52 @@ var layerFeature = defineFeature({
5845
5834
 
5846
5835
  // src/feature/images/index.ts
5847
5836
  import { $ as $22, Group as Group23 } from "@awsless/formation";
5848
- import { glob as glob3 } from "glob";
5849
- import { join as join12, extname as extname3, dirname as dirname8 } from "path";
5850
- import { contentType as contentType2 } from "mime-types";
5851
- import { Future as Future4 } from "@awsless/formation";
5852
- import { createHash as createHash5 } from "crypto";
5837
+ import { join as join12, dirname as dirname8 } from "path";
5853
5838
  import { mebibytes as mebibytes4 } from "@awsless/size";
5854
- import { days as days6, seconds as seconds9, toSeconds as toSeconds8, weeks } from "@awsless/duration";
5839
+ import { days as days6, seconds as seconds9, toSeconds as toSeconds8 } from "@awsless/duration";
5855
5840
  import { constantCase as constantCase11 } from "change-case";
5856
5841
  import { fileURLToPath as fileURLToPath2 } from "url";
5842
+ import { glob as glob3 } from "glob";
5857
5843
  var __dirname2 = dirname8(fileURLToPath2(import.meta.url));
5858
5844
  var imagesFeature = defineFeature({
5859
5845
  name: "images",
5846
+ onApp(ctx) {
5847
+ const found = ctx.stackConfigs.filter((stack) => {
5848
+ return Object.keys(stack.images ?? {}).length > 0;
5849
+ });
5850
+ if (!found) {
5851
+ return;
5852
+ }
5853
+ const group = new Group23(ctx.base, "image", "layer");
5854
+ const path = join12(__dirname2, "/layers/sharp-arm.zip");
5855
+ const layerId = formatGlobalResourceName({
5856
+ appName: ctx.appConfig.name,
5857
+ resourceType: "layer",
5858
+ resourceName: "sharp"
5859
+ });
5860
+ const zipFile = new $22.aws.s3.BucketObject(group, "layer", {
5861
+ bucket: ctx.shared.get("layer", "bucket-name"),
5862
+ key: `/layer/${layerId}.zip`,
5863
+ contentType: "application/zip",
5864
+ source: path,
5865
+ sourceHash: $hash(path)
5866
+ });
5867
+ const layer = new $22.aws.lambda.LayerVersion(group, "layer", {
5868
+ layerName: layerId,
5869
+ description: "sharp-arm.zip for the awsless images feature.",
5870
+ compatibleArchitectures: ["arm64"],
5871
+ s3Bucket: zipFile.bucket,
5872
+ s3ObjectVersion: zipFile.versionId,
5873
+ s3Key: zipFile.key.pipe((name) => {
5874
+ if (name.startsWith("/")) {
5875
+ return name.substring(1);
5876
+ }
5877
+ return name;
5878
+ }),
5879
+ sourceCodeHash: $hash(path)
5880
+ });
5881
+ ctx.shared.add("layer", "arn", layerId, layer.arn);
5882
+ },
5860
5883
  onStack(ctx) {
5861
5884
  for (const [id, props] of Object.entries(ctx.stackConfig.images ?? {})) {
5862
5885
  const group = new Group23(ctx.stack, "images", id);
@@ -5866,14 +5889,13 @@ var imagesFeature = defineFeature({
5866
5889
  resourceType: "images",
5867
5890
  resourceName: id
5868
5891
  });
5869
- const originGroup = new Group23(ctx.stack, "images-origins", id);
5870
5892
  let lambdaOrigin = void 0;
5871
5893
  if (props.origin.function) {
5872
- lambdaOrigin = createLambdaFunction(originGroup, ctx, `lambda-origin`, id, props.origin.function);
5894
+ lambdaOrigin = createLambdaFunction(group, ctx, `origin`, id, props.origin.function);
5873
5895
  }
5874
5896
  let s3Origin;
5875
5897
  if (props.origin.static) {
5876
- s3Origin = new $22.aws.s3.Bucket(originGroup, "bucket", {
5898
+ s3Origin = new $22.aws.s3.Bucket(group, "origin", {
5877
5899
  bucket: formatLocalResourceName({
5878
5900
  appName: ctx.app.name,
5879
5901
  stackName: ctx.stack.name,
@@ -5884,43 +5906,21 @@ var imagesFeature = defineFeature({
5884
5906
  forceDestroy: true
5885
5907
  });
5886
5908
  }
5887
- const path = join12(__dirname2, "/layers/sharp-arm.zip");
5888
- const layerId = formatLocalResourceName({
5909
+ const cacheBucket = new $22.aws.s3.Bucket(group, "cache", {
5910
+ bucket: formatLocalResourceName({
5911
+ appName: ctx.app.name,
5912
+ stackName: ctx.stack.name,
5913
+ resourceType: "images",
5914
+ resourceName: `cache-${id}`,
5915
+ postfix: ctx.appId
5916
+ }),
5917
+ forceDestroy: true
5918
+ });
5919
+ const sharpLayerId = formatGlobalResourceName({
5889
5920
  appName: ctx.appConfig.name,
5890
- stackName: ctx.stack.name,
5891
5921
  resourceType: "layer",
5892
- resourceName: shortId(id)
5922
+ resourceName: "sharp"
5893
5923
  });
5894
- const zipFile = new $22.aws.s3.BucketObject(group, "layer-zip", {
5895
- bucket: ctx.shared.get("layer", "bucket-name"),
5896
- key: `/layer/${layerId}.zip`,
5897
- contentType: "application/zip",
5898
- source: path,
5899
- sourceHash: $hash(path)
5900
- });
5901
- const layer = new $22.aws.lambda.LayerVersion(
5902
- group,
5903
- "layer",
5904
- {
5905
- layerName: layerId,
5906
- description: "sharp-arm.zip for the awsless images feature.",
5907
- compatibleArchitectures: ["arm64"],
5908
- compatibleRuntimes: ["nodejs22.x"],
5909
- s3Bucket: zipFile.bucket,
5910
- s3ObjectVersion: zipFile.versionId,
5911
- s3Key: zipFile.key.pipe((name2) => {
5912
- if (name2.startsWith("/")) {
5913
- return name2.substring(1);
5914
- }
5915
- return name2;
5916
- }),
5917
- sourceCodeHash: $hash(path)
5918
- },
5919
- {
5920
- dependsOn: [zipFile]
5921
- }
5922
- );
5923
- ctx.shared.add("layer", "arn", layerId, layer.arn);
5924
5924
  const transformFn = createPrebuildLambdaFunction(group, ctx, "images", id, {
5925
5925
  bundleFile: join12(__dirname2, "/prebuild/images/bundle.zip"),
5926
5926
  bundleHash: join12(__dirname2, "/prebuild/images/HASH"),
@@ -5928,17 +5928,8 @@ var imagesFeature = defineFeature({
5928
5928
  timeout: seconds9(10),
5929
5929
  handler: "index.default",
5930
5930
  runtime: "nodejs22.x",
5931
- log: { retention: weeks(2) },
5932
- layers: [layerId]
5933
- });
5934
- new UpdateFunctionCode(group, "update", {
5935
- version: transformFn.code.sourceHash,
5936
- functionName: transformFn.lambda.functionName,
5937
- architectures: transformFn.lambda.architectures,
5938
- s3Bucket: transformFn.lambda.s3Bucket,
5939
- s3Key: transformFn.lambda.s3Key,
5940
- s3ObjectVersion: transformFn.lambda.s3ObjectVersion,
5941
- imageUri: transformFn.lambda.imageUri
5931
+ log: props.log,
5932
+ layers: [sharpLayerId]
5942
5933
  });
5943
5934
  const permission = new $22.aws.lambda.Permission(group, "permission", {
5944
5935
  principal: "cloudfront.amazonaws.com",
@@ -5956,37 +5947,38 @@ var imagesFeature = defineFeature({
5956
5947
  },
5957
5948
  { dependsOn: [permission] }
5958
5949
  );
5950
+ transformFn.addPermission({
5951
+ actions: [
5952
+ "s3:ListBucket",
5953
+ "s3:ListBucketV2",
5954
+ "s3:HeadObject",
5955
+ "s3:GetObject",
5956
+ "s3:PutObject",
5957
+ "s3:DeleteObject",
5958
+ "s3:GetObjectAttributes"
5959
+ ],
5960
+ resources: [
5961
+ //
5962
+ cacheBucket.arn,
5963
+ cacheBucket.arn.pipe((arn) => `${arn}/*`),
5964
+ ...s3Origin ? [s3Origin.arn, s3Origin.arn.pipe((arn) => `${arn}/*`)] : []
5965
+ ]
5966
+ });
5959
5967
  transformFn.setEnvironment(
5960
5968
  "IMAGES_CONFIG",
5961
5969
  JSON.stringify({
5962
5970
  presets: props.presets,
5963
- extensions: props.extensions
5971
+ extensions: props.extensions,
5972
+ version: props.version
5964
5973
  })
5965
5974
  );
5975
+ transformFn.setEnvironment("IMAGES_CACHE_BUCKET", cacheBucket.bucket);
5966
5976
  if (lambdaOrigin) {
5967
5977
  transformFn.setEnvironment("IMAGES_ORIGIN_LAMBDA", lambdaOrigin.name);
5968
5978
  }
5969
5979
  if (s3Origin) {
5970
5980
  transformFn.setEnvironment("IMAGES_ORIGIN_S3", s3Origin.bucket);
5971
- transformFn.addPermission({
5972
- actions: [
5973
- "s3:ListBucket",
5974
- "s3:ListBucketV2",
5975
- "s3:HeadObject",
5976
- "s3:GetObject",
5977
- "s3:PutObject",
5978
- "s3:DeleteObject",
5979
- // 's3:CopyObject',
5980
- "s3:GetObjectAttributes"
5981
- ],
5982
- resources: [
5983
- //
5984
- s3Origin.arn,
5985
- s3Origin.arn.pipe((arn) => `${arn}/*`)
5986
- ]
5987
- });
5988
5981
  }
5989
- const versions = [];
5990
5982
  ctx.onReady(() => {
5991
5983
  if (props.origin.static && s3Origin) {
5992
5984
  const files = glob3.sync("**", {
@@ -5994,23 +5986,26 @@ var imagesFeature = defineFeature({
5994
5986
  nodir: true
5995
5987
  });
5996
5988
  for (const file of files) {
5997
- const object = new $22.aws.s3.BucketObject(group, `static-${file}`, {
5989
+ new $22.aws.s3.BucketObject(group, `static-${file}`, {
5998
5990
  bucket: s3Origin.bucket,
5999
5991
  key: file,
6000
- cacheControl: "public, max-age=31536000, immutable",
6001
- contentType: contentType2(extname3(file)) || `image/${extname3(file).slice(1)}`,
6002
5992
  source: join12(props.origin.static, file),
6003
5993
  sourceHash: $hash(join12(props.origin.static, file))
6004
5994
  });
6005
- versions.push(object.key);
6006
- versions.push(object.sourceHash);
6007
5995
  }
6008
5996
  }
6009
5997
  });
6010
5998
  const domainName = props.domain ? formatFullDomainName(ctx.appConfig, props.domain, props.subDomain) : void 0;
6011
5999
  const certificateArn = props.domain ? ctx.shared.entry("domain", `global-certificate-arn`, props.domain) : void 0;
6012
- const accessControl = new $22.aws.cloudfront.OriginAccessControl(group, "access", {
6013
- name,
6000
+ const s3AccessControl = new $22.aws.cloudfront.OriginAccessControl(group, `s3`, {
6001
+ name: `${name}-s3`,
6002
+ description: "Policy for Images cache in S3",
6003
+ originAccessControlOriginType: "s3",
6004
+ signingBehavior: "always",
6005
+ signingProtocol: "sigv4"
6006
+ });
6007
+ const lambdaAccessControl = new $22.aws.cloudfront.OriginAccessControl(group, "lambda", {
6008
+ name: `${name}-lambda`,
6014
6009
  description: "Policy for Images Lambda Transformation Function URL",
6015
6010
  originAccessControlOriginType: "lambda",
6016
6011
  signingBehavior: "always",
@@ -6035,9 +6030,18 @@ var imagesFeature = defineFeature({
6035
6030
  },
6036
6031
  origin: [
6037
6032
  {
6038
- originId: "default",
6033
+ originId: "cache",
6034
+ domainName: cacheBucket.bucketRegionalDomainName,
6035
+ originAccessControlId: s3AccessControl.id,
6036
+ s3OriginConfig: {
6037
+ // is required to have an value for s3 origins when using origin access control
6038
+ originAccessIdentity: ""
6039
+ }
6040
+ },
6041
+ {
6042
+ originId: "transform",
6039
6043
  domainName: transformFnUrl.functionUrl.pipe((url) => url.split("/")[2]),
6040
- originAccessControlId: accessControl.id,
6044
+ originAccessControlId: lambdaAccessControl.id,
6041
6045
  customOriginConfig: {
6042
6046
  originProtocolPolicy: "https-only",
6043
6047
  httpPort: 80,
@@ -6046,26 +6050,54 @@ var imagesFeature = defineFeature({
6046
6050
  }
6047
6051
  }
6048
6052
  ],
6053
+ originGroup: [
6054
+ {
6055
+ originId: "group",
6056
+ member: [{ originId: "cache" }, { originId: "transform" }],
6057
+ failoverCriteria: {
6058
+ statusCodes: [403, 404]
6059
+ }
6060
+ }
6061
+ ],
6049
6062
  defaultCacheBehavior: {
6050
6063
  compress: true,
6051
- targetOriginId: "default",
6064
+ targetOriginId: "group",
6052
6065
  cachePolicyId: cache.id,
6053
6066
  viewerProtocolPolicy: "redirect-to-https",
6054
6067
  allowedMethods: ["GET", "HEAD"],
6055
6068
  cachedMethods: ["GET", "HEAD"]
6056
6069
  }
6057
6070
  });
6058
- new Invalidation(group, "invalidate", {
6059
- distributionId: distribution.id,
6060
- paths: ["/*"],
6061
- version: new Future4((resolve) => {
6062
- $combine(...versions).then((versions2) => {
6063
- const combined = versions2.filter((v) => !!v).sort().join(",");
6064
- const version = createHash5("sha1").update(combined).digest("hex");
6065
- resolve(version);
6066
- });
6067
- })
6068
- });
6071
+ new $22.aws.s3.BucketPolicy(
6072
+ group,
6073
+ `policy`,
6074
+ {
6075
+ bucket: cacheBucket.bucket,
6076
+ policy: $resolve([cacheBucket.arn, distribution.id], (arn, id2) => {
6077
+ return JSON.stringify({
6078
+ Version: "2012-10-17",
6079
+ Statement: [
6080
+ {
6081
+ Effect: "Allow",
6082
+ Action: "s3:GetObject",
6083
+ Resource: `${arn}/*`,
6084
+ Principal: {
6085
+ Service: "cloudfront.amazonaws.com"
6086
+ },
6087
+ Condition: {
6088
+ StringEquals: {
6089
+ "AWS:SourceArn": `arn:aws:cloudfront::${ctx.accountId}:distribution/${id2}`
6090
+ }
6091
+ }
6092
+ }
6093
+ ]
6094
+ });
6095
+ })
6096
+ },
6097
+ {
6098
+ dependsOn: [cacheBucket, distribution]
6099
+ }
6100
+ );
6069
6101
  if (domainName) {
6070
6102
  new $22.aws.route53.Record(group, `record`, {
6071
6103
  zoneId: ctx.shared.entry("domain", "zone-id", props.domain),
@@ -6983,9 +7015,9 @@ import { join as join15 } from "path";
6983
7015
  import wildstring3 from "wildstring";
6984
7016
 
6985
7017
  // src/build/__fingerprint.ts
6986
- import { createHash as createHash6 } from "crypto";
7018
+ import { createHash as createHash5 } from "crypto";
6987
7019
  import { readdir as readdir4, readFile as readFile4, stat as stat4 } from "fs/promises";
6988
- import { basename as basename4, dirname as dirname9, extname as extname4, join as join13 } from "path";
7020
+ import { basename as basename4, dirname as dirname9, extname as extname3, join as join13 } from "path";
6989
7021
  import parseStaticImports from "parse-static-imports";
6990
7022
  var extensions = ["js", "mjs", "jsx", "ts", "mts", "tsx"];
6991
7023
  var generateFileHashes = async (file, hashes) => {
@@ -6994,7 +7026,7 @@ var generateFileHashes = async (file, hashes) => {
6994
7026
  }
6995
7027
  const code = await readModuleFile(file);
6996
7028
  const deps = await findDependencies(file, code);
6997
- const hash = createHash6("sha1").update(code).digest();
7029
+ const hash = createHash5("sha1").update(code).digest();
6998
7030
  hashes.set(file, hash);
6999
7031
  for (const dep of deps) {
7000
7032
  if (dep.startsWith("/")) {
@@ -7006,12 +7038,12 @@ var fingerprintFromDirectory = async (dir) => {
7006
7038
  const hashes = /* @__PURE__ */ new Map();
7007
7039
  const files = await readdir4(dir, { recursive: true });
7008
7040
  for (const file of files) {
7009
- if (extensions.includes(extname4(file).substring(1)) && file.at(0) !== "_") {
7041
+ if (extensions.includes(extname3(file).substring(1)) && file.at(0) !== "_") {
7010
7042
  await generateFileHashes(join13(dir, file), hashes);
7011
7043
  }
7012
7044
  }
7013
7045
  const merge2 = Buffer.concat(Array.from(hashes.values()).sort());
7014
- return createHash6("sha1").update(merge2).digest("hex");
7046
+ return createHash5("sha1").update(merge2).digest("hex");
7015
7047
  };
7016
7048
  var readModuleFile = (file) => {
7017
7049
  if (file.endsWith(".js")) {
@@ -1053,41 +1053,11 @@ var StoresSchema = z30.union([
1053
1053
  // src/feature/images/schema.ts
1054
1054
  import { z as z31 } from "zod";
1055
1055
  var transformationOptionsSchema = z31.object({
1056
- // Resize options
1057
1056
  width: z31.number().int().positive().optional(),
1058
1057
  height: z31.number().int().positive().optional(),
1059
1058
  fit: z31.enum(["cover", "contain", "fill", "inside", "outside"]).optional(),
1060
1059
  position: z31.enum(["top", "right top", "right", "right bottom", "bottom", "left bottom", "left", "left top", "center"]).optional(),
1061
- // Format options
1062
- quality: z31.number().int().min(1).max(100).optional(),
1063
- progressive: z31.boolean().optional(),
1064
- // Processing options
1065
- rotate: z31.number().optional(),
1066
- flip: z31.boolean().optional(),
1067
- flop: z31.boolean().optional(),
1068
- blur: z31.number().min(0.3).max(1e3).optional(),
1069
- sharpen: z31.boolean().optional(),
1070
- grayscale: z31.boolean().optional(),
1071
- normalize: z31.boolean().optional()
1072
- });
1073
- var extensionOptionsSchema = z31.object({
1074
- // WebP specific
1075
- effort: z31.number().int().min(0).max(6).optional(),
1076
- lossless: z31.boolean().optional(),
1077
- nearLossless: z31.boolean().optional(),
1078
- // smartSubsample: z.boolean().optional(),
1079
- // JPEG specific
1080
- mozjpeg: z31.boolean().optional(),
1081
- // trellisQuantisation: z.boolean().optional(),
1082
- // overshootDeringing: z.boolean().optional(),
1083
- // optimiseScans: z.boolean().optional(),
1084
- // PNG specific
1085
- compressionLevel: z31.number().int().min(0).max(9).optional(),
1086
- adaptiveFiltering: z31.boolean().optional(),
1087
- // palette: z.boolean().optional(),
1088
- // AVIF specific
1089
- speed: z31.number().int().min(0).max(9).optional()
1090
- // chromaSubsampling: z.string().optional(),
1060
+ quality: z31.number().int().min(1).max(100).optional()
1091
1061
  });
1092
1062
  var staticOriginSchema = LocalDirectorySchema.describe(
1093
1063
  "Specifies the path to a image directory that will be uploaded in S3."
@@ -1100,8 +1070,24 @@ var ImagesSchema = z31.record(
1100
1070
  z31.object({
1101
1071
  domain: ResourceIdSchema.describe("The domain id to link your site with.").optional(),
1102
1072
  subDomain: z31.string().optional(),
1073
+ log: LogSchema.optional(),
1103
1074
  presets: z31.record(z31.string(), transformationOptionsSchema).describe("Named presets for image transformations"),
1104
- extensions: z31.record(z31.enum(["jpeg", "jpg", "png", "webp"]), extensionOptionsSchema).describe("Format-specific optimization options"),
1075
+ extensions: z31.object({
1076
+ jpeg: z31.object({
1077
+ mozjpeg: z31.boolean().optional(),
1078
+ progressive: z31.boolean().optional()
1079
+ }).optional(),
1080
+ webp: z31.object({
1081
+ effort: z31.number().int().min(0).max(6).optional(),
1082
+ lossless: z31.boolean().optional(),
1083
+ nearLossless: z31.boolean().optional()
1084
+ }).optional(),
1085
+ png: z31.object({
1086
+ compressionLevel: z31.number().int().min(0).max(9).optional()
1087
+ }).optional()
1088
+ }).refine((data) => {
1089
+ return Object.keys(data).length > 0;
1090
+ }, "At least one extension must be defined.").describe("Image format-specific options for transformations"),
1105
1091
  origin: z31.union([
1106
1092
  z31.object({
1107
1093
  static: staticOriginSchema,
@@ -1117,7 +1103,8 @@ var ImagesSchema = z31.record(
1117
1103
  })
1118
1104
  ]).describe(
1119
1105
  "Image transformation will be applied from a base image. Base images orginates from a local directory that will be uploaded to S3 or from a lambda function."
1120
- )
1106
+ ),
1107
+ version: z31.number().int().min(1).optional().describe("Version of the image configuration.")
1121
1108
  // postprocess: FunctionSchema.optional()
1122
1109
  })
1123
1110
  ).optional().describe("Define image CDN & transformations in your stack.");
@@ -1 +1 @@
1
- aff78a96da73334952084c182d6677419c448866
1
+ 926a68186dbe9b6df8e8fe21bddf53dee7499436
Binary file
Binary file