Compare commits

..

No commits in common. "main" and "v2024.10.2" have entirely different histories.

32 changed files with 4130 additions and 3366 deletions

2
.gitignore vendored
View File

@ -4,7 +4,6 @@
.envrc .envrc
.direnv .direnv
.devenv
# Server # Server
/app/server/bin/ /app/server/bin/
@ -17,7 +16,6 @@
/app/frontend/.pnp /app/frontend/.pnp
/app/frontend/.pnp.js /app/frontend/.pnp.js
/app/frontend/.dependency-graph /app/frontend/.dependency-graph
/app/frontend/eslint.shared.mjs
# testing # testing
/app/frontend/coverage /app/frontend/coverage

View File

View File

@ -0,0 +1,46 @@
module.exports = {
env: { browser: true, es2020: true },
extends: [
"eslint:recommended",
"react-app",
"airbnb-typescript",
"airbnb/hooks",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
"plugin:react-hooks/recommended",
"prettier", // Help to cooperate ESLint and Prettier
"plugin:prettier/recommended",
],
ignorePatterns: [
"/build",
"/dist",
"/node_modules",
"/.eslintrc.cjs",
"/vite.config.ts",
],
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaVersion: "latest",
project: "./tsconfig.json",
sourceType: "module",
tsconfigRootDir: __dirname,
},
plugins: ["react-refresh"],
rules: {
// Run prettier separately but use its configuration
// This speeds up on-the-fly linting during development
"prettier/prettier": "off",
"react-refresh/only-export-components": "warn",
"import/no-extraneous-dependencies": [
"error",
{
devDependencies: true,
},
],
},
settings: {
react: {
version: "detect",
},
},
};

View File

@ -0,0 +1,9 @@
/node_modules
# Ignore artifacts:
/build
/dist
/coverage
# generated code
/src/api/naming
/src/preview

4
app/frontend/.prettierrc Normal file
View File

@ -0,0 +1,4 @@
{
"importOrder": ["^[./]"],
"importOrderSeparation": true
}

View File

@ -1,20 +0,0 @@
import sharedConfig from "./eslint.shared.mjs";
export default [
{
ignores: [
"eslint.shared.mjs",
"prettier.config.mjs",
"vite.config.ts"
],
},
...sharedConfig,
{
languageOptions: {
parserOptions: {
tsconfigRootDir: import.meta.dirname,
project: "./tsconfig.app.json",
},
},
}
];

File diff suppressed because it is too large Load Diff

View File

@ -8,13 +8,13 @@
"check": "npm run typecheck && echo \"Checking files with prettier\" && npm run prettier > /dev/null && npm run lint", "check": "npm run typecheck && echo \"Checking files with prettier\" && npm run prettier > /dev/null && npm run lint",
"dev": "vite", "dev": "vite",
"fix": "npm run prettier:format && npm run lint:fix", "fix": "npm run prettier:format && npm run lint:fix",
"lint": "eslint", "lint": "eslint src --ext ts,tsx",
"lint:fix": "eslint --fix", "lint:fix": "eslint --fix src --ext ts,tsx",
"lint:fix:changed": "eslint --fix $(npm run --silent list:changed)", "lint:fix:changed": "eslint --fix $(npm run --silent list:changed)",
"list:changed": "git diff HEAD --name-only --diff-filter=ACM --relative=app/console/src \"*.tsx\" \"*.ts\" \"*.js\" | sed 's#^#./src/#' ; git ls-files \"./src/*.tsx\" \"./src/*.ts\" -o --exclude-standard", "list:changed": "git diff HEAD --name-only --diff-filter=ACM --relative=app/console/src \"*.tsx\" \"*.ts\" \"*.js\" | sed 's#^#./src/#' ; git ls-files \"./src/*.tsx\" \"./src/*.ts\" -o --exclude-standard",
"prettier": "prettier --check 'src/**/*.{js,ts,tsx}'", "prettier": "prettier --config ./.prettierrc --check 'src/**/*.{js,ts,tsx}'",
"prettier:format": "prettier --write 'src/**/*.{js,ts,tsx}'", "prettier:format": "prettier --config ./.prettierrc --write 'src/**/*.{js,ts,tsx}'",
"prettier:format:changed": "prettier --write $(npm run --silent list:changed)", "prettier:format:changed": "prettier --config ./.prettierrc --write $(npm run --silent list:changed)",
"typecheck": "tsc --noEmit" "typecheck": "tsc --noEmit"
}, },
"dependencies": { "dependencies": {
@ -25,28 +25,27 @@
"@emotion/cache": "^11.11.0", "@emotion/cache": "^11.11.0",
"@emotion/react": "^11.11.0", "@emotion/react": "^11.11.0",
"@emotion/styled": "^11.11.0", "@emotion/styled": "^11.11.0",
"@eslint/js": "^9.13.0", "@trivago/prettier-plugin-sort-imports": "^4.1.1",
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@types/react": "^18.0.37", "@types/react": "^18.0.37",
"@types/react-dom": "^18.0.11", "@types/react-dom": "^18.0.11",
"@types/stylis": "^4.2.0", "@types/stylis": "^4.2.0",
"@vitejs/plugin-react-swc": "^3.7.1", "@typescript-eslint/eslint-plugin": "^5.59.0",
"eslint": "^9.13.0", "@typescript-eslint/parser": "^5.59.0",
"@vitejs/plugin-react-swc": "^3.0.0",
"eslint": "^8.38.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^17.0.0",
"eslint-config-prettier": "^8.8.0", "eslint-config-prettier": "^8.8.0",
"eslint-import-resolver-typescript": "^3.6.3", "eslint-config-react-app": "^7.0.1",
"eslint-plugin-formatjs": "^5.1.5", "eslint-plugin-import": "^2.27.5",
"eslint-plugin-import-x": "^4.3.1", "eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-prettier": "^5.2.1", "eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react": "^7.37.2", "eslint-plugin-react-refresh": "^0.3.4",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.14",
"normalize.css": "^8.0.1", "normalize.css": "^8.0.1",
"prettier": "^3.3.3",
"react-intl": "^6.4.2", "react-intl": "^6.4.2",
"react-router-dom": "^6.11.2", "react-router-dom": "^6.11.2",
"stylis": "^4.2.0", "stylis": "^4.2.0",
"typescript": "^5.6.3", "typescript": "^5.0.2",
"typescript-eslint": "^8.11.0", "vite": "^4.3.9"
"vite": "^5.4.10"
} }
} }

