diff --git a/.gitignore b/.gitignore index 798fe10..fb85303 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ .env /docker-compose.* +/build/ + +# Nix /result* -/.direnv/ -/build/ \ No newline at end of file +/.direnv/ \ No newline at end of file diff --git a/.treli.yaml b/.treli.yaml index 2dcd377..9adb6dd 100644 --- a/.treli.yaml +++ b/.treli.yaml @@ -39,7 +39,7 @@ apps: - ts - svelte onstart: npx prettier --check . - onchange: npx prettier --check . || npx prettier --write . + onchange: npx prettier --check . revive: color: "#89dceb" diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..224d6a4 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,9 @@ +{ + "recommendations": [ + "golang.go", + "dorzey.vscode-sqlfluff", + "dbaeumer.vscode-eslint", + "svelte.svelte-vscode", + "esbenp.prettier-vscode" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json index ed364c9..be6a823 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,37 @@ { - "go.lintTool": "revive", - "go.lintFlags": [ - "--config=server/revive.toml" - ], - "sqlfluff.config": "server/db/.sqlfluff", -} \ No newline at end of file + "editor.formatOnSave": true, + + // Go + "go.lintTool": "revive", + "go.formatTool": "goimports", + "go.lintFlags": ["--config=server/revive.toml"], + "gopls": { "ui.semanticTokens": true }, + "[go]": { + "editor.defaultFormatter": "golang.go" + }, + + // SQLFluff + "sqlfluff.config": "server/db/.sqlfluff", + + // ESLint + "eslint.workingDirectories": ["./client"], + "eslint.validate": ["svelte", "javascript", "typescript"], + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit" + }, + + // Svelte + "svelte.enable-ts-plugin": true, + "[svelte]": { + "editor.defaultFormatter": "svelte.svelte-vscode" + }, + + // Prettier + "editor.defaultFormatter": "esbenp.prettier-vscode", + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + } +} diff --git a/client/.prettierrc b/client/.prettierrc index c67aa0a..7198641 100644 --- a/client/.prettierrc +++ b/client/.prettierrc @@ -3,8 +3,21 @@ "singleQuote": true, "trailingComma": "none", "printWidth": 100, - "plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"], + "plugins": [ + "prettier-plugin-svelte", + "prettier-plugin-tailwindcss", + "@ianvs/prettier-plugin-sort-imports" + ], "tailwindFunctions": ["tv", "cn", "clsx"], + "importOrder": [ + "^(node:)", + "", + "^[.]", + "", + "^(\\$lib/ui)(/.*)$", + "", + "^[.]" + ], "overrides": [ { "files": "*.svelte", diff --git a/client/eslint.config.js b/client/eslint.config.js index 6bf665f..4060a96 100644 --- a/client/eslint.config.js +++ b/client/eslint.config.js @@ -1,11 +1,12 @@ -import prettier from 'eslint-config-prettier'; -import js from '@eslint/js'; +import { fileURLToPath } from 'node:url'; import { includeIgnoreFile } from '@eslint/compat'; +import js from '@eslint/js'; +import prettier from 'eslint-config-prettier'; import svelte from 'eslint-plugin-svelte'; import globals from 'globals'; -import { fileURLToPath } from 'node:url'; import ts from 'typescript-eslint'; import svelteConfig from './svelte.config.js'; + const gitignorePath = fileURLToPath(new URL('./.prettierignore', import.meta.url)); export default ts.config( diff --git a/client/package-lock.json b/client/package-lock.json index e187daa..64e1e0d 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -13,6 +13,7 @@ "@connectrpc/connect-web": "^2.0.2", "@eslint/compat": "^1.2.9", "@eslint/js": "^9.18.0", + "@ianvs/prettier-plugin-sort-imports": "^4.4.1", "@lucide/svelte": "^0.479.0", "@scalar/api-reference": "^1.28.32", "@simplewebauthn/browser": "^13.1.0", @@ -57,6 +58,38 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.1.tgz", + "integrity": "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.27.1", + "@babel/types": "^7.27.1", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-string-parser": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", @@ -93,6 +126,50 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.1.tgz", + "integrity": "sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.1", + "@babel/parser": "^7.27.1", + "@babel/template": "^7.27.1", + "@babel/types": "^7.27.1", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/types": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz", @@ -1205,6 +1282,29 @@ "url": "https://github.com/sponsors/jdesrosiers" } }, + "node_modules/@ianvs/prettier-plugin-sort-imports": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@ianvs/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.4.1.tgz", + "integrity": "sha512-F0/Hrcfpy8WuxlQyAWJTEren/uxKhYonOGY4OyWmwRdeTvkh9mMSCxowZLjNkhwi/2ipqCgtXwwOk7tW0mWXkA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@babel/generator": "^7.26.2", + "@babel/parser": "^7.26.2", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.26.0", + "semver": "^7.5.2" + }, + "peerDependencies": { + "@vue/compiler-sfc": "2.7.x || 3.x", + "prettier": "2 || 3" + }, + "peerDependenciesMeta": { + "@vue/compiler-sfc": { + "optional": true + } + } + }, "node_modules/@internationalized/date": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.8.0.tgz", @@ -5480,6 +5580,13 @@ "jiti": "lib/jiti-cli.mjs" } }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -5493,6 +5600,19 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", diff --git a/client/package.json b/client/package.json index aa5e7e7..5d3493c 100644 --- a/client/package.json +++ b/client/package.json @@ -19,6 +19,7 @@ "@connectrpc/connect-web": "^2.0.2", "@eslint/compat": "^1.2.9", "@eslint/js": "^9.18.0", + "@ianvs/prettier-plugin-sort-imports": "^4.4.1", "@lucide/svelte": "^0.479.0", "@scalar/api-reference": "^1.28.32", "@simplewebauthn/browser": "^13.1.0", diff --git a/client/src/lib/coolforms/coolforms.svelte.ts b/client/src/lib/coolforms/coolforms.svelte.ts index a652bf3..0bdd530 100644 --- a/client/src/lib/coolforms/coolforms.svelte.ts +++ b/client/src/lib/coolforms/coolforms.svelte.ts @@ -1,14 +1,11 @@ -import { - create, - type DescMessage, - type DescService, - type MessageShape, - type MessageInitShape -} from '@bufbuild/protobuf'; -import { ValidationError, type Violation } from '@bufbuild/protovalidate'; -import { Validator } from '../transport'; -import { ConnectError, type Client } from '@connectrpc/connect'; +import type { DescMessage, DescService, MessageInitShape, MessageShape } from '@bufbuild/protobuf'; +import type { Violation } from '@bufbuild/protovalidate'; +import type { Client } from '@connectrpc/connect'; import type { Action } from 'svelte/action'; +import { create } from '@bufbuild/protobuf'; +import { ValidationError } from '@bufbuild/protovalidate'; +import { ConnectError } from '@connectrpc/connect'; +import { Validator } from '../transport'; type Options = { init?: MessageInitShape; @@ -30,9 +27,7 @@ export function coolForm & { - form?: ConnectError; - } = $state({}); + const errors: Violations & { form?: ConnectError } = $state({}); let loading = $state(false); const validate = () => { diff --git a/client/src/lib/coolforms/index.ts b/client/src/lib/coolforms/index.ts index 5179a09..6467ec0 100644 --- a/client/src/lib/coolforms/index.ts +++ b/client/src/lib/coolforms/index.ts @@ -1,4 +1,4 @@ -import { coolForm } from './coolforms.svelte'; import { newState } from './conststate.svelte'; +import { coolForm } from './coolforms.svelte'; export { coolForm, newState }; diff --git a/client/src/lib/transport.ts b/client/src/lib/transport.ts index 1ae2cf5..4108b6b 100644 --- a/client/src/lib/transport.ts +++ b/client/src/lib/transport.ts @@ -1,11 +1,12 @@ -import { createConnectTransport } from '@connectrpc/connect-web'; +import type { Interceptor } from '@connectrpc/connect'; import { createValidator } from '@bufbuild/protovalidate'; -import { Code, ConnectError, createClient, type Interceptor } from '@connectrpc/connect'; -import { AuthService } from '$lib/connect/user/v1/auth_pb'; -import { UserService } from '$lib/connect/user/v1/user_pb'; -import { ItemService } from '$lib/connect/item/v1/item_pb'; +import { Code, ConnectError, createClient } from '@connectrpc/connect'; +import { createConnectTransport } from '@connectrpc/connect-web'; import { goto } from '$app/navigation'; import { page } from '$app/state'; +import { ItemService } from '$lib/connect/item/v1/item_pb'; +import { AuthService } from '$lib/connect/user/v1/auth_pb'; +import { UserService } from '$lib/connect/user/v1/user_pb'; const redirector: Interceptor = (next) => async (req) => { try { diff --git a/client/src/lib/ui/avatar/avatar-fallback.svelte b/client/src/lib/ui/avatar/avatar-fallback.svelte index ffa30d1..bf3eda7 100644 --- a/client/src/lib/ui/avatar/avatar-fallback.svelte +++ b/client/src/lib/ui/avatar/avatar-fallback.svelte @@ -1,6 +1,6 @@ diff --git a/client/src/lib/ui/table/index.ts b/client/src/lib/ui/table/index.ts index 99239ae..553b6b4 100644 --- a/client/src/lib/ui/table/index.ts +++ b/client/src/lib/ui/table/index.ts @@ -1,4 +1,3 @@ -import Root from './table.svelte'; import Body from './table-body.svelte'; import Caption from './table-caption.svelte'; import Cell from './table-cell.svelte'; @@ -6,6 +5,7 @@ import Footer from './table-footer.svelte'; import Head from './table-head.svelte'; import Header from './table-header.svelte'; import Row from './table-row.svelte'; +import Root from './table.svelte'; export { Root, diff --git a/client/src/lib/ui/table/table-body.svelte b/client/src/lib/ui/table/table-body.svelte index b5fa553..f039cbb 100644 --- a/client/src/lib/ui/table/table-body.svelte +++ b/client/src/lib/ui/table/table-body.svelte @@ -1,6 +1,6 @@ diff --git a/client/src/lib/ui/tabs/tabs-trigger.svelte b/client/src/lib/ui/tabs/tabs-trigger.svelte index ad316e6..97f213c 100644 --- a/client/src/lib/ui/tabs/tabs-trigger.svelte +++ b/client/src/lib/ui/tabs/tabs-trigger.svelte @@ -1,6 +1,6 @@