From f82b4bb24d1d9db33cc0c4be05c70bdbb2f4f5eb Mon Sep 17 00:00:00 2001 From: jabahum Date: Sat, 24 Oct 2026 18:12:39 +0300 Subject: [PATCH 1/2] Deliver all templates as embedded source files --- CHANGELOG.md | 6 + README.md | 120 ++------- assets.go | 37 ++- internal/cache/cache.go | 58 ---- internal/cache/cache_test.go | 19 -- internal/cli/cli.go | 110 +------- internal/cli/cli_test.go | 65 +++-- internal/generator/generator.go | 124 +-------- internal/generator/generator_test.go | 41 ++- internal/publish/pack.go | 88 ------ internal/publish/pack_test.go | 25 -- internal/registry/registry.go | 17 +- internal/templatehub/hub.go | 253 ------------------ internal/templatehub/hub_test.go | 59 ---- internal/upgrade/upgrade.go | 10 +- internal/upgrade/upgrade_test.go | 25 ++ templates/flutter_foundations/apps/.gitkeep | 1 + templates/go-foundations.zip | Bin 634452 -> 0 bytes templates/go-foundations/README.md | 8 +- .../cmd/server/{main.go => main.go.tmpl} | 0 .../v1/{audit.pb.go => audit.pb.go.tmpl} | 0 .../{audit.pb.gw.go => audit.pb.gw.go.tmpl} | 0 ...audit_grpc.pb.go => audit_grpc.pb.go.tmpl} | 0 .../auth/v1/{auth.pb.go => auth.pb.go.tmpl} | 0 .../v1/{auth.pb.gw.go => auth.pb.gw.go.tmpl} | 0 .../{auth_grpc.pb.go => auth_grpc.pb.go.tmpl} | 0 .../rbac/v1/{rbac.pb.go => rbac.pb.go.tmpl} | 0 .../v1/{rbac.pb.gw.go => rbac.pb.gw.go.tmpl} | 0 .../{rbac_grpc.pb.go => rbac_grpc.pb.go.tmpl} | 0 .../user/v1/{user.pb.go => user.pb.go.tmpl} | 0 .../v1/{user.pb.gw.go => user.pb.gw.go.tmpl} | 0 .../{user_grpc.pb.go => user_grpc.pb.go.tmpl} | 0 .../go-foundations/{go.mod => go.mod.tmpl} | 0 .../audit/{service.go => service.go.tmpl} | 0 .../{service_test.go => service_test.go.tmpl} | 0 ...thentication.go => authentication.go.tmpl} | 0 .../auth/{service.go => service.go.tmpl} | 0 .../{service_test.go => service_test.go.tmpl} | 0 .../rbac/{service.go => service.go.tmpl} | 0 .../user/{service.go => service.go.tmpl} | 0 .../{service_test.go => service_test.go.tmpl} | 0 .../domain/audit/{model.go => model.go.tmpl} | 0 .../domain/auth/{auth.go => auth.go.tmpl} | 0 .../auth/{session.go => session.go.tmpl} | 0 .../idempotency/{model.go => model.go.tmpl} | 0 .../domain/rbac/{model.go => model.go.tmpl} | 0 .../{repository.go => repository.go.tmpl} | 0 .../domain/user/{entity.go => entity.go.tmpl} | 0 .../domain/user/{errors.go => errors.go.tmpl} | 0 .../{repository.go => repository.go.tmpl} | 0 .../auth/local/{jwt.go => jwt.go.tmpl} | 0 .../local/{password.go => password.go.tmpl} | 0 ...password_test.go => password_test.go.tmpl} | 0 .../oidc/{verifier.go => verifier.go.tmpl} | 0 .../bootstrap/{admin.go => admin.go.tmpl} | 0 .../config/{config.go => config.go.tmpl} | 0 .../{postgres.go => postgres.go.tmpl} | 0 .../{metrics.go => metrics.go.tmpl} | 0 .../{telemetry.go => telemetry.go.tmpl} | 0 ..._repository.go => user_repository.go.tmpl} | 0 ...repository.go => audit_repository.go.tmpl} | 0 ...ncy_store.go => idempotency_store.go.tmpl} | 0 ..._repository.go => rbac_repository.go.tmpl} | 0 ...pository.go => session_repository.go.tmpl} | 0 ..._repository.go => user_repository.go.tmpl} | 0 .../security/{context.go => context.go.tmpl} | 0 .../grpc/apierror/{error.go => error.go.tmpl} | 0 .../{error_test.go => error_test.go.tmpl} | 0 ...audit_handler.go => audit_handler.go.tmpl} | 0 .../{auth_handler.go => auth_handler.go.tmpl} | 0 .../interceptor/{audit.go => audit.go.tmpl} | 0 .../{audit_test.go => audit_test.go.tmpl} | 0 ...thentication.go => authentication.go.tmpl} | 0 ...authorization.go => authorization.go.tmpl} | 0 .../interceptor/{errors.go => errors.go.tmpl} | 0 .../{idempotency.go => idempotency.go.tmpl} | 0 ...tency_test.go => idempotency_test.go.tmpl} | 0 .../{logging.go => logging.go.tmpl} | 0 .../{metrics.go => metrics.go.tmpl} | 0 .../{recovery.go => recovery.go.tmpl} | 0 .../{request_id.go => request_id.go.tmpl} | 0 .../{validation.go => validation.go.tmpl} | 0 ...dation_test.go => validation_test.go.tmpl} | 0 .../grpc/policy/{policy.go => policy.go.tmpl} | 0 .../{rbac_handler.go => rbac_handler.go.tmpl} | 0 .../{user_handler.go => user_handler.go.tmpl} | 0 ...documentation.go => documentation.go.tmpl} | 0 .../http/{gateway.go => gateway.go.tmpl} | 0 .../{gateway_test.go => gateway_test.go.tmpl} | 0 89 files changed, 203 insertions(+), 863 deletions(-) delete mode 100644 internal/cache/cache.go delete mode 100644 internal/cache/cache_test.go delete mode 100644 internal/publish/pack.go delete mode 100644 internal/publish/pack_test.go delete mode 100644 internal/templatehub/hub.go delete mode 100644 internal/templatehub/hub_test.go create mode 100644 internal/upgrade/upgrade_test.go create mode 100644 templates/flutter_foundations/apps/.gitkeep delete mode 100644 templates/go-foundations.zip rename templates/go-foundations/cmd/server/{main.go => main.go.tmpl} (100%) rename templates/go-foundations/gen/proto/audit/v1/{audit.pb.go => audit.pb.go.tmpl} (100%) rename templates/go-foundations/gen/proto/audit/v1/{audit.pb.gw.go => audit.pb.gw.go.tmpl} (100%) rename templates/go-foundations/gen/proto/audit/v1/{audit_grpc.pb.go => audit_grpc.pb.go.tmpl} (100%) rename templates/go-foundations/gen/proto/auth/v1/{auth.pb.go => auth.pb.go.tmpl} (100%) rename templates/go-foundations/gen/proto/auth/v1/{auth.pb.gw.go => auth.pb.gw.go.tmpl} (100%) rename templates/go-foundations/gen/proto/auth/v1/{auth_grpc.pb.go => auth_grpc.pb.go.tmpl} (100%) rename templates/go-foundations/gen/proto/rbac/v1/{rbac.pb.go => rbac.pb.go.tmpl} (100%) rename templates/go-foundations/gen/proto/rbac/v1/{rbac.pb.gw.go => rbac.pb.gw.go.tmpl} (100%) rename templates/go-foundations/gen/proto/rbac/v1/{rbac_grpc.pb.go => rbac_grpc.pb.go.tmpl} (100%) rename templates/go-foundations/gen/proto/user/v1/{user.pb.go => user.pb.go.tmpl} (100%) rename templates/go-foundations/gen/proto/user/v1/{user.pb.gw.go => user.pb.gw.go.tmpl} (100%) rename templates/go-foundations/gen/proto/user/v1/{user_grpc.pb.go => user_grpc.pb.go.tmpl} (100%) rename templates/go-foundations/{go.mod => go.mod.tmpl} (100%) rename templates/go-foundations/internal/application/audit/{service.go => service.go.tmpl} (100%) rename templates/go-foundations/internal/application/audit/{service_test.go => service_test.go.tmpl} (100%) rename templates/go-foundations/internal/application/auth/{authentication.go => authentication.go.tmpl} (100%) rename templates/go-foundations/internal/application/auth/{service.go => service.go.tmpl} (100%) rename templates/go-foundations/internal/application/auth/{service_test.go => service_test.go.tmpl} (100%) rename templates/go-foundations/internal/application/rbac/{service.go => service.go.tmpl} (100%) rename templates/go-foundations/internal/application/user/{service.go => service.go.tmpl} (100%) rename templates/go-foundations/internal/application/user/{service_test.go => service_test.go.tmpl} (100%) rename templates/go-foundations/internal/domain/audit/{model.go => model.go.tmpl} (100%) rename templates/go-foundations/internal/domain/auth/{auth.go => auth.go.tmpl} (100%) rename templates/go-foundations/internal/domain/auth/{session.go => session.go.tmpl} (100%) rename templates/go-foundations/internal/domain/idempotency/{model.go => model.go.tmpl} (100%) rename templates/go-foundations/internal/domain/rbac/{model.go => model.go.tmpl} (100%) rename templates/go-foundations/internal/domain/rbac/{repository.go => repository.go.tmpl} (100%) rename templates/go-foundations/internal/domain/user/{entity.go => entity.go.tmpl} (100%) rename templates/go-foundations/internal/domain/user/{errors.go => errors.go.tmpl} (100%) rename templates/go-foundations/internal/domain/user/{repository.go => repository.go.tmpl} (100%) rename templates/go-foundations/internal/infrastructure/auth/local/{jwt.go => jwt.go.tmpl} (100%) rename templates/go-foundations/internal/infrastructure/auth/local/{password.go => password.go.tmpl} (100%) rename templates/go-foundations/internal/infrastructure/auth/local/{password_test.go => password_test.go.tmpl} (100%) rename templates/go-foundations/internal/infrastructure/auth/oidc/{verifier.go => verifier.go.tmpl} (100%) rename templates/go-foundations/internal/infrastructure/bootstrap/{admin.go => admin.go.tmpl} (100%) rename templates/go-foundations/internal/infrastructure/config/{config.go => config.go.tmpl} (100%) rename templates/go-foundations/internal/infrastructure/database/{postgres.go => postgres.go.tmpl} (100%) rename templates/go-foundations/internal/infrastructure/observability/{metrics.go => metrics.go.tmpl} (100%) rename templates/go-foundations/internal/infrastructure/observability/{telemetry.go => telemetry.go.tmpl} (100%) rename templates/go-foundations/internal/infrastructure/persistence/memory/{user_repository.go => user_repository.go.tmpl} (100%) rename templates/go-foundations/internal/infrastructure/persistence/postgres/{audit_repository.go => audit_repository.go.tmpl} (100%) rename templates/go-foundations/internal/infrastructure/persistence/postgres/{idempotency_store.go => idempotency_store.go.tmpl} (100%) rename templates/go-foundations/internal/infrastructure/persistence/postgres/{rbac_repository.go => rbac_repository.go.tmpl} (100%) rename templates/go-foundations/internal/infrastructure/persistence/postgres/{session_repository.go => session_repository.go.tmpl} (100%) rename templates/go-foundations/internal/infrastructure/persistence/postgres/{user_repository.go => user_repository.go.tmpl} (100%) rename templates/go-foundations/internal/security/{context.go => context.go.tmpl} (100%) rename templates/go-foundations/internal/transport/grpc/apierror/{error.go => error.go.tmpl} (100%) rename templates/go-foundations/internal/transport/grpc/apierror/{error_test.go => error_test.go.tmpl} (100%) rename templates/go-foundations/internal/transport/grpc/{audit_handler.go => audit_handler.go.tmpl} (100%) rename templates/go-foundations/internal/transport/grpc/{auth_handler.go => auth_handler.go.tmpl} (100%) rename templates/go-foundations/internal/transport/grpc/interceptor/{audit.go => audit.go.tmpl} (100%) rename templates/go-foundations/internal/transport/grpc/interceptor/{audit_test.go => audit_test.go.tmpl} (100%) rename templates/go-foundations/internal/transport/grpc/interceptor/{authentication.go => authentication.go.tmpl} (100%) rename templates/go-foundations/internal/transport/grpc/interceptor/{authorization.go => authorization.go.tmpl} (100%) rename templates/go-foundations/internal/transport/grpc/interceptor/{errors.go => errors.go.tmpl} (100%) rename templates/go-foundations/internal/transport/grpc/interceptor/{idempotency.go => idempotency.go.tmpl} (100%) rename templates/go-foundations/internal/transport/grpc/interceptor/{idempotency_test.go => idempotency_test.go.tmpl} (100%) rename templates/go-foundations/internal/transport/grpc/interceptor/{logging.go => logging.go.tmpl} (100%) rename templates/go-foundations/internal/transport/grpc/interceptor/{metrics.go => metrics.go.tmpl} (100%) rename templates/go-foundations/internal/transport/grpc/interceptor/{recovery.go => recovery.go.tmpl} (100%) rename templates/go-foundations/internal/transport/grpc/interceptor/{request_id.go => request_id.go.tmpl} (100%) rename templates/go-foundations/internal/transport/grpc/interceptor/{validation.go => validation.go.tmpl} (100%) rename templates/go-foundations/internal/transport/grpc/interceptor/{validation_test.go => validation_test.go.tmpl} (100%) rename templates/go-foundations/internal/transport/grpc/policy/{policy.go => policy.go.tmpl} (100%) rename templates/go-foundations/internal/transport/grpc/{rbac_handler.go => rbac_handler.go.tmpl} (100%) rename templates/go-foundations/internal/transport/grpc/{user_handler.go => user_handler.go.tmpl} (100%) rename templates/go-foundations/internal/transport/http/{documentation.go => documentation.go.tmpl} (100%) rename templates/go-foundations/internal/transport/http/{gateway.go => gateway.go.tmpl} (100%) rename templates/go-foundations/internal/transport/http/{gateway_test.go => gateway_test.go.tmpl} (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64e7d9c..e718387 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +- Deliver all templates as embedded source files and restore `.tmpl` filenames during generation. +- Remove template ZIP packaging, downloads, external registries, and cache commands. +- Resolve template version checks and upgrade reports from the bundled registry only. + ## 1.2.0 - 2026-08-30 - Remove checked-in build artifacts and an orphan generated application file. diff --git a/README.md b/README.md index 9dd30b9..e7de5e3 100644 --- a/README.md +++ b/README.md @@ -4,13 +4,11 @@ Foundry is a single Go CLI for creating and extending projects from reusable fou ## Highlights -- external, versioned template registry support -- SHA-256 verified template ZIP downloads -- local template cache and offline generation -- `foundry template update` / `foundry template list` +- Go and Flutter templates bundled directly as source files in one executable +- offline project generation with no template downloads or packaging step +- `foundry template list` to inspect the bundled templates - `foundry add service` and `foundry add migration` for Go projects - `foundry add feature` and `foundry add package` for Flutter workspaces -- bundled templates remain available without a registry or network connection ## Bundled templates @@ -75,20 +73,7 @@ foundry new mediguide \ --org ug.go.health ``` -Select an external/cached version: - -```bash -foundry new users-service \ - --template go \ - --version 1.2.0 \ - --module github.com/your-org/users-service -``` - -Force offline operation: - -```bash -foundry new users-service --template go --version 1.2.0 --offline -``` +Both templates are available offline. Optional generation hooks may invoke installed SDKs and their package managers; use `--no-hooks` to skip them. ## Extend an existing project @@ -112,68 +97,20 @@ foundry add package foundation_analytics A Flutter feature is created as a small clean slice with `domain`, `application`, `data`, and `presentation` directories. -## External template registry - -Foundry does not require a registry. The built-in templates always remain available. A registry lets templates evolve independently from the Foundry binary. +## Template delivery -Configure it once: +All templates are maintained under `templates/` and embedded directly into the Foundry executable. Generation copies their files, restores template filenames, and substitutes project settings. -```bash -export FOUNDRY_REGISTRY_URL="https://raw.githubusercontent.com/your-org/foundry-templates/main/registry.json" -foundry template update -foundry template list -``` +| Template | Source folder | Delivery | +| --- | --- | --- | +| Go Foundations | `templates/go-foundations/` | Embedded source files | +| Flutter Foundations | `templates/flutter_foundations/` | Embedded source files | -or provide the URL explicitly: +Go source files use `.go.tmpl` and its module manifest uses `go.mod.tmpl` to keep the template separate from Foundry's Go module. Generated projects receive ordinary `.go` files and `go.mod`. -```bash -foundry template update --registry https://example.org/foundry/registry.json -``` - -Registry format: - -```json -{ - "schema": 1, - "updated_at": "2026-08-14T12:00:00Z", - "templates": [ - { - "id": "go-foundations", - "name": "Go Foundations", - "version": "1.2.0", - "description": "Production Go gRPC foundation", - "kind": "go", - "aliases": ["go", "grpc", "backend"], - "url": "https://github.com/your-org/foundry-templates/releases/download/go-foundations-v1.2.0/go-foundations.zip", - "sha256": "" - } - ] -} -``` +Template changes ship with a new Foundry build/release. There is no external template registry, template archive download, or template cache. `foundry template list` shows the available versions; `--version` can assert the bundled version but cannot select an external release. -The `url` can be a GitHub Release asset or any direct HTTP(S) ZIP. Foundry verifies the downloaded archive against `sha256` before adding it to the cache. - -Cache layout is platform-specific under the operating system's standard user-cache directory: - -```text -foundry/ -├── registry.json -└── templates/ - └── go-foundations/ - └── 1.2.0/ - └── template.zip -``` - -Set `FOUNDRY_CACHE_DIR` to use an explicit cache location, which is useful in -CI, containers, and other isolated environments. - -Once downloaded: - -```bash -foundry new demo --template go --version 1.2.0 --offline -``` - -works without a network connection. +To update a template, edit its source files and rebuild Foundry with `make build`. ## Commands @@ -185,12 +122,9 @@ foundry add migration foundry add feature foundry add package foundry template list -foundry template update --registry foundry list foundry info