migrate to monorepo

api-as-package
pegasust 2022-11-15 17:03:19 +00:00
parent db48c7c962
commit 3f267afb84
80 changed files with 5859 additions and 2 deletions

View File

@ -0,0 +1 @@
/nix/store/0yw3h1p66cx0yr3yg4z90v1n0pqj1jnf-source

View File

@ -0,0 +1 @@
/nix/store/477zl9l6k5vjdzfvj4gp577lgh9cml80-source

View File

@ -0,0 +1 @@
/nix/store/9cj1830pvd88lrwmmxw65achd3lw2q9n-source

View File

@ -0,0 +1 @@
/nix/store/gpn8846qjzkyn19m61x33zshhhnb5zmz-source

View File

@ -0,0 +1 @@
/nix/store/q3dc8i1zdl3870mp56ff0rkz1hzc55ry-source

View File

@ -0,0 +1 @@
/nix/store/sk4ga2wy0b02k7pnzakwq4r3jdknda4g-source

View File

@ -0,0 +1 @@
/nix/store/y0vjv4jpzrwdw0x5m4p9c2p4w7mrcz3w-source

View File

@ -0,0 +1 @@
/nix/store/pvhv7qw9cbdldpid1kdw43l83kqg2ds5-nix-shell-env

File diff suppressed because it is too large Load Diff

4
.envrc Normal file
View File

@ -0,0 +1,4 @@
if command -v nix-shell &> /dev/null
then
use flake
fi

10
.eslintrc.js Normal file
View File

@ -0,0 +1,10 @@
module.exports = {
root: true,
// This tells ESLint to load the config from the package `eslint-config-custom`
extends: ["custom"],
settings: {
next: {
rootDir: ["apps/*/"],
},
},
};

33
.gitignore vendored
View File

@ -0,0 +1,33 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
node_modules
.pnp
.pnp.js
# testing
coverage
# next.js
.next/
out/
build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local
# turbo
.turbo

79
README.md Normal file
View File

