Files
KArtSell.Aegis/tools/scaffold_vertical_slice.py
T
kjh2064 dcd1322d41
ci / backend (push) Failing after 12s
ci / frontend (push) Failing after 19s
ci / static (push) Failing after 45s
Initial commit: Add project files
2026-08-02 05:15:36 +09:00

43 lines
2.3 KiB
Python

#!/usr/bin/env python3
from __future__ import annotations
import argparse, re
from pathlib import Path
def valid_identifier(value: str) -> str:
if not re.fullmatch(r'[A-Za-z][A-Za-z0-9]*', value):
raise argparse.ArgumentTypeError('Use PascalCase alphanumeric identifiers only.')
return value
def render_tree(source: Path, target: Path, tokens: dict[str, str], dry_run: bool) -> list[Path]:
generated: list[Path] = []
for item in source.rglob('*'):
if item.is_dir(): continue
relative = Path(str(item.relative_to(source)).replace('__MODULE__', tokens['MODULE']).replace('__FEATURE__', tokens['FEATURE']))
output = target / relative
content = item.read_text(encoding='utf-8')
for key, value in tokens.items(): content = content.replace(f'__{key}__', value)
if '__' in content: raise RuntimeError(f'Unresolved template token in {item}')
generated.append(output)
if not dry_run:
output.parent.mkdir(parents=True, exist_ok=True)
if output.exists(): raise FileExistsError(f'Refusing to overwrite {output}')
output.write_text(content, encoding='utf-8')
return generated
def main() -> int:
parser=argparse.ArgumentParser(description='Generate a K-ArtSell Vertical Slice backend/frontend packet.')
parser.add_argument('--module', required=True, type=valid_identifier)
parser.add_argument('--feature', required=True, type=valid_identifier)
parser.add_argument('--slice-id', required=True, help='e.g. VS-14')
parser.add_argument('--root', type=Path, default=Path.cwd())
parser.add_argument('--dry-run', action='store_true')
args=parser.parse_args()
template_root=Path(__file__).resolve().parents[1] / 'templates' / 'vertical-slice'
tokens={'MODULE':args.module,'FEATURE':args.feature,'SLICE_ID':args.slice_id}
targets=[(template_root/'backend',args.root/'src'/f'KArtSell.Modules.{args.module}'/'Features'/args.feature),(template_root/'frontend',args.root/'frontend'/'src'/'features'/re.sub(r'(?<!^)(?=[A-Z])','-',args.feature).lower())]
generated=[]
for source,target in targets: generated.extend(render_tree(source,target,tokens,args.dry_run))
for path in generated: print(path)
return 0
if __name__=='__main__': raise SystemExit(main())