View File

@ -1,5 +0,0 @@
export default {
importOrder: ["^[./]"],
importOrderSeparation: true,
plugins: ["@trivago/prettier-plugin-sort-imports"],
};

View File

@ -13,7 +13,7 @@ const themeCache = createCache({
key: "cv", key: "cv",
}); });
const i = themeCache.insert.bind(themeCache); const i = themeCache.insert;
themeCache.insert = (...args) => { themeCache.insert = (...args) => {
args[2].tags.forEach((t) => { args[2].tags.forEach((t) => {
if (!t.getAttribute("media")) { if (!t.getAttribute("media")) {

View File

@ -9,19 +9,19 @@ import { Paragraph } from "../common/Text";
const messages = defineMessages({ const messages = defineMessages({
skills: { skills: {
defaultMessage: "Skills", defaultMessage: "Skills",
id: "4JISx9", id: "Experience.skills",
}, },
}); });
const approxCurrentYears = { const approxCurrentYears = {
InvestBay: Math.round( InvestBay: Math.round(
(Date.now() - new Date("2024-02-01").getTime()) / 1000 / 60 / 60 / 24 / 365, (Date.now() - new Date("2024-02-01").getTime()) / 1000 / 60 / 60 / 24 / 365
), ),
YourPass: Math.round( YourPass: Math.round(
(Date.now() - new Date("2021-06-01").getTime()) / 1000 / 60 / 60 / 24 / 365, (Date.now() - new Date("2021-06-01").getTime()) / 1000 / 60 / 60 / 24 / 365
), ),
YourSystemSysOps: Math.round( YourSystemSysOps: Math.round(
(Date.now() - new Date("2022-01-01").getTime()) / 1000 / 60 / 60 / 24 / 365, (Date.now() - new Date("2022-01-01").getTime()) / 1000 / 60 / 60 / 24 / 365
), ),
}; };
@ -56,7 +56,6 @@ const yourpassSkills = [
"Terraform", "Terraform",
"Go (Programming Language)", "Go (Programming Language)",
"gRPC", "gRPC",
"OWASP ZAP",
"Front-End Development", "Front-End Development",
"React.js", "React.js",
"Node.js", "Node.js",
@ -104,12 +103,12 @@ const Experience: React.FC = () => {
{intl.formatMessage( {intl.formatMessage(
{ {
defaultMessage: "February 2024 - Present", defaultMessage: "February 2024 - Present",
id: "w2Pn7j", id: "Experience.investbay",
}, },
{ {
// not used atm // not used atm
count: approxCurrentYears.InvestBay, count: approxCurrentYears.InvestBay,
}, }
)} )}
</Paragraph> </Paragraph>
<Paragraph> <Paragraph>
@ -127,11 +126,11 @@ const Experience: React.FC = () => {
{intl.formatMessage( {intl.formatMessage(
{ {
defaultMessage: "July 2021 - Present ({count} years)", defaultMessage: "July 2021 - Present ({count} years)",
id: "6T3Cls", id: "Experience.yourpass",
}, },
{ {
count: approxCurrentYears.YourPass, count: approxCurrentYears.YourPass,
}, }
)} )}
</Paragraph> </Paragraph>
<Paragraph> <Paragraph>
@ -150,11 +149,11 @@ const Experience: React.FC = () => {
{intl.formatMessage( {intl.formatMessage(
{ {
defaultMessage: "January 2022 - Present ({count} years)", defaultMessage: "January 2022 - Present ({count} years)",
id: "nqa9U0", id: "Experience.yoursystem",
}, },
{ {
count: approxCurrentYears.YourSystemSysOps, count: approxCurrentYears.YourSystemSysOps,
}, }
)} )}
</Paragraph> </Paragraph>
<Paragraph> <Paragraph>
@ -169,7 +168,7 @@ const Experience: React.FC = () => {
<Paragraph> <Paragraph>
{intl.formatMessage({ {intl.formatMessage({
defaultMessage: "February 2016 - December 2021 (5 years)", defaultMessage: "February 2016 - December 2021 (5 years)",
id: "96SwL8", id: "Experience.yoursystem",
})} })}
</Paragraph> </Paragraph>
<Paragraph> <Paragraph>
@ -187,14 +186,14 @@ const Experience: React.FC = () => {
<Paragraph> <Paragraph>
{intl.formatMessage({ {intl.formatMessage({
defaultMessage: "Birth - February 2016", defaultMessage: "Birth - February 2016",
id: "KtILZ7", id: "Experience.past",
})} })}
</Paragraph> </Paragraph>
<Paragraph> <Paragraph>
{intl.formatMessage({ {intl.formatMessage({
defaultMessage: defaultMessage:
"Working on smaller projects such as chats, forum based websites, web based presentations, most notably a system for handling the driver training center and driving school agenda... Tinkering...", "Working on smaller projects such as chats, forum based websites, web based presentations, most notably a system for handling the driver training center and driving school agenda... Tinkering...",
id: "obpLg6", id: "Experience.pastDescription",
})} })}
</Paragraph> </Paragraph>
</Content> </Content>

View File

@ -1,4 +1,4 @@
import React, { Children } from "react"; import React from "react";
import PageBreakAvoid from "../common/PageBreakAvoid"; import PageBreakAvoid from "../common/PageBreakAvoid";
import { Spacer } from "../common/Spacer"; import { Spacer } from "../common/Spacer";
@ -15,7 +15,7 @@ const Skill: React.FC<React.PropsWithChildren<SkillProps>> = (props) => {
<PageBreakAvoid> <PageBreakAvoid>
<strong>{title}</strong> <strong>{title}</strong>
<Spacer /> <Spacer />
{Children.map(children, (c) => ( {React.Children.map(children, (c) => (
<Paragraph>{c}</Paragraph> <Paragraph>{c}</Paragraph>
))} ))}
</PageBreakAvoid> </PageBreakAvoid>

View File

@ -16,12 +16,12 @@ type OtherSkill = {
const otherSkills: OtherSkill[] = [ const otherSkills: OtherSkill[] = [
{ {
title: "Strong proficiency in", title: "Strong proficiency in",
description: "IaaC tooling, Go, Typescript (and Javascript), Bash", description: "Go, Typescript (and Javascript), Bash, IaaC tools",
}, },
{ {
title: "Infrastructure related skills", title: "Infrastructure related skills",
description: description:
"Kubernetes and AWS EKS, Containerized applications, Linux system administration, Amazon Web Services - good understanding of Networking, Databases, Queues and many other managed services. Notable experience with GCP/Azure. Experience with most major platforms such as Github, Gitlab, Gitea, Bitbucket and their tooling.", "Kubernetes and AWS EKS, Containerized applications, Linux system administration, Amazon Web Services - good understanding of Networking, RDS, Queues. Notable experience with GCP/Azure.",
}, },
{ {
title: "Databases", title: "Databases",
@ -30,7 +30,7 @@ const otherSkills: OtherSkill[] = [
{ {
title: "Some of the relevant Frameworks/Tooling", title: "Some of the relevant Frameworks/Tooling",
description: description:
"Terraform, Prometheus, Grafana, InfluxDB, Prometheus, Elasticsearch, Nix, OWASP ZAP, React, Esbuild, deep understanding of Git", "Terraform, Prometheus, Grafana, Nix shell, React, Webpack, Rollup, Esbuild, deep understanding of Git",
}, },
{ {
title: "Software Development", title: "Software Development",
@ -56,45 +56,45 @@ const Skills: React.FC = () => {
{intl.formatMessage({ {intl.formatMessage({
defaultMessage: defaultMessage:
"Several years of experience developing, maintaining and adhering to the DevOps practices to streamline organization's processes across both backend and frontend development.", "Several years of experience developing, maintaining and adhering to the DevOps practices to streamline organization's processes across both backend and frontend development.",
id: "BOZ+do", id: "Skills.devops",
})}
</Skill>
<Skill title="Infrastructure operations">
{intl.formatMessage({
defaultMessage:
"Throughout my career, I have gained valuable experience in developing, maintaining and monitoring high-load infrastructure clusters.",
id: "PKLG9N",
})}
{intl.formatMessage({
defaultMessage:
"Following the OCI (Open Container Initiative) and leveraging Docker and Kubernetes to create highly available deployments, primarily on the AWS platform, was a challenging and enjoyable experience, that has greatly enhanced my skills in this area.",
id: "VRhCte",
})}
</Skill>
<Skill title="Back-End Development">
{intl.formatMessage({
defaultMessage:
"Deep knowledge of backend operations, mostly supporting web based applications using various technologies, programming languages and frameworks.",
id: "h4cHqQ",
})}
{intl.formatMessage({
defaultMessage:
"In recent years, my focus was on Go to write tooling and backend services.",
id: "y/ymnB",
})} })}
</Skill> </Skill>
<Skill title="Front-End Development"> <Skill title="Front-End Development">
{intl.formatMessage({ {intl.formatMessage({
defaultMessage: defaultMessage:
"Extensive experience in frontend development spanning back to the early 2000s.", "Extensive experience in frontend development spanning back to the early 2000s.",
id: "AjT8sf", id: "Skills.frontendDevelopment",
})}
</Skill>
<Skill title="Back-End Development">
{intl.formatMessage({
defaultMessage:
"Deep knowledge of backend operations, mostly supporting web based applications using various technologies, programming languages and frameworks.",
id: "Skills.backendDevelopmentSum1",
})}
{intl.formatMessage({
defaultMessage:
"In recent years, the main focus was on Go to write tooling and backend services.",
id: "Skills.backendDevelopmentSum2",
})}
</Skill>
<Skill title="Infrastructure operations">
{intl.formatMessage({
defaultMessage:
"Throughout my career, I have gained valuable experience in developing and maintaining high-load infrastructures over several years.",
id: "Skills.infrastructureOperations",
})}
{intl.formatMessage({
defaultMessage:
"Following the OCI (Open Container Initiative) and leveraging Docker and Kubernetes to create highly available deployments, primarily on the AWS platform, was a challenging and enjoyable experience, that has greatly enhanced my skills in this area.",
id: "Skills.infrastructureOperationsAdditional",
})} })}
</Skill> </Skill>
<Spacer withDivider /> <Spacer withDivider />
<SubHeadline level={4}> <SubHeadline level={4}>
{intl.formatMessage({ {intl.formatMessage({
defaultMessage: "Other notable skills", defaultMessage: "Other notable skills",
id: "8NqNwY", id: "Skills.otherNotableSkills",
})} })}
</SubHeadline> </SubHeadline>
<List> <List>

View File

@ -1,6 +1,7 @@
import React from "react"; import React from "react";
import { Paragraph, Caption } from "../common/Text"; import { Paragraph } from "../common/Text";
import { Caption } from "../common/Text";
const Summary: React.FC = () => { const Summary: React.FC = () => {
return ( return (

View File

@ -1,22 +1,22 @@
import React, { Component } from "react"; import React from "react";
type ErrorHandler = (error: Error, info: React.ErrorInfo) => void; type ErrorHandler = (error: Error, info: React.ErrorInfo) => void;
type ErrorHandlingComponent<Props> = ( type ErrorHandlingComponent<Props> = (
props: Props, props: Props,
error?: Error, error?: Error
) => React.ReactNode; ) => React.ReactNode;
type ErrorState = { error?: Error }; type ErrorState = { error?: Error };
function Catch<Props extends object>( function Catch<Props extends object>(
component: ErrorHandlingComponent<Props>, component: ErrorHandlingComponent<Props>,
errorHandler?: ErrorHandler, errorHandler?: ErrorHandler
): React.ComponentType<Props> { ): React.ComponentType<Props> {
function Inner({ error, props }: { error?: Error; props: Props }) { function Inner({ error, props }: { error?: Error; props: Props }) {
return <React.Fragment>{component(props, error)}</React.Fragment>; return <React.Fragment>{component(props, error)}</React.Fragment>;
} }
return class CatchClass extends Component<Props, ErrorState> { return class CatchClass extends React.Component<Props, ErrorState> {
state: ErrorState = { state: ErrorState = {
error: undefined, error: undefined,
}; };
@ -46,7 +46,7 @@ const divStyles: React.CSSProperties = {
const ErrorBoundary = Catch(function ( const ErrorBoundary = Catch(function (
props: React.PropsWithChildren, props: React.PropsWithChildren,
error?: Error, error?: Error
) { ) {
if (error) { if (error) {
return ( return (

View File

@ -6,10 +6,6 @@ import { hideNavigationMQ } from "./navigationBreakpoint";
const Root = styled("div")({ const Root = styled("div")({
background: "rgb(215, 215, 215)", background: "rgb(215, 215, 215)",
"@media print": {
// Nav background
background: "rgb(41, 62, 73)",
},
}); });
const Container = styled("div")({ const Container = styled("div")({

View File

@ -78,7 +78,7 @@ const MainNavigation: React.FC = () => {
<NavigationHeadline> <NavigationHeadline>
{intl.formatMessage({ {intl.formatMessage({
defaultMessage: "Contact", defaultMessage: "Contact",
id: "s3RWxF", id: "Navigation.contact",
})} })}
</NavigationHeadline> </NavigationHeadline>
@ -89,28 +89,14 @@ const MainNavigation: React.FC = () => {
<NavigationHeadline href="#objective"> <NavigationHeadline href="#objective">
{intl.formatMessage({ {intl.formatMessage({
defaultMessage: "Objective", defaultMessage: "Objective",
id: "UMiSC4", id: "Navigation.objective",
})} })}
</NavigationHeadline> </NavigationHeadline>
<Spacer />
<List>
<ListItem>
{intl.formatMessage(
{
defaultMessage: "If there is a need,{br}there is a path.",
id: "Wg8h9t",
},
{ br: <br /> },
)}
</ListItem>
</List>
<NavigationHeadline href="#skills"> <NavigationHeadline href="#skills">
{intl.formatMessage({ {intl.formatMessage({
defaultMessage: "Top Skills", defaultMessage: "Top Skills",
id: "JUWjX4", id: "Navigation.topSkills",
})} })}
</NavigationHeadline> </NavigationHeadline>
@ -133,7 +119,7 @@ const MainNavigation: React.FC = () => {
<NavigationHeadline> <NavigationHeadline>
{intl.formatMessage({ {intl.formatMessage({
defaultMessage: "Certifications", defaultMessage: "Certifications",
id: "tl429z", id: "Navigation.certifications",
})} })}
</NavigationHeadline> </NavigationHeadline>
@ -149,7 +135,7 @@ const MainNavigation: React.FC = () => {
<NavigationHeadline href="#experience"> <NavigationHeadline href="#experience">
{intl.formatMessage({ {intl.formatMessage({
defaultMessage: "Experience", defaultMessage: "Experience",
id: "W1qv5r", id: "Navigation.experience",
})} })}
</NavigationHeadline> </NavigationHeadline>
</StickyWrapper> </StickyWrapper>

View File

@ -25,18 +25,18 @@ const Space = styled("div", { shouldForwardProp })<SpaceProps>(
({ spacing, theme }) => ({ ({ spacing, theme }) => ({
width: "100%", width: "100%",
height: theme.spacing(spacing === undefined ? 1 : spacing), height: theme.spacing(spacing === undefined ? 1 : spacing),
}), })
); );
const Spacer: React.FC<SpacerProps> = (props) => { const Spacer: React.FC<SpacerProps> = (props) => {
const { spacing, withDivider } = props; const { spacing, withDivider } = props;
if (!withDivider) { if (!withDivider) {
const spaceSize = spacing === undefined ? 2 : spacing; const spaceSize = typeof spacing === undefined ? 2 : spacing;
return <Space spacing={spaceSize} />; return <Space spacing={spaceSize} />;
} }
const spaceSize = spacing === undefined ? 1 : spacing; const spaceSize = typeof spacing === undefined ? 1 : spacing;
return ( return (
<Root> <Root>

View File

@ -28,21 +28,15 @@ export const BUILD_TIMESTAMP: Date = window.APP_CONFIG?.commitTime
export const CONTACT_EMAIL = confString( export const CONTACT_EMAIL = confString(
window.APP_CONFIG?.contactEmail, window.APP_CONFIG?.contactEmail,
typeof import.meta.env.VITE_CONTACT_EMAIL === "string" import.meta.env.VITE_CONTACT_EMAIL || ""
? import.meta.env.VITE_CONTACT_EMAIL
: "",
); );
export const CONTACT_PHONE = confString( export const CONTACT_PHONE = confString(
window.APP_CONFIG?.contactPhone, window.APP_CONFIG?.contactPhone,
typeof import.meta.env.VITE_CONTACT_PHONE === "string" import.meta.env.VITE_CONTACT_PHONE || ""
? import.meta.env.VITE_CONTACT_PHONE
: "",
); );
export const POSITION = confString( export const POSITION = confString(
window.APP_CONFIG?.position, window.APP_CONFIG?.position,
typeof import.meta.env.VITE_POSITION === "string" import.meta.env.VITE_POSITION || ""
? import.meta.env.VITE_POSITION
: "",
); );

View File

@ -1,10 +1,10 @@
import React from "react"; import React from "react";
import { createRoot } from "react-dom/client"; import ReactDOM from "react-dom/client";
import App from "./App"; import App from "./App";
createRoot(document.getElementById("root") as HTMLElement).render( ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
<React.StrictMode> <React.StrictMode>
<App /> <App />
</React.StrictMode>, </React.StrictMode>
); );

View File

@ -28,7 +28,7 @@ const Dashboard: React.FC = () => {
<SubHeadline level={4}> <SubHeadline level={4}>
{intl.formatMessage({ {intl.formatMessage({
defaultMessage: "Central Bohemia, Czechia", defaultMessage: "Central Bohemia, Czechia",
id: "Lkk994", id: "Dashboard.location",
})} })}
</SubHeadline> </SubHeadline>
@ -43,14 +43,13 @@ const Dashboard: React.FC = () => {
<Summary /> <Summary />
</Content> </Content>
<Spacer withDivider />
<div id="skills" /> <div id="skills" />
<Spacer withDivider />
<Headline level={2}> <Headline level={2}>
{intl.formatMessage({ {intl.formatMessage({
defaultMessage: "Skills", defaultMessage: "Skills",
id: "4JISx9", id: "Dashboard.skillsTitle",
})} })}
</Headline> </Headline>
<Spacer /> <Spacer />
@ -58,14 +57,13 @@ const Dashboard: React.FC = () => {
<Skills /> <Skills />
</Content> </Content>
<Spacer withDivider />
<div id="experience" /> <div id="experience" />
<Spacer withDivider />
<Headline level={2}> <Headline level={2}>
{intl.formatMessage({ {intl.formatMessage({
defaultMessage: "Experience", defaultMessage: "Experience",
id: "W1qv5r", id: "Dashboard.experienceTitle",
})} })}
</Headline> </Headline>
<Spacer /> <Spacer />

View File

@ -21,7 +21,7 @@ const NotFound = () => {
<p> <p>
{intl.formatMessage({ {intl.formatMessage({
defaultMessage: "Nothing to see here", defaultMessage: "Nothing to see here",
id: "ywIjM0", id: "Router.NotFound",
})} })}
</p> </p>
<Link to="/">Go home</Link> <Link to="/">Go home</Link>

View File

@ -1,5 +1,6 @@
import React, { lazy } from "react"; import React from "react";
import { Outlet, RouterProvider, createBrowserRouter } from "react-router-dom"; import { Outlet, RouterProvider } from "react-router-dom";
import { createBrowserRouter } from "react-router-dom";
import { ErrorBoundary } from "../components/ErrorBoundary"; import { ErrorBoundary } from "../components/ErrorBoundary";
import Dashboard from "./Dashboard"; import Dashboard from "./Dashboard";
@ -12,7 +13,7 @@ const Layout: React.FC = () => {
); );
}; };
const NotFound = lazy(() => import("./NotFound")); const NotFound = React.lazy(() => import("./NotFound"));
const router = createBrowserRouter([ const router = createBrowserRouter([
{ {

View File

@ -1,28 +0,0 @@
{
"compilerOptions": {
"composite": true,
"allowSyntheticDefaultImports": true,
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2021", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "Bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["src"]
}

View File

@ -1,7 +1,23 @@
{ {
"files": [], "compilerOptions": {
"references": [ "target": "ES2020",
{ "path": "./tsconfig.app.json" }, "useDefineForClassFields": true,
{ "path": "./tsconfig.node.json" } "lib": ["ES2020", "DOM", "DOM.Iterable"],
] "module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"]
} }

View File

@ -1,25 +0,0 @@
{
"compilerOptions": {
"composite": true,
"allowSyntheticDefaultImports": true,
"target": "ES2022",
"lib": ["ES2023"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "Bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["vite.config.ts"]
}

View File

@ -7,10 +7,9 @@ import (
"os" "os"
"time" "time"
"go.c3c.cz/cv/app/server/internal/version"
"go.uber.org/zap" "go.uber.org/zap"
"go.uber.org/zap/zapcore" "go.uber.org/zap/zapcore"
"go.c3c.cz/cv/app/server/internal/version"
) )
type FrontendConfigDef struct { type FrontendConfigDef struct {

View File

@ -14,10 +14,9 @@ import (
"strings" "strings"
"time" "time"
"go.uber.org/zap"
"go.c3c.cz/cv/app/server/internal/files" "go.c3c.cz/cv/app/server/internal/files"
"go.c3c.cz/cv/app/server/internal/version" "go.c3c.cz/cv/app/server/internal/version"
"go.uber.org/zap"
) )
type handler struct { type handler struct {

View File

@ -10,9 +10,8 @@ import (
"net/http" "net/http"
"time" "time"
"go.uber.org/zap"
"go.c3c.cz/cv/app/server/internal/files" "go.c3c.cz/cv/app/server/internal/files"
"go.uber.org/zap"
) )
func init() { func init() {

View File

@ -8,12 +8,11 @@ import (
"os/signal" "os/signal"
"syscall" "syscall"
"go.uber.org/zap"
"go.c3c.cz/cv/app/server/internal/config" "go.c3c.cz/cv/app/server/internal/config"
"go.c3c.cz/cv/app/server/internal/httpserver" "go.c3c.cz/cv/app/server/internal/httpserver"
"go.c3c.cz/cv/app/server/internal/pprofserver" "go.c3c.cz/cv/app/server/internal/pprofserver"
"go.c3c.cz/cv/app/server/internal/version" "go.c3c.cz/cv/app/server/internal/version"
"go.uber.org/zap"
) )
func main() { func main() {

View File

@ -1,314 +1,37 @@
{ {
"nodes": { "nodes": {
"cachix": { "devshell": {
"inputs": { "inputs": {
"devenv": "devenv_2",
"flake-compat": [
"nix",
"devenv",
"flake-compat"
],
"git-hooks": [
"nix",
"devenv",
"pre-commit-hooks"
],
"nixpkgs": [
"nix",
"devenv",
"nixpkgs"
]
},
"locked": {
"lastModified": 1726520618,
"narHash": "sha256-jOsaBmJ/EtX5t/vbylCdS7pWYcKGmWOKg4QKUzKr6dA=",
"owner": "cachix",
"repo": "cachix",
"rev": "695525f9086542dfb09fde0871dbf4174abbf634",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "cachix",
"type": "github"
}
},
"cachix_2": {
"inputs": {
"devenv": "devenv_3",
"flake-compat": [
"nix",
"devenv",
"cachix",
"devenv",
"flake-compat"
],
"nixpkgs": [
"nix",
"devenv",
"cachix",
"devenv",
"nixpkgs"
],
"pre-commit-hooks": [
"nix",
"devenv",
"cachix",
"devenv",
"pre-commit-hooks"
]
},
"locked": {
"lastModified": 1712055811,
"narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=",
"owner": "cachix",
"repo": "cachix",
"rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "cachix",
"type": "github"
}
},
"devenv": {
"inputs": {
"cachix": "cachix",
"flake-compat": "flake-compat_2",
"nix": "nix_4",
"nixpkgs": [ "nixpkgs": [
"nix", "nix",
"nixpkgs" "nixpkgs"
],
"pre-commit-hooks": "pre-commit-hooks_2"
},
"locked": {
"lastModified": 1729857292,
"narHash": "sha256-+uYhri8aC9Jdu6fSfjkFOmBIYVWYQnF6mdFj+ophud0=",
"owner": "cachix",
"repo": "devenv",
"rev": "d9156ba99fed6f4bc4d84b8ff1b442f04a98210a",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "devenv",
"type": "github"
}
},
"devenv_2": {
"inputs": {
"cachix": "cachix_2",
"flake-compat": [
"nix",
"devenv",
"cachix",
"flake-compat"
],
"nix": "nix_3",
"nixpkgs": [
"nix",
"devenv",
"cachix",
"nixpkgs"
],
"pre-commit-hooks": [
"nix",
"devenv",
"cachix",
"git-hooks"
] ]
}, },
"locked": { "locked": {
"lastModified": 1723156315, "lastModified": 1728330715,
"narHash": "sha256-0JrfahRMJ37Rf1i0iOOn+8Z4CLvbcGNwa2ChOAVrp/8=", "narHash": "sha256-xRJ2nPOXb//u1jaBnDP56M7v5ldavjbtR6lfGqSvcKg=",
"owner": "cachix",
"repo": "devenv",
"rev": "ff5eb4f2accbcda963af67f1a1159e3f6c7f5f91",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "devenv",
"type": "github"
}
},
"devenv_3": {
"inputs": {
"flake-compat": [
"nix",
"devenv",
"cachix",
"devenv",
"cachix",
"flake-compat"
],
"nix": "nix_2",
"nixpkgs": "nixpkgs",
"poetry2nix": "poetry2nix",
"pre-commit-hooks": [
"nix",
"devenv",
"cachix",
"devenv",
"cachix",
"pre-commit-hooks"
]
},
"locked": {
"lastModified": 1708704632,
"narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=",
"owner": "cachix",
"repo": "devenv",
"rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196",
"type": "github"
},
"original": {
"owner": "cachix",
"ref": "python-rewrite",
"repo": "devenv",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1673956053,
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-compat_2": {
"flake": false,
"locked": {
"lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": [
"nix",
"devenv",
"nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1712014858,
"narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "9126214d0a59633752a136528f5f3b9aa8565b7d",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1689068808,
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "devshell",
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", "rev": "dd6b80932022cea34a019e2bb32f6fa9e494dfef",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "devshell",
"type": "github"
}
},
"flake-utils_2": {
"locked": {
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"nix",
"devenv",
"pre-commit-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"libgit2": {
"flake": false,
"locked": {
"lastModified": 1697646580,
"narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=",
"owner": "libgit2",
"repo": "libgit2",
"rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5",
"type": "github"
},
"original": {
"owner": "libgit2",
"repo": "libgit2",
"type": "github" "type": "github"
} }
}, },
"nix": { "nix": {
"inputs": { "inputs": {
"devenv": "devenv", "devshell": "devshell",
"nixpkgs": "nixpkgs_3" "nixpkgs": "nixpkgs"
}, },
"locked": { "locked": {
"lastModified": 1729891574, "lastModified": 1729027123,
"narHash": "sha256-OOAwctBTUwKc9yTvvK1+sbcGcYqHSYvI060DlczMUbI=", "narHash": "sha256-LjD40ya8efdhxQ26Zy/LkLDOriZIHJZqutAorvPIka8=",
"ref": "refs/heads/main", "ref": "refs/heads/main",
"rev": "986890b04467a51533b03a5d5c4cf4ea5ebc4cbb", "rev": "d3596fc7e933c171a284771f7f72342d33ad6508",
"revCount": 7, "revCount": 5,
"type": "git", "type": "git",
"url": "ssh://git@git.c3c.cz/C3C/nix" "url": "ssh://git@git.c3c.cz/C3C/nix"
}, },
@ -317,237 +40,7 @@
"url": "ssh://git@git.c3c.cz/C3C/nix" "url": "ssh://git@git.c3c.cz/C3C/nix"
} }
}, },
"nix-github-actions": {
"inputs": {
"nixpkgs": [
"nix",
"devenv",
"cachix",
"devenv",
"cachix",
"devenv",
"poetry2nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1688870561,
"narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=",
"owner": "nix-community",
"repo": "nix-github-actions",
"rev": "165b1650b753316aa7f1787f3005a8d2da0f5301",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nix-github-actions",
"type": "github"
}
},
"nix_2": {
"inputs": {
"flake-compat": "flake-compat",
"nixpkgs": [
"nix",
"devenv",
"cachix",
"devenv",
"cachix",
"devenv",
"nixpkgs"
],
"nixpkgs-regression": "nixpkgs-regression"
},
"locked": {
"lastModified": 1712911606,
"narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
"owner": "domenkozar",
"repo": "nix",
"rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
"type": "github"
},
"original": {
"owner": "domenkozar",
"ref": "devenv-2.21",
"repo": "nix",
"type": "github"
}
},
"nix_3": {
"inputs": {
"flake-compat": [
"nix",
"devenv",
"cachix",
"devenv",
"flake-compat"
],
"nixpkgs": [
"nix",
"devenv",
"cachix",
"devenv",
"nixpkgs"
],
"nixpkgs-regression": "nixpkgs-regression_2"
},
"locked": {
"lastModified": 1712911606,
"narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
"owner": "domenkozar",
"repo": "nix",
"rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
"type": "github"
},
"original": {
"owner": "domenkozar",
"ref": "devenv-2.21",
"repo": "nix",
"type": "github"
}
},
"nix_4": {
"inputs": {
"flake-compat": [
"nix",
"devenv",
"flake-compat"
],
"flake-parts": "flake-parts",
"libgit2": "libgit2",
"nixpkgs": "nixpkgs_2",
"nixpkgs-23-11": "nixpkgs-23-11",
"nixpkgs-regression": "nixpkgs-regression_3",
"pre-commit-hooks": "pre-commit-hooks"
},
"locked": {
"lastModified": 1727438425,
"narHash": "sha256-X8ES7I1cfNhR9oKp06F6ir4Np70WGZU5sfCOuNBEwMg=",
"owner": "domenkozar",
"repo": "nix",
"rev": "f6c5ae4c1b2e411e6b1e6a8181cc84363d6a7546",
"type": "github"
},
"original": {
"owner": "domenkozar",
"ref": "devenv-2.24",
"repo": "nix",
"type": "github"
}
},
"nixpkgs": { "nixpkgs": {
"locked": {
"lastModified": 1692808169,
"narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "9201b5ff357e781bf014d0330d18555695df7ba8",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-23-11": {
"locked": {
"lastModified": 1717159533,
"narHash": "sha256-oamiKNfr2MS6yH64rUn99mIZjc45nGJlj9eGth/3Xuw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a62e6edd6d5e1fa0329b8653c801147986f8d446",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a62e6edd6d5e1fa0329b8653c801147986f8d446",
"type": "github"
}
},
"nixpkgs-regression": {
"locked": {
"lastModified": 1643052045,
"narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "github"
}
},
"nixpkgs-regression_2": {
"locked": {
"lastModified": 1643052045,
"narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "github"
}
},
"nixpkgs-regression_3": {
"locked": {
"lastModified": 1643052045,
"narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "github"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1720386169,
"narHash": "sha256-NGKVY4PjzwAa4upkGtAMz1npHGoRzWotlSnVlqI40mo=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "194846768975b7ad2c4988bdb82572c00222c0d7",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-24.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1717432640,
"narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "88269ab3044128b7c2f4c7d68448b2fb50456870",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "release-24.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_3": {
"locked": { "locked": {
"lastModified": 1728538411, "lastModified": 1728538411,
"narHash": "sha256-f0SBJz1eZ2yOuKUr5CA9BHULGXVSn6miBuUWdTyhUhU=", "narHash": "sha256-f0SBJz1eZ2yOuKUr5CA9BHULGXVSn6miBuUWdTyhUhU=",
@ -563,122 +56,10 @@
"type": "github" "type": "github"
} }
}, },
"poetry2nix": {
"inputs": {
"flake-utils": "flake-utils",
"nix-github-actions": "nix-github-actions",
"nixpkgs": [
"nix",
"devenv",
"cachix",
"devenv",
"cachix",
"devenv",
"nixpkgs"
]
},
"locked": {
"lastModified": 1692876271,
"narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=",
"owner": "nix-community",
"repo": "poetry2nix",
"rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "poetry2nix",
"type": "github"
}
},
"pre-commit-hooks": {
"inputs": {
"flake-compat": [
"nix",
"devenv",
"nix"
],
"flake-utils": "flake-utils_2",
"gitignore": [
"nix",
"devenv",
"nix"
],
"nixpkgs": [
"nix",
"devenv",
"nix",
"nixpkgs"
],
"nixpkgs-stable": [
"nix",
"devenv",
"nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1712897695,
"narHash": "sha256-nMirxrGteNAl9sWiOhoN5tIHyjBbVi5e2tgZUgZlK3Y=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "40e6053ecb65fcbf12863338a6dcefb3f55f1bf8",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"type": "github"
}
},
"pre-commit-hooks_2": {
"inputs": {
"flake-compat": [
"nix",
"devenv",
"flake-compat"
],
"gitignore": "gitignore",
"nixpkgs": [
"nix",
"devenv",
"nixpkgs"
],
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1726745158,
"narHash": "sha256-D5AegvGoEjt4rkKedmxlSEmC+nNLMBPWFxvmYnVLhjk=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "4e743a6920eab45e8ba0fbe49dc459f1423a4b74",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"type": "github"
}
},
"root": { "root": {
"inputs": { "inputs": {
"nix": "nix" "nix": "nix"
} }
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
} }
}, },
"root": "root", "root": "root",

View File

@ -15,20 +15,12 @@
package = builtins.fromJSON (builtins.readFile ./app/frontend/package.json); package = builtins.fromJSON (builtins.readFile ./app/frontend/package.json);
in in
rec { rec {
devenv-up = self.devShells.${pkgs.system}.default.config.procfileScript;
devenv-test = self.devShells.${pkgs.system}.default.config.test;
ui = pkgs.buildNpmPackage { ui = pkgs.buildNpmPackage {
inherit version; inherit version;
pname = "cv"; pname = "cv";
src = ./app/frontend; src = ./app/frontend;
preBuild = ''
cp ${nix.lib.eslint-config-file} ./eslint.shared.mjs
npm run check
'';
npmInstallFlags = "--no-audit --no-progress --no-fund"; npmInstallFlags = "--no-audit --no-progress --no-fund";
npmDepsHash = "sha256-P+TNtlilrzlnkclZtYrG163ucEavm9koei69ZG3sOSM="; npmDepsHash = "sha256-p4rTpy0t8aajbubvtF1TA83/FFqvfKEOPBb5T0ZRfQY=";
npmPackFlags = [ "--ignore-scripts" ]; npmPackFlags = [ "--ignore-scripts" ];
}; };
@ -72,29 +64,19 @@
); );
devShells = nix.lib.forAllSystems (pkgs: { devShells = nix.lib.forAllSystems (pkgs: {
default = nix.lib.mkDevenvShell { default = pkgs.devshell.mkShell {
inherit pkgs; name = "c3c-cv";
inputs = {
self = self;
nixpkgs = pkgs;
};
modules = [
{
packages = [ packages = [
pkgs.go pkgs.go
pkgs.nodejs_22 pkgs.nodejs_22
]; ];
enterShell = '' commands = [
cp -f ${nix.lib.eslint-config-file} ./app/frontend/eslint.shared.mjs {
'';
scripts = {
# Override golangci-lint for vscode, because the extension incorrectly assumes usage of global binaries is preferred # Override golangci-lint for vscode, because the extension incorrectly assumes usage of global binaries is preferred
golangci-lint = { name = "golangci-lint";
exec = '' command = ''
CMD=''${1:-} CMD=''${1:-}
if [[ "$CMD" == "run" ]]; then if [[ "$CMD" == "run" ]]; then
shift shift
@ -103,46 +85,47 @@
${pkgs.golangci-lint}/bin/golangci-lint $@ ${pkgs.golangci-lint}/bin/golangci-lint $@
fi fi
''; '';
}; }
{
lint = { name = "lint";
exec = '' help = "run linters";
command = ''
${nix.lib.cd_root} ${nix.lib.cd_root}
${pkgs.golangci-lint}/bin/golangci-lint run --sort-results --out-format tab --config ${nix.lib.golangci-config-file} ./... ${pkgs.golangci-lint}/bin/golangci-lint run --sort-results --out-format tab --config ${nix.lib.golangci-config-file} ./...
npm --prefix app/frontend run check npm --prefix app/frontend run check
''; '';
}; }
{
fix = { name = "fix";
exec = '' help = "format & fix found issues";
command = ''
${nix.lib.cd_root} ${nix.lib.cd_root}
nix fmt ./*.nix nix fmt ./*.nix
${pkgs.golangci-lint}/bin/golangci-lint run --sort-results --out-format tab --config ${nix.lib.golangci-config-file} --fix --issues-exit-code 0 ./... ${pkgs.golangci-lint}/bin/golangci-lint run --sort-results --out-format tab --config ${nix.lib.golangci-config-file} --fix --issues-exit-code 0 ./...
npm --prefix app/frontend run fix npm --prefix app/frontend run fix
''; '';
}; }
{
update-npm-deps-hash = { name = "update-npm-deps-hash";
exec = '' help = "Calculates and updates the npmDepsHash in default.nix";
command = ''
${nix.lib.cd_root} ${nix.lib.cd_root}
echo "Calculating npm deps" echo "Calculating npm deps"
# STDERR is poluted by the installed nodules, silencing # STDERR is poluted by the installed nodules, silencing
HASH=''$(${pkgs.prefetch-npm-deps}/bin/prefetch-npm-deps ./app/frontend/package-lock.json 2> /dev/null) HASH=''$(${pkgs.prefetch-npm-deps}/bin/prefetch-npm-deps ''$PRJ_ROOT/app/frontend/package-lock.json 2> /dev/null)
[[ ''$HASH = sha256* ]] && echo "Hash is ''$HASH" [[ ''$HASH = sha256* ]] && echo "Hash is ''$HASH"
[[ ''$HASH != sha256* ]] && echo "Failed" && exit 137 [[ ''$HASH != sha256* ]] && echo "Failed" && exit 137
# Replace the first occurence of npmDepsHash with the new calculated hash in this file # Replace the first occurence of npmDepsHash with the new calculated hash in this file
sed -i "0,/npmDepsHash =/{s@npmDepsHash = .*@npmDepsHash = \"''$HASH\";@}" ./flake.nix sed -i "0,/npmDepsHash =/{s@npmDepsHash = .*@npmDepsHash = \"''$HASH\";@}" ./flake.nix
''; '';
}; }
{
dev = { name = "dev";
exec = '' help = "Starts the javascript project in dev";
${nix.lib.cd_root} command = ''
npm --prefix ./app/frontend run dev npm --prefix ''$PRJ_ROOT/app/frontend run dev
''; '';
};
};
} }
]; ];
}; };