asa-standard 2.0.0__tar.gz
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.
- asa_standard-2.0.0/PKG-INFO +112 -0
- asa_standard-2.0.0/README.md +91 -0
- asa_standard-2.0.0/asa/__init__.py +3 -0
- asa_standard-2.0.0/asa/cli/__init__.py +1 -0
- asa_standard-2.0.0/asa/cli/deploy.py +37 -0
- asa_standard-2.0.0/asa/cli/init_cmd.py +341 -0
- asa_standard-2.0.0/asa/cli/install.py +27 -0
- asa_standard-2.0.0/asa/cli/lint.py +35 -0
- asa_standard-2.0.0/asa/cli/main.py +174 -0
- asa_standard-2.0.0/asa/cli/scan.py +33 -0
- asa_standard-2.0.0/asa/cli/slice/__init__.py +1 -0
- asa_standard-2.0.0/asa/cli/slice/analyze.py +48 -0
- asa_standard-2.0.0/asa/cli/slice/build.py +41 -0
- asa_standard-2.0.0/asa/cli/slice/new.py +71 -0
- asa_standard-2.0.0/asa/cli/slice/plan.py +59 -0
- asa_standard-2.0.0/asa/cli/slice/split.py +58 -0
- asa_standard-2.0.0/asa/cli/slice/sync.py +47 -0
- asa_standard-2.0.0/asa/cli/slice/update.py +42 -0
- asa_standard-2.0.0/asa/cli/ui/__init__.py +1 -0
- asa_standard-2.0.0/asa/cli/ui/generate.py +54 -0
- asa_standard-2.0.0/asa/core/__init__.py +1 -0
- asa_standard-2.0.0/asa/core/config.py +64 -0
- asa_standard-2.0.0/asa/core/errors.py +53 -0
- asa_standard-2.0.0/asa/core/fs.py +117 -0
- asa_standard-2.0.0/asa/core/logging.py +58 -0
- asa_standard-2.0.0/asa/core/paths.py +146 -0
- asa_standard-2.0.0/asa/engine_loader.py +54 -0
- asa_standard-2.0.0/asa/modules/__init__.py +1 -0
- asa_standard-2.0.0/asa/modules/admin_basic/manifest.json +37 -0
- asa_standard-2.0.0/asa/modules/admin_basic/migrations/004_user_roles.sql +117 -0
- asa_standard-2.0.0/asa/modules/admin_basic/migrations/005_audit_log.sql +34 -0
- asa_standard-2.0.0/asa/modules/admin_basic/migrations/006_impersonation_sessions.sql +22 -0
- asa_standard-2.0.0/asa/modules/admin_basic/shared/audit.ts +97 -0
- asa_standard-2.0.0/asa/modules/admin_basic/shared/guards.ts +58 -0
- asa_standard-2.0.0/asa/modules/admin_basic/shared/impersonation.ts +165 -0
- asa_standard-2.0.0/asa/modules/admin_basic/shared/permissions.ts +27 -0
- asa_standard-2.0.0/asa/modules/admin_basic/shared/roles.ts +151 -0
- asa_standard-2.0.0/asa/modules/admin_basic/slices/audit_log/handler.ts +34 -0
- asa_standard-2.0.0/asa/modules/admin_basic/slices/audit_log/slice.contract.json +19 -0
- asa_standard-2.0.0/asa/modules/admin_basic/slices/dashboard/handler.ts +51 -0
- asa_standard-2.0.0/asa/modules/admin_basic/slices/dashboard/slice.contract.json +13 -0
- asa_standard-2.0.0/asa/modules/admin_basic/slices/impersonation/handler.ts +61 -0
- asa_standard-2.0.0/asa/modules/admin_basic/slices/impersonation/slice.contract.json +21 -0
- asa_standard-2.0.0/asa/modules/admin_basic/slices/roles/handler.ts +90 -0
- asa_standard-2.0.0/asa/modules/admin_basic/slices/roles/slice.contract.json +21 -0
- asa_standard-2.0.0/asa/modules/admin_basic/slices/users/handler.ts +48 -0
- asa_standard-2.0.0/asa/modules/admin_basic/slices/users/slice.contract.json +15 -0
- asa_standard-2.0.0/asa/modules/auth_basic/__init__.py +0 -0
- asa_standard-2.0.0/asa/modules/auth_basic/manifest.json +32 -0
- asa_standard-2.0.0/asa/modules/auth_basic/migrations/001_create_profiles.sql +36 -0
- asa_standard-2.0.0/asa/modules/auth_basic/shared/guards.ts +89 -0
- asa_standard-2.0.0/asa/modules/auth_basic/shared/hooks.ts +63 -0
- asa_standard-2.0.0/asa/modules/auth_basic/shared/middleware.ts +46 -0
- asa_standard-2.0.0/asa/modules/auth_basic/shared/server-user.ts +61 -0
- asa_standard-2.0.0/asa/modules/auth_basic/shared/session.ts +38 -0
- asa_standard-2.0.0/asa/modules/auth_basic/shared/types.ts +29 -0
- asa_standard-2.0.0/asa/modules/auth_basic/slices/login/handler.ts +50 -0
- asa_standard-2.0.0/asa/modules/auth_basic/slices/login/repository.ts +23 -0
- asa_standard-2.0.0/asa/modules/auth_basic/slices/login/schemas.ts +22 -0
- asa_standard-2.0.0/asa/modules/auth_basic/slices/login/slice.contract.json +19 -0
- asa_standard-2.0.0/asa/modules/auth_basic/slices/login/ui/AuthLogin.tsx +107 -0
- asa_standard-2.0.0/asa/modules/auth_basic/slices/login/ui/hook.ts +44 -0
- asa_standard-2.0.0/asa/modules/auth_basic/slices/logout/handler.ts +19 -0
- asa_standard-2.0.0/asa/modules/auth_basic/slices/logout/slice.contract.json +16 -0
- asa_standard-2.0.0/asa/modules/auth_basic/slices/register/handler.ts +61 -0
- asa_standard-2.0.0/asa/modules/auth_basic/slices/register/repository.ts +25 -0
- asa_standard-2.0.0/asa/modules/auth_basic/slices/register/schemas.ts +29 -0
- asa_standard-2.0.0/asa/modules/auth_basic/slices/register/slice.contract.json +21 -0
- asa_standard-2.0.0/asa/modules/auth_basic/slices/register/ui/AuthRegister.tsx +118 -0
- asa_standard-2.0.0/asa/modules/auth_basic/slices/register/ui/hook.ts +48 -0
- asa_standard-2.0.0/asa/modules/auth_basic/slices/reset_password/handler.ts +47 -0
- asa_standard-2.0.0/asa/modules/auth_basic/slices/reset_password/schemas.ts +21 -0
- asa_standard-2.0.0/asa/modules/auth_basic/slices/reset_password/slice.contract.json +18 -0
- asa_standard-2.0.0/asa/modules/auth_basic/slices/reset_password/ui/AuthResetPassword.tsx +79 -0
- asa_standard-2.0.0/asa/modules/auth_basic/slices/reset_password/ui/hook.ts +48 -0
- asa_standard-2.0.0/asa/modules/db_basic/__init__.py +0 -0
- asa_standard-2.0.0/asa/modules/db_basic/manifest.json +33 -0
- asa_standard-2.0.0/asa/modules/db_basic/shared/seed.ts +27 -0
- asa_standard-2.0.0/asa/modules/db_basic/shared/supabase-client.ts +70 -0
- asa_standard-2.0.0/asa/modules/db_basic/shared/types.ts +20 -0
- asa_standard-2.0.0/asa/modules/db_basic/shared/utils.ts +43 -0
- asa_standard-2.0.0/asa/modules/payments_basic/__init__.py +0 -0
- asa_standard-2.0.0/asa/modules/payments_basic/manifest.json +54 -0
- asa_standard-2.0.0/asa/modules/payments_basic/migrations/002_create_subscriptions.sql +44 -0
- asa_standard-2.0.0/asa/modules/payments_basic/migrations/003_create_entitlements.sql +54 -0
- asa_standard-2.0.0/asa/modules/payments_basic/migrations/003b_create_webhook_events.sql +28 -0
- asa_standard-2.0.0/asa/modules/payments_basic/shared/entitlement-hooks.ts +50 -0
- asa_standard-2.0.0/asa/modules/payments_basic/shared/entitlement-types.ts +29 -0
- asa_standard-2.0.0/asa/modules/payments_basic/shared/entitlements.ts +78 -0
- asa_standard-2.0.0/asa/modules/payments_basic/shared/guards.ts +110 -0
- asa_standard-2.0.0/asa/modules/payments_basic/shared/hooks.ts +45 -0
- asa_standard-2.0.0/asa/modules/payments_basic/shared/plans.ts +54 -0
- asa_standard-2.0.0/asa/modules/payments_basic/shared/reconciliation.ts +85 -0
- asa_standard-2.0.0/asa/modules/payments_basic/shared/resolver.ts +61 -0
- asa_standard-2.0.0/asa/modules/payments_basic/shared/stripe-client.ts +15 -0
- asa_standard-2.0.0/asa/modules/payments_basic/shared/types.ts +84 -0
- asa_standard-2.0.0/asa/modules/payments_basic/shared/webhook-handler.ts +198 -0
- asa_standard-2.0.0/asa/modules/payments_basic/shared/webhook-processor.ts +174 -0
- asa_standard-2.0.0/asa/modules/payments_basic/slices/cancel/handler.ts +55 -0
- asa_standard-2.0.0/asa/modules/payments_basic/slices/cancel/slice.contract.json +17 -0
- asa_standard-2.0.0/asa/modules/payments_basic/slices/cancel/ui/hook.ts +45 -0
- asa_standard-2.0.0/asa/modules/payments_basic/slices/check_limits/handler.ts +33 -0
- asa_standard-2.0.0/asa/modules/payments_basic/slices/check_limits/slice.contract.json +17 -0
- asa_standard-2.0.0/asa/modules/payments_basic/slices/subscribe/handler.ts +79 -0
- asa_standard-2.0.0/asa/modules/payments_basic/slices/subscribe/repository.ts +32 -0
- asa_standard-2.0.0/asa/modules/payments_basic/slices/subscribe/schemas.ts +21 -0
- asa_standard-2.0.0/asa/modules/payments_basic/slices/subscribe/slice.contract.json +20 -0
- asa_standard-2.0.0/asa/modules/payments_basic/slices/subscribe/ui/BillingSubscribe.tsx +93 -0
- asa_standard-2.0.0/asa/modules/payments_basic/slices/subscribe/ui/hook.ts +44 -0
- asa_standard-2.0.0/asa/modules/payments_basic/slices/webhook/handler.ts +67 -0
- asa_standard-2.0.0/asa/modules/payments_basic/slices/webhook/slice.contract.json +19 -0
- asa_standard-2.0.0/asa_standard.egg-info/PKG-INFO +112 -0
- asa_standard-2.0.0/asa_standard.egg-info/SOURCES.txt +117 -0
- asa_standard-2.0.0/asa_standard.egg-info/dependency_links.txt +1 -0
- asa_standard-2.0.0/asa_standard.egg-info/entry_points.txt +2 -0
- asa_standard-2.0.0/asa_standard.egg-info/requires.txt +11 -0
- asa_standard-2.0.0/asa_standard.egg-info/top_level.txt +1 -0
- asa_standard-2.0.0/pyproject.toml +74 -0
- asa_standard-2.0.0/setup.cfg +4 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: asa-standard
|
|
3
|
+
Version: 2.0.0
|
|
4
|
+
Summary: ASA CLI v2 - Slice-oriented architecture tool for AI-built apps
|
|
5
|
+
Author-email: Jan Voldán <jan@vibecodiq.com>
|
|
6
|
+
Classifier: Development Status :: 3 - Alpha
|
|
7
|
+
Classifier: Intended Audience :: Developers
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
Requires-Dist: typer>=0.9.0
|
|
12
|
+
Requires-Dist: jinja2>=3.1.0
|
|
13
|
+
Requires-Dist: pydantic>=2.0.0
|
|
14
|
+
Requires-Dist: rich>=13.0.0
|
|
15
|
+
Requires-Dist: pyyaml>=6.0.0
|
|
16
|
+
Provides-Extra: dev
|
|
17
|
+
Requires-Dist: pytest>=7.4.0; extra == "dev"
|
|
18
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
|
|
19
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
20
|
+
Requires-Dist: mypy>=1.5.0; extra == "dev"
|
|
21
|
+
|
|
22
|
+
# ASA CLI v2 — Starter Kit
|
|
23
|
+
|
|
24
|
+
> Slice-oriented architecture tool for AI-built apps.
|
|
25
|
+
> New repo from scratch. Replaces `asa-starter-kit` + `asa-cli`.
|
|
26
|
+
|
|
27
|
+
## Quick Start
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install -e ".[dev]"
|
|
31
|
+
asa --help
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Commands
|
|
35
|
+
|
|
36
|
+
### Public Core (9)
|
|
37
|
+
|
|
38
|
+
| Command | Role | Description |
|
|
39
|
+
|---|---|---|
|
|
40
|
+
| `asa init` | Builder | Initialize ASA project (config, domains/, shared/) |
|
|
41
|
+
| `asa scan` | Diagnostic | ACI score, structural risk, hotspots |
|
|
42
|
+
| `asa install <module>` | Builder | Install foundation module (auth-basic, db-basic, payments-basic) |
|
|
43
|
+
| `asa slice new <name>` | Builder | Create new vertical slice (FE + BE + contract) |
|
|
44
|
+
| `asa slice update <name>` | Builder | Regenerate slice (preserve user code via markers) |
|
|
45
|
+
| `asa slice plan <spec>` | Builder | Spec → slice architecture proposal |
|
|
46
|
+
| `asa slice split <name>` | Builder | Analyze oversized slice, propose split |
|
|
47
|
+
| `asa lint` | Enforcement | Boundary, contract, security checks |
|
|
48
|
+
| `asa deploy` | Delivery | Vercel + Supabase deployment |
|
|
49
|
+
|
|
50
|
+
### Advanced (4)
|
|
51
|
+
|
|
52
|
+
| Command | Description |
|
|
53
|
+
|---|---|
|
|
54
|
+
| `asa slice build <name>` | Run internal build pipeline (contract → zod → skeleton) |
|
|
55
|
+
| `asa slice sync` | Validate all contracts across project |
|
|
56
|
+
| `asa slice analyze <name>` | Detailed slice analysis (LOC, coupling, complexity) |
|
|
57
|
+
| `asa ui generate <name>` | Regenerate frontend part of slice |
|
|
58
|
+
|
|
59
|
+
## ASA Native Stack v1
|
|
60
|
+
|
|
61
|
+
All generated code targets this stack:
|
|
62
|
+
|
|
63
|
+
- **Frontend:** Next.js (App Router) + TypeScript + React
|
|
64
|
+
- **UI:** Tailwind CSS + shadcn/ui
|
|
65
|
+
- **Backend:** Next.js route handlers / server actions
|
|
66
|
+
- **Database:** PostgreSQL via Supabase
|
|
67
|
+
- **Auth:** Supabase Auth (SSR/cookie-based)
|
|
68
|
+
- **Payments:** Stripe
|
|
69
|
+
- **Deploy:** Vercel + Supabase
|
|
70
|
+
|
|
71
|
+
## Foundation Modules
|
|
72
|
+
|
|
73
|
+
| Module | Command | What it creates |
|
|
74
|
+
|---|---|---|
|
|
75
|
+
| `db-basic` | `asa install db-basic` | Supabase client, types, utils, migrations framework |
|
|
76
|
+
| `auth-basic` | `asa install auth-basic` | 4 slices (register, login, logout, reset-password) + middleware + session |
|
|
77
|
+
| `payments-basic` | `asa install payments-basic` | 4 slices (subscribe, cancel, webhook, check-limits) + Stripe config |
|
|
78
|
+
|
|
79
|
+
## Documentation
|
|
80
|
+
|
|
81
|
+
- [Implementation Spec](docs/SPEC.md) — full technical specification
|
|
82
|
+
- [Commands Reference](docs/COMMANDS.md) — user-facing docs (TODO)
|
|
83
|
+
- [Architecture](docs/ARCHITECTURE.md) — internal architecture (TODO)
|
|
84
|
+
|
|
85
|
+
## Development
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# Install with dev dependencies
|
|
89
|
+
pip install -e ".[dev]"
|
|
90
|
+
|
|
91
|
+
# Run tests
|
|
92
|
+
pytest
|
|
93
|
+
|
|
94
|
+
# Lint
|
|
95
|
+
ruff check .
|
|
96
|
+
|
|
97
|
+
# Type check
|
|
98
|
+
mypy asa/
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Related
|
|
102
|
+
|
|
103
|
+
| Resource | Repo |
|
|
104
|
+
|---|---|
|
|
105
|
+
| Distribution | [janvoldan/asa-cli](https://github.com/janvoldan/asa-cli) |
|
|
106
|
+
| Demo 02 spec | [janvoldan/02-asa-demo-spec](https://github.com/janvoldan/02-asa-demo-spec) |
|
|
107
|
+
| v1 source (archived) | [janvoldan/asa-starter-kit-old-bck](https://github.com/janvoldan/asa-starter-kit-old-bck) |
|
|
108
|
+
| v1 distribution (archived) | [janvoldan/asa-cli-old-bck](https://github.com/janvoldan/asa-cli-old-bck) |
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
*v2.0.0 — 2026-03-08*
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# ASA CLI v2 — Starter Kit
|
|
2
|
+
|
|
3
|
+
> Slice-oriented architecture tool for AI-built apps.
|
|
4
|
+
> New repo from scratch. Replaces `asa-starter-kit` + `asa-cli`.
|
|
5
|
+
|
|
6
|
+
## Quick Start
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
pip install -e ".[dev]"
|
|
10
|
+
asa --help
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Commands
|
|
14
|
+
|
|
15
|
+
### Public Core (9)
|
|
16
|
+
|
|
17
|
+
| Command | Role | Description |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| `asa init` | Builder | Initialize ASA project (config, domains/, shared/) |
|
|
20
|
+
| `asa scan` | Diagnostic | ACI score, structural risk, hotspots |
|
|
21
|
+
| `asa install <module>` | Builder | Install foundation module (auth-basic, db-basic, payments-basic) |
|
|
22
|
+
| `asa slice new <name>` | Builder | Create new vertical slice (FE + BE + contract) |
|
|
23
|
+
| `asa slice update <name>` | Builder | Regenerate slice (preserve user code via markers) |
|
|
24
|
+
| `asa slice plan <spec>` | Builder | Spec → slice architecture proposal |
|
|
25
|
+
| `asa slice split <name>` | Builder | Analyze oversized slice, propose split |
|
|
26
|
+
| `asa lint` | Enforcement | Boundary, contract, security checks |
|
|
27
|
+
| `asa deploy` | Delivery | Vercel + Supabase deployment |
|
|
28
|
+
|
|
29
|
+
### Advanced (4)
|
|
30
|
+
|
|
31
|
+
| Command | Description |
|
|
32
|
+
|---|---|
|
|
33
|
+
| `asa slice build <name>` | Run internal build pipeline (contract → zod → skeleton) |
|
|
34
|
+
| `asa slice sync` | Validate all contracts across project |
|
|
35
|
+
| `asa slice analyze <name>` | Detailed slice analysis (LOC, coupling, complexity) |
|
|
36
|
+
| `asa ui generate <name>` | Regenerate frontend part of slice |
|
|
37
|
+
|
|
38
|
+
## ASA Native Stack v1
|
|
39
|
+
|
|
40
|
+
All generated code targets this stack:
|
|
41
|
+
|
|
42
|
+
- **Frontend:** Next.js (App Router) + TypeScript + React
|
|
43
|
+
- **UI:** Tailwind CSS + shadcn/ui
|
|
44
|
+
- **Backend:** Next.js route handlers / server actions
|
|
45
|
+
- **Database:** PostgreSQL via Supabase
|
|
46
|
+
- **Auth:** Supabase Auth (SSR/cookie-based)
|
|
47
|
+
- **Payments:** Stripe
|
|
48
|
+
- **Deploy:** Vercel + Supabase
|
|
49
|
+
|
|
50
|
+
## Foundation Modules
|
|
51
|
+
|
|
52
|
+
| Module | Command | What it creates |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| `db-basic` | `asa install db-basic` | Supabase client, types, utils, migrations framework |
|
|
55
|
+
| `auth-basic` | `asa install auth-basic` | 4 slices (register, login, logout, reset-password) + middleware + session |
|
|
56
|
+
| `payments-basic` | `asa install payments-basic` | 4 slices (subscribe, cancel, webhook, check-limits) + Stripe config |
|
|
57
|
+
|
|
58
|
+
## Documentation
|
|
59
|
+
|
|
60
|
+
- [Implementation Spec](docs/SPEC.md) — full technical specification
|
|
61
|
+
- [Commands Reference](docs/COMMANDS.md) — user-facing docs (TODO)
|
|
62
|
+
- [Architecture](docs/ARCHITECTURE.md) — internal architecture (TODO)
|
|
63
|
+
|
|
64
|
+
## Development
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# Install with dev dependencies
|
|
68
|
+
pip install -e ".[dev]"
|
|
69
|
+
|
|
70
|
+
# Run tests
|
|
71
|
+
pytest
|
|
72
|
+
|
|
73
|
+
# Lint
|
|
74
|
+
ruff check .
|
|
75
|
+
|
|
76
|
+
# Type check
|
|
77
|
+
mypy asa/
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Related
|
|
81
|
+
|
|
82
|
+
| Resource | Repo |
|
|
83
|
+
|---|---|
|
|
84
|
+
| Distribution | [janvoldan/asa-cli](https://github.com/janvoldan/asa-cli) |
|
|
85
|
+
| Demo 02 spec | [janvoldan/02-asa-demo-spec](https://github.com/janvoldan/02-asa-demo-spec) |
|
|
86
|
+
| v1 source (archived) | [janvoldan/asa-starter-kit-old-bck](https://github.com/janvoldan/asa-starter-kit-old-bck) |
|
|
87
|
+
| v1 distribution (archived) | [janvoldan/asa-cli-old-bck](https://github.com/janvoldan/asa-cli-old-bck) |
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
*v2.0.0 — 2026-03-08*
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""ASA CLI v2 — thin Typer wrappers over engine."""
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""asa deploy — Architecture-safe deployment (Vercel + Supabase)."""
|
|
2
|
+
|
|
3
|
+
import typer
|
|
4
|
+
|
|
5
|
+
from ..core import logging as log
|
|
6
|
+
from ..core.errors import AsaError
|
|
7
|
+
from ..core.paths import find_project_root
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def run_deploy(*, check: bool, staging: bool, prod: bool, verbose: bool) -> None:
|
|
11
|
+
"""Deploy to Vercel + Supabase."""
|
|
12
|
+
from ..engine_loader import require_engine
|
|
13
|
+
require_engine()
|
|
14
|
+
from ..engine.deployer.deployer import deploy_check, deploy_prod, deploy_staging
|
|
15
|
+
try:
|
|
16
|
+
project_root = find_project_root()
|
|
17
|
+
|
|
18
|
+
if check:
|
|
19
|
+
exit_code = deploy_check(project_root)
|
|
20
|
+
elif staging:
|
|
21
|
+
exit_code = deploy_staging(project_root)
|
|
22
|
+
elif prod:
|
|
23
|
+
exit_code = deploy_prod(project_root)
|
|
24
|
+
else:
|
|
25
|
+
log.info("Usage: asa deploy --check | --staging | --prod")
|
|
26
|
+
exit_code = 1
|
|
27
|
+
|
|
28
|
+
raise typer.Exit(exit_code)
|
|
29
|
+
|
|
30
|
+
except AsaError as e:
|
|
31
|
+
log.error(str(e))
|
|
32
|
+
raise typer.Exit(1)
|
|
33
|
+
except typer.Exit:
|
|
34
|
+
raise
|
|
35
|
+
except Exception as e:
|
|
36
|
+
log.error(f"[INTERNAL ERROR] {e}")
|
|
37
|
+
raise typer.Exit(2)
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
"""asa init — Initialize a new ASA project."""
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import typer
|
|
7
|
+
|
|
8
|
+
from ..core import logging as log
|
|
9
|
+
from ..core.config import AsaConfig, save_config
|
|
10
|
+
from ..core.fs import ensure_directory, safe_write_file
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def run_init(name: str | None = None) -> None:
|
|
14
|
+
"""Initialize a new ASA project with runnable Next.js App Router starter.
|
|
15
|
+
|
|
16
|
+
After `asa init && npm install && npm run dev` the project must run.
|
|
17
|
+
"""
|
|
18
|
+
project_dir = Path.cwd()
|
|
19
|
+
config_path = project_dir / "asa.config.json"
|
|
20
|
+
|
|
21
|
+
if config_path.exists():
|
|
22
|
+
log.error(f"ASA project already initialized at {project_dir}")
|
|
23
|
+
raise typer.Exit(1)
|
|
24
|
+
|
|
25
|
+
project_name = name or project_dir.name
|
|
26
|
+
|
|
27
|
+
# 1. asa.config.json
|
|
28
|
+
config = AsaConfig(name=project_name)
|
|
29
|
+
save_config(config, project_dir)
|
|
30
|
+
log.detail(f"Created: asa.config.json")
|
|
31
|
+
|
|
32
|
+
# 2. directories
|
|
33
|
+
ensure_directory(project_dir / "domains")
|
|
34
|
+
log.detail("Created: domains/")
|
|
35
|
+
ensure_directory(project_dir / "shared")
|
|
36
|
+
log.detail("Created: shared/")
|
|
37
|
+
ensure_directory(project_dir / "app")
|
|
38
|
+
log.detail("Created: app/")
|
|
39
|
+
|
|
40
|
+
# 3. package.json
|
|
41
|
+
safe_write_file(project_dir / "package.json", _package_json(project_name))
|
|
42
|
+
log.detail("Created: package.json")
|
|
43
|
+
|
|
44
|
+
# 4. next.config.ts
|
|
45
|
+
safe_write_file(project_dir / "next.config.ts", _next_config())
|
|
46
|
+
log.detail("Created: next.config.ts")
|
|
47
|
+
|
|
48
|
+
# 5. tsconfig.json
|
|
49
|
+
safe_write_file(project_dir / "tsconfig.json", _tsconfig())
|
|
50
|
+
log.detail("Created: tsconfig.json")
|
|
51
|
+
|
|
52
|
+
# 6. tailwind.config.ts
|
|
53
|
+
safe_write_file(project_dir / "tailwind.config.ts", _tailwind_config())
|
|
54
|
+
log.detail("Created: tailwind.config.ts")
|
|
55
|
+
|
|
56
|
+
# 7. postcss.config.mjs
|
|
57
|
+
safe_write_file(project_dir / "postcss.config.mjs", _postcss_config())
|
|
58
|
+
log.detail("Created: postcss.config.mjs")
|
|
59
|
+
|
|
60
|
+
# 8. app/layout.tsx (developer-owned, CLI never overwrites)
|
|
61
|
+
safe_write_file(project_dir / "app" / "layout.tsx", _layout(project_name))
|
|
62
|
+
log.detail("Created: app/layout.tsx")
|
|
63
|
+
|
|
64
|
+
# 9. app/page.tsx (developer-owned)
|
|
65
|
+
safe_write_file(project_dir / "app" / "page.tsx", _page(project_name))
|
|
66
|
+
log.detail("Created: app/page.tsx")
|
|
67
|
+
|
|
68
|
+
# 10. app/globals.css
|
|
69
|
+
safe_write_file(project_dir / "app" / "globals.css", _globals_css())
|
|
70
|
+
log.detail("Created: app/globals.css")
|
|
71
|
+
|
|
72
|
+
# 11. .env.example
|
|
73
|
+
safe_write_file(project_dir / ".env.example", "# ASA project environment variables\n")
|
|
74
|
+
log.detail("Created: .env.example")
|
|
75
|
+
|
|
76
|
+
# 12. .cursorrules
|
|
77
|
+
safe_write_file(project_dir / ".cursorrules", _cursorrules())
|
|
78
|
+
log.detail("Created: .cursorrules")
|
|
79
|
+
|
|
80
|
+
# 13. .gitignore
|
|
81
|
+
safe_write_file(project_dir / ".gitignore", _gitignore())
|
|
82
|
+
log.detail("Created: .gitignore")
|
|
83
|
+
|
|
84
|
+
# 14. .asa/spec.yaml (desired architecture state)
|
|
85
|
+
safe_write_file(project_dir / ".asa" / "spec.yaml", _spec_yaml(project_name))
|
|
86
|
+
log.detail("Created: .asa/spec.yaml")
|
|
87
|
+
|
|
88
|
+
log.success(f"ASA project initialized: {project_name}")
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _package_json(name: str) -> str:
|
|
92
|
+
import json
|
|
93
|
+
pkg = {
|
|
94
|
+
"name": name,
|
|
95
|
+
"version": "0.1.0",
|
|
96
|
+
"private": True,
|
|
97
|
+
"scripts": {
|
|
98
|
+
"dev": "next dev",
|
|
99
|
+
"build": "next build",
|
|
100
|
+
"start": "next start",
|
|
101
|
+
"lint": "next lint",
|
|
102
|
+
},
|
|
103
|
+
"dependencies": {
|
|
104
|
+
"next": "^15.0.0",
|
|
105
|
+
"react": "^19.0.0",
|
|
106
|
+
"react-dom": "^19.0.0",
|
|
107
|
+
"zod": "^3.23.0",
|
|
108
|
+
},
|
|
109
|
+
"devDependencies": {
|
|
110
|
+
"typescript": "^5.6.0",
|
|
111
|
+
"@types/node": "^22.0.0",
|
|
112
|
+
"@types/react": "^19.0.0",
|
|
113
|
+
"@types/react-dom": "^19.0.0",
|
|
114
|
+
"tailwindcss": "^4.0.0",
|
|
115
|
+
"@tailwindcss/postcss": "^4.0.0",
|
|
116
|
+
"postcss": "^8.4.0",
|
|
117
|
+
},
|
|
118
|
+
}
|
|
119
|
+
return json.dumps(pkg, indent=2, ensure_ascii=False) + "\n"
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _next_config() -> str:
|
|
123
|
+
return """import type { NextConfig } from 'next';
|
|
124
|
+
|
|
125
|
+
const nextConfig: NextConfig = {};
|
|
126
|
+
|
|
127
|
+
export default nextConfig;
|
|
128
|
+
"""
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def _tsconfig() -> str:
|
|
132
|
+
return """{
|
|
133
|
+
"compilerOptions": {
|
|
134
|
+
"target": "ES2017",
|
|
135
|
+
"lib": ["dom", "dom.iterable", "esnext"],
|
|
136
|
+
"allowJs": true,
|
|
137
|
+
"skipLibCheck": true,
|
|
138
|
+
"strict": true,
|
|
139
|
+
"noEmit": true,
|
|
140
|
+
"esModuleInterop": true,
|
|
141
|
+
"module": "esnext",
|
|
142
|
+
"moduleResolution": "bundler",
|
|
143
|
+
"resolveJsonModule": true,
|
|
144
|
+
"isolatedModules": true,
|
|
145
|
+
"jsx": "preserve",
|
|
146
|
+
"incremental": true,
|
|
147
|
+
"plugins": [{ "name": "next" }],
|
|
148
|
+
"paths": {
|
|
149
|
+
"@/*": ["./*"]
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
|
153
|
+
"exclude": ["node_modules"]
|
|
154
|
+
}
|
|
155
|
+
"""
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def _tailwind_config() -> str:
|
|
159
|
+
return """import type { Config } from 'tailwindcss';
|
|
160
|
+
|
|
161
|
+
const config: Config = {
|
|
162
|
+
content: [
|
|
163
|
+
'./app/**/*.{ts,tsx}',
|
|
164
|
+
'./domains/**/*.{ts,tsx}',
|
|
165
|
+
'./shared/**/*.{ts,tsx}',
|
|
166
|
+
],
|
|
167
|
+
theme: {
|
|
168
|
+
extend: {},
|
|
169
|
+
},
|
|
170
|
+
plugins: [],
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
export default config;
|
|
174
|
+
"""
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def _postcss_config() -> str:
|
|
178
|
+
return """export default {
|
|
179
|
+
plugins: {
|
|
180
|
+
'@tailwindcss/postcss': {},
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
"""
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def _layout(name: str) -> str:
|
|
187
|
+
return f"""import type {{ Metadata }} from 'next';
|
|
188
|
+
import './globals.css';
|
|
189
|
+
|
|
190
|
+
export const metadata: Metadata = {{
|
|
191
|
+
title: '{name}',
|
|
192
|
+
description: 'Built with ASA architecture',
|
|
193
|
+
}};
|
|
194
|
+
|
|
195
|
+
export default function RootLayout({{
|
|
196
|
+
children,
|
|
197
|
+
}}: {{
|
|
198
|
+
children: React.ReactNode;
|
|
199
|
+
}}) {{
|
|
200
|
+
return (
|
|
201
|
+
<html lang="en">
|
|
202
|
+
<body>{{children}}</body>
|
|
203
|
+
</html>
|
|
204
|
+
);
|
|
205
|
+
}}
|
|
206
|
+
"""
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def _page(name: str) -> str:
|
|
210
|
+
return f"""export default function HomePage() {{
|
|
211
|
+
return (
|
|
212
|
+
<main className="flex min-h-screen flex-col items-center justify-center p-24">
|
|
213
|
+
<h1 className="text-4xl font-bold">{name}</h1>
|
|
214
|
+
<p className="mt-4 text-gray-600">Built with ASA architecture</p>
|
|
215
|
+
</main>
|
|
216
|
+
);
|
|
217
|
+
}}
|
|
218
|
+
"""
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def _globals_css() -> str:
|
|
222
|
+
return """@import 'tailwindcss';
|
|
223
|
+
"""
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def _cursorrules() -> str:
|
|
227
|
+
return """# ASA Architecture Rules for AI Tools
|
|
228
|
+
|
|
229
|
+
## Boundary Rules
|
|
230
|
+
- NEVER import from other domains (domains/X cannot import from domains/Y)
|
|
231
|
+
- ALWAYS use shared/ for cross-domain code
|
|
232
|
+
- Each slice is a vertical unit: handler + repository + schemas + UI
|
|
233
|
+
- Business logic belongs in domains/, not in app/
|
|
234
|
+
|
|
235
|
+
## File Ownership
|
|
236
|
+
- app/api/**/route.ts — ASA runtime adapters (DO NOT EDIT)
|
|
237
|
+
- app/**/page.tsx — ASA runtime adapters (DO NOT EDIT)
|
|
238
|
+
- app/layout.tsx — Developer-owned (safe to edit)
|
|
239
|
+
- domains/**/* — Slice files with ASA markers (edit only USER CODE sections)
|
|
240
|
+
- shared/**/* — Cross-domain utilities
|
|
241
|
+
|
|
242
|
+
## ASA Markers
|
|
243
|
+
- Code between `// --- ASA GENERATED START ---` and `// --- ASA GENERATED END ---` is auto-generated. DO NOT EDIT.
|
|
244
|
+
- Code between `// --- USER CODE START ---` and `// --- USER CODE END ---` is your code. SAFE TO EDIT.
|
|
245
|
+
|
|
246
|
+
## Naming
|
|
247
|
+
- Slice directories: kebab-case (e.g., reset-password/)
|
|
248
|
+
- Components: PascalCase (e.g., AuthLoginForm.tsx)
|
|
249
|
+
- Hooks: camelCase with use prefix (e.g., useAuthLogin)
|
|
250
|
+
- DB tables: snake_case
|
|
251
|
+
- Env vars: SCREAMING_SNAKE_CASE
|
|
252
|
+
"""
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def _spec_yaml(name: str) -> str:
|
|
256
|
+
return f"""# ASA Architecture Spec v0.1
|
|
257
|
+
# This file declares the desired architecture state for your project.
|
|
258
|
+
# Edit this file to match your project's actual configuration.
|
|
259
|
+
|
|
260
|
+
asa:
|
|
261
|
+
spec_version: "0.1"
|
|
262
|
+
|
|
263
|
+
app:
|
|
264
|
+
name: "{name}"
|
|
265
|
+
mode: "greenfield"
|
|
266
|
+
framework: "nextjs"
|
|
267
|
+
runtime: "vercel"
|
|
268
|
+
|
|
269
|
+
providers:
|
|
270
|
+
auth: "supabase"
|
|
271
|
+
database: "supabase-postgres"
|
|
272
|
+
billing: "stripe"
|
|
273
|
+
|
|
274
|
+
tenancy:
|
|
275
|
+
principal: "user"
|
|
276
|
+
tenant_key: "user_id"
|
|
277
|
+
|
|
278
|
+
domains:
|
|
279
|
+
foundation:
|
|
280
|
+
- "auth"
|
|
281
|
+
- "billing"
|
|
282
|
+
- "entitlements"
|
|
283
|
+
business: []
|
|
284
|
+
# Add your business domains here, e.g.:
|
|
285
|
+
# - "invoices"
|
|
286
|
+
# - "projects"
|
|
287
|
+
|
|
288
|
+
rules:
|
|
289
|
+
no_auth_in_ui: true
|
|
290
|
+
no_stripe_outside_billing: true
|
|
291
|
+
no_direct_db_from_ui: true
|
|
292
|
+
no_supabase_admin_outside_server: true
|
|
293
|
+
|
|
294
|
+
auth:
|
|
295
|
+
session_source: "supabase"
|
|
296
|
+
user_entity: "profiles"
|
|
297
|
+
guard_api:
|
|
298
|
+
- "requireUser"
|
|
299
|
+
- "requireRole"
|
|
300
|
+
|
|
301
|
+
billing:
|
|
302
|
+
provider: "stripe"
|
|
303
|
+
webhook_source_of_truth: true
|
|
304
|
+
plans:
|
|
305
|
+
- key: "free"
|
|
306
|
+
- key: "pro"
|
|
307
|
+
|
|
308
|
+
entitlements:
|
|
309
|
+
source_of_truth: "database"
|
|
310
|
+
features: []
|
|
311
|
+
limits: []
|
|
312
|
+
# Add your features and limits here, e.g.:
|
|
313
|
+
# features:
|
|
314
|
+
# - key: "csv_export"
|
|
315
|
+
# type: "boolean"
|
|
316
|
+
# default: false
|
|
317
|
+
# limits:
|
|
318
|
+
# - key: "max_invoices_per_month"
|
|
319
|
+
# type: "number"
|
|
320
|
+
# default: 5
|
|
321
|
+
guard_api:
|
|
322
|
+
- "requireEntitlement"
|
|
323
|
+
- "requireLimit"
|
|
324
|
+
|
|
325
|
+
data_access:
|
|
326
|
+
rls_required: true
|
|
327
|
+
ownership_model: "user-scoped"
|
|
328
|
+
forbidden_imports:
|
|
329
|
+
- "@supabase/supabase-js in ui"
|
|
330
|
+
- "stripe in ui"
|
|
331
|
+
"""
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
def _gitignore() -> str:
|
|
335
|
+
return """node_modules/
|
|
336
|
+
.next/
|
|
337
|
+
.env
|
|
338
|
+
.env.local
|
|
339
|
+
*.tsbuildinfo
|
|
340
|
+
next-env.d.ts
|
|
341
|
+
"""
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""asa install — Install ASA foundation module."""
|
|
2
|
+
|
|
3
|
+
import typer
|
|
4
|
+
|
|
5
|
+
from ..core import logging as log
|
|
6
|
+
from ..core.errors import AsaError
|
|
7
|
+
from ..core.paths import find_project_root
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def run_install(module_name: str) -> None:
|
|
11
|
+
"""Install an ASA foundation module."""
|
|
12
|
+
from ..engine_loader import require_engine
|
|
13
|
+
require_engine()
|
|
14
|
+
from ..engine.installer.installer import install_module
|
|
15
|
+
try:
|
|
16
|
+
project_root = find_project_root()
|
|
17
|
+
created = install_module(module_name, project_root)
|
|
18
|
+
log.success(f"Module installed: {module_name}")
|
|
19
|
+
for path in created:
|
|
20
|
+
log.detail(f"Created: {path}")
|
|
21
|
+
|
|
22
|
+
except AsaError as e:
|
|
23
|
+
log.error(str(e))
|
|
24
|
+
raise typer.Exit(1)
|
|
25
|
+
except Exception as e:
|
|
26
|
+
log.error(f"[INTERNAL ERROR] {e}")
|
|
27
|
+
raise typer.Exit(2)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""asa lint — Boundary, contract, structure, security enforcement."""
|
|
2
|
+
|
|
3
|
+
import typer
|
|
4
|
+
|
|
5
|
+
from ..core import logging as log
|
|
6
|
+
from ..core.config import load_config
|
|
7
|
+
from ..core.errors import AsaError
|
|
8
|
+
from ..core.paths import find_project_root, parse_domain_slice
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def run_lint(target: str | None, *, strict: bool = False) -> None:
|
|
12
|
+
"""Lint project or single slice for violations."""
|
|
13
|
+
from ..engine_loader import require_engine
|
|
14
|
+
require_engine()
|
|
15
|
+
from ..engine.linter.linter import lint_project, lint_slice
|
|
16
|
+
try:
|
|
17
|
+
project_root = find_project_root()
|
|
18
|
+
config = load_config(project_root)
|
|
19
|
+
|
|
20
|
+
if target:
|
|
21
|
+
domain, slice_name = parse_domain_slice(target)
|
|
22
|
+
exit_code = lint_slice(domain, slice_name, project_root, config, strict=strict)
|
|
23
|
+
else:
|
|
24
|
+
exit_code = lint_project(project_root, config, strict=strict)
|
|
25
|
+
|
|
26
|
+
raise typer.Exit(exit_code)
|
|
27
|
+
|
|
28
|
+
except AsaError as e:
|
|
29
|
+
log.error(str(e))
|
|
30
|
+
raise typer.Exit(1)
|
|
31
|
+
except typer.Exit:
|
|
32
|
+
raise
|
|
33
|
+
except Exception as e:
|
|
34
|
+
log.error(f"[INTERNAL ERROR] {e}")
|
|
35
|
+
raise typer.Exit(2)
|