├── bad-code
├── backend
│ ├── .gitignore
│ ├── .env.example
│ ├── src
│ │ ├── index.ts
│ │ ├── http.ts
│ │ ├── pty.ts
│ │ ├── fs.ts
│ │ ├── ws.ts
│ │ └── aws.ts
│ ├── package.json
│ └── tsconfig.json
└── frontend
│ ├── src
│ ├── vite-env.d.ts
│ ├── config.ts
│ ├── index.css
│ ├── main.tsx
│ ├── components
│ │ ├── Output.tsx
│ │ ├── external
│ │ │ └── editor
│ │ │ │ ├── components
│ │ │ │ ├── sidebar.tsx
│ │ │ │ ├── icon.tsx
│ │ │ │ └── file-tree.tsx
│ │ │ │ ├── utils
│ │ │ │ ├── index.tsx
│ │ │ │ └── file-manager.tsx
│ │ │ │ └── editor
│ │ │ │ └── code.tsx
│ │ ├── Editor.tsx
│ │ ├── Terminal.tsx
│ │ ├── Landing.tsx
│ │ └── CodingPage.tsx
│ ├── App.tsx
│ ├── assets
│ │ └── react.svg
│ └── App.css
│ ├── vite.config.ts
│ ├── tsconfig.node.json
│ ├── .gitignore
│ ├── index.html
│ ├── .eslintrc.cjs
│ ├── tsconfig.json
│ ├── package.json
│ ├── README.md
│ └── public
│ └── vite.svg
├── good-code
├── runner
│ ├── .gitignore
│ ├── .DS_Store
│ ├── .env.example
│ ├── src
│ │ ├── index.ts
│ │ ├── pty.ts
│ │ ├── fs.ts
│ │ ├── ws.ts
│ │ └── aws.ts
│ ├── Dockerfile
│ ├── package.json
│ └── tsconfig.json
├── init-service
│ ├── .gitignore
│ ├── src
│ │ ├── .env.example
│ │ ├── index.ts
│ │ └── aws.ts
│ ├── package.json
│ └── tsconfig.json
├── orchestrator-simple
│ ├── .gitignore
│ ├── src
│ │ ├── .env.example
│ │ ├── index.ts
│ │ └── aws.ts
│ ├── package.json
│ ├── service.yaml
│ └── tsconfig.json
├── frontend
│ ├── src
│ │ ├── vite-env.d.ts
│ │ ├── index.css
│ │ ├── main.tsx
│ │ ├── components
│ │ │ ├── Output.tsx
│ │ │ ├── external
│ │ │ │ └── editor
│ │ │ │ │ ├── components
│ │ │ │ │ ├── sidebar.tsx
│ │ │ │ │ ├── icon.tsx
│ │ │ │ │ └── file-tree.tsx
│ │ │ │ │ ├── utils
│ │ │ │ │ ├── index.tsx
│ │ │ │ │ └── file-manager.tsx
│ │ │ │ │ └── editor
│ │ │ │ │ └── code.tsx
│ │ │ ├── Editor.tsx
│ │ │ ├── Terminal.tsx
│ │ │ ├── Landing.tsx
│ │ │ └── CodingPage.tsx
│ │ ├── App.tsx
│ │ ├── assets
│ │ │ └── react.svg
│ │ └── App.css
│ ├── vite.config.ts
│ ├── tsconfig.node.json
│ ├── .gitignore
│ ├── index.html
│ ├── .eslintrc.cjs
│ ├── tsconfig.json
│ ├── package.json
│ ├── README.md
│ └── public
│ │ └── vite.svg
└── k8s
│ └── ingress-controller.yaml
└── README.md
/bad-code/backend/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | tmp
--------------------------------------------------------------------------------
/good-code/runner/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/good-code/init-service/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/good-code/orchestrator-simple/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/bad-code/frontend/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/good-code/frontend/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/bad-code/frontend/src/config.ts:
--------------------------------------------------------------------------------
1 |
2 | export const EXECUTION_ENGINE_URI = "ws://localhost:3001";
--------------------------------------------------------------------------------
/good-code/runner/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hkirat/repl/HEAD/good-code/runner/.DS_Store
--------------------------------------------------------------------------------
/bad-code/backend/.env.example:
--------------------------------------------------------------------------------
1 | S3_BUCKET=
2 | AWS_ACCESS_KEY_ID=
3 | AWS_SECRET_ACCESS_KEY=
4 | S3_ENDPOINT=
--------------------------------------------------------------------------------
/good-code/runner/.env.example:
--------------------------------------------------------------------------------
1 | S3_BUCKET=
2 | AWS_ACCESS_KEY_ID=
3 | AWS_SECRET_ACCESS_KEY=
4 | S3_ENDPOINT=
--------------------------------------------------------------------------------
/good-code/init-service/src/.env.example:
--------------------------------------------------------------------------------
1 | S3_BUCKET=
2 | AWS_ACCESS_KEY_ID=
3 | AWS_SECRET_ACCESS_KEY=
4 | S3_ENDPOINT=
--------------------------------------------------------------------------------
/good-code/orchestrator-simple/src/.env.example:
--------------------------------------------------------------------------------
1 | S3_BUCKET=
2 | AWS_ACCESS_KEY_ID=
3 | AWS_SECRET_ACCESS_KEY=
4 | S3_ENDPOINT=
--------------------------------------------------------------------------------
/bad-code/frontend/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: 'Inter', sans-serif;
3 | font-size: 14px;
4 |
5 | background-color: #151515;
6 | color: white;
7 | zoom: 1;
8 | margin: 0;
9 | }
10 |
--------------------------------------------------------------------------------
/good-code/frontend/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: 'Inter', sans-serif;
3 | font-size: 14px;
4 |
5 | background-color: #151515;
6 | color: white;
7 | zoom: 1;
8 | margin: 0;
9 | }
10 |
--------------------------------------------------------------------------------
/bad-code/frontend/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | })
8 |
--------------------------------------------------------------------------------
/good-code/frontend/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | })
8 |
--------------------------------------------------------------------------------
/bad-code/frontend/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom/client'
3 | import App from './App.tsx'
4 | import './index.css'
5 |
6 | ReactDOM.createRoot(document.getElementById('root')!).render(
7 | ,
8 | )
9 |
--------------------------------------------------------------------------------
/good-code/frontend/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom/client'
3 | import App from './App.tsx'
4 | import './index.css'
5 |
6 | ReactDOM.createRoot(document.getElementById('root')!).render(
7 | ,
8 | )
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Repl.it implementation
2 | Implementation of an online code editor in Node.js
3 |
4 | ## Stack
5 | Node.js
6 | K8s
7 | Express
8 | socket.io
9 |
10 | ## TODOs
11 | There are a bunch of TODOs that you can go through, there are bounties associated with all of them
12 |
--------------------------------------------------------------------------------
/bad-code/frontend/src/components/Output.tsx:
--------------------------------------------------------------------------------
1 |
2 | const INSTANCE_URI = "http://localhost:3000";
3 |
4 | export const Output = () => {
5 | return
6 |
7 |
8 | }
--------------------------------------------------------------------------------
/bad-code/frontend/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "skipLibCheck": true,
5 | "module": "ESNext",
6 | "moduleResolution": "bundler",
7 | "allowSyntheticDefaultImports": true,
8 | "strict": true
9 | },
10 | "include": ["vite.config.ts"]
11 | }
12 |
--------------------------------------------------------------------------------
/good-code/frontend/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "skipLibCheck": true,
5 | "module": "ESNext",
6 | "moduleResolution": "bundler",
7 | "allowSyntheticDefaultImports": true,
8 | "strict": true
9 | },
10 | "include": ["vite.config.ts"]
11 | }
12 |
--------------------------------------------------------------------------------
/bad-code/frontend/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/good-code/frontend/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/bad-code/frontend/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React + TS
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/good-code/frontend/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React + TS
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/good-code/frontend/src/components/Output.tsx:
--------------------------------------------------------------------------------
1 | import { useSearchParams } from "react-router-dom";
2 |
3 | export const Output = () => {
4 | const [searchParams] = useSearchParams();
5 | const replId = searchParams.get('replId') ?? '';
6 | const INSTANCE_URI = `http://${replId}.autogpt-cloud.com`;
7 |
8 | return
9 |
10 |
11 | }
--------------------------------------------------------------------------------
/good-code/runner/src/index.ts:
--------------------------------------------------------------------------------
1 | import dotenv from "dotenv"
2 | dotenv.config()
3 | import express from "express";
4 | import { createServer } from "http";
5 | import { initWs } from "./ws";
6 | import cors from "cors";
7 |
8 | const app = express();
9 | app.use(cors());
10 | const httpServer = createServer(app);
11 |
12 | initWs(httpServer);
13 |
14 | const port = process.env.PORT || 3001;
15 | httpServer.listen(port, () => {
16 | console.log(`listening on *:${port}`);
17 | });
--------------------------------------------------------------------------------
/bad-code/frontend/src/App.tsx:
--------------------------------------------------------------------------------
1 | import './App.css'
2 | import { CodingPage } from './components/CodingPage'
3 | import { BrowserRouter, Route, Routes } from "react-router-dom";
4 | import { Landing } from './components/Landing';
5 |
6 | function App() {
7 | return (
8 |
9 |
10 | } />
11 | } />
12 |
13 |
14 | )
15 | }
16 |
17 | export default App
18 |
--------------------------------------------------------------------------------
/bad-code/frontend/src/components/external/editor/components/sidebar.tsx:
--------------------------------------------------------------------------------
1 | import React, {ReactNode} from 'react';
2 | import styled from "@emotion/styled";
3 |
4 | export const Sidebar = ({children}: { children: ReactNode }) => {
5 | return (
6 |
9 | )
10 | }
11 |
12 | const Aside = styled.aside`
13 | width: 250px;
14 | height: 100vh;
15 | border-right: 2px solid;
16 | border-color: #242424;
17 | padding-top: 3px;
18 | `
19 |
20 | export default Sidebar
21 |
--------------------------------------------------------------------------------
/good-code/frontend/src/App.tsx:
--------------------------------------------------------------------------------
1 | import './App.css'
2 | import { CodingPage } from './components/CodingPage'
3 | import { BrowserRouter, Route, Routes } from "react-router-dom";
4 | import { Landing } from './components/Landing';
5 |
6 | function App() {
7 | return (
8 |
9 |
10 | } />
11 | } />
12 |
13 |
14 | )
15 | }
16 |
17 | export default App
18 |
--------------------------------------------------------------------------------
/good-code/frontend/src/components/external/editor/components/sidebar.tsx:
--------------------------------------------------------------------------------
1 | import React, {ReactNode} from 'react';
2 | import styled from "@emotion/styled";
3 |
4 | export const Sidebar = ({children}: { children: ReactNode }) => {
5 | return (
6 |
9 | )
10 | }
11 |
12 | const Aside = styled.aside`
13 | width: 250px;
14 | height: 100vh;
15 | border-right: 2px solid;
16 | border-color: #242424;
17 | padding-top: 3px;
18 | `
19 |
20 | export default Sidebar
21 |
--------------------------------------------------------------------------------
/bad-code/backend/src/index.ts:
--------------------------------------------------------------------------------
1 | import dotenv from "dotenv"
2 | dotenv.config()
3 | import express from "express";
4 | import { createServer } from "http";
5 | import { initWs } from "./ws";
6 | import { initHttp } from "./http";
7 | import cors from "cors";
8 |
9 | const app = express();
10 | app.use(cors());
11 | const httpServer = createServer(app);
12 |
13 | initWs(httpServer);
14 | initHttp(app);
15 |
16 | const port = process.env.PORT || 3001;
17 | httpServer.listen(port, () => {
18 | console.log(`listening on *:${port}`);
19 | });
--------------------------------------------------------------------------------
/bad-code/frontend/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: { browser: true, es2020: true },
4 | extends: [
5 | 'eslint:recommended',
6 | 'plugin:@typescript-eslint/recommended',
7 | 'plugin:react-hooks/recommended',
8 | ],
9 | ignorePatterns: ['dist', '.eslintrc.cjs'],
10 | parser: '@typescript-eslint/parser',
11 | plugins: ['react-refresh'],
12 | rules: {
13 | 'react-refresh/only-export-components': [
14 | 'warn',
15 | { allowConstantExport: true },
16 | ],
17 | },
18 | }
19 |
--------------------------------------------------------------------------------
/good-code/frontend/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: { browser: true, es2020: true },
4 | extends: [
5 | 'eslint:recommended',
6 | 'plugin:@typescript-eslint/recommended',
7 | 'plugin:react-hooks/recommended',
8 | ],
9 | ignorePatterns: ['dist', '.eslintrc.cjs'],
10 | parser: '@typescript-eslint/parser',
11 | plugins: ['react-refresh'],
12 | rules: {
13 | 'react-refresh/only-export-components': [
14 | 'warn',
15 | { allowConstantExport: true },
16 | ],
17 | },
18 | }
19 |
--------------------------------------------------------------------------------
/bad-code/frontend/src/components/external/editor/utils/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {buildFileTree, Directory} from "./file-manager";
3 |
4 | export const useFilesFromSandbox = (id: string, callback: (dir: Directory) => void) => {
5 | React.useEffect(() => {
6 | fetch('https://codesandbox.io/api/v1/sandboxes/' + id)
7 | .then(response => response.json())
8 | .then(({data}) => {
9 | const rootDir = buildFileTree(data);
10 | callback(rootDir)
11 | })
12 | // eslint-disable-next-line react-hooks/exhaustive-deps
13 | }, [])
14 | }
15 |
--------------------------------------------------------------------------------
/good-code/frontend/src/components/external/editor/utils/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {buildFileTree, Directory} from "./file-manager";
3 |
4 | export const useFilesFromSandbox = (id: string, callback: (dir: Directory) => void) => {
5 | React.useEffect(() => {
6 | fetch('https://codesandbox.io/api/v1/sandboxes/' + id)
7 | .then(response => response.json())
8 | .then(({data}) => {
9 | const rootDir = buildFileTree(data);
10 | callback(rootDir)
11 | })
12 | // eslint-disable-next-line react-hooks/exhaustive-deps
13 | }, [])
14 | }
15 |
--------------------------------------------------------------------------------
/bad-code/backend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "backend",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "dependencies": {
7 | "aws-sdk": "^2.1556.0",
8 | "dotenv": "^16.4.3",
9 | "express": "^4.18.2",
10 | "node-pty": "^1.0.0",
11 | "socket.io": "^4.7.4"
12 | },
13 | "scripts": {
14 | "build": "tsc -b",
15 | "start": "node dist/index.js",
16 | "dev": "nodemon --watch src src/index.ts"
17 | },
18 | "devDependencies": {
19 | "@types/express": "^4.17.21",
20 | "typescript": "^5.3.3",
21 | "nodemon": "^3.0.3",
22 | "ts-node": "^10.9.2"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/good-code/init-service/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "init-service",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "dependencies": {
7 | "@types/cors": "^2.8.17",
8 | "aws-sdk": "^2.1556.0",
9 | "cors": "^2.8.5",
10 | "dotenv": "^16.4.3",
11 | "express": "^4.18.2",
12 | "nodemon": "^3.0.3",
13 | "ts-node": "^10.9.2"
14 | },
15 | "scripts": {
16 | "build": "tsc -b",
17 | "start": "node dist/index.js",
18 | "dev": "nodemon --watch src src/index.ts"
19 | },
20 | "devDependencies": {
21 | "@types/express": "^4.17.21",
22 | "typescript": "^5.3.3"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/bad-code/backend/src/http.ts:
--------------------------------------------------------------------------------
1 | import { Express } from "express";
2 | import { copyS3Folder } from "./aws";
3 | import express from "express";
4 |
5 | export function initHttp(app: Express) {
6 | app.use(express.json());
7 |
8 | app.post("/project", async (req, res) => {
9 | // Hit a database to ensure this slug isn't taken already
10 | const { replId, language } = req.body;
11 |
12 | if (!replId) {
13 | res.status(400).send("Bad request");
14 | return;
15 | }
16 |
17 | await copyS3Folder(`base/${language}`, `code/${replId}`);
18 |
19 | res.send("Project created");
20 | });
21 | }
--------------------------------------------------------------------------------
/good-code/orchestrator-simple/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "init-service",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "dependencies": {
7 | "@kubernetes/client-node": "^0.20.0",
8 | "@types/cors": "^2.8.17",
9 | "aws-sdk": "^2.1556.0",
10 | "cors": "^2.8.5",
11 | "dotenv": "^16.4.3",
12 | "express": "^4.18.2",
13 | "nodemon": "^3.0.3",
14 | "ts-node": "^10.9.2",
15 | "yaml": "^2.3.4"
16 | },
17 | "scripts": {
18 | "build": "tsc -b",
19 | "start": "node dist/index.js",
20 | "dev": "nodemon --watch src src/index.ts"
21 | },
22 | "devDependencies": {
23 | "@types/express": "^4.17.21",
24 | "typescript": "^5.3.3"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/bad-code/frontend/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "useDefineForClassFields": true,
5 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
6 | "module": "ESNext",
7 | "skipLibCheck": true,
8 |
9 | /* Bundler mode */
10 | "moduleResolution": "bundler",
11 | "allowImportingTsExtensions": true,
12 | "resolveJsonModule": true,
13 | "isolatedModules": true,
14 | "noEmit": true,
15 | "jsx": "react-jsx",
16 |
17 | /* Linting */
18 | "strict": true,
19 | "noUnusedLocals": true,
20 | "noUnusedParameters": true,
21 | "noFallthroughCasesInSwitch": true
22 | },
23 | "include": ["src"],
24 | "references": [{ "path": "./tsconfig.node.json" }]
25 | }
26 |
--------------------------------------------------------------------------------
/good-code/frontend/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "useDefineForClassFields": true,
5 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
6 | "module": "ESNext",
7 | "skipLibCheck": true,
8 |
9 | /* Bundler mode */
10 | "moduleResolution": "bundler",
11 | "allowImportingTsExtensions": true,
12 | "resolveJsonModule": true,
13 | "isolatedModules": true,
14 | "noEmit": true,
15 | "jsx": "react-jsx",
16 |
17 | /* Linting */
18 | "strict": true,
19 | "noUnusedLocals": true,
20 | "noUnusedParameters": true,
21 | "noFallthroughCasesInSwitch": true
22 | },
23 | "include": ["src"],
24 | "references": [{ "path": "./tsconfig.node.json" }]
25 | }
26 |
--------------------------------------------------------------------------------
/good-code/runner/Dockerfile:
--------------------------------------------------------------------------------
1 | # Use the official Node.js 14 as a parent image
2 | FROM node:20
3 |
4 | # Set the working directory in the container
5 | WORKDIR /code
6 |
7 | # Copy package.json and package-lock.json (if available) to the working directory
8 | COPY package*.json ./
9 |
10 | # Install any dependencies
11 | RUN npm install
12 |
13 | # Copy the rest of your application's code to the working directory
14 | COPY . .
15 |
16 | # Build your app
17 | RUN npm run build
18 |
19 | # Your app binds to port 3000 so you'll use the EXPOSE instruction to have it mapped by the docker daemon
20 | EXPOSE 3000
21 |
22 | # Define the command to run your app using CMD which defines your runtime
23 | CMD [ "node", "dist/index.js" ]
24 |
25 |
--------------------------------------------------------------------------------
/good-code/runner/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "runner",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "build": "tsc -b",
8 | "start": "node dist/index.js",
9 | "dev": "nodemon --watch src src/index.ts"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "dependencies": {
15 | "@types/express": "^4.17.21",
16 | "aws-sdk": "^2.1559.0",
17 | "cors": "^2.8.5",
18 | "dotenv": "^16.4.4",
19 | "express": "^4.18.2",
20 | "node-pty": "^1.0.0",
21 | "socket.io": "^4.7.4"
22 | },
23 | "devDependencies": {
24 | "@types/express": "^4.17.21",
25 | "nodemon": "^3.0.3",
26 | "ts-node": "^10.9.2",
27 | "typescript": "^5.3.3"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/good-code/init-service/src/index.ts:
--------------------------------------------------------------------------------
1 | import express from "express";
2 | import dotenv from "dotenv"
3 | import cors from "cors";
4 | dotenv.config()
5 | import { copyS3Folder } from "./aws";
6 |
7 | const app = express();
8 | app.use(express.json());
9 | app.use(cors())
10 |
11 | app.post("/project", async (req, res) => {
12 | // Hit a database to ensure this slug isn't taken already
13 | const { replId, language } = req.body;
14 |
15 | if (!replId) {
16 | res.status(400).send("Bad request");
17 | return;
18 | }
19 |
20 | await copyS3Folder(`base/${language}`, `code/${replId}`);
21 |
22 | res.send("Project created");
23 | });
24 |
25 | const port = process.env.PORT || 3001;
26 |
27 | app.listen(port, () => {
28 | console.log(`listening on *:${port}`);
29 | });
30 |
--------------------------------------------------------------------------------
/bad-code/frontend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "frontend",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc && vite build",
9 | "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "@emotion/react": "^11.11.3",
14 | "@emotion/styled": "^11.11.0",
15 | "@monaco-editor/react": "^4.6.0",
16 | "axios": "^1.6.7",
17 | "react": "^18.2.0",
18 | "react-dom": "^18.2.0",
19 | "react-icons": "^5.0.1",
20 | "react-router-dom": "^6.22.0",
21 | "socket.io-client": "^4.7.4",
22 | "xterm": "^5.3.0",
23 | "xterm-addon-fit": "^0.8.0"
24 | },
25 | "devDependencies": {
26 | "@types/react": "^18.2.55",
27 | "@types/react-dom": "^18.2.19",
28 | "@typescript-eslint/eslint-plugin": "^6.21.0",
29 | "@typescript-eslint/parser": "^6.21.0",
30 | "@vitejs/plugin-react": "^4.2.1",
31 | "eslint": "^8.56.0",
32 | "eslint-plugin-react-hooks": "^4.6.0",
33 | "eslint-plugin-react-refresh": "^0.4.5",
34 | "typescript": "^5.2.2",
35 | "vite": "^5.1.0"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/good-code/frontend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "frontend",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc && vite build",
9 | "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "@emotion/react": "^11.11.3",
14 | "@emotion/styled": "^11.11.0",
15 | "@monaco-editor/react": "^4.6.0",
16 | "axios": "^1.6.7",
17 | "react": "^18.2.0",
18 | "react-dom": "^18.2.0",
19 | "react-icons": "^5.0.1",
20 | "react-router-dom": "^6.22.0",
21 | "socket.io-client": "^4.7.4",
22 | "xterm": "^5.3.0",
23 | "xterm-addon-fit": "^0.8.0"
24 | },
25 | "devDependencies": {
26 | "@types/react": "^18.2.55",
27 | "@types/react-dom": "^18.2.19",
28 | "@typescript-eslint/eslint-plugin": "^6.21.0",
29 | "@typescript-eslint/parser": "^6.21.0",
30 | "@vitejs/plugin-react": "^4.2.1",
31 | "eslint": "^8.56.0",
32 | "eslint-plugin-react-hooks": "^4.6.0",
33 | "eslint-plugin-react-refresh": "^0.4.5",
34 | "typescript": "^5.2.2",
35 | "vite": "^5.1.0"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/good-code/runner/src/pty.ts:
--------------------------------------------------------------------------------
1 | //@ts-ignore => someone fix this
2 | import { fork, IPty } from 'node-pty';
3 | import path from "path";
4 |
5 | const SHELL = "bash";
6 |
7 | export class TerminalManager {
8 | private sessions: { [id: string]: {terminal: IPty, replId: string;} } = {};
9 |
10 | constructor() {
11 | this.sessions = {};
12 | }
13 |
14 | createPty(id: string, replId: string, onData: (data: string, id: number) => void) {
15 | let term = fork(SHELL, [], {
16 | cols: 100,
17 | name: 'xterm',
18 | cwd: `/workspace`
19 | });
20 |
21 | term.on('data', (data: string) => onData(data, term.pid));
22 | this.sessions[id] = {
23 | terminal: term,
24 | replId
25 | };
26 | term.on('exit', () => {
27 | delete this.sessions[term.pid];
28 | });
29 | return term;
30 | }
31 |
32 | write(terminalId: string, data: string) {
33 | this.sessions[terminalId]?.terminal.write(data);
34 | }
35 |
36 | clear(terminalId: string) {
37 | this.sessions[terminalId].terminal.kill();
38 | delete this.sessions[terminalId];
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/bad-code/backend/src/pty.ts:
--------------------------------------------------------------------------------
1 | //@ts-ignore => someone fix this
2 | import { fork, IPty } from 'node-pty';
3 | import path from "path";
4 |
5 | const SHELL = "bash";
6 |
7 | export class TerminalManager {
8 | private sessions: { [id: string]: {terminal: IPty, replId: string;} } = {};
9 |
10 | constructor() {
11 | this.sessions = {};
12 | }
13 |
14 | createPty(id: string, replId: string, onData: (data: string, id: number) => void) {
15 | let term = fork(SHELL, [], {
16 | cols: 100,
17 | name: 'xterm',
18 | cwd: path.join(__dirname, `../tmp/${replId}`)
19 | });
20 |
21 | term.on('data', (data: string) => onData(data, term.pid));
22 | this.sessions[id] = {
23 | terminal: term,
24 | replId
25 | };
26 | term.on('exit', () => {
27 | delete this.sessions[term.pid];
28 | });
29 | return term;
30 | }
31 |
32 | write(terminalId: string, data: string) {
33 | this.sessions[terminalId]?.terminal.write(data);
34 | }
35 |
36 | clear(terminalId: string) {
37 | this.sessions[terminalId].terminal.kill();
38 | delete this.sessions[terminalId];
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/bad-code/backend/src/fs.ts:
--------------------------------------------------------------------------------
1 | import fs from "fs";
2 |
3 | interface File {
4 | type: "file" | "dir";
5 | name: string;
6 | }
7 |
8 | export const fetchDir = (dir: string, baseDir: string): Promise => {
9 | return new Promise((resolve, reject) => {
10 | fs.readdir(dir, { withFileTypes: true }, (err, files) => {
11 | if (err) {
12 | reject(err);
13 | } else {
14 | resolve(files.map(file => ({ type: file.isDirectory() ? "dir" : "file", name: file.name, path: `${baseDir}/${file.name}` })));
15 | }
16 | });
17 | });
18 | }
19 |
20 | export const fetchFileContent = (file: string): Promise => {
21 | return new Promise((resolve, reject) => {
22 | fs.readFile(file, "utf8", (err, data) => {
23 | if (err) {
24 | reject(err);
25 | } else {
26 | resolve(data);
27 | }
28 | });
29 | })
30 | }
31 |
32 | export const saveFile = async (file: string, content: string): Promise => {
33 | return new Promise((resolve, reject) => {
34 | fs.writeFile(file, content, "utf8", (err) => {
35 | if (err) {
36 | return reject(err);
37 | }
38 | resolve();
39 | });
40 | });
41 | }
--------------------------------------------------------------------------------
/good-code/runner/src/fs.ts:
--------------------------------------------------------------------------------
1 | import fs from "fs";
2 |
3 | interface File {
4 | type: "file" | "dir";
5 | name: string;
6 | }
7 |
8 | export const fetchDir = (dir: string, baseDir: string): Promise => {
9 | return new Promise((resolve, reject) => {
10 | fs.readdir(dir, { withFileTypes: true }, (err, files) => {
11 | if (err) {
12 | reject(err);
13 | } else {
14 | resolve(files.map(file => ({ type: file.isDirectory() ? "dir" : "file", name: file.name, path: `${baseDir}/${file.name}` })));
15 | }
16 | });
17 | });
18 | }
19 |
20 | export const fetchFileContent = (file: string): Promise => {
21 | return new Promise((resolve, reject) => {
22 | fs.readFile(file, "utf8", (err, data) => {
23 | if (err) {
24 | reject(err);
25 | } else {
26 | resolve(data);
27 | }
28 | });
29 | })
30 | }
31 |
32 | export const saveFile = async (file: string, content: string): Promise => {
33 | return new Promise((resolve, reject) => {
34 | fs.writeFile(file, content, "utf8", (err) => {
35 | if (err) {
36 | return reject(err);
37 | }
38 | resolve();
39 | });
40 | });
41 | }
--------------------------------------------------------------------------------
/bad-code/frontend/src/components/external/editor/components/icon.tsx:
--------------------------------------------------------------------------------
1 | import React, {ReactNode} from 'react'
2 | import {SiHtml5, SiCss3, SiJavascript, SiTypescript, SiJson} from "react-icons/si";
3 | import {FcFolder, FcOpenedFolder, FcPicture, FcFile} from "react-icons/fc";
4 | import {AiFillFileText} from "react-icons/ai";
5 |
6 | function getIconHelper() {
7 | const cache = new Map();
8 | cache.set("js", );
9 | cache.set("jsx", );
10 | cache.set("ts", );
11 | cache.set("tsx", );
12 | cache.set("css", );
13 | cache.set("json", );
14 | cache.set("html", );
15 | cache.set("png", );
16 | cache.set("jpg", );
17 | cache.set("ico", );
18 | cache.set("txt", );
19 | cache.set("closedDirectory", );
20 | cache.set("openDirectory", );
21 | return function (extension: string, name: string): ReactNode {
22 | if (cache.has(extension))
23 | return cache.get(extension);
24 | else if (cache.has(name))
25 | return cache.get(name);
26 | else
27 | return ;
28 | }
29 | }
30 |
31 | export const getIcon = getIconHelper();
32 |
--------------------------------------------------------------------------------
/good-code/frontend/src/components/external/editor/components/icon.tsx:
--------------------------------------------------------------------------------
1 | import React, {ReactNode} from 'react'
2 | import {SiHtml5, SiCss3, SiJavascript, SiTypescript, SiJson} from "react-icons/si";
3 | import {FcFolder, FcOpenedFolder, FcPicture, FcFile} from "react-icons/fc";
4 | import {AiFillFileText} from "react-icons/ai";
5 |
6 | function getIconHelper() {
7 | const cache = new Map();
8 | cache.set("js", );
9 | cache.set("jsx", );
10 | cache.set("ts", );
11 | cache.set("tsx", );
12 | cache.set("css", );
13 | cache.set("json", );
14 | cache.set("html", );
15 | cache.set("png", );
16 | cache.set("jpg", );
17 | cache.set("ico", );
18 | cache.set("txt", );
19 | cache.set("closedDirectory", );
20 | cache.set("openDirectory", );
21 | return function (extension: string, name: string): ReactNode {
22 | if (cache.has(extension))
23 | return cache.get(extension);
24 | else if (cache.has(name))
25 | return cache.get(name);
26 | else
27 | return ;
28 | }
29 | }
30 |
31 | export const getIcon = getIconHelper();
32 |
--------------------------------------------------------------------------------
/bad-code/frontend/README.md:
--------------------------------------------------------------------------------
1 | # React + TypeScript + Vite
2 |
3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4 |
5 | Currently, two official plugins are available:
6 |
7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9 |
10 | ## Expanding the ESLint configuration
11 |
12 | If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
13 |
14 | - Configure the top-level `parserOptions` property like this:
15 |
16 | ```js
17 | export default {
18 | // other rules...
19 | parserOptions: {
20 | ecmaVersion: 'latest',
21 | sourceType: 'module',
22 | project: ['./tsconfig.json', './tsconfig.node.json'],
23 | tsconfigRootDir: __dirname,
24 | },
25 | }
26 | ```
27 |
28 | - Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
29 | - Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
30 | - Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
31 |
--------------------------------------------------------------------------------
/bad-code/frontend/src/components/external/editor/editor/code.tsx:
--------------------------------------------------------------------------------
1 | import Editor from "@monaco-editor/react";
2 | import { File } from "../utils/file-manager";
3 | import { Socket } from "socket.io-client";
4 |
5 | export const Code = ({ selectedFile, socket }: { selectedFile: File | undefined, socket: Socket }) => {
6 | if (!selectedFile)
7 | return null
8 |
9 | const code = selectedFile.content
10 | let language = selectedFile.name.split('.').pop()
11 |
12 | if (language === "js" || language === "jsx")
13 | language = "javascript";
14 | else if (language === "ts" || language === "tsx")
15 | language = "typescript"
16 | else if (language === "py" )
17 | language = "python"
18 |
19 | function debounce(func: (value: string) => void, wait: number) {
20 | let timeout: number;
21 | return (value: string) => {
22 | clearTimeout(timeout);
23 | timeout = setTimeout(() => {
24 | func(value);
25 | }, wait);
26 | };
27 | }
28 |
29 | return (
30 | {
36 | // Should send diffs, for now sending the whole file
37 | // PR and win a bounty!
38 | socket.emit("updateContent", { path: selectedFile.path, content: value });
39 | }, 500)}
40 | />
41 | )
42 | }
43 |
--------------------------------------------------------------------------------
/good-code/frontend/README.md:
--------------------------------------------------------------------------------
1 | # React + TypeScript + Vite
2 |
3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4 |
5 | Currently, two official plugins are available:
6 |
7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9 |
10 | ## Expanding the ESLint configuration
11 |
12 | If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
13 |
14 | - Configure the top-level `parserOptions` property like this:
15 |
16 | ```js
17 | export default {
18 | // other rules...
19 | parserOptions: {
20 | ecmaVersion: 'latest',
21 | sourceType: 'module',
22 | project: ['./tsconfig.json', './tsconfig.node.json'],
23 | tsconfigRootDir: __dirname,
24 | },
25 | }
26 | ```
27 |
28 | - Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
29 | - Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
30 | - Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
31 |
--------------------------------------------------------------------------------
/good-code/frontend/src/components/external/editor/editor/code.tsx:
--------------------------------------------------------------------------------
1 | import Editor from "@monaco-editor/react";
2 | import { File } from "../utils/file-manager";
3 | import { Socket } from "socket.io-client";
4 |
5 | export const Code = ({ selectedFile, socket }: { selectedFile: File | undefined, socket: Socket }) => {
6 | if (!selectedFile)
7 | return null
8 |
9 | const code = selectedFile.content
10 | let language = selectedFile.name.split('.').pop()
11 |
12 | if (language === "js" || language === "jsx")
13 | language = "javascript";
14 | else if (language === "ts" || language === "tsx")
15 | language = "typescript"
16 | else if (language === "py" )
17 | language = "python"
18 |
19 | function debounce(func: (value: string) => void, wait: number) {
20 | let timeout: number;
21 | return (value: string) => {
22 | clearTimeout(timeout);
23 | timeout = setTimeout(() => {
24 | func(value);
25 | }, wait);
26 | };
27 | }
28 |
29 | return (
30 | {
36 | // Should send diffs, for now sending the whole file
37 | // PR and win a bounty!
38 | socket.emit("updateContent", { path: selectedFile.path, content: value });
39 | }, 500)}
40 | />
41 | )
42 | }
43 |
--------------------------------------------------------------------------------
/bad-code/frontend/src/components/Editor.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useMemo, useState } from "react";
2 | import Sidebar from "./external/editor/components/sidebar";
3 | import { Code } from "./external/editor/editor/code";
4 | import styled from "@emotion/styled";
5 | import { File, buildFileTree, RemoteFile } from "./external/editor/utils/file-manager";
6 | import { FileTree } from "./external/editor/components/file-tree";
7 | import { Socket } from "socket.io-client";
8 |
9 | // credits - https://codesandbox.io/s/monaco-tree-pec7u
10 | export const Editor = ({
11 | files,
12 | onSelect,
13 | selectedFile,
14 | socket
15 | }: {
16 | files: RemoteFile[];
17 | onSelect: (file: File) => void;
18 | selectedFile: File | undefined;
19 | socket: Socket;
20 | }) => {
21 | const rootDir = useMemo(() => {
22 | return buildFileTree(files);
23 | }, [files]);
24 |
25 | useEffect(() => {
26 | if (!selectedFile) {
27 | onSelect(rootDir.files[0])
28 | }
29 | }, [selectedFile])
30 |
31 | return (
32 |
33 |
34 |
35 |
40 |
41 |
42 |
43 |
44 | );
45 | };
46 |
47 | const Main = styled.main`
48 | display: flex;
49 | `;
--------------------------------------------------------------------------------
/good-code/frontend/src/components/Editor.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useMemo, useState } from "react";
2 | import Sidebar from "./external/editor/components/sidebar";
3 | import { Code } from "./external/editor/editor/code";
4 | import styled from "@emotion/styled";
5 | import { File, buildFileTree, RemoteFile } from "./external/editor/utils/file-manager";
6 | import { FileTree } from "./external/editor/components/file-tree";
7 | import { Socket } from "socket.io-client";
8 |
9 | // credits - https://codesandbox.io/s/monaco-tree-pec7u
10 | export const Editor = ({
11 | files,
12 | onSelect,
13 | selectedFile,
14 | socket
15 | }: {
16 | files: RemoteFile[];
17 | onSelect: (file: File) => void;
18 | selectedFile: File | undefined;
19 | socket: Socket;
20 | }) => {
21 | const rootDir = useMemo(() => {
22 | return buildFileTree(files);
23 | }, [files]);
24 |
25 | useEffect(() => {
26 | if (!selectedFile) {
27 | onSelect(rootDir.files[0])
28 | }
29 | }, [selectedFile])
30 |
31 | return (
32 |
33 |
34 |
35 |
40 |
41 |
42 |
43 |
44 | );
45 | };
46 |
47 | const Main = styled.main`
48 | display: flex;
49 | `;
--------------------------------------------------------------------------------
/bad-code/frontend/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/good-code/frontend/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/good-code/frontend/src/components/Terminal.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef } from "react"
2 | import { Socket } from "socket.io-client";
3 | import { Terminal } from "xterm";
4 | import { FitAddon } from 'xterm-addon-fit';
5 | const fitAddon = new FitAddon();
6 |
7 | function ab2str(buf: string) {
8 | return String.fromCharCode.apply(null, new Uint8Array(buf));
9 | }
10 |
11 | const OPTIONS_TERM = {
12 | useStyle: true,
13 | screenKeys: true,
14 | cursorBlink: true,
15 | cols: 200,
16 | theme: {
17 | background: "black"
18 | }
19 | };
20 | export const TerminalComponent = ({ socket }: {socket: Socket}) => {
21 | const terminalRef = useRef();
22 |
23 | useEffect(() => {
24 | if (!terminalRef || !terminalRef.current || !socket) {
25 | return;
26 | }
27 |
28 | socket.emit("requestTerminal");
29 | socket.on("terminal", terminalHandler)
30 | const term = new Terminal(OPTIONS_TERM)
31 | term.loadAddon(fitAddon);
32 | term.open(terminalRef.current);
33 | fitAddon.fit();
34 | function terminalHandler({ data }) {
35 | if (data instanceof ArrayBuffer) {
36 | console.error(data);
37 | console.log(ab2str(data))
38 | term.write(ab2str(data))
39 | }
40 | }
41 | term.onData((data) => {
42 | socket.emit('terminalData', {
43 | data
44 | });
45 | });
46 |
47 | socket.emit('terminalData', {
48 | data: '\n'
49 | });
50 |
51 | return () => {
52 | socket.off("terminal")
53 | }
54 | }, [terminalRef]);
55 |
56 | return
57 |
58 |
59 | }
--------------------------------------------------------------------------------
/bad-code/frontend/src/components/Terminal.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef } from "react"
2 | import { Socket } from "socket.io-client";
3 | import { Terminal } from "xterm";
4 | import { FitAddon } from 'xterm-addon-fit';
5 | const fitAddon = new FitAddon();
6 |
7 | function ab2str(buf: string) {
8 | return String.fromCharCode.apply(null, new Uint8Array(buf));
9 | }
10 |
11 | const OPTIONS_TERM = {
12 | useStyle: true,
13 | screenKeys: true,
14 | cursorBlink: true,
15 | cols: 200,
16 | theme: {
17 | background: "black"
18 | }
19 | };
20 | export const TerminalComponent = ({ socket }: {socket: Socket}) => {
21 | const terminalRef = useRef();
22 |
23 | useEffect(() => {
24 | if (!terminalRef || !terminalRef.current || !socket) {
25 | return;
26 | }
27 |
28 | socket.emit("requestTerminal");
29 | socket.on("terminal", terminalHandler)
30 | const term = new Terminal(OPTIONS_TERM)
31 | term.loadAddon(fitAddon);
32 | term.open(terminalRef.current);
33 | fitAddon.fit();
34 | function terminalHandler({ data }) {
35 | if (data instanceof ArrayBuffer) {
36 | console.error(data);
37 | console.log(ab2str(data))
38 | term.write(ab2str(data))
39 | }
40 | }
41 | term.onData((data) => {
42 | console.log(data);
43 | socket.emit('terminalData', {
44 | data
45 | });
46 | });
47 |
48 | socket.emit('terminalData', {
49 | data: '\n'
50 | });
51 |
52 | return () => {
53 | socket.off("terminal")
54 | }
55 | }, [terminalRef]);
56 |
57 | return
58 |
59 |
60 | }
--------------------------------------------------------------------------------
/good-code/init-service/src/aws.ts:
--------------------------------------------------------------------------------
1 | import { S3 } from "aws-sdk"
2 | import fs from "fs";
3 | import path from "path";
4 |
5 | const s3 = new S3({
6 | accessKeyId: process.env.AWS_ACCESS_KEY_ID,
7 | secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
8 | endpoint: process.env.S3_ENDPOINT
9 | })
10 |
11 | export async function copyS3Folder(sourcePrefix: string, destinationPrefix: string, continuationToken?: string): Promise {
12 | try {
13 | // List all objects in the source folder
14 | const listParams = {
15 | Bucket: process.env.S3_BUCKET ?? "",
16 | Prefix: sourcePrefix,
17 | ContinuationToken: continuationToken
18 | };
19 |
20 | const listedObjects = await s3.listObjectsV2(listParams).promise();
21 |
22 | if (!listedObjects.Contents || listedObjects.Contents.length === 0) return;
23 |
24 | // Copy each object to the new location
25 | // We're doing it parallely here, using promise.all()
26 | await Promise.all(listedObjects.Contents.map(async (object) => {
27 | if (!object.Key) return;
28 | let destinationKey = object.Key.replace(sourcePrefix, destinationPrefix);
29 | let copyParams = {
30 | Bucket: process.env.S3_BUCKET ?? "",
31 | CopySource: `${process.env.S3_BUCKET}/${object.Key}`,
32 | Key: destinationKey
33 | };
34 |
35 | console.log(copyParams);
36 |
37 | await s3.copyObject(copyParams).promise();
38 | console.log(`Copied ${object.Key} to ${destinationKey}`);
39 | }));
40 |
41 | // Check if the list was truncated and continue copying if necessary
42 | if (listedObjects.IsTruncated) {
43 | listParams.ContinuationToken = listedObjects.NextContinuationToken;
44 | await copyS3Folder(sourcePrefix, destinationPrefix, continuationToken);
45 | }
46 | } catch (error) {
47 | console.error('Error copying folder:', error);
48 | }
49 | }
50 |
51 | export const saveToS3 = async (key: string, filePath: string, content: string): Promise => {
52 | const params = {
53 | Bucket: process.env.S3_BUCKET ?? "",
54 | Key: `${key}${filePath}`,
55 | Body: content
56 | }
57 |
58 | await s3.putObject(params).promise()
59 | }
--------------------------------------------------------------------------------
/good-code/orchestrator-simple/service.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: service_name
5 | labels:
6 | app: service_name
7 | spec:
8 | replicas: 1
9 | selector:
10 | matchLabels:
11 | app: service_name
12 | template:
13 | metadata:
14 | labels:
15 | app: service_name
16 | spec:
17 | volumes:
18 | - name: workspace-volume
19 | emptyDir: {}
20 | initContainers:
21 | - name: copy-s3-resources
22 | image: amazon/aws-cli
23 | command: ["/bin/sh", "-c"]
24 | args:
25 | - >
26 | aws s3 cp s3://repl/code/service_name/ /workspace/ --recursive &&
27 | echo "Resources copied from S3";
28 | env:
29 | - name: AWS_ACCESS_KEY_ID
30 | value: "your_aws_key_id"
31 | - name: AWS_SECRET_ACCESS_KEY
32 | value: "your_aws_secret"
33 | volumeMounts:
34 | - name: workspace-volume
35 | mountPath: /workspace
36 | containers:
37 | - name: runner
38 | image: 100xdevs/runner:latest
39 | ports:
40 | - containerPort: 3001
41 | - containerPort: 3000
42 | volumeMounts:
43 | - name: workspace-volume
44 | mountPath: /workspace
45 | resources:
46 | # Bounty $25 Use ephemeral-storage to add space limits here
47 | requests:
48 | cpu: "1"
49 | memory: "1Gi"
50 | limits:
51 | cpu: "1"
52 | memory: "1Gi"
53 |
54 | ---
55 | apiVersion: v1
56 | kind: Service
57 | metadata:
58 | name: service_name
59 | spec:
60 | selector:
61 | app: service_name
62 | ports:
63 | - protocol: TCP
64 | name: ws
65 | port: 3001
66 | targetPort: 3001
67 | - protocol: TCP
68 | name: user
69 | port: 3000
70 | targetPort: 3000
71 | ---
72 | apiVersion: networking.k8s.io/v1
73 | kind: Ingress
74 | metadata:
75 | name: service_name
76 | spec:
77 | ingressClassName: nginx
78 | rules:
79 | - host: service_name.peetcode.com
80 | http:
81 | paths:
82 | - path: /
83 | pathType: Prefix
84 | backend:
85 | service:
86 | name: service_name
87 | port:
88 | number: 3001
89 | - host: service_name.autogpt-cloud.com
90 | http:
91 | paths:
92 | - path: /
93 | pathType: Prefix
94 | backend:
95 | service:
96 | name: service_name
97 | port:
98 | number: 3000
99 |
--------------------------------------------------------------------------------
/good-code/orchestrator-simple/src/index.ts:
--------------------------------------------------------------------------------
1 | import express from "express";
2 | import fs from "fs";
3 | import yaml from "yaml";
4 | import path from "path";
5 | import cors from "cors";
6 | import { KubeConfig, AppsV1Api, CoreV1Api, NetworkingV1Api } from "@kubernetes/client-node";
7 |
8 | const app = express();
9 | app.use(express.json());
10 | app.use(cors());
11 |
12 | const kubeconfig = new KubeConfig();
13 | kubeconfig.loadFromDefault();
14 | const coreV1Api = kubeconfig.makeApiClient(CoreV1Api);
15 | const appsV1Api = kubeconfig.makeApiClient(AppsV1Api);
16 | const networkingV1Api = kubeconfig.makeApiClient(NetworkingV1Api);
17 |
18 | // Updated utility function to handle multi-document YAML files
19 | const readAndParseKubeYaml = (filePath: string, replId: string): Array => {
20 | const fileContent = fs.readFileSync(filePath, 'utf8');
21 | const docs = yaml.parseAllDocuments(fileContent).map((doc) => {
22 | let docString = doc.toString();
23 | const regex = new RegExp(`service_name`, 'g');
24 | docString = docString.replace(regex, replId);
25 | console.log(docString);
26 | return yaml.parse(docString);
27 | });
28 | return docs;
29 | };
30 |
31 | app.post("/start", async (req, res) => {
32 | const { userId, replId } = req.body; // Assume a unique identifier for each user
33 | const namespace = "default"; // Assuming a default namespace, adjust as needed
34 |
35 | try {
36 | const kubeManifests = readAndParseKubeYaml(path.join(__dirname, "../service.yaml"), replId);
37 | for (const manifest of kubeManifests) {
38 | switch (manifest.kind) {
39 | case "Deployment":
40 | await appsV1Api.createNamespacedDeployment(namespace, manifest);
41 | break;
42 | case "Service":
43 | await coreV1Api.createNamespacedService(namespace, manifest);
44 | break;
45 | case "Ingress":
46 | await networkingV1Api.createNamespacedIngress(namespace, manifest);
47 | break;
48 | default:
49 | console.log(`Unsupported kind: ${manifest.kind}`);
50 | }
51 | }
52 | res.status(200).send({ message: "Resources created successfully" });
53 | } catch (error) {
54 | console.error("Failed to create resources", error);
55 | res.status(500).send({ message: "Failed to create resources" });
56 | }
57 | });
58 |
59 | const port = process.env.PORT || 3002;
60 | app.listen(port, () => {
61 | console.log(`Listening on port: ${port}`);
62 | });
63 |
--------------------------------------------------------------------------------
/bad-code/frontend/src/components/Landing.tsx:
--------------------------------------------------------------------------------
1 | /** Import necessary libraries */
2 | import axios from 'axios';
3 | import { useState } from 'react';
4 | import { useNavigate } from 'react-router-dom';
5 | import styled from '@emotion/styled';
6 |
7 | /** Constants */
8 | const SLUG_WORKS = ["car", "dog", "computer", "person", "inside", "word", "for", "please", "to", "cool", "open", "source"];
9 | const SERVICE_URL = "http://localhost:3001";
10 |
11 | /** Styled components */
12 | const Container = styled.div`
13 | padding: 20px;
14 | display: flex;
15 | flex-direction: column;
16 | align-items: center;
17 | `;
18 |
19 | const Title = styled.h1`
20 | color: white;
21 | `;
22 |
23 | const StyledInput = styled.input`
24 | margin: 10px 0;
25 | padding: 10px;
26 | border: 1px solid #ccc;
27 | border-radius: 5px;
28 | `;
29 |
30 | const StyledSelect = styled.select`
31 | margin: 10px 0;
32 | padding: 10px;
33 | border: 1px solid #ccc;
34 | border-radius: 5px;
35 | `;
36 |
37 | const StyledButton = styled.button`
38 | padding: 10px 20px;
39 | background-color: #007bff;
40 | color: white;
41 | border: none;
42 | border-radius: 5px;
43 | cursor: pointer;
44 | &:hover {
45 | background-color: #0056b3;
46 | }
47 | `;
48 |
49 | /** Helper function */
50 | function getRandomSlug() {
51 | let slug = "";
52 | for (let i = 0; i < 3; i++) {
53 | slug += SLUG_WORKS[Math.floor(Math.random() * SLUG_WORKS.length)];
54 | }
55 | return slug;
56 | }
57 |
58 | /** Component */
59 | export const Landing = () => {
60 | const [language, setLanguage] = useState("node-js");
61 | const [replId, setReplId] = useState(getRandomSlug());
62 | const [loading, setLoading] = useState(false);
63 | const navigate = useNavigate();
64 |
65 | return (
66 |
67 | Lepl lit
68 | setReplId(e.target.value)}
70 | type="text"
71 | placeholder="Repl ID"
72 | value={replId}
73 | />
74 | setLanguage(e.target.value)}
78 | >
79 |
80 |
81 |
82 | {
83 | setLoading(true);
84 | await axios.post(`${SERVICE_URL}/project`, { replId, language });
85 | setLoading(false);
86 | navigate(`/coding/?replId=${replId}`)
87 | }}>{loading ? "Starting ..." : "Start Coding"}
88 |
89 | );
90 | }
91 |
--------------------------------------------------------------------------------
/good-code/frontend/src/components/Landing.tsx:
--------------------------------------------------------------------------------
1 | /** Import necessary libraries */
2 | import axios from 'axios';
3 | import { useState } from 'react';
4 | import { useNavigate } from 'react-router-dom';
5 | import styled from '@emotion/styled';
6 |
7 | /** Constants */
8 | const SLUG_WORKS = ["car", "dog", "computer", "person", "inside", "word", "for", "please", "to", "cool", "open", "source"];
9 | const SERVICE_URL = "http://localhost:3001";
10 |
11 | /** Styled components */
12 | const Container = styled.div`
13 | padding: 20px;
14 | display: flex;
15 | flex-direction: column;
16 | align-items: center;
17 | `;
18 |
19 | const Title = styled.h1`
20 | color: white;
21 | `;
22 |
23 | const StyledInput = styled.input`
24 | margin: 10px 0;
25 | padding: 10px;
26 | border: 1px solid #ccc;
27 | border-radius: 5px;
28 | `;
29 |
30 | const StyledSelect = styled.select`
31 | margin: 10px 0;
32 | padding: 10px;
33 | border: 1px solid #ccc;
34 | border-radius: 5px;
35 | `;
36 |
37 | const StyledButton = styled.button`
38 | padding: 10px 20px;
39 | background-color: #007bff;
40 | color: white;
41 | border: none;
42 | border-radius: 5px;
43 | cursor: pointer;
44 | &:hover {
45 | background-color: #0056b3;
46 | }
47 | `;
48 |
49 | /** Helper function */
50 | function getRandomSlug() {
51 | let slug = "";
52 | for (let i = 0; i < 3; i++) {
53 | slug += SLUG_WORKS[Math.floor(Math.random() * SLUG_WORKS.length)];
54 | }
55 | return slug;
56 | }
57 |
58 | /** Component */
59 | export const Landing = () => {
60 | const [language, setLanguage] = useState("node-js");
61 | const [replId, setReplId] = useState(getRandomSlug());
62 | const [loading, setLoading] = useState(false);
63 | const navigate = useNavigate();
64 |
65 | return (
66 |
67 | Lepl lit
68 | setReplId(e.target.value)}
70 | type="text"
71 | placeholder="Repl ID"
72 | value={replId}
73 | />
74 | setLanguage(e.target.value)}
78 | >
79 |
80 |
81 |
82 | {
83 | setLoading(true);
84 | await axios.post(`${SERVICE_URL}/project`, { replId, language });
85 | setLoading(false);
86 | navigate(`/coding/?replId=${replId}`)
87 | }}>{loading ? "Starting ..." : "Start Coding"}
88 |
89 | );
90 | }
91 |
--------------------------------------------------------------------------------
/good-code/runner/src/ws.ts:
--------------------------------------------------------------------------------
1 | import { Server, Socket } from "socket.io";
2 | import { Server as HttpServer } from "http";
3 | import { saveToS3 } from "./aws";
4 | import path from "path";
5 | import { fetchDir, fetchFileContent, saveFile } from "./fs";
6 | import { TerminalManager } from "./pty";
7 |
8 | const terminalManager = new TerminalManager();
9 |
10 | export function initWs(httpServer: HttpServer) {
11 | const io = new Server(httpServer, {
12 | cors: {
13 | // Should restrict this more!
14 | origin: "*",
15 | methods: ["GET", "POST"],
16 | },
17 | });
18 |
19 | io.on("connection", async (socket) => {
20 | // Auth checks should happen here
21 | const host = socket.handshake.headers.host;
22 | console.log(`host is ${host}`);
23 | // Split the host by '.' and take the first part as replId
24 | const replId = host?.split('.')[0];
25 |
26 | if (!replId) {
27 | socket.disconnect();
28 | terminalManager.clear(socket.id);
29 | return;
30 | }
31 |
32 | socket.emit("loaded", {
33 | rootContent: await fetchDir("/workspace", "")
34 | });
35 |
36 | initHandlers(socket, replId);
37 | });
38 | }
39 |
40 | function initHandlers(socket: Socket, replId: string) {
41 |
42 | socket.on("disconnect", () => {
43 | console.log("user disconnected");
44 | });
45 |
46 | socket.on("fetchDir", async (dir: string, callback) => {
47 | const dirPath = `/workspace/${dir}`;
48 | const contents = await fetchDir(dirPath, dir);
49 | callback(contents);
50 | });
51 |
52 | socket.on("fetchContent", async ({ path: filePath }: { path: string }, callback) => {
53 | const fullPath = `/workspace/${filePath}`;
54 | const data = await fetchFileContent(fullPath);
55 | callback(data);
56 | });
57 |
58 | // TODO: contents should be diff, not full file
59 | // Should be validated for size
60 | // Should be throttled before updating S3 (or use an S3 mount)
61 | socket.on("updateContent", async ({ path: filePath, content }: { path: string, content: string }) => {
62 | const fullPath = `/workspace/${filePath}`;
63 | await saveFile(fullPath, content);
64 | await saveToS3(`code/${replId}`, filePath, content);
65 | });
66 |
67 | socket.on("requestTerminal", async () => {
68 | terminalManager.createPty(socket.id, replId, (data, id) => {
69 | socket.emit('terminal', {
70 | data: Buffer.from(data,"utf-8")
71 | });
72 | });
73 | });
74 |
75 | socket.on("terminalData", async ({ data }: { data: string, terminalId: number }) => {
76 | terminalManager.write(socket.id, data);
77 | });
78 |
79 | }
--------------------------------------------------------------------------------
/bad-code/backend/src/ws.ts:
--------------------------------------------------------------------------------
1 | import { Server, Socket } from "socket.io";
2 | import { Server as HttpServer } from "http";
3 | import { fetchS3Folder, saveToS3 } from "./aws";
4 | import path from "path";
5 | import { fetchDir, fetchFileContent, saveFile } from "./fs";
6 | import { TerminalManager } from "./pty";
7 |
8 | const terminalManager = new TerminalManager();
9 |
10 | export function initWs(httpServer: HttpServer) {
11 | const io = new Server(httpServer, {
12 | cors: {
13 | // Should restrict this more!
14 | origin: "*",
15 | methods: ["GET", "POST"],
16 | },
17 | });
18 |
19 | io.on("connection", async (socket) => {
20 | // Auth checks should happen here
21 | const replId = socket.handshake.query.roomId as string;
22 |
23 | if (!replId) {
24 | socket.disconnect();
25 | terminalManager.clear(socket.id);
26 | return;
27 | }
28 |
29 | await fetchS3Folder(`code/${replId}`, path.join(__dirname, `../tmp/${replId}`));
30 | socket.emit("loaded", {
31 | rootContent: await fetchDir(path.join(__dirname, `../tmp/${replId}`), "")
32 | });
33 |
34 | initHandlers(socket, replId);
35 | });
36 | }
37 |
38 | function initHandlers(socket: Socket, replId: string) {
39 |
40 | socket.on("disconnect", () => {
41 | console.log("user disconnected");
42 | });
43 |
44 | socket.on("fetchDir", async (dir: string, callback) => {
45 | const dirPath = path.join(__dirname, `../tmp/${replId}/${dir}`);
46 | const contents = await fetchDir(dirPath, dir);
47 | callback(contents);
48 | });
49 |
50 | socket.on("fetchContent", async ({ path: filePath }: { path: string }, callback) => {
51 | const fullPath = path.join(__dirname, `../tmp/${replId}/${filePath}`);
52 | const data = await fetchFileContent(fullPath);
53 | callback(data);
54 | });
55 |
56 | // TODO: contents should be diff, not full file
57 | // Should be validated for size
58 | // Should be throttled before updating S3 (or use an S3 mount)
59 | socket.on("updateContent", async ({ path: filePath, content }: { path: string, content: string }) => {
60 | const fullPath = path.join(__dirname, `../tmp/${replId}/${filePath}`);
61 | await saveFile(fullPath, content);
62 | await saveToS3(`code/${replId}`, filePath, content);
63 | });
64 |
65 | socket.on("requestTerminal", async () => {
66 | terminalManager.createPty(socket.id, replId, (data, id) => {
67 | socket.emit('terminal', {
68 | data: Buffer.from(data,"utf-8")
69 | });
70 | });
71 | });
72 |
73 | socket.on("terminalData", async ({ data }: { data: string, terminalId: number }) => {
74 | terminalManager.write(socket.id, data);
75 | });
76 |
77 | }
--------------------------------------------------------------------------------
/bad-code/frontend/src/components/CodingPage.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react';
2 | import { Editor } from './Editor';
3 | import { File, RemoteFile, Type } from './external/editor/utils/file-manager';
4 | import { useSearchParams } from 'react-router-dom';
5 | import styled from '@emotion/styled';
6 | import { Output } from './Output';
7 | import { TerminalComponent as Terminal } from './Terminal';
8 | import { Socket, io } from 'socket.io-client';
9 | import { EXECUTION_ENGINE_URI } from '../config';
10 |
11 | const Container = styled.div`
12 | display: flex;
13 | flex-direction: column;
14 | width: 100%;
15 | `;
16 |
17 | const ButtonContainer = styled.div`
18 | display: flex;
19 | justify-content: flex-end; /* Aligns children (button) to the right */
20 | padding: 10px; /* Adds some space around the button */
21 | `;
22 |
23 | const Workspace = styled.div`
24 | display: flex;
25 | margin: 0;
26 | font-size: 16px;
27 | width: 100%;
28 | `;
29 |
30 | const LeftPanel = styled.div`
31 | flex: 1;
32 | width: 60%;
33 | `;
34 |
35 | const RightPanel = styled.div`
36 | flex: 1;
37 | width: 40%;
38 | `;
39 |
40 | function useSocket(replId: string) {
41 | const [socket, setSocket] = useState(null);
42 |
43 | useEffect(() => {
44 | const newSocket = io(`${EXECUTION_ENGINE_URI}?roomId=${replId}`);
45 | setSocket(newSocket);
46 |
47 | return () => {
48 | newSocket.disconnect();
49 | };
50 | }, [replId]);
51 |
52 | return socket;
53 | }
54 |
55 | export const CodingPage = () => {
56 | const [searchParams] = useSearchParams();
57 | const replId = searchParams.get('replId') ?? '';
58 | const [loaded, setLoaded] = useState(false);
59 | const socket = useSocket(replId);
60 | const [fileStructure, setFileStructure] = useState([]);
61 | const [selectedFile, setSelectedFile] = useState(undefined);
62 | const [showOutput, setShowOutput] = useState(false);
63 |
64 | useEffect(() => {
65 | if (socket) {
66 | socket.on('loaded', ({ rootContent }: { rootContent: RemoteFile[]}) => {
67 | setLoaded(true);
68 | setFileStructure(rootContent);
69 | });
70 | }
71 | }, [socket]);
72 |
73 | const onSelect = (file: File) => {
74 | if (file.type === Type.DIRECTORY) {
75 | socket?.emit("fetchDir", file.path, (data: RemoteFile[]) => {
76 | setFileStructure(prev => {
77 | const allFiles = [...prev, ...data];
78 | return allFiles.filter((file, index, self) =>
79 | index === self.findIndex(f => f.path === file.path)
80 | );
81 | });
82 | });
83 |
84 | } else {
85 | socket?.emit("fetchContent", { path: file.path }, (data: string) => {
86 | file.content = data;
87 | setSelectedFile(file);
88 | });
89 | }
90 | };
91 |
92 | if (!loaded) {
93 | return "Loading...";
94 | }
95 |
96 | return (
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | {showOutput && }
107 |
108 |
109 |
110 |
111 | );
112 | }
113 |
--------------------------------------------------------------------------------
/bad-code/frontend/src/components/external/editor/utils/file-manager.tsx:
--------------------------------------------------------------------------------
1 | export enum Type {
2 | FILE,
3 | DIRECTORY,
4 | DUMMY
5 | }
6 |
7 | interface CommonProps {
8 | id: string; // 文件id
9 | type: Type; // 文件类型
10 | name: string; // 名称
11 | content?: string;
12 | path: string;
13 | parentId: string | undefined; // 父级目录,如果为根目录则undefined
14 | depth: number; // 文件深度
15 | }
16 |
17 | export interface File extends CommonProps {
18 |
19 | }
20 |
21 | export interface RemoteFile {
22 | type: "file" | "dir";
23 | name: string;
24 | path: string;
25 | }
26 |
27 | export interface Directory extends CommonProps {
28 | files: File[];
29 | dirs: Directory[];
30 | }
31 |
32 | /**
33 | * 构建文件树
34 | * @param data fetch获取的结果
35 | */
36 | export function buildFileTree(data: RemoteFile[]): Directory {
37 | const dirs = data.filter(x => x.type === "dir");
38 | const files = data.filter(x => x.type === "file");
39 | const cache = new Map(); // 缓存
40 | // 待构建的根目录
41 | let rootDir: Directory = {
42 | id: "root",
43 | name: "root",
44 | parentId: undefined,
45 | type: Type.DIRECTORY,
46 | path: "",
47 | depth: 0,
48 | dirs: [],
49 | files: []
50 | };
51 | // 将存入map
52 | dirs.forEach((item) => {
53 | let dir: Directory = {
54 | id: item.path,
55 | name: item.name,
56 | path: item.path,
57 | parentId: item.path.split("/").length === 2 ? "0" : dirs.find(x => x.path === item.path.split("/").slice(0, -1).join("/"))?.path,
58 | type: Type.DIRECTORY,
59 | depth: 0,
60 | dirs: [],
61 | files: []
62 | };
63 |
64 | cache.set(dir.id, dir);
65 | });
66 | // 将存入map
67 | files.forEach((item) => {
68 | let file: File = {
69 | id: item.path,
70 | name: item.name,
71 | path: item.path,
72 | parentId: item.path.split("/").length === 2 ? "0" : dirs.find(x => x.path === item.path.split("/").slice(0, -1).join("/"))?.path,
73 | type: Type.FILE,
74 | depth: 0
75 | };
76 | cache.set(file.id, file);
77 | });
78 | // 开始遍历构建文件树
79 | cache.forEach((value, key) => {
80 | // '0'表示文件或目录位于根目录
81 | if (value.parentId === "0") {
82 | if (value.type === Type.DIRECTORY) rootDir.dirs.push(value as Directory);
83 | else rootDir.files.push(value as File);
84 | } else {
85 | const parentDir = cache.get(value.parentId as string) as Directory;
86 | if (value.type === Type.DIRECTORY)
87 | parentDir.dirs.push(value as Directory);
88 | else parentDir.files.push(value as File);
89 | }
90 | });
91 |
92 | // 获取文件深度
93 | getDepth(rootDir, 0);
94 |
95 | return rootDir;
96 | }
97 |
98 | /**
99 | * 获取文件深度
100 | * @param rootDir 根目录
101 | * @param curDepth 当前深度
102 | */
103 | function getDepth(rootDir: Directory, curDepth: number) {
104 | rootDir.files.forEach((file) => {
105 | file.depth = curDepth + 1;
106 | });
107 | rootDir.dirs.forEach((dir) => {
108 | dir.depth = curDepth + 1;
109 | getDepth(dir, curDepth + 1);
110 | });
111 | }
112 |
113 | export function findFileByName(
114 | rootDir: Directory,
115 | filename: string
116 | ): File | undefined {
117 | let targetFile: File | undefined = undefined;
118 |
119 | function findFile(rootDir: Directory, filename: string) {
120 | rootDir.files.forEach((file) => {
121 | if (file.name === filename) {
122 | targetFile = file;
123 | return;
124 | }
125 | });
126 | rootDir.dirs.forEach((dir) => {
127 | findFile(dir, filename);
128 | });
129 | }
130 |
131 | findFile(rootDir, filename);
132 | return targetFile;
133 | }
134 |
135 | export function sortDir(l: Directory, r: Directory) {
136 | return l.name.localeCompare(r.name);
137 | }
138 |
139 | export function sortFile(l: File, r: File) {
140 | return l.name.localeCompare(r.name);
141 | }
142 |
--------------------------------------------------------------------------------
/good-code/frontend/src/components/external/editor/utils/file-manager.tsx:
--------------------------------------------------------------------------------
1 | export enum Type {
2 | FILE,
3 | DIRECTORY,
4 | DUMMY
5 | }
6 |
7 | interface CommonProps {
8 | id: string; // 文件id
9 | type: Type; // 文件类型
10 | name: string; // 名称
11 | content?: string;
12 | path: string;
13 | parentId: string | undefined; // 父级目录,如果为根目录则undefined
14 | depth: number; // 文件深度
15 | }
16 |
17 | export interface File extends CommonProps {
18 |
19 | }
20 |
21 | export interface RemoteFile {
22 | type: "file" | "dir";
23 | name: string;
24 | path: string;
25 | }
26 |
27 | export interface Directory extends CommonProps {
28 | files: File[];
29 | dirs: Directory[];
30 | }
31 |
32 | /**
33 | * 构建文件树
34 | * @param data fetch获取的结果
35 | */
36 | export function buildFileTree(data: RemoteFile[]): Directory {
37 | const dirs = data.filter(x => x.type === "dir");
38 | const files = data.filter(x => x.type === "file");
39 | const cache = new Map(); // 缓存
40 | // 待构建的根目录
41 | let rootDir: Directory = {
42 | id: "root",
43 | name: "root",
44 | parentId: undefined,
45 | type: Type.DIRECTORY,
46 | path: "",
47 | depth: 0,
48 | dirs: [],
49 | files: []
50 | };
51 | // 将存入map
52 | dirs.forEach((item) => {
53 | let dir: Directory = {
54 | id: item.path,
55 | name: item.name,
56 | path: item.path,
57 | parentId: item.path.split("/").length === 2 ? "0" : dirs.find(x => x.path === item.path.split("/").slice(0, -1).join("/"))?.path,
58 | type: Type.DIRECTORY,
59 | depth: 0,
60 | dirs: [],
61 | files: []
62 | };
63 |
64 | cache.set(dir.id, dir);
65 | });
66 | // 将存入map
67 | files.forEach((item) => {
68 | let file: File = {
69 | id: item.path,
70 | name: item.name,
71 | path: item.path,
72 | parentId: item.path.split("/").length === 2 ? "0" : dirs.find(x => x.path === item.path.split("/").slice(0, -1).join("/"))?.path,
73 | type: Type.FILE,
74 | depth: 0
75 | };
76 | cache.set(file.id, file);
77 | });
78 | // 开始遍历构建文件树
79 | cache.forEach((value, key) => {
80 | // '0'表示文件或目录位于根目录
81 | if (value.parentId === "0") {
82 | if (value.type === Type.DIRECTORY) rootDir.dirs.push(value as Directory);
83 | else rootDir.files.push(value as File);
84 | } else {
85 | const parentDir = cache.get(value.parentId as string) as Directory;
86 | if (value.type === Type.DIRECTORY)
87 | parentDir.dirs.push(value as Directory);
88 | else parentDir.files.push(value as File);
89 | }
90 | });
91 |
92 | // 获取文件深度
93 | getDepth(rootDir, 0);
94 |
95 | return rootDir;
96 | }
97 |
98 | /**
99 | * 获取文件深度
100 | * @param rootDir 根目录
101 | * @param curDepth 当前深度
102 | */
103 | function getDepth(rootDir: Directory, curDepth: number) {
104 | rootDir.files.forEach((file) => {
105 | file.depth = curDepth + 1;
106 | });
107 | rootDir.dirs.forEach((dir) => {
108 | dir.depth = curDepth + 1;
109 | getDepth(dir, curDepth + 1);
110 | });
111 | }
112 |
113 | export function findFileByName(
114 | rootDir: Directory,
115 | filename: string
116 | ): File | undefined {
117 | let targetFile: File | undefined = undefined;
118 |
119 | function findFile(rootDir: Directory, filename: string) {
120 | rootDir.files.forEach((file) => {
121 | if (file.name === filename) {
122 | targetFile = file;
123 | return;
124 | }
125 | });
126 | rootDir.dirs.forEach((dir) => {
127 | findFile(dir, filename);
128 | });
129 | }
130 |
131 | findFile(rootDir, filename);
132 | return targetFile;
133 | }
134 |
135 | export function sortDir(l: Directory, r: Directory) {
136 | return l.name.localeCompare(r.name);
137 | }
138 |
139 | export function sortFile(l: File, r: File) {
140 | return l.name.localeCompare(r.name);
141 | }
142 |
--------------------------------------------------------------------------------
/bad-code/frontend/src/assets/react.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/good-code/frontend/src/assets/react.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/good-code/runner/src/aws.ts:
--------------------------------------------------------------------------------
1 | import { S3 } from "aws-sdk"
2 | import fs from "fs";
3 | import path from "path";
4 |
5 | const s3 = new S3({
6 | accessKeyId: process.env.AWS_ACCESS_KEY_ID,
7 | secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
8 | endpoint: process.env.S3_ENDPOINT
9 | })
10 | export const fetchS3Folder = async (key: string, localPath: string): Promise => {
11 | const params = {
12 | Bucket: process.env.S3_BUCKET ?? "",
13 | Prefix: key
14 | }
15 |
16 | const response = await s3.listObjectsV2(params).promise()
17 | if (response.Contents) {
18 | for (const file of response.Contents) {
19 | const fileKey = file.Key
20 | if (fileKey) {
21 | const params = {
22 | Bucket: process.env.S3_BUCKET ?? "",
23 | Key: fileKey
24 | }
25 | const data = await s3.getObject(params).promise()
26 | if (data.Body) {
27 | const fileData = data.Body
28 | const filePath = `${localPath}/${fileKey.replace(key, "")}`
29 | //@ts-ignore
30 | await writeFile(filePath, fileData)
31 | }
32 | }
33 | }
34 | }
35 | }
36 |
37 | export async function copyS3Folder(sourcePrefix: string, destinationPrefix: string, continuationToken?: string): Promise {
38 | try {
39 | // List all objects in the source folder
40 | const listParams = {
41 | Bucket: process.env.S3_BUCKET ?? "",
42 | Prefix: sourcePrefix,
43 | ContinuationToken: continuationToken
44 | };
45 |
46 | const listedObjects = await s3.listObjectsV2(listParams).promise();
47 |
48 | if (!listedObjects.Contents || listedObjects.Contents.length === 0) return;
49 |
50 | // Copy each object to the new location
51 | for (const object of listedObjects.Contents) {
52 | if (!object.Key) continue;
53 | let destinationKey = object.Key.replace(sourcePrefix, destinationPrefix);
54 | let copyParams = {
55 | Bucket: process.env.S3_BUCKET ?? "",
56 | CopySource: `${process.env.S3_BUCKET}/${object.Key}`,
57 | Key: destinationKey
58 | };
59 | console.log(copyParams)
60 |
61 | await s3.copyObject(copyParams).promise();
62 | console.log(`Copied ${object.Key} to ${destinationKey}`);
63 | }
64 |
65 | // Check if the list was truncated and continue copying if necessary
66 | if (listedObjects.IsTruncated) {
67 | listParams.ContinuationToken = listedObjects.NextContinuationToken;
68 | await copyS3Folder(sourcePrefix, destinationPrefix, continuationToken);
69 | }
70 | } catch (error) {
71 | console.error('Error copying folder:', error);
72 | }
73 | }
74 |
75 | function writeFile(filePath: string, fileData: Buffer): Promise {
76 | return new Promise(async (resolve, reject) => {
77 | await createFolder(path.dirname(filePath));
78 |
79 | fs.writeFile(filePath, fileData, (err) => {
80 | if (err) {
81 | reject(err)
82 | } else {
83 | resolve()
84 | }
85 | })
86 | });
87 | }
88 |
89 | function createFolder(dirName: string) {
90 | return new Promise((resolve, reject) => {
91 | fs.mkdir(dirName, { recursive: true }, (err) => {
92 | if (err) {
93 | return reject(err)
94 | }
95 | resolve()
96 | });
97 | })
98 | }
99 |
100 | export const saveToS3 = async (key: string, filePath: string, content: string): Promise => {
101 | const params = {
102 | Bucket: process.env.S3_BUCKET ?? "",
103 | Key: `${key}${filePath}`,
104 | Body: content
105 | }
106 |
107 | await s3.putObject(params).promise()
108 | }
--------------------------------------------------------------------------------
/good-code/orchestrator-simple/src/aws.ts:
--------------------------------------------------------------------------------
1 | import { S3 } from "aws-sdk"
2 | import fs from "fs";
3 | import path from "path";
4 |
5 | const s3 = new S3({
6 | accessKeyId: process.env.AWS_ACCESS_KEY_ID,
7 | secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
8 | endpoint: process.env.S3_ENDPOINT
9 | })
10 | export const fetchS3Folder = async (key: string, localPath: string): Promise => {
11 | const params = {
12 | Bucket: process.env.S3_BUCKET ?? "",
13 | Prefix: key
14 | }
15 |
16 | const response = await s3.listObjectsV2(params).promise()
17 | if (response.Contents) {
18 | for (const file of response.Contents) {
19 | const fileKey = file.Key
20 | if (fileKey) {
21 | const params = {
22 | Bucket: process.env.S3_BUCKET ?? "",
23 | Key: fileKey
24 | }
25 | const data = await s3.getObject(params).promise()
26 | if (data.Body) {
27 | const fileData = data.Body
28 | const filePath = `${localPath}/${fileKey.replace(key, "")}`
29 | //@ts-ignore
30 | await writeFile(filePath, fileData)
31 | }
32 | }
33 | }
34 | }
35 | }
36 |
37 | export async function copyS3Folder(sourcePrefix: string, destinationPrefix: string, continuationToken?: string): Promise {
38 | try {
39 | // List all objects in the source folder
40 | const listParams = {
41 | Bucket: process.env.S3_BUCKET ?? "",
42 | Prefix: sourcePrefix,
43 | ContinuationToken: continuationToken
44 | };
45 |
46 | const listedObjects = await s3.listObjectsV2(listParams).promise();
47 |
48 | if (!listedObjects.Contents || listedObjects.Contents.length === 0) return;
49 |
50 | // Copy each object to the new location
51 | for (const object of listedObjects.Contents) {
52 | if (!object.Key) continue;
53 | let destinationKey = object.Key.replace(sourcePrefix, destinationPrefix);
54 | let copyParams = {
55 | Bucket: process.env.S3_BUCKET ?? "",
56 | CopySource: `${process.env.S3_BUCKET}/${object.Key}`,
57 | Key: destinationKey
58 | };
59 | console.log(copyParams)
60 |
61 | await s3.copyObject(copyParams).promise();
62 | console.log(`Copied ${object.Key} to ${destinationKey}`);
63 | }
64 |
65 | // Check if the list was truncated and continue copying if necessary
66 | if (listedObjects.IsTruncated) {
67 | listParams.ContinuationToken = listedObjects.NextContinuationToken;
68 | await copyS3Folder(sourcePrefix, destinationPrefix, continuationToken);
69 | }
70 | } catch (error) {
71 | console.error('Error copying folder:', error);
72 | }
73 | }
74 |
75 | function writeFile(filePath: string, fileData: Buffer): Promise {
76 | return new Promise(async (resolve, reject) => {
77 | await createFolder(path.dirname(filePath));
78 |
79 | fs.writeFile(filePath, fileData, (err) => {
80 | if (err) {
81 | reject(err)
82 | } else {
83 | resolve()
84 | }
85 | })
86 | });
87 | }
88 |
89 | function createFolder(dirName: string) {
90 | return new Promise((resolve, reject) => {
91 | fs.mkdir(dirName, { recursive: true }, (err) => {
92 | if (err) {
93 | return reject(err)
94 | }
95 | resolve()
96 | });
97 | })
98 | }
99 |
100 | export const saveToS3 = async (key: string, filePath: string, content: string): Promise => {
101 | const params = {
102 | Bucket: process.env.S3_BUCKET ?? "",
103 | Key: `${key}${filePath}`,
104 | Body: content
105 | }
106 |
107 | await s3.putObject(params).promise()
108 | }
--------------------------------------------------------------------------------
/good-code/frontend/src/components/CodingPage.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react';
2 | import { Socket, io } from 'socket.io-client';
3 | import { Editor } from './Editor';
4 | import { File, RemoteFile, Type } from './external/editor/utils/file-manager';
5 | import { useSearchParams } from 'react-router-dom';
6 | import styled from '@emotion/styled';
7 | import { Output } from './Output';
8 | import { TerminalComponent as Terminal } from './Terminal';
9 | import axios from 'axios';
10 |
11 | function useSocket(replId: string) {
12 | const [socket, setSocket] = useState(null);
13 |
14 | useEffect(() => {
15 | const newSocket = io(`ws://${replId}.peetcode.com`);
16 | setSocket(newSocket);
17 |
18 | return () => {
19 | newSocket.disconnect();
20 | };
21 | }, [replId]);
22 |
23 | return socket;
24 | }
25 |
26 | const Container = styled.div`
27 | display: flex;
28 | flex-direction: column;
29 | width: 100%;
30 | `;
31 |
32 | const ButtonContainer = styled.div`
33 | display: flex;
34 | justify-content: flex-end; /* Aligns children (button) to the right */
35 | padding: 10px; /* Adds some space around the button */
36 | `;
37 |
38 | const Workspace = styled.div`
39 | display: flex;
40 | margin: 0;
41 | font-size: 16px;
42 | width: 100%;
43 | `;
44 |
45 | const LeftPanel = styled.div`
46 | flex: 1;
47 | width: 60%;
48 | `;
49 |
50 | const RightPanel = styled.div`
51 | flex: 1;
52 | width: 40%;
53 | `;
54 |
55 |
56 | export const CodingPage = () => {
57 | const [podCreated, setPodCreated] = useState(false);
58 | const [searchParams] = useSearchParams();
59 | const replId = searchParams.get('replId') ?? '';
60 |
61 | useEffect(() => {
62 | if (replId) {
63 | axios.post(`http://localhost:3002/start`, { replId })
64 | .then(() => setPodCreated(true))
65 | .catch((err) => console.error(err));
66 | }
67 | }, []);
68 |
69 | if (!podCreated) {
70 | return <>Booting...>
71 | }
72 | return
73 |
74 | }
75 |
76 | export const CodingPagePostPodCreation = () => {
77 | const [searchParams] = useSearchParams();
78 | const replId = searchParams.get('replId') ?? '';
79 | const [loaded, setLoaded] = useState(false);
80 | const socket = useSocket(replId);
81 | const [fileStructure, setFileStructure] = useState([]);
82 | const [selectedFile, setSelectedFile] = useState(undefined);
83 | const [showOutput, setShowOutput] = useState(false);
84 |
85 | useEffect(() => {
86 | if (socket) {
87 | socket.on('loaded', ({ rootContent }: { rootContent: RemoteFile[]}) => {
88 | setLoaded(true);
89 | setFileStructure(rootContent);
90 | });
91 | }
92 | }, [socket]);
93 |
94 | const onSelect = (file: File) => {
95 | if (file.type === Type.DIRECTORY) {
96 | socket?.emit("fetchDir", file.path, (data: RemoteFile[]) => {
97 | setFileStructure(prev => {
98 | const allFiles = [...prev, ...data];
99 | return allFiles.filter((file, index, self) =>
100 | index === self.findIndex(f => f.path === file.path)
101 | );
102 | });
103 | });
104 | } else {
105 | socket?.emit("fetchContent", { path: file.path }, (data: string) => {
106 | file.content = data;
107 | setSelectedFile(file);
108 | });
109 | }
110 | };
111 |
112 | if (!loaded) {
113 | return "Loading...";
114 | }
115 |
116 | return (
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 | {showOutput && }
127 |
128 |
129 |
130 |
131 | );
132 | }
133 |
--------------------------------------------------------------------------------
/bad-code/backend/src/aws.ts:
--------------------------------------------------------------------------------
1 | import { S3 } from "aws-sdk"
2 | import fs from "fs";
3 | import path from "path";
4 |
5 | const s3 = new S3({
6 | accessKeyId: process.env.AWS_ACCESS_KEY_ID,
7 | secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
8 | endpoint: process.env.S3_ENDPOINT
9 | })
10 | export const fetchS3Folder = async (key: string, localPath: string): Promise => {
11 | try {
12 | const params = {
13 | Bucket: process.env.S3_BUCKET ?? "",
14 | Prefix: key
15 | };
16 |
17 | const response = await s3.listObjectsV2(params).promise();
18 | if (response.Contents) {
19 | // Use Promise.all to run getObject operations in parallel
20 | await Promise.all(response.Contents.map(async (file) => {
21 | const fileKey = file.Key;
22 | if (fileKey) {
23 | const getObjectParams = {
24 | Bucket: process.env.S3_BUCKET ?? "",
25 | Key: fileKey
26 | };
27 |
28 | const data = await s3.getObject(getObjectParams).promise();
29 | if (data.Body) {
30 | const fileData = data.Body;
31 | const filePath = `${localPath}/${fileKey.replace(key, "")}`;
32 |
33 | await writeFile(filePath, fileData);
34 |
35 | console.log(`Downloaded ${fileKey} to ${filePath}`);
36 | }
37 | }
38 | }));
39 | }
40 | } catch (error) {
41 | console.error('Error fetching folder:', error);
42 | }
43 | };
44 |
45 | export async function copyS3Folder(sourcePrefix: string, destinationPrefix: string, continuationToken?: string): Promise {
46 | try {
47 | // List all objects in the source folder
48 | const listParams = {
49 | Bucket: process.env.S3_BUCKET ?? "",
50 | Prefix: sourcePrefix,
51 | ContinuationToken: continuationToken
52 | };
53 |
54 | const listedObjects = await s3.listObjectsV2(listParams).promise();
55 |
56 | if (!listedObjects.Contents || listedObjects.Contents.length === 0) return;
57 |
58 | // Copy each object to the new location
59 | await Promise.all(listedObjects.Contents.map(async (object) => {
60 | if (!object.Key) return;
61 | let destinationKey = object.Key.replace(sourcePrefix, destinationPrefix);
62 | let copyParams = {
63 | Bucket: process.env.S3_BUCKET ?? "",
64 | CopySource: `${process.env.S3_BUCKET}/${object.Key}`,
65 | Key: destinationKey
66 | };
67 |
68 | console.log(copyParams);
69 |
70 | await s3.copyObject(copyParams).promise();
71 | console.log(`Copied ${object.Key} to ${destinationKey}`);
72 | }));
73 |
74 | // Check if the list was truncated and continue copying if necessary
75 | if (listedObjects.IsTruncated) {
76 | listParams.ContinuationToken = listedObjects.NextContinuationToken;
77 | await copyS3Folder(sourcePrefix, destinationPrefix, continuationToken);
78 | }
79 | } catch (error) {
80 | console.error('Error copying folder:', error);
81 | }
82 | }
83 |
84 | function writeFile(filePath: string, fileData: Buffer): Promise {
85 | return new Promise(async (resolve, reject) => {
86 | await createFolder(path.dirname(filePath));
87 |
88 | fs.writeFile(filePath, fileData, (err) => {
89 | if (err) {
90 | reject(err)
91 | } else {
92 | resolve()
93 | }
94 | })
95 | });
96 | }
97 |
98 | function createFolder(dirName: string) {
99 | return new Promise((resolve, reject) => {
100 | fs.mkdir(dirName, { recursive: true }, (err) => {
101 | if (err) {
102 | return reject(err)
103 | }
104 | resolve()
105 | });
106 | })
107 | }
108 |
109 | export const saveToS3 = async (key: string, filePath: string, content: string): Promise => {
110 | const params = {
111 | Bucket: process.env.S3_BUCKET ?? "",
112 | Key: `${key}${filePath}`,
113 | Body: content
114 | }
115 |
116 | await s3.putObject(params).promise()
117 | }
--------------------------------------------------------------------------------
/bad-code/frontend/src/components/external/editor/components/file-tree.tsx:
--------------------------------------------------------------------------------
1 | import React, {useState} from 'react'
2 | import {Directory, File, sortDir, sortFile} from "../utils/file-manager";
3 | import {getIcon} from "./icon";
4 | import styled from "@emotion/styled";
5 |
6 | interface FileTreeProps {
7 | rootDir: Directory; // 根目录
8 | selectedFile: File | undefined; // 当前选中文件
9 | onSelect: (file: File) => void; // 更改选中时触发事件
10 | }
11 |
12 | export const FileTree = (props: FileTreeProps) => {
13 | return
14 | }
15 |
16 | interface SubTreeProps {
17 | directory: Directory; // 根目录
18 | selectedFile: File | undefined; // 当前选中文件
19 | onSelect: (file: File) => void; // 更改选中时触发事件
20 | }
21 |
22 | const SubTree = (props: SubTreeProps) => {
23 | return (
24 |
25 | {
26 | props.directory.dirs
27 | .sort(sortDir)
28 | .map(dir => (
29 |
30 |
34 |
35 | ))
36 | }
37 | {
38 | props.directory.files
39 | .sort(sortFile)
40 | .map(file => (
41 |
42 | props.onSelect(file)}/>
46 |
47 | ))
48 | }
49 |
50 | )
51 | }
52 |
53 | const FileDiv = ({file, icon, selectedFile, onClick}: {
54 | file: File | Directory; // 当前文件
55 | icon?: string; // 图标名称
56 | selectedFile: File | undefined; // 选中的文件
57 | onClick: () => void; // 点击事件
58 | }) => {
59 | const isSelected = (selectedFile && selectedFile.id === file.id) as boolean;
60 | const depth = file.depth;
61 | return (
62 |
66 |
69 |
70 | {file.name}
71 |
72 |
73 | )
74 | }
75 |
76 | const Div = styled.div<{
77 | depth: number;
78 | isSelected: boolean;
79 | }>`
80 | display: flex;
81 | align-items: center;
82 | padding-left: ${props => props.depth * 16}px;
83 | background-color: ${props => props.isSelected ? "#242424" : "transparent"};
84 |
85 | :hover {
86 | cursor: pointer;
87 | background-color: #242424;
88 | }
89 | `
90 |
91 | const DirDiv = ({directory, selectedFile, onSelect}: {
92 | directory: Directory; // 当前目录
93 | selectedFile: File | undefined; // 选中的文件
94 | onSelect: (file: File) => void; // 点击事件
95 | }) => {
96 | let defaultOpen = false;
97 | if (selectedFile)
98 | defaultOpen = isChildSelected(directory, selectedFile)
99 | const [open, setOpen] = useState(defaultOpen);
100 | return (
101 | <>
102 | {
107 | if (!open) {
108 | onSelect(directory)
109 | }
110 | setOpen(!open)
111 | }}/>
112 | {
113 | open ? (
114 |
118 | ) : null
119 | }
120 | >
121 | )
122 | }
123 |
124 | const isChildSelected = (directory: Directory, selectedFile: File) => {
125 | let res: boolean = false;
126 |
127 | function isChild(dir: Directory, file: File) {
128 | if (selectedFile.parentId === dir.id) {
129 | res = true;
130 | return;
131 | }
132 | if (selectedFile.parentId === '0') {
133 | res = false;
134 | return;
135 | }
136 | dir.dirs.forEach((item) => {
137 | isChild(item, file);
138 | })
139 | }
140 |
141 | isChild(directory, selectedFile);
142 | return res;
143 | }
144 |
145 | const FileIcon = ({extension, name}: { name?: string, extension?: string }) => {
146 | let icon = getIcon(extension || "", name || "");
147 | return (
148 |
149 | {icon}
150 |
151 | )
152 | }
153 |
154 | const Span = styled.span`
155 | display: flex;
156 | width: 32px;
157 | height: 32px;
158 | justify-content: center;
159 | align-items: center;
160 | `
161 |
162 |
--------------------------------------------------------------------------------
/good-code/frontend/src/components/external/editor/components/file-tree.tsx:
--------------------------------------------------------------------------------
1 | import React, {useState} from 'react'
2 | import {Directory, File, sortDir, sortFile} from "../utils/file-manager";
3 | import {getIcon} from "./icon";
4 | import styled from "@emotion/styled";
5 |
6 | interface FileTreeProps {
7 | rootDir: Directory; // 根目录
8 | selectedFile: File | undefined; // 当前选中文件
9 | onSelect: (file: File) => void; // 更改选中时触发事件
10 | }
11 |
12 | export const FileTree = (props: FileTreeProps) => {
13 | return
14 | }
15 |
16 | interface SubTreeProps {
17 | directory: Directory; // 根目录
18 | selectedFile: File | undefined; // 当前选中文件
19 | onSelect: (file: File) => void; // 更改选中时触发事件
20 | }
21 |
22 | const SubTree = (props: SubTreeProps) => {
23 | return (
24 |
25 | {
26 | props.directory.dirs
27 | .sort(sortDir)
28 | .map(dir => (
29 |
30 |
34 |
35 | ))
36 | }
37 | {
38 | props.directory.files
39 | .sort(sortFile)
40 | .map(file => (
41 |
42 | props.onSelect(file)}/>
46 |
47 | ))
48 | }
49 |
50 | )
51 | }
52 |
53 | const FileDiv = ({file, icon, selectedFile, onClick}: {
54 | file: File | Directory; // 当前文件
55 | icon?: string; // 图标名称
56 | selectedFile: File | undefined; // 选中的文件
57 | onClick: () => void; // 点击事件
58 | }) => {
59 | const isSelected = (selectedFile && selectedFile.id === file.id) as boolean;
60 | const depth = file.depth;
61 | return (
62 |
66 |
69 |
70 | {file.name}
71 |
72 |
73 | )
74 | }
75 |
76 | const Div = styled.div<{
77 | depth: number;
78 | isSelected: boolean;
79 | }>`
80 | display: flex;
81 | align-items: center;
82 | padding-left: ${props => props.depth * 16}px;
83 | background-color: ${props => props.isSelected ? "#242424" : "transparent"};
84 |
85 | :hover {
86 | cursor: pointer;
87 | background-color: #242424;
88 | }
89 | `
90 |
91 | const DirDiv = ({directory, selectedFile, onSelect}: {
92 | directory: Directory; // 当前目录
93 | selectedFile: File | undefined; // 选中的文件
94 | onSelect: (file: File) => void; // 点击事件
95 | }) => {
96 | let defaultOpen = false;
97 | if (selectedFile)
98 | defaultOpen = isChildSelected(directory, selectedFile)
99 | const [open, setOpen] = useState(defaultOpen);
100 | return (
101 | <>
102 | {
107 | if (!open) {
108 | onSelect(directory)
109 | }
110 | setOpen(!open)
111 | }}/>
112 | {
113 | open ? (
114 |
118 | ) : null
119 | }
120 | >
121 | )
122 | }
123 |
124 | const isChildSelected = (directory: Directory, selectedFile: File) => {
125 | let res: boolean = false;
126 |
127 | function isChild(dir: Directory, file: File) {
128 | if (selectedFile.parentId === dir.id) {
129 | res = true;
130 | return;
131 | }
132 | if (selectedFile.parentId === '0') {
133 | res = false;
134 | return;
135 | }
136 | dir.dirs.forEach((item) => {
137 | isChild(item, file);
138 | })
139 | }
140 |
141 | isChild(directory, selectedFile);
142 | return res;
143 | }
144 |
145 | const FileIcon = ({extension, name}: { name?: string, extension?: string }) => {
146 | let icon = getIcon(extension || "", name || "");
147 | return (
148 |
149 | {icon}
150 |
151 | )
152 | }
153 |
154 | const Span = styled.span`
155 | display: flex;
156 | width: 32px;
157 | height: 32px;
158 | justify-content: center;
159 | align-items: center;
160 | `
161 |
162 |
--------------------------------------------------------------------------------
/bad-code/frontend/src/App.css:
--------------------------------------------------------------------------------
1 | #root {
2 | margin: 0 auto;
3 | padding: 2rem;
4 | }
5 |
6 | .logo {
7 | height: 6em;
8 | padding: 1.5em;
9 | will-change: filter;
10 | transition: filter 300ms;
11 | }
12 | .logo:hover {
13 | filter: drop-shadow(0 0 2em #646cffaa);
14 | }
15 | .logo.react:hover {
16 | filter: drop-shadow(0 0 2em #61dafbaa);
17 | }
18 |
19 | @keyframes logo-spin {
20 | from {
21 | transform: rotate(0deg);
22 | }
23 | to {
24 | transform: rotate(360deg);
25 | }
26 | }
27 |
28 | @media (prefers-reduced-motion: no-preference) {
29 | a:nth-of-type(2) .logo {
30 | animation: logo-spin infinite 20s linear;
31 | }
32 | }
33 |
34 | .card {
35 | padding: 2em;
36 | }
37 |
38 | .read-the-docs {
39 | color: #888;
40 | }
41 |
42 |
43 | /**
44 | * Copyright (c) 2014 The xterm.js authors. All rights reserved.
45 | * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
46 | * https://github.com/chjj/term.js
47 | * @license MIT
48 | *
49 | * Permission is hereby granted, free of charge, to any person obtaining a copy
50 | * of this software and associated documentation files (the "Software"), to deal
51 | * in the Software without restriction, including without limitation the rights
52 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
53 | * copies of the Software, and to permit persons to whom the Software is
54 | * furnished to do so, subject to the following conditions:
55 | *
56 | * The above copyright notice and this permission notice shall be included in
57 | * all copies or substantial portions of the Software.
58 | *
59 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
60 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
61 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
62 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
63 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
64 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
65 | * THE SOFTWARE.
66 | *
67 | * Originally forked from (with the author's permission):
68 | * Fabrice Bellard's javascript vt100 for jslinux:
69 | * http://bellard.org/jslinux/
70 | * Copyright (c) 2011 Fabrice Bellard
71 | * The original design remains. The terminal itself
72 | * has been extended to include xterm CSI codes, among
73 | * other features.
74 | */
75 |
76 | /**
77 | * Default styles for xterm.js
78 | */
79 |
80 | .xterm {
81 | font-feature-settings: "liga" 0;
82 | position: relative;
83 | user-select: none;
84 | -ms-user-select: none;
85 | -webkit-user-select: none;
86 | }
87 |
88 | .xterm.focus,
89 | .xterm:focus {
90 | outline: none;
91 | }
92 |
93 | .xterm .xterm-helpers {
94 | position: absolute;
95 | top: 0;
96 | /**
97 | * The z-index of the helpers must be higher than the canvases in order for
98 | * IMEs to appear on top.
99 | */
100 | z-index: 5;
101 | }
102 |
103 | .xterm .xterm-helper-textarea {
104 | padding: 0;
105 | border: 0;
106 | margin: 0;
107 | /* Move textarea out of the screen to the far left, so that the cursor is not visible */
108 | position: absolute;
109 | opacity: 0;
110 | left: -9999em;
111 | top: 0;
112 | width: 0;
113 | height: 0;
114 | z-index: -5;
115 | /** Prevent wrapping so the IME appears against the textarea at the correct position */
116 | white-space: nowrap;
117 | overflow: hidden;
118 | resize: none;
119 | }
120 |
121 | .xterm .composition-view {
122 | /* TODO: Composition position got messed up somewhere */
123 | background: #000;
124 | color: #FFF;
125 | display: none;
126 | position: absolute;
127 | white-space: nowrap;
128 | z-index: 1;
129 | }
130 |
131 | .xterm .composition-view.active {
132 | display: block;
133 | }
134 |
135 | .xterm .xterm-viewport {
136 | /* On OS X this is required in order for the scroll bar to appear fully opaque */
137 | background-color: #000;
138 | overflow-y: scroll;
139 | cursor: default;
140 | position: absolute;
141 | right: 0;
142 | left: 0;
143 | top: 0;
144 | bottom: 0;
145 | }
146 |
147 | .xterm .xterm-screen {
148 | position: relative;
149 | }
150 |
151 | .xterm .xterm-screen canvas {
152 | position: absolute;
153 | left: 0;
154 | top: 0;
155 | }
156 |
157 | .xterm .xterm-scroll-area {
158 | visibility: hidden;
159 | }
160 |
161 | .xterm-char-measure-element {
162 | display: inline-block;
163 | visibility: hidden;
164 | position: absolute;
165 | top: 0;
166 | left: -9999em;
167 | line-height: normal;
168 | }
169 |
170 | .xterm {
171 | cursor: text;
172 | }
173 |
174 | .xterm.enable-mouse-events {
175 | /* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */
176 | cursor: default;
177 | }
178 |
179 | .xterm.xterm-cursor-pointer {
180 | cursor: pointer;
181 | }
182 |
183 | .xterm.column-select.focus {
184 | /* Column selection mode */
185 | cursor: crosshair;
186 | }
187 |
188 | .xterm .xterm-accessibility,
189 | .xterm .xterm-message {
190 | position: absolute;
191 | left: 0;
192 | top: 0;
193 | bottom: 0;
194 | right: 0;
195 | z-index: 10;
196 | color: transparent;
197 | }
198 |
199 | .xterm .live-region {
200 | position: absolute;
201 | left: -9999px;
202 | width: 1px;
203 | height: 1px;
204 | overflow: hidden;
205 | }
206 |
207 | .xterm-dim {
208 | opacity: 0.5;
209 | }
210 |
211 | .xterm-underline {
212 | text-decoration: underline;
213 | }
214 |
--------------------------------------------------------------------------------
/good-code/frontend/src/App.css:
--------------------------------------------------------------------------------
1 | #root {
2 | margin: 0 auto;
3 | padding: 2rem;
4 | }
5 |
6 | .logo {
7 | height: 6em;
8 | padding: 1.5em;
9 | will-change: filter;
10 | transition: filter 300ms;
11 | }
12 | .logo:hover {
13 | filter: drop-shadow(0 0 2em #646cffaa);
14 | }
15 | .logo.react:hover {
16 | filter: drop-shadow(0 0 2em #61dafbaa);
17 | }
18 |
19 | @keyframes logo-spin {
20 | from {
21 | transform: rotate(0deg);
22 | }
23 | to {
24 | transform: rotate(360deg);
25 | }
26 | }
27 |
28 | @media (prefers-reduced-motion: no-preference) {
29 | a:nth-of-type(2) .logo {
30 | animation: logo-spin infinite 20s linear;
31 | }
32 | }
33 |
34 | .card {
35 | padding: 2em;
36 | }
37 |
38 | .read-the-docs {
39 | color: #888;
40 | }
41 |
42 |
43 | /**
44 | * Copyright (c) 2014 The xterm.js authors. All rights reserved.
45 | * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
46 | * https://github.com/chjj/term.js
47 | * @license MIT
48 | *
49 | * Permission is hereby granted, free of charge, to any person obtaining a copy
50 | * of this software and associated documentation files (the "Software"), to deal
51 | * in the Software without restriction, including without limitation the rights
52 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
53 | * copies of the Software, and to permit persons to whom the Software is
54 | * furnished to do so, subject to the following conditions:
55 | *
56 | * The above copyright notice and this permission notice shall be included in
57 | * all copies or substantial portions of the Software.
58 | *
59 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
60 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
61 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
62 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
63 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
64 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
65 | * THE SOFTWARE.
66 | *
67 | * Originally forked from (with the author's permission):
68 | * Fabrice Bellard's javascript vt100 for jslinux:
69 | * http://bellard.org/jslinux/
70 | * Copyright (c) 2011 Fabrice Bellard
71 | * The original design remains. The terminal itself
72 | * has been extended to include xterm CSI codes, among
73 | * other features.
74 | */
75 |
76 | /**
77 | * Default styles for xterm.js
78 | */
79 |
80 | .xterm {
81 | font-feature-settings: "liga" 0;
82 | position: relative;
83 | user-select: none;
84 | -ms-user-select: none;
85 | -webkit-user-select: none;
86 | }
87 |
88 | .xterm.focus,
89 | .xterm:focus {
90 | outline: none;
91 | }
92 |
93 | .xterm .xterm-helpers {
94 | position: absolute;
95 | top: 0;
96 | /**
97 | * The z-index of the helpers must be higher than the canvases in order for
98 | * IMEs to appear on top.
99 | */
100 | z-index: 5;
101 | }
102 |
103 | .xterm .xterm-helper-textarea {
104 | padding: 0;
105 | border: 0;
106 | margin: 0;
107 | /* Move textarea out of the screen to the far left, so that the cursor is not visible */
108 | position: absolute;
109 | opacity: 0;
110 | left: -9999em;
111 | top: 0;
112 | width: 0;
113 | height: 0;
114 | z-index: -5;
115 | /** Prevent wrapping so the IME appears against the textarea at the correct position */
116 | white-space: nowrap;
117 | overflow: hidden;
118 | resize: none;
119 | }
120 |
121 | .xterm .composition-view {
122 | /* TODO: Composition position got messed up somewhere */
123 | background: #000;
124 | color: #FFF;
125 | display: none;
126 | position: absolute;
127 | white-space: nowrap;
128 | z-index: 1;
129 | }
130 |
131 | .xterm .composition-view.active {
132 | display: block;
133 | }
134 |
135 | .xterm .xterm-viewport {
136 | /* On OS X this is required in order for the scroll bar to appear fully opaque */
137 | background-color: #000;
138 | overflow-y: scroll;
139 | cursor: default;
140 | position: absolute;
141 | right: 0;
142 | left: 0;
143 | top: 0;
144 | bottom: 0;
145 | }
146 |
147 | .xterm .xterm-screen {
148 | position: relative;
149 | }
150 |
151 | .xterm .xterm-screen canvas {
152 | position: absolute;
153 | left: 0;
154 | top: 0;
155 | }
156 |
157 | .xterm .xterm-scroll-area {
158 | visibility: hidden;
159 | }
160 |
161 | .xterm-char-measure-element {
162 | display: inline-block;
163 | visibility: hidden;
164 | position: absolute;
165 | top: 0;
166 | left: -9999em;
167 | line-height: normal;
168 | }
169 |
170 | .xterm {
171 | cursor: text;
172 | }
173 |
174 | .xterm.enable-mouse-events {
175 | /* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */
176 | cursor: default;
177 | }
178 |
179 | .xterm.xterm-cursor-pointer {
180 | cursor: pointer;
181 | }
182 |
183 | .xterm.column-select.focus {
184 | /* Column selection mode */
185 | cursor: crosshair;
186 | }
187 |
188 | .xterm .xterm-accessibility,
189 | .xterm .xterm-message {
190 | position: absolute;
191 | left: 0;
192 | top: 0;
193 | bottom: 0;
194 | right: 0;
195 | z-index: 10;
196 | color: transparent;
197 | }
198 |
199 | .xterm .live-region {
200 | position: absolute;
201 | left: -9999px;
202 | width: 1px;
203 | height: 1px;
204 | overflow: hidden;
205 | }
206 |
207 | .xterm-dim {
208 | opacity: 0.5;
209 | }
210 |
211 | .xterm-underline {
212 | text-decoration: underline;
213 | }
214 |
--------------------------------------------------------------------------------
/bad-code/backend/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Visit https://aka.ms/tsconfig to read more about this file */
4 |
5 | /* Projects */
6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
12 |
13 | /* Language and Environment */
14 | "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
16 | // "jsx": "preserve", /* Specify what JSX code is generated. */
17 | // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
26 |
27 | /* Modules */
28 | "module": "commonjs", /* Specify what module code is generated. */
29 | "rootDir": "./src", /* Specify the root folder within your source files. */
30 | // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */
36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
38 | // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
39 | // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
40 | // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
41 | // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
42 | // "resolveJsonModule": true, /* Enable importing .json files. */
43 | // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
44 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
45 |
46 | /* JavaScript Support */
47 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
48 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
49 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
50 |
51 | /* Emit */
52 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
53 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */
54 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
55 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */
56 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
57 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
58 | "outDir": "./dist", /* Specify an output folder for all emitted files. */
59 | // "removeComments": true, /* Disable emitting comments. */
60 | // "noEmit": true, /* Disable emitting files from a compilation. */
61 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
62 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
63 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
64 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
65 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
66 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
67 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
68 | // "newLine": "crlf", /* Set the newline character for emitting files. */
69 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
70 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
71 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
72 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
73 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
74 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
75 |
76 | /* Interop Constraints */
77 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
78 | // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
79 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
80 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
81 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
82 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
83 |
84 | /* Type Checking */
85 | "strict": true, /* Enable all strict type-checking options. */
86 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
87 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
88 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
89 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
90 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
91 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
92 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
93 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
94 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
95 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
96 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
97 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
98 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
99 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
100 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
101 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
102 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
103 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
104 |
105 | /* Completeness */
106 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
107 | "skipLibCheck": true /* Skip type checking all .d.ts files. */
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/good-code/runner/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Visit https://aka.ms/tsconfig to read more about this file */
4 |
5 | /* Projects */
6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
12 |
13 | /* Language and Environment */
14 | "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
16 | // "jsx": "preserve", /* Specify what JSX code is generated. */
17 | // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
26 |
27 | /* Modules */
28 | "module": "commonjs", /* Specify what module code is generated. */
29 | "rootDir": "./src", /* Specify the root folder within your source files. */
30 | // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */
36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
38 | // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
39 | // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
40 | // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
41 | // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
42 | // "resolveJsonModule": true, /* Enable importing .json files. */
43 | // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
44 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
45 |
46 | /* JavaScript Support */
47 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
48 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
49 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
50 |
51 | /* Emit */
52 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
53 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */
54 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
55 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */
56 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
57 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
58 | "outDir": "./dist", /* Specify an output folder for all emitted files. */
59 | // "removeComments": true, /* Disable emitting comments. */
60 | // "noEmit": true, /* Disable emitting files from a compilation. */
61 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
62 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
63 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
64 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
65 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
66 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
67 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
68 | // "newLine": "crlf", /* Set the newline character for emitting files. */
69 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
70 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
71 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
72 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
73 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
74 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
75 |
76 | /* Interop Constraints */
77 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
78 | // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
79 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
80 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
81 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
82 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
83 |
84 | /* Type Checking */
85 | "strict": true, /* Enable all strict type-checking options. */
86 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
87 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
88 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
89 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
90 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
91 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
92 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
93 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
94 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
95 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
96 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
97 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
98 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
99 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
100 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
101 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
102 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
103 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
104 |
105 | /* Completeness */
106 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
107 | "skipLibCheck": true /* Skip type checking all .d.ts files. */
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/good-code/init-service/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Visit https://aka.ms/tsconfig to read more about this file */
4 |
5 | /* Projects */
6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
12 |
13 | /* Language and Environment */
14 | "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
16 | // "jsx": "preserve", /* Specify what JSX code is generated. */
17 | // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
26 |
27 | /* Modules */
28 | "module": "commonjs", /* Specify what module code is generated. */
29 | "rootDir": "./src", /* Specify the root folder within your source files. */
30 | // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */
36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
38 | // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
39 | // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
40 | // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
41 | // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
42 | // "resolveJsonModule": true, /* Enable importing .json files. */
43 | // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
44 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
45 |
46 | /* JavaScript Support */
47 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
48 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
49 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
50 |
51 | /* Emit */
52 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
53 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */
54 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
55 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */
56 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
57 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
58 | "outDir": "./dist", /* Specify an output folder for all emitted files. */
59 | // "removeComments": true, /* Disable emitting comments. */
60 | // "noEmit": true, /* Disable emitting files from a compilation. */
61 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
62 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
63 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
64 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
65 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
66 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
67 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
68 | // "newLine": "crlf", /* Set the newline character for emitting files. */
69 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
70 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
71 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
72 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
73 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
74 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
75 |
76 | /* Interop Constraints */
77 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
78 | // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
79 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
80 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
81 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
82 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
83 |
84 | /* Type Checking */
85 | "strict": true, /* Enable all strict type-checking options. */
86 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
87 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
88 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
89 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
90 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
91 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
92 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
93 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
94 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
95 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
96 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
97 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
98 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
99 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
100 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
101 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
102 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
103 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
104 |
105 | /* Completeness */
106 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
107 | "skipLibCheck": true /* Skip type checking all .d.ts files. */
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/good-code/orchestrator-simple/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Visit https://aka.ms/tsconfig to read more about this file */
4 |
5 | /* Projects */
6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
12 |
13 | /* Language and Environment */
14 | "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
16 | // "jsx": "preserve", /* Specify what JSX code is generated. */
17 | // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
26 |
27 | /* Modules */
28 | "module": "commonjs", /* Specify what module code is generated. */
29 | // "rootDir": "./", /* Specify the root folder within your source files. */
30 | // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */
36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
38 | // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
39 | // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
40 | // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
41 | // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
42 | // "resolveJsonModule": true, /* Enable importing .json files. */
43 | // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
44 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
45 |
46 | /* JavaScript Support */
47 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
48 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
49 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
50 |
51 | /* Emit */
52 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
53 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */
54 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
55 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */
56 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
57 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
58 | // "outDir": "./", /* Specify an output folder for all emitted files. */
59 | // "removeComments": true, /* Disable emitting comments. */
60 | // "noEmit": true, /* Disable emitting files from a compilation. */
61 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
62 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
63 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
64 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
65 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
66 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
67 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
68 | // "newLine": "crlf", /* Set the newline character for emitting files. */
69 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
70 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
71 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
72 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
73 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
74 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
75 |
76 | /* Interop Constraints */
77 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
78 | // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
79 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
80 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
81 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
82 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
83 |
84 | /* Type Checking */
85 | "strict": true, /* Enable all strict type-checking options. */
86 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
87 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
88 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
89 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
90 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
91 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
92 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
93 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
94 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
95 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
96 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
97 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
98 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
99 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
100 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
101 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
102 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
103 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
104 |
105 | /* Completeness */
106 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
107 | "skipLibCheck": true /* Skip type checking all .d.ts files. */
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/good-code/k8s/ingress-controller.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # Source: ingress-nginx/templates/controller-serviceaccount.yaml
3 | apiVersion: v1
4 | kind: ServiceAccount
5 | metadata:
6 | labels:
7 | helm.sh/chart: ingress-nginx-4.9.1
8 | app.kubernetes.io/name: ingress-nginx
9 | app.kubernetes.io/instance: ingress-nginx
10 | app.kubernetes.io/version: "1.9.6"
11 | app.kubernetes.io/part-of: ingress-nginx
12 | app.kubernetes.io/managed-by: Helm
13 | app.kubernetes.io/component: controller
14 | name: ingress-nginx
15 | namespace: ingress-nginx
16 | automountServiceAccountToken: true
17 | ---
18 | # Source: ingress-nginx/templates/controller-configmap.yaml
19 | apiVersion: v1
20 | kind: ConfigMap
21 | metadata:
22 | labels:
23 | helm.sh/chart: ingress-nginx-4.9.1
24 | app.kubernetes.io/name: ingress-nginx
25 | app.kubernetes.io/instance: ingress-nginx
26 | app.kubernetes.io/version: "1.9.6"
27 | app.kubernetes.io/part-of: ingress-nginx
28 | app.kubernetes.io/managed-by: Helm
29 | app.kubernetes.io/component: controller
30 | name: ingress-nginx-controller
31 | namespace: ingress-nginx
32 | data:
33 | allow-snippet-annotations: "false"
34 | log-format-escape-json: "true"
35 | log-format-upstream: '{"time":"$time_iso8601","remote_addr":"$remote_addr","proxy_protocol_addr":"$proxy_protocol_addr","proxy_protocol_port":"$proxy_protocol_port","x_forward_for":"$proxy_add_x_forwarded_for","remote_user":"$remote_user","host":"$host","request_method":"$request_method","request_uri":"$request_uri","server_protocol":"$server_protocol","status":$status,"request_time":$request_time,"request_length":$request_length,"bytes_sent":$bytes_sent,"upstream_name":"$proxy_upstream_name","upstream_addr":"$upstream_addr","upstream_uri":"$uri","upstream_response_length":$upstream_response_length,"upstream_response_time":$upstream_response_time,"upstream_status":$upstream_status,"http_referrer":"$http_referer","http_user_agent":"$http_user_agent","http_cookie":"$http_cookie","http_device_id":"$http_x_device_id","http_customer_id":"$http_x_customer_id"}'
36 | ---
37 | # Source: ingress-nginx/templates/clusterrole.yaml
38 | apiVersion: rbac.authorization.k8s.io/v1
39 | kind: ClusterRole
40 | metadata:
41 | labels:
42 | helm.sh/chart: ingress-nginx-4.9.1
43 | app.kubernetes.io/name: ingress-nginx
44 | app.kubernetes.io/instance: ingress-nginx
45 | app.kubernetes.io/version: "1.9.6"
46 | app.kubernetes.io/part-of: ingress-nginx
47 | app.kubernetes.io/managed-by: Helm
48 | name: ingress-nginx
49 | rules:
50 | - apiGroups:
51 | - ""
52 | resources:
53 | - configmaps
54 | - endpoints
55 | - nodes
56 | - pods
57 | - secrets
58 | - namespaces
59 | verbs:
60 | - list
61 | - watch
62 | - apiGroups:
63 | - coordination.k8s.io
64 | resources:
65 | - leases
66 | verbs:
67 | - list
68 | - watch
69 | - apiGroups:
70 | - ""
71 | resources:
72 | - nodes
73 | verbs:
74 | - get
75 | - apiGroups:
76 | - ""
77 | resources:
78 | - services
79 | verbs:
80 | - get
81 | - list
82 | - watch
83 | - apiGroups:
84 | - networking.k8s.io
85 | resources:
86 | - ingresses
87 | verbs:
88 | - get
89 | - list
90 | - watch
91 | - apiGroups:
92 | - ""
93 | resources:
94 | - events
95 | verbs:
96 | - create
97 | - patch
98 | - apiGroups:
99 | - networking.k8s.io
100 | resources:
101 | - ingresses/status
102 | verbs:
103 | - update
104 | - apiGroups:
105 | - networking.k8s.io
106 | resources:
107 | - ingressclasses
108 | verbs:
109 | - get
110 | - list
111 | - watch
112 | - apiGroups:
113 | - discovery.k8s.io
114 | resources:
115 | - endpointslices
116 | verbs:
117 | - list
118 | - watch
119 | - get
120 | ---
121 | # Source: ingress-nginx/templates/clusterrolebinding.yaml
122 | apiVersion: rbac.authorization.k8s.io/v1
123 | kind: ClusterRoleBinding
124 | metadata:
125 | labels:
126 | helm.sh/chart: ingress-nginx-4.9.1
127 | app.kubernetes.io/name: ingress-nginx
128 | app.kubernetes.io/instance: ingress-nginx
129 | app.kubernetes.io/version: "1.9.6"
130 | app.kubernetes.io/part-of: ingress-nginx
131 | app.kubernetes.io/managed-by: Helm
132 | name: ingress-nginx
133 | roleRef:
134 | apiGroup: rbac.authorization.k8s.io
135 | kind: ClusterRole
136 | name: ingress-nginx
137 | subjects:
138 | - kind: ServiceAccount
139 | name: ingress-nginx
140 | namespace: ingress-nginx
141 | ---
142 | # Source: ingress-nginx/templates/controller-role.yaml
143 | apiVersion: rbac.authorization.k8s.io/v1
144 | kind: Role
145 | metadata:
146 | labels:
147 | helm.sh/chart: ingress-nginx-4.9.1
148 | app.kubernetes.io/name: ingress-nginx
149 | app.kubernetes.io/instance: ingress-nginx
150 | app.kubernetes.io/version: "1.9.6"
151 | app.kubernetes.io/part-of: ingress-nginx
152 | app.kubernetes.io/managed-by: Helm
153 | app.kubernetes.io/component: controller
154 | name: ingress-nginx
155 | namespace: ingress-nginx
156 | rules:
157 | - apiGroups:
158 | - ""
159 | resources:
160 | - namespaces
161 | verbs:
162 | - get
163 | - apiGroups:
164 | - ""
165 | resources:
166 | - configmaps
167 | - pods
168 | - secrets
169 | - endpoints
170 | verbs:
171 | - get
172 | - list
173 | - watch
174 | - apiGroups:
175 | - ""
176 | resources:
177 | - services
178 | verbs:
179 | - get
180 | - list
181 | - watch
182 | - apiGroups:
183 | - networking.k8s.io
184 | resources:
185 | - ingresses
186 | verbs:
187 | - get
188 | - list
189 | - watch
190 | # Omit Ingress status permissions if `--update-status` is disabled.
191 | - apiGroups:
192 | - networking.k8s.io
193 | resources:
194 | - ingresses/status
195 | verbs:
196 | - update
197 | - apiGroups:
198 | - networking.k8s.io
199 | resources:
200 | - ingressclasses
201 | verbs:
202 | - get
203 | - list
204 | - watch
205 | - apiGroups:
206 | - coordination.k8s.io
207 | resources:
208 | - leases
209 | resourceNames:
210 | - ingress-nginx-leader
211 | verbs:
212 | - get
213 | - update
214 | - apiGroups:
215 | - coordination.k8s.io
216 | resources:
217 | - leases
218 | verbs:
219 | - create
220 | - apiGroups:
221 | - ""
222 | resources:
223 | - events
224 | verbs:
225 | - create
226 | - patch
227 | - apiGroups:
228 | - discovery.k8s.io
229 | resources:
230 | - endpointslices
231 | verbs:
232 | - list
233 | - watch
234 | - get
235 | ---
236 | # Source: ingress-nginx/templates/controller-rolebinding.yaml
237 | apiVersion: rbac.authorization.k8s.io/v1
238 | kind: RoleBinding
239 | metadata:
240 | labels:
241 | helm.sh/chart: ingress-nginx-4.9.1
242 | app.kubernetes.io/name: ingress-nginx
243 | app.kubernetes.io/instance: ingress-nginx
244 | app.kubernetes.io/version: "1.9.6"
245 | app.kubernetes.io/part-of: ingress-nginx
246 | app.kubernetes.io/managed-by: Helm
247 | app.kubernetes.io/component: controller
248 | name: ingress-nginx
249 | namespace: ingress-nginx
250 | roleRef:
251 | apiGroup: rbac.authorization.k8s.io
252 | kind: Role
253 | name: ingress-nginx
254 | subjects:
255 | - kind: ServiceAccount
256 | name: ingress-nginx
257 | namespace: ingress-nginx
258 | ---
259 | # Source: ingress-nginx/templates/controller-service-webhook.yaml
260 | apiVersion: v1
261 | kind: Service
262 | metadata:
263 | labels:
264 | helm.sh/chart: ingress-nginx-4.9.1
265 | app.kubernetes.io/name: ingress-nginx
266 | app.kubernetes.io/instance: ingress-nginx
267 | app.kubernetes.io/version: "1.9.6"
268 | app.kubernetes.io/part-of: ingress-nginx
269 | app.kubernetes.io/managed-by: Helm
270 | app.kubernetes.io/component: controller
271 | name: ingress-nginx-controller-admission
272 | namespace: ingress-nginx
273 | spec:
274 | type: ClusterIP
275 | ports:
276 | - name: https-webhook
277 | port: 443
278 | targetPort: webhook
279 | appProtocol: https
280 | selector:
281 | app.kubernetes.io/name: ingress-nginx
282 | app.kubernetes.io/instance: ingress-nginx
283 | app.kubernetes.io/component: controller
284 | ---
285 | # Source: ingress-nginx/templates/controller-service.yaml
286 | apiVersion: v1
287 | kind: Service
288 | metadata:
289 | annotations:
290 | labels:
291 | helm.sh/chart: ingress-nginx-4.9.1
292 | app.kubernetes.io/name: ingress-nginx
293 | app.kubernetes.io/instance: ingress-nginx
294 | app.kubernetes.io/version: "1.9.6"
295 | app.kubernetes.io/part-of: ingress-nginx
296 | app.kubernetes.io/managed-by: Helm
297 | app.kubernetes.io/component: controller
298 | name: ingress-nginx-controller
299 | namespace: ingress-nginx
300 | spec:
301 | type: LoadBalancer
302 | ipFamilyPolicy: SingleStack
303 | ipFamilies:
304 | - IPv4
305 | ports:
306 | - name: http
307 | port: 80
308 | protocol: TCP
309 | targetPort: http
310 | appProtocol: http
311 | - name: https
312 | port: 443
313 | protocol: TCP
314 | targetPort: https
315 | appProtocol: https
316 | selector:
317 | app.kubernetes.io/name: ingress-nginx
318 | app.kubernetes.io/instance: ingress-nginx
319 | app.kubernetes.io/component: controller
320 | ---
321 | # Source: ingress-nginx/templates/controller-deployment.yaml
322 | apiVersion: apps/v1
323 | kind: Deployment
324 | metadata:
325 | labels:
326 | helm.sh/chart: ingress-nginx-4.9.1
327 | app.kubernetes.io/name: ingress-nginx
328 | app.kubernetes.io/instance: ingress-nginx
329 | app.kubernetes.io/version: "1.9.6"
330 | app.kubernetes.io/part-of: ingress-nginx
331 | app.kubernetes.io/managed-by: Helm
332 | app.kubernetes.io/component: controller
333 | name: ingress-nginx-controller
334 | namespace: ingress-nginx
335 | spec:
336 | selector:
337 | matchLabels:
338 | app.kubernetes.io/name: ingress-nginx
339 | app.kubernetes.io/instance: ingress-nginx
340 | app.kubernetes.io/component: controller
341 | replicas: 1
342 | revisionHistoryLimit: 10
343 | minReadySeconds: 0
344 | template:
345 | metadata:
346 | labels:
347 | helm.sh/chart: ingress-nginx-4.9.1
348 | app.kubernetes.io/name: ingress-nginx
349 | app.kubernetes.io/instance: ingress-nginx
350 | app.kubernetes.io/version: "1.9.6"
351 | app.kubernetes.io/part-of: ingress-nginx
352 | app.kubernetes.io/managed-by: Helm
353 | app.kubernetes.io/component: controller
354 | spec:
355 | dnsPolicy: ClusterFirst
356 | containers:
357 | - name: controller
358 | image: registry.k8s.io/ingress-nginx/controller:v1.9.6@sha256:1405cc613bd95b2c6edd8b2a152510ae91c7e62aea4698500d23b2145960ab9c
359 | imagePullPolicy: IfNotPresent
360 | lifecycle:
361 | preStop:
362 | exec:
363 | command:
364 | - /wait-shutdown
365 | args:
366 | - /nginx-ingress-controller
367 | - --publish-service=$(POD_NAMESPACE)/ingress-nginx-controller
368 | - --election-id=ingress-nginx-leader
369 | - --controller-class=k8s.io/ingress-nginx
370 | - --ingress-class=nginx
371 | - --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
372 | - --validating-webhook=:8443
373 | - --validating-webhook-certificate=/usr/local/certificates/cert
374 | - --validating-webhook-key=/usr/local/certificates/key
375 | securityContext:
376 | runAsNonRoot: true
377 | runAsUser: 101
378 | allowPrivilegeEscalation: false
379 | seccompProfile:
380 | type: RuntimeDefault
381 | capabilities:
382 | drop:
383 | - ALL
384 | add:
385 | - NET_BIND_SERVICE
386 | readOnlyRootFilesystem: false
387 | env:
388 | - name: POD_NAME
389 | valueFrom:
390 | fieldRef:
391 | fieldPath: metadata.name
392 | - name: POD_NAMESPACE
393 | valueFrom:
394 | fieldRef:
395 | fieldPath: metadata.namespace
396 | - name: LD_PRELOAD
397 | value: /usr/local/lib/libmimalloc.so
398 | livenessProbe:
399 | failureThreshold: 5
400 | httpGet:
401 | path: /healthz
402 | port: 10254
403 | scheme: HTTP
404 | initialDelaySeconds: 10
405 | periodSeconds: 10
406 | successThreshold: 1
407 | timeoutSeconds: 1
408 | readinessProbe:
409 | failureThreshold: 3
410 | httpGet:
411 | path: /healthz
412 | port: 10254
413 | scheme: HTTP
414 | initialDelaySeconds: 10
415 | periodSeconds: 10
416 | successThreshold: 1
417 | timeoutSeconds: 1
418 | ports:
419 | - name: http
420 | containerPort: 80
421 | protocol: TCP
422 | - name: https
423 | containerPort: 443
424 | protocol: TCP
425 | - name: webhook
426 | containerPort: 8443
427 | protocol: TCP
428 | volumeMounts:
429 | - name: webhook-cert
430 | mountPath: /usr/local/certificates/
431 | readOnly: true
432 | resources:
433 | requests:
434 | cpu: 100m
435 | memory: 90Mi
436 | nodeSelector:
437 | kubernetes.io/os: linux
438 | serviceAccountName: ingress-nginx
439 | terminationGracePeriodSeconds: 300
440 | volumes:
441 | - name: webhook-cert
442 | secret:
443 | secretName: ingress-nginx-admission
444 | ---
445 | # Source: ingress-nginx/templates/controller-ingressclass.yaml
446 | # We don't support namespaced ingressClass yet
447 | # So a ClusterRole and a ClusterRoleBinding is required
448 | apiVersion: networking.k8s.io/v1
449 | kind: IngressClass
450 | metadata:
451 | labels:
452 | helm.sh/chart: ingress-nginx-4.9.1
453 | app.kubernetes.io/name: ingress-nginx
454 | app.kubernetes.io/instance: ingress-nginx
455 | app.kubernetes.io/version: "1.9.6"
456 | app.kubernetes.io/part-of: ingress-nginx
457 | app.kubernetes.io/managed-by: Helm
458 | app.kubernetes.io/component: controller
459 | name: nginx
460 | spec:
461 | controller: k8s.io/ingress-nginx
462 | ---
463 | # Source: ingress-nginx/templates/admission-webhooks/validating-webhook.yaml
464 | # before changing this value, check the required kubernetes version
465 | # https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#prerequisites
466 | apiVersion: admissionregistration.k8s.io/v1
467 | kind: ValidatingWebhookConfiguration
468 | metadata:
469 | annotations:
470 | labels:
471 | helm.sh/chart: ingress-nginx-4.9.1
472 | app.kubernetes.io/name: ingress-nginx
473 | app.kubernetes.io/instance: ingress-nginx
474 | app.kubernetes.io/version: "1.9.6"
475 | app.kubernetes.io/part-of: ingress-nginx
476 | app.kubernetes.io/managed-by: Helm
477 | app.kubernetes.io/component: admission-webhook
478 | name: ingress-nginx-admission
479 | webhooks:
480 | - name: validate.nginx.ingress.kubernetes.io
481 | matchPolicy: Equivalent
482 | rules:
483 | - apiGroups:
484 | - networking.k8s.io
485 | apiVersions:
486 | - v1
487 | operations:
488 | - CREATE
489 | - UPDATE
490 | resources:
491 | - ingresses
492 | failurePolicy: Fail
493 | sideEffects: None
494 | admissionReviewVersions:
495 | - v1
496 | clientConfig:
497 | service:
498 | name: ingress-nginx-controller-admission
499 | namespace: ingress-nginx
500 | path: /networking/v1/ingresses
501 | ---
502 | # Source: ingress-nginx/templates/admission-webhooks/job-patch/serviceaccount.yaml
503 | apiVersion: v1
504 | kind: ServiceAccount
505 | metadata:
506 | name: ingress-nginx-admission
507 | namespace: ingress-nginx
508 | annotations:
509 | "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade
510 | "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
511 | labels:
512 | helm.sh/chart: ingress-nginx-4.9.1
513 | app.kubernetes.io/name: ingress-nginx
514 | app.kubernetes.io/instance: ingress-nginx
515 | app.kubernetes.io/version: "1.9.6"
516 | app.kubernetes.io/part-of: ingress-nginx
517 | app.kubernetes.io/managed-by: Helm
518 | app.kubernetes.io/component: admission-webhook
519 | ---
520 | # Source: ingress-nginx/templates/admission-webhooks/job-patch/clusterrole.yaml
521 | apiVersion: rbac.authorization.k8s.io/v1
522 | kind: ClusterRole
523 | metadata:
524 | name: ingress-nginx-admission
525 | annotations:
526 | "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade
527 | "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
528 | labels:
529 | helm.sh/chart: ingress-nginx-4.9.1
530 | app.kubernetes.io/name: ingress-nginx
531 | app.kubernetes.io/instance: ingress-nginx
532 | app.kubernetes.io/version: "1.9.6"
533 | app.kubernetes.io/part-of: ingress-nginx
534 | app.kubernetes.io/managed-by: Helm
535 | app.kubernetes.io/component: admission-webhook
536 | rules:
537 | - apiGroups:
538 | - admissionregistration.k8s.io
539 | resources:
540 | - validatingwebhookconfigurations
541 | verbs:
542 | - get
543 | - update
544 | ---
545 | # Source: ingress-nginx/templates/admission-webhooks/job-patch/clusterrolebinding.yaml
546 | apiVersion: rbac.authorization.k8s.io/v1
547 | kind: ClusterRoleBinding
548 | metadata:
549 | name: ingress-nginx-admission
550 | annotations:
551 | "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade
552 | "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
553 | labels:
554 | helm.sh/chart: ingress-nginx-4.9.1
555 | app.kubernetes.io/name: ingress-nginx
556 | app.kubernetes.io/instance: ingress-nginx
557 | app.kubernetes.io/version: "1.9.6"
558 | app.kubernetes.io/part-of: ingress-nginx
559 | app.kubernetes.io/managed-by: Helm
560 | app.kubernetes.io/component: admission-webhook
561 | roleRef:
562 | apiGroup: rbac.authorization.k8s.io
563 | kind: ClusterRole
564 | name: ingress-nginx-admission
565 | subjects:
566 | - kind: ServiceAccount
567 | name: ingress-nginx-admission
568 | namespace: ingress-nginx
569 | ---
570 | # Source: ingress-nginx/templates/admission-webhooks/job-patch/role.yaml
571 | apiVersion: rbac.authorization.k8s.io/v1
572 | kind: Role
573 | metadata:
574 | name: ingress-nginx-admission
575 | namespace: ingress-nginx
576 | annotations:
577 | "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade
578 | "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
579 | labels:
580 | helm.sh/chart: ingress-nginx-4.9.1
581 | app.kubernetes.io/name: ingress-nginx
582 | app.kubernetes.io/instance: ingress-nginx
583 | app.kubernetes.io/version: "1.9.6"
584 | app.kubernetes.io/part-of: ingress-nginx
585 | app.kubernetes.io/managed-by: Helm
586 | app.kubernetes.io/component: admission-webhook
587 | rules:
588 | - apiGroups:
589 | - ""
590 | resources:
591 | - secrets
592 | verbs:
593 | - get
594 | - create
595 | ---
596 | # Source: ingress-nginx/templates/admission-webhooks/job-patch/rolebinding.yaml
597 | apiVersion: rbac.authorization.k8s.io/v1
598 | kind: RoleBinding
599 | metadata:
600 | name: ingress-nginx-admission
601 | namespace: ingress-nginx
602 | annotations:
603 | "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade
604 | "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
605 | labels:
606 | helm.sh/chart: ingress-nginx-4.9.1
607 | app.kubernetes.io/name: ingress-nginx
608 | app.kubernetes.io/instance: ingress-nginx
609 | app.kubernetes.io/version: "1.9.6"
610 | app.kubernetes.io/part-of: ingress-nginx
611 | app.kubernetes.io/managed-by: Helm
612 | app.kubernetes.io/component: admission-webhook
613 | roleRef:
614 | apiGroup: rbac.authorization.k8s.io
615 | kind: Role
616 | name: ingress-nginx-admission
617 | subjects:
618 | - kind: ServiceAccount
619 | name: ingress-nginx-admission
620 | namespace: ingress-nginx
621 | ---
622 | # Source: ingress-nginx/templates/admission-webhooks/job-patch/job-createSecret.yaml
623 | apiVersion: batch/v1
624 | kind: Job
625 | metadata:
626 | name: ingress-nginx-admission-create
627 | namespace: ingress-nginx
628 | annotations:
629 | "helm.sh/hook": pre-install,pre-upgrade
630 | "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
631 | labels:
632 | helm.sh/chart: ingress-nginx-4.9.1
633 | app.kubernetes.io/name: ingress-nginx
634 | app.kubernetes.io/instance: ingress-nginx
635 | app.kubernetes.io/version: "1.9.6"
636 | app.kubernetes.io/part-of: ingress-nginx
637 | app.kubernetes.io/managed-by: Helm
638 | app.kubernetes.io/component: admission-webhook
639 | spec:
640 | template:
641 | metadata:
642 | name: ingress-nginx-admission-create
643 | labels:
644 | helm.sh/chart: ingress-nginx-4.9.1
645 | app.kubernetes.io/name: ingress-nginx
646 | app.kubernetes.io/instance: ingress-nginx
647 | app.kubernetes.io/version: "1.9.6"
648 | app.kubernetes.io/part-of: ingress-nginx
649 | app.kubernetes.io/managed-by: Helm
650 | app.kubernetes.io/component: admission-webhook
651 | spec:
652 | containers:
653 | - name: create
654 | image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20231226-1a7112e06@sha256:25d6a5f11211cc5c3f9f2bf552b585374af287b4debf693cacbe2da47daa5084
655 | imagePullPolicy: IfNotPresent
656 | args:
657 | - create
658 | - --host=ingress-nginx-controller-admission,ingress-nginx-controller-admission.$(POD_NAMESPACE).svc
659 | - --namespace=$(POD_NAMESPACE)
660 | - --secret-name=ingress-nginx-admission
661 | env:
662 | - name: POD_NAMESPACE
663 | valueFrom:
664 | fieldRef:
665 | fieldPath: metadata.namespace
666 | securityContext:
667 | allowPrivilegeEscalation: false
668 | capabilities:
669 | drop:
670 | - ALL
671 | readOnlyRootFilesystem: true
672 | runAsNonRoot: true
673 | runAsUser: 65532
674 | seccompProfile:
675 | type: RuntimeDefault
676 | restartPolicy: OnFailure
677 | serviceAccountName: ingress-nginx-admission
678 | nodeSelector:
679 | kubernetes.io/os: linux
680 | ---
681 | # Source: ingress-nginx/templates/admission-webhooks/job-patch/job-patchWebhook.yaml
682 | apiVersion: batch/v1
683 | kind: Job
684 | metadata:
685 | name: ingress-nginx-admission-patch
686 | namespace: ingress-nginx
687 | annotations:
688 | "helm.sh/hook": post-install,post-upgrade
689 | "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
690 | labels:
691 | helm.sh/chart: ingress-nginx-4.9.1
692 | app.kubernetes.io/name: ingress-nginx
693 | app.kubernetes.io/instance: ingress-nginx
694 | app.kubernetes.io/version: "1.9.6"
695 | app.kubernetes.io/part-of: ingress-nginx
696 | app.kubernetes.io/managed-by: Helm
697 | app.kubernetes.io/component: admission-webhook
698 | spec:
699 | template:
700 | metadata:
701 | name: ingress-nginx-admission-patch
702 | labels:
703 | helm.sh/chart: ingress-nginx-4.9.1
704 | app.kubernetes.io/name: ingress-nginx
705 | app.kubernetes.io/instance: ingress-nginx
706 | app.kubernetes.io/version: "1.9.6"
707 | app.kubernetes.io/part-of: ingress-nginx
708 | app.kubernetes.io/managed-by: Helm
709 | app.kubernetes.io/component: admission-webhook
710 | spec:
711 | containers:
712 | - name: patch
713 | image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20231226-1a7112e06@sha256:25d6a5f11211cc5c3f9f2bf552b585374af287b4debf693cacbe2da47daa5084
714 | imagePullPolicy: IfNotPresent
715 | args:
716 | - patch
717 | - --webhook-name=ingress-nginx-admission
718 | - --namespace=$(POD_NAMESPACE)
719 | - --patch-mutating=false
720 | - --secret-name=ingress-nginx-admission
721 | - --patch-failure-policy=Fail
722 | env:
723 | - name: POD_NAMESPACE
724 | valueFrom:
725 | fieldRef:
726 | fieldPath: metadata.namespace
727 | securityContext:
728 | allowPrivilegeEscalation: false
729 | capabilities:
730 | drop:
731 | - ALL
732 | readOnlyRootFilesystem: true
733 | runAsNonRoot: true
734 | runAsUser: 65532
735 | seccompProfile:
736 | type: RuntimeDefault
737 | restartPolicy: OnFailure
738 | serviceAccountName: ingress-nginx-admission
739 | nodeSelector:
740 | kubernetes.io/os: linux
--------------------------------------------------------------------------------