@ -0,0 +1,79 @@
# Felia
Scaffolded by `pnpm create turbo@latest`
This project manages my homelab infrastructure under a monorepo to keep things
centralized and easily sharable across different modules
# Turbo-repo details
## What's inside?
This turborepo uses [pnpm](https://pnpm.io) as a package manager. It includes the following packages/apps:
### Apps and Packages
- `docs`: a [Next.js](https://nextjs.org/) app
- `web`: another [Next.js](https://nextjs.org/) app
- `ui`: a stub React component library shared by both `web` and `docs` applications
- `eslint-config-custom`: `eslint` configurations (includes `eslint-config-next` and `eslint-config-prettier`)
- `tsconfig`: `tsconfig.json`s used throughout the monorepo
Each package/app is 100% [TypeScript](https://www.typescriptlang.org/).
### Utilities
This turborepo has some additional tools already setup for you:
- [TypeScript](https://www.typescriptlang.org/) for static type checking
- [ESLint](https://eslint.org/) for code linting
- [Prettier](https://prettier.io) for code formatting
### Build
To build all apps and packages, run the following command:
```
cd my-turborepo
pnpm run build
```
### Develop
To develop all apps and packages, run the following command:
```
cd my-turborepo
pnpm run dev
```
### Remote Caching
Turborepo can use a technique known as [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) to share cache artifacts across machines, enabling you to share build caches with your team and CI/CD pipelines.
By default, Turborepo will cache locally. To enable Remote Caching you will need an account with Vercel. If you don't have an account you can [create one](https://vercel.com/signup), then enter the following commands:
```
cd my-turborepo
pnpm dlx turbo login
```
This will authenticate the Turborepo CLI with your [Vercel account](https://vercel.com/docs/concepts/personal-accounts/overview).
Next, you can link your Turborepo to your Remote Cache by running the following command from the root of your turborepo:
```
pnpm dlx turbo link
```
## Useful Links
Learn more about the power of Turborepo:
- [Pipelines](https://turbo.build/repo/docs/core-concepts/monorepos/running-tasks)
- [Caching](https://turbo.build/repo/docs/core-concepts/caching)
- [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching)
- [Filtering](https://turbo.build/repo/docs/core-concepts/monorepos/filtering)
- [Configuration Options](https://turbo.build/repo/docs/reference/configuration)
- [CLI Usage](https://turbo.build/repo/docs/reference/command-line-reference)

View File

@ -1 +0,0 @@
/home/ubuntu_admin/local_repos/about-me/

View File

@ -0,0 +1,10 @@
# Since .env is gitignored, you can use .env-example to build a new `.env` file when you clone the repo.
# Keep this file up-to-date when you add new variables to `.env`.
# This file will be committed to version control, so make sure not to have any secrets in it.
# If you are cloning this repo, create a copy of this file named `.env` and populate it with your secrets.
# When adding additional env variables, the schema in /env/schema.mjs should be updated accordingly
# Prisma
DATABASE_URL=file:./db.sqlite

View File

@ -0,0 +1,11 @@
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"plugins": ["@typescript-eslint"],
"extends": ["next/core-web-vitals", "plugin:@typescript-eslint/recommended"],
"rules": {
"@typescript-eslint/consistent-type-imports": "warn"
}
}

40
apps/about-me/.gitignore vendored Normal file
View File

@ -0,0 +1,40 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# database
/prisma/db.sqlite
/prisma/db.sqlite-journal
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# local env files
.env
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo

27
apps/about-me/README.md Normal file
View File

@ -0,0 +1,27 @@
# Create T3 App
This is an app bootstrapped according to the [init.tips](https://init.tips) stack, also known as the T3-Stack.
## What's next? How do I make an app with this?
We try to keep this project as simple as possible, so you can start with the most basic configuration and then move on to more advanced configuration.
If you are not familiar with the different technologies used in this project, please refer to the respective docs. If you still are in the wind, please join our [Discord](https://t3.gg/discord) and ask for help.
- [Next-Auth.js](https://next-auth.js.org)
- [Prisma](https://prisma.io)
- [TailwindCSS](https://tailwindcss.com)
- [tRPC](https://trpc.io)
We also [roll our own docs](https://beta.create.t3.gg) with some summary information and links to the respective documentation.
Also checkout these awesome tutorials on `create-t3-app`.
- [Build a Blog With the T3 Stack - tRPC, TypeScript, Next.js, Prisma & Zod](https://www.youtube.com/watch?v=syEWlxVFUrY)
- [Build a Live Chat Application with the T3 Stack - TypeScript, Tailwind, tRPC](https://www.youtube.com/watch?v=dXRRY37MPuk)
- [Build a full stack app with create-t3-app](https://www.nexxel.dev/blog/ct3a-guestbook)
- [A first look at create-t3-app](https://dev.to/ajcwebdev/a-first-look-at-create-t3-app-1i8f)
## How do I deploy this?
Follow our deployment guides for [Vercel](https://beta.create.t3.gg/en/deployment/vercel) and [Docker](https://beta.create.t3.gg/en/deployment/docker) for more information.

5
apps/about-me/next-env.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

View File

@ -0,0 +1,17 @@
// @ts-check
/**
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation.
* This is especially useful for Docker builds.
*/
!process.env.SKIP_ENV_VALIDATION && (await import("./src/env/server.mjs"));
/** @type {import("next").NextConfig} */
const config = {
reactStrictMode: true,
swcMinify: true,
i18n: {
locales: ["en"],
defaultLocale: "en",
},
};
export default config;

View File

@ -0,0 +1,44 @@
{
"name": "about-me",
"version": "0.1.0",
"private": true,
"scripts": {
"build": "next build",
"dev": "next dev",
"postinstall": "prisma generate",
"lint": "next lint",
"start": "next start"
},
"dependencies": {
"@prisma/client": "^4.5.0",
"@tanstack/react-query": "^4.10.0",
"@trpc/client": "10.0.0-rc.4",
"@trpc/next": "10.0.0-rc.4",
"@trpc/react-query": "10.0.0-rc.4",
"@trpc/server": "10.0.0-rc.4",
"next": "13.0.2",
"react": "18.2.0",
"react-dom": "18.2.0",
"superjson": "1.9.1",
"zod": "^3.18.0"
},
"devDependencies": {
"@types/node": "^18.0.0",
"@types/react": "^18.0.14",
"@types/react-dom": "^18.0.5",
"@typescript-eslint/eslint-plugin": "^5.33.0",
"@typescript-eslint/parser": "^5.33.0",
"autoprefixer": "^10.4.7",
"eslint": "^8.26.0",
"eslint-config-next": "13.0.2",
"postcss": "^8.4.14",
"prettier": "^2.7.1",
"prettier-plugin-tailwindcss": "^0.1.13",
"prisma": "^4.5.0",
"tailwindcss": "^3.2.0",
"typescript": "^4.8.4"
},
"ct3aMetadata": {
"initVersion": "6.9.0"
}
}

View File

@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

View File

@ -0,0 +1,4 @@
/** @type {import("prettier").Config} */
module.exports = {
plugins: [require.resolve("prettier-plugin-tailwindcss")],
};

View File

@ -0,0 +1,17 @@
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
model Example {
id String @id @default(cuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

35
apps/about-me/src/env/client.mjs vendored Normal file
View File

@ -0,0 +1,35 @@
// @ts-check
import { clientEnv, clientSchema } from "./schema.mjs";
const _clientEnv = clientSchema.safeParse(clientEnv);
export const formatErrors = (
/** @type {import('zod').ZodFormattedError<Map<string,string>,string>} */
errors,
) =>
Object.entries(errors)
.map(([name, value]) => {
if (value && "_errors" in value)
return `${name}: ${value._errors.join(", ")}\n`;
})
.filter(Boolean);
if (!_clientEnv.success) {
console.error(
"❌ Invalid environment variables:\n",
...formatErrors(_clientEnv.error.format()),
);
throw new Error("Invalid environment variables");
}
for (let key of Object.keys(_clientEnv.data)) {
if (!key.startsWith("NEXT_PUBLIC_")) {
console.warn(
`❌ Invalid public environment variable name: ${key}. It must begin with 'NEXT_PUBLIC_'`,
);
throw new Error("Invalid public environment variable name");
}
}
export const env = _clientEnv.data;

30
apps/about-me/src/env/schema.mjs vendored Normal file
View File

@ -0,0 +1,30 @@
// @ts-check
import { z } from "zod";
/**
* Specify your server-side environment variables schema here.
* This way you can ensure the app isn't built with invalid env vars.
*/
export const serverSchema = z.object({
DATABASE_URL: z.string().url(),
NODE_ENV: z.enum(["development", "test", "production"]),
});
/**
* Specify your client-side environment variables schema here.
* This way you can ensure the app isn't built with invalid env vars.
* To expose them to the client, prefix them with `NEXT_PUBLIC_`.
*/
export const clientSchema = z.object({
// NEXT_PUBLIC_BAR: z.string(),
});
/**
* You can't destruct `process.env` as a regular object, so you have to do
* it manually here. This is because Next.js evaluates this at build time,
* and only used environment variables are included in the build.
* @type {{ [k in keyof z.infer<typeof clientSchema>]: z.infer<typeof clientSchema>[k] | undefined }}
*/
export const clientEnv = {
// NEXT_PUBLIC_BAR: process.env.NEXT_PUBLIC_BAR,
};

27
apps/about-me/src/env/server.mjs vendored Normal file
View File

@ -0,0 +1,27 @@
// @ts-check
/**
* This file is included in `/next.config.mjs` which ensures the app isn't built with invalid env vars.
* It has to be a `.mjs`-file to be imported there.
*/
import { serverSchema } from "./schema.mjs";
import { env as clientEnv, formatErrors } from "./client.mjs";
const _serverEnv = serverSchema.safeParse(process.env);
if (!_serverEnv.success) {
console.error(
"❌ Invalid environment variables:\n",
...formatErrors(_serverEnv.error.format()),
);
throw new Error("Invalid environment variables");
}
for (let key of Object.keys(_serverEnv.data)) {
if (key.startsWith("NEXT_PUBLIC_")) {
console.warn("❌ You are exposing a server-side env-variable:", key);
throw new Error("You are exposing a server-side env-variable");
}
}
export const env = { ..._serverEnv.data, ...clientEnv };

View File

@ -0,0 +1,11 @@
import { type AppType } from "next/app";
import { trpc } from "../utils/trpc";
import "../styles/globals.css";
const MyApp: AppType = ({ Component, pageProps }) => {
return <Component {...pageProps} />;
};
export default trpc.withTRPC(MyApp);

View File

@ -0,0 +1,10 @@
import { type NextApiRequest, type NextApiResponse } from "next";
import { prisma } from "../../server/db/client";
const examples = async (req: NextApiRequest, res: NextApiResponse) => {
const examples = await prisma.example.findMany();
res.status(200).json(examples);
};
export default examples;

View File

@ -0,0 +1,17 @@
import { createNextApiHandler } from "@trpc/server/adapters/next";
import { env } from "../../../env/server.mjs";
import { createContext } from "../../../server/trpc/context";
import { appRouter } from "../../../server/trpc/router/_app";
// export API handler
export default createNextApiHandler({
router: appRouter,
createContext,
onError:
env.NODE_ENV === "development"
? ({ path, error }) => {
console.error(`❌ tRPC failed on ${path}: ${error}`);
}
: undefined,
});

View File

@ -0,0 +1,90 @@
import { type NextPage } from "next";
import Head from "next/head";
import Link from "next/link";
import { trpc } from "../utils/trpc";
const Home: NextPage = () => {
const hello = trpc.example.hello.useQuery({ text: "from tRPC" });
return (
<>
<Head>
<title>Create T3 App</title>
<meta name="description" content="Generated by create-t3-app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className="container mx-auto flex min-h-screen flex-col items-center justify-center p-4">
<h1 className="text-5xl font-extrabold leading-normal text-gray-700 md:text-[5rem]">
Create <span className="text-purple-300">T3</span> App
</h1>
<p className="text-2xl text-gray-700">This stack uses:</p>
<div className="mt-3 grid gap-3 pt-3 text-center md:grid-cols-2 lg:w-2/3">
<TechnologyCard
name="NextJS"
description="The React framework for production"
documentation="https://nextjs.org/"
/>
<TechnologyCard
name="TypeScript"
description="Strongly typed programming language that builds on JavaScript, giving you better tooling at any scale"
documentation="https://www.typescriptlang.org/"
/>
<TechnologyCard
name="TailwindCSS"
description="Rapidly build modern websites without ever leaving your HTML"
documentation="https://tailwindcss.com/"
/>
<TechnologyCard
name="tRPC"
description="End-to-end typesafe APIs made easy"
documentation="https://trpc.io/"
/>
<TechnologyCard
name="Next-Auth"
description="Authentication for Next.js"
documentation="https://next-auth.js.org/"
/>
<TechnologyCard
name="Prisma"
description="Build data-driven JavaScript & TypeScript apps in less time"
documentation="https://www.prisma.io/docs/"
/>
</div>
<div className="flex w-full items-center justify-center pt-6 text-2xl text-blue-500">
{hello.data ? <p>{hello.data.greeting}</p> : <p>Loading..</p>}
</div>
</main>
</>
);
};
export default Home;
type TechnologyCardProps = {
name: string;
description: string;
documentation: string;
};
const TechnologyCard: React.FC<TechnologyCardProps> = ({
name,
description,
documentation,
}) => {
return (
<section className="flex flex-col justify-center rounded border-2 border-gray-500 p-6 shadow-xl duration-500 motion-safe:hover:scale-105">
<h2 className="text-lg text-gray-700">{name}</h2>
<p className="text-sm text-gray-600">{description}</p>
<Link
className="m-auto mt-3 w-fit text-sm text-violet-500 underline decoration-dotted underline-offset-2"
href={documentation}
target="_blank"
rel="noreferrer"
>
Documentation
</Link>
</section>
);
};

View File

@ -0,0 +1,19 @@
import { PrismaClient } from "@prisma/client";
import { env } from "../../env/server.mjs";
declare global {
// eslint-disable-next-line no-var
var prisma: PrismaClient | undefined;
}
export const prisma =
global.prisma ||
new PrismaClient({
log:
env.NODE_ENV === "development" ? ["query", "error", "warn"] : ["error"],
});
if (env.NODE_ENV !== "production") {
global.prisma = prisma;
}

View File

@ -0,0 +1,30 @@
import { type inferAsyncReturnType } from "@trpc/server";
import { type CreateNextContextOptions } from "@trpc/server/adapters/next";
import { prisma } from "../db/client";
/**
* Replace this with an object if you want to pass things to createContextInner
*/
type CreateContextOptions = Record<string, never>;
/** Use this helper for:
* - testing, so we dont have to mock Next.js' req/res
* - trpc's `createSSGHelpers` where we don't have req/res
* @see https://beta.create.t3.gg/en/usage/trpc#-servertrpccontextts
**/
export const createContextInner = async (opts: CreateContextOptions) => {
return {
prisma,
};
};
/**
* This is the actual context you'll use in your router
* @link https://trpc.io/docs/context
**/
export const createContext = async (opts: CreateNextContextOptions) => {
return await createContextInner({});
};
export type Context = inferAsyncReturnType<typeof createContext>;

View File

@ -0,0 +1,9 @@
import { router } from "../trpc";
import { exampleRouter } from "./example";
export const appRouter = router({
example: exampleRouter,
});
// export type definition of API
export type AppRouter = typeof appRouter;

View File

@ -0,0 +1,16 @@
import { z } from "zod";
import { router, publicProcedure } from "../trpc";
export const exampleRouter = router({
hello: publicProcedure
.input(z.object({ text: z.string().nullish() }).nullish())
.query(({ input }) => {
return {
greeting: `Hello ${input?.text ?? "world"}`,
};
}),
getAll: publicProcedure.query(({ ctx }) => {
return ctx.prisma.example.findMany();
}),
});

View File

@ -0,0 +1,15 @@
import { initTRPC } from "@trpc/server";
import superjson from "superjson";
import { type Context } from "./context";
const t = initTRPC.context<Context>().create({
transformer: superjson,
errorFormatter({ shape }) {
return shape;
},
});
export const router = t.router;
export const publicProcedure = t.procedure;

View File

@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@ -0,0 +1,42 @@
import { httpBatchLink, loggerLink } from "@trpc/client";
import { createTRPCNext } from "@trpc/next";
import { type inferRouterInputs, type inferRouterOutputs } from "@trpc/server";
import superjson from "superjson";
import { type AppRouter } from "../server/trpc/router/_app";
const getBaseUrl = () => {
if (typeof window !== "undefined") return ""; // browser should use relative url
if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`; // SSR should use vercel url
return `http://localhost:${process.env.PORT ?? 3000}`; // dev SSR should use localhost
};
export const trpc = createTRPCNext<AppRouter>({
config() {
return {
transformer: superjson,
links: [
loggerLink({
enabled: (opts) =>
process.env.NODE_ENV === "development" ||
(opts.direction === "down" && opts.result instanceof Error),
}),
httpBatchLink({
url: `${getBaseUrl()}/api/trpc`,
}),
],
};
},
ssr: false,
});
/**
* Inference helper for inputs
* @example type HelloInput = RouterInputs['example']['hello']
**/
export type RouterInputs = inferRouterInputs<AppRouter>;
/**
* Inference helper for outputs
* @example type HelloOutput = RouterOutputs['example']['hello']
**/
export type RouterOutputs = inferRouterOutputs<AppRouter>;

View File

@ -0,0 +1,8 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./src/**/*.{js,ts,jsx,tsx}"],
theme: {
extend: {},
},
plugins: [],
};

View File

@ -0,0 +1,21 @@
{
"compilerOptions": {
"target": "es2017",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"noUncheckedIndexedAccess": true
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.cjs", "**/*.mjs"],
"exclude": ["node_modules"]
}

4
apps/docs/.eslintrc.js Normal file
View File

@ -0,0 +1,4 @@
module.exports = {
root: true,
extends: ["custom"],
};

30
apps/docs/README.md Normal file
View File

@ -0,0 +1,30 @@
## Getting Started
First, run the development server:
```bash
yarn dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`.
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.

5
apps/docs/next-env.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

6
apps/docs/next.config.js Normal file
View File

@ -0,0 +1,6 @@
module.exports = {
reactStrictMode: true,
experimental: {
transpilePackages: ["ui"],
},
};

27
apps/docs/package.json Normal file
View File

@ -0,0 +1,27 @@
{
"name": "docs",
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "next dev --port 3001",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"next": "13.0.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"ui": "workspace:*"
},
"devDependencies": {
"@babel/core": "^7.0.0",
"eslint-config-custom": "workspace:*",
"eslint": "7.32.0",
"tsconfig": "workspace:*",
"@types/node": "^17.0.12",
"@types/react": "^18.0.22",
"@types/react-dom": "^18.0.7",
"typescript": "^4.5.3"
}
}

10
apps/docs/pages/index.tsx Normal file
View File

@ -0,0 +1,10 @@
import { Button } from "ui";
export default function Docs() {
return (
<div>
<h1>Docs</h1>
<Button />
</div>
);
}

5
apps/docs/tsconfig.json Normal file
View File

@ -0,0 +1,5 @@
{
"extends": "tsconfig/nextjs.json",
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}

View File

@ -0,0 +1,61 @@
# Hashicorp's Vault Administration
A dump of knowledge, commands, and documentations to lookup for troubleshooting
or setting up
## CLI getting started
`export VAULT_ADDR='https://c4c.pegasust.com'`
`vault login`
- Note, the vault will first need to be unsealed
- The first time we log in as admin, it's probably best to use the
root token to access.
## Seal/unseal
- Vault server begins sealed
- I generated with 6/10 cluster vault configuration (10 keys & require 6 keys to unseal)
- These keys can be shared to other admins
- This means an admin only need 6 keys to unseal the vault when needed
## Enabling GitHub auth
- First, add our policy:
```bash
vault policy write {POLICY_NAME} {POLICY_FILE}
```
- Our deployment's replacements:
- `{POLICY_NAME}` is `web-app-admin`
- `{POLICY_FILE}` is `config/hashicorp-policy/web-app-admin.hcl`
- Then, we enable GitHub auth and attach `web-app-admin` to our `web-app-dev` team
```bash
vault auth enable github
vault write auth/github/config organization={GITHUB_ORG}
vault write auth/github/map/teams/{GITHUB_TEAM} value={VAULT_POLICY}
```
- Our deployment's version replaces:
- `{GITHUB_ORG}` is `change-for-change`
- `{GITHUB_TEAM}` is `web-app-dev`
- `{VAULT_POLICY}` is `web-app-admin`
## Updating policy
```bash
vault write sys/policy/{POLICY_NAME} policy=@{POLICY_FILE}
```
- An example is:
- `{POLICY_NAME}`: `web-app-admin`
- `{POLICY_FILE}`: `config/hashicorp-policy/web-app-admin.hcl`
## Bootstrapping our vault
`vault secrets enable -path=secret kv`
`vault secrets enable -path=secretv2 kv-v2`

View File

@ -0,0 +1,66 @@
# c4c-secrets
A dive into secret management for c4c web-app
# HashiCorp vault
- `docker-compose.yml` -> `docker-compose.hashicorp.yml`
- Uses in-file store (maybe slow/unreliable!)
- Can be migrated to AWS in the future
- Pretty good cli experience
- You could try my (@Pegasust) deployment at [pegasust.com/vault](https://pegasust.com/vault)
- Log in with your GitHub account
(this is done with personal access token [docs](https://www.vaultproject.io/docs/auth/github))
- Make sure that you're in our change-for-change organization
- And also is in web-dev GitHub team
## Installing the CLI
See here [hashicorp's official installtion guide](https://developer.hashicorp.com/vault/downloads)
- You could also access the secrets with the web UI. But to streamline the env
exchange process, we should use the CLI
## Login as user (CLI)
`export VAULT_ADDR='https://c4c.pegasust.com'`
`vault login -method=github`
## Vault onto `.env*`
```bash
vault kv get --format=json path/to/secret | jq -r '.data|to_entries|map("\(.key)=\(.value|tostring)")|.[]'
# Likely
vault kv get --format=json secret/c4c-web-app | jq -r '.data|to_entries|map("\(.key)=\(.value|tostring)")|.[]'
```
## Simple put-get-list
```bash
# put
vault kv put path/to/secret hello="world"
# get
vault kv get path/to/secret hello
# list
vault kv get path/to/secret
```
## `.env.*` onto Vault
- NOTE: This does not support syntax like `HELLO='WORLD'`. Everything must be
in the form of: `HELLO=WORLD`
```bash
vault kv put path/to/secret `cat .env`
# Likely
vault kv put secret/c4c-web-app `grep -v ^# .env`
```
## About the `cubbyhole` secret engine
- It is per-token (that means per-auth) secret storage
- Can be used as secret manager
- Don't count on my deployment to be 100\% reliable!

View File

@ -0,0 +1,35 @@
# Read the configuration secret example
path "secret/config" {
capabilities = ["read"]
}
path "secret" {
capabilities = ["list"]
}
path "secret/*" {
capabilities = ["list"]
}
path "secret/c4c-web-app" {
capabilities = ["read", "list", "create", "update"]
}
path "secret/c4c-web-app/*" {
capabilities = ["read", "create", "update", "list"]
}
path "secretv2" {
capabilities = ["list"]
}
path "secretv2/*" {
capabilities = ["list"]
}
path "secretv2/c4c-web-app" {
capabilities = ["read", "list", "create", "update"]
}
path "secretv2/c4c-web-app/*" {
capabilities = ["read", "create", "update", "list"]
}
# List secrets engines
path "sys/mounts" {
capabilities = ["read"]
}

View File

@ -0,0 +1,14 @@
{
"backend": {
"file": {
"path": "/vault/file"
}
},
"listener": {
"tcp":{
"address": "0.0.0.0:8200",
"tls_disable": 1
}
},
"ui": true
}

View File

@ -0,0 +1,20 @@
version: '3.5'
services:
vault:
image: vault:1.11.3
restart: always
entrypoint: vault server -config=vault/config/vault.json
volumes:
- hashicorp_vault:/vault
- ./config/hashicorp:/vault/config
cap_add:
- IPC_LOCK
networks: [felia]
ports:
- 8200:8200
volumes:
hashicorp_vault:
networks:
felia:
name: felia-nginx-net

4
apps/web/.eslintrc.js Normal file
View File

@ -0,0 +1,4 @@
module.exports = {
root: true,
extends: ["custom"],
};

30
apps/web/README.md Normal file
View File

@ -0,0 +1,30 @@
## Getting Started
First, run the development server:
```bash
yarn dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`.
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.

5
apps/web/next-env.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

6
apps/web/next.config.js Normal file
View File

@ -0,0 +1,6 @@
module.exports = {
reactStrictMode: true,
experimental: {
transpilePackages: ["ui"],
},
};

27
apps/web/package.json Normal file
View File

@ -0,0 +1,27 @@
{
"name": "web",
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"next": "13.0.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"ui": "workspace:*"
},
"devDependencies": {
"@babel/core": "^7.0.0",
"eslint-config-custom": "workspace:*",
"eslint": "7.32.0",
"tsconfig": "workspace:*",
"@types/node": "^17.0.12",
"@types/react": "^18.0.22",
"@types/react-dom": "^18.0.7",
"typescript": "^4.5.3"
}
}

10
apps/web/pages/index.tsx Normal file
View File

@ -0,0 +1,10 @@
import { Button } from "ui";
export default function Web() {
return (
<div>
<h1>Web</h1>
<Button />
</div>
);
}

5
apps/web/tsconfig.json Normal file
View File

@ -0,0 +1,5 @@
{
"extends": "tsconfig/nextjs.json",
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}

View File

@ -1 +0,0 @@
/home/ubuntu_admin/local_repos/c4c-secret-manager/

120
flake.lock Normal file
View File

@ -0,0 +1,120 @@
{
"nodes": {
"flake-utils": {
"locked": {
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"locked": {
"lastModified": 1667077288,
"narHash": "sha256-bdC8sFNDpT0HK74u9fUkpbf1MEzVYJ+ka7NXCdgBoaA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "6ee9ebb6b1ee695d2cacc4faa053a7b9baa76817",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1667629849,
"narHash": "sha256-P+v+nDOFWicM4wziFK9S/ajF2lc0N2Rg9p6Y35uMoZI=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "3bacde6273b09a21a8ccfba15586fb165078fb62",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1667050928,
"narHash": "sha256-xOn0ZgjImIyeecEsrjxuvlW7IW5genTwvvnDQRFncB8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "fdebb81f45a1ba2c4afca5fd9f526e1653ad0949",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"turbo": "turbo"
}
},
"rust-overlay": {
"inputs": {
"flake-utils": [
"turbo",
"flake-utils"
],
"nixpkgs": [
"turbo",
"nixpkgs"
]
},
"locked": {
"lastModified": 1667098607,
"narHash": "sha256-zTYgUaS+81mNq8Z0v2WYr46ACJFBeWqcQfOVQaTxtNE=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "de5c4d5d40ae0a0dab67c5f7ae8d26c5445cf00d",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"turbo": {
"inputs": {
"flake-utils": "flake-utils_2",
"nixpkgs": "nixpkgs_2",
"rust-overlay": "rust-overlay"
},
"locked": {
"lastModified": 1667101919,
"narHash": "sha256-xOCDfi7ADRkfmHt83gQ+rs7Oaqij4IMV1NF3PQZtF+c=",
"owner": "dlip",
"repo": "turbo",
"rev": "ffce29ea3b5ede544128b790d67c80aa2d3efc03",
"type": "github"
},
"original": {
"owner": "dlip",
"repo": "turbo",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

59
flake.nix Normal file
View File

@ -0,0 +1,59 @@
{
description = "Provides devShell and (very unlikely) package & app";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
# https://github.com/vercel/turbo/issues/2293#issuecomment-1296094236
# work-around for turbo-repo on nix
turbo.url = "github:dlip/turbo";
};
outputs = { self, turbo, flake-utils, nixpkgs }:
with flake-utils; lib.eachSystem lib.defaultSystems (sys:
let
overlays = [ turbo.overlay ];
# pkgs is our tweaked nixpkgs
pkgs = import nixpkgs { system = sys; overlays = overlays; };
shellMsg = ''
echo "Hello from nix ${sys}"
'';
shellAliases = ''
'';
in
{
devShell = pkgs.mkShell {
nativeBuildInputs = [ pkgs.bashInteractive ];
buildInputs = [
pkgs.nodejs-18_x
pkgs.nodePackages.pnpm
pkgs.nodePackages.prisma
pkgs.prisma-engines
pkgs.turbo
# pkgs.turbo-tooling
pkgs.vault
pkgs.jq
pkgs.pscale
pkgs.act
pkgs.cypress
];
shellHook =
# https://github.com/prisma/prisma/issues/3026#issuecomment-927258138
# nix-direnv is required (impure build?) https://github.com/nix-community/nix-direnv
''
# Prisma
export PRISMA_MIGRATION_ENGINE_BINARY="${pkgs.prisma-engines}/bin/migration-engine"
export PRISMA_QUERY_ENGINE_BINARY="${pkgs.prisma-engines}/bin/query-engine"
export PRISMA_QUERY_ENGINE_LIBRARY="${pkgs.prisma-engines}/lib/libquery_engine.node"
export PRISMA_INTROSPECTION_ENGINE_BINARY="${pkgs.prisma-engines}/bin/introspection-engine"
export PRISMA_FMT_BINARY="${pkgs.prisma-engines}/bin/prisma-fmt"
# Turbo
export TURBO_BINARY_PATH="${pkgs.turbo}/bin/turbo"
# Cypress
export CYPRESS_RUN_BINARY="${pkgs.cypress}/bin/Cypress"
'' + shellAliases + shellMsg;
};
});
}

25
package.json Normal file
View File

@ -0,0 +1,25 @@
{
"name": "felia",
"version": "0.0.0",
"private": true,
"workspaces": [
"apps/*",
"packages/*"
],
"scripts": {
"build": "turbo run build",
"dev": "turbo run dev --parallel",
"lint": "turbo run lint",
"format": "prettier --write \"**/*.{ts,tsx,md}\""
},
"devDependencies": {
"eslint-config-custom": "workspace:*",
"prettier": "latest",
"turbo": "1.6.2"
},
"engines": {
"node": ">=14.0.0"
},
"dependencies": {},
"packageManager": "pnpm@7.14.0"
}

View File

@ -0,0 +1,14 @@
module.exports = {
extends: ["next", "prettier"],
settings: {
next: {
rootDir: [
"apps/docs/",
"apps/web/",
"packages/ui/",
"packages/config/",
"packages/tsconfig/",
],
},
},
};

View File

@ -0,0 +1,15 @@
{
"name": "config",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"files": [
"eslint-preset.js"
],
"dependencies": {
"eslint": "^8.27.0",
"eslint-config-next": "^12.0.3",
"eslint-config-prettier": "^8.3.0",
"typescript": "^4.8.4"
}
}

View File

@ -0,0 +1,7 @@
module.exports = {
extends: ["next", "turbo", "prettier"],
rules: {
"@next/next/no-html-link-for-pages": "off",
"react/jsx-key": "off",
},
};

View File

@ -0,0 +1,19 @@
{
"name": "eslint-config-custom",
"version": "0.0.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"eslint": "^7.23.0",
"eslint-config-next": "13.0.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-react": "7.31.8",
"eslint-config-turbo": "latest"
},
"devDependencies": {
"typescript": "^4.7.4"
},
"publishConfig": {
"access": "public"
}
}

View File

@ -0,0 +1,3 @@
# `tsconfig`
These are base shared `tsconfig.json`s from which all other `tsconfig.json`'s inherit from.

View File

@ -0,0 +1,20 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Default",
"compilerOptions": {
"composite": false,
"declaration": true,
"declarationMap": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"inlineSources": false,
"isolatedModules": true,
"moduleResolution": "node",
"noUnusedLocals": false,
"noUnusedParameters": false,
"preserveWatchOutput": true,
"skipLibCheck": true,
"strict": true
},
"exclude": ["node_modules"]
}

View File

@ -0,0 +1,22 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Next.js",
"extends": "./base.json",
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"incremental": true,
"esModuleInterop": true,
"module": "esnext",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve"
},
"include": ["src", "next-env.d.ts"],
"exclude": ["node_modules"]
}

View File

@ -0,0 +1,10 @@
{
"name": "tsconfig",
"version": "0.0.0",
"private": true,
"files": [
"base.json",
"nextjs.json",
"react-library.json"
]
}

View File

@ -0,0 +1,11 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"display": "React Library",
"extends": "./base.json",
"compilerOptions": {
"jsx": "react-jsx",
"lib": ["ES2015"],
"module": "ESNext",
"target": "es6"
}
}

4
packages/ui/Button.tsx Normal file
View File

@ -0,0 +1,4 @@
import * as React from "react";
export const Button = () => {
return <button>Boop</button>;
};

2
packages/ui/index.tsx Normal file
View File

@ -0,0 +1,2 @@
import * as React from "react";
export * from "./Button";

19
packages/ui/package.json Normal file
View File

@ -0,0 +1,19 @@
{
"name": "ui",
"version": "0.0.0",
"main": "./index.tsx",
"types": "./index.tsx",
"license": "MIT",
"scripts": {
"lint": "eslint *.ts*"
},
"devDependencies": {
"@types/react": "^18.0.17",
"@types/react-dom": "^18.0.6",
"eslint": "^7.32.0",
"eslint-config-custom": "workspace:*",
"react": "^18.2.0",
"tsconfig": "workspace:*",
"typescript": "^4.5.2"
}
}

View File

@ -0,0 +1,5 @@
{
"extends": "tsconfig/react-library.json",
"include": ["."],
"exclude": ["dist", "build", "node_modules"]
}

2726
pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

3
pnpm-workspace.yaml Normal file
View File

@ -0,0 +1,3 @@
packages:
- "apps/*"
- "packages/*"

15
turbo.json Normal file
View File

@ -0,0 +1,15 @@
{
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**"]
},
"lint": {
"outputs": []
},
"dev": {
"cache": false
}
}
}