Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
sahinvardar committed Feb 7, 2024
1 parent 21ed855 commit 22faaac
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 114 deletions.
1 change: 0 additions & 1 deletion example/deploy/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"private": true,
"name": "deploy",
"version": "0.1.14",
"type": "module",
"bin": {
"deploy": "bin/deploy.js"
Expand Down
12 changes: 4 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,17 @@
"watch": "tsc --build --watch"
},
"peerDependencies": {
"@apimda/npm-layer-version": "1.x",
"@aws-cdk/aws-apigatewayv2-alpha": "2.x",
"@aws-cdk/aws-apigatewayv2-integrations-alpha": "2.x",
"aws-cdk-lib": "2.x",
"aws-cdk-lib": ">= 2.115.0",
"constructs": "10.x"
},
"devDependencies": {
"@apimda/npm-layer-version": "^1.0.0",
"@aws-cdk/aws-apigatewayv2-alpha": "2.110.1-alpha.0",
"@aws-cdk/aws-apigatewayv2-integrations-alpha": "2.110.1-alpha.0",
"@sveltejs/kit": "^1.5.0",
"@types/aws-lambda": "^8.10.128",
"@types/folder-hash": "^4.0.4",
"@types/node": "^20.9.4",
"@typescript-eslint/eslint-plugin": "^6.12.0",
"aws-cdk-lib": "^2.110.1",
"aws-cdk": "^2.126.0",
"aws-cdk-lib": "^2.126.0",
"constructs": "^10.3.0",
"eslint": "^8.54.0",
"eslint-config-prettier": "^9.0.0",
Expand All @@ -63,6 +58,7 @@
"packageManager": "pnpm@8.10.5",
"pnpm": {
"overrides": {
"aws-cdk": "$aws-cdk-lib",
"typescript": "$typescript",
"aws-cdk-lib": "$aws-cdk-lib",
"constructs": "$constructs",
Expand Down
76 changes: 18 additions & 58 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 4 additions & 12 deletions src/svelte-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@ import * as s3 from 'aws-cdk-lib/aws-s3';
import * as s3d from 'aws-cdk-lib/aws-s3-deployment';
import * as cdk from 'aws-cdk-lib';
import fs from 'fs';
import * as apigw from '@aws-cdk/aws-apigatewayv2-alpha';
import * as apigw from 'aws-cdk-lib/aws-apigatewayv2';
import * as lambdaNode from 'aws-cdk-lib/aws-lambda-nodejs';
import * as apigwInt from '@aws-cdk/aws-apigatewayv2-integrations-alpha';
import * as apigwInt from 'aws-cdk-lib/aws-apigatewayv2-integrations';
import * as cfo from 'aws-cdk-lib/aws-cloudfront-origins';
import * as cf from 'aws-cdk-lib/aws-cloudfront';
import * as cm from 'aws-cdk-lib/aws-certificatemanager';
import * as r53t from 'aws-cdk-lib/aws-route53-targets';
import { NpmLayerVersion } from '@apimda/npm-layer-version';

import {
LAMBDA_ARCHITECTURE,
Expand Down Expand Up @@ -142,14 +141,6 @@ export class SvelteApp extends Construct {
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const svelteKitLayer = new NpmLayerVersion(this, 'SvelteKitLambdaLayer', {
layerPath: this.stackProps.svelteAppLayerPath ?? path.resolve(__dirname, '../layers/svelte-kit-layer'),
layerVersionProps: {
compatibleArchitectures: [LAMBDA_ARCHITECTURE],
compatibleRuntimes: [LAMBDA_RUNTIME]
}
});

const serverLambda = new lambdaNode.NodejsFunction(this, 'SvelteServerLambda', {
currentVersionOptions: this.stackProps.provisionedConcurrentExecutions
? {
Expand All @@ -163,10 +154,11 @@ export class SvelteApp extends Construct {
entry: path.resolve(__dirname, 'svelte-server-handler.js'),
environment: this.stackProps.svelteServerEnvironment,
bundling: {
nodeModules: ['@sveltejs/kit'],
format: lambdaNode.OutputFormat.ESM,
minify: false,
target: LAMBDA_ESBUILD_TARGET,
externalModules: [LAMBDA_ESBUILD_EXTERNAL_AWS_SDK, './server/index.js', './server/manifest-full.js'],
externalModules: [LAMBDA_ESBUILD_EXTERNAL_AWS_SDK],
commandHooks: {
afterBundling(inputDir: string, outputDir: string): string[] {
return [
Expand Down
28 changes: 13 additions & 15 deletions src/svelte-server-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export type Handler = (event: APIGatewayProxyEventV2) => Promise<APIGatewayProxy
export function createSvelteServerHandler(serverDir: string): Handler {
return async event => {
const { Server } = await import(path.resolve(serverDir, 'index.js'));
const { manifest } = await import(path.resolve(serverDir, 'manifest.js'));
const { manifest } = await import(path.resolve(serverDir, 'manifest-full.js'));
const server = new Server(manifest) as Server;
await server.init({ env: process.env });

Expand All @@ -21,24 +21,22 @@ export function createSvelteServerHandler(serverDir: string): Handler {
const queryString = event.rawQueryString ? `?${event.rawQueryString}` : undefined;
const url = `${origin}${event.requestContext.http.path}${queryString ?? ''}`;

console.log('url:', url);

if (event.cookies) {
event.headers['cookie'] = event.cookies.join('; ');
}

const response = await server.respond(
new Request(url, {
method: event.requestContext.http.method,
headers: new Headers((event.headers as Record<string, string>) || {}),
body
}),
{
getClientAddress() {
return event.requestContext.http.sourceIp;
}
const req = new Request(url, {
method: event.requestContext.http.method,
headers: new Headers((event.headers as Record<string, string>) || {}),
body
});

const response = await server.respond(req, {
platform: { req },
getClientAddress() {
return event.requestContext.http.sourceIp;
}
);
});

const headers: Record<string, string> = {};

Expand All @@ -54,4 +52,4 @@ export function createSvelteServerHandler(serverDir: string): Handler {
};
}

export const handler: APIGatewayProxyHandlerV2 = await createSvelteServerHandler('/opt/server');
export const handler: APIGatewayProxyHandlerV2 = createSvelteServerHandler('./server');
37 changes: 33 additions & 4 deletions src/tests/svelte-server-handler.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,41 @@
import { test, describe } from 'vitest';
import { test, describe, expect } from 'vitest';
import path from 'node:path';
import { createSvelteServerHandler } from '../svelte-server-handler.js';
import { createAwsProxyEvent } from './test-utils.js';
//import formDataToString from 'formdata-to-string';

describe('svelte-server-handler', () => {
test('createSvelteServerHandler', async () => {
const handler = await createSvelteServerHandler(path.resolve(__dirname, '../../example/svelte-app/build/server'));
const rootResponse = await handler(createAwsProxyEvent('/', 'GET'));
console.log(rootResponse.statusCode);
const handler = createSvelteServerHandler(
path.resolve(__dirname, '../../example/svelte-app/.svelte-kit/output/server')
);

const pages = ['/', '/about', '/sverdle', '/sverdle/how-to-play'];

for (const page of pages) {
const preRenderedResponse = await handler(createAwsProxyEvent(page, 'GET'));
expect(preRenderedResponse.statusCode).toBe(200);
expect(preRenderedResponse.headers?.['content-type']).toBe('text/html');
}

//TODO: Get this working
// const formData = new FormData();
// formData.append('guess', 'e');
// formData.append('guess', 'e');
// formData.append('guess', 'e');
// formData.append('guess', 'e');

// const formDataBody = await formDataToString(formData);
// const [boundary] = formDataBody.split('\n');
// const formServerAction = await handler(
// createAwsProxyEvent('/sverdle?/enter', 'POST', {
// body: formDataBody,
// headers: {
// 'content-type': `multipart/form-data; boundary=${boundary}`,
// 'content-length': formDataBody.length.toString(),
// origin: 'https://localhost'
// }
// })
// );
});
});
12 changes: 9 additions & 3 deletions src/tests/test-utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { APIGatewayProxyEventV2 } from 'aws-lambda';

export function createAwsProxyEvent(path: string, method: string): APIGatewayProxyEventV2 {
export function createAwsProxyEvent(
path: string,
method: string,
override?: Partial<APIGatewayProxyEventV2>
): APIGatewayProxyEventV2 {
return {
version: '2.0',
routeKey: '$default',
Expand All @@ -9,7 +13,8 @@ export function createAwsProxyEvent(path: string, method: string): APIGatewayPro
cookies: ['cookie1', 'cookie2'],
headers: {
Header1: 'value1',
Header2: 'value1,value2'
Header2: 'value1,value2',
origin: 'https://localhost'
},
queryStringParameters: {},
requestContext: {
Expand Down Expand Up @@ -47,6 +52,7 @@ export function createAwsProxyEvent(path: string, method: string): APIGatewayPro
stageVariables: {
stageVariable1: 'value1',
stageVariable2: 'value2'
}
},
...override
};
}
22 changes: 9 additions & 13 deletions todos/index.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
# CDK Svelte App

- [] Add turbo to project
- [] Refactor server handler to create function
- [] Use @codegenie/serverless-express to convert AWS Lambda Event to node req, res
- [] Parametrize Svelte output path to get Svelte server
- [] Update CDK version and use core apigw constructs
- [] Add testing for server lambda
- [] Check if SvelteKit Lambda Layer is needed or not, I assume it is not needed
- [] Proxy all methods
- [] PUT
- [] PATCH
- [] DELETE
- [x] Refactor server handler to create function
- [x] Use @codegenie/serverless-express to convert AWS Lambda Event to node req, res
- [x] Parametrize Svelte output path to get Svelte server
- [x] Update CDK version and use core apigw constructs
- [x] Add testing for server lambda
- [x] Check if SvelteKit Lambda Layer is needed or not, I assume it is not needed
- [] Check if check for no-cache control header makes sense, some of those 300 are permanent and caching makes sense in this case
- [] Figure TS dev import vs Prd import
- [] Remove the need for package.json magic for esm support in lambda
- [] Check the use if a Lambda Layer for the resulting svelte server code
- [x] Figure TS dev import vs Prd import
- [x] Remove the need for package.json magic for esm support in lambda
- [x] Check the use if a Lambda Layer for the resulting svelte server code

0 comments on commit 22faaac

Please sign in to comment.