Skip to content

Commit 37bae46

Browse files
committed
chore(repo): add .gitignore and prepare push
1 parent fc60d30 commit 37bae46

File tree

4,999 files changed

+85395
-84
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

4,999 files changed

+85395
-84
lines changed

.env.example

Lines changed: 0 additions & 10 deletions
This file was deleted.

.gitignore

Lines changed: 39 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,55 @@
1-
# Dependencies
2-
node_modules/
3-
.pnp/
4-
.pnp.js
5-
.npm
1+
# macOS
2+
.DS_Store
3+
4+
# Editors/IDE
5+
.vscode/
6+
.idea/
67

78
# Python
89
__pycache__/
910
*.py[cod]
10-
*$py.class
11-
*.so
12-
.Python
11+
*.pyo
12+
*.pyd
13+
*.egg-info/
14+
.python-version
15+
.venv/
16+
venv/
17+
.mypy_cache/
18+
.ruff_cache/
1319
.pytest_cache/
14-
.coverage
20+
coverage/
1521
htmlcov/
16-
.tox/
17-
.nox/
18-
.hypothesis/
19-
.pytest_cache/
20-
.coverage
21-
.env
22-
.venv
23-
env/
24-
venv/
25-
ENV/
26-
env.bak/
27-
venv.bak/
2822

29-
# Build outputs
30-
.next/
31-
/out/
32-
/build
33-
/dist
34-
/site/
35-
/combined_site/
36-
frontend/out/
37-
*/out/
38-
tmp_next_out/
39-
docs/assets/template-ui/
23+
# FastAPI/Build
24+
dist/
25+
build/
4026

41-
# Environment files
42-
.env.local
43-
.env.development
44-
.env.test
45-
.env.production
27+
# Alembic (keep versions tracked)
28+
# alembic/ <-- do NOT ignore versions
4629

47-
# Logs
48-
logs
49-
*.log
30+
# Node/Next.js
31+
node_modules/
5032
npm-debug.log*
5133
yarn-debug.log*
5234
yarn-error.log*
35+
.pnpm-store/
36+
.next/
37+
out/
38+
.cache/
5339

54-
# Misc
55-
.DS_Store
56-
*.pem
57-
Thumbs.db
58-
59-
# Editor directories and files
60-
.idea/
61-
.vscode/
62-
*.swp
63-
*.swo
40+
# Env files (keep example)
41+
.env
42+
.env.*
43+
!.env.example
6444

65-
# Vercel
66-
.vercel
45+
# Docker
46+
**/.dockerignore
47+
docker-data/
48+
*.pid
6749

