10 Commits

Author SHA1 Message Date
Arnie a0980213fd Update npm deps hash
continuous-integration/drone/tag Build is passing
2024-10-25 23:49:08 +02:00
Arnie 344d34d3f5 Fix lint errors in server 2024-10-25 23:48:28 +02:00
Arnie 08a45037fa Update frontend linting 2024-10-25 23:48:13 +02:00
Arnie 31eebd8dab Implement shared eslint config through devenv 2024-10-25 23:47:55 +02:00
Arnie 4124de9311 Update flakes 2024-10-25 23:27:12 +02:00
Arnie 302d3aa4ab Update tsconfig
continuous-integration/drone/tag Build is failing
2024-10-25 10:22:16 +02:00
Arnie 0d74fd01bc Change the nav sticky behavior
continuous-integration/drone/tag Build is passing
2024-10-24 14:35:43 +02:00
Arnie ea5fed1bf9 Formatting
continuous-integration/drone/tag Build is passing
2024-10-24 13:20:19 +02:00
Arnie 373f01c9c2 Update skills, page breaks and add profile picture
continuous-integration/drone/tag Build is failing
2024-10-24 13:15:06 +02:00
Arnie df24388d95 Fix translation ids 2024-10-21 14:52:24 +02:00
32 changed files with 2996 additions and 4065 deletions
+2
View File
@@ -4,6 +4,7 @@
.envrc
.direnv
.devenv
# Server
/app/server/bin/
@@ -16,6 +17,7 @@
/app/frontend/.pnp
/app/frontend/.pnp.js
/app/frontend/.dependency-graph
/app/frontend/eslint.shared.mjs
# testing
/app/frontend/coverage
View File
-46
View File
@@ -1,46 +0,0 @@
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",
},
},
};
-9
View File
@@ -1,9 +0,0 @@
/node_modules
# Ignore artifacts:
/build
/dist
/coverage
# generated code
/src/api/naming
/src/preview
-4
View File
@@ -1,4 +0,0 @@
{
"importOrder": ["^[./]"],
"importOrderSeparation": true
}
+20
View File
@@ -0,0 +1,20 @@
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",
},
},
}
];
+1934 -3693
View File
File diff suppressed because it is too large Load Diff
+18 -17
View File
@@ -8,13 +8,13 @@
"check": "npm run typecheck && echo \"Checking files with prettier\" && npm run prettier > /dev/null && npm run lint",
"dev": "vite",
"fix": "npm run prettier:format && npm run lint:fix",
"lint": "eslint src --ext ts,tsx",
"lint:fix": "eslint --fix src --ext ts,tsx",
"lint": "eslint",
"lint:fix": "eslint --fix",
"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",
"prettier": "prettier --config ./.prettierrc --check 'src/**/*.{js,ts,tsx}'",
"prettier:format": "prettier --config ./.prettierrc --write 'src/**/*.{js,ts,tsx}'",
"prettier:format:changed": "prettier --config ./.prettierrc --write $(npm run --silent list:changed)",
"prettier": "prettier --check 'src/**/*.{js,ts,tsx}'",
"prettier:format": "prettier --write 'src/**/*.{js,ts,tsx}'",
"prettier:format:changed": "prettier --write $(npm run --silent list:changed)",
"typecheck": "tsc --noEmit"
},
"dependencies": {
@@ -25,27 +25,28 @@
"@emotion/cache": "^11.11.0",
"@emotion/react": "^11.11.0",
"@emotion/styled": "^11.11.0",
"@trivago/prettier-plugin-sort-imports": "^4.1.1",
"@eslint/js": "^9.13.0",
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@types/react": "^18.0.37",
"@types/react-dom": "^18.0.11",
"@types/stylis": "^4.2.0",
"@typescript-eslint/eslint-plugin": "^5.59.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": "^9.13.0",
"eslint-config-prettier": "^8.8.0",
"eslint-config-react-app": "^7.0.1",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.3.4",
"eslint-import-resolver-typescript": "^3.6.3",
"eslint-plugin-formatjs": "^5.1.5",
"eslint-plugin-import-x": "^4.3.1",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react": "^7.37.2",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.14",
"normalize.css": "^8.0.1",
"prettier": "^3.3.3",
"react-intl": "^6.4.2",
"react-router-dom": "^6.11.2",
"stylis": "^4.2.0",
"typescript": "^5.0.2",
"typescript": "^5.6.3",
"typescript-eslint": "^8.11.0",
"vite": "^4.3.9"
}
}
+5
View File
@@ -0,0 +1,5 @@
export default {
importOrder: ["^[./]"],
importOrderSeparation: true,
plugins: ["@trivago/prettier-plugin-sort-imports"],
};
+2 -2
View File
@@ -1,4 +1,4 @@
import createCache from "@emotion/cache";
import createCache, { EmotionCache } from "@emotion/cache";
import { CacheProvider, Global, ThemeProvider, css } from "@emotion/react";
import styled from "@emotion/styled";
import normalizeCss from "normalize.css/normalize.css?inline";
@@ -13,7 +13,7 @@ const themeCache = createCache({
key: "cv",
});
const i = themeCache.insert;
const i: EmotionCache["insert"] = (...args) => themeCache.insert(...args);
themeCache.insert = (...args) => {
args[2].tags.forEach((t) => {
if (!t.getAttribute("media")) {
Binary file not shown.

After

Width:  |  Height:  |  Size: 280 KiB

+71 -40
View File
@@ -3,66 +3,91 @@ import { defineMessages, useIntl } from "react-intl";
import { Content } from "../common/Content";
import { Headline, SubHeadline } from "../common/Headline";
import { Spacer } from "../common/Spacer";
import PageBreakAvoid from "../common/PageBreakAvoid";
import { Paragraph } from "../common/Text";
const messages = defineMessages({
skills: {
defaultMessage: "Skills",
id: "Experience.skills",
id: "4JISx9",
},
});
const approxCurrentYears = {
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(
(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(
(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,
),
};
const yourpassSkills = [
const investbaySkills = [
"DevOps",
"Front-End Development",
"Back-end Operations",
"Software Development",
"Kubernetes",
"TypeScript",
"Go",
"Linux",
"Linux Server",
"Google Cloud Platform (GCP)",
"Amazon Web Services (AWS)",
"Gitlab",
"Terraform",
"Cloud infrastructure",
"Cloud Applications",
"Software Development Life Cycle (SDLC)",
"Linux System Administration",
"Back-End Web Development",
"Git",
"Go",
"TypeScript",
"Nix",
"GraphQL",
"gRPC",
"PostgreSQL",
"Node.js",
"React.js",
];
const yourpassSkills = [
"DevOps",
"Software as a Service (SaaS)",
"Cloud Infrastructure",
"Kubernetes",
"Back-end Operations",
"Linux System Administration",
"Amazon Web Services (AWS)",
"Amazon EKS",
"Terraform",
"Go (Programming Language)",
"gRPC",
"Front-End Development",
"React.js",
"Node.js",
"TypeScript",
"Nix",
"Software Development Life Cycle (SDLC)",
"Software Development",
"Git",
"PostgreSQL",
];
const yoursystemSkills = [
"DevOps",
"Front-End Development",
"Docker Swarm",
"Linux System Administration",
"Back-end Operations",
"Front-End Development",
"Amazon Web Services (AWS)",
"Bash",
"Linux Server",
"Terraform",
"Cloud Infrastructure",
"Cloud Applications",
"Go (Programming Language)",
"TypeScript",
"Node.js",
"Software Development Life Cycle (SDLC)",
"Software Development",
"Kubernetes",
"TypeScript",
"Linux",
"Linux Server",
"Linux System Administration",
"Back-End Web Development",
"GraphQL",
"Git",
"Node.js",
"Vue.js",
"PHP",
"Bash",
"Amazon Web Services (AWS)",
"Amazon EKS",
];
const Experience: React.FC = () => {
@@ -70,6 +95,7 @@ const Experience: React.FC = () => {
return (
<>
<PageBreakAvoid>
<Headline level={3}>INVESTBAY s.r.o.</Headline>
<SubHeadline level={4}>DevOps Architect</SubHeadline>
<Content>
@@ -77,20 +103,22 @@ const Experience: React.FC = () => {
{intl.formatMessage(
{
defaultMessage: "February 2024 - Present",
id: "Experience.investbay",
id: "w2Pn7j",
},
{
// not used atm
count: approxCurrentYears.InvestBay,
}
},
)}
</Paragraph>
<Paragraph>
<strong>{intl.formatMessage(messages.skills)}:</strong>{" "}
{yourpassSkills.join(" · ")}
{investbaySkills.join(" · ")}
</Paragraph>
</Content>
</PageBreakAvoid>
<PageBreakAvoid>
<Headline level={3}>YOUR PASS s.r.o.</Headline>
<SubHeadline level={4}>DevOps Engineer</SubHeadline>
<Content>
@@ -98,11 +126,11 @@ const Experience: React.FC = () => {
{intl.formatMessage(
{
defaultMessage: "July 2021 - Present ({count} years)",
id: "Experience.yourpass",
id: "6T3Cls",
},
{
count: approxCurrentYears.YourPass,
}
},
)}
</Paragraph>
<Paragraph>
@@ -110,9 +138,9 @@ const Experience: React.FC = () => {
{yourpassSkills.join(" · ")}
</Paragraph>
</Content>
</PageBreakAvoid>
<Spacer />
<PageBreakAvoid>
<Headline level={3}>YOUR SYSTEM s.r.o.</Headline>
<SubHeadline level={4}>SysOps</SubHeadline>
@@ -121,11 +149,11 @@ const Experience: React.FC = () => {
{intl.formatMessage(
{
defaultMessage: "January 2022 - Present ({count} years)",
id: "Experience.yoursystem",
id: "nqa9U0",
},
{
count: approxCurrentYears.YourSystemSysOps,
}
},
)}
</Paragraph>
<Paragraph>
@@ -140,7 +168,7 @@ const Experience: React.FC = () => {
<Paragraph>
{intl.formatMessage({
defaultMessage: "February 2016 - December 2021 (5 years)",
id: "Experience.yoursystem",
id: "96SwL8",
})}
</Paragraph>
<Paragraph>
@@ -148,7 +176,9 @@ const Experience: React.FC = () => {
{yoursystemSkills.join(" · ")}
</Paragraph>
</Content>
</PageBreakAvoid>
<PageBreakAvoid>
<Headline level={3}>Past experience</Headline>
<SubHeadline level={4}>Developer</SubHeadline>
@@ -156,17 +186,18 @@ const Experience: React.FC = () => {
<Paragraph>
{intl.formatMessage({
defaultMessage: "Birth - February 2016",
id: "Experience.past",
id: "KtILZ7",
})}
</Paragraph>
<Paragraph>
{intl.formatMessage({
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...",
id: "Experience.pastDescription",
id: "obpLg6",
})}
</Paragraph>
</Content>
</PageBreakAvoid>
</>
);
};
+5 -4
View File
@@ -1,5 +1,6 @@
import React from "react";
import React, { Children } from "react";
import PageBreakAvoid from "../common/PageBreakAvoid";
import { Spacer } from "../common/Spacer";
import { Paragraph } from "../common/Text";
@@ -11,13 +12,13 @@ const Skill: React.FC<React.PropsWithChildren<SkillProps>> = (props) => {
const { children, title } = props;
return (
<div>
<PageBreakAvoid>
<strong>{title}</strong>
<Spacer />
{React.Children.map(children, (c) => (
{Children.map(children, (c) => (
<Paragraph>{c}</Paragraph>
))}
</div>
</PageBreakAvoid>
);
};
+10 -7
View File
@@ -3,6 +3,7 @@ import { useIntl } from "react-intl";
import { SubHeadline } from "../common/Headline";
import { List, ListItem } from "../common/List";
import PageBreakAvoid from "../common/PageBreakAvoid";
import { Spacer } from "../common/Spacer";
import { Paragraph } from "../common/Text";
import Skill from "./Skill";
@@ -55,52 +56,54 @@ const Skills: React.FC = () => {
{intl.formatMessage({
defaultMessage:
"Several years of experience developing, maintaining and adhering to the DevOps practices to streamline organization's processes across both backend and frontend development.",
id: "Skills.devops",
id: "BOZ+do",
})}
</Skill>
<Skill title="Front-End Development">
{intl.formatMessage({
defaultMessage:
"Extensive experience in frontend development spanning back to the early 2000s.",
id: "Skills.frontendDevelopment",
id: "AjT8sf",
})}
</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.backendDevelopment",
id: "h4cHqQ",
})}
{intl.formatMessage({
defaultMessage:
"In recent years, the main focus was on Go to write tooling and backend services.",
id: "Skills.backendDevelopment",
id: "FxkFRP",
})}
</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",
id: "YBTD7C",
})}
{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",
id: "VRhCte",
})}
</Skill>
<Spacer withDivider />
<SubHeadline level={4}>
{intl.formatMessage({
defaultMessage: "Other notable skills",
id: "Skills.otherNotableSkills",
id: "8NqNwY",
})}
</SubHeadline>
<List>
{otherSkills.map((s) => (
<ListItem key={s.title}>
<PageBreakAvoid>
<strong>{s.title}</strong>
{s.description && `: ${s.description}`}
</PageBreakAvoid>
</ListItem>
))}
</List>
+2 -4
View File
@@ -1,7 +1,6 @@
import React from "react";
import { Paragraph } from "../common/Text";
import { Caption } from "../common/Text";
import { Paragraph, Caption } from "../common/Text";
const Summary: React.FC = () => {
return (
@@ -38,8 +37,7 @@ const Summary: React.FC = () => {
knowledge of KNX systems.
</Paragraph>
<Caption>
-- This summary was graciously generated by an AI and then rewritten and
adjusted by a human
-- Summary graciously generated by an AI and curated by human
</Caption>
</>
);
@@ -1,22 +1,22 @@
import React from "react";
import React, { Component } from "react";
type ErrorHandler = (error: Error, info: React.ErrorInfo) => void;
type ErrorHandlingComponent<Props> = (
props: Props,
error?: Error
error?: Error,
) => React.ReactNode;
type ErrorState = { error?: Error };
function Catch<Props extends object>(
component: ErrorHandlingComponent<Props>,
errorHandler?: ErrorHandler
errorHandler?: ErrorHandler,
): React.ComponentType<Props> {
function Inner({ error, props }: { error?: Error; props: Props }) {
return <React.Fragment>{component(props, error)}</React.Fragment>;
}
return class CatchClass extends React.Component<Props, ErrorState> {
return class CatchClass extends Component<Props, ErrorState> {
state: ErrorState = {
error: undefined,
};
@@ -46,7 +46,7 @@ const divStyles: React.CSSProperties = {
const ErrorBoundary = Catch(function (
props: React.PropsWithChildren,
error?: Error
error?: Error,
) {
if (error) {
return (
@@ -23,7 +23,7 @@ const Nav = styled("nav")({
flex: "0 0 280px",
width: 280,
minHeight: "100%",
padding: "3rem 2rem 2rem",
padding: "0 2rem 2rem",
[hideNavigationMQ]: {
display: "none",
@@ -1,27 +1,32 @@
import styled from "@emotion/styled";
import React, { useEffect, useRef } from "react";
import { useIntl } from "react-intl";
import profile from "../../assets/profile.jpg";
import { CONTACT_EMAIL, CONTACT_PHONE } from "../../config/environment";
import { Contact } from "../common/Contact";
import { List, ListItem } from "../common/List";
import { Spacer } from "../common/Spacer";
import NavigationHeadline from "./NavigationHeadline";
const getTopOffset = (input: HTMLElement) => {
let el: HTMLElement | Element | null = input;
let o = 0;
do {
if (!(el instanceof HTMLElement)) {
break;
}
const ProfileImg = styled("img")({
borderRadius: "50%",
border: "2px solid white",
display: "block",
margin: "0 auto",
maxWidth: "100%",
width: 150,
});
if (!isNaN(el.offsetTop)) {
o += el.offsetTop;
}
} while ((el = el.offsetParent));
const navBottomPadding = 50;
return o;
};
const TopSpacer = styled("div")({
height: 40,
});
const StickyWrapper = styled("div")({
position: "sticky",
});
const MainNavigation: React.FC = () => {
const intl = useIntl();
@@ -34,49 +39,30 @@ const MainNavigation: React.FC = () => {
return;
}
d.style.top = "0px";
let { height } = d.getBoundingClientRect();
const listener = () => {
const visibleArea = navBottomPadding + height;
if (window.innerHeight > visibleArea) {
d.style.top = "0px";
} else {
d.style.top = `${window.innerHeight - visibleArea}px`;
}
};
const ro = new ResizeObserver((entries) => {
if (entries[0]) {
height = entries[0].contentRect.height;
listener();
}
});
ro.observe(d);
let scrollPrev = window.scrollY;
const listener = () => {
const down = scrollPrev < window.scrollY;
scrollPrev = window.scrollY;
const top = getTopOffset(d);
if (window.innerHeight > height) {
d.style.marginTop = `${Math.max(window.scrollY, 0)}px`;
return;
}
if (down) {
const delta = top + height;
const wDelta = window.scrollY + window.innerHeight;
const diff = wDelta - delta;
if (diff > 0) {
const sizeDelta = Math.min(window.innerHeight - height, 0);
d.style.marginTop = `${Math.max(top + diff + sizeDelta, 0)}px`;
}
} else {
const delta = top;
const wDelta = window.scrollY;
const diff = wDelta - delta;
if (diff < 0) {
d.style.marginTop = `${Math.max(top + diff, 0)}px`;
}
}
};
window.addEventListener("scroll", listener);
window.addEventListener("scroll", listener, { passive: true });
window.addEventListener("resize", listener, { passive: true });
return () => {
window.removeEventListener("scroll", listener);
@@ -85,11 +71,14 @@ const MainNavigation: React.FC = () => {
}, []);
return (
<div ref={ref}>
<StickyWrapper ref={ref}>
<TopSpacer />
<ProfileImg src={profile} alt="profile picture" />
<NavigationHeadline>
{intl.formatMessage({
defaultMessage: "Contact",
id: "Navigation.contact",
id: "s3RWxF",
})}
</NavigationHeadline>
@@ -100,14 +89,14 @@ const MainNavigation: React.FC = () => {
<NavigationHeadline href="#objective">
{intl.formatMessage({
defaultMessage: "Objective",
id: "Navigation.objective",
id: "UMiSC4",
})}
</NavigationHeadline>
<NavigationHeadline href="#skills">
{intl.formatMessage({
defaultMessage: "Top Skills",
id: "Navigation.topSkills",
id: "JUWjX4",
})}
</NavigationHeadline>
@@ -130,7 +119,7 @@ const MainNavigation: React.FC = () => {
<NavigationHeadline>
{intl.formatMessage({
defaultMessage: "Certifications",
id: "Navigation.certifications",
id: "tl429z",
})}
</NavigationHeadline>
@@ -146,10 +135,10 @@ const MainNavigation: React.FC = () => {
<NavigationHeadline href="#experience">
{intl.formatMessage({
defaultMessage: "Experience",
id: "Navigation.experience",
id: "W1qv5r",
})}
</NavigationHeadline>
</div>
</StickyWrapper>
);
};
@@ -0,0 +1,7 @@
import styled from "@emotion/styled";
const PageBreakAvoid = styled("div")({
pageBreakInside: "avoid",
});
export default PageBreakAvoid;
@@ -25,18 +25,18 @@ const Space = styled("div", { shouldForwardProp })<SpaceProps>(
({ spacing, theme }) => ({
width: "100%",
height: theme.spacing(spacing === undefined ? 1 : spacing),
})
}),
);
const Spacer: React.FC<SpacerProps> = (props) => {
const { spacing, withDivider } = props;
if (!withDivider) {
const spaceSize = typeof spacing === undefined ? 2 : spacing;
const spaceSize = spacing === undefined ? 2 : spacing;
return <Space spacing={spaceSize} />;
}
const spaceSize = typeof spacing === undefined ? 1 : spacing;
const spaceSize = spacing === undefined ? 1 : spacing;
return (
<Root>
+9 -3
View File
@@ -28,15 +28,21 @@ export const BUILD_TIMESTAMP: Date = window.APP_CONFIG?.commitTime
export const CONTACT_EMAIL = confString(
window.APP_CONFIG?.contactEmail,
import.meta.env.VITE_CONTACT_EMAIL || ""
typeof import.meta.env.VITE_CONTACT_EMAIL === "string"
? import.meta.env.VITE_CONTACT_EMAIL
: "",
);
export const CONTACT_PHONE = confString(
window.APP_CONFIG?.contactPhone,
import.meta.env.VITE_CONTACT_PHONE || ""
typeof import.meta.env.VITE_CONTACT_PHONE === "string"
? import.meta.env.VITE_CONTACT_PHONE
: "",
);
export const POSITION = confString(
window.APP_CONFIG?.position,
import.meta.env.VITE_POSITION || ""
typeof import.meta.env.VITE_POSITION === "string"
? import.meta.env.VITE_POSITION
: "",
);
+3 -3
View File
@@ -1,10 +1,10 @@
import React from "react";
import ReactDOM from "react-dom/client";
import { createRoot } from "react-dom/client";
import App from "./App";
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
createRoot(document.getElementById("root") as HTMLElement).render(
<React.StrictMode>
<App />
</React.StrictMode>
</React.StrictMode>,
);
+3 -3
View File
@@ -28,7 +28,7 @@ const Dashboard: React.FC = () => {
<SubHeadline level={4}>
{intl.formatMessage({
defaultMessage: "Central Bohemia, Czechia",
id: "Dashboard.location",
id: "Lkk994",
})}
</SubHeadline>
@@ -49,7 +49,7 @@ const Dashboard: React.FC = () => {
<Headline level={2}>
{intl.formatMessage({
defaultMessage: "Skills",
id: "Dashboard.skillsTitle",
id: "4JISx9",
})}
</Headline>
<Spacer />
@@ -63,7 +63,7 @@ const Dashboard: React.FC = () => {
<Headline level={2}>
{intl.formatMessage({
defaultMessage: "Experience",
id: "Dashboard.experienceTitle",
id: "W1qv5r",
})}
</Headline>
<Spacer />
+1 -1
View File
@@ -21,7 +21,7 @@ const NotFound = () => {
<p>
{intl.formatMessage({
defaultMessage: "Nothing to see here",
id: "Router.NotFound",
id: "ywIjM0",
})}
</p>
<Link to="/">Go home</Link>
+3 -4
View File
@@ -1,6 +1,5 @@
import React from "react";
import { Outlet, RouterProvider } from "react-router-dom";
import { createBrowserRouter } from "react-router-dom";
import React, { lazy } from "react";
import { Outlet, RouterProvider, createBrowserRouter } from "react-router-dom";
import { ErrorBoundary } from "../components/ErrorBoundary";
import Dashboard from "./Dashboard";
@@ -13,7 +12,7 @@ const Layout: React.FC = () => {
);
};
const NotFound = React.lazy(() => import("./NotFound"));
const NotFound = lazy(() => import("./NotFound"));
const router = createBrowserRouter([
{
+28
View File
@@ -0,0 +1,28 @@
{
"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"]
}
+5 -21
View File
@@ -1,23 +1,7 @@
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"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"]
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
]
}
+25
View File
@@ -0,0 +1,25 @@
{
"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"]
}
@@ -67,7 +67,6 @@ func (h *handler) serveFile(w http.ResponseWriter, r *http.Request, modtime time
gw.Reset(io.Discard)
}
err = gw.Close()
if err != nil {
h.logger.Warn("Could not close gzip writer", zap.Error(err))
return
-1
View File
@@ -33,7 +33,6 @@ func main() {
var err error
logger, err = config.LoggerConfig.Build()
if err != nil {
fmt.Println(notice)
fmt.Println(version.CommitTime.Format("Committed at 2006/01/02 15:04:05 MST"))
Generated
+631 -12
View File
@@ -1,37 +1,314 @@
{
"nodes": {
"devshell": {
"cachix": {
"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": [
"nix",
"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": {
"lastModified": 1723156315,
"narHash": "sha256-0JrfahRMJ37Rf1i0iOOn+8Z4CLvbcGNwa2ChOAVrp/8=",
"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": 1728330715,
"narHash": "sha256-xRJ2nPOXb//u1jaBnDP56M7v5ldavjbtR6lfGqSvcKg=",
"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",
"repo": "devshell",
"rev": "dd6b80932022cea34a019e2bb32f6fa9e494dfef",
"repo": "flake-utils",
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "devshell",
"repo": "flake-utils",
"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"
}
},
"nix": {
"inputs": {
"devshell": "devshell",
"nixpkgs": "nixpkgs"
"devenv": "devenv",
"nixpkgs": "nixpkgs_3"
},
"locked": {
"lastModified": 1729027123,
"narHash": "sha256-LjD40ya8efdhxQ26Zy/LkLDOriZIHJZqutAorvPIka8=",
"lastModified": 1729891574,
"narHash": "sha256-OOAwctBTUwKc9yTvvK1+sbcGcYqHSYvI060DlczMUbI=",
"ref": "refs/heads/main",
"rev": "d3596fc7e933c171a284771f7f72342d33ad6508",
"revCount": 5,
"rev": "986890b04467a51533b03a5d5c4cf4ea5ebc4cbb",
"revCount": 7,
"type": "git",
"url": "ssh://git@git.c3c.cz/C3C/nix"
},
@@ -40,7 +317,237 @@
"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": {
"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": {
"lastModified": 1728538411,
"narHash": "sha256-f0SBJz1eZ2yOuKUr5CA9BHULGXVSn6miBuUWdTyhUhU=",
@@ -56,10 +563,122 @@
"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": {
"inputs": {
"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",
+61 -28
View File
@@ -8,18 +8,27 @@
{
formatter = nix.formatter;
packages = nix.lib.forAllSystems (pkgs:
packages = nix.lib.forAllSystems (
pkgs:
let
version = "rev-${self.shortRev or self.dirtyShortRev}";
package = builtins.fromJSON (builtins.readFile ./app/frontend/package.json);
in
rec {
devenv-up = self.devShells.${pkgs.system}.default.config.procfileScript;
devenv-test = self.devShells.${pkgs.system}.default.config.test;
ui = pkgs.buildNpmPackage {
inherit version;
pname = "cv";
src = ./app/frontend;
preBuild = ''
cp ${nix.lib.eslint-config-file} ./eslint.shared.mjs
npm run check
'';
npmInstallFlags = "--no-audit --no-progress --no-fund";
npmDepsHash = "sha256-p4rTpy0t8aajbubvtF1TA83/FFqvfKEOPBb5T0ZRfQY=";
npmDepsHash = "sha256-yINvhHFYT00khqo9D3rIDNSvJMdhQ1M5xa9SJEDZito=";
npmPackFlags = [ "--ignore-scripts" ];
};
@@ -42,7 +51,9 @@
"-w"
"-X gopkg.c3c.cz/cv/app/server/internal/version.Tag=${version}"
"-X gopkg.c3c.cz/cv/app/server/internal/version.Commit=${self.rev or self.dirtyRev}"
"-X gopkg.c3c.cz/cv/app/server/internal/version.commitTime=${builtins.toString (self.lastModified or 0)}"
"-X gopkg.c3c.cz/cv/app/server/internal/version.commitTime=${
builtins.toString (self.lastModified or 0)
}"
];
vendorHash = "sha256-44xcyVk5KcurQLkVJv1MeAj+Pfcu53664pvVgHdyv3E=";
};
@@ -61,55 +72,77 @@
);
devShells = nix.lib.forAllSystems (pkgs: {
default = pkgs.devshell.mkShell {
name = "c3c-cv";
default = nix.lib.mkDevenvShell {
inputs = {
self = self;
nixpkgs = pkgs;
};
pkgs = pkgs;
modules = [
{
packages = [
pkgs.go
pkgs.nodejs_22
];
commands = [
{
name = "lint";
help = "run linters";
command = ''
enterShell = ''
cp ${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
golangci-lint = {
exec = ''
CMD=''${1:-}
if [[ "$CMD" == "run" ]]; then
shift
${pkgs.golangci-lint}/bin/golangci-lint run --config ${nix.lib.golangci-config-file} $@
else
${pkgs.golangci-lint}/bin/golangci-lint $@
fi
'';
};
lint = {
exec = ''
${nix.lib.cd_root}
${pkgs.golangci-lint}/bin/golangci-lint run --sort-results --out-format tab --config ${nix.lib.golangci-config-file} ./...
npm --prefix app/frontend run check
'';
}
{
name = "fix";
help = "format & fix found issues";
command = ''
};
fix = {
exec = ''
${nix.lib.cd_root}
nix fmt .
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 ./...
npm --prefix app/frontend run fix
'';
}
{
name = "update-npm-deps-hash";
help = "Calculates and updates the npmDepsHash in default.nix";
command = ''
};
update-npm-deps-hash = {
exec = ''
${nix.lib.cd_root}
echo "Calculating npm deps"
# STDERR is poluted by the installed nodules, silencing
HASH=''$(${pkgs.prefetch-npm-deps}/bin/prefetch-npm-deps ''$PRJ_ROOT/app/frontend/package-lock.json 2> /dev/null)
HASH=''$(${pkgs.prefetch-npm-deps}/bin/prefetch-npm-deps ./app/frontend/package-lock.json 2> /dev/null)
[[ ''$HASH = sha256* ]] && echo "Hash is ''$HASH"
[[ ''$HASH != sha256* ]] && echo "Failed" && exit 137
# Replace the first occurence of npmDepsHash with the new calculated hash in this file
sed -i "0,/npmDepsHash =/{s@npmDepsHash = .*@npmDepsHash = \"''$HASH\";@}" ./flake.nix
'';
}
{
name = "dev";
help = "Starts the javascript project in dev";
command = ''
npm --prefix ''$PRJ_ROOT/app/frontend run dev
};
dev = {
exec = ''
${nix.lib.cd_root}
npm --prefix ./app/frontend run dev
'';
};
};
}
];
};