@awsless/awsless 0.0.488 → 0.0.490
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 +401 -79
- package/dist/build-json-schema.js +104 -31
- package/dist/layers/sharp-arm.zip +0 -0
- package/dist/prebuild/images/HASH +1 -0
- package/dist/prebuild/images/bundle.zip +0 -0
- package/dist/prebuild/rpc/bundle.zip +0 -0
- package/dist/prebuild.js +5 -4
- package/dist/stack.json +1 -1
- package/package.json +15 -13
package/dist/bin.js
CHANGED
|
@@ -861,7 +861,7 @@ var LogRetentionSchema = DurationSchema.refine(
|
|
|
861
861
|
(duration) => {
|
|
862
862
|
return validLogRetentionDays.includes(toDays(duration));
|
|
863
863
|
},
|
|
864
|
-
`Invalid log retention. Valid days are: ${validLogRetentionDays.map((
|
|
864
|
+
`Invalid log retention. Valid days are: ${validLogRetentionDays.map((days7) => `${days7}`).join(", ")}`
|
|
865
865
|
).describe("The log retention duration.");
|
|
866
866
|
var LogSchema = z14.union([
|
|
867
867
|
z14.boolean().transform((enabled) => ({ retention: enabled ? days(7) : days(0) })),
|
|
@@ -1241,7 +1241,7 @@ var AppSchema = z24.object({
|
|
|
1241
1241
|
});
|
|
1242
1242
|
|
|
1243
1243
|
// src/config/stack.ts
|
|
1244
|
-
import { z as
|
|
1244
|
+
import { z as z39 } from "zod";
|
|
1245
1245
|
|
|
1246
1246
|
// src/feature/cache/schema.ts
|
|
1247
1247
|
import { gibibytes as gibibytes2 } from "@awsless/size";
|
|
@@ -1676,24 +1676,96 @@ var StoresSchema = z33.union([
|
|
|
1676
1676
|
)
|
|
1677
1677
|
]).optional().describe("Define the stores in your stack.");
|
|
1678
1678
|
|
|
1679
|
-
// src/feature/
|
|
1680
|
-
import { minutes as minutes4, seconds as seconds4 } from "@awsless/duration";
|
|
1679
|
+
// src/feature/images/schema.ts
|
|
1681
1680
|
import { z as z34 } from "zod";
|
|
1682
|
-
var
|
|
1683
|
-
|
|
1681
|
+
var transformationOptionsSchema = z34.object({
|
|
1682
|
+
// Resize options
|
|
1683
|
+
width: z34.number().int().positive().optional(),
|
|
1684
|
+
height: z34.number().int().positive().optional(),
|
|
1685
|
+
fit: z34.enum(["cover", "contain", "fill", "inside", "outside"]).optional(),
|
|
1686
|
+
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(),
|
|
1717
|
+
});
|
|
1718
|
+
var staticOriginSchema = LocalDirectorySchema.describe(
|
|
1719
|
+
"Specifies the path to a image directory that will be uploaded in S3."
|
|
1720
|
+
);
|
|
1721
|
+
var functionOriginSchema = FunctionSchema.describe(
|
|
1722
|
+
"Specifies the file that will be called when an image isn't found in the S3 bucket."
|
|
1723
|
+
);
|
|
1724
|
+
var ImagesSchema = z34.record(
|
|
1684
1725
|
ResourceIdSchema,
|
|
1685
1726
|
z34.object({
|
|
1727
|
+
domain: ResourceIdSchema.describe("The domain id to link your site with.").optional(),
|
|
1728
|
+
subDomain: z34.string().optional(),
|
|
1729
|
+
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"),
|
|
1731
|
+
origin: z34.union([
|
|
1732
|
+
z34.object({
|
|
1733
|
+
static: staticOriginSchema,
|
|
1734
|
+
function: functionOriginSchema.optional()
|
|
1735
|
+
}),
|
|
1736
|
+
z34.object({
|
|
1737
|
+
static: staticOriginSchema.optional(),
|
|
1738
|
+
function: functionOriginSchema
|
|
1739
|
+
}),
|
|
1740
|
+
z34.object({
|
|
1741
|
+
static: staticOriginSchema,
|
|
1742
|
+
function: functionOriginSchema
|
|
1743
|
+
})
|
|
1744
|
+
]).describe(
|
|
1745
|
+
"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
|
+
)
|
|
1747
|
+
// postprocess: FunctionSchema.optional()
|
|
1748
|
+
})
|
|
1749
|
+
).optional().describe("Define image CDN & transformations in your stack.");
|
|
1750
|
+
|
|
1751
|
+
// src/feature/table/schema.ts
|
|
1752
|
+
import { minutes as minutes4, seconds as seconds4 } from "@awsless/duration";
|
|
1753
|
+
import { z as z35 } from "zod";
|
|
1754
|
+
var KeySchema = z35.string().min(1).max(255);
|
|
1755
|
+
var TablesSchema = z35.record(
|
|
1756
|
+
ResourceIdSchema,
|
|
1757
|
+
z35.object({
|
|
1686
1758
|
hash: KeySchema.describe(
|
|
1687
1759
|
"Specifies the name of the partition / hash key that makes up the primary key for the table."
|
|
1688
1760
|
),
|
|
1689
1761
|
sort: KeySchema.optional().describe(
|
|
1690
1762
|
"Specifies the name of the range / sort key that makes up the primary key for the table."
|
|
1691
1763
|
),
|
|
1692
|
-
fields:
|
|
1764
|
+
fields: z35.record(z35.string(), z35.enum(["string", "number", "binary"])).optional().describe(
|
|
1693
1765
|
'A list of attributes that describe the key schema for the table and indexes. If no attribute field is defined we default to "string".'
|
|
1694
1766
|
),
|
|
1695
|
-
class:
|
|
1696
|
-
pointInTimeRecovery:
|
|
1767
|
+
class: z35.enum(["standard", "standard-infrequent-access"]).default("standard").describe("The table class of the table."),
|
|
1768
|
+
pointInTimeRecovery: z35.boolean().default(false).describe("Indicates whether point in time recovery is enabled on the table."),
|
|
1697
1769
|
ttl: KeySchema.optional().describe(
|
|
1698
1770
|
[
|
|
1699
1771
|
"The name of the TTL attribute used to store the expiration time for items in the table.",
|
|
@@ -1701,8 +1773,8 @@ var TablesSchema = z34.record(
|
|
|
1701
1773
|
].join("\n")
|
|
1702
1774
|
),
|
|
1703
1775
|
// deletionProtection: DeletionProtectionSchema.optional(),
|
|
1704
|
-
stream:
|
|
1705
|
-
type:
|
|
1776
|
+
stream: z35.object({
|
|
1777
|
+
type: z35.enum(["keys-only", "new-image", "old-image", "new-and-old-images"]).describe(
|
|
1706
1778
|
[
|
|
1707
1779
|
"When an item in the table is modified, you can determines what information is written to the stream for this table.",
|
|
1708
1780
|
"Valid values are:",
|
|
@@ -1712,7 +1784,7 @@ var TablesSchema = z34.record(
|
|
|
1712
1784
|
"- new-and-old-images - Both the new and the old item images of the item are written to the stream."
|
|
1713
1785
|
].join("\n")
|
|
1714
1786
|
),
|
|
1715
|
-
batchSize:
|
|
1787
|
+
batchSize: z35.number().min(1).max(1e4).default(1).describe(
|
|
1716
1788
|
[
|
|
1717
1789
|
"The maximum number of records in each batch that Lambda pulls from your stream and sends to your function.",
|
|
1718
1790
|
"Lambda passes all of the records in the batch to the function in a single call, up to the payload limit for synchronous invocation (6 MB).",
|
|
@@ -1742,7 +1814,7 @@ var TablesSchema = z34.record(
|
|
|
1742
1814
|
// 'You can specify a number from -1 to 10000.',
|
|
1743
1815
|
// ].join('\n')
|
|
1744
1816
|
// ),
|
|
1745
|
-
retryAttempts:
|
|
1817
|
+
retryAttempts: z35.number().min(-1).max(1e4).default(-1).describe(
|
|
1746
1818
|
[
|
|
1747
1819
|
"Discard records after the specified number of retries.",
|
|
1748
1820
|
"The default value is -1, which sets the maximum number of retries to infinite.",
|
|
@@ -1750,7 +1822,7 @@ var TablesSchema = z34.record(
|
|
|
1750
1822
|
"You can specify a number from -1 to 10000."
|
|
1751
1823
|
].join("\n")
|
|
1752
1824
|
),
|
|
1753
|
-
concurrencyPerShard:
|
|
1825
|
+
concurrencyPerShard: z35.number().min(1).max(10).default(1).describe(
|
|
1754
1826
|
[
|
|
1755
1827
|
"The number of batches to process concurrently from each shard.",
|
|
1756
1828
|
"You can specify a number from 1 to 10."
|
|
@@ -1760,16 +1832,16 @@ var TablesSchema = z34.record(
|
|
|
1760
1832
|
}).optional().describe(
|
|
1761
1833
|
"The settings for the DynamoDB table stream, which capture changes to items stored in the table."
|
|
1762
1834
|
),
|
|
1763
|
-
indexes:
|
|
1764
|
-
|
|
1765
|
-
|
|
1835
|
+
indexes: z35.record(
|
|
1836
|
+
z35.string(),
|
|
1837
|
+
z35.object({
|
|
1766
1838
|
hash: KeySchema.describe(
|
|
1767
1839
|
"Specifies the name of the partition / hash key that makes up the primary key for the global secondary index."
|
|
1768
1840
|
),
|
|
1769
1841
|
sort: KeySchema.optional().describe(
|
|
1770
1842
|
"Specifies the name of the range / sort key that makes up the primary key for the global secondary index."
|
|
1771
1843
|
),
|
|
1772
|
-
projection:
|
|
1844
|
+
projection: z35.enum(["all", "keys-only"]).default("all").describe(
|
|
1773
1845
|
[
|
|
1774
1846
|
"The set of attributes that are projected into the index:",
|
|
1775
1847
|
"- all - All of the table attributes are projected into the index.",
|
|
@@ -1783,11 +1855,11 @@ var TablesSchema = z34.record(
|
|
|
1783
1855
|
).optional().describe("Define the tables in your stack.");
|
|
1784
1856
|
|
|
1785
1857
|
// src/feature/task/schema.ts
|
|
1786
|
-
import { z as
|
|
1787
|
-
var RetryAttemptsSchema2 =
|
|
1858
|
+
import { z as z36 } from "zod";
|
|
1859
|
+
var RetryAttemptsSchema2 = z36.number().int().min(0).max(2).describe(
|
|
1788
1860
|
"The maximum number of times to retry when the function returns an error. You can specify a number from 0 to 2."
|
|
1789
1861
|
);
|
|
1790
|
-
var TaskSchema =
|
|
1862
|
+
var TaskSchema = z36.union([
|
|
1791
1863
|
LocalFileSchema.transform((file) => ({
|
|
1792
1864
|
consumer: {
|
|
1793
1865
|
code: {
|
|
@@ -1798,33 +1870,33 @@ var TaskSchema = z35.union([
|
|
|
1798
1870
|
},
|
|
1799
1871
|
retryAttempts: void 0
|
|
1800
1872
|
})),
|
|
1801
|
-
|
|
1873
|
+
z36.object({
|
|
1802
1874
|
consumer: FunctionSchema,
|
|
1803
1875
|
retryAttempts: RetryAttemptsSchema2.optional()
|
|
1804
1876
|
})
|
|
1805
1877
|
]);
|
|
1806
|
-
var TasksSchema =
|
|
1878
|
+
var TasksSchema = z36.record(ResourceIdSchema, TaskSchema).optional().describe("Define the tasks in your stack.");
|
|
1807
1879
|
|
|
1808
1880
|
// src/feature/test/schema.ts
|
|
1809
|
-
import { z as
|
|
1810
|
-
var TestsSchema =
|
|
1881
|
+
import { z as z37 } from "zod";
|
|
1882
|
+
var TestsSchema = z37.union([LocalDirectorySchema.transform((v) => [v]), LocalDirectorySchema.array()]).describe("Define the location of your tests for your stack.").optional();
|
|
1811
1883
|
|
|
1812
1884
|
// src/feature/topic/schema.ts
|
|
1813
1885
|
import { kebabCase as kebabCase3 } from "change-case";
|
|
1814
|
-
import { z as
|
|
1815
|
-
var TopicNameSchema =
|
|
1816
|
-
var TopicsSchema =
|
|
1886
|
+
import { z as z38 } from "zod";
|
|
1887
|
+
var TopicNameSchema = z38.string().min(3).max(256).regex(/^[a-z0-9\-]+$/i, "Invalid topic name").transform((value) => kebabCase3(value)).describe("Define event topic name.");
|
|
1888
|
+
var TopicsSchema = z38.array(TopicNameSchema).refine((topics) => {
|
|
1817
1889
|
return topics.length === new Set(topics).size;
|
|
1818
1890
|
}, "Must be a list of unique topic names").optional().describe("Define the event topics to publish too in your stack.");
|
|
1819
|
-
var SubscribersSchema =
|
|
1891
|
+
var SubscribersSchema = z38.record(TopicNameSchema, FunctionSchema).optional().describe("Define the event topics to subscribe too in your stack.");
|
|
1820
1892
|
|
|
1821
1893
|
// src/config/stack.ts
|
|
1822
1894
|
var DependsSchema = ResourceIdSchema.array().optional().describe("Define the stacks that this stack is depended on.");
|
|
1823
1895
|
var NameSchema = ResourceIdSchema.refine((name) => !["base", "hostedzones"].includes(name), {
|
|
1824
1896
|
message: `Stack name can't be a reserved name.`
|
|
1825
1897
|
}).describe("Stack name.");
|
|
1826
|
-
var StackSchema =
|
|
1827
|
-
$schema:
|
|
1898
|
+
var StackSchema = z39.object({
|
|
1899
|
+
$schema: z39.string().optional(),
|
|
1828
1900
|
name: NameSchema,
|
|
1829
1901
|
depends: DependsSchema,
|
|
1830
1902
|
commands: CommandsSchema,
|
|
@@ -1849,7 +1921,8 @@ var StackSchema = z38.object({
|
|
|
1849
1921
|
pubsub: PubSubSchema,
|
|
1850
1922
|
searchs: SearchsSchema,
|
|
1851
1923
|
sites: SitesSchema,
|
|
1852
|
-
tests: TestsSchema
|
|
1924
|
+
tests: TestsSchema,
|
|
1925
|
+
images: ImagesSchema
|
|
1853
1926
|
});
|
|
1854
1927
|
|
|
1855
1928
|
// src/config/load/read.ts
|
|
@@ -1891,13 +1964,13 @@ var readConfigWithStage = async (file, stage) => {
|
|
|
1891
1964
|
};
|
|
1892
1965
|
|
|
1893
1966
|
// src/config/load/validate.ts
|
|
1894
|
-
import { z as
|
|
1967
|
+
import { z as z40 } from "zod";
|
|
1895
1968
|
var validateConfig = async (schema, file, data) => {
|
|
1896
1969
|
try {
|
|
1897
1970
|
const result = await schema.parseAsync(data);
|
|
1898
1971
|
return result;
|
|
1899
1972
|
} catch (error) {
|
|
1900
|
-
if (error instanceof
|
|
1973
|
+
if (error instanceof z40.ZodError) {
|
|
1901
1974
|
throw new ConfigError(file, error, data);
|
|
1902
1975
|
}
|
|
1903
1976
|
throw error;
|
|
@@ -4076,19 +4149,23 @@ var createPrebuildLambdaFunction = (group, ctx, ns, id, props) => {
|
|
|
4076
4149
|
}
|
|
4077
4150
|
if (props.log?.retention && props.log?.retention?.value > 0n) {
|
|
4078
4151
|
const logGroup = new $12.aws.cloudwatch.LogGroup(group, "log", {
|
|
4079
|
-
name:
|
|
4152
|
+
name: `/aws/lambda/${name}`,
|
|
4080
4153
|
retentionInDays: toDays4(props.log.retention ?? days3(7))
|
|
4081
4154
|
});
|
|
4082
|
-
addPermission(
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4155
|
+
addPermission({
|
|
4156
|
+
actions: ["logs:PutLogEvents", "logs:CreateLogStream"],
|
|
4157
|
+
resources: [logGroup.arn.pipe((arn) => `${arn}:*`)]
|
|
4158
|
+
});
|
|
4159
|
+
const onLogArn = getGlobalOnLog(ctx);
|
|
4160
|
+
if (onLogArn && ctx.appConfig.defaults.onLog) {
|
|
4161
|
+
const logFilter = ctx.appConfig.defaults.onLog.filter;
|
|
4162
|
+
new $12.aws.cloudwatch.LogSubscriptionFilter(group, `on-log`, {
|
|
4163
|
+
name: "log-subscription",
|
|
4164
|
+
destinationArn: onLogArn,
|
|
4165
|
+
logGroupName: logGroup.name,
|
|
4166
|
+
filterPattern: formatFilterPattern(logFilter)
|
|
4167
|
+
});
|
|
4168
|
+
}
|
|
4092
4169
|
}
|
|
4093
4170
|
if (props.warm) {
|
|
4094
4171
|
const rule = new $12.aws.cloudwatch.EventRule(group, "warm", {
|
|
@@ -4322,10 +4399,11 @@ var rpcFeature = defineFeature({
|
|
|
4322
4399
|
}
|
|
4323
4400
|
});
|
|
4324
4401
|
const cdn = new $13.aws.cloudfront.Distribution(group, "cdn", {
|
|
4325
|
-
tags: {
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
},
|
|
4402
|
+
// tags: {
|
|
4403
|
+
// Name: name,
|
|
4404
|
+
// // Feature: ''
|
|
4405
|
+
// },
|
|
4406
|
+
comment: name,
|
|
4329
4407
|
enabled: true,
|
|
4330
4408
|
aliases: domainName ? [domainName] : void 0,
|
|
4331
4409
|
priceClass: "PriceClass_All",
|
|
@@ -4733,6 +4811,11 @@ var siteFeature = defineFeature({
|
|
|
4733
4811
|
functionUrl = new $15.aws.lambda.FunctionUrl(group, "url", {
|
|
4734
4812
|
functionName: result.lambda.functionName,
|
|
4735
4813
|
authorizationType: "AWS_IAM"
|
|
4814
|
+
// cors: {
|
|
4815
|
+
// allowOrigins: ['*'],
|
|
4816
|
+
// allowMethods: ['*'],
|
|
4817
|
+
// allowHeaders: ['*'],
|
|
4818
|
+
// },
|
|
4736
4819
|
});
|
|
4737
4820
|
}
|
|
4738
4821
|
let bucket;
|
|
@@ -5690,10 +5773,6 @@ import { $ as $21, Group as Group22 } from "@awsless/formation";
|
|
|
5690
5773
|
var layerFeature = defineFeature({
|
|
5691
5774
|
name: "layer",
|
|
5692
5775
|
onBefore(ctx) {
|
|
5693
|
-
const layers = Object.entries(ctx.appConfig.defaults.layers ?? {});
|
|
5694
|
-
if (layers.length === 0) {
|
|
5695
|
-
return;
|
|
5696
|
-
}
|
|
5697
5776
|
const group = new Group22(ctx.base, "layer", "asset");
|
|
5698
5777
|
const bucket = new $21.aws.s3.Bucket(group, "bucket", {
|
|
5699
5778
|
bucket: formatGlobalResourceName({
|
|
@@ -5725,7 +5804,7 @@ var layerFeature = defineFeature({
|
|
|
5725
5804
|
for (const [id, _props] of layers) {
|
|
5726
5805
|
const props = _props;
|
|
5727
5806
|
const group = new Group22(ctx.base, "layer", id);
|
|
5728
|
-
const
|
|
5807
|
+
const zip = new $21.aws.s3.BucketObject(group, "zip", {
|
|
5729
5808
|
bucket: ctx.shared.get("layer", "bucket-name"),
|
|
5730
5809
|
key: `/layer/${id}.zip`,
|
|
5731
5810
|
contentType: "application/zip",
|
|
@@ -5744,9 +5823,9 @@ var layerFeature = defineFeature({
|
|
|
5744
5823
|
description: id,
|
|
5745
5824
|
compatibleArchitectures: props.architecture ? [props.architecture] : void 0,
|
|
5746
5825
|
compatibleRuntimes: props.runtimes,
|
|
5747
|
-
s3Bucket:
|
|
5748
|
-
s3ObjectVersion:
|
|
5749
|
-
s3Key:
|
|
5826
|
+
s3Bucket: zip.bucket,
|
|
5827
|
+
s3ObjectVersion: zip.versionId,
|
|
5828
|
+
s3Key: zip.key.pipe((name) => {
|
|
5750
5829
|
if (name.startsWith("/")) {
|
|
5751
5830
|
return name.substring(1);
|
|
5752
5831
|
}
|
|
@@ -5755,7 +5834,7 @@ var layerFeature = defineFeature({
|
|
|
5755
5834
|
sourceCodeHash: $hash(props.file)
|
|
5756
5835
|
},
|
|
5757
5836
|
{
|
|
5758
|
-
dependsOn: [
|
|
5837
|
+
dependsOn: [zip]
|
|
5759
5838
|
}
|
|
5760
5839
|
);
|
|
5761
5840
|
ctx.shared.add("layer", "arn", id, layer.arn);
|
|
@@ -5764,6 +5843,248 @@ var layerFeature = defineFeature({
|
|
|
5764
5843
|
}
|
|
5765
5844
|
});
|
|
5766
5845
|
|
|
5846
|
+
// src/feature/images/index.ts
|
|
5847
|
+
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";
|
|
5853
|
+
import { mebibytes as mebibytes4 } from "@awsless/size";
|
|
5854
|
+
import { days as days6, seconds as seconds9, toSeconds as toSeconds8, weeks } from "@awsless/duration";
|
|
5855
|
+
import { constantCase as constantCase11 } from "change-case";
|
|
5856
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
5857
|
+
var __dirname2 = dirname8(fileURLToPath2(import.meta.url));
|
|
5858
|
+
var imagesFeature = defineFeature({
|
|
5859
|
+
name: "images",
|
|
5860
|
+
onStack(ctx) {
|
|
5861
|
+
for (const [id, props] of Object.entries(ctx.stackConfig.images ?? {})) {
|
|
5862
|
+
const group = new Group23(ctx.stack, "images", id);
|
|
5863
|
+
const name = formatLocalResourceName({
|
|
5864
|
+
appName: ctx.app.name,
|
|
5865
|
+
stackName: ctx.stack.name,
|
|
5866
|
+
resourceType: "images",
|
|
5867
|
+
resourceName: id
|
|
5868
|
+
});
|
|
5869
|
+
const originGroup = new Group23(ctx.stack, "images-origins", id);
|
|
5870
|
+
let lambdaOrigin = void 0;
|
|
5871
|
+
if (props.origin.function) {
|
|
5872
|
+
lambdaOrigin = createLambdaFunction(originGroup, ctx, `images-lambda-origin`, id, props.origin.function);
|
|
5873
|
+
}
|
|
5874
|
+
let s3Origin;
|
|
5875
|
+
if (props.origin.static) {
|
|
5876
|
+
s3Origin = new $22.aws.s3.Bucket(originGroup, "bucket", {
|
|
5877
|
+
bucket: formatLocalResourceName({
|
|
5878
|
+
appName: ctx.app.name,
|
|
5879
|
+
stackName: ctx.stack.name,
|
|
5880
|
+
resourceType: "images",
|
|
5881
|
+
resourceName: id,
|
|
5882
|
+
postfix: ctx.appId
|
|
5883
|
+
}),
|
|
5884
|
+
forceDestroy: true
|
|
5885
|
+
});
|
|
5886
|
+
}
|
|
5887
|
+
const path = join12(__dirname2, "/layers/sharp-arm.zip");
|
|
5888
|
+
const layerId = formatLocalResourceName({
|
|
5889
|
+
appName: ctx.appConfig.name,
|
|
5890
|
+
stackName: ctx.stack.name,
|
|
5891
|
+
resourceType: "layer",
|
|
5892
|
+
resourceName: shortId(id)
|
|
5893
|
+
});
|
|
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
|
+
const transformFn = createPrebuildLambdaFunction(group, ctx, "images", id, {
|
|
5925
|
+
bundleFile: join12(__dirname2, "/prebuild/images/bundle.zip"),
|
|
5926
|
+
bundleHash: join12(__dirname2, "/prebuild/images/HASH"),
|
|
5927
|
+
memorySize: mebibytes4(512),
|
|
5928
|
+
timeout: seconds9(10),
|
|
5929
|
+
handler: "index.default",
|
|
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
|
|
5942
|
+
});
|
|
5943
|
+
const permission = new $22.aws.lambda.Permission(group, "permission", {
|
|
5944
|
+
principal: "cloudfront.amazonaws.com",
|
|
5945
|
+
action: "lambda:InvokeFunctionUrl",
|
|
5946
|
+
functionName: transformFn.lambda.functionName,
|
|
5947
|
+
functionUrlAuthType: "AWS_IAM",
|
|
5948
|
+
sourceArn: `arn:aws:cloudfront::${ctx.accountId}:distribution/*`
|
|
5949
|
+
});
|
|
5950
|
+
const transformFnUrl = new $22.aws.lambda.FunctionUrl(
|
|
5951
|
+
group,
|
|
5952
|
+
"url",
|
|
5953
|
+
{
|
|
5954
|
+
functionName: transformFn.lambda.functionName,
|
|
5955
|
+
authorizationType: "AWS_IAM"
|
|
5956
|
+
},
|
|
5957
|
+
{ dependsOn: [permission] }
|
|
5958
|
+
);
|
|
5959
|
+
transformFn.setEnvironment(
|
|
5960
|
+
"IMAGES_CONFIG",
|
|
5961
|
+
JSON.stringify({
|
|
5962
|
+
presets: props.presets,
|
|
5963
|
+
extensions: props.extensions
|
|
5964
|
+
})
|
|
5965
|
+
);
|
|
5966
|
+
if (lambdaOrigin) {
|
|
5967
|
+
transformFn.setEnvironment("IMAGES_ORIGIN_LAMBDA", lambdaOrigin.name);
|
|
5968
|
+
}
|
|
5969
|
+
if (s3Origin) {
|
|
5970
|
+
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
|
+
}
|
|
5989
|
+
const versions = [];
|
|
5990
|
+
ctx.onReady(() => {
|
|
5991
|
+
if (props.origin.static && s3Origin) {
|
|
5992
|
+
const files = glob3.sync("**", {
|
|
5993
|
+
cwd: props.origin.static,
|
|
5994
|
+
nodir: true
|
|
5995
|
+
});
|
|
5996
|
+
for (const file of files) {
|
|
5997
|
+
const object = new $22.aws.s3.BucketObject(group, `static-${file}`, {
|
|
5998
|
+
bucket: s3Origin.bucket,
|
|
5999
|
+
key: file,
|
|
6000
|
+
cacheControl: "public, max-age=31536000, immutable",
|
|
6001
|
+
contentType: contentType2(extname3(file)) || `image/${extname3(file).slice(1)}`,
|
|
6002
|
+
source: join12(props.origin.static, file),
|
|
6003
|
+
sourceHash: $hash(join12(props.origin.static, file))
|
|
6004
|
+
});
|
|
6005
|
+
versions.push(object.key);
|
|
6006
|
+
versions.push(object.sourceHash);
|
|
6007
|
+
}
|
|
6008
|
+
}
|
|
6009
|
+
});
|
|
6010
|
+
const domainName = props.domain ? formatFullDomainName(ctx.appConfig, props.domain, props.subDomain) : void 0;
|
|
6011
|
+
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,
|
|
6014
|
+
description: "Policy for Images Lambda Transformation Function URL",
|
|
6015
|
+
originAccessControlOriginType: "lambda",
|
|
6016
|
+
signingBehavior: "always",
|
|
6017
|
+
signingProtocol: "sigv4"
|
|
6018
|
+
});
|
|
6019
|
+
const cache = new $22.aws.cloudfront.CachePolicy(group, "cache", {
|
|
6020
|
+
name,
|
|
6021
|
+
defaultTtl: toSeconds8(days6(365))
|
|
6022
|
+
});
|
|
6023
|
+
const distribution = new $22.aws.cloudfront.Distribution(group, "distribution", {
|
|
6024
|
+
comment: name,
|
|
6025
|
+
enabled: true,
|
|
6026
|
+
aliases: domainName ? [domainName] : void 0,
|
|
6027
|
+
priceClass: "PriceClass_All",
|
|
6028
|
+
httpVersion: "http2and3",
|
|
6029
|
+
viewerCertificate: certificateArn ? {
|
|
6030
|
+
sslSupportMethod: "sni-only",
|
|
6031
|
+
minimumProtocolVersion: "TLSv1.2_2021",
|
|
6032
|
+
acmCertificateArn: certificateArn
|
|
6033
|
+
} : {
|
|
6034
|
+
cloudfrontDefaultCertificate: true
|
|
6035
|
+
},
|
|
6036
|
+
origin: [
|
|
6037
|
+
{
|
|
6038
|
+
originId: "default",
|
|
6039
|
+
domainName: transformFnUrl.functionUrl.pipe((url) => url.split("/")[2]),
|
|
6040
|
+
originAccessControlId: accessControl.id,
|
|
6041
|
+
customOriginConfig: {
|
|
6042
|
+
originProtocolPolicy: "https-only",
|
|
6043
|
+
httpPort: 80,
|
|
6044
|
+
httpsPort: 443,
|
|
6045
|
+
originSslProtocols: ["TLSv1.2"]
|
|
6046
|
+
}
|
|
6047
|
+
}
|
|
6048
|
+
],
|
|
6049
|
+
defaultCacheBehavior: {
|
|
6050
|
+
compress: true,
|
|
6051
|
+
targetOriginId: "default",
|
|
6052
|
+
cachePolicyId: cache.id,
|
|
6053
|
+
viewerProtocolPolicy: "redirect-to-https",
|
|
6054
|
+
allowedMethods: ["GET", "HEAD"],
|
|
6055
|
+
cachedMethods: ["GET", "HEAD"]
|
|
6056
|
+
}
|
|
6057
|
+
});
|
|
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
|
+
});
|
|
6069
|
+
if (domainName) {
|
|
6070
|
+
new $22.aws.route53.Record(group, `record`, {
|
|
6071
|
+
zoneId: ctx.shared.entry("domain", "zone-id", props.domain),
|
|
6072
|
+
type: "A",
|
|
6073
|
+
name: domainName,
|
|
6074
|
+
alias: {
|
|
6075
|
+
name: distribution.domainName,
|
|
6076
|
+
zoneId: distribution.hostedZoneId,
|
|
6077
|
+
evaluateTargetHealth: false
|
|
6078
|
+
}
|
|
6079
|
+
});
|
|
6080
|
+
ctx.bind(`IMAGES_${ctx.stack.name}_${constantCase11(id)}_ENDPOINT`, domainName);
|
|
6081
|
+
} else {
|
|
6082
|
+
ctx.bind(`IMAGES_${ctx.stack.name}_${constantCase11(id)}_ENDPOINT`, distribution.domainName);
|
|
6083
|
+
}
|
|
6084
|
+
}
|
|
6085
|
+
}
|
|
6086
|
+
});
|
|
6087
|
+
|
|
5767
6088
|
// src/feature/index.ts
|
|
5768
6089
|
var features = [
|
|
5769
6090
|
// 1
|
|
@@ -5796,6 +6117,7 @@ var features = [
|
|
|
5796
6117
|
// httpFeature,
|
|
5797
6118
|
restFeature,
|
|
5798
6119
|
siteFeature,
|
|
6120
|
+
imagesFeature,
|
|
5799
6121
|
// 4
|
|
5800
6122
|
rpcFeature
|
|
5801
6123
|
];
|
|
@@ -6657,13 +6979,13 @@ import wildstring4 from "wildstring";
|
|
|
6657
6979
|
import { log as log9 } from "@clack/prompts";
|
|
6658
6980
|
import chalk5 from "chalk";
|
|
6659
6981
|
import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile3 } from "fs/promises";
|
|
6660
|
-
import { join as
|
|
6982
|
+
import { join as join15 } from "path";
|
|
6661
6983
|
import wildstring3 from "wildstring";
|
|
6662
6984
|
|
|
6663
6985
|
// src/build/__fingerprint.ts
|
|
6664
|
-
import { createHash as
|
|
6986
|
+
import { createHash as createHash6 } from "crypto";
|
|
6665
6987
|
import { readdir as readdir4, readFile as readFile4, stat as stat4 } from "fs/promises";
|
|
6666
|
-
import { basename as basename4, dirname as
|
|
6988
|
+
import { basename as basename4, dirname as dirname9, extname as extname4, join as join13 } from "path";
|
|
6667
6989
|
import parseStaticImports from "parse-static-imports";
|
|
6668
6990
|
var extensions = ["js", "mjs", "jsx", "ts", "mts", "tsx"];
|
|
6669
6991
|
var generateFileHashes = async (file, hashes) => {
|
|
@@ -6672,7 +6994,7 @@ var generateFileHashes = async (file, hashes) => {
|
|
|
6672
6994
|
}
|
|
6673
6995
|
const code = await readModuleFile(file);
|
|
6674
6996
|
const deps = await findDependencies(file, code);
|
|
6675
|
-
const hash =
|
|
6997
|
+
const hash = createHash6("sha1").update(code).digest();
|
|
6676
6998
|
hashes.set(file, hash);
|
|
6677
6999
|
for (const dep of deps) {
|
|
6678
7000
|
if (dep.startsWith("/")) {
|
|
@@ -6684,12 +7006,12 @@ var fingerprintFromDirectory = async (dir) => {
|
|
|
6684
7006
|
const hashes = /* @__PURE__ */ new Map();
|
|
6685
7007
|
const files = await readdir4(dir, { recursive: true });
|
|
6686
7008
|
for (const file of files) {
|
|
6687
|
-
if (extensions.includes(
|
|
6688
|
-
await generateFileHashes(
|
|
7009
|
+
if (extensions.includes(extname4(file).substring(1)) && file.at(0) !== "_") {
|
|
7010
|
+
await generateFileHashes(join13(dir, file), hashes);
|
|
6689
7011
|
}
|
|
6690
7012
|
}
|
|
6691
7013
|
const merge2 = Buffer.concat(Array.from(hashes.values()).sort());
|
|
6692
|
-
return
|
|
7014
|
+
return createHash6("sha1").update(merge2).digest("hex");
|
|
6693
7015
|
};
|
|
6694
7016
|
var readModuleFile = (file) => {
|
|
6695
7017
|
if (file.endsWith(".js")) {
|
|
@@ -6699,7 +7021,7 @@ var readModuleFile = (file) => {
|
|
|
6699
7021
|
return readFiles([
|
|
6700
7022
|
file,
|
|
6701
7023
|
...extensions.map((exp) => `${file}.${exp}`),
|
|
6702
|
-
...extensions.map((exp) =>
|
|
7024
|
+
...extensions.map((exp) => join13(file, `/index.${exp}`))
|
|
6703
7025
|
]);
|
|
6704
7026
|
}
|
|
6705
7027
|
return readFile4(file, "utf8");
|
|
@@ -6719,7 +7041,7 @@ var readFiles = async (files) => {
|
|
|
6719
7041
|
};
|
|
6720
7042
|
var findDependencies = async (file, code) => {
|
|
6721
7043
|
const imports = await parseStaticImports(code);
|
|
6722
|
-
return imports.map((entry) => entry.moduleName).filter(Boolean).map((value) => value?.startsWith(".") ?
|
|
7044
|
+
return imports.map((entry) => entry.moduleName).filter(Boolean).map((value) => value?.startsWith(".") ? join13(dirname9(file), value) : value);
|
|
6723
7045
|
};
|
|
6724
7046
|
|
|
6725
7047
|
// src/test/reporter.ts
|
|
@@ -6799,13 +7121,13 @@ var CustomReporter = class {
|
|
|
6799
7121
|
import commonjs2 from "@rollup/plugin-commonjs";
|
|
6800
7122
|
import json2 from "@rollup/plugin-json";
|
|
6801
7123
|
import nodeResolve2 from "@rollup/plugin-node-resolve";
|
|
6802
|
-
import { dirname as
|
|
7124
|
+
import { dirname as dirname10, join as join14 } from "path";
|
|
6803
7125
|
import { swc as swc2 } from "rollup-plugin-swc3";
|
|
6804
|
-
import { fileURLToPath as
|
|
7126
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
6805
7127
|
import { configDefaults } from "vitest/config";
|
|
6806
7128
|
import { startVitest } from "vitest/node";
|
|
6807
7129
|
var startTest = async (props) => {
|
|
6808
|
-
const
|
|
7130
|
+
const __dirname3 = dirname10(fileURLToPath3(import.meta.url));
|
|
6809
7131
|
const result = await startVitest(
|
|
6810
7132
|
"test",
|
|
6811
7133
|
props.filters,
|
|
@@ -6821,7 +7143,7 @@ var startTest = async (props) => {
|
|
|
6821
7143
|
reporters: props.reporter,
|
|
6822
7144
|
setupFiles: [
|
|
6823
7145
|
//
|
|
6824
|
-
|
|
7146
|
+
join14(__dirname3, "test-global-setup.js")
|
|
6825
7147
|
]
|
|
6826
7148
|
// globalSetup: [
|
|
6827
7149
|
// //
|
|
@@ -6920,7 +7242,7 @@ var logTestErrors = (event) => {
|
|
|
6920
7242
|
var runTest = async (stack, dir, filters) => {
|
|
6921
7243
|
await mkdir4(directories.test, { recursive: true });
|
|
6922
7244
|
const fingerprint = await fingerprintFromDirectory(dir);
|
|
6923
|
-
const file =
|
|
7245
|
+
const file = join15(directories.test, `${stack}.json`);
|
|
6924
7246
|
const exists = await fileExist(file);
|
|
6925
7247
|
if (exists && !process.env.NO_CACHE) {
|
|
6926
7248
|
const raw = await readFile5(file, { encoding: "utf8" });
|
|
@@ -7159,7 +7481,7 @@ var auth = (program2) => {
|
|
|
7159
7481
|
|
|
7160
7482
|
// src/cli/command/bind.ts
|
|
7161
7483
|
import { log as log10, note as note3 } from "@clack/prompts";
|
|
7162
|
-
import { constantCase as
|
|
7484
|
+
import { constantCase as constantCase12 } from "change-case";
|
|
7163
7485
|
import { spawn } from "child_process";
|
|
7164
7486
|
var bind = (program2) => {
|
|
7165
7487
|
program2.command("bind").argument("[command...]", "The command to execute").option("--config <string...>", "List of config values that will be accessable", (v) => v.split(",")).description(`Bind your site environment variables to a command`).action(async (commands7 = [], opts) => {
|
|
@@ -7188,10 +7510,10 @@ var bind = (program2) => {
|
|
|
7188
7510
|
const configList = opts.config ?? [];
|
|
7189
7511
|
const configs = {};
|
|
7190
7512
|
for (const name of configList) {
|
|
7191
|
-
configs[`CONFIG_${
|
|
7513
|
+
configs[`CONFIG_${constantCase12(name)}`] = name;
|
|
7192
7514
|
}
|
|
7193
7515
|
if (configList.length ?? 0 > 0) {
|
|
7194
|
-
note3(wrap(configList.map((v) => color.label(
|
|
7516
|
+
note3(wrap(configList.map((v) => color.label(constantCase12(v)))), "Bind Config");
|
|
7195
7517
|
}
|
|
7196
7518
|
if (commands7.length === 0) {
|
|
7197
7519
|
return "No command to execute.";
|
|
@@ -7254,7 +7576,7 @@ import { log as log11 } from "@clack/prompts";
|
|
|
7254
7576
|
|
|
7255
7577
|
// src/type-gen/generate.ts
|
|
7256
7578
|
import { mkdir as mkdir5, writeFile as writeFile4 } from "fs/promises";
|
|
7257
|
-
import { dirname as
|
|
7579
|
+
import { dirname as dirname11, join as join16, relative as relative7 } from "path";
|
|
7258
7580
|
var generateTypes = async (props) => {
|
|
7259
7581
|
const files = [];
|
|
7260
7582
|
await Promise.all(
|
|
@@ -7263,12 +7585,12 @@ var generateTypes = async (props) => {
|
|
|
7263
7585
|
...props,
|
|
7264
7586
|
async write(file, data, include = false) {
|
|
7265
7587
|
const code = data?.toString("utf8");
|
|
7266
|
-
const path =
|
|
7588
|
+
const path = join16(directories.types, file);
|
|
7267
7589
|
if (code) {
|
|
7268
7590
|
if (include) {
|
|
7269
7591
|
files.push(relative7(directories.root, path));
|
|
7270
7592
|
}
|
|
7271
|
-
await mkdir5(
|
|
7593
|
+
await mkdir5(dirname11(path), { recursive: true });
|
|
7272
7594
|
await writeFile4(path, code);
|
|
7273
7595
|
}
|
|
7274
7596
|
}
|
|
@@ -7277,7 +7599,7 @@ var generateTypes = async (props) => {
|
|
|
7277
7599
|
);
|
|
7278
7600
|
if (files.length) {
|
|
7279
7601
|
const code = files.map((file) => `/// <reference path='${file}' />`).join("\n");
|
|
7280
|
-
await writeFile4(
|
|
7602
|
+
await writeFile4(join16(directories.root, `awsless.d.ts`), code);
|
|
7281
7603
|
}
|
|
7282
7604
|
};
|
|
7283
7605
|
|