csrd-utils 0.5.4__tar.gz → 0.5.6__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.
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/PKG-INFO +1 -1
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/pyproject.toml +1 -1
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/__main__.py +47 -44
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/compose/operations.py +31 -1
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/.gitignore +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/README.md +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/AGENTS.md +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/__init__.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/audit.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/compose/__init__.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/compose/augments.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/compose/git.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/compose/infra.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/compose/loader.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/compose/presets.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/compose/renderer.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/compose/scaffolder.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/compose/service_renderers.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/compose/yaml_editor.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/doctor.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/generate/__init__.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/generate/handlers.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/generate/helpers.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/generate/menu.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/models/__init__.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/models/base.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/models/spec.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/models/types.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/__init__.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/__init__.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/auth-passthrough/__init__.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/auth-passthrough/delegates/__init__.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/auth-passthrough/delegates/auth_delegate.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/auth-passthrough/dependencies/__init__.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/auth-passthrough/dependencies/auth_passthrough.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/auth-passthrough/models/__init__.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/auth-passthrough/models/auth_passthrough.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/auth-passthrough/views/__init__.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/auth-passthrough/views/auth_passthrough_view.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/caching/dependencies/cache.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/caching/views/cache_view.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/celery-dispatcher/celery_client.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/celery-dispatcher/models/an/__init__.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/celery-dispatcher/models/an/tasks.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/celery-dispatcher/models/tasks.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/celery-dispatcher/views/tasks_view.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/celery-worker/celery_app.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/celery-worker/tasks/__init__.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/celery-worker/tasks/example.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/crud-scaffold/dependencies/${entity_name_snake}_repository.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/crud-scaffold/migrations_${entity_name_snake}.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/crud-scaffold/models/${entity_name_snake}.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/crud-scaffold/repositories/${entity_name_snake}_repository.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/crud-scaffold/views/${entity_name_snake}_view.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/db-config/dependencies/db.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/gateway/dependencies/proxy.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/gateway/middleware/auth_guard.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/gateway/views/proxy_view.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/jwt-auth-consumer/dependencies/auth.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/jwt-auth-provider/AUTH.md +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/jwt-auth-provider/__init__.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/jwt-auth-provider/dependencies/__init__.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/jwt-auth-provider/dependencies/auth.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/jwt-auth-provider/dependencies/db.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/jwt-auth-provider/dependencies/token_service.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/jwt-auth-provider/migrations.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/jwt-auth-provider/models/__init__.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/jwt-auth-provider/models/auth.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/jwt-auth-provider/models/jwks.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/jwt-auth-provider/models/users.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/jwt-auth-provider/repositories/__init__.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/jwt-auth-provider/repositories/user_repository.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/jwt-auth-provider/services/__init__.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/jwt-auth-provider/services/token_service.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/jwt-auth-provider/views/__init__.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/jwt-auth-provider/views/auth_view.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/jwt-auth-provider/views/jwks_view.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/jwt-auth-provider/views/users_admin_view.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/jwt-auth-provider/views/users_view.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/metrics/middleware/metrics.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/metrics/views/metrics_view.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/rabbit-messaging/dependencies/rabbit.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/rabbit-messaging/handlers/example_handler.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/rabbit-messaging/handlers/ping_handler.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/rabbit-messaging/views/messaging_view.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/tracing/middleware/tracing.py.template +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/service/cookiecutter.json +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/service/{{cookiecutter.__service_name_snake}}/Dockerfile +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/service/{{cookiecutter.__service_name_snake}}/README.md +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/service/{{cookiecutter.__service_name_snake}}/__init__.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/service/{{cookiecutter.__service_name_snake}}/dependencies/__init__.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/service/{{cookiecutter.__service_name_snake}}/models/__init__.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/service/{{cookiecutter.__service_name_snake}}/requirements.txt +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/service/{{cookiecutter.__service_name_snake}}/settings.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/service/{{cookiecutter.__service_name_snake}}/tests/__init__.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/service/{{cookiecutter.__service_name_snake}}/tests/conftest.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/service/{{cookiecutter.__service_name_snake}}/views/__init__.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/tui_wizard/__init__.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/tui_wizard/exceptions.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/tui_wizard/menu.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/tui_wizard/models.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/tui_wizard/prompts.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/tui_wizard/terminal.py +0 -0
- {csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/tui_wizard/wizard.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: csrd-utils
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.6
|
|
4
4
|
Summary: CLI utilities for csrd service generation and feature augmentation
|
|
5
5
|
Project-URL: Repository, https://github.com/csrd-api/fastapi-common
|
|
6
6
|
Project-URL: Documentation, https://github.com/csrd-api/fastapi-common/tree/main/packages/utils
|
|
@@ -42,48 +42,45 @@ def _parser_shape(
|
|
|
42
42
|
return commands, options
|
|
43
43
|
|
|
44
44
|
|
|
45
|
-
def _render_bash_completion(
|
|
45
|
+
def _render_bash_completion() -> str:
|
|
46
|
+
"""Render a dynamic bash completion script.
|
|
47
|
+
|
|
48
|
+
Instead of baking a static word list, the script calls
|
|
49
|
+
``csrd --_complete`` at tab-time so it always reflects the
|
|
50
|
+
currently installed version's commands and flags.
|
|
51
|
+
"""
|
|
52
|
+
return (
|
|
53
|
+
"# bash completion for csrd — dynamic (calls csrd --_complete)\n"
|
|
54
|
+
"_csrd_completion() {\n"
|
|
55
|
+
" local cur words\n"
|
|
56
|
+
' cur="${COMP_WORDS[COMP_CWORD]}"\n'
|
|
57
|
+
' words=$(csrd --_complete "${COMP_WORDS[@]:1:COMP_CWORD-1}" 2>/dev/null)\n'
|
|
58
|
+
' COMPREPLY=( $(compgen -W "$words" -- "$cur") )\n'
|
|
59
|
+
"}\n"
|
|
60
|
+
"complete -F _csrd_completion csrd csrd-utils csrt\n"
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _handle_complete(parser: argparse.ArgumentParser, words: list[str]) -> int:
|
|
65
|
+
"""Print completion candidates for the given partial command line.
|
|
66
|
+
|
|
67
|
+
Called by the bash completion script via ``csrd --_complete <words>``.
|
|
68
|
+
"""
|
|
46
69
|
commands, options = _parser_shape(parser)
|
|
47
70
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
' cur="${COMP_WORDS[COMP_CWORD]}"',
|
|
53
|
-
' key=""',
|
|
54
|
-
"",
|
|
55
|
-
' for token in "${COMP_WORDS[@]:1:COMP_CWORD-1}"; do',
|
|
56
|
-
' case "$token" in',
|
|
57
|
-
" -*) continue ;;",
|
|
58
|
-
" esac",
|
|
59
|
-
' if [[ -n "$key" ]]; then',
|
|
60
|
-
' key="$key $token"',
|
|
61
|
-
" else",
|
|
62
|
-
' key="$token"',
|
|
63
|
-
" fi",
|
|
64
|
-
" done",
|
|
65
|
-
"",
|
|
66
|
-
' case "$key" in',
|
|
67
|
-
]
|
|
68
|
-
|
|
69
|
-
for chain in sorted(commands.keys()):
|
|
70
|
-
key = " ".join(chain)
|
|
71
|
-
command_candidates = commands.get(chain, [])
|
|
72
|
-
option_candidates = options.get(chain, [])
|
|
73
|
-
candidates = " ".join(command_candidates + option_candidates).strip()
|
|
74
|
-
if not candidates:
|
|
71
|
+
# Walk the word chain to find the deepest matching subcommand
|
|
72
|
+
chain: tuple[str, ...] = ()
|
|
73
|
+
for word in words:
|
|
74
|
+
if word.startswith("-"):
|
|
75
75
|
continue
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
]
|
|
85
|
-
)
|
|
86
|
-
return "\n".join(lines) + "\n"
|
|
76
|
+
candidate = (*chain, word)
|
|
77
|
+
if candidate in commands:
|
|
78
|
+
chain = candidate
|
|
79
|
+
|
|
80
|
+
command_candidates = commands.get(chain, [])
|
|
81
|
+
option_candidates = options.get(chain, [])
|
|
82
|
+
print(" ".join(command_candidates + option_candidates))
|
|
83
|
+
return 0
|
|
87
84
|
|
|
88
85
|
|
|
89
86
|
# ---------------------------------------------------------------------------
|
|
@@ -94,16 +91,17 @@ _COMPLETION_DIR = Path.home() / ".local" / "share" / "bash-completion" / "comple
|
|
|
94
91
|
_COMPLETION_FILE = _COMPLETION_DIR / "csrd"
|
|
95
92
|
|
|
96
93
|
|
|
97
|
-
def _install_completion(
|
|
94
|
+
def _install_completion() -> int:
|
|
98
95
|
"""Write the bash completion script to the user completions directory.
|
|
99
96
|
|
|
100
97
|
bash-completion auto-loads files from ``~/.local/share/bash-completion/completions/``
|
|
101
|
-
so no ``.bashrc`` edit is needed.
|
|
98
|
+
so no ``.bashrc`` edit is needed. The script is a thin shim that calls
|
|
99
|
+
``csrd --_complete`` at tab-time, so it never goes stale after upgrades.
|
|
102
100
|
"""
|
|
103
101
|
|
|
104
102
|
_COMPLETION_DIR.mkdir(parents=True, exist_ok=True)
|
|
105
103
|
already = _COMPLETION_FILE.is_file()
|
|
106
|
-
_COMPLETION_FILE.write_text(_render_bash_completion(
|
|
104
|
+
_COMPLETION_FILE.write_text(_render_bash_completion(), encoding="utf-8")
|
|
107
105
|
if already:
|
|
108
106
|
print(f"Updated bash completion at {_COMPLETION_FILE}")
|
|
109
107
|
else:
|
|
@@ -266,6 +264,11 @@ def main() -> int:
|
|
|
266
264
|
sys.argv = [sys.argv[0], "compose", "apply", "--output", second, *raw_argv[2:]]
|
|
267
265
|
|
|
268
266
|
parser = _build_parser()
|
|
267
|
+
|
|
268
|
+
# Hidden --_complete for dynamic tab completion (called by the bash shim)
|
|
269
|
+
if raw_argv and raw_argv[0] == "--_complete":
|
|
270
|
+
return _handle_complete(parser, raw_argv[1:])
|
|
271
|
+
|
|
269
272
|
args = parser.parse_args()
|
|
270
273
|
|
|
271
274
|
# ── generate ──────────────────────────────────────────────────────
|
|
@@ -379,10 +382,10 @@ def main() -> int:
|
|
|
379
382
|
if args.command == "completion":
|
|
380
383
|
shell = getattr(args, "completion_shell", None)
|
|
381
384
|
if shell == "bash":
|
|
382
|
-
print(_render_bash_completion(
|
|
385
|
+
print(_render_bash_completion(), end="")
|
|
383
386
|
return 0
|
|
384
387
|
if shell == "install":
|
|
385
|
-
return _install_completion(
|
|
388
|
+
return _install_completion()
|
|
386
389
|
if shell == "uninstall":
|
|
387
390
|
return _uninstall_completion()
|
|
388
391
|
|
|
@@ -9,6 +9,7 @@ the spec, renders all workspace files, scaffolds services, and optionally
|
|
|
9
9
|
initializes a git repository.
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
|
+
import re
|
|
12
13
|
from pathlib import Path
|
|
13
14
|
|
|
14
15
|
from ..models import (
|
|
@@ -28,6 +29,32 @@ from .loader import default_spec, load_spec, save_spec, spec_file_path
|
|
|
28
29
|
# Workspace rendering (orchestration)
|
|
29
30
|
# ---------------------------------------------------------------------------
|
|
30
31
|
|
|
32
|
+
_ENV_KEY_RE = re.compile(r"^([A-Z][A-Z0-9_]*)=", re.MULTILINE)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _merge_new_env_vars(env_path: Path, env_example_content: str) -> None:
|
|
36
|
+
"""Append env vars from .env.example that are missing in .env.
|
|
37
|
+
|
|
38
|
+
Preserves all existing user values. Only adds new keys with their
|
|
39
|
+
default values so services don't crash after adding augments.
|
|
40
|
+
"""
|
|
41
|
+
existing = env_path.read_text(encoding="utf-8")
|
|
42
|
+
existing_keys = set(_ENV_KEY_RE.findall(existing))
|
|
43
|
+
|
|
44
|
+
new_lines: list[str] = []
|
|
45
|
+
for line in env_example_content.splitlines():
|
|
46
|
+
m = _ENV_KEY_RE.match(line)
|
|
47
|
+
if m and m.group(1) not in existing_keys:
|
|
48
|
+
new_lines.append(line)
|
|
49
|
+
|
|
50
|
+
if new_lines:
|
|
51
|
+
# Ensure trailing newline before appending
|
|
52
|
+
if existing and not existing.endswith("\n"):
|
|
53
|
+
existing += "\n"
|
|
54
|
+
existing += "\n# Added by csrd (new augment vars)\n"
|
|
55
|
+
existing += "\n".join(new_lines) + "\n"
|
|
56
|
+
env_path.write_text(existing, encoding="utf-8")
|
|
57
|
+
|
|
31
58
|
|
|
32
59
|
def render_workspace(output_dir: Path, *, git_init: bool = False) -> Path:
|
|
33
60
|
"""Render deterministic workspace files from the current spec.
|
|
@@ -74,10 +101,13 @@ def render_workspace(output_dir: Path, *, git_init: bool = False) -> Path:
|
|
|
74
101
|
|
|
75
102
|
# Seed .env from .env.example only on first render so services can
|
|
76
103
|
# start immediately. On subsequent renders the user may have set
|
|
77
|
-
# strong passwords or API keys — never overwrite
|
|
104
|
+
# strong passwords or API keys — never overwrite existing values.
|
|
105
|
+
# However, new keys added by augments/services must be appended.
|
|
78
106
|
env_path = output_dir / ".env"
|
|
79
107
|
if not env_path.exists():
|
|
80
108
|
env_path.write_text(env_example_content, encoding="utf-8")
|
|
109
|
+
else:
|
|
110
|
+
_merge_new_env_vars(env_path, env_example_content)
|
|
81
111
|
(output_dir / "README.md").write_text(_render_readme(spec), encoding="utf-8")
|
|
82
112
|
(output_dir / ".gitignore").write_text(_render_gitignore(), encoding="utf-8")
|
|
83
113
|
(output_dir / ".dockerignore").write_text(_render_dockerignore(), encoding="utf-8")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/auth-passthrough/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{csrd_utils-0.5.4 → csrd_utils-0.5.6}/src/csrd_utils/templates/augments/jwt-auth-provider/AUTH.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|