@batijs/cli 0.0.260 → 0.0.261

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 (22) hide show
  1. package/dist/boilerplates/@batijs/aws/files/$README.md.js +109 -0
  2. package/dist/boilerplates/@batijs/aws/files/$package.json.js +138 -0
  3. package/dist/boilerplates/@batijs/aws/files/$tsconfig.json.js +15 -0
  4. package/dist/boilerplates/@batijs/aws/files/cdk/$stack-name-suffix.json.js +19 -0
  5. package/dist/boilerplates/@batijs/aws/files/cdk/bin/infrastructure.ts +85 -0
  6. package/dist/boilerplates/@batijs/aws/files/cdk/lib/vike-stack.ts +186 -0
  7. package/dist/boilerplates/@batijs/aws/files/cdk.json +72 -0
  8. package/dist/boilerplates/@batijs/aws/files/tests/aws_handler.spec.ts +116 -0
  9. package/dist/boilerplates/@batijs/aws/files/vitest.config.ts +8 -0
  10. package/dist/boilerplates/@batijs/aws/types/cdk/bin/infrastructure.d.ts +11 -0
  11. package/dist/boilerplates/@batijs/aws/types/cdk/lib/vike-stack.d.ts +13 -0
  12. package/dist/boilerplates/@batijs/aws/types/tests/aws_handler.spec.d.ts +1 -0
  13. package/dist/boilerplates/@batijs/aws/types/vitest.config.d.ts +2 -0
  14. package/dist/boilerplates/@batijs/hattip/files/$package.json.js +12 -1
  15. package/dist/boilerplates/@batijs/hattip/files/entry_aws_lambda.ts +37 -0
  16. package/dist/boilerplates/@batijs/hattip/types/entry_aws_lambda.d.ts +2 -0
  17. package/dist/boilerplates/@batijs/hono/files/$package.json.js +8 -1
  18. package/dist/boilerplates/@batijs/hono/files/entry_aws_lambda.ts +37 -0
  19. package/dist/boilerplates/@batijs/hono/types/entry_aws_lambda.d.ts +3 -0
  20. package/dist/boilerplates/boilerplates.json +11 -0
  21. package/dist/index.js +5 -1
  22. package/package.json +5 -5