68-
# Typescript
69-
*.tsbuildinfo
70-
next-env.d.ts
50+
# Frontend assets generated locally
51+
frontend/public/models/*.tmp
7152

72-
# Docker volumes
73-
*.volume
53+
# Large design/BIM assets (avoid pushing huge binaries; use LFS or separate storage)
54+
docs/kitchen-system-prime/**
55+
docs/kitchen-system-vvd/**

backend/Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,5 @@ ENV BACKEND_PORT=${BACKEND_PORT} \
2020

2121
EXPOSE ${BACKEND_PORT}
2222

23-
CMD ["uvicorn", "api.main:app", "--host", "0.0.0.0", "--port", "${BACKEND_PORT}"]
23+
# Use shell to expand ${BACKEND_PORT}
24+
CMD ["sh", "-lc", "uvicorn api.main:app --host 0.0.0.0 --port ${BACKEND_PORT}"]

backend/Dockerfile.dev

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ ENV BACKEND_PORT=${BACKEND_PORT} \
1515

1616
EXPOSE ${BACKEND_PORT}
1717

18-
CMD ["uvicorn", "api.main:app", "--host", "0.0.0.0", "--port", "${BACKEND_PORT}", "--reload"]
18+
# Use shell form to allow env var expansion for BACKEND_PORT
19+
CMD ["sh", "-lc", "uvicorn api.main:app --host 0.0.0.0 --port ${BACKEND_PORT} --reload"]

backend/alembic.ini

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
[alembic]
2+
script_location = alembic
3+
prepend_sys_path = .
4+
file_template = %%(rev)s_%%(slug)s
5+
timezone = UTC
6+
7+
[alembic:runtime]
8+
sqlalchemy.url =
9+
10+
[loggers]
11+
keys = root,sqlalchemy,alembic
12+
13+
[handlers]
14+
keys = console
15+
16+
[formatters]
17+
keys = generic
18+
19+
[logger_root]
20+
level = WARN
21+
handlers = console
22+
qualname =
23+
24+
[logger_sqlalchemy]
25+
level = WARN
26+
handlers =
27+
qualname = sqlalchemy.engine
28+
29+
[logger_alembic]
30+
level = INFO
31+
handlers = console
32+
qualname = alembic
33+
34+
[handler_console]
35+
class = StreamHandler
36+
args = (sys.stderr,)
37+
level = NOTSET
38+
formatter = generic
39+
40+
[formatter_generic]
41+
format = %(asctime)s %(levelname)-5.5s [%(name)s] %(message)s
42+
43+

backend/alembic/env.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
"""Alembic environment configuration.
2+
3+
This config reads the database URL from the environment variable ``DATABASE_URL``
4+
or falls back to the application's settings. It sets up both offline and online
5+
migration contexts and uses the application's Base metadata for autogenerate.
6+
"""
7+
8+
from __future__ import annotations
9+
10+
import os
11+
from logging.config import fileConfig
12+
13+
from alembic import context
14+
from sqlalchemy import engine_from_config, pool
15+
16+
# Interpret the config file for Python logging.
17+
config = context.config
18+
if config.config_file_name is not None:
19+
fileConfig(config.config_file_name)
20+
21+
# Import application metadata
22+
from api.db import Base, get_engine_url # noqa: E402
23+
24+
target_metadata = Base.metadata
25+
26+
27+
def get_url() -> str:
28+
env_url = os.getenv("DATABASE_URL")
29+
if env_url:
30+
return env_url
31+
return get_engine_url()
32+
33+
34+
def run_migrations_offline() -> None:
35+
"""Run migrations in 'offline' mode."""
36+
37+
url = get_url()
38+
context.configure(
39+
url=url,
40+
target_metadata=target_metadata,
41+
literal_binds=True,
42+
dialect_opts={"paramstyle": "named"},
43+
compare_type=True,
44+
render_as_batch=url.startswith("sqlite"),
45+
)
46+
47+
with context.begin_transaction():
48+
context.run_migrations()
49+
50+
51+
def run_migrations_online() -> None:
52+
"""Run migrations in 'online' mode."""
53+
54+
configuration = config.get_section(config.config_ini_section) or {}
55+
configuration["sqlalchemy.url"] = get_url()
56+
57+
connectable = engine_from_config(
58+
configuration,
59+
prefix="sqlalchemy.",
60+
poolclass=pool.NullPool,
61+
)
62+
63+
with connectable.connect() as connection:
64+
context.configure(
65+
connection=connection,
66+
target_metadata=target_metadata,
67+
compare_type=True,
68+
render_as_batch=configuration["sqlalchemy.url"].startswith("sqlite"),
69+
)
70+
71+
with context.begin_transaction():
72+
context.run_migrations()
73+
74+
75+
if context.is_offline_mode():
76+
run_migrations_offline()
77+
else:
78+
run_migrations_online()
79+
80+

backend/alembic/versions/.gitkeep

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
"""Initial Paform models
2+
3+
Revision ID: 0001
4+
Revises:
5+
Create Date: 2025-10-11 00:00:00
6+
"""
7+
8+
from __future__ import annotations
9+
10+
from alembic import op
11+
import sqlalchemy as sa
12+
from sqlalchemy.dialects import postgresql
13+
14+
15+
# revision identifiers, used by Alembic.
16+
revision = "0001"
17+
down_revision = None
18+
branch_labels = None
19+
depends_on = None
20+
21+
22+
def upgrade() -> None:
23+
op.create_table(
24+
"materials",
25+
sa.Column("id", sa.String(length=36), nullable=False),
26+
sa.Column("name", sa.String(length=255), nullable=False),
27+
sa.Column("texture_url", sa.String(length=2048), nullable=True),
28+
sa.Column("cost_per_sq_ft", sa.Float(), nullable=False, server_default=sa.text("0")),
29+
sa.Column(
30+
"external_ids",
31+
sa.JSON().with_variant(postgresql.JSONB(astext_type=sa.Text()), "postgresql"),
32+
nullable=True,
33+
),
34+
sa.Column("created_at", sa.TIMESTAMP(timezone=True), server_default=sa.text("CURRENT_TIMESTAMP"), nullable=False),
35+
sa.Column("updated_at", sa.TIMESTAMP(timezone=True), server_default=sa.text("CURRENT_TIMESTAMP"), nullable=True),
36+
sa.PrimaryKeyConstraint("id"),
37+
)
38+
op.create_index(op.f("ix_materials_name"), "materials", ["name"], unique=False)
39+
40+
op.create_table(
41+
"modules",
42+
sa.Column("id", sa.String(length=36), nullable=False),
43+
sa.Column("name", sa.String(length=255), nullable=False),
44+
sa.Column("width", sa.Float(), nullable=False),
45+
sa.Column("height", sa.Float(), nullable=False),
46+
sa.Column("depth", sa.Float(), nullable=False),
47+
sa.Column("base_price", sa.Float(), nullable=False, server_default=sa.text("0")),
48+
sa.Column("material_id", sa.String(length=36), nullable=False),
49+
sa.Column(
50+
"assembly_attributes",
51+
sa.JSON().with_variant(postgresql.JSONB(astext_type=sa.Text()), "postgresql"),
52+
nullable=True,
53+
),
54+
sa.Column(
55+
"placement_constraints",
56+
sa.JSON().with_variant(postgresql.JSONB(astext_type=sa.Text()), "postgresql"),
57+
nullable=True,
58+
),
59+
sa.Column(
60+
"connection_points",
61+
sa.JSON().with_variant(postgresql.JSONB(astext_type=sa.Text()), "postgresql"),
62+
nullable=True,
63+
),
64+
sa.Column(
65+
"external_ids",
66+
sa.JSON().with_variant(postgresql.JSONB(astext_type=sa.Text()), "postgresql"),
67+
nullable=True,
68+
),
69+
sa.Column("created_at", sa.TIMESTAMP(timezone=True), server_default=sa.text("CURRENT_TIMESTAMP"), nullable=False),
70+
sa.Column("updated_at", sa.TIMESTAMP(timezone=True), server_default=sa.text("CURRENT_TIMESTAMP"), nullable=True),
71+
sa.ForeignKeyConstraint(["material_id"], ["materials.id"], ondelete="RESTRICT"),
72+
sa.PrimaryKeyConstraint("id"),
73+
)
74+
op.create_index(op.f("ix_modules_name"), "modules", ["name"], unique=False)
75+
op.create_index("ix_modules_material_name", "modules", ["material_id", "name"], unique=False)
76+
77+
78+
def downgrade() -> None:
79+
op.drop_index("ix_modules_material_name", table_name="modules")
80+
op.drop_index(op.f("ix_modules_name"), table_name="modules")
81+
op.drop_table("modules")
82+
op.drop_index(op.f("ix_materials_name"), table_name="materials")
83+
op.drop_table("materials")
84+
85+

backend/api/config.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,21 @@ class Settings(BaseSettings):
2020
default=3000, description="Port for the frontend service"
2121
)
2222

23+
# Database and integration settings
24+
database_url: str = Field(
25+
default="sqlite:///./paform.db",
26+
description="SQLAlchemy database URL",
27+
)
28+
environment: str = Field(
29+
default="development", description="Runtime environment"
30+
)
31+
hygraph_endpoint: str = Field(
32+
default="", description="Hygraph GraphQL endpoint"
33+
)
34+
hygraph_token: str = Field(
35+
default="", description="Hygraph access token"
36+
)
37+
2338
# Add your custom settings here
2439
# example_api_key: str = Field(
2540
# default="", description="API key for Example service"

0 commit comments

Comments
 (0)