@cherishxn/agent-scaffold 0.0.0-stage → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +99 -2
- package/THIRD_PARTY_NOTICES.md +18 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +105 -0
- package/dist/diagnostics.d.ts +10 -0
- package/dist/diagnostics.js +27 -0
- package/dist/generate.d.ts +55 -0
- package/dist/generate.js +159 -0
- package/dist/model.d.ts +33 -0
- package/dist/model.js +24 -0
- package/dist/verify.d.ts +67 -0
- package/dist/verify.js +278 -0
- package/package.json +52 -4
- package/schemas/manifest.json +171 -0
- package/schemas/plan.json +164 -0
- package/schemas/result.json +97 -0
- package/schemas/spec.json +50 -0
- package/skills/scaffold-use/SKILL.md +24 -0
- package/templates/catalog.json +37 -0
- package/templates/next-fullstack-antd/.agents/skills/design-contract/SKILL.md +23 -0
- package/templates/next-fullstack-antd/.agents/skills/project-work/SKILL.md +10 -0
- package/templates/next-fullstack-antd/.claude/skills/design-contract/SKILL.md +23 -0
- package/templates/next-fullstack-antd/.claude/skills/project-work/SKILL.md +10 -0
- package/templates/next-fullstack-antd/.dockerignore +18 -0
- package/templates/next-fullstack-antd/.env.example +13 -0
- package/templates/next-fullstack-antd/.grok/skills/design-contract/SKILL.md +23 -0
- package/templates/next-fullstack-antd/.grok/skills/project-work/SKILL.md +10 -0
- package/templates/next-fullstack-antd/.scaffold-checks.json +7 -0
- package/templates/next-fullstack-antd/AGENTS.md +11 -0
- package/templates/next-fullstack-antd/CLAUDE.md +1 -0
- package/templates/next-fullstack-antd/DESIGN.md +208 -0
- package/templates/next-fullstack-antd/LICENSE +21 -0
- package/templates/next-fullstack-antd/README.md +64 -0
- package/templates/next-fullstack-antd/THIRD_PARTY_NOTICES.md +18 -0
- package/templates/next-fullstack-antd/compose.yaml +18 -0
- package/templates/next-fullstack-antd/design/guide.md +61 -0
- package/templates/next-fullstack-antd/design/layout.css +6 -0
- package/templates/next-fullstack-antd/design/structure.json +107 -0
- package/templates/next-fullstack-antd/design/tokens.json +171 -0
- package/templates/next-fullstack-antd/design/widgets.css +30 -0
- package/templates/next-fullstack-antd/design/widgets.json +233 -0
- package/templates/next-fullstack-antd/docs/PROJECT.md +32 -0
- package/templates/next-fullstack-antd/docs/api.d.ts +544 -0
- package/templates/next-fullstack-antd/docs/openapi.json +461 -0
- package/templates/next-fullstack-antd/gitignore.template +19 -0
- package/templates/next-fullstack-antd/licenses/fastapi.txt +21 -0
- package/templates/next-fullstack-antd/licenses/nest.txt +22 -0
- package/templates/next-fullstack-antd/licenses/next.txt +21 -0
- package/templates/next-fullstack-antd/licenses/shadcn.txt +21 -0
- package/templates/next-fullstack-antd/licenses/sources.json +27 -0
- package/templates/next-fullstack-antd/licenses/spring.txt +202 -0
- package/templates/next-fullstack-antd/package-lock.json +494 -0
- package/templates/next-fullstack-antd/package.json +26 -0
- package/templates/next-fullstack-antd/playwright.config.ts +3 -0
- package/templates/next-fullstack-antd/project.json +8 -0
- package/templates/next-fullstack-antd/scripts/api-check.mjs +18 -0
- package/templates/next-fullstack-antd/scripts/api-contract.mjs +46 -0
- package/templates/next-fullstack-antd/scripts/design-coverage.mjs +20 -0
- package/templates/next-fullstack-antd/scripts/design-next-cleanup.mjs +13 -0
- package/templates/next-fullstack-antd/scripts/design-verify.mjs +154 -0
- package/templates/next-fullstack-antd/scripts/design.mjs +108 -0
- package/templates/next-fullstack-antd/scripts/project.mjs +120 -0
- package/templates/next-fullstack-antd/tests/contract-client.ts +20 -0
- package/templates/next-fullstack-antd/tests/contract.spec.ts +49 -0
- package/templates/next-fullstack-antd/tests/design/harness.tsx +63 -0
- package/templates/next-fullstack-antd/tests/ui.spec.ts +61 -0
- package/templates/next-fullstack-antd/web/Dockerfile +12 -0
- package/templates/next-fullstack-antd/web/app/api/auth/login/route.ts +1 -0
- package/templates/next-fullstack-antd/web/app/api/auth/logout/route.ts +1 -0
- package/templates/next-fullstack-antd/web/app/api/auth/me/route.ts +1 -0
- package/templates/next-fullstack-antd/web/app/api/health/route.ts +1 -0
- package/templates/next-fullstack-antd/web/app/api/records/[id]/route.ts +5 -0
- package/templates/next-fullstack-antd/web/app/api/records/route.ts +3 -0
- package/templates/next-fullstack-antd/web/app/layout.tsx +5 -0
- package/templates/next-fullstack-antd/web/app/page.tsx +2 -0
- package/templates/next-fullstack-antd/web/eslint.config.mjs +3 -0
- package/templates/next-fullstack-antd/web/lib/api.ts +35 -0
- package/templates/next-fullstack-antd/web/lib/auth.ts +10 -0
- package/templates/next-fullstack-antd/web/lib/db.ts +3 -0
- package/templates/next-fullstack-antd/web/lib/session.test.ts +15 -0
- package/templates/next-fullstack-antd/web/lib/validation.test.ts +3 -0
- package/templates/next-fullstack-antd/web/lib/validation.ts +5 -0
- package/templates/next-fullstack-antd/web/next-env.d.ts +7 -0
- package/templates/next-fullstack-antd/web/next.config.ts +3 -0
- package/templates/next-fullstack-antd/web/package.json +35 -0
- package/templates/next-fullstack-antd/web/pnpm-lock.yaml +3756 -0
- package/templates/next-fullstack-antd/web/pnpm-workspace.yaml +7 -0
- package/templates/next-fullstack-antd/web/prisma/migrations/202610190001_initial/migration.sql +99 -0
- package/templates/next-fullstack-antd/web/prisma/migrations/migration_lock.toml +1 -0
- package/templates/next-fullstack-antd/web/prisma/schema.prisma +72 -0
- package/templates/next-fullstack-antd/web/scripts/seed.ts +4 -0
- package/templates/next-fullstack-antd/web/src/App.tsx +29 -0
- package/templates/next-fullstack-antd/web/src/design-layout.css +7 -0
- package/templates/next-fullstack-antd/web/src/design-runtime.json +511 -0
- package/templates/next-fullstack-antd/web/src/design-tokens.css +168 -0
- package/templates/next-fullstack-antd/web/src/design-widgets.css +31 -0
- package/templates/next-fullstack-antd/web/src/structure-view.tsx +16 -0
- package/templates/next-fullstack-antd/web/src/styles.css +3 -0
- package/templates/next-fullstack-antd/web/src/ui.tsx +30 -0
- package/templates/next-fullstack-antd/web/src/widget-icon.tsx +5 -0
- package/templates/next-fullstack-antd/web/src/widget-types.ts +13 -0
- package/templates/next-fullstack-antd/web/src/workspace-model.ts +85 -0
- package/templates/next-fullstack-antd/web/tsconfig.json +42 -0
- package/templates/next-fullstack-antd/web/vitest.config.ts +2 -0
- package/templates/next-fullstack-shadcn/.agents/skills/design-contract/SKILL.md +23 -0
- package/templates/next-fullstack-shadcn/.agents/skills/project-work/SKILL.md +10 -0
- package/templates/next-fullstack-shadcn/.claude/skills/design-contract/SKILL.md +23 -0
- package/templates/next-fullstack-shadcn/.claude/skills/project-work/SKILL.md +10 -0
- package/templates/next-fullstack-shadcn/.dockerignore +18 -0
- package/templates/next-fullstack-shadcn/.env.example +13 -0
- package/templates/next-fullstack-shadcn/.grok/skills/design-contract/SKILL.md +23 -0
- package/templates/next-fullstack-shadcn/.grok/skills/project-work/SKILL.md +10 -0
- package/templates/next-fullstack-shadcn/.scaffold-checks.json +7 -0
- package/templates/next-fullstack-shadcn/AGENTS.md +11 -0
- package/templates/next-fullstack-shadcn/CLAUDE.md +1 -0
- package/templates/next-fullstack-shadcn/DESIGN.md +208 -0
- package/templates/next-fullstack-shadcn/LICENSE +21 -0
- package/templates/next-fullstack-shadcn/README.md +64 -0
- package/templates/next-fullstack-shadcn/THIRD_PARTY_NOTICES.md +18 -0
- package/templates/next-fullstack-shadcn/compose.yaml +18 -0
- package/templates/next-fullstack-shadcn/design/guide.md +61 -0
- package/templates/next-fullstack-shadcn/design/layout.css +6 -0
- package/templates/next-fullstack-shadcn/design/structure.json +107 -0
- package/templates/next-fullstack-shadcn/design/tokens.json +171 -0
- package/templates/next-fullstack-shadcn/design/widgets.css +30 -0
- package/templates/next-fullstack-shadcn/design/widgets.json +233 -0
- package/templates/next-fullstack-shadcn/docs/PROJECT.md +32 -0
- package/templates/next-fullstack-shadcn/docs/api.d.ts +544 -0
- package/templates/next-fullstack-shadcn/docs/openapi.json +461 -0
- package/templates/next-fullstack-shadcn/gitignore.template +19 -0
- package/templates/next-fullstack-shadcn/licenses/fastapi.txt +21 -0
- package/templates/next-fullstack-shadcn/licenses/nest.txt +22 -0
- package/templates/next-fullstack-shadcn/licenses/next.txt +21 -0
- package/templates/next-fullstack-shadcn/licenses/shadcn.txt +21 -0
- package/templates/next-fullstack-shadcn/licenses/sources.json +27 -0
- package/templates/next-fullstack-shadcn/licenses/spring.txt +202 -0
- package/templates/next-fullstack-shadcn/package-lock.json +494 -0
- package/templates/next-fullstack-shadcn/package.json +26 -0
- package/templates/next-fullstack-shadcn/playwright.config.ts +3 -0
- package/templates/next-fullstack-shadcn/project.json +8 -0
- package/templates/next-fullstack-shadcn/scripts/api-check.mjs +18 -0
- package/templates/next-fullstack-shadcn/scripts/api-contract.mjs +46 -0
- package/templates/next-fullstack-shadcn/scripts/design-coverage.mjs +20 -0
- package/templates/next-fullstack-shadcn/scripts/design-next-cleanup.mjs +13 -0
- package/templates/next-fullstack-shadcn/scripts/design-verify.mjs +154 -0
- package/templates/next-fullstack-shadcn/scripts/design.mjs +108 -0
- package/templates/next-fullstack-shadcn/scripts/project.mjs +120 -0
- package/templates/next-fullstack-shadcn/tests/contract-client.ts +20 -0
- package/templates/next-fullstack-shadcn/tests/contract.spec.ts +49 -0
- package/templates/next-fullstack-shadcn/tests/design/harness.tsx +63 -0
- package/templates/next-fullstack-shadcn/tests/ui.spec.ts +61 -0
- package/templates/next-fullstack-shadcn/web/Dockerfile +12 -0
- package/templates/next-fullstack-shadcn/web/app/api/auth/login/route.ts +1 -0
- package/templates/next-fullstack-shadcn/web/app/api/auth/logout/route.ts +1 -0
- package/templates/next-fullstack-shadcn/web/app/api/auth/me/route.ts +1 -0
- package/templates/next-fullstack-shadcn/web/app/api/health/route.ts +1 -0
- package/templates/next-fullstack-shadcn/web/app/api/records/[id]/route.ts +5 -0
- package/templates/next-fullstack-shadcn/web/app/api/records/route.ts +3 -0
- package/templates/next-fullstack-shadcn/web/app/layout.tsx +4 -0
- package/templates/next-fullstack-shadcn/web/app/page.tsx +2 -0
- package/templates/next-fullstack-shadcn/web/eslint.config.mjs +3 -0
- package/templates/next-fullstack-shadcn/web/lib/api.ts +35 -0
- package/templates/next-fullstack-shadcn/web/lib/auth.ts +10 -0
- package/templates/next-fullstack-shadcn/web/lib/db.ts +3 -0
- package/templates/next-fullstack-shadcn/web/lib/session.test.ts +15 -0
- package/templates/next-fullstack-shadcn/web/lib/validation.test.ts +3 -0
- package/templates/next-fullstack-shadcn/web/lib/validation.ts +5 -0
- package/templates/next-fullstack-shadcn/web/next-env.d.ts +7 -0
- package/templates/next-fullstack-shadcn/web/next.config.ts +3 -0
- package/templates/next-fullstack-shadcn/web/package.json +39 -0
- package/templates/next-fullstack-shadcn/web/pnpm-lock.yaml +3286 -0
- package/templates/next-fullstack-shadcn/web/pnpm-workspace.yaml +7 -0
- package/templates/next-fullstack-shadcn/web/postcss.config.mjs +1 -0
- package/templates/next-fullstack-shadcn/web/prisma/migrations/202610190001_initial/migration.sql +99 -0
- package/templates/next-fullstack-shadcn/web/prisma/migrations/migration_lock.toml +1 -0
- package/templates/next-fullstack-shadcn/web/prisma/schema.prisma +72 -0
- package/templates/next-fullstack-shadcn/web/scripts/seed.ts +4 -0
- package/templates/next-fullstack-shadcn/web/src/App.tsx +30 -0
- package/templates/next-fullstack-shadcn/web/src/design-layout.css +7 -0
- package/templates/next-fullstack-shadcn/web/src/design-runtime.json +511 -0
- package/templates/next-fullstack-shadcn/web/src/design-tokens.css +168 -0
- package/templates/next-fullstack-shadcn/web/src/design-widgets.css +31 -0
- package/templates/next-fullstack-shadcn/web/src/structure-view.tsx +16 -0
- package/templates/next-fullstack-shadcn/web/src/styles.css +3 -0
- package/templates/next-fullstack-shadcn/web/src/tailwind.css +2 -0
- package/templates/next-fullstack-shadcn/web/src/ui.tsx +13 -0
- package/templates/next-fullstack-shadcn/web/src/widget-icon.tsx +5 -0
- package/templates/next-fullstack-shadcn/web/src/widget-types.ts +13 -0
- package/templates/next-fullstack-shadcn/web/src/workspace-model.ts +85 -0
- package/templates/next-fullstack-shadcn/web/tsconfig.json +42 -0
- package/templates/next-fullstack-shadcn/web/vitest.config.ts +2 -0
- package/templates/react-fastapi-antd/.agents/skills/design-contract/SKILL.md +23 -0
- package/templates/react-fastapi-antd/.agents/skills/project-work/SKILL.md +10 -0
- package/templates/react-fastapi-antd/.claude/skills/design-contract/SKILL.md +23 -0
- package/templates/react-fastapi-antd/.claude/skills/project-work/SKILL.md +10 -0
- package/templates/react-fastapi-antd/.dockerignore +18 -0
- package/templates/react-fastapi-antd/.env.example +13 -0
- package/templates/react-fastapi-antd/.grok/skills/design-contract/SKILL.md +23 -0
- package/templates/react-fastapi-antd/.grok/skills/project-work/SKILL.md +10 -0
- package/templates/react-fastapi-antd/.scaffold-checks.json +7 -0
- package/templates/react-fastapi-antd/AGENTS.md +11 -0
- package/templates/react-fastapi-antd/CLAUDE.md +1 -0
- package/templates/react-fastapi-antd/DESIGN.md +208 -0
- package/templates/react-fastapi-antd/LICENSE +21 -0
- package/templates/react-fastapi-antd/README.md +64 -0
- package/templates/react-fastapi-antd/THIRD_PARTY_NOTICES.md +18 -0
- package/templates/react-fastapi-antd/backend/.python-version +1 -0
- package/templates/react-fastapi-antd/backend/Dockerfile +10 -0
- package/templates/react-fastapi-antd/backend/alembic.ini +3 -0
- package/templates/react-fastapi-antd/backend/app/__init__.py +0 -0
- package/templates/react-fastapi-antd/backend/app/core/__init__.py +0 -0
- package/templates/react-fastapi-antd/backend/app/core/security.py +25 -0
- package/templates/react-fastapi-antd/backend/app/db.py +11 -0
- package/templates/react-fastapi-antd/backend/app/main.py +146 -0
- package/templates/react-fastapi-antd/backend/app/models.py +21 -0
- package/templates/react-fastapi-antd/backend/app/seed.py +21 -0
- package/templates/react-fastapi-antd/backend/migrations/env.py +9 -0
- package/templates/react-fastapi-antd/backend/migrations/versions/0001_initial.py +18 -0
- package/templates/react-fastapi-antd/backend/pyproject.toml +16 -0
- package/templates/react-fastapi-antd/backend/tests/test_api.py +27 -0
- package/templates/react-fastapi-antd/backend/uv.lock +1085 -0
- package/templates/react-fastapi-antd/compose.yaml +18 -0
- package/templates/react-fastapi-antd/design/guide.md +61 -0
- package/templates/react-fastapi-antd/design/layout.css +6 -0
- package/templates/react-fastapi-antd/design/structure.json +107 -0
- package/templates/react-fastapi-antd/design/tokens.json +171 -0
- package/templates/react-fastapi-antd/design/widgets.css +30 -0
- package/templates/react-fastapi-antd/design/widgets.json +233 -0
- package/templates/react-fastapi-antd/docs/PROJECT.md +32 -0
- package/templates/react-fastapi-antd/docs/api.d.ts +544 -0
- package/templates/react-fastapi-antd/docs/openapi.json +461 -0
- package/templates/react-fastapi-antd/gitignore.template +19 -0
- package/templates/react-fastapi-antd/licenses/fastapi.txt +21 -0
- package/templates/react-fastapi-antd/licenses/nest.txt +22 -0
- package/templates/react-fastapi-antd/licenses/next.txt +21 -0
- package/templates/react-fastapi-antd/licenses/shadcn.txt +21 -0
- package/templates/react-fastapi-antd/licenses/sources.json +27 -0
- package/templates/react-fastapi-antd/licenses/spring.txt +202 -0
- package/templates/react-fastapi-antd/package-lock.json +494 -0
- package/templates/react-fastapi-antd/package.json +26 -0
- package/templates/react-fastapi-antd/playwright.config.ts +3 -0
- package/templates/react-fastapi-antd/project.json +8 -0
- package/templates/react-fastapi-antd/scripts/api-check.mjs +18 -0
- package/templates/react-fastapi-antd/scripts/api-contract.mjs +46 -0
- package/templates/react-fastapi-antd/scripts/design-coverage.mjs +20 -0
- package/templates/react-fastapi-antd/scripts/design-next-cleanup.mjs +13 -0
- package/templates/react-fastapi-antd/scripts/design-verify.mjs +154 -0
- package/templates/react-fastapi-antd/scripts/design.mjs +108 -0
- package/templates/react-fastapi-antd/scripts/project.mjs +120 -0
- package/templates/react-fastapi-antd/tests/contract-client.ts +20 -0
- package/templates/react-fastapi-antd/tests/contract.spec.ts +49 -0
- package/templates/react-fastapi-antd/tests/design/harness.tsx +63 -0
- package/templates/react-fastapi-antd/tests/ui.spec.ts +61 -0
- package/templates/react-fastapi-antd/web/bun.lock +442 -0
- package/templates/react-fastapi-antd/web/eslint.config.mjs +3 -0
- package/templates/react-fastapi-antd/web/index.html +1 -0
- package/templates/react-fastapi-antd/web/package.json +28 -0
- package/templates/react-fastapi-antd/web/src/App.tsx +29 -0
- package/templates/react-fastapi-antd/web/src/design-layout.css +7 -0
- package/templates/react-fastapi-antd/web/src/design-runtime.json +511 -0
- package/templates/react-fastapi-antd/web/src/design-tokens.css +168 -0
- package/templates/react-fastapi-antd/web/src/design-widgets.css +31 -0
- package/templates/react-fastapi-antd/web/src/main.tsx +6 -0
- package/templates/react-fastapi-antd/web/src/structure-view.tsx +16 -0
- package/templates/react-fastapi-antd/web/src/styles.css +3 -0
- package/templates/react-fastapi-antd/web/src/ui.tsx +30 -0
- package/templates/react-fastapi-antd/web/src/widget-icon.tsx +5 -0
- package/templates/react-fastapi-antd/web/src/widget-types.ts +13 -0
- package/templates/react-fastapi-antd/web/src/workspace-model.ts +85 -0
- package/templates/react-fastapi-antd/web/tsconfig.json +22 -0
- package/templates/react-fastapi-antd/web/vite.config.ts +3 -0
- package/templates/react-fastapi-shadcn/.agents/skills/design-contract/SKILL.md +23 -0
- package/templates/react-fastapi-shadcn/.agents/skills/project-work/SKILL.md +10 -0
- package/templates/react-fastapi-shadcn/.claude/skills/design-contract/SKILL.md +23 -0
- package/templates/react-fastapi-shadcn/.claude/skills/project-work/SKILL.md +10 -0
- package/templates/react-fastapi-shadcn/.dockerignore +18 -0
- package/templates/react-fastapi-shadcn/.env.example +13 -0
- package/templates/react-fastapi-shadcn/.grok/skills/design-contract/SKILL.md +23 -0
- package/templates/react-fastapi-shadcn/.grok/skills/project-work/SKILL.md +10 -0
- package/templates/react-fastapi-shadcn/.scaffold-checks.json +7 -0
- package/templates/react-fastapi-shadcn/AGENTS.md +11 -0
- package/templates/react-fastapi-shadcn/CLAUDE.md +1 -0
- package/templates/react-fastapi-shadcn/DESIGN.md +208 -0
- package/templates/react-fastapi-shadcn/LICENSE +21 -0
- package/templates/react-fastapi-shadcn/README.md +64 -0
- package/templates/react-fastapi-shadcn/THIRD_PARTY_NOTICES.md +18 -0
- package/templates/react-fastapi-shadcn/backend/.python-version +1 -0
- package/templates/react-fastapi-shadcn/backend/Dockerfile +10 -0
- package/templates/react-fastapi-shadcn/backend/alembic.ini +3 -0
- package/templates/react-fastapi-shadcn/backend/app/__init__.py +0 -0
- package/templates/react-fastapi-shadcn/backend/app/core/__init__.py +0 -0
- package/templates/react-fastapi-shadcn/backend/app/core/security.py +25 -0
- package/templates/react-fastapi-shadcn/backend/app/db.py +11 -0
- package/templates/react-fastapi-shadcn/backend/app/main.py +146 -0
- package/templates/react-fastapi-shadcn/backend/app/models.py +21 -0
- package/templates/react-fastapi-shadcn/backend/app/seed.py +21 -0
- package/templates/react-fastapi-shadcn/backend/migrations/env.py +9 -0
- package/templates/react-fastapi-shadcn/backend/migrations/versions/0001_initial.py +18 -0
- package/templates/react-fastapi-shadcn/backend/pyproject.toml +16 -0
- package/templates/react-fastapi-shadcn/backend/tests/test_api.py +27 -0
- package/templates/react-fastapi-shadcn/backend/uv.lock +1085 -0
- package/templates/react-fastapi-shadcn/compose.yaml +18 -0
- package/templates/react-fastapi-shadcn/design/guide.md +61 -0
- package/templates/react-fastapi-shadcn/design/layout.css +6 -0
- package/templates/react-fastapi-shadcn/design/structure.json +107 -0
- package/templates/react-fastapi-shadcn/design/tokens.json +171 -0
- package/templates/react-fastapi-shadcn/design/widgets.css +30 -0
- package/templates/react-fastapi-shadcn/design/widgets.json +233 -0
- package/templates/react-fastapi-shadcn/docs/PROJECT.md +32 -0
- package/templates/react-fastapi-shadcn/docs/api.d.ts +544 -0
- package/templates/react-fastapi-shadcn/docs/openapi.json +461 -0
- package/templates/react-fastapi-shadcn/gitignore.template +19 -0
- package/templates/react-fastapi-shadcn/licenses/fastapi.txt +21 -0
- package/templates/react-fastapi-shadcn/licenses/nest.txt +22 -0
- package/templates/react-fastapi-shadcn/licenses/next.txt +21 -0
- package/templates/react-fastapi-shadcn/licenses/shadcn.txt +21 -0
- package/templates/react-fastapi-shadcn/licenses/sources.json +27 -0
- package/templates/react-fastapi-shadcn/licenses/spring.txt +202 -0
- package/templates/react-fastapi-shadcn/package-lock.json +494 -0
- package/templates/react-fastapi-shadcn/package.json +26 -0
- package/templates/react-fastapi-shadcn/playwright.config.ts +3 -0
- package/templates/react-fastapi-shadcn/project.json +8 -0
- package/templates/react-fastapi-shadcn/scripts/api-check.mjs +18 -0
- package/templates/react-fastapi-shadcn/scripts/api-contract.mjs +46 -0
- package/templates/react-fastapi-shadcn/scripts/design-coverage.mjs +20 -0
- package/templates/react-fastapi-shadcn/scripts/design-next-cleanup.mjs +13 -0
- package/templates/react-fastapi-shadcn/scripts/design-verify.mjs +154 -0
- package/templates/react-fastapi-shadcn/scripts/design.mjs +108 -0
- package/templates/react-fastapi-shadcn/scripts/project.mjs +120 -0
- package/templates/react-fastapi-shadcn/tests/contract-client.ts +20 -0
- package/templates/react-fastapi-shadcn/tests/contract.spec.ts +49 -0
- package/templates/react-fastapi-shadcn/tests/design/harness.tsx +63 -0
- package/templates/react-fastapi-shadcn/tests/ui.spec.ts +61 -0
- package/templates/react-fastapi-shadcn/web/bun.lock +413 -0
- package/templates/react-fastapi-shadcn/web/eslint.config.mjs +3 -0
- package/templates/react-fastapi-shadcn/web/index.html +1 -0
- package/templates/react-fastapi-shadcn/web/package.json +33 -0
- package/templates/react-fastapi-shadcn/web/src/App.tsx +30 -0
- package/templates/react-fastapi-shadcn/web/src/design-layout.css +7 -0
- package/templates/react-fastapi-shadcn/web/src/design-runtime.json +511 -0
- package/templates/react-fastapi-shadcn/web/src/design-tokens.css +168 -0
- package/templates/react-fastapi-shadcn/web/src/design-widgets.css +31 -0
- package/templates/react-fastapi-shadcn/web/src/main.tsx +6 -0
- package/templates/react-fastapi-shadcn/web/src/structure-view.tsx +16 -0
- package/templates/react-fastapi-shadcn/web/src/styles.css +3 -0
- package/templates/react-fastapi-shadcn/web/src/tailwind.css +2 -0
- package/templates/react-fastapi-shadcn/web/src/ui.tsx +13 -0
- package/templates/react-fastapi-shadcn/web/src/widget-icon.tsx +5 -0
- package/templates/react-fastapi-shadcn/web/src/widget-types.ts +13 -0
- package/templates/react-fastapi-shadcn/web/src/workspace-model.ts +85 -0
- package/templates/react-fastapi-shadcn/web/tsconfig.json +22 -0
- package/templates/react-fastapi-shadcn/web/vite.config.ts +4 -0
- package/templates/react-nest-antd/.agents/skills/design-contract/SKILL.md +23 -0
- package/templates/react-nest-antd/.agents/skills/project-work/SKILL.md +10 -0
- package/templates/react-nest-antd/.claude/skills/design-contract/SKILL.md +23 -0
- package/templates/react-nest-antd/.claude/skills/project-work/SKILL.md +10 -0
- package/templates/react-nest-antd/.dockerignore +18 -0
- package/templates/react-nest-antd/.env.example +13 -0
- package/templates/react-nest-antd/.grok/skills/design-contract/SKILL.md +23 -0
- package/templates/react-nest-antd/.grok/skills/project-work/SKILL.md +10 -0
- package/templates/react-nest-antd/.scaffold-checks.json +7 -0
- package/templates/react-nest-antd/AGENTS.md +11 -0
- package/templates/react-nest-antd/CLAUDE.md +1 -0
- package/templates/react-nest-antd/DESIGN.md +208 -0
- package/templates/react-nest-antd/LICENSE +21 -0
- package/templates/react-nest-antd/README.md +64 -0
- package/templates/react-nest-antd/THIRD_PARTY_NOTICES.md +18 -0
- package/templates/react-nest-antd/backend/Dockerfile +12 -0
- package/templates/react-nest-antd/backend/eslint.config.mjs +3 -0
- package/templates/react-nest-antd/backend/jest.config.cjs +1 -0
- package/templates/react-nest-antd/backend/package.json +40 -0
- package/templates/react-nest-antd/backend/pnpm-lock.yaml +5165 -0
- package/templates/react-nest-antd/backend/pnpm-workspace.yaml +6 -0
- package/templates/react-nest-antd/backend/prisma/migrations/202610190001_initial/migration.sql +3 -0
- package/templates/react-nest-antd/backend/prisma/migrations/migration_lock.toml +1 -0
- package/templates/react-nest-antd/backend/prisma/schema.prisma +25 -0
- package/templates/react-nest-antd/backend/scripts/seed.ts +4 -0
- package/templates/react-nest-antd/backend/src/app.module.ts +43 -0
- package/templates/react-nest-antd/backend/src/main.ts +6 -0
- package/templates/react-nest-antd/backend/src/password.ts +3 -0
- package/templates/react-nest-antd/backend/src/validation.ts +7 -0
- package/templates/react-nest-antd/backend/test/api.test.ts +25 -0
- package/templates/react-nest-antd/backend/tsconfig.build.json +15 -0
- package/templates/react-nest-antd/backend/tsconfig.json +17 -0
- package/templates/react-nest-antd/compose.yaml +18 -0
- package/templates/react-nest-antd/design/guide.md +61 -0
- package/templates/react-nest-antd/design/layout.css +6 -0
- package/templates/react-nest-antd/design/structure.json +107 -0
- package/templates/react-nest-antd/design/tokens.json +171 -0
- package/templates/react-nest-antd/design/widgets.css +30 -0
- package/templates/react-nest-antd/design/widgets.json +233 -0
- package/templates/react-nest-antd/docs/PROJECT.md +32 -0
- package/templates/react-nest-antd/docs/api.d.ts +544 -0
- package/templates/react-nest-antd/docs/openapi.json +461 -0
- package/templates/react-nest-antd/gitignore.template +19 -0
- package/templates/react-nest-antd/licenses/fastapi.txt +21 -0
- package/templates/react-nest-antd/licenses/nest.txt +22 -0
- package/templates/react-nest-antd/licenses/next.txt +21 -0
- package/templates/react-nest-antd/licenses/shadcn.txt +21 -0
- package/templates/react-nest-antd/licenses/sources.json +27 -0
- package/templates/react-nest-antd/licenses/spring.txt +202 -0
- package/templates/react-nest-antd/package-lock.json +494 -0
- package/templates/react-nest-antd/package.json +26 -0
- package/templates/react-nest-antd/playwright.config.ts +3 -0
- package/templates/react-nest-antd/project.json +8 -0
- package/templates/react-nest-antd/scripts/api-check.mjs +18 -0
- package/templates/react-nest-antd/scripts/api-contract.mjs +46 -0
- package/templates/react-nest-antd/scripts/design-coverage.mjs +20 -0
- package/templates/react-nest-antd/scripts/design-next-cleanup.mjs +13 -0
- package/templates/react-nest-antd/scripts/design-verify.mjs +154 -0
- package/templates/react-nest-antd/scripts/design.mjs +108 -0
- package/templates/react-nest-antd/scripts/project.mjs +120 -0
- package/templates/react-nest-antd/tests/contract-client.ts +20 -0
- package/templates/react-nest-antd/tests/contract.spec.ts +49 -0
- package/templates/react-nest-antd/tests/design/harness.tsx +63 -0
- package/templates/react-nest-antd/tests/ui.spec.ts +61 -0
- package/templates/react-nest-antd/web/eslint.config.mjs +3 -0
- package/templates/react-nest-antd/web/index.html +1 -0
- package/templates/react-nest-antd/web/package.json +28 -0
- package/templates/react-nest-antd/web/pnpm-lock.yaml +2215 -0
- package/templates/react-nest-antd/web/src/App.tsx +29 -0
- package/templates/react-nest-antd/web/src/design-layout.css +7 -0
- package/templates/react-nest-antd/web/src/design-runtime.json +511 -0
- package/templates/react-nest-antd/web/src/design-tokens.css +168 -0
- package/templates/react-nest-antd/web/src/design-widgets.css +31 -0
- package/templates/react-nest-antd/web/src/main.tsx +6 -0
- package/templates/react-nest-antd/web/src/structure-view.tsx +16 -0
- package/templates/react-nest-antd/web/src/styles.css +3 -0
- package/templates/react-nest-antd/web/src/ui.tsx +30 -0
- package/templates/react-nest-antd/web/src/widget-icon.tsx +5 -0
- package/templates/react-nest-antd/web/src/widget-types.ts +13 -0
- package/templates/react-nest-antd/web/src/workspace-model.ts +85 -0
- package/templates/react-nest-antd/web/tsconfig.json +22 -0
- package/templates/react-nest-antd/web/vite.config.ts +3 -0
- package/templates/react-nest-shadcn/.agents/skills/design-contract/SKILL.md +23 -0
- package/templates/react-nest-shadcn/.agents/skills/project-work/SKILL.md +10 -0
- package/templates/react-nest-shadcn/.claude/skills/design-contract/SKILL.md +23 -0
- package/templates/react-nest-shadcn/.claude/skills/project-work/SKILL.md +10 -0
- package/templates/react-nest-shadcn/.dockerignore +18 -0
- package/templates/react-nest-shadcn/.env.example +13 -0
- package/templates/react-nest-shadcn/.grok/skills/design-contract/SKILL.md +23 -0
- package/templates/react-nest-shadcn/.grok/skills/project-work/SKILL.md +10 -0
- package/templates/react-nest-shadcn/.scaffold-checks.json +7 -0
- package/templates/react-nest-shadcn/AGENTS.md +11 -0
- package/templates/react-nest-shadcn/CLAUDE.md +1 -0
- package/templates/react-nest-shadcn/DESIGN.md +208 -0
- package/templates/react-nest-shadcn/LICENSE +21 -0
- package/templates/react-nest-shadcn/README.md +64 -0
- package/templates/react-nest-shadcn/THIRD_PARTY_NOTICES.md +18 -0
- package/templates/react-nest-shadcn/backend/Dockerfile +12 -0
- package/templates/react-nest-shadcn/backend/eslint.config.mjs +3 -0
- package/templates/react-nest-shadcn/backend/jest.config.cjs +1 -0
- package/templates/react-nest-shadcn/backend/package.json +40 -0
- package/templates/react-nest-shadcn/backend/pnpm-lock.yaml +5165 -0
- package/templates/react-nest-shadcn/backend/pnpm-workspace.yaml +6 -0
- package/templates/react-nest-shadcn/backend/prisma/migrations/202610190001_initial/migration.sql +3 -0
- package/templates/react-nest-shadcn/backend/prisma/migrations/migration_lock.toml +1 -0
- package/templates/react-nest-shadcn/backend/prisma/schema.prisma +25 -0
- package/templates/react-nest-shadcn/backend/scripts/seed.ts +4 -0
- package/templates/react-nest-shadcn/backend/src/app.module.ts +43 -0
- package/templates/react-nest-shadcn/backend/src/main.ts +6 -0
- package/templates/react-nest-shadcn/backend/src/password.ts +3 -0
- package/templates/react-nest-shadcn/backend/src/validation.ts +7 -0
- package/templates/react-nest-shadcn/backend/test/api.test.ts +25 -0
- package/templates/react-nest-shadcn/backend/tsconfig.build.json +15 -0
- package/templates/react-nest-shadcn/backend/tsconfig.json +17 -0
- package/templates/react-nest-shadcn/compose.yaml +18 -0
- package/templates/react-nest-shadcn/design/guide.md +61 -0
- package/templates/react-nest-shadcn/design/layout.css +6 -0
- package/templates/react-nest-shadcn/design/structure.json +107 -0
- package/templates/react-nest-shadcn/design/tokens.json +171 -0
- package/templates/react-nest-shadcn/design/widgets.css +30 -0
- package/templates/react-nest-shadcn/design/widgets.json +233 -0
- package/templates/react-nest-shadcn/docs/PROJECT.md +32 -0
- package/templates/react-nest-shadcn/docs/api.d.ts +544 -0
- package/templates/react-nest-shadcn/docs/openapi.json +461 -0
- package/templates/react-nest-shadcn/gitignore.template +19 -0
- package/templates/react-nest-shadcn/licenses/fastapi.txt +21 -0
- package/templates/react-nest-shadcn/licenses/nest.txt +22 -0
- package/templates/react-nest-shadcn/licenses/next.txt +21 -0
- package/templates/react-nest-shadcn/licenses/shadcn.txt +21 -0
- package/templates/react-nest-shadcn/licenses/sources.json +27 -0
- package/templates/react-nest-shadcn/licenses/spring.txt +202 -0
- package/templates/react-nest-shadcn/package-lock.json +494 -0
- package/templates/react-nest-shadcn/package.json +26 -0
- package/templates/react-nest-shadcn/playwright.config.ts +3 -0
- package/templates/react-nest-shadcn/project.json +8 -0
- package/templates/react-nest-shadcn/scripts/api-check.mjs +18 -0
- package/templates/react-nest-shadcn/scripts/api-contract.mjs +46 -0
- package/templates/react-nest-shadcn/scripts/design-coverage.mjs +20 -0
- package/templates/react-nest-shadcn/scripts/design-next-cleanup.mjs +13 -0
- package/templates/react-nest-shadcn/scripts/design-verify.mjs +154 -0
- package/templates/react-nest-shadcn/scripts/design.mjs +108 -0
- package/templates/react-nest-shadcn/scripts/project.mjs +120 -0
- package/templates/react-nest-shadcn/tests/contract-client.ts +20 -0
- package/templates/react-nest-shadcn/tests/contract.spec.ts +49 -0
- package/templates/react-nest-shadcn/tests/design/harness.tsx +63 -0
- package/templates/react-nest-shadcn/tests/ui.spec.ts +61 -0
- package/templates/react-nest-shadcn/web/eslint.config.mjs +3 -0
- package/templates/react-nest-shadcn/web/index.html +1 -0
- package/templates/react-nest-shadcn/web/package.json +33 -0
- package/templates/react-nest-shadcn/web/pnpm-lock.yaml +1788 -0
- package/templates/react-nest-shadcn/web/src/App.tsx +30 -0
- package/templates/react-nest-shadcn/web/src/design-layout.css +7 -0
- package/templates/react-nest-shadcn/web/src/design-runtime.json +511 -0
- package/templates/react-nest-shadcn/web/src/design-tokens.css +168 -0
- package/templates/react-nest-shadcn/web/src/design-widgets.css +31 -0
- package/templates/react-nest-shadcn/web/src/main.tsx +6 -0
- package/templates/react-nest-shadcn/web/src/structure-view.tsx +16 -0
- package/templates/react-nest-shadcn/web/src/styles.css +3 -0
- package/templates/react-nest-shadcn/web/src/tailwind.css +2 -0
- package/templates/react-nest-shadcn/web/src/ui.tsx +13 -0
- package/templates/react-nest-shadcn/web/src/widget-icon.tsx +5 -0
- package/templates/react-nest-shadcn/web/src/widget-types.ts +13 -0
- package/templates/react-nest-shadcn/web/src/workspace-model.ts +85 -0
- package/templates/react-nest-shadcn/web/tsconfig.json +22 -0
- package/templates/react-nest-shadcn/web/vite.config.ts +4 -0
- package/templates/react-spring-antd/.agents/skills/design-contract/SKILL.md +23 -0
- package/templates/react-spring-antd/.agents/skills/project-work/SKILL.md +10 -0
- package/templates/react-spring-antd/.claude/skills/design-contract/SKILL.md +23 -0
- package/templates/react-spring-antd/.claude/skills/project-work/SKILL.md +10 -0
- package/templates/react-spring-antd/.dockerignore +18 -0
- package/templates/react-spring-antd/.env.example +13 -0
- package/templates/react-spring-antd/.grok/skills/design-contract/SKILL.md +23 -0
- package/templates/react-spring-antd/.grok/skills/project-work/SKILL.md +10 -0
- package/templates/react-spring-antd/.scaffold-checks.json +7 -0
- package/templates/react-spring-antd/AGENTS.md +11 -0
- package/templates/react-spring-antd/CLAUDE.md +1 -0
- package/templates/react-spring-antd/DESIGN.md +208 -0
- package/templates/react-spring-antd/LICENSE +21 -0
- package/templates/react-spring-antd/README.md +64 -0
- package/templates/react-spring-antd/THIRD_PARTY_NOTICES.md +18 -0
- package/templates/react-spring-antd/backend/.mvn/wrapper/maven-wrapper.properties +3 -0
- package/templates/react-spring-antd/backend/Dockerfile +11 -0
- package/templates/react-spring-antd/backend/mvnw +295 -0
- package/templates/react-spring-antd/backend/pom.xml +15 -0
- package/templates/react-spring-antd/backend/src/main/java/dev/scaffold/app/Api.java +38 -0
- package/templates/react-spring-antd/backend/src/main/java/dev/scaffold/app/AppUser.java +11 -0
- package/templates/react-spring-antd/backend/src/main/java/dev/scaffold/app/Application.java +7 -0
- package/templates/react-spring-antd/backend/src/main/java/dev/scaffold/app/Errors.java +13 -0
- package/templates/react-spring-antd/backend/src/main/java/dev/scaffold/app/PersonalRecord.java +15 -0
- package/templates/react-spring-antd/backend/src/main/java/dev/scaffold/app/Records.java +14 -0
- package/templates/react-spring-antd/backend/src/main/java/dev/scaffold/app/Security.java +28 -0
- package/templates/react-spring-antd/backend/src/main/java/dev/scaffold/app/Seed.java +13 -0
- package/templates/react-spring-antd/backend/src/main/java/dev/scaffold/app/Users.java +5 -0
- package/templates/react-spring-antd/backend/src/main/resources/application.properties +17 -0
- package/templates/react-spring-antd/backend/src/main/resources/db/migration/V1__initial.sql +3 -0
- package/templates/react-spring-antd/backend/src/main/resources/openapi.json +461 -0
- package/templates/react-spring-antd/backend/src/test/java/dev/scaffold/app/ApiTest.java +28 -0
- package/templates/react-spring-antd/backend/src/test/java/dev/scaffold/app/SessionExpiryTest.java +37 -0
- package/templates/react-spring-antd/compose.yaml +18 -0
- package/templates/react-spring-antd/design/guide.md +61 -0
- package/templates/react-spring-antd/design/layout.css +6 -0
- package/templates/react-spring-antd/design/structure.json +107 -0
- package/templates/react-spring-antd/design/tokens.json +171 -0
- package/templates/react-spring-antd/design/widgets.css +30 -0
- package/templates/react-spring-antd/design/widgets.json +233 -0
- package/templates/react-spring-antd/docs/PROJECT.md +32 -0
- package/templates/react-spring-antd/docs/api.d.ts +544 -0
- package/templates/react-spring-antd/docs/openapi.json +461 -0
- package/templates/react-spring-antd/gitignore.template +19 -0
- package/templates/react-spring-antd/licenses/fastapi.txt +21 -0
- package/templates/react-spring-antd/licenses/nest.txt +22 -0
- package/templates/react-spring-antd/licenses/next.txt +21 -0
- package/templates/react-spring-antd/licenses/shadcn.txt +21 -0
- package/templates/react-spring-antd/licenses/sources.json +27 -0
- package/templates/react-spring-antd/licenses/spring.txt +202 -0
- package/templates/react-spring-antd/package-lock.json +494 -0
- package/templates/react-spring-antd/package.json +26 -0
- package/templates/react-spring-antd/playwright.config.ts +3 -0
- package/templates/react-spring-antd/project.json +8 -0
- package/templates/react-spring-antd/scripts/api-check.mjs +18 -0
- package/templates/react-spring-antd/scripts/api-contract.mjs +46 -0
- package/templates/react-spring-antd/scripts/design-coverage.mjs +20 -0
- package/templates/react-spring-antd/scripts/design-next-cleanup.mjs +13 -0
- package/templates/react-spring-antd/scripts/design-verify.mjs +154 -0
- package/templates/react-spring-antd/scripts/design.mjs +108 -0
- package/templates/react-spring-antd/scripts/project.mjs +120 -0
- package/templates/react-spring-antd/tests/contract-client.ts +20 -0
- package/templates/react-spring-antd/tests/contract.spec.ts +49 -0
- package/templates/react-spring-antd/tests/design/harness.tsx +63 -0
- package/templates/react-spring-antd/tests/ui.spec.ts +61 -0
- package/templates/react-spring-antd/web/eslint.config.mjs +3 -0
- package/templates/react-spring-antd/web/index.html +1 -0
- package/templates/react-spring-antd/web/package.json +28 -0
- package/templates/react-spring-antd/web/pnpm-lock.yaml +2215 -0
- package/templates/react-spring-antd/web/src/App.tsx +29 -0
- package/templates/react-spring-antd/web/src/design-layout.css +7 -0
- package/templates/react-spring-antd/web/src/design-runtime.json +511 -0
- package/templates/react-spring-antd/web/src/design-tokens.css +168 -0
- package/templates/react-spring-antd/web/src/design-widgets.css +31 -0
- package/templates/react-spring-antd/web/src/main.tsx +6 -0
- package/templates/react-spring-antd/web/src/structure-view.tsx +16 -0
- package/templates/react-spring-antd/web/src/styles.css +3 -0
- package/templates/react-spring-antd/web/src/ui.tsx +30 -0
- package/templates/react-spring-antd/web/src/widget-icon.tsx +5 -0
- package/templates/react-spring-antd/web/src/widget-types.ts +13 -0
- package/templates/react-spring-antd/web/src/workspace-model.ts +85 -0
- package/templates/react-spring-antd/web/tsconfig.json +22 -0
- package/templates/react-spring-antd/web/vite.config.ts +3 -0
- package/templates/react-spring-shadcn/.agents/skills/design-contract/SKILL.md +23 -0
- package/templates/react-spring-shadcn/.agents/skills/project-work/SKILL.md +10 -0
- package/templates/react-spring-shadcn/.claude/skills/design-contract/SKILL.md +23 -0
- package/templates/react-spring-shadcn/.claude/skills/project-work/SKILL.md +10 -0
- package/templates/react-spring-shadcn/.dockerignore +18 -0
- package/templates/react-spring-shadcn/.env.example +13 -0
- package/templates/react-spring-shadcn/.grok/skills/design-contract/SKILL.md +23 -0
- package/templates/react-spring-shadcn/.grok/skills/project-work/SKILL.md +10 -0
- package/templates/react-spring-shadcn/.scaffold-checks.json +7 -0
- package/templates/react-spring-shadcn/AGENTS.md +11 -0
- package/templates/react-spring-shadcn/CLAUDE.md +1 -0
- package/templates/react-spring-shadcn/DESIGN.md +208 -0
- package/templates/react-spring-shadcn/LICENSE +21 -0
- package/templates/react-spring-shadcn/README.md +64 -0
- package/templates/react-spring-shadcn/THIRD_PARTY_NOTICES.md +18 -0
- package/templates/react-spring-shadcn/backend/.mvn/wrapper/maven-wrapper.properties +3 -0
- package/templates/react-spring-shadcn/backend/Dockerfile +11 -0
- package/templates/react-spring-shadcn/backend/mvnw +295 -0
- package/templates/react-spring-shadcn/backend/pom.xml +15 -0
- package/templates/react-spring-shadcn/backend/src/main/java/dev/scaffold/app/Api.java +38 -0
- package/templates/react-spring-shadcn/backend/src/main/java/dev/scaffold/app/AppUser.java +11 -0
- package/templates/react-spring-shadcn/backend/src/main/java/dev/scaffold/app/Application.java +7 -0
- package/templates/react-spring-shadcn/backend/src/main/java/dev/scaffold/app/Errors.java +13 -0
- package/templates/react-spring-shadcn/backend/src/main/java/dev/scaffold/app/PersonalRecord.java +15 -0
- package/templates/react-spring-shadcn/backend/src/main/java/dev/scaffold/app/Records.java +14 -0
- package/templates/react-spring-shadcn/backend/src/main/java/dev/scaffold/app/Security.java +28 -0
- package/templates/react-spring-shadcn/backend/src/main/java/dev/scaffold/app/Seed.java +13 -0
- package/templates/react-spring-shadcn/backend/src/main/java/dev/scaffold/app/Users.java +5 -0
- package/templates/react-spring-shadcn/backend/src/main/resources/application.properties +17 -0
- package/templates/react-spring-shadcn/backend/src/main/resources/db/migration/V1__initial.sql +3 -0
- package/templates/react-spring-shadcn/backend/src/main/resources/openapi.json +461 -0
- package/templates/react-spring-shadcn/backend/src/test/java/dev/scaffold/app/ApiTest.java +28 -0
- package/templates/react-spring-shadcn/backend/src/test/java/dev/scaffold/app/SessionExpiryTest.java +37 -0
- package/templates/react-spring-shadcn/compose.yaml +18 -0
- package/templates/react-spring-shadcn/design/guide.md +61 -0
- package/templates/react-spring-shadcn/design/layout.css +6 -0
- package/templates/react-spring-shadcn/design/structure.json +107 -0
- package/templates/react-spring-shadcn/design/tokens.json +171 -0
- package/templates/react-spring-shadcn/design/widgets.css +30 -0
- package/templates/react-spring-shadcn/design/widgets.json +233 -0
- package/templates/react-spring-shadcn/docs/PROJECT.md +32 -0
- package/templates/react-spring-shadcn/docs/api.d.ts +544 -0
- package/templates/react-spring-shadcn/docs/openapi.json +461 -0
- package/templates/react-spring-shadcn/gitignore.template +19 -0
- package/templates/react-spring-shadcn/licenses/fastapi.txt +21 -0
- package/templates/react-spring-shadcn/licenses/nest.txt +22 -0
- package/templates/react-spring-shadcn/licenses/next.txt +21 -0
- package/templates/react-spring-shadcn/licenses/shadcn.txt +21 -0
- package/templates/react-spring-shadcn/licenses/sources.json +27 -0
- package/templates/react-spring-shadcn/licenses/spring.txt +202 -0
- package/templates/react-spring-shadcn/package-lock.json +494 -0
- package/templates/react-spring-shadcn/package.json +26 -0
- package/templates/react-spring-shadcn/playwright.config.ts +3 -0
- package/templates/react-spring-shadcn/project.json +8 -0
- package/templates/react-spring-shadcn/scripts/api-check.mjs +18 -0
- package/templates/react-spring-shadcn/scripts/api-contract.mjs +46 -0
- package/templates/react-spring-shadcn/scripts/design-coverage.mjs +20 -0
- package/templates/react-spring-shadcn/scripts/design-next-cleanup.mjs +13 -0
- package/templates/react-spring-shadcn/scripts/design-verify.mjs +154 -0
- package/templates/react-spring-shadcn/scripts/design.mjs +108 -0
- package/templates/react-spring-shadcn/scripts/project.mjs +120 -0
- package/templates/react-spring-shadcn/tests/contract-client.ts +20 -0
- package/templates/react-spring-shadcn/tests/contract.spec.ts +49 -0
- package/templates/react-spring-shadcn/tests/design/harness.tsx +63 -0
- package/templates/react-spring-shadcn/tests/ui.spec.ts +61 -0
- package/templates/react-spring-shadcn/web/eslint.config.mjs +3 -0
- package/templates/react-spring-shadcn/web/index.html +1 -0
- package/templates/react-spring-shadcn/web/package.json +33 -0
- package/templates/react-spring-shadcn/web/pnpm-lock.yaml +1788 -0
- package/templates/react-spring-shadcn/web/src/App.tsx +30 -0
- package/templates/react-spring-shadcn/web/src/design-layout.css +7 -0
- package/templates/react-spring-shadcn/web/src/design-runtime.json +511 -0
- package/templates/react-spring-shadcn/web/src/design-tokens.css +168 -0
- package/templates/react-spring-shadcn/web/src/design-widgets.css +31 -0
- package/templates/react-spring-shadcn/web/src/main.tsx +6 -0
- package/templates/react-spring-shadcn/web/src/structure-view.tsx +16 -0
- package/templates/react-spring-shadcn/web/src/styles.css +3 -0
- package/templates/react-spring-shadcn/web/src/tailwind.css +2 -0
- package/templates/react-spring-shadcn/web/src/ui.tsx +13 -0
- package/templates/react-spring-shadcn/web/src/widget-icon.tsx +5 -0
- package/templates/react-spring-shadcn/web/src/widget-types.ts +13 -0
- package/templates/react-spring-shadcn/web/src/workspace-model.ts +85 -0
- package/templates/react-spring-shadcn/web/tsconfig.json +22 -0
- package/templates/react-spring-shadcn/web/vite.config.ts +4 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: "alpha"
|
|
3
|
+
name: "Scientific Workspace"
|
|
4
|
+
description: "从 CleerScience 提炼的通用深色科技视觉,适配可读、安静的工具型界面。"
|
|
5
|
+
colors:
|
|
6
|
+
primary: "#8fc3ff"
|
|
7
|
+
primary-hover: "#b5d8ff"
|
|
8
|
+
primary-active: "#69a9f3"
|
|
9
|
+
primary-text: "#02040a"
|
|
10
|
+
background: "#02040a"
|
|
11
|
+
text: "#f4f8ff"
|
|
12
|
+
surface: "#0b111d"
|
|
13
|
+
focus: "#8fc3ff"
|
|
14
|
+
border: "#283547"
|
|
15
|
+
brand: "#f4f8ff"
|
|
16
|
+
eyebrow: "#9baecb"
|
|
17
|
+
muted: "#a1afc3"
|
|
18
|
+
intro: "#b5c3d7"
|
|
19
|
+
panel-border: "#283547"
|
|
20
|
+
divider: "#202c3e"
|
|
21
|
+
record-text: "#f4f8ff"
|
|
22
|
+
record-meta: "#a1afc3"
|
|
23
|
+
record-hover: "#142237"
|
|
24
|
+
pagination-border: "#283547"
|
|
25
|
+
empty: "#a1afc3"
|
|
26
|
+
empty-heading: "#e2eeff"
|
|
27
|
+
success-background: "#102b25"
|
|
28
|
+
success-border: "#387c69"
|
|
29
|
+
success-text: "#a2e6cc"
|
|
30
|
+
error-background: "#311b24"
|
|
31
|
+
error-border: "#8f4c61"
|
|
32
|
+
error-text: "#ffbdcd"
|
|
33
|
+
footer-border: "#283547"
|
|
34
|
+
footer-text: "#a1afc3"
|
|
35
|
+
badge-border: "#435773"
|
|
36
|
+
badge-text: "#b5c3d7"
|
|
37
|
+
control-focus: "#8fc3ff"
|
|
38
|
+
control-border: "#657891"
|
|
39
|
+
control-background: "#080e18"
|
|
40
|
+
secondary-border: "#657891"
|
|
41
|
+
secondary-text: "#e2eeff"
|
|
42
|
+
secondary-hover: "#19283d"
|
|
43
|
+
danger-border: "#ad6578"
|
|
44
|
+
danger-background: "#311b24"
|
|
45
|
+
danger-text: "#ffbdcd"
|
|
46
|
+
danger-hover: "#472636"
|
|
47
|
+
typography:
|
|
48
|
+
body:
|
|
49
|
+
fontFamily: "Inter,ui-sans-serif,-apple-system,BlinkMacSystemFont,\"Segoe UI\",\"PingFang SC\",\"Hiragino Sans GB\",\"Microsoft YaHei\",sans-serif"
|
|
50
|
+
fontSize: "16px"
|
|
51
|
+
lineHeight: 1.65
|
|
52
|
+
h1:
|
|
53
|
+
fontSize: "36px"
|
|
54
|
+
lineHeight: 1.2
|
|
55
|
+
letterSpacing: "-0.03em"
|
|
56
|
+
fontWeight: 560
|
|
57
|
+
login-heading:
|
|
58
|
+
fontSize: "48px"
|
|
59
|
+
lineHeight: 1.15
|
|
60
|
+
fontWeight: 560
|
|
61
|
+
letterSpacing: "-0.03em"
|
|
62
|
+
h2:
|
|
63
|
+
fontSize: "20px"
|
|
64
|
+
lineHeight: 1.4
|
|
65
|
+
fontWeight: 580
|
|
66
|
+
letterSpacing: "-0.02em"
|
|
67
|
+
h3:
|
|
68
|
+
fontSize: "18px"
|
|
69
|
+
fontWeight: 600
|
|
70
|
+
lineHeight: 1.5
|
|
71
|
+
label:
|
|
72
|
+
fontSize: "14px"
|
|
73
|
+
fontWeight: 600
|
|
74
|
+
eyebrow:
|
|
75
|
+
fontSize: "11px"
|
|
76
|
+
fontWeight: 700
|
|
77
|
+
letterSpacing: "0.22em"
|
|
78
|
+
lineHeight: 1.5
|
|
79
|
+
button:
|
|
80
|
+
fontSize: "14px"
|
|
81
|
+
fontWeight: 600
|
|
82
|
+
lineHeight: "20px"
|
|
83
|
+
caption:
|
|
84
|
+
fontSize: "12px"
|
|
85
|
+
intro:
|
|
86
|
+
fontSize: "18px"
|
|
87
|
+
lineHeight: 1.8
|
|
88
|
+
mobile-heading:
|
|
89
|
+
fontSize: "32px"
|
|
90
|
+
lineHeight: 1.2
|
|
91
|
+
mobile-page-heading:
|
|
92
|
+
fontSize: "28px"
|
|
93
|
+
lineHeight: 1.25
|
|
94
|
+
rounded:
|
|
95
|
+
md: "0px"
|
|
96
|
+
panel: "0px"
|
|
97
|
+
full: "0px"
|
|
98
|
+
spacing:
|
|
99
|
+
s0: "0px"
|
|
100
|
+
s1: "1px"
|
|
101
|
+
s2: "2px"
|
|
102
|
+
s3: "3px"
|
|
103
|
+
s4: "4px"
|
|
104
|
+
s6: "6px"
|
|
105
|
+
s8: "8px"
|
|
106
|
+
s10: "10px"
|
|
107
|
+
s12: "12px"
|
|
108
|
+
s14: "14px"
|
|
109
|
+
s15: "15px"
|
|
110
|
+
s16: "16px"
|
|
111
|
+
s18: "18px"
|
|
112
|
+
s20: "20px"
|
|
113
|
+
s22: "22px"
|
|
114
|
+
s24: "24px"
|
|
115
|
+
s26: "26px"
|
|
116
|
+
s28: "28px"
|
|
117
|
+
s30: "30px"
|
|
118
|
+
s32: "32px"
|
|
119
|
+
s34: "34px"
|
|
120
|
+
s38: "38px"
|
|
121
|
+
s44: "44px"
|
|
122
|
+
s48: "48px"
|
|
123
|
+
s60: "60px"
|
|
124
|
+
s80: "80px"
|
|
125
|
+
s88: "88px"
|
|
126
|
+
shell-max: "1240px"
|
|
127
|
+
login-max: "1020px"
|
|
128
|
+
intro-max: "460px"
|
|
129
|
+
login-card-max: "430px"
|
|
130
|
+
list-min: "260px"
|
|
131
|
+
footer-reserve: "155px"
|
|
132
|
+
mobile-breakpoint: "760px"
|
|
133
|
+
control-min: "44px"
|
|
134
|
+
components:
|
|
135
|
+
button-primary:
|
|
136
|
+
backgroundColor: "{colors.primary}"
|
|
137
|
+
textColor: "{colors.primary-text}"
|
|
138
|
+
rounded: "{rounded.md}"
|
|
139
|
+
height: "{spacing.control-min}"
|
|
140
|
+
panel:
|
|
141
|
+
backgroundColor: "{colors.surface}"
|
|
142
|
+
padding: "{spacing.s26}"
|
|
143
|
+
rounded: "{rounded.panel}"
|
|
144
|
+
input:
|
|
145
|
+
rounded: "{rounded.md}"
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Overview
|
|
149
|
+
|
|
150
|
+
**Scientific Workspace**:从 [CleerScience 官网](https://cleerscience.com/) 提炼的通用深色科技视觉。以近黑蓝底、冷白文字、冰蓝重点、直角薄边框和清晰排版传达秩序;各组件库使用同一份视觉、控件和结构规格。它服务于登录、列表与编辑任务,不把科学品牌、产品名或营销文案带入生成项目。
|
|
151
|
+
|
|
152
|
+
来源于 2026-10-20 对官网桌面 1440px 和手机 375px 的实际页面及计算样式观察。官网原值包括背景 #02040a、正文 #f4f8ff、冰蓝 #8fc3ff、0px 面板圆角;本模板沿用这些核心值。正文与控件对比度、实体表面、较小标题和 44px 以上操作尺寸是工具型界面的适配决定,并非官网原样复刻。背景视频、品牌标识、全屏叙事和科学插图不属于本模板。
|
|
153
|
+
|
|
154
|
+
**唯一编辑源**:`design/tokens.json`、`design/widgets.json`、`design/structure.json`、`design/guide.md` 及中立布局/控件样式。执行 `npm run design:sync` 生成本文件、design-tokens.css、design-layout.css、design-widgets.css、design-runtime.json,再执行 `npm run design:check`。不要直接修改派生产物;build/typecheck/lint 会拒绝漂移。YAML 是与组件库无关的有效 token;阴影等非标准字段在正文给出,避免伪装成官方 schema 字段。
|
|
155
|
+
|
|
156
|
+
## Colors
|
|
157
|
+
|
|
158
|
+
背景使用 `colors.background`,面板使用 `colors.surface`,输入区使用 `colors.control-background`。正文使用 `colors.text`,辅助说明使用 `colors.muted`,标题不降低透明度。不要把官网用于装饰的低透明度文字直接用于表单标签或必要说明。
|
|
159
|
+
|
|
160
|
+
`primary` 仅用于主要操作、当前选中项和可见焦点;按钮文字使用 `primary-text`,确保亮色按钮上的深色字可读。`primary-hover` / `primary-active` 表达交互状态。普通表面保持中性冷色,避免整页泛蓝或大面积发光。错误和成功使用各自的 background/border/text 组合,同时保留明确文字或状态角色。
|
|
161
|
+
|
|
162
|
+
必要文字对比度至少 4.5:1,焦点与操作控件边界至少 3:1;装饰分隔线可以更弱。对比度必须按实际背景检查,不能只比较两个透明 token。新项目若改变主色,需重新验证文字、hover、active 和焦点,不仅替换一个十六进制值。
|
|
163
|
+
|
|
164
|
+
## Typography
|
|
165
|
+
|
|
166
|
+
一套无衬线字体贯穿全站:Inter 可用时优先,否则落到系统字体与 PingFang SC / Microsoft YaHei;不主动下载字体。中文正文 16px、行高 1.65,标签 14px,辅助信息 12px;避免将官网 11px 导航字直接当作表单正文。
|
|
167
|
+
|
|
168
|
+
页面标题 36px、登录标题 48px,手机分别 28px/32px;h2 为 20px,h3 为 18px。标题使用 560–600 字重与轻微负字距,中文不采用官网展示标题的 -0.075em 压缩。`eyebrow` 用 11px、700 字重、0.22em 字距作短标签,不承载唯一操作说明。标题平衡换行,说明文字自然换行,长记录标题允许断行,账号单行省略。
|
|
169
|
+
|
|
170
|
+
具体字号、字重与行高以 typography 为准。所有套件严格使用同一按钮字号 14px 与行高 20px;不要混用第二套展示字体。
|
|
171
|
+
|
|
172
|
+
## Layout
|
|
173
|
+
|
|
174
|
+
沿用工作空间的信息结构:顶栏、页面标题、记录列表与编辑区。桌面 shell-max 为 1240px,水平边距 32px;记录区两栏,登录页说明与表单两栏。面板间距 24px,桌面面板内边距 26px。避免为了科技感给每一行再套卡片。
|
|
175
|
+
|
|
176
|
+
在 `spacing.mobile-breakpoint`(当前 760px)收为单列,水平边距 18px、面板内边距 20px。375px 不允许横向溢出;操作区允许自然增长,不用全屏固定高度压缩内容。布局 CSS 与媒体查询由同一 token 源生成。
|
|
177
|
+
|
|
178
|
+
官网的超大留白、全屏分区与宽幅媒体可用于品牌落地页,但不是登录和 CRUD 页面默认规则。新增导航、统计卡或营销分区需要业务需求,不能由设计规范自行扩张功能。
|
|
179
|
+
|
|
180
|
+
## Elevation & Depth
|
|
181
|
+
|
|
182
|
+
面板首先依靠深浅表面和 1px 冷色边框分层;阴影为 `0 16px 48px rgba(0,0,0,0.18)`,来自 design/tokens.json 的 effects.panelShadow。控件边框比装饰分隔线更清晰。选中记录增加冰蓝侧线与背景变化,不只靠文字颜色。
|
|
183
|
+
|
|
184
|
+
官网玻璃面板的 blur(14px) 和影像叠层可作为品牌页面参考;本工具使用实体表面保证阅读和性能,不全局加 backdrop-filter。禁止给每个按钮、输入框加辉光或重阴影。
|
|
185
|
+
|
|
186
|
+
## Shapes
|
|
187
|
+
|
|
188
|
+
`rounded.md` 为 0px、`rounded.panel` 为 0px、`rounded.full` 为 0px:按钮、输入、面板和标签保持精确直角。`full` 是沿用的 token 名,在当前主题不代表胶囊。修改形状时同步组件 token;所有尺寸的圆角由套件显式绑定,避免库派生出另一种圆角。
|
|
189
|
+
|
|
190
|
+
边框厚度通常为 1px。图标沿用所选组件库的简洁线性风格,保持光学尺寸一致;不复制官网 Logo 或专有插图。
|
|
191
|
+
|
|
192
|
+
## Components
|
|
193
|
+
|
|
194
|
+
主按钮:冰蓝填充、深色文字;secondary:深色表面与清晰描边;danger:暗红表面与浅红文字。按钮与单行输入高度 44px,保持键盘焦点。default/hover/active/focus/disabled/loading 与输入错误态由 design/widgets.json 定义,套件逐项翻译,不接受原生默认值偏差。颜色派生结果以共享 token 为准;图标使用同一份 SVG 几何,套件不得替换成近似图标。
|
|
195
|
+
|
|
196
|
+
输入:深色底、冷白输入文字、可读 placeholder,标签始终可见。加载时禁用重复提交;错误后保留输入;空态说明下一步;记录正文以纯文本显示。删除需确认,退出清除当前编辑内容。控件自身焦点、输入和禁用状态由原生控件/套件管理;登录身份、校验、记录状态与请求隔离只在框架无关的 workspace-model 中实现。页面区块顺序和嵌套来自 design/structure.json,框架视图负责绑定。上述行为由业务实现与 Playwright 测试负责,设计文件不替代执行逻辑。
|
|
197
|
+
|
|
198
|
+
动效只用于短暂状态反馈;遵循 150–250ms 的颜色/边框变化,不新增背景循环、滚动接管或入场延迟。`prefers-reduced-motion: reduce` 下取消非必要动画与过渡。品牌页面如果采用背景媒体,需静态后备、降低亮度、保障文字对比度,并单独验收性能。
|
|
199
|
+
|
|
200
|
+
## Do's and Don'ts
|
|
201
|
+
|
|
202
|
+
- UI 开发前读本文件;设计修改先改源,再 sync/check,最后看浏览器真实结果。
|
|
203
|
+
- 复用冷色中性层级、单一字体、直角薄边框与有限强调色;保持所选 UI 库的一致性。
|
|
204
|
+
- 验证默认、hover、active、focus、disabled、loading、empty、error,以及键盘与 375px 布局。
|
|
205
|
+
- 不将来源网站的行业、品牌内容、低对比装饰字或全屏动效当成通用业务要求。
|
|
206
|
+
- 不给每个面板加玻璃、光晕或渐变;库默认值与规格不符时修改套件,不反向修改规范。
|
|
207
|
+
- 全量执行控件/页面比较:位置容差 ≤0.6 CSS px;颜色、圆角、图标几何零容差;必须覆盖 widgets.json 和 structure.json 的全部声明项。
|
|
208
|
+
- 不直接编辑生成文件,不把文档格式通过当成浏览器验收通过,不根据项目简介随机改变视觉。
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 qinchaomeishenmeshi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
## 运行
|
|
2
|
+
|
|
3
|
+
需要 Node.js 24、Docker 和该模板的运行时(见 project.json 与下方说明)。
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm run setup
|
|
7
|
+
npm run dev
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
`setup` 安装依赖,然后显式启动本地 PostgreSQL、迁移并创建 A/B 开发账号。首次生成随机密码,登录信息在 Git 忽略的 `.scaffold-local-credentials`;不是生产默认密码。已有 `.env` 时保留配置,请仅使用本地开发实例。
|
|
11
|
+
|
|
12
|
+
默认数据库端口为 54329、API 为 8000、Web 为 5173(Next 为 3000)。首次 setup 可用 `POSTGRES_PORT`、`PORT`、`WEB_PORT` 环境变量指定空闲端口;后续沿用 `.env`。
|
|
13
|
+
|
|
14
|
+
页面名称与简介来自根 project.json;英文名用于目录和工程标识。基础示例只包含个人记录功能,不因简介自动新增业务。
|
|
15
|
+
|
|
16
|
+
## 验证
|
|
17
|
+
|
|
18
|
+
安装前可只检查工具;doctor 不会安装依赖或启动服务:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npx @cherishxn/agent-scaffold@__CLI_VERSION__ doctor --dir . --tools-only --json
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
安装依赖后,先做快速检查,再按需要验证完整业务:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm run check
|
|
28
|
+
npx @cherishxn/agent-scaffold@__CLI_VERSION__ doctor --dir . --json
|
|
29
|
+
npx @cherishxn/agent-scaffold@__CLI_VERSION__ verify --dir . --profile baseline --json
|
|
30
|
+
npx @cherishxn/agent-scaffold@__CLI_VERSION__ report --dir . --json
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`check` 顺序执行类型、Lint、构建,任一步失败即停止;它不创建数据库、不执行迁移或业务测试。
|
|
34
|
+
|
|
35
|
+
verify 创建自己的临时 PostgreSQL 并注入连接,不使用开发 DATABASE_URL;完成后释放本次容器。单独运行项目命令时需要显式提供本地环境:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
node scripts/project.mjs typecheck
|
|
39
|
+
node scripts/project.mjs lint
|
|
40
|
+
node scripts/project.mjs build
|
|
41
|
+
node scripts/project.mjs test:native
|
|
42
|
+
node scripts/project.mjs test:api
|
|
43
|
+
node scripts/project.mjs test:e2e
|
|
44
|
+
node scripts/project.mjs api:generate
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
接口:docs/openapi.json;结构:docs/PROJECT.md;规则:AGENTS.md。修改契约后运行 npm run api:generate 更新 TypeScript 类型。npm run api:check 在临时目录重新生成并只读比较,check/verify 自动执行;test:api 同时按 OpenAPI 检查真实响应状态、必填字段和类型。验证不会自动修改源码。
|
|
48
|
+
|
|
49
|
+
## 认证边界
|
|
50
|
+
|
|
51
|
+
JWT 模板只在浏览器内存保存 Token,页面刷新需重新登录;退出清除内存,不声称服务器撤销旧 JWT。Session 模板使用 HttpOnly Cookie 和同源写入校验,退出后 Session 失效。所有记录访问由服务端按当前用户过滤。
|
|
52
|
+
|
|
53
|
+
## 容器构建
|
|
54
|
+
|
|
55
|
+
按模板提供的 Dockerfile 构建,配置自己的数据库和秘密;构建与本地验证不代表生产部署或业务验收通过。不要把 `.env`、凭据文件或运行报告加入镜像/版本库。
|
|
56
|
+
|
|
57
|
+
## 视觉设计
|
|
58
|
+
|
|
59
|
+
UI 开发前读根目录 DESIGN.md 和内置 design-contract Skill。`design/tokens.json`、`widgets.json`、`structure.json` 与公共 CSS 是组件库无关的设计源;`web/src/ui.tsx` 是所选组件库适配器;`workspace-model.ts` 管理业务。修改源后执行 `npm run design:sync`,再运行只读漂移检查 `npm run design:check` 和浏览器契约检查 `npm run design:verify`。后者临时创建测试入口,验证全部声明的组件状态及页面(桌面/移动端),输出 `reports/design-check/result.json`,结束后清理入口。需要已安装依赖及 Playwright Chromium。build/typecheck/lint 同样检查漂移。当前项目的 PASS 仅证明已选适配器;新增库须保持共享规范和业务不变,添加适配器、依赖及框架绑定,并在脚手架完整矩阵中复验。
|
|
60
|
+
|
|
61
|
+
## 本模板
|
|
62
|
+
|
|
63
|
+
技术栈:react-fastapi;UI:shadcn。需要 Python 3.12 + uv、Bun(前端)。
|
|
64
|
+
后端镜像:docker build backend;前端构建产物位于 web/dist,生产需要同源反向代理 /api 到后端。
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Template sources and licenses
|
|
2
|
+
|
|
3
|
+
Templates are maintained derivatives, not unmodified upstream distributions. Exact bundled files are hashed in templates/catalog.json; npm/uv/pnpm/Bun locks pin dependency resolution. Initialization is offline and never invokes upstream generators.
|
|
4
|
+
|
|
5
|
+
| Source | Fixed reference | Use / modifications | License |
|
|
6
|
+
| --- | --- | --- | --- |
|
|
7
|
+
| fastapi/full-stack-fastapi-template | b1125d8839482cb7bbae603ddc6d0081bf87532e | SQLModel/Alembic/JWT/pwdlib foundation; reduced accounts, replaced sample feature with owner-scoped records, retained Bun frontend | MIT, licenses/fastapi.txt |
|
|
8
|
+
| nestjs/typescript-starter | a122dea65cd0610ee205d7765ed46f9d73629141 | Nest module/bootstrap foundation; added Prisma, JWT/Guard, Jest/Supertest; no deployment tooling | MIT, licenses/nest.txt |
|
|
9
|
+
| Spring Initializr | starter.zip fetched 2026-10-19; Maven Wrapper and Java layout | Generator returned unresolved 4.1.1.RELEASE; parent adjusted to stable Maven Central 3.5.16, Session/JPA/Flyway/CRUD added | Apache-2.0 wrapper, licenses/spring.txt |
|
|
10
|
+
| create-next-app | npm 16.4.2 | Official App Router/TypeScript baseline; Better Auth + Prisma + records; no remote fonts | MIT, licenses/next.txt |
|
|
11
|
+
| shadcn/ui | Button/Input pattern, pinned source reference in licenses/sources.json | Adapted local CVA/Slot controls with Tailwind; retained copy ownership | MIT, licenses/shadcn.txt |
|
|
12
|
+
| Ant Design | npm 6.6.6 | Installed dependency; no copied source | MIT (package license) |
|
|
13
|
+
|
|
14
|
+
Package dependencies carry their own licenses. Generated apps include these notices; template authors must carry applicable notices when changing upstream-derived files. Names and marks remain their respective owners'.
|
|
15
|
+
|
|
16
|
+
## Design and workflow reference
|
|
17
|
+
|
|
18
|
+
VinkyDev/vibestart at commit `5768fc561340422bf7736499fe69b1aae263790a` (MIT) informed the preview, task-oriented Agent guidance, quick checks and template-layer collision rules. These changes are independently implemented for Agent Scaffold; no VibeStart source, bundled skills, branding or UI assets are redistributed. The source review and selected adaptations are recorded in docs/reference/VIBESTART-REVIEW.md.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
FROM python:3.12-slim
|
|
2
|
+
COPY --from=ghcr.io/astral-sh/uv:0.13.1 /uv /usr/local/bin/uv
|
|
3
|
+
WORKDIR /app
|
|
4
|
+
COPY pyproject.toml uv.lock ./
|
|
5
|
+
RUN uv sync --frozen --no-dev
|
|
6
|
+
COPY app ./app
|
|
7
|
+
COPY migrations ./migrations
|
|
8
|
+
COPY alembic.ini ./
|
|
9
|
+
EXPOSE 8000
|
|
10
|
+
CMD ["uv", "run", "--frozen", "--no-dev", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Adapted from the pinned FastAPI full-stack template; see THIRD_PARTY_NOTICES.md.
|
|
2
|
+
from datetime import UTC, datetime, timedelta
|
|
3
|
+
import os
|
|
4
|
+
import jwt
|
|
5
|
+
from pwdlib import PasswordHash
|
|
6
|
+
from pwdlib.hashers.argon2 import Argon2Hasher
|
|
7
|
+
from pwdlib.hashers.bcrypt import BcryptHasher
|
|
8
|
+
|
|
9
|
+
password_hash = PasswordHash((Argon2Hasher(), BcryptHasher()))
|
|
10
|
+
ALGORITHM = "HS256"
|
|
11
|
+
SECRET_KEY = os.environ["AUTH_SECRET"]
|
|
12
|
+
if len(SECRET_KEY) < 32:
|
|
13
|
+
raise RuntimeError("AUTH_SECRET must contain at least 32 characters")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def create_access_token(subject: str, expires_delta: timedelta = timedelta(minutes=15)) -> str:
|
|
17
|
+
return jwt.encode({"exp": datetime.now(UTC) + expires_delta, "sub": subject, "aud": "personal-records"}, SECRET_KEY, algorithm=ALGORITHM)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def verify_password(plain_password: str, hashed_password: str) -> bool:
|
|
21
|
+
return password_hash.verify(plain_password, hashed_password)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def get_password_hash(password: str) -> str:
|
|
25
|
+
return password_hash.hash(password)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from collections.abc import Generator
|
|
3
|
+
from sqlmodel import Session, create_engine
|
|
4
|
+
|
|
5
|
+
url = os.environ["DATABASE_URL"].replace("postgresql://", "postgresql+psycopg://", 1)
|
|
6
|
+
engine = create_engine(url, pool_pre_ping=True, echo=False)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def get_session() -> Generator[Session, None, None]:
|
|
10
|
+
with Session(engine) as session:
|
|
11
|
+
yield session
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
from datetime import UTC, datetime
|
|
2
|
+
from typing import Annotated, Any
|
|
3
|
+
from uuid import UUID
|
|
4
|
+
import jwt
|
|
5
|
+
from fastapi import Depends, FastAPI, HTTPException, Query, Request, Response
|
|
6
|
+
from fastapi.exceptions import RequestValidationError
|
|
7
|
+
from fastapi.responses import JSONResponse
|
|
8
|
+
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
|
|
9
|
+
from pydantic import BaseModel, ConfigDict, field_validator
|
|
10
|
+
from sqlalchemy import func
|
|
11
|
+
from sqlmodel import Session, col, select
|
|
12
|
+
from app.core.security import ALGORITHM, SECRET_KEY, create_access_token, verify_password
|
|
13
|
+
from app.db import get_session
|
|
14
|
+
from app.models import PersonalRecord, User
|
|
15
|
+
|
|
16
|
+
app = FastAPI(title="Personal Records", docs_url="/api/docs", openapi_url="/api/openapi.json")
|
|
17
|
+
Db = Annotated[Session, Depends(get_session)]
|
|
18
|
+
bearer = HTTPBearer(auto_error=False)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@app.exception_handler(HTTPException)
|
|
22
|
+
async def http_error(_request: Request, exc: HTTPException) -> JSONResponse:
|
|
23
|
+
messages = {401: "请重新登录。", 404: "记录不存在。", 422: "输入不合法。"}
|
|
24
|
+
return JSONResponse(status_code=exc.status_code, content={"error": {"code": str(exc.status_code), "message": messages.get(exc.status_code, "请求失败。")}})
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@app.exception_handler(RequestValidationError)
|
|
28
|
+
async def validation_error(_request: Request, _exc: RequestValidationError) -> JSONResponse:
|
|
29
|
+
return JSONResponse(status_code=422, content={"error": {"code": "INVALID_INPUT", "message": "输入不合法,请检查字段和长度。"}})
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Login(BaseModel):
|
|
33
|
+
model_config = ConfigDict(extra="forbid")
|
|
34
|
+
email: str
|
|
35
|
+
password: str
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class RecordInput(BaseModel):
|
|
39
|
+
model_config = ConfigDict(extra="forbid", strict=True)
|
|
40
|
+
title: str
|
|
41
|
+
content: str
|
|
42
|
+
|
|
43
|
+
@field_validator("title")
|
|
44
|
+
@classmethod
|
|
45
|
+
def valid_title(cls, value: str) -> str:
|
|
46
|
+
value = value.strip()
|
|
47
|
+
if not 1 <= len(value) <= 120:
|
|
48
|
+
raise ValueError("Invalid title length")
|
|
49
|
+
return value
|
|
50
|
+
|
|
51
|
+
@field_validator("content")
|
|
52
|
+
@classmethod
|
|
53
|
+
def valid_content(cls, value: str) -> str:
|
|
54
|
+
if len(value) > 10000:
|
|
55
|
+
raise ValueError("Invalid content length")
|
|
56
|
+
return value
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def current_user(db: Db, auth: Annotated[HTTPAuthorizationCredentials | None, Depends(bearer)]) -> User:
|
|
60
|
+
try:
|
|
61
|
+
if auth is None:
|
|
62
|
+
raise ValueError("missing")
|
|
63
|
+
claims = jwt.decode(auth.credentials, SECRET_KEY, algorithms=[ALGORITHM], audience="personal-records", options={"require": ["exp", "sub", "aud"]})
|
|
64
|
+
user = db.get(User, UUID(claims["sub"]))
|
|
65
|
+
if user is None:
|
|
66
|
+
raise ValueError("missing")
|
|
67
|
+
return user
|
|
68
|
+
except (jwt.InvalidTokenError, ValueError, KeyError):
|
|
69
|
+
raise HTTPException(401) from None
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
Identity = Annotated[User, Depends(current_user)]
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def public_record(row: PersonalRecord) -> dict[str, Any]:
|
|
76
|
+
return {"id": str(row.id), "title": row.title, "content": row.content, "created_at": row.created_at.isoformat(), "updated_at": row.updated_at.isoformat()}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def owned(db: Session, record_id: UUID, user: User) -> PersonalRecord:
|
|
80
|
+
row = db.exec(select(PersonalRecord).where(PersonalRecord.id == record_id, PersonalRecord.owner_id == user.id)).first()
|
|
81
|
+
if row is None:
|
|
82
|
+
raise HTTPException(404)
|
|
83
|
+
return row
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@app.get("/api/health")
|
|
87
|
+
def health() -> dict[str, str]:
|
|
88
|
+
return {"status": "ok"}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@app.post("/api/auth/login")
|
|
92
|
+
def login(body: Login, db: Db) -> dict[str, Any]:
|
|
93
|
+
user = db.exec(select(User).where(User.email == body.email.strip().lower())).first()
|
|
94
|
+
if user is None or not verify_password(body.password, user.hashed_password):
|
|
95
|
+
raise HTTPException(401)
|
|
96
|
+
return {"user": {"id": str(user.id), "email": user.email}, "token": create_access_token(str(user.id)), "mode": "jwt"}
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@app.get("/api/auth/me")
|
|
100
|
+
def me(user: Identity) -> dict[str, Any]:
|
|
101
|
+
return {"user": {"id": str(user.id), "email": user.email}}
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@app.post("/api/auth/logout", status_code=204)
|
|
105
|
+
def logout(_user: Identity) -> Response:
|
|
106
|
+
return Response(status_code=204)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@app.get("/api/records")
|
|
110
|
+
def records(user: Identity, db: Db, page: Annotated[int, Query(ge=1, le=1000000)] = 1, pageSize: Annotated[int, Query(ge=1, le=100)] = 10) -> dict[str, Any]:
|
|
111
|
+
total = db.exec(select(func.count()).select_from(PersonalRecord).where(PersonalRecord.owner_id == user.id)).one()
|
|
112
|
+
rows = db.exec(select(PersonalRecord).where(PersonalRecord.owner_id == user.id).order_by(col(PersonalRecord.created_at).desc(), col(PersonalRecord.id).desc()).offset((page - 1) * pageSize).limit(pageSize)).all()
|
|
113
|
+
return {"items": [public_record(row) for row in rows], "total": total, "page": page, "pageSize": pageSize}
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
@app.post("/api/records", status_code=201)
|
|
117
|
+
def create(body: RecordInput, user: Identity, db: Db) -> dict[str, Any]:
|
|
118
|
+
row = PersonalRecord(owner_id=user.id, **body.model_dump())
|
|
119
|
+
db.add(row)
|
|
120
|
+
db.commit()
|
|
121
|
+
db.refresh(row)
|
|
122
|
+
return public_record(row)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@app.get("/api/records/{record_id}")
|
|
126
|
+
def detail(record_id: UUID, user: Identity, db: Db) -> dict[str, Any]:
|
|
127
|
+
return public_record(owned(db, record_id, user))
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
@app.put("/api/records/{record_id}")
|
|
131
|
+
def update(record_id: UUID, body: RecordInput, user: Identity, db: Db) -> dict[str, Any]:
|
|
132
|
+
row = owned(db, record_id, user)
|
|
133
|
+
row.title, row.content = body.title, body.content
|
|
134
|
+
row.updated_at = datetime.now(UTC)
|
|
135
|
+
db.add(row)
|
|
136
|
+
db.commit()
|
|
137
|
+
db.refresh(row)
|
|
138
|
+
return public_record(row)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
@app.delete("/api/records/{record_id}", status_code=204)
|
|
142
|
+
def delete(record_id: UUID, user: Identity, db: Db) -> Response:
|
|
143
|
+
row = owned(db, record_id, user)
|
|
144
|
+
db.delete(row)
|
|
145
|
+
db.commit()
|
|
146
|
+
return Response(status_code=204)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from datetime import UTC, datetime
|
|
2
|
+
from uuid import UUID, uuid4
|
|
3
|
+
from sqlmodel import SQLModel, Field
|
|
4
|
+
from sqlalchemy import Column, DateTime, Text
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class User(SQLModel, table=True):
|
|
8
|
+
__tablename__ = "app_user"
|
|
9
|
+
id: UUID = Field(default_factory=uuid4, primary_key=True)
|
|
10
|
+
email: str = Field(unique=True, index=True)
|
|
11
|
+
hashed_password: str
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class PersonalRecord(SQLModel, table=True):
|
|
15
|
+
__tablename__ = "personal_record"
|
|
16
|
+
id: UUID = Field(default_factory=uuid4, primary_key=True)
|
|
17
|
+
owner_id: UUID = Field(foreign_key="app_user.id", index=True)
|
|
18
|
+
title: str
|
|
19
|
+
content: str = Field(sa_column=Column(Text, nullable=False))
|
|
20
|
+
created_at: datetime = Field(default_factory=lambda: datetime.now(UTC), sa_column=Column(DateTime(timezone=True), nullable=False))
|
|
21
|
+
updated_at: datetime = Field(default_factory=lambda: datetime.now(UTC), sa_column=Column(DateTime(timezone=True), nullable=False))
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from sqlmodel import Session, select
|
|
3
|
+
from app.core.security import get_password_hash
|
|
4
|
+
from app.db import engine
|
|
5
|
+
from app.models import User
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def main() -> None:
|
|
9
|
+
password = os.environ["SEED_PASSWORD"]
|
|
10
|
+
if len(password) < 12:
|
|
11
|
+
raise RuntimeError("Development/test seed password must be at least 12 characters")
|
|
12
|
+
with Session(engine) as db:
|
|
13
|
+
for key in ("SEED_A_EMAIL", "SEED_B_EMAIL"):
|
|
14
|
+
email = os.environ[key].strip().lower()
|
|
15
|
+
if not db.exec(select(User).where(User.email == email)).first():
|
|
16
|
+
db.add(User(email=email, hashed_password=get_password_hash(password)))
|
|
17
|
+
db.commit()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
if __name__ == "__main__":
|
|
21
|
+
main()
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
from alembic import context
|
|
2
|
+
from sqlmodel import SQLModel
|
|
3
|
+
from app.db import engine
|
|
4
|
+
from app import models # noqa: F401
|
|
5
|
+
|
|
6
|
+
with engine.connect() as connection:
|
|
7
|
+
context.configure(connection=connection, target_metadata=SQLModel.metadata)
|
|
8
|
+
with context.begin_transaction():
|
|
9
|
+
context.run_migrations()
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from alembic import op
|
|
2
|
+
import sqlalchemy as sa
|
|
3
|
+
revision = "0001"
|
|
4
|
+
down_revision = None
|
|
5
|
+
branch_labels = None
|
|
6
|
+
depends_on = None
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def upgrade():
|
|
10
|
+
op.create_table("app_user", sa.Column("id", sa.Uuid(), primary_key=True), sa.Column("email", sa.String(), nullable=False), sa.Column("hashed_password", sa.String(), nullable=False))
|
|
11
|
+
op.create_index("ix_app_user_email", "app_user", ["email"], unique=True)
|
|
12
|
+
op.create_table("personal_record", sa.Column("id", sa.Uuid(), primary_key=True), sa.Column("owner_id", sa.Uuid(), sa.ForeignKey("app_user.id"), nullable=False), sa.Column("title", sa.String(), nullable=False), sa.Column("content", sa.Text(), nullable=False), sa.Column("created_at", sa.DateTime(timezone=True), nullable=False), sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False))
|
|
13
|
+
op.create_index("ix_personal_record_owner_id", "personal_record", ["owner_id"])
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def downgrade():
|
|
17
|
+
op.drop_table("personal_record")
|
|
18
|
+
op.drop_table("app_user")
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "backend"
|
|
3
|
+
version = "1.0.0"
|
|
4
|
+
requires-python = ">=3.12,<3.13"
|
|
5
|
+
dependencies = ["fastapi[standard]==0.141.1", "sqlmodel==0.0.46", "alembic==1.19.1", "psycopg[binary]==3.3.6", "pyjwt==2.15.0", "pwdlib[argon2,bcrypt]==0.3.1", "pydantic==2.13.5", "httpx==0.28.1"]
|
|
6
|
+
[dependency-groups]
|
|
7
|
+
dev = ["pytest>=8,<10", "mypy>=1.18,<2", "ruff>=0.16,<1"]
|
|
8
|
+
[tool.mypy]
|
|
9
|
+
python_version = "3.12"
|
|
10
|
+
strict = true
|
|
11
|
+
[tool.ruff]
|
|
12
|
+
target-version = "py312"
|
|
13
|
+
[tool.ruff.lint]
|
|
14
|
+
select = ["E4", "E7", "E9", "F"]
|
|
15
|
+
[tool.pytest.ini_options]
|
|
16
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from datetime import timedelta
|
|
3
|
+
from fastapi.testclient import TestClient
|
|
4
|
+
from app.main import app
|
|
5
|
+
from app.core.security import create_access_token
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_identity_persistence_and_ownership():
|
|
9
|
+
with TestClient(app) as c:
|
|
10
|
+
assert c.get("/api/records").status_code == 401
|
|
11
|
+
login = c.post("/api/auth/login", json={"email": os.environ["SEED_A_EMAIL"], "password": os.environ["SEED_PASSWORD"]}).json()
|
|
12
|
+
a = {"Authorization": "Bearer " + login["token"]}
|
|
13
|
+
expired = create_access_token(login["user"]["id"], timedelta(seconds=-10))
|
|
14
|
+
assert c.get("/api/records", headers={"Authorization": "Bearer " + expired}).status_code == 401
|
|
15
|
+
btoken = c.post("/api/auth/login", json={"email": os.environ["SEED_B_EMAIL"], "password": os.environ["SEED_PASSWORD"]}).json()["token"]
|
|
16
|
+
b = {"Authorization": "Bearer " + btoken}
|
|
17
|
+
assert c.post("/api/records", headers=a, json={"title": "x", "content": "", "owner_id": login["user"]["id"]}).status_code == 422
|
|
18
|
+
row = c.post("/api/records", headers=a, json={"title": " native test ", "content": "persisted"}).json()
|
|
19
|
+
path = "/api/records/" + row["id"]
|
|
20
|
+
assert c.get(path, headers=a).json()["content"] == "persisted"
|
|
21
|
+
assert c.get(path, headers=b).status_code == 404
|
|
22
|
+
assert c.put(path, headers=b, json={"title": "x", "content": ""}).status_code == 404
|
|
23
|
+
assert c.delete(path, headers=b).status_code == 404
|
|
24
|
+
assert c.put(path, headers=a, json={"title": "", "content": ""}).status_code == 422
|
|
25
|
+
assert c.get(path, headers=a).json()["title"] == "native test"
|
|
26
|
+
assert c.delete(path, headers=a).status_code == 204
|
|
27
|
+
assert c.get(path, headers=a).status_code == 404
|