From f8bdc9ed51f0678c5407d8b8fe7b9d153f6f7aeb Mon Sep 17 00:00:00 2001 From: Jay V Date: Tue, 15 Oct 2024 15:22:55 -0400 Subject: [PATCH] docs: solidstart ws --- examples/aws-ec2-pulumi/sst.config.ts | 32 ++--- examples/aws-solid-container-ws/.dockerignore | 3 + examples/aws-solid-container-ws/.gitignore | 32 +++++ examples/aws-solid-container-ws/Dockerfile | 23 ++++ examples/aws-solid-container-ws/README.md | 32 +++++ examples/aws-solid-container-ws/app.config.ts | 15 +++ examples/aws-solid-container-ws/package.json | 21 ++++ .../aws-solid-container-ws/public/favicon.ico | Bin 0 -> 664 bytes examples/aws-solid-container-ws/src/app.css | 39 ++++++ examples/aws-solid-container-ws/src/app.tsx | 22 ++++ .../src/components/Counter.css | 21 ++++ .../src/components/Counter.tsx | 11 ++ .../src/entry-client.tsx | 4 + .../src/entry-server.tsx | 21 ++++ .../aws-solid-container-ws/src/global.d.ts | 1 + .../src/routes/[...404].tsx | 19 +++ .../src/routes/about.tsx | 10 ++ .../src/routes/index.tsx | 19 +++ examples/aws-solid-container-ws/src/ws.ts | 23 ++++ examples/aws-solid-container-ws/sst-env.d.ts | 18 +++ examples/aws-solid-container-ws/sst.config.ts | 50 ++++++++ examples/aws-solid-container-ws/tsconfig.json | 19 +++ www/src/content/docs/docs/examples.mdx | 118 +++++++++++++++++- www/src/content/docs/docs/start/aws/solid.mdx | 10 +- 24 files changed, 542 insertions(+), 21 deletions(-) create mode 100644 examples/aws-solid-container-ws/.dockerignore create mode 100644 examples/aws-solid-container-ws/.gitignore create mode 100644 examples/aws-solid-container-ws/Dockerfile create mode 100644 examples/aws-solid-container-ws/README.md create mode 100644 examples/aws-solid-container-ws/app.config.ts create mode 100644 examples/aws-solid-container-ws/package.json create mode 100644 examples/aws-solid-container-ws/public/favicon.ico create mode 100644 examples/aws-solid-container-ws/src/app.css create mode 100644 examples/aws-solid-container-ws/src/app.tsx create mode 100644 examples/aws-solid-container-ws/src/components/Counter.css create mode 100644 examples/aws-solid-container-ws/src/components/Counter.tsx create mode 100644 examples/aws-solid-container-ws/src/entry-client.tsx create mode 100644 examples/aws-solid-container-ws/src/entry-server.tsx create mode 100644 examples/aws-solid-container-ws/src/global.d.ts create mode 100644 examples/aws-solid-container-ws/src/routes/[...404].tsx create mode 100644 examples/aws-solid-container-ws/src/routes/about.tsx create mode 100644 examples/aws-solid-container-ws/src/routes/index.tsx create mode 100644 examples/aws-solid-container-ws/src/ws.ts create mode 100644 examples/aws-solid-container-ws/sst-env.d.ts create mode 100644 examples/aws-solid-container-ws/sst.config.ts create mode 100644 examples/aws-solid-container-ws/tsconfig.json diff --git a/examples/aws-ec2-pulumi/sst.config.ts b/examples/aws-ec2-pulumi/sst.config.ts index 80bd2118a..fc6318c02 100644 --- a/examples/aws-ec2-pulumi/sst.config.ts +++ b/examples/aws-ec2-pulumi/sst.config.ts @@ -1,21 +1,21 @@ /// /** - * ## EC2 (using Pulumi) example + * ## EC2 with Pulumi * - * Use raw pulumi code to create an EC2 instance. + * Use raw Pulumi resources to create an EC2 instance. */ export default $config({ - app(input) { - return { - name: "aws-ec2-pulumi", - home: "aws", - removal: input?.stage === "production" ? "retain" : "remove", - }; - }, - async run() { - // Notice you don't need to import pulumi, it is already part of sst. - const securityGroup = new aws.ec2.SecurityGroup("web-secgrp", { + app(input) { + return { + name: "aws-ec2-pulumi", + home: "aws", + removal: input?.stage === "production" ? "retain" : "remove", + }; + }, + async run() { + // Notice you don't need to import pulumi, it is already part of sst. + const securityGroup = new aws.ec2.SecurityGroup("web-secgrp", { ingress: [ { protocol: "tcp", @@ -52,8 +52,8 @@ export default $config({ associatePublicIpAddress: true, }); - return { - app: server.publicIp, - }; - }, + return { + app: server.publicIp, + }; + }, }); diff --git a/examples/aws-solid-container-ws/.dockerignore b/examples/aws-solid-container-ws/.dockerignore new file mode 100644 index 000000000..89e3d841f --- /dev/null +++ b/examples/aws-solid-container-ws/.dockerignore @@ -0,0 +1,3 @@ +node_modules +# sst +.sst diff --git a/examples/aws-solid-container-ws/.gitignore b/examples/aws-solid-container-ws/.gitignore new file mode 100644 index 000000000..8ebae3024 --- /dev/null +++ b/examples/aws-solid-container-ws/.gitignore @@ -0,0 +1,32 @@ + +dist +.solid +.output +.vercel +.netlify +.vinxi +app.config.timestamp_*.js + +# Environment +.env +.env*.local + +# dependencies +/node_modules + +# IDEs and editors +/.idea +.project +.classpath +*.launch +.settings/ + +# Temp +gitignore + +# System Files +.DS_Store +Thumbs.db + +# sst +.sst diff --git a/examples/aws-solid-container-ws/Dockerfile b/examples/aws-solid-container-ws/Dockerfile new file mode 100644 index 000000000..eb842b02d --- /dev/null +++ b/examples/aws-solid-container-ws/Dockerfile @@ -0,0 +1,23 @@ +FROM node:lts AS base + +WORKDIR /src + +# Build +FROM base as build + +COPY --link package.json package-lock.json ./ +RUN npm install + +COPY --link . . + +RUN npm run build + +# Run +FROM base + +ENV PORT=3000 +ENV NODE_ENV=production + +COPY --from=build /src/.output /src/.output + +CMD [ "node", ".output/server/index.mjs" ] diff --git a/examples/aws-solid-container-ws/README.md b/examples/aws-solid-container-ws/README.md new file mode 100644 index 000000000..a84af3943 --- /dev/null +++ b/examples/aws-solid-container-ws/README.md @@ -0,0 +1,32 @@ +# SolidStart + +Everything you need to build a Solid project, powered by [`solid-start`](https://start.solidjs.com); + +## Creating a project + +```bash +# create a new project in the current directory +npm init solid@latest + +# create a new project in my-app +npm init solid@latest my-app +``` + +## Developing + +Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: + +```bash +npm run dev + +# or start the server and open the app in a new browser tab +npm run dev -- --open +``` + +## Building + +Solid apps are built with _presets_, which optimise your project for deployment to different environments. + +By default, `npm run build` will generate a Node app that you can run with `npm start`. To use a different preset, add it to the `devDependencies` in `package.json` and specify in your `app.config.js`. + +## This project was created with the [Solid CLI](https://solid-cli.netlify.app) diff --git a/examples/aws-solid-container-ws/app.config.ts b/examples/aws-solid-container-ws/app.config.ts new file mode 100644 index 000000000..792fe7a64 --- /dev/null +++ b/examples/aws-solid-container-ws/app.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from "@solidjs/start/config"; + +export default defineConfig({ + server: { + experimental: { + websocket: true, + }, + }, +}).addRouter({ + name: "ws", + type: "http", + handler: "./src/ws.ts", + target: "server", + base: "/ws", +}); diff --git a/examples/aws-solid-container-ws/package.json b/examples/aws-solid-container-ws/package.json new file mode 100644 index 000000000..bfabc86bc --- /dev/null +++ b/examples/aws-solid-container-ws/package.json @@ -0,0 +1,21 @@ +{ + "name": "example-basic", + "type": "module", + "scripts": { + "build": "vinxi build", + "dev": "vinxi dev", + "start": "vinxi start", + "version": "vinxi version" + }, + "dependencies": { + "@solidjs/meta": "^0.29.4", + "@solidjs/router": "^0.14.7", + "@solidjs/start": "^1.0.8", + "solid-js": "^1.9.1", + "sst": "3.2.22", + "vinxi": "^0.4.3" + }, + "engines": { + "node": ">=18" + } +} diff --git a/examples/aws-solid-container-ws/public/favicon.ico b/examples/aws-solid-container-ws/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..fb282da0719ef6ab4c1732df93be6216b0d85520 GIT binary patch literal 664 zcmV;J0%!e+P)m9ebk1R zejT~~6f_`?;`cEd!+`7(hw@%%2;?RN8gX-L?z6cM( zKoG@&w+0}f@Pfvwc+deid)qgE!L$ENKYjViZC_Zcr>L(`2oXUT8f0mRQ(6-=HN_Ai zeBBEz3WP+1Cw`m!49Wf!MnZzp5bH8VkR~BcJ1s-j90TAS2Yo4j!J|KodxYR%3Numw zA?gq6e`5@!W~F$_De3yt&uspo&2yLb$(NwcPPI-4LGc!}HdY%jfq@AFs8LiZ4k(p} zZ!c9o+qbWYs-Mg zgdyTALzJX&7QXHdI_DPTFL33;w}88{e6Zk)MX0kN{3DX9uz#O_L58&XRH$Nvvu;fO zf&)7@?C~$z1K<>j0ga$$MIg+5xN;eQ?1-CA=`^Y169@Ab6!vcaNP=hxfKN%@Ly^R* zK1iv*s1Yl6_dVyz8>ZqYhz6J4|3fQ@2LQeX@^%W(B~8>=MoEmBEGGD1;gHXlpX>!W ym)!leA2L@`cpb^hy)P75=I!`pBYxP7<2VfQ3j76qLgzIA0000 ( + + SolidStart - Basic + Index + About + {props.children} + + )} + > + + + ); +} diff --git a/examples/aws-solid-container-ws/src/components/Counter.css b/examples/aws-solid-container-ws/src/components/Counter.css new file mode 100644 index 000000000..220e17946 --- /dev/null +++ b/examples/aws-solid-container-ws/src/components/Counter.css @@ -0,0 +1,21 @@ +.increment { + font-family: inherit; + font-size: inherit; + padding: 1em 2em; + color: #335d92; + background-color: rgba(68, 107, 158, 0.1); + border-radius: 2em; + border: 2px solid rgba(68, 107, 158, 0); + outline: none; + width: 200px; + font-variant-numeric: tabular-nums; + cursor: pointer; +} + +.increment:focus { + border: 2px solid #335d92; +} + +.increment:active { + background-color: rgba(68, 107, 158, 0.2); +} \ No newline at end of file diff --git a/examples/aws-solid-container-ws/src/components/Counter.tsx b/examples/aws-solid-container-ws/src/components/Counter.tsx new file mode 100644 index 000000000..091fc5d0b --- /dev/null +++ b/examples/aws-solid-container-ws/src/components/Counter.tsx @@ -0,0 +1,11 @@ +import { createSignal } from "solid-js"; +import "./Counter.css"; + +export default function Counter() { + const [count, setCount] = createSignal(0); + return ( + + ); +} diff --git a/examples/aws-solid-container-ws/src/entry-client.tsx b/examples/aws-solid-container-ws/src/entry-client.tsx new file mode 100644 index 000000000..0ca4e3c30 --- /dev/null +++ b/examples/aws-solid-container-ws/src/entry-client.tsx @@ -0,0 +1,4 @@ +// @refresh reload +import { mount, StartClient } from "@solidjs/start/client"; + +mount(() => , document.getElementById("app")!); diff --git a/examples/aws-solid-container-ws/src/entry-server.tsx b/examples/aws-solid-container-ws/src/entry-server.tsx new file mode 100644 index 000000000..401eff83f --- /dev/null +++ b/examples/aws-solid-container-ws/src/entry-server.tsx @@ -0,0 +1,21 @@ +// @refresh reload +import { createHandler, StartServer } from "@solidjs/start/server"; + +export default createHandler(() => ( + ( + + + + + + {assets} + + +
{children}
+ {scripts} + + + )} + /> +)); diff --git a/examples/aws-solid-container-ws/src/global.d.ts b/examples/aws-solid-container-ws/src/global.d.ts new file mode 100644 index 000000000..dc6f10c22 --- /dev/null +++ b/examples/aws-solid-container-ws/src/global.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/aws-solid-container-ws/src/routes/[...404].tsx b/examples/aws-solid-container-ws/src/routes/[...404].tsx new file mode 100644 index 000000000..4ea71ec7f --- /dev/null +++ b/examples/aws-solid-container-ws/src/routes/[...404].tsx @@ -0,0 +1,19 @@ +import { Title } from "@solidjs/meta"; +import { HttpStatusCode } from "@solidjs/start"; + +export default function NotFound() { + return ( +
+ Not Found + +

Page Not Found

+

+ Visit{" "} + + start.solidjs.com + {" "} + to learn how to build SolidStart apps. +

+
+ ); +} diff --git a/examples/aws-solid-container-ws/src/routes/about.tsx b/examples/aws-solid-container-ws/src/routes/about.tsx new file mode 100644 index 000000000..8371d911c --- /dev/null +++ b/examples/aws-solid-container-ws/src/routes/about.tsx @@ -0,0 +1,10 @@ +import { Title } from "@solidjs/meta"; + +export default function Home() { + return ( +
+ About +

About

+
+ ); +} diff --git a/examples/aws-solid-container-ws/src/routes/index.tsx b/examples/aws-solid-container-ws/src/routes/index.tsx new file mode 100644 index 000000000..5d557d819 --- /dev/null +++ b/examples/aws-solid-container-ws/src/routes/index.tsx @@ -0,0 +1,19 @@ +import { Title } from "@solidjs/meta"; +import Counter from "~/components/Counter"; + +export default function Home() { + return ( +
+ Hello World +

Hello world!

+ +

+ Visit{" "} + + start.solidjs.com + {" "} + to learn how to build SolidStart apps. +

+
+ ); +} diff --git a/examples/aws-solid-container-ws/src/ws.ts b/examples/aws-solid-container-ws/src/ws.ts new file mode 100644 index 000000000..7ee8d34f4 --- /dev/null +++ b/examples/aws-solid-container-ws/src/ws.ts @@ -0,0 +1,23 @@ +import { eventHandler } from "vinxi/http"; +export default eventHandler({ + handler() { }, + websocket: { + async open(peer) { + console.log("open", peer.id, peer.url); + }, + async message(peer, msg) { + const message = msg.text(); + console.log("msg", peer.id, peer.url, message); + + setTimeout(() => { + peer.send("Message received from: #" + peer.id); + }, 3000); + }, + async close(peer, _details) { + console.log("close", peer.id, peer.url); + }, + async error(peer, error) { + console.log("error", peer.id, peer.url, error); + }, + }, +}); diff --git a/examples/aws-solid-container-ws/sst-env.d.ts b/examples/aws-solid-container-ws/sst-env.d.ts new file mode 100644 index 000000000..8beddcd4c --- /dev/null +++ b/examples/aws-solid-container-ws/sst-env.d.ts @@ -0,0 +1,18 @@ +/* This file is auto-generated by SST. Do not edit. */ +/* tslint:disable */ +/* eslint-disable */ +import "sst" +export {} +declare module "sst" { + export interface Resource { + "MyService": { + "service": string + "type": "sst.aws.Service" + "url": string + } + "MyVpc": { + "bastion": string + "type": "sst.aws.Vpc" + } + } +} diff --git a/examples/aws-solid-container-ws/sst.config.ts b/examples/aws-solid-container-ws/sst.config.ts new file mode 100644 index 000000000..d421bb7dd --- /dev/null +++ b/examples/aws-solid-container-ws/sst.config.ts @@ -0,0 +1,50 @@ +/// + +/** + * ## AWS SolidStart WebSocket endpoint + * + * Deploys a SolidStart app with a [WebSocket endpoint](https://docs.solidjs.com/solid-start/advanced/websocket) + * in a container to AWS. + * + * Uses the experimental WebSocket support in Nitro. + * + * ```ts title="app.config.ts" {4} + * export default defineConfig({ + * server: { + * experimental: { + * websocket: true, + * }, + * }, + * }).addRouter({ + * name: "ws", + * type: "http", + * handler: "./src/ws.ts", + * target: "server", + * base: "/ws", + * }); + * ``` + * + * Once deployed you can test the `/ws` endpoint and it'll send a message back after a 3s delay. + */ +export default $config({ + app(input) { + return { + name: "aws-solid-container-ws", + removal: input?.stage === "production" ? "retain" : "remove", + home: "aws", + }; + }, + async run() { + const vpc = new sst.aws.Vpc("MyVpc", { bastion: true }); + const cluster = new sst.aws.Cluster("MyCluster", { vpc }); + + cluster.addService("MyService", { + public: { + ports: [{ listen: "80/http", forward: "3000/http" }], + }, + dev: { + command: "npm run dev", + }, + }); + }, +}); diff --git a/examples/aws-solid-container-ws/tsconfig.json b/examples/aws-solid-container-ws/tsconfig.json new file mode 100644 index 000000000..7d5871a07 --- /dev/null +++ b/examples/aws-solid-container-ws/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "jsx": "preserve", + "jsxImportSource": "solid-js", + "allowJs": true, + "strict": true, + "noEmit": true, + "types": ["vinxi/types/client"], + "isolatedModules": true, + "paths": { + "~/*": ["./src/*"] + } + } +} diff --git a/www/src/content/docs/docs/examples.mdx b/www/src/content/docs/docs/examples.mdx index 602f26157..439734bad 100644 --- a/www/src/content/docs/docs/examples.mdx +++ b/www/src/content/docs/docs/examples.mdx @@ -127,16 +127,15 @@ Create an S3 bucket and transform its bucket policy. const bucket = new sst.aws.Bucket("MyBucket", { transform: { policy: (args) => { - // use $jsonParse and $jsonStringify helper functions to manipulate JSON strings + // use sst.aws.iamEdit helper function to manipulate IAM policy // containing Output values from components - args.policy = $jsonParse(args.policy).apply((policy) => { + args.policy = sst.aws.iamEdit(args.policy, (policy) => { policy.Statement.push({ Effect: "Allow", Principal: { Service: "ses.amazonaws.com" }, Action: "s3:PutObject", Resource: $interpolate`arn:aws:s3:::${args.bucket}/*`, }); - return $jsonStringify(policy); }); }, }, @@ -403,6 +402,75 @@ return { View the [full example](https://github.com/sst/ion/tree/dev/examples/aws-dynamo). +--- +## EC2 with Pulumi + +Use raw Pulumi resources to create an EC2 instance. +```ts title="sst.config.ts" + + + +# EC2 with Pulumi + +se raw Pulumi resources to create an EC2 instance. + +rt default $config({ +(input) { +turn { +ame: "aws-ec2-pulumi", +ome: "aws", +emoval: input?.stage === "production" ? "retain" : "remove", + + +nc run() { + Notice you don't need to import pulumi, it is already part of sst. +nst securityGroup = new aws.ec2.SecurityGroup("web-secgrp", { +ngress: [ +{ + protocol: "tcp", + fromPort: 80, + toPort: 80, + cidrBlocks: ["0.0.0.0/0"], +}, +, +; + + Find the latest Ubuntu AMI +nst ami = aws.ec2.getAmi({ +ilters: [ +{ + name: "name", + values: ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"], +}, +, +ostRecent: true, +wners: ["099720109477"], // Canonical +; + + User data to set up a simple web server +nst userData = `#!/bin/bash +ho "Hello, World!" > index.html +hup python3 -m http.server 80 &`; + + Create an EC2 instance +nst server = new aws.ec2.Instance("web-server", { +nstanceType: "t2.micro", +mi: ami.then((ami) => ami.id), +serData: userData, +pcSecurityGroupIds: [securityGroup.id], +ssociatePublicIpAddress: true, +; + +turn { +pp: server.publicIp, + + + +``` + +View the [full example](https://github.com/sst/ion/tree/dev/examples/aws-ec2-pulumi). + + --- ## AWS Express file upload @@ -813,7 +881,7 @@ This needs _sudo_ to create the network interface on your machine. You'll only n this once. Now you can run `sst dev`, your function can access resources in the VPC. For example, here -we're connecting to a Redis cluster. +we are connecting to a Redis cluster. ```ts title="index.ts" const redis = new Cluster( @@ -1380,6 +1448,48 @@ return { View the [full example](https://github.com/sst/ion/tree/dev/examples/aws-sharp). +--- +## AWS SolidStart WebSocket endpoint + +Deploys a SolidStart app with a [WebSocket endpoint](https://docs.solidjs.com/solid-start/advanced/websocket) +in a container to AWS. + +Uses the experimental WebSocket support in Nitro. + +```ts title="app.config.ts" {4} +export default defineConfig({ + server: { + experimental: { + websocket: true, + }, + }, +}).addRouter({ + name: "ws", + type: "http", + handler: "./src/ws.ts", + target: "server", + base: "/ws", +}); +``` + +Once deployed you can test the `/ws` endpoint and it'll send a message back after a 3s delay. +```ts title="sst.config.ts" +const vpc = new sst.aws.Vpc("MyVpc", { bastion: true }); +const cluster = new sst.aws.Cluster("MyCluster", { vpc }); + +cluster.addService("MyService", { + public: { + ports: [{ listen: "80/http", forward: "3000/http" }], + }, + dev: { + command: "npm run dev", + }, +}); +``` + +View the [full example](https://github.com/sst/ion/tree/dev/examples/aws-solid-container-ws). + + --- ## AWS static site basic auth diff --git a/www/src/content/docs/docs/start/aws/solid.mdx b/www/src/content/docs/docs/start/aws/solid.mdx index 7e6b562ed..2d6710ab5 100644 --- a/www/src/content/docs/docs/start/aws/solid.mdx +++ b/www/src/content/docs/docs/start/aws/solid.mdx @@ -12,6 +12,14 @@ We'll use both to build a couple of simple apps below. --- +#### Examples + +We also have a few other SolidStart examples that you can refer to. + +- [Adding a WebSocket endpoint to SolidStart](/docs/examples/#aws-solidstart-websocket-endpoint) + +--- + ## Serverless We are going to create a SolidStart app, add an S3 Bucket for file uploads, and deploy it using the `SolidStart` component. @@ -250,7 +258,7 @@ async run() { cluster.addService("MyService", { public: { - ports: [{ listen: "80/http", forward: "4321/http" }], + ports: [{ listen: "80/http", forward: "3000/http" }], }, dev: { command: "npm run dev",