diff --git a/.github/workflows/sst.yml b/.github/workflows/sst.yml new file mode 100644 index 00000000..b8b90161 --- /dev/null +++ b/.github/workflows/sst.yml @@ -0,0 +1,60 @@ +name: sst + +on: + workflow_dispatch: + +concurrency: + group: ${{ github.ref }} + + +jobs: + deploy: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - uses: actions/cache@v2 + with: + path: | + .sst + key: ${{ runner.os }}-sst + + - uses: oven-sh/setup-bun@v1 + with: + bun-version: latest + + - uses: actions/setup-node@v1 + with: + node-version: "20" + + - run: "curl -fsSL https://ion.sst.dev/install | bash" + + - if: github.ref == 'refs/heads/dev' + name: Configure Dev AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + role-to-assume: arn:aws:iam::058264103289:role/terminal-shop-dev-github + aws-region: us-east-2 + + - if: github.ref == 'refs/heads/production' + name: Configure Production AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + role-to-assume: arn:aws:iam::211125775473:role/terminal-shop-production-github + aws-region: us-east-2 + + - name: deps + run: bun install + + - name: Deploy + env: + CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} + run: | + sst install + sst deploy --stage=${GITHUB_REF_NAME} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 96fab4fe..28dc834e 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,9 @@ yarn-error.log* # Misc .DS_Store *.pem + +# sst +.sst + +#Bun merging errors, EVERY time :( +bun.lockb \ No newline at end of file diff --git a/apps/docs/package.json b/apps/docs/package.json index ea1bb6a7..2b08ccc9 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -31,9 +31,9 @@ "devDependencies": { "@builder.io/qwik": "^1.8.0", "@builder.io/qwik-city": "^1.8.0", - "@nestri/eslint-config": "workspace:*", - "@nestri/typescript-config": "workspace:*", - "@nestri/ui": "workspace:*", + "@nestri/eslint-config": "*", + "@nestri/typescript-config": "*", + "@nestri/ui": "*", "@types/eslint": "8.56.10", "@types/node": "20.14.11", "@typescript-eslint/eslint-plugin": "7.16.1", diff --git a/apps/nexus/package.json b/apps/nexus/package.json index 9bc4a03d..1bd375eb 100644 --- a/apps/nexus/package.json +++ b/apps/nexus/package.json @@ -16,7 +16,7 @@ "@jsquash/avif": "^1.3.0", "@jsquash/jpeg": "^1.4.0", "@jsquash/resize": "^2.0.0", - "@nestri/cache": "workspace:*", + "@nestri/cache": "*", "tinycolor2": "^1.6.0", "wrangler": "^3.72.2" } diff --git a/apps/www/.eslintrc.js b/apps/www/.eslintrc.cjs similarity index 100% rename from apps/www/.eslintrc.js rename to apps/www/.eslintrc.cjs diff --git a/apps/www/package.json b/apps/www/package.json index 9e034cf4..b39d3648 100644 --- a/apps/www/package.json +++ b/apps/www/package.json @@ -32,9 +32,9 @@ "@builder.io/qwik": "^1.8.0", "@builder.io/qwik-city": "^1.8.0", "@builder.io/qwik-react": "0.5.0", - "@nestri/eslint-config": "workspace:*", - "@nestri/typescript-config": "workspace:*", - "@nestri/ui": "workspace:*", + "@nestri/eslint-config": "*", + "@nestri/typescript-config": "*", + "@nestri/ui": "*", "@types/eslint": "8.56.10", "@types/node": "^22.5.1", "@types/react": "^18.2.28", diff --git a/apps/www/postcss.config.cjs b/apps/www/postcss.config.cjs index dd1d0abe..c1464c07 100644 --- a/apps/www/postcss.config.cjs +++ b/apps/www/postcss.config.cjs @@ -1 +1,7 @@ -module.exports = require("@nestri/ui/postcss.config"); \ No newline at end of file +// module.exports = require("@nestri/ui/postcss.config"); +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; \ No newline at end of file diff --git a/apps/www/src/routes/404.tsx b/apps/www/src/routes/404.tsx index d7e0ec4d..18a4c2e9 100644 --- a/apps/www/src/routes/404.tsx +++ b/apps/www/src/routes/404.tsx @@ -1,7 +1,5 @@ import { component$ } from "@builder.io/qwik"; import { Link } from "@builder.io/qwik-city"; -import { buttonVariants, cn } from "@nestri/ui/design"; - export default component$(() => { return ( diff --git a/apps/www/src/routes/changelog/index.tsx b/apps/www/src/routes/changelog/index.tsx index c0bf2634..1170c38e 100644 --- a/apps/www/src/routes/changelog/index.tsx +++ b/apps/www/src/routes/changelog/index.tsx @@ -1,3 +1,4 @@ +/* eslint-disable qwik/jsx-img */ import { component$ } from "@builder.io/qwik"; import { Link } from "@builder.io/qwik-city"; import { NavBar, Footer } from "@nestri/ui"; diff --git a/apps/www/src/routes/home/index.tsx b/apps/www/src/routes/home/index.tsx index ce9d5e6e..02d4478a 100644 --- a/apps/www/src/routes/home/index.tsx +++ b/apps/www/src/routes/home/index.tsx @@ -1,5 +1,5 @@ import { component$ } from "@builder.io/qwik"; -import { GameCard, HomeNavBar, Card } from "@nestri/ui"; +import { HomeNavBar, Card } from "@nestri/ui"; function getGreeting(): string { const hour = new Date().getHours(); diff --git a/apps/www/sst-env.d.ts b/apps/www/sst-env.d.ts new file mode 100644 index 00000000..af3a3c21 --- /dev/null +++ b/apps/www/sst-env.d.ts @@ -0,0 +1,4 @@ +/* tslint:disable */ +/* eslint-disable */ +/// +export {} diff --git a/apps/www/tailwind.config.js b/apps/www/tailwind.config.js index e9547628..81dc036f 100644 --- a/apps/www/tailwind.config.js +++ b/apps/www/tailwind.config.js @@ -1,8 +1,8 @@ // import colors from "tailwindcss/colors"; import baseConfig from "@nestri/ui/tailwind.config"; /** @type {import('tailwindcss').Config} */ -module.exports = { +module.exports = { content: [ "./{src,components,app}/**/*.{ts,tsx,html}", "../../packages/ui/src/**/*.{ts,tsx}", diff --git a/apps/www/tsconfig.json b/apps/www/tsconfig.json index a6e96939..cbbdb97d 100644 --- a/apps/www/tsconfig.json +++ b/apps/www/tsconfig.json @@ -11,6 +11,7 @@ "forceConsistentCasingInFileNames": true, "resolveJsonModule": true, "moduleResolution": "Bundler", + "allowImportingTsExtensions": true, "esModuleInterop": true, "skipLibCheck": true, "incremental": true, @@ -24,7 +25,7 @@ } }, "files": [ - ".eslintrc.js" + ".eslintrc.cjs" ], "include": [ "src", diff --git a/bun.lockb b/bun.lockb index bf213580..9a524b4d 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/infra/domain.ts b/infra/domain.ts new file mode 100644 index 00000000..2fd8e807 --- /dev/null +++ b/infra/domain.ts @@ -0,0 +1,9 @@ +export const domain = + { + production: "fst.so", + dev: "dev.fst.so", + }[$app.stage] || $app.stage + ".dev.fst.so"; + +export const zone = cloudflare.getZoneOutput({ + name: "fst.so", +}); \ No newline at end of file diff --git a/infra/github.ts b/infra/github.ts new file mode 100644 index 00000000..cf1e0d5f --- /dev/null +++ b/infra/github.ts @@ -0,0 +1,38 @@ +import { isPermanentStage } from "./stage"; + +if (isPermanentStage) { + const github = new aws.iam.OpenIdConnectProvider("GithubProvider", { + url: "https://token.actions.githubusercontent.com", + clientIdLists: ["sts.amazonaws.com"], + thumbprintLists: [ + "6938fd4d98bab03faadb97b34396831e3780aea1", + "1c58a3a8518e8759bf075b76b750d4f2df264fcd", + ], + }); + + const githubRole = new aws.iam.Role("GithubRole", { + name: [$app.name, $app.stage, "github"].join("-"), + assumeRolePolicy: { + Version: "2012-10-17", + Statement: [ + { + Effect: "Allow", + Principal: { + Federated: github.arn, + }, + Action: "sts:AssumeRoleWithWebIdentity", + Condition: { + StringLike: github.url.apply((url) => ({ + [`${url}:sub`]: "repo:nestriness/nestri:*", + })), + }, + }, + ], + }, + }); + + new aws.iam.RolePolicyAttachment("GithubRolePolicy", { + policyArn: "arn:aws:iam::aws:policy/AdministratorAccess", + role: githubRole.name, + }); +} \ No newline at end of file diff --git a/infra/secrets.ts b/infra/secrets.ts new file mode 100644 index 00000000..28377c8d --- /dev/null +++ b/infra/secrets.ts @@ -0,0 +1,5 @@ +export const secret = { + CloudflareAccountIdSecret: new sst.Secret("CloudflareAccountId"), +}; + +export const allSecrets = Object.values(secret); \ No newline at end of file diff --git a/infra/stage.ts b/infra/stage.ts new file mode 100644 index 00000000..3f4f5335 --- /dev/null +++ b/infra/stage.ts @@ -0,0 +1,2 @@ +export const isPermanentStage = + $app.stage === "production" || $app.stage === "dev"; \ No newline at end of file diff --git a/infra/www.ts b/infra/www.ts new file mode 100644 index 00000000..705a679a --- /dev/null +++ b/infra/www.ts @@ -0,0 +1,36 @@ +//Deploys the website to cloudflare pages under the domain nestri.io (redirects all requests to www.nestri.io to avoid duplicate content) +// const cloudflareAccountId = new sst.Secret("CloudflareAccountId"); + +export const www = new cloudflare.PagesProject("www", { + name: "nestri", + accountId: "8405b2acb6746935b975bc2cfcb5c288", + productionBranch: "main", + buildConfig: { + rootDir: "apps/www", + // buildCommand: "bun run build", + destinationDir: "dist" + }, + deploymentConfigs: { + production: { + compatibilityFlags: ["nodejs_compat"] + }, + preview: { + compatibilityFlags: ["nodejs_compat"] + } + }, + source: { + type: "github", + config: { + owner: "nestriness", + deploymentsEnabled: true, + productionBranch: "main", + repoName: "nestri", + productionDeploymentEnabled: true, + prCommentsEnabled: true, + } + } +}); + +export const outputs = { + www: www.subdomain, +}; \ No newline at end of file diff --git a/package.json b/package.json index 08f45986..0a112bbd 100644 --- a/package.json +++ b/package.json @@ -4,10 +4,12 @@ "scripts": { "build": "turbo build", "dev": "turbo dev", - "lint": "turbo lint", - "format": "prettier --write \"**/*.{ts,tsx,md}\"" + "format": "prettier --write \"**/*.{ts,tsx,md}\"", + "lint": "turbo lint" }, "devDependencies": { + "@cloudflare/workers-types": "4.20240821.1", + "@types/aws-lambda": "8.10.145", "prettier": "^3.2.5", "sst": "^3.0.91", "turbo": "^2.0.12", @@ -25,5 +27,8 @@ "core-js-pure", "esbuild", "workerd" - ] + ], + "dependencies": { + "sst": "3.0.94" + } } diff --git a/packages/mdx/package.json b/packages/mdx/package.json index d970a671..67e3a339 100644 --- a/packages/mdx/package.json +++ b/packages/mdx/package.json @@ -14,9 +14,9 @@ "@builder.io/qwik": "^1.8.0", "@builder.io/qwik-city": "^1.8.0", "@builder.io/qwik-react": "0.5.0", - "@nestri/eslint-config": "workspace:*", - "@nestri/typescript-config": "workspace:*", - "@nestri/core": "workspace:*", + "@nestri/eslint-config": "*", + "@nestri/typescript-config": "*", + "@nestri/core": "*", "@types/eslint": "^8.56.5", "@types/node": "^20.11.24", "autoprefixer": "^10.4.20", diff --git a/packages/ui/package.json b/packages/ui/package.json index cf7d3946..54c405fb 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -4,7 +4,7 @@ "private": true, "sideEffects": false, "files": [ - "tailwind.config.ts", + "tailwind.config.js", "postcss.config.js", "globals.css" ], @@ -26,9 +26,9 @@ "@builder.io/qwik-react": "0.5.0", "@fontsource/bricolage-grotesque": "^5.0.7", "@fontsource/geist-sans": "^5.0.3", - "@nestri/eslint-config": "workspace:*", - "@nestri/typescript-config": "workspace:*", - "@nestri/core": "workspace:*", + "@nestri/eslint-config": "*", + "@nestri/typescript-config": "*", + "@nestri/core": "*", "@turbo/gen": "^1.12.4", "@types/eslint": "^8.56.5", "@types/node": "^20.11.24", diff --git a/packages/ui/post.config.js b/packages/ui/post.config.js index 4701c1c1..ba7a7e40 100644 --- a/packages/ui/post.config.js +++ b/packages/ui/post.config.js @@ -1,4 +1,4 @@ -export default { +module.exports = { plugins: { tailwindcss: {}, autoprefixer: {}, diff --git a/packages/ui/src/card.tsx b/packages/ui/src/card.tsx index 3addf169..4973f2e2 100644 --- a/packages/ui/src/card.tsx +++ b/packages/ui/src/card.tsx @@ -10,7 +10,6 @@ type Props = { export const Card = component$(({ game }: Props) => { const imageUrl = `http://localhost:8787/image/cover/${game.id}.avif` const backgroundColor = useSignal(undefined); - const ringColor = useSignal(undefined); const imgRef = useSignal(); const extractColor = $((img: HTMLImageElement) => { diff --git a/packages/ui/src/github-banner.tsx b/packages/ui/src/github-banner.tsx index 69b02bd7..302cad9b 100644 --- a/packages/ui/src/github-banner.tsx +++ b/packages/ui/src/github-banner.tsx @@ -1,5 +1,5 @@ import { component$ } from "@builder.io/qwik"; -import { MotionComponent, transition } from "@/react/motion"; +import { MotionComponent, transition } from "@nestri/ui/react"; import { Link } from "@builder.io/qwik-city"; export const GithubBanner = component$(() => { diff --git a/packages/ui/src/home-nav-bar.tsx b/packages/ui/src/home-nav-bar.tsx index d89f885b..2e2d59da 100644 --- a/packages/ui/src/home-nav-bar.tsx +++ b/packages/ui/src/home-nav-bar.tsx @@ -1,5 +1,5 @@ import { $, component$, useOnDocument, useSignal } from "@builder.io/qwik"; -import { cn } from "@/design"; +import { cn } from "./design"; export const HomeNavBar = component$(() => { const hasScrolled = useSignal(false); diff --git a/packages/ui/src/image/basic-image-loader.tsx b/packages/ui/src/image/basic-image-loader.tsx index 6972d9c6..fc0c0190 100644 --- a/packages/ui/src/image/basic-image-loader.tsx +++ b/packages/ui/src/image/basic-image-loader.tsx @@ -1,6 +1,6 @@ /* eslint-disable qwik/no-use-visible-task */ -import { cn } from '@/design'; -import { component$, useSignal, useTask$, useStyles$, useVisibleTask$, $ } from '@builder.io/qwik'; +import { cn } from '@nestri/ui/design'; +import { component$, useSignal, useTask$, useStyles$, useVisibleTask$ } from '@builder.io/qwik'; interface ImageLoaderProps { src: string; diff --git a/packages/ui/src/image/image-loader.tsx b/packages/ui/src/image/image-loader.tsx index fa26db63..472c011b 100644 --- a/packages/ui/src/image/image-loader.tsx +++ b/packages/ui/src/image/image-loader.tsx @@ -1,5 +1,5 @@ /* eslint-disable qwik/no-use-visible-task */ -import { cn } from '@/design'; +import { cn } from '@nestri/ui/design'; import { component$, useSignal, useTask$, useStyles$, useVisibleTask$, $ } from '@builder.io/qwik'; interface ImageLoaderProps { diff --git a/packages/ui/src/input.tsx b/packages/ui/src/input.tsx index 63cc31a1..36dcf144 100644 --- a/packages/ui/src/input.tsx +++ b/packages/ui/src/input.tsx @@ -2,7 +2,7 @@ import { form, cn, type InputProps as InputVariants, -} from "@/design" +} from "./design" import { type QwikIntrinsicElements, component$ } from '@builder.io/qwik'; export interface InputComponentProps extends Omit, InputVariants { diff --git a/packages/ui/src/nav-bar.tsx b/packages/ui/src/nav-bar.tsx index 14092aef..0273780c 100644 --- a/packages/ui/src/nav-bar.tsx +++ b/packages/ui/src/nav-bar.tsx @@ -1,6 +1,6 @@ import { $, component$, useOnDocument, useSignal } from "@builder.io/qwik"; import { Link, useLocation } from "@builder.io/qwik-city"; -import { buttonVariants, cn } from "@/design"; +import { buttonVariants, cn } from "./design"; const navLinks = [ { diff --git a/packages/ui/src/react/cursor.tsx b/packages/ui/src/react/cursor.tsx index be7b27a2..b73ad35c 100644 --- a/packages/ui/src/react/cursor.tsx +++ b/packages/ui/src/react/cursor.tsx @@ -1,7 +1,7 @@ /** @jsxImportSource react */ import React from 'react' import { motion } from 'framer-motion' -import { cn } from '@/design' +import { cn } from "@nestri/ui/design" import { qwikify$ } from '@builder.io/qwik-react'; export const CursorSVG = ({ flip }: { flip?: boolean }) => ( diff --git a/packages/ui/src/react/display.tsx b/packages/ui/src/react/display.tsx index 85369d8f..a0fd4d0d 100644 --- a/packages/ui/src/react/display.tsx +++ b/packages/ui/src/react/display.tsx @@ -6,9 +6,9 @@ import { type DisplayProps as DisplayVariants, type TextAlignProp, type TextWeightProp -} from "@/design" +} from "@nestri/ui/design" import * as ReactBalancer from "react-wrap-balancer" -import { cn } from "@/design" +import { cn } from "@nestri/ui/design" import { qwikify$ } from "@builder.io/qwik-react" type DisplaySize = DisplayVariants["size"] diff --git a/packages/ui/src/react/hero-section.tsx b/packages/ui/src/react/hero-section.tsx index f80abd0a..207696d4 100644 --- a/packages/ui/src/react/hero-section.tsx +++ b/packages/ui/src/react/hero-section.tsx @@ -2,7 +2,7 @@ /** @jsxImportSource react */ import { qwikify$ } from "@builder.io/qwik-react"; import { motion } from "framer-motion" -import { ReactDisplay } from "@/react/display" +import { ReactDisplay } from "./display" import * as React from "react" // type Props = { // children?: React.ReactElement[] diff --git a/packages/ui/src/react/marquee.tsx b/packages/ui/src/react/marquee.tsx index 29bc3586..d3870dc9 100644 --- a/packages/ui/src/react/marquee.tsx +++ b/packages/ui/src/react/marquee.tsx @@ -1,4 +1,4 @@ -import { cn } from "@/design"; +import { cn } from "@nestri/ui/design"; import { component$, useStore, type Component } from "@builder.io/qwik"; diff --git a/packages/ui/src/react/my-cursor.tsx b/packages/ui/src/react/my-cursor.tsx index 7c89bff5..bbb43ebe 100644 --- a/packages/ui/src/react/my-cursor.tsx +++ b/packages/ui/src/react/my-cursor.tsx @@ -1,7 +1,6 @@ /** @jsxImportSource react */ import React from 'react' -import { motion } from 'framer-motion' -import { cn } from '@/design' +import { cn } from "@nestri/ui/design" import { qwikify$ } from '@builder.io/qwik-react'; export const CursorSVG = ({ flip }: { flip?: boolean }) => ( diff --git a/packages/ui/src/react/save.tsx b/packages/ui/src/react/save.tsx index ea17fed2..eb9d848d 100644 --- a/packages/ui/src/react/save.tsx +++ b/packages/ui/src/react/save.tsx @@ -1,5 +1,5 @@ /** @jsxImportSource react */ -import { cn } from "@/design"; +import { cn } from "@nestri/ui/design"; import { qwikify$ } from "@builder.io/qwik-react"; import React, { useEffect, useRef, useState } from "react"; import { diff --git a/packages/ui/src/react/text.tsx b/packages/ui/src/react/text.tsx index e8bc3498..aece6f7e 100644 --- a/packages/ui/src/react/text.tsx +++ b/packages/ui/src/react/text.tsx @@ -7,7 +7,7 @@ import { type TextAlignProp, type TextWeightProp, cn -} from "@/design" +} from "@nestri/ui/design" // import * as ReactBalancer from "react-wrap-balancer" import { qwikify$ } from "@builder.io/qwik-react" diff --git a/packages/ui/src/react/title-section.tsx b/packages/ui/src/react/title-section.tsx index 554ee989..e03f85fd 100644 --- a/packages/ui/src/react/title-section.tsx +++ b/packages/ui/src/react/title-section.tsx @@ -2,7 +2,7 @@ /** @jsxImportSource react */ import { qwikify$ } from "@builder.io/qwik-react"; import { motion } from "framer-motion" -import { ReactDisplay } from "@/react/display" +import { ReactDisplay } from "./display" // type Props = { // children?: React.ReactElement[] // } diff --git a/packages/ui/src/react/title.tsx b/packages/ui/src/react/title.tsx index b1ad8289..b7e766ab 100644 --- a/packages/ui/src/react/title.tsx +++ b/packages/ui/src/react/title.tsx @@ -7,7 +7,7 @@ import { type TextAlignProp, type TextWeightProp, cn -} from "@/design" +} from "@nestri/ui/design" import { qwikify$ } from "@builder.io/qwik-react"; diff --git a/packages/ui/tsconfig.json b/packages/ui/tsconfig.json index d377e2e7..e8055b2b 100644 --- a/packages/ui/tsconfig.json +++ b/packages/ui/tsconfig.json @@ -3,10 +3,7 @@ "compilerOptions": { "outDir": "tmp", "rootDir": ".", - "allowImportingTsExtensions": true, - "paths": { - "@/*": ["./src/*"] - } + "allowImportingTsExtensions": true }, "files": [".eslintrc.js"], "include": ["src", "./*.d.ts"] diff --git a/packages/ui/tsconfig.lint.json b/packages/ui/tsconfig.lint.json index 5e2b9c84..f150d092 100644 --- a/packages/ui/tsconfig.lint.json +++ b/packages/ui/tsconfig.lint.json @@ -2,6 +2,7 @@ "extends": "@nestri/typescript-config/base.json", "compilerOptions": { "outDir": "dist", + "allowImportingTsExtensions": true }, "include": ["src", "./*.config.js","./.eslintrc.js"], "exclude": ["node_modules", "dist"] diff --git a/sst-env.d.ts b/sst-env.d.ts new file mode 100644 index 00000000..f110f330 --- /dev/null +++ b/sst-env.d.ts @@ -0,0 +1,8 @@ +/* tslint:disable */ +/* eslint-disable */ +import "sst" +declare module "sst" { + export interface Resource { + } +} +export {} diff --git a/sst.config.ts b/sst.config.ts new file mode 100644 index 00000000..8f3f882a --- /dev/null +++ b/sst.config.ts @@ -0,0 +1,20 @@ +/// +import { readdirSync } from "fs"; +export default $config({ + app(input) { + return { + name: "nestri", + removal: input?.stage === "production" ? "retain" : "remove", + home: "aws", + providers: { cloudflare: "5.37.1" }, + }; + }, + async run() { + const outputs = {}; + for (const value of readdirSync("./infra/")) { + const result = await import("./infra/" + value); + if (result.outputs) Object.assign(outputs, result.outputs); + } + return outputs; + }, +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1 @@ +{}