Chore: Updated .vscode/* files and other boilerplate stuff
This commit is contained in:
13
.vscode/extensions.json
vendored
13
.vscode/extensions.json
vendored
@ -1,5 +1,14 @@
|
|||||||
{
|
{
|
||||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
|
||||||
"recommendations": ["angular.ng-template"]
|
"recommendations": [
|
||||||
|
"ms-vscode-remote.remote-wsl",
|
||||||
|
"ms-python.python",
|
||||||
|
"ms-python.vscode-pylance",
|
||||||
|
"ms-python.debugpy",
|
||||||
|
"charliermarsh.ruff",
|
||||||
|
"docker.docker",
|
||||||
|
"angular.ng-template",
|
||||||
|
"dbaeumer.vscode-eslint",
|
||||||
|
"tombi-toml.tombi"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
48
.vscode/launch.json
vendored
48
.vscode/launch.json
vendored
@ -5,27 +5,39 @@
|
|||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "ng serve",
|
"name": "Python: FastAPI (debug, no reload)",
|
||||||
"type": "chrome",
|
|
||||||
"request": "launch",
|
|
||||||
"preLaunchTask": "npm: start",
|
|
||||||
"url": "http://localhost:4200/"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ng test",
|
|
||||||
"type": "chrome",
|
|
||||||
"request": "launch",
|
|
||||||
"preLaunchTask": "npm: test",
|
|
||||||
"url": "http://localhost:9876/debug.html"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Python: FastAPI",
|
|
||||||
"type": "debugpy",
|
"type": "debugpy",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"module": "brewman",
|
"module": "uvicorn",
|
||||||
"args": [],
|
"args": [
|
||||||
|
"brewman.main:app",
|
||||||
|
"--port",
|
||||||
|
"9998"
|
||||||
|
],
|
||||||
"cwd": "${workspaceFolder}/brewman",
|
"cwd": "${workspaceFolder}/brewman",
|
||||||
"justMyCode": true
|
"justMyCode": true,
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
// "envFile": "${workspaceFolder}/.env",
|
||||||
|
"env": {
|
||||||
|
"PYTHONUNBUFFERED": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Angular: Chrome",
|
||||||
|
"type": "chrome",
|
||||||
|
"request": "launch",
|
||||||
|
"preLaunchTask": "frontend: dev (npm start)",
|
||||||
|
"url": "http://localhost:4200",
|
||||||
|
"webRoot": "${workspaceFolder}/overlord"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"compounds": [
|
||||||
|
{
|
||||||
|
"name": "Dev: Backend + Frontend",
|
||||||
|
"configurations": [
|
||||||
|
"Python: FastAPI (debug, no reload)",
|
||||||
|
"Angular: Chrome"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
13
.vscode/mcp.json
vendored
Normal file
13
.vscode/mcp.json
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
// For more information, visit: https://angular.dev/ai/mcp
|
||||||
|
"servers": {
|
||||||
|
"angular-cli": {
|
||||||
|
"command": "npx",
|
||||||
|
"args": [
|
||||||
|
"-y",
|
||||||
|
"@angular/cli",
|
||||||
|
"mcp"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
34
.vscode/settings.json
vendored
34
.vscode/settings.json
vendored
@ -1,5 +1,29 @@
|
|||||||
{
|
{
|
||||||
"python.defaultInterpreterPath": "/home/tanshu/.cache/pypoetry/virtualenvs/brewman-C3_Ccu4O-py3.13/bin/python",
|
// Use WSL paths + Poetry venv interpreter
|
||||||
|
"python.defaultInterpreterPath": "/home/tanshu/.cache/pypoetry/virtualenvs/brewman-C3_Ccu4O-py3.14/bin/python",
|
||||||
|
"python.terminal.activateEnvironment": true,
|
||||||
|
// Quality-of-life
|
||||||
|
/* --- Pylance: keep IntelliSense, disable type checking --- */
|
||||||
|
// "python.analysis.typeCheckingMode": "off",
|
||||||
|
// "python.analysis.diagnosticMode": "openFilesOnly",
|
||||||
|
"python.analysis.typeCheckingMode": "basic",
|
||||||
|
"python.analysis.extraPaths": [
|
||||||
|
"./brewman"
|
||||||
|
],
|
||||||
|
// Ruff (you have ruff installed via poetry)
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"[python]": {
|
||||||
|
"editor.defaultFormatter": "charliermarsh.ruff"
|
||||||
|
},
|
||||||
|
"ruff.enable": true,
|
||||||
|
"files.eol": "\n",
|
||||||
|
"eslint.workingDirectories": [
|
||||||
|
{
|
||||||
|
"directory": "overlord",
|
||||||
|
"changeProcessCWD": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"makefile.configureOnOpen": false,
|
||||||
"files.exclude": {
|
"files.exclude": {
|
||||||
"**/__pycache__": true,
|
"**/__pycache__": true,
|
||||||
"**/.mypy_cache": true,
|
"**/.mypy_cache": true,
|
||||||
@ -12,12 +36,16 @@
|
|||||||
"**/.mypy_cache": true,
|
"**/.mypy_cache": true,
|
||||||
".idea": true,
|
".idea": true,
|
||||||
"**/node_modules": true,
|
"**/node_modules": true,
|
||||||
|
"**/poetry.lock": true,
|
||||||
"**/package-lock.json": true,
|
"**/package-lock.json": true,
|
||||||
"/overlord/.angular/**": true,
|
"/overlord/.angular/**": true,
|
||||||
"typings": true,
|
"typings": true,
|
||||||
},
|
},
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
"source.fixAll.eslint": "explicit"
|
"source.fixAll.ruff": "always",
|
||||||
|
"source.fixAll.eslint": "always",
|
||||||
},
|
},
|
||||||
"makefile.configureOnOpen": false
|
"python-envs.defaultEnvManager": "ms-python.python:poetry",
|
||||||
|
"python-envs.defaultPackageManager": "ms-python.python:poetry",
|
||||||
|
"python-envs.pythonProjects": []
|
||||||
}
|
}
|
||||||
81
.vscode/tasks.json
vendored
81
.vscode/tasks.json
vendored
@ -1,8 +1,60 @@
|
|||||||
{
|
{
|
||||||
// For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558
|
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"tasks": [
|
"tasks": [
|
||||||
{
|
{
|
||||||
|
"label": "backend: dev (uvicorn reload)",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "poetry run uvicorn brewman.main:app --reload",
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}/brewman"
|
||||||
|
},
|
||||||
|
"problemMatcher": {
|
||||||
|
"owner": "python",
|
||||||
|
"pattern": [
|
||||||
|
{
|
||||||
|
"regexp": "^(.*):(\\d+):(\\d+):\\s+(error|warning):\\s+(.*)$",
|
||||||
|
"file": 1,
|
||||||
|
"line": 2,
|
||||||
|
"column": 3,
|
||||||
|
"severity": 4,
|
||||||
|
"message": 5
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"background": {
|
||||||
|
"activeOnStart": true,
|
||||||
|
"beginsPattern": ".*Uvicorn running on.*",
|
||||||
|
"endsPattern": ".*Application startup complete.*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "backend: debug (no reload)",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "poetry run uvicorn brewman.main:app",
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}/brewman"
|
||||||
|
},
|
||||||
|
"problemMatcher": {
|
||||||
|
"owner": "python",
|
||||||
|
"pattern": [
|
||||||
|
{
|
||||||
|
"regexp": "^(.*):(\\d+):(\\d+):\\s+(error|warning):\\s+(.*)$",
|
||||||
|
"file": 1,
|
||||||
|
"line": 2,
|
||||||
|
"column": 3,
|
||||||
|
"severity": 4,
|
||||||
|
"message": 5
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"background": {
|
||||||
|
"activeOnStart": true,
|
||||||
|
"beginsPattern": ".*Uvicorn running on.*",
|
||||||
|
"endsPattern": ".*Application startup complete.*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "frontend: dev (npm start)",
|
||||||
"type": "npm",
|
"type": "npm",
|
||||||
"script": "start",
|
"script": "start",
|
||||||
"isBackground": true,
|
"isBackground": true,
|
||||||
@ -15,32 +67,21 @@
|
|||||||
"background": {
|
"background": {
|
||||||
"activeOnStart": true,
|
"activeOnStart": true,
|
||||||
"beginsPattern": {
|
"beginsPattern": {
|
||||||
"regexp": "(.*?)"
|
"regexp": "Changes detected"
|
||||||
},
|
},
|
||||||
"endsPattern": {
|
"endsPattern": {
|
||||||
"regexp": "bundle generation complete"
|
"regexp": "bundle generation (complete|failed)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "npm",
|
"label": "dev: run both",
|
||||||
"script": "test",
|
"dependsOn": [
|
||||||
"isBackground": true,
|
"backend: dev (uvicorn reload)",
|
||||||
"problemMatcher": {
|
"frontend: dev (npm start)"
|
||||||
"owner": "typescript",
|
],
|
||||||
"pattern": "$tsc",
|
"dependsOrder": "parallel"
|
||||||
"background": {
|
|
||||||
"activeOnStart": true,
|
|
||||||
"beginsPattern": {
|
|
||||||
"regexp": "(.*?)"
|
|
||||||
},
|
|
||||||
"endsPattern": {
|
|
||||||
"regexp": "bundle generation complete"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
56
AGENTS.md
Normal file
56
AGENTS.md
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
|
||||||
|
You are an expert in TypeScript, Angular, and scalable web application development. You write functional, maintainable, performant, and accessible code following Angular and TypeScript best practices.
|
||||||
|
|
||||||
|
## TypeScript Best Practices
|
||||||
|
|
||||||
|
- Use strict type checking
|
||||||
|
- Prefer type inference when the type is obvious
|
||||||
|
- Avoid the `any` type; use `unknown` when type is uncertain
|
||||||
|
|
||||||
|
## Angular Best Practices
|
||||||
|
|
||||||
|
- Always use standalone components over NgModules
|
||||||
|
- Must NOT set `standalone: true` inside Angular decorators. It's the default in Angular v20+.
|
||||||
|
- Use signals for state management
|
||||||
|
- Implement lazy loading for feature routes
|
||||||
|
- Do NOT use the `@HostBinding` and `@HostListener` decorators. Put host bindings inside the `host` object of the `@Component` or `@Directive` decorator instead
|
||||||
|
- Use `NgOptimizedImage` for all static images.
|
||||||
|
- `NgOptimizedImage` does not work for inline base64 images.
|
||||||
|
|
||||||
|
## Accessibility Requirements
|
||||||
|
|
||||||
|
- It MUST pass all AXE checks.
|
||||||
|
- It MUST follow all WCAG AA minimums, including focus management, color contrast, and ARIA attributes.
|
||||||
|
|
||||||
|
### Components
|
||||||
|
|
||||||
|
- Keep components small and focused on a single responsibility
|
||||||
|
- Use `input()` and `output()` functions instead of decorators
|
||||||
|
- Use `computed()` for derived state
|
||||||
|
- Set `changeDetection: ChangeDetectionStrategy.OnPush` in `@Component` decorator
|
||||||
|
- Prefer inline templates for small components
|
||||||
|
- Prefer Reactive forms instead of Template-driven ones
|
||||||
|
- Do NOT use `ngClass`, use `class` bindings instead
|
||||||
|
- Do NOT use `ngStyle`, use `style` bindings instead
|
||||||
|
- When using external templates/styles, use paths relative to the component TS file.
|
||||||
|
|
||||||
|
## State Management
|
||||||
|
|
||||||
|
- Use signals for local component state
|
||||||
|
- Use `computed()` for derived state
|
||||||
|
- Keep state transformations pure and predictable
|
||||||
|
- Do NOT use `mutate` on signals, use `update` or `set` instead
|
||||||
|
|
||||||
|
## Templates
|
||||||
|
|
||||||
|
- Keep templates simple and avoid complex logic
|
||||||
|
- Use native control flow (`@if`, `@for`, `@switch`) instead of `*ngIf`, `*ngFor`, `*ngSwitch`
|
||||||
|
- Use the async pipe to handle observables
|
||||||
|
- Do not assume globals like (`new Date()`) are available.
|
||||||
|
- Do not write arrow functions in templates (they are not supported).
|
||||||
|
|
||||||
|
## Services
|
||||||
|
|
||||||
|
- Design services around a single responsibility
|
||||||
|
- Use the `providedIn: 'root'` option for singleton services
|
||||||
|
- Use the `inject()` function instead of constructor injection
|
||||||
1
brewman/.gitignore
vendored
1
brewman/.gitignore
vendored
@ -2,4 +2,3 @@
|
|||||||
*/__pycache__/
|
*/__pycache__/
|
||||||
*.egg-info/
|
*.egg-info/
|
||||||
dist/
|
dist/
|
||||||
poetry.lock
|
|
||||||
@ -1 +1 @@
|
|||||||
3.13
|
3.14
|
||||||
|
|||||||
3227
brewman/poetry.lock
generated
Normal file
3227
brewman/poetry.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -5,30 +5,30 @@ description = "Accounting plus inventory management for a restaurant."
|
|||||||
authors = ["tanshu <git@tanshu.com>"]
|
authors = ["tanshu <git@tanshu.com>"]
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.13"
|
python = "^3.14"
|
||||||
uvicorn = {extras = ["standard"], version = "^0.34.3"}
|
uvicorn = {extras = ["standard"], version = "^0.41.0"}
|
||||||
fastapi = {extras = ["all"], version = "^0.115.12"}
|
fastapi = {extras = ["all"], version = "^0.129.0"}
|
||||||
passlib = {extras = ["bcrypt"], version = "^1.7.4"}
|
passlib = {extras = ["bcrypt"], version = "^1.7.4"}
|
||||||
psycopg = {extras = ["binary", "pool"], version = "^3.2.9"}
|
psycopg = {extras = ["binary", "pool"], version = "^3.3.2"}
|
||||||
SQLAlchemy = "^2.0.41"
|
SQLAlchemy = "^2.0.46"
|
||||||
python-multipart = "^0.0.20"
|
python-multipart = "^0.0.22"
|
||||||
PyJWT = "^2.10.1"
|
PyJWT = "^2.11.0"
|
||||||
alembic = "^1.16.1"
|
alembic = "^1.18.4"
|
||||||
itsdangerous = "^2.2.0"
|
itsdangerous = "^2.2.0"
|
||||||
python-dotenv = "^1.1.0"
|
python-dotenv = "^1.2.1"
|
||||||
pydantic = {extras = ["dotenv"], version = "^2.11.5"}
|
pydantic = {extras = ["dotenv"], version = "^2.12.5"}
|
||||||
pandas = "^2.3.0"
|
pandas = "^3.0.1"
|
||||||
arq = "^0.26.3"
|
arq = "^0.27.0"
|
||||||
openpyxl = "^3.1.5"
|
openpyxl = "^3.1.5"
|
||||||
cryptography = "^45.0.3"
|
cryptography = "^46.0.5"
|
||||||
gunicorn = "^23.0.0"
|
gunicorn = "^25.1.0"
|
||||||
|
|
||||||
[tool.poetry.group.dev.dependencies]
|
[tool.poetry.group.dev.dependencies]
|
||||||
pre-commit = "^4.2.0"
|
pre-commit = "^4.5.1"
|
||||||
mypy = "^1.16.0"
|
mypy = "^1.19.1"
|
||||||
ruff = "^0.11.13"
|
ruff = "^0.15.1"
|
||||||
bandit = "^1.8.3"
|
bandit = "^1.9.3"
|
||||||
# safety = "^3.5.2"
|
# safety = "^3.7.0"
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry-core>=1.0.0"]
|
requires = ["poetry-core>=1.0.0"]
|
||||||
@ -36,8 +36,8 @@ build-backend = "poetry.core.masonry.api"
|
|||||||
|
|
||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
line-length = 120
|
line-length = 120
|
||||||
# Assume Python 3.13.
|
# Assume Python 3.14.
|
||||||
target-version = "py313"
|
target-version = "py314"
|
||||||
exclude = [
|
exclude = [
|
||||||
".eggs",
|
".eggs",
|
||||||
".git",
|
".git",
|
||||||
@ -98,18 +98,36 @@ line-ending = "auto"
|
|||||||
|
|
||||||
[tool.mypy]
|
[tool.mypy]
|
||||||
# --strict
|
# --strict
|
||||||
disallow_any_generics = true
|
|
||||||
disallow_subclassing_any = true
|
# Good safety defaults
|
||||||
disallow_untyped_calls = true
|
|
||||||
disallow_untyped_defs = true
|
|
||||||
disallow_incomplete_defs = true
|
|
||||||
check_untyped_defs = true
|
|
||||||
disallow_untyped_decorators = true
|
|
||||||
no_implicit_optional = true
|
|
||||||
warn_redundant_casts = true
|
|
||||||
warn_unused_ignores = true
|
|
||||||
warn_return_any = true
|
warn_return_any = true
|
||||||
warn_unused_configs = true
|
warn_unused_configs = true
|
||||||
|
warn_redundant_casts = true
|
||||||
|
warn_unused_ignores = true
|
||||||
|
no_implicit_optional = true
|
||||||
strict_equality = true
|
strict_equality = true
|
||||||
plugins = ["sqlalchemy.ext.mypy.plugin"]
|
|
||||||
|
# Practical ergonomics
|
||||||
|
pretty = true
|
||||||
|
show_error_codes = true
|
||||||
|
show_column_numbers = true
|
||||||
|
error_summary = true
|
||||||
|
|
||||||
|
# These keep signal high in real-world FastAPI projects
|
||||||
|
disallow_any_generics = true
|
||||||
|
check_untyped_defs = true
|
||||||
|
|
||||||
|
# Start here; tighten later
|
||||||
|
disallow_untyped_calls = true
|
||||||
|
disallow_incomplete_defs = true
|
||||||
|
disallow_subclassing_any = true
|
||||||
|
disallow_untyped_defs = true
|
||||||
|
disallow_untyped_decorators = true
|
||||||
|
|
||||||
|
plugins = ["sqlalchemy.ext.mypy.plugin", "pydantic.mypy"]
|
||||||
# --strict end
|
# --strict end
|
||||||
|
|
||||||
|
[tool.pydantic-mypy]
|
||||||
|
init_forbid_extra = true
|
||||||
|
init_typed = true
|
||||||
|
warn_required_dynamic_aliases = true
|
||||||
|
|||||||
@ -10,6 +10,7 @@ trim_trailing_whitespace = true
|
|||||||
|
|
||||||
[*.ts]
|
[*.ts]
|
||||||
quote_type = single
|
quote_type = single
|
||||||
|
ij_typescript_use_double_quotes = false
|
||||||
|
|
||||||
[*.md]
|
[*.md]
|
||||||
max_line_length = off
|
max_line_length = off
|
||||||
|
|||||||
Reference in New Issue
Block a user