@@ -0,0 +1,109 @@
1
+ // files/$README.md.ts
2
+ import { loadReadme } from "@batijs/core";
3
+ async function getReadme(props) {
4
+ const content = await loadReadme(props);
5
+ const todo = `
6
+ ## *AWS CDK Deployment*
7
+
8
+ This is a boilerplate for deploying your Vike app to AWS using the AWS Cloud Development Kit (CDK) including creating a custom domain in Route53.
9
+
10
+ **Architecture:**
11
+ - S3 Bucket for static client assets (\`/dist/client/assets\`).
12
+ - Lambda function for the backend and SSR.
13
+ - CloudFront distribution for CDN and routing requests \`/assets/*\` to the S3 bucket.
14
+
15
+ This boilerplate is a starting point for deploying your Vike app to AWS. You can customize the deployment by modifying the \`cdk/lib/vike-stack.ts\` file.
16
+
17
+ ### Prerequisites
18
+
19
+ Before you get started, make sure to configure your AWS credentials.
20
+
21
+ **Loading from a file:**
22
+
23
+ You can keep your AWS credentials in a file. The credentials are found at:
24
+
25
+ \`~/.aws/credentials\` on Linux, Unix, and macOS;
26
+ \`C:\\Users\\USER_NAME\\.aws\\credentials\` on Windows
27
+
28
+ If the credentials file does not exist on your machine:
29
+
30
+ Download the AWS CLI from [here](https://aws.amazon.com/cli/) and configure your AWS credentials using the following command:
31
+ \`aws configure\`
32
+
33
+ And then use this guide to configure the credentials
34
+ The credentials file should look like:
35
+
36
+ \`
37
+ [default]
38
+ aws_access_key_id = <YOUR_ACCESS_KEY_ID>
39
+ aws_secret_access_key = <YOUR_SECRET_ACCESS_KEY>
40
+ \`
41
+
42
+ **Loading from environment variables:**
43
+
44
+ AWS SDK automatically detects AWS credentials in your environment and uses them for making requests to AWS. The environment variables that you need to set are:
45
+
46
+ \`AWS_ACCESS_KEY_ID\`
47
+ \`AWS_SECRET_ACCESS_KEY\`
48
+ If you are using temporary credentials, also set:
49
+
50
+ \`AWS_SESSION_TOKEN\`
51
+ This is often the most convenient way to configure credentials when deploying your AWS CDK app in a CI environment.
52
+
53
+ > [!NOTE]
54
+ > You should change the stack name to give your app stack a distinctive name in your AWS environment. You can do so by modifying the \`infrastructure.ts.ts\` file in the \`cdk/bin\` directory.
55
+
56
+ ### Deployment to AWS
57
+
58
+ If you want to have a look at the synthesized CloudFormation template, you can run \`pnpm cdk synth\` and see the template as YAML on screen or in \`cdk.out/VikeStack.template.json\`.
59
+
60
+ > [!NOTE]
61
+ > If this is your **first time deploying a CDK app** in this environment you need to **bootstrap**:
62
+ > \`pnpm cdk bootstrap\`. (The default region based on your AWS CLI configuration will be used)
63
+
64
+ You can deploy your Vike App via the following command:
65
+ \`pnpm deploy:aws\` or \`pnpm cdk deploy\`
66
+
67
+ The URL to the CloudFront distribution will be displayed in the output of the deployment.
68
+ You can also access the CloudFront distribution domainname in the AWS SSM registry und \`vike/distribution/url\`.
69
+
70
+ ### Stack Configuration
71
+
72
+ You can configure the stack in the \`cdk/bin/infrastructure.ts\` file:
73
+ | --- | --- | --- |
74
+ | Variable | Examples | Description |
75
+ | \`domainName: "example.com",\` | "example.com" | |
76
+ | \`subDomain: "www",\` |"www" | |
77
+ | \`certificate: undefined,\` | "arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012" or a certificatemanager.ICertificate | reuse an existing AWS Certificate |
78
+ | \`hostedZone: undefined,\` | route53.HostedZone.fromLookup(stack, "MyHostedZone", { domainName: "example.com" }) | |
79
+
80
+ If \`domainName\` is managed by **Route53**, the \`hostedZone\` will be updated with by lookup in Route53 based on the \`domainName\`.
81
+
82
+ These scenarios are supported:
83
+ A. \`domainName\` exists in Route53, \`subDomain\` is given - the subdomain with the domain are used as alternative domains for the CloudFront Distribution. An new Certificate for the url is created and assigned to the CF-Distribution. An Alias-Record pointing to the CF-Distribution ist created in Route53.
84
+ B. \`domainName\` exists in Route53, \`subDomain\` is given - the subdomain with the domain are used as alternative domains for the CloudFront Distribution. If \`certificate\` contains a valid entry it will be assigned to the CF-Distribution. An Alias-Record pointing to the CF-Distribution ist created in Route53.
85
+ C. \`domainName\` **does not exist** in Route53, \`subDomain\` is given - the subdomain with the domain are used as alternative domains for the CloudFront Distribution. If \`certificate\` contains a valid entry it will be assigned to the CF-Distribution. A manual created CNAME or A-Record should pointing to the CF-Distribution.
86
+
87
+ #### Custom Domain
88
+
89
+ If you have a custom domain, you can add it to the stack configuration in the \`cdk/bin/infrastructure.ts\` file:
90
+
91
+ > [!NOTE]
92
+ > If you deploy your App to a region different than \`us-east-1\` and you have never deployed to this region before, you will need to bootstrap this region too:
93
+ \`CDK_DEFAULT_REGION=us-east-1 pnpm deploy:cdk bootstrap\`
94
+
95
+
96
+ ### Destroying the Stack on AWS
97
+
98
+ To destroy the stack on AWS, run the following command:
99
+ \`pnpm cdk destroy\`
100
+
101
+ Or delete the CloudFormation stack which starts with "VikeStack-<Your App Name>" created by this project.
102
+
103
+ `;
104
+ content.addTodo(todo);
105
+ return content.finalize();
106
+ }
107
+ export {
108
+ getReadme as default
109
+ };
@@ -0,0 +1,138 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __commonJS = (cb, mod) => function __require() {
8
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
19
+ // If the importer is in node compatibility mode or this is not an ESM
20
+ // file that has been converted to a CommonJS file using a Babel-
21
+ // compatible transform (i.e. "__esModule" has not been set), then set
22
+ // "default" to the CommonJS "module.exports" for node compatibility.
23
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
24
+ mod
25
+ ));
26
+
27
+ // package.json
28
+ var require_package = __commonJS({
29
+ "package.json"(exports, module) {
30
+ module.exports = {
31
+ name: "@batijs/aws",
32
+ private: true,
33
+ version: "0.0.1",
34
+ description: "",
35
+ type: "module",
36
+ scripts: {
37
+ "check-types": "tsc --noEmit",
38
+ build: "bati-compile-boilerplate"
39
+ },
40
+ keywords: [],
41
+ author: "",
42
+ license: "MIT",
43
+ devDependencies: {
44
+ "@batijs/compile": "workspace:*",
45
+ "@types/node": "^18.19.14",
46
+ "@types/which": "^3.0.4",
47
+ "aws-cdk": "^2.154.1",
48
+ "aws-cdk-lib": "^2.154.1",
49
+ cdk: "^2.154.1",
50
+ constructs: "^10.3.0",
51
+ esbuild: "^0.23.1",
52
+ "source-map-support": "^0.5.21",
53
+ tsx: "^4.19.0",
54
+ typescript: "^5.5.4",
55
+ vitest: "^2.0.5",
56
+ which: "^4.0.0"
57
+ },
58
+ dependencies: {
59
+ "@batijs/core": "workspace:*"
60
+ },
61
+ files: [
62
+ "dist/"
63
+ ],
64
+ bati: {
65
+ if: {
66
+ flag: "aws"
67
+ }
68
+ },
69
+ exports: {
70
+ "./vitest.config": {
71
+ types: "./dist/types/vitest.config.d.ts"
72
+ },
73
+ "./cdk/lib/vike-stack": {
74
+ types: "./dist/types/cdk/lib/vike-stack.d.ts"
75
+ },
76
+ "./cdk/bin/infrastructure": {
77
+ types: "./dist/types/cdk/bin/infrastructure.d.ts"
78
+ },
79
+ "./tests/aws_handler.spec": {
80
+ types: "./dist/types/tests/aws_handler.spec.d.ts"
81
+ }
82
+ },
83
+ typesVersions: {
84
+ "*": {
85
+ "vitest.config": [
86
+ "./dist/types/vitest.config.d.ts"
87
+ ],
88
+ "cdk/lib/vike-stack": [
89
+ "./dist/types/cdk/lib/vike-stack.d.ts"
90
+ ],
91
+ "cdk/bin/infrastructure": [
92
+ "./dist/types/cdk/bin/infrastructure.d.ts"
93
+ ],
94
+ "tests/aws_handler.spec": [
95
+ "./dist/types/tests/aws_handler.spec.d.ts"
96
+ ]
97
+ }
98
+ }
99
+ };
100
+ }
101
+ });
102
+
103
+ // files/$package.json.ts
104
+ import { addDependency, loadAsJson, setScripts } from "@batijs/core";
105
+ async function getPackageJson(props) {
106
+ const packageJson = await loadAsJson(props);
107
+ setScripts(packageJson, {
108
+ test: {
109
+ value: "vitest",
110
+ precedence: 0
111
+ },
112
+ "deploy:cdk": {
113
+ value: "cdk",
114
+ precedence: 0
115
+ },
116
+ "deploy:aws": {
117
+ value: "pnpm run build && cdk deploy --all",
118
+ precedence: 0
119
+ }
120
+ });
121
+ return addDependency(packageJson, await Promise.resolve().then(() => __toESM(require_package(), 1)).then((x) => x.default), {
122
+ devDependencies: [
123
+ "cdk",
124
+ "aws-cdk",
125
+ "@types/node",
126
+ "tsx",
127
+ "typescript",
128
+ "esbuild",
129
+ "vitest",
130
+ "which",
131
+ "@types/which"
132
+ ],
133
+ dependencies: ["aws-cdk-lib", "constructs", "source-map-support"]
134
+ });
135
+ }
136
+ export {
137
+ getPackageJson as default
138
+ };
@@ -0,0 +1,15 @@
1
+ // files/$tsconfig.json.ts
2
+ import { loadAsJson } from "@batijs/core";
3
+ async function getTsConfig(props) {
4
+ const tsConfig = await loadAsJson(props);
5
+ tsConfig.compilerOptions.types = [
6
+ ...tsConfig.compilerOptions.types ?? [],
7
+ "@types/node",
8
+ "vitest/globals",
9
+ "@types/which"
10
+ ];
11
+ return tsConfig;
12
+ }
13
+ export {
14
+ getTsConfig as default
15
+ };
@@ -0,0 +1,19 @@
1
+ // files/cdk/$stack-name-suffix.json.ts
2
+ async function getDataJson() {
3
+ const dataJson = {
4
+ stackNameSuffix: generateRandomPrefix(8)
5
+ };
6
+ return dataJson;
7
+ }
8
+ function generateRandomPrefix(length) {
9
+ if (process.env.NODE_ENV === "test") return "TEST";
10
+ const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
11
+ let result = "";
12
+ for (let i = 0; i < length; i++) {
13
+ result += characters.charAt(Math.floor(Math.random() * characters.length));
14
+ }
15
+ return result;
16
+ }
17
+ export {
18
+ getDataJson as default
19
+ };
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env node
2
+ import "source-map-support/register";
3
+ import * as cdk from "aws-cdk-lib";
4
+ import { VikeStack } from "../lib/vike-stack";
5
+
6
+ import * as certificatemanager from "aws-cdk-lib/aws-certificatemanager";
7
+ import * as route53 from "aws-cdk-lib/aws-route53";
8
+
9
+ //# BATI.has("REMOVE-COMMENT") || "remove-comments-only"
10
+ // @ts-ignore file will be generated by the transformer
11
+ import { stackNameSuffix } from "../stack-name-suffix.json";
12
+
13
+ const env: cdk.Environment = {
14
+ account: process.env.CDK_DEFAULT_ACCOUNT,
15
+ region: process.env.CDK_DEFAULT_REGION,
16
+ };
17
+
18
+ export type CustomStackProps = cdk.StackProps & {
19
+ domainName?: string;
20
+ subDomain?: string;
21
+ certificate?: string | certificatemanager.ICertificate;
22
+ hostedZone?: route53.IHostedZone;
23
+ };
24
+
25
+ // Here you can configure the stack:
26
+ const customStackProps: CustomStackProps = {
27
+ domainName: undefined, // e.g. "example.com"
28
+ subDomain: undefined, // e.g. "www"
29
+ certificate: undefined, // e.g. "arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012" or a certificatemanager.ICertificate
30
+ hostedZone: undefined, // e.g. route53.HostedZone.fromLookup(stack, "MyHostedZone", { domainName: "example.com" })
31
+ };
32
+
33
+ const app = new cdk.App();
34
+
35
+ const usEast1Stack = customStackProps?.domainName
36
+ ? new cdk.Stack(app, `VikeStack-Cert-${stackNameSuffix}`, {
37
+ env: {
38
+ ...env,
39
+ region: "us-east-1",
40
+ },
41
+ crossRegionReferences: true,
42
+ })
43
+ : undefined;
44
+
45
+ customStackProps.hostedZone = usEast1Stack
46
+ ? customStackProps?.hostedZone
47
+ ? customStackProps?.hostedZone
48
+ : customStackProps?.domainName
49
+ ? route53.HostedZone.fromLookup(usEast1Stack, "MyHostedZone", {
50
+ domainName: customStackProps.domainName,
51
+ })
52
+ : undefined
53
+ : undefined;
54
+
55
+ customStackProps.certificate = usEast1Stack ? loadCertificate(usEast1Stack, customStackProps) : undefined;
56
+
57
+ const mainStack = new VikeStack(app, `VikeStack-${stackNameSuffix}`, {
58
+ env,
59
+ crossRegionReferences: true,
60
+ customStackProps,
61
+ });
62
+
63
+ if (usEast1Stack) {
64
+ mainStack.addDependency(usEast1Stack);
65
+ app.synth();
66
+ }
67
+ function loadCertificate(stack: cdk.Stack, stackConfig: CustomStackProps): certificatemanager.ICertificate | undefined {
68
+ const { domainName, subDomain, certificate, hostedZone } = stackConfig;
69
+ if (typeof certificate === "string") {
70
+ certificatemanager.Certificate.fromCertificateArn(stack, "Certificate", certificate);
71
+ } else if (certificate) {
72
+ return certificate;
73
+ }
74
+
75
+ if (!domainName) {
76
+ return undefined;
77
+ }
78
+
79
+ const siteDomainName = `${(subDomain?.length ?? 0 > 0) ? `${subDomain}.` : ""}${domainName}`;
80
+ return new certificatemanager.Certificate(stack, "Certificate", {
81
+ domainName: siteDomainName,
82
+ //subjectAlternativeNames: props.domainAliases,
83
+ validation: certificatemanager.CertificateValidation.fromDns(hostedZone),
84
+ });
85
+ }
@@ -0,0 +1,186 @@
1
+ #!/usr/bin/env node
2
+ import "source-map-support/register";
3
+ import { Construct } from "constructs";
4
+ import { join } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import * as cdk from "aws-cdk-lib";
7
+ import * as ssm from "aws-cdk-lib/aws-ssm";
8
+ import * as s3 from "aws-cdk-lib/aws-s3";
9
+ import * as s3deploy from "aws-cdk-lib/aws-s3-deployment";
10
+ import * as lambda from "aws-cdk-lib/aws-lambda";
11
+ import * as logs from "aws-cdk-lib/aws-logs";
12
+ import * as cloudfront from "aws-cdk-lib/aws-cloudfront";
13
+ import * as nodejs from "aws-cdk-lib/aws-lambda-nodejs";
14
+ import * as origin from "aws-cdk-lib/aws-cloudfront-origins";
15
+ import * as api from "aws-cdk-lib/aws-apigatewayv2";
16
+ import { HttpLambdaIntegration } from "aws-cdk-lib/aws-apigatewayv2-integrations";
17
+ import * as route53 from "aws-cdk-lib/aws-route53";
18
+ import * as targets from "aws-cdk-lib/aws-route53-targets";
19
+ import { existsSync } from "node:fs";
20
+ import type { CustomStackProps } from "../bin/infrastructure";
21
+
22
+ type VikeStackProps = cdk.StackProps & {
23
+ customStackProps: CustomStackProps;
24
+ };
25
+
26
+ // Define __dirname for ES module scope
27
+ const __filename = fileURLToPath(import.meta.url);
28
+ const __dirname = join(__filename, "..");
29
+
30
+ export class VikeStack extends cdk.Stack {
31
+ readonly distributionUrlParameterName = `/${this.stackName}/distribution/url`;
32
+
33
+ constructor(scope: Construct, id: string, props: VikeStackProps) {
34
+ super(scope, id, props);
35
+
36
+ const certificate =
37
+ props.customStackProps?.certificate && typeof props.customStackProps?.certificate !== "string"
38
+ ? props.customStackProps?.certificate
39
+ : undefined;
40
+
41
+ const hostedZone = props.customStackProps?.hostedZone;
42
+ const subDomain = props.customStackProps?.subDomain;
43
+ const domainName = props.customStackProps?.domainName;
44
+ const siteDomainName = domainName
45
+ ? `${(subDomain?.length ?? 0 > 0) ? `${subDomain}.` : ""}${domainName}`
46
+ : undefined;
47
+
48
+ const bucket = new s3.Bucket(this, "StaticAssetsBucket", {
49
+ /**
50
+ * The default removal policy is RETAIN, which means that cdk destroy will not attempt to delete
51
+ * the new bucket, and it will remain in your account until manually deleted. By setting the policy to
52
+ * DESTROY, cdk destroy will attempt to delete the bucket, but will error if the bucket is not empty.
53
+ */
54
+ removalPolicy: cdk.RemovalPolicy.DESTROY, // NOT recommended for production code
55
+
56
+ /**
57
+ * For sample purposes only, if you create an S3 bucket then populate it, stack destruction fails. This
58
+ * setting will enable full cleanup of the demo.
59
+ */
60
+ autoDeleteObjects: true, // NOT recommended for production code
61
+ });
62
+
63
+ // Create a Lambda function for the backend
64
+ const banner =
65
+ "const require = (await import('node:module')).createRequire(import.meta.url);const __filename = (await import('node:url')).fileURLToPath(import.meta.url);const __dirname = (await import('node:path')).dirname(__filename);";
66
+
67
+ const fn = new nodejs.NodejsFunction(this, "RequestHandler", {
68
+ handler: "handler",
69
+ entry: join(__dirname, "../../entry_aws_lambda.ts"),
70
+ // fix error: "Cannot find a package lock file ..." when using "bun" javascript package manager and runtime
71
+ depsLockFilePath: findBunLockFile(),
72
+ environment: {
73
+ NODE_ENV: "production",
74
+ },
75
+ bundling: {
76
+ banner,
77
+ format: nodejs.OutputFormat.ESM,
78
+ minify: true,
79
+ target: "esnext",
80
+ //nodeModules: ["react", "react-dom"],
81
+ esbuildArgs: {
82
+ "--tree-shaking": true,
83
+ },
84
+ },
85
+ runtime: lambda.Runtime.NODEJS_20_X,
86
+ architecture: lambda.Architecture.ARM_64,
87
+ memorySize: 256,
88
+ timeout: cdk.Duration.seconds(10),
89
+ logRetention: logs.RetentionDays.THREE_DAYS,
90
+ tracing: lambda.Tracing.ACTIVE,
91
+ });
92
+
93
+ const integration = new HttpLambdaIntegration("RequestHandlerIntegration", fn, {
94
+ payloadFormatVersion: api.PayloadFormatVersion.VERSION_2_0,
95
+ });
96
+
97
+ const httpApi = new api.HttpApi(this, "WebsiteApi", {
98
+ defaultIntegration: integration,
99
+ });
100
+
101
+ const httpApiUrl = `${httpApi.httpApiId}.execute-api.${cdk.Stack.of(this).region}.${cdk.Stack.of(this).urlSuffix}`;
102
+
103
+ // Create a CloudFront distribution with custom behaviors
104
+ const requestHandlerOrigin = new origin.HttpOrigin(httpApiUrl);
105
+
106
+ const requestHandlerBehavior: cloudfront.AddBehaviorOptions = {
107
+ allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,
108
+ viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
109
+ cachePolicy: cloudfront.CachePolicy.CACHING_DISABLED,
110
+ // https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-managed-origin-request-policies.html
111
+ originRequestPolicy: cloudfront.OriginRequestPolicy.ALL_VIEWER_EXCEPT_HOST_HEADER,
112
+ compress: true,
113
+ };
114
+
115
+ const assetOrigin = new origin.S3Origin(bucket);
116
+ const assetBehaviorOptions = {
117
+ viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
118
+ compress: true,
119
+ };
120
+
121
+ const distribution = new cloudfront.Distribution(this, "CloudFront", {
122
+ defaultBehavior: {
123
+ origin: requestHandlerOrigin,
124
+ ...requestHandlerBehavior,
125
+ },
126
+ domainNames: siteDomainName ? [siteDomainName] : undefined,
127
+ certificate,
128
+ enableIpv6: true,
129
+ minimumProtocolVersion: cloudfront.SecurityPolicyProtocol.TLS_V1_2_2021,
130
+ httpVersion: cloudfront.HttpVersion.HTTP2_AND_3,
131
+ priceClass: cloudfront.PriceClass.PRICE_CLASS_100,
132
+ });
133
+
134
+ distribution.addBehavior("/assets/*", assetOrigin, assetBehaviorOptions);
135
+
136
+ // Deploy static assets to the S3 bucket and invalidate the CloudFront cache
137
+ new s3deploy.BucketDeployment(this, "DeployStaticAssets", {
138
+ sources: [s3deploy.Source.asset(join(__dirname, "../../dist/client"))],
139
+ destinationBucket: bucket,
140
+ distribution,
141
+ distributionPaths: ["/*"],
142
+ prune: true,
143
+ cacheControl: [
144
+ s3deploy.CacheControl.maxAge(cdk.Duration.days(365)),
145
+ s3deploy.CacheControl.sMaxAge(cdk.Duration.days(365)),
146
+ ],
147
+ });
148
+
149
+ // Create a Route 53 alias record pointing to the CloudFront distribution
150
+ if (hostedZone) {
151
+ new route53.ARecord(this, "AliasRecord", {
152
+ zone: hostedZone,
153
+ target: route53.RecordTarget.fromAlias(new targets.CloudFrontTarget(distribution)),
154
+ recordName: subDomain ?? "", // This will create a record for www.example.com
155
+ });
156
+ }
157
+
158
+ // Store the CloudFront URL in an SSM parameter
159
+ new ssm.StringParameter(this, "DistributionUrlParameter", {
160
+ parameterName: this.distributionUrlParameterName,
161
+ stringValue: siteDomainName ? siteDomainName! : distribution.distributionDomainName,
162
+ tier: ssm.ParameterTier.STANDARD,
163
+ });
164
+
165
+ // Output the CloudFront URL and API endpoint
166
+ new cdk.CfnOutput(this, "CloudFrontURL", {
167
+ value: `https://${siteDomainName ? siteDomainName : distribution.distributionDomainName}`,
168
+ });
169
+
170
+ new cdk.CfnOutput(this, "CloudFrontID", {
171
+ value: distribution.distributionId,
172
+ });
173
+ }
174
+ }
175
+
176
+ function findBunLockFile() {
177
+ let bunLockFile = join(__dirname, "../../", "bun.lockb");
178
+ if (existsSync(bunLockFile)) {
179
+ return bunLockFile;
180
+ }
181
+ bunLockFile = join(__dirname, "../../", "../../", "bun.lockb"); // special case for bat tests
182
+ if (existsSync(bunLockFile)) {
183
+ return bunLockFile;
184
+ }
185
+ return undefined;
186
+ }
@@ -0,0 +1,72 @@
1
+ {
2
+ "app": "pnpm tsx cdk/bin/infrastructure.ts",
3
+ "watch": {
4
+ "include": [
5
+ "**"
6
+ ],
7
+ "exclude": [
8
+ "README.md",
9
+ "cdk*.json",
10
+ "**/*.d.ts",
11
+ "**/*.js",
12
+ "tsconfig.json",
13
+ "package*.json",
14
+ "yarn.lock",
15
+ "node_modules",
16
+ "test"
17
+ ]
18
+ },
19
+ "context": {
20
+ "@aws-cdk/core:newStyleStackSynthesis": true,
21
+ "@aws-cdk/aws-lambda:recognizeLayerVersion": true,
22
+ "@aws-cdk/core:checkSecretUsage": true,
23
+ "@aws-cdk/core:target-partitions": [
24
+ "aws",
25
+ "aws-cn"
26
+ ],
27
+ "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
28
+ "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
29
+ "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
30
+ "@aws-cdk/aws-iam:minimizePolicies": true,
31
+ "@aws-cdk/core:validateSnapshotRemovalPolicy": true,
32
+ "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
33
+ "@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
34
+ "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
35
+ "@aws-cdk/aws-apigateway:disableCloudWatchRole": true,
36
+ "@aws-cdk/core:enablePartitionLiterals": true,
37
+ "@aws-cdk/aws-events:eventsTargetQueueSameAccount": true,
38
+ "@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true,
39
+ "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true,
40
+ "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true,
41
+ "@aws-cdk/aws-route53-patters:useCertificate": true,
42
+ "@aws-cdk/customresources:installLatestAwsSdkDefault": false,
43
+ "@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true,
44
+ "@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true,
45
+ "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true,
46
+ "@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true,
47
+ "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true,
48
+ "@aws-cdk/aws-redshift:columnId": true,
49
+ "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true,
50
+ "@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true,
51
+ "@aws-cdk/aws-apigateway:requestValidatorUniqueId": true,
52
+ "@aws-cdk/aws-kms:aliasNameRef": true,
53
+ "@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": true,
54
+ "@aws-cdk/core:includePrefixInUniqueNameGeneration": true,
55
+ "@aws-cdk/aws-efs:denyAnonymousAccess": true,
56
+ "@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true,
57
+ "@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": true,
58
+ "@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true,
59
+ "@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": true,
60
+ "@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": true,
61
+ "@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": true,
62
+ "@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": true,
63
+ "@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": true,
64
+ "@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": true,
65
+ "@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": true,
66
+ "@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": true,
67
+ "@aws-cdk/aws-eks:nodegroupNameAttribute": true,
68
+ "@aws-cdk/aws-ec2:ebsDefaultGp3Volume": true,
69
+ "@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": true,
70
+ "@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": false
71
+ }
72
+ }
@@ -0,0 +1,116 @@
1
+ import { beforeAll, describe, expect, it } from "vitest";
2
+
3
+ import { execSync } from "node:child_process";
4
+ import { existsSync, readdirSync, readFileSync, rmSync } from "node:fs";
5
+ import path from "node:path";
6
+ import * as which from "which";
7
+
8
+ const bunExists = which.sync("bun", { nothrow: true }) !== null;
9
+ const npmCli = bunExists ? "bun" : "pnpm";
10
+
11
+ console.log("RUN TESTS ***");
12
+
13
+ describe("AWSHandler", () => {
14
+ beforeAll(
15
+ async () => {
16
+ if (existsSync(path.join(process.cwd(), "cdk.out"))) {
17
+ rmSync(path.join(process.cwd(), "cdk.out"), { recursive: true });
18
+ }
19
+ /*
20
+ * `--build "${npmCli} run build"` is required to build the project before synth
21
+ */
22
+ const synthCommand = `${npmCli} run cdk --json --build "${npmCli} run build" synth`;
23
+ execSync(synthCommand, {
24
+ encoding: "utf8",
25
+ maxBuffer: 50 * 1024 * 1024,
26
+ env: {
27
+ BUN_LOCKFILE: "../../bun.lockb", // This is to make sure that the correct lockfile is used in a bun project
28
+ PATH: process.env.PATH,
29
+ },
30
+ });
31
+ },
32
+ 2 * 60 * 1000,
33
+ );
34
+
35
+ it("should request a page from the AWS handler", async () => {
36
+ const cdkOutPath = path.join(process.cwd(), "cdk.out");
37
+ const templateFilePath = readdirSync(cdkOutPath).find(
38
+ (file) => file.startsWith("VikeStack-") && file.endsWith(".template.json"),
39
+ );
40
+ const templateFullPath = path.join(cdkOutPath, templateFilePath!);
41
+ expect(existsSync(templateFullPath)).toBe(true);
42
+ const cloudfrontTemplateJson = readFileSync(templateFullPath, "utf8");
43
+ const requestHandlerFolder = extractRequestHandlerPath(
44
+ JSON.parse(cloudfrontTemplateJson),
45
+ "/RequestHandler/Resource",
46
+ );
47
+ const requestHandlerPath = path.join(process.cwd(), "cdk.out", requestHandlerFolder!, "index.mjs");
48
+ expect(existsSync(requestHandlerPath)).toBe(true);
49
+
50
+ const { handler } = await import(requestHandlerPath);
51
+ const event = {
52
+ version: "2.0",
53
+ routeKey: "$default",
54
+ rawPath: "/",
55
+ rawQueryString: "",
56
+ headers: {
57
+ accept: "*/*",
58
+ "content-length": "0",
59
+ host: "example.com",
60
+ "user-agent": "PostmanRuntime/7.26.8",
61
+ "x-amzn-trace-id": "Root=1-5f84c7a9-0e5b1e1e1e1e1e1e1e1e1e1e",
62
+ "x-forwarded-for": "127.0.0.1",
63
+ "x-forwarded-port": "443",
64
+ "x-forwarded-proto": "https",
65
+ },
66
+ requestContext: {
67
+ accountId: "123456789012",
68
+ apiId: "api-id",
69
+ domainName: "example.com",
70
+ domainPrefix: "example",
71
+ http: {
72
+ method: "GET",
73
+ path: "/",
74
+ protocol: "HTTP/1.1",
75
+ sourceIp: "127.0.0.1",
76
+ userAgent: "PostmanRuntime/7.26.8",
77
+ },
78
+ requestId: "id",
79
+ routeKey: "$default",
80
+ stage: "$default",
81
+ time: "12/Mar/2021:19:03:58 +0000",
82
+ timeEpoch: 1615578238000,
83
+ },
84
+ isBase64Encoded: false,
85
+ };
86
+ const response = await handler(event, {});
87
+ expect(response.statusCode).toBe(200);
88
+ const body = response.isBase64Encoded ? Buffer.from(response.body, "base64").toString("utf8") : response.body;
89
+ expect(body).toContain("My Vike App");
90
+ });
91
+ });
92
+
93
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
94
+ type JsonData = Record<string, any>;
95
+
96
+ function extractRequestHandlerPath(jsonData: JsonData, targetCdkPath: string): string | null {
97
+ let assetPath: string | null = null;
98
+
99
+ function traverse(obj: JsonData) {
100
+ if (typeof obj !== "object" || obj === null) return;
101
+
102
+ if (obj?.["aws:cdk:path"]?.endsWith(targetCdkPath)) {
103
+ assetPath = obj?.["aws:asset:path"];
104
+ return;
105
+ }
106
+
107
+ for (const key in obj) {
108
+ if (obj?.[key]) {
109
+ traverse(obj[key]);
110
+ }
111
+ }
112
+ }
113
+
114
+ traverse(jsonData);
115
+ return assetPath;
116
+ }
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from "vitest/config";
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ include: ["tests/**/*.spec.ts"], // Adjust the pattern as needed
6
+ watch: false,
7
+ },
8
+ });
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ import "source-map-support/register";
3
+ import * as cdk from "aws-cdk-lib";
4
+ import * as certificatemanager from "aws-cdk-lib/aws-certificatemanager";
5
+ import * as route53 from "aws-cdk-lib/aws-route53";
6
+ export type CustomStackProps = cdk.StackProps & {
7
+ domainName?: string;
8
+ subDomain?: string;
9
+ certificate?: string | certificatemanager.ICertificate;
10
+ hostedZone?: route53.IHostedZone;
11
+ };
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ import "source-map-support/register";
3
+ import { Construct } from "constructs";
4
+ import * as cdk from "aws-cdk-lib";
5
+ import type { CustomStackProps } from "../bin/infrastructure";
6
+ type VikeStackProps = cdk.StackProps & {
7
+ customStackProps: CustomStackProps;
8
+ };
9
+ export declare class VikeStack extends cdk.Stack {
10
+ readonly distributionUrlParameterName: string;
11
+ constructor(scope: Construct, id: string, props: VikeStackProps);
12
+ }
13
+ export {};
@@ -0,0 +1,2 @@
1
+ declare const _default: import("vite").UserConfig;
2
+ export default _default;
@@ -58,6 +58,10 @@ var require_package = __commonJS({
58
58
  "@hattip/core": "^0.0.47",
59
59
  "@hattip/router": "^0.0.47",
60
60
  "@hattip/vite": "^0.0.47",
61
+ "@hattip/adapter-aws-lambda": "^0.0.47",
62
+ "@hattip/static": "^0.0.47",
63
+ "@hattip/walk": "^0.0.47",
64
+ "@types/aws-lambda": "^8.10.143",
61
65
  "@trpc/server": "^10.45.2",
62
66
  "@types/node": "^18.19.14",
63
67
  "@universal-middleware/hattip": "^0.2.4",
@@ -82,12 +86,18 @@ var require_package = __commonJS({
82
86
  exports: {
83
87
  "./hattip-entry": {
84
88
  types: "./dist/types/hattip-entry.d.ts"
89
+ },
90
+ "./entry_aws_lambda": {
91
+ types: "./dist/types/entry_aws_lambda.d.ts"
85
92
  }
86
93
  },
87
94
  typesVersions: {
88
95
  "*": {
89
96
  "hattip-entry": [
90
97
  "./dist/types/hattip-entry.d.ts"
98
+ ],
99
+ entry_aws_lambda: [
100
+ "./dist/types/entry_aws_lambda.d.ts"
91
101
  ]
92
102
  }
93
103
  }
@@ -136,7 +146,8 @@ async function getPackageJson(props) {
136
146
  "vite",
137
147
  "vike",
138
148
  "@universal-middleware/hattip",
139
- ...props.meta.BATI.has("vercel") ? ["@hattip/adapter-vercel-edge"] : []
149
+ ...props.meta.BATI.has("vercel") ? ["@hattip/adapter-vercel-edge"] : [],
150
+ ...props.meta.BATI.has("aws") ? ["@types/aws-lambda", "@hattip/adapter-aws-lambda", "@hattip/static", "@hattip/walk"] : []
140
151
  ]
141
152
  });
142
153
  }
@@ -0,0 +1,37 @@
1
+ /*{ @if (it.BATI.has("aws")) }*/
2
+ /*
3
+ entry_aws_lambda.ts
4
+
5
+ This file is the entry point for AWS Lambda
6
+
7
+ Notes:
8
+ * The file name must not have any special characters or dots except for the extension. https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html#API_CreateFunction_RequestSyntax
9
+
10
+ */
11
+
12
+ import { existsSync } from "node:fs";
13
+ import awsLambdaAdapter from "@hattip/adapter-aws-lambda";
14
+ import { walk } from "@hattip/walk";
15
+ import type { FileInfo } from "@hattip/walk";
16
+ import { createStaticMiddleware } from "@hattip/static";
17
+ import { createFileReader } from "@hattip/static/fs";
18
+ import hattipHandler from "@batijs/hattip/hattip-entry";
19
+ import type { Handler, APIGatewayProxyResultV2, APIGatewayProxyEventV2 } from "aws-lambda";
20
+
21
+ const root = new URL("./dist/client", import.meta.url);
22
+ const staticRootExists = existsSync(root);
23
+ const files = staticRootExists ? walk(root) : new Map<string, FileInfo>();
24
+ const staticMiddleware = staticRootExists
25
+ ? createStaticMiddleware(files, createFileReader(root), {
26
+ urlRoot: "/",
27
+ })
28
+ : undefined;
29
+
30
+ const awsHandler = awsLambdaAdapter((ctx) => {
31
+ if (hattipHandler === undefined) throw new Error("hattipHandler is undefined");
32
+ if (staticMiddleware === undefined) return hattipHandler(ctx);
33
+ return staticMiddleware(ctx) || hattipHandler(ctx);
34
+ });
35
+
36
+ export const handler: Handler<APIGatewayProxyEventV2, APIGatewayProxyResultV2> = awsHandler;
37
+ /*{ /if }*/
@@ -0,0 +1,2 @@
1
+ import type { Handler, APIGatewayProxyResultV2, APIGatewayProxyEventV2 } from "aws-lambda";
2
+ export declare const handler: Handler<APIGatewayProxyEventV2, APIGatewayProxyResultV2>;
@@ -55,6 +55,7 @@ var require_package = __commonJS({
55
55
  "@cloudflare/workers-types": "^4.20240821.1",
56
56
  "@hono/node-server": "^1.12.2",
57
57
  "@hono/vite-dev-server": "^0.15.1",
58
+ "@types/aws-lambda": "^8.10.145",
58
59
  "@trpc/server": "^10.45.2",
59
60
  "@types/node": "^18.19.14",
60
61
  "@universal-middleware/hono": "^0.2.5",
@@ -81,6 +82,9 @@ var require_package = __commonJS({
81
82
  "./hono-entry": {
82
83
  types: "./dist/types/hono-entry.d.ts"
83
84
  },
85
+ "./entry_aws_lambda": {
86
+ types: "./dist/types/entry_aws_lambda.d.ts"
87
+ },
84
88
  "./hono-entry.node": {
85
89
  types: "./dist/types/hono-entry.node.d.ts"
86
90
  }
@@ -90,6 +94,9 @@ var require_package = __commonJS({
90
94
  "hono-entry": [
91
95
  "./dist/types/hono-entry.d.ts"
92
96
  ],
97
+ entry_aws_lambda: [
98
+ "./dist/types/entry_aws_lambda.d.ts"
99
+ ],
93
100
  "hono-entry.node": [
94
101
  "./dist/types/hono-entry.node.d.ts"
95
102
  ]
@@ -120,7 +127,7 @@ async function getPackageJson(props) {
120
127
  }
121
128
  });
122
129
  return addDependency(packageJson, await Promise.resolve().then(() => __toESM(require_package(), 1)).then((x) => x.default), {
123
- devDependencies: ["@hono/vite-dev-server", "@types/node"],
130
+ devDependencies: ["@hono/vite-dev-server", "@types/node", "@types/aws-lambda"],
124
131
  dependencies: [
125
132
  "@hono/node-server",
126
133
  "@universal-middleware/hono",
@@ -0,0 +1,37 @@
1
+ /*{ @if (it.BATI.has("aws")) }*/
2
+ /*
3
+ entry_aws_lambda.ts
4
+
5
+ This file is the entry point for AWS Lambda
6
+
7
+ Notes:
8
+ * The file name must not have any special characters or dots except for the extension. https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html#API_CreateFunction_RequestSyntax
9
+
10
+ */
11
+
12
+ import { Hono } from "hono";
13
+ import { serveStatic } from "@hono/node-server/serve-static";
14
+ import { handle } from "hono/aws-lambda";
15
+ import type { LambdaEvent, LambdaContext } from "hono/aws-lambda";
16
+ import app from "@batijs/hono/hono-entry"; // file is provided by hono
17
+ import type { Handler, APIGatewayProxyResult } from "aws-lambda";
18
+
19
+ type Bindings = {
20
+ event: LambdaEvent;
21
+ lambdaContext: LambdaContext;
22
+ };
23
+
24
+ const lambdaApp = new Hono<{ Bindings: Bindings }>();
25
+
26
+ lambdaApp.use(
27
+ "/*",
28
+ serveStatic({
29
+ root: `./dist/client/`,
30
+ }),
31
+ );
32
+
33
+ lambdaApp.route("/", app!);
34
+ const awsHandler = handle(lambdaApp);
35
+
36
+ export const handler: Handler<LambdaEvent, APIGatewayProxyResult> = awsHandler;
37
+ /*{ /if }*/
@@ -0,0 +1,3 @@
1
+ import type { LambdaEvent } from "hono/aws-lambda";
2
+ import type { Handler, APIGatewayProxyResult } from "aws-lambda";
3
+ export declare const handler: Handler<LambdaEvent, APIGatewayProxyResult>;
@@ -26,6 +26,17 @@
26
26
  "files"
27
27
  ]
28
28
  },
29
+ {
30
+ "config": {
31
+ "if": {
32
+ "flag": "aws"
33
+ }
34
+ },
35
+ "folder": "@batijs/aws",
36
+ "subfolders": [
37
+ "files"
38
+ ]
39
+ },
29
40
  {
30
41
  "config": {
31
42
  "if": {
package/dist/index.js CHANGED
@@ -1677,7 +1677,7 @@ var createDefaultQueryTester = function(query, options) {
1677
1677
  // package.json
1678
1678
  var package_default = {
1679
1679
  name: "@batijs/cli",
1680
- version: "0.0.260",
1680
+ version: "0.0.261",
1681
1681
  type: "module",
1682
1682
  scripts: {
1683
1683
  "check-types": "tsc --noEmit",
@@ -1760,6 +1760,10 @@ Choose one of them, or simply remove selected Server`
1760
1760
  [RulesMessage.ERROR_LUCIA_R_COMPAT_DATABASE]: error(
1761
1761
  `${inverse(bold("Lucia"))} requires a ${inverse(bold("Database"))}, and is only compatible with ${inverse(bold("SQLite"))} or ${inverse(bold("Drizzle"))}`
1762
1762
  ),
1763
+ [RulesMessage.ERROR_AWS_R_COMPAT_SERVER]: error(
1764
+ `${inverse(bold("AWS"))} is only compatible with ${inverse(bold("Hono"))} or ${inverse(bold("HatTip"))}.
1765
+ Choose one of them, or simply remove selected Server`
1766
+ ),
1763
1767
  [RulesMessage.INFO_DRIZZLE_STACKBLITZ]: null
1764
1768
  };
1765
1769
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@batijs/cli",
3
- "version": "0.0.260",
3
+ "version": "0.0.261",
4
4
  "type": "module",
5
5
  "keywords": [],
6
6
  "description": "Next-gen scaffolder. Get started with fully-functional apps, and choose any tool you want",
@@ -20,12 +20,12 @@
20
20
  "typescript": "^5.5.4",
21
21
  "unplugin-purge-polyfills": "^0.0.5",
22
22
  "vite": "^5.4.2",
23
- "@batijs/build": "0.0.260",
24
- "@batijs/compile": "0.0.260"
23
+ "@batijs/compile": "0.0.261",
24
+ "@batijs/build": "0.0.261"
25
25
  },
26
26
  "dependencies": {
27
- "@batijs/features": "0.0.260",
28
- "@batijs/core": "0.0.260"
27
+ "@batijs/core": "0.0.261",
28
+ "@batijs/features": "0.0.261"
29
29
  },
30
30
  "bin": "./dist/index.js",
31
31
  "exports": {