# iisi-app-core

`iisi-app-core` is a small Python library for `punq`-based applications that provides:

- DI registration decorators (`register` + aliases)
- Recursive package autoloading (`autoload`)
- Feature-flag decorator (`feature_enabled`) with configurable integration points
- AWS-oriented platform handlers:
  - `ApiGatewayEventHandler`
  - `EventBridgeEventHandler`
  - `JwtTokenHandler`
  - `CorsPreflightRestHandler`

## Requirements

- Python `>=3.14,<4`
- `punq` (installed automatically with this package)

## Installation

```bash
pip install iisi-app-core
```

## Quickstart

```python
from punq import Container

from iisi_app_core import autoload, set_default_container, usecase

container = Container()
set_default_container(container)


class IUserRepo:
    ...


@repository
class UserRepo(IUserRepo):
    ...

# Import every module under app.contexts to trigger decorator registration
import app.contexts

autoload(app.contexts)
```

## Feature flags

`feature_enabled` needs a settings interface that can be resolved from the active `punq.Container`.

```python
from iisi_app_core import (
    FeatureDisabledError,
    configure_feature_flags,
    feature_enabled,
)


class SettingsStore:
    def is_feature_enabled(self, name, default=False) -> bool:
        ...


configure_feature_flags(settings_interface=SettingsStore)

@usecase
@feature_enabled("/feature/auth/register_user", message="Registration disabled")
class RegisterUser:
    def __call__(self, command):
        return "ok"
```

### App-specific compatibility configuration

If your app uses dedicated value objects and exceptions, configure them once:

```python
from app.platform.domain.errors import FeatureDisabled
from app.platform.domain.ports import SettingsStore
from app.platform.domain.value_objects import SettingName
from iisi_app_core import configure_feature_flags

configure_feature_flags(
    settings_interface=SettingsStore,
    setting_name_factory=SettingName,
    disabled_exception=FeatureDisabled,
)
```

## API overview

- `register(cls=None, *, interface=None, container=None)`
- `component`, `adapter`, `controller`, `policy`, `repository`, `service`, `usecase`, `seed`
- `set_default_container(container)`, `get_default_container()`, `clear_default_container()`
- `autoload(package)`
- `feature_enabled(feature_path, default=True, message=None, *, settings_interface=None, setting_name_factory=None, disabled_exception=None, container=None)`
- `configure_feature_flags(settings_interface, *, setting_name_factory=None, disabled_exception=None)`
- `clear_feature_flag_config()`
- `FeatureDisabledError`
- `ApiGatewayEventHandler`, `EventBridgeEventHandler`
- `JwtTokenHandler`
- `CorsPreflightRestHandler`, `CorsResponseHandler`

## Migration notes

From old local helpers:

- `app.platform.decorators.register` -> `iisi_app_core.register`
- `app.platform.decorators.usecase` -> `iisi_app_core.usecase` (and other aliases)
- `app.dependency_injection.autoload` -> `iisi_app_core.autoload`
- `app.platform.decorators.feature_enabled` -> `iisi_app_core.feature_enabled`
- `app.platform.handlers.event.ApiGatewayEventHandler` -> `iisi_app_core.ApiGatewayEventHandler`
- `app.platform.handlers.event.EventBridgeEventHandler` -> `iisi_app_core.EventBridgeEventHandler`
- `app.platform.handlers.jwt.JwtTokenHandler` -> `iisi_app_core.JwtTokenHandler`
- `app.platform.handlers.cors.CorsPreflightRestHandler` -> `iisi_app_core.CorsPreflightRestHandler`

Initialize once at app startup:

1. Create/configure your `punq.Container`
2. Call `set_default_container(container)`
3. Call `configure_feature_flags(...)` if you use `feature_enabled`

## Build and publish

Twine reads credentials (including API tokens) from `~/.pypirc` sections `[testpypi]` and `[pypi]`.

Prepare environment:

```bash
python3.14 -m venv .venv
source .venv/bin/activate
pip install pip-tools
pip install -e '.[dev]'
```

Build:

```bash
python -m build
```

Upload to TestPyPI:

```bash
python -m twine upload -r testpypi dist/*
```

Upload to PyPI:

```bash
python -m twine upload -r pypi dist/*
```