Ports generic-scripts-module-v1 into a routed skill: module anatomy, shared loggers/base modules, Taskfile integration, workflows, and pattern decisions. Fixes a latent defect in the loggers example that silenced all logging in the module scaffold: loggers/lib/--index-api.sh now sources --env-vars-reader.sh, and the reader preserves already-exported values so caller overrides still win. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
166 lines
5.3 KiB
Markdown
166 lines
5.3 KiB
Markdown
# Shared Modules — `loggers` and `base`
|
|
|
|
The two foundation modules every other module depends on, and the bootstrap rule that decides
|
|
whether logging works at all.
|
|
|
|
Working implementations are in `assets/loggers/` and `assets/base/`.
|
|
|
|
---
|
|
|
|
## 1. `loggers` — support-only library
|
|
|
|
No `api/` commands, no `Taskfile.yml`. It exists to be sourced.
|
|
|
|
```text
|
|
.scripts/loggers/
|
|
lib/
|
|
--env-vars-reader.sh # level flags + padding strings
|
|
--index-api.sh # sources the reader, then every logger function
|
|
--index.sh
|
|
-debug.sh -error.sh -info.sh -trace.sh -warn.sh
|
|
-empty-line.sh -enable-trailing-new-line.sh -waiting-dot.sh
|
|
```
|
|
|
|
Consume it from any module:
|
|
|
|
```bash
|
|
. ./.scripts/loggers/lib/--index-api.sh
|
|
```
|
|
|
|
Available functions:
|
|
|
|
```bash
|
|
_loggers_info "${FUNCTION_NAME}" "message"
|
|
_loggers_debug "${FUNCTION_NAME}" "message"
|
|
_loggers_warn "${FUNCTION_NAME}" "message"
|
|
_loggers_error "${FUNCTION_NAME}" "message"
|
|
_loggers_trace "${FUNCTION_NAME}" "message"
|
|
_loggers_emptyLine
|
|
```
|
|
|
|
Levels are controlled by environment flags, defaulting to everything except trace:
|
|
|
|
```bash
|
|
LOGGER_IS_ENABLED_ERROR=true
|
|
LOGGER_IS_ENABLED_INFO=true
|
|
LOGGER_IS_ENABLED_WARN=true
|
|
LOGGER_IS_ENABLED_DEBUG=true
|
|
LOGGER_IS_ENABLED_TRACE=false
|
|
```
|
|
|
|
Export any of them before invoking a command to change verbosity for that run:
|
|
|
|
```bash
|
|
LOGGER_IS_ENABLED_DEBUG=false ./.scripts/<module>/api/<command>.sh
|
|
```
|
|
|
|
Rules:
|
|
|
|
1. Do not add `api/` wrappers to `loggers` without a real user-facing requirement.
|
|
2. Keep logger helpers small and side-effect-light.
|
|
3. Log to `stderr` — `stdout` stays clean so command output remains pipeable.
|
|
4. Dependent modules source the logger API directly.
|
|
|
|
---
|
|
|
|
## 2. `base` — shared foundation
|
|
|
|
Has public `api/` wrappers but no `Taskfile.yml`. Provides local environment handling and
|
|
local-storage helpers over `.env` files.
|
|
|
|
```text
|
|
.scripts/base/
|
|
api/
|
|
local-storage-ensure-existance-file-dot-env.sh
|
|
local-storage-read-lines-from-file-dot-env.sh
|
|
local-storage-reset-file-dot-env.sh
|
|
local-storage-save-env-variable-2-file-dot-env.sh
|
|
local-storage-view-file-dot-env.sh
|
|
lib/
|
|
--env-vars-reader.sh --env-vars-validator.sh
|
|
--index-api.sh --index.sh
|
|
-export-env-variable.sh
|
|
-export-env-variables-from-file-dot-env.sh
|
|
-export-env-variables-from-file.sh
|
|
-get-env-variable-key-from-line.sh
|
|
-get-env-variable-value-from-line.sh
|
|
-log-env-vars.sh
|
|
-prompt-for-env-var.sh
|
|
local-storage/
|
|
--index-api.sh
|
|
-ensure-existance-file.sh -ensure-existance-file-dot-env.sh
|
|
-read-lines-from-file.sh -read-lines-from-file-dot-env.sh
|
|
-reset-file.sh -reset-file-dot-env.sh
|
|
-save-env-variable-2-file.sh -save-env-variable-2-file-dot-env.sh
|
|
-view-file.sh -view-file-dot-env.sh
|
|
```
|
|
|
|
### Which entrypoint to source — this matters
|
|
|
|
```bash
|
|
# From another module, when you only need base's shared functions:
|
|
. ./.scripts/base/lib/--index-api.sh
|
|
|
|
# Only from base's own api/ wrappers:
|
|
. ./.scripts/base/lib/--index.sh
|
|
```
|
|
|
|
`base/lib/--index.sh` runs base's reader and validator, and **reads `.env` and
|
|
environment-specific files as a side effect**. Sourcing it from a library function pulls that
|
|
whole environment into an unrelated command — values appear that nobody set, and the failure
|
|
is hard to trace because nothing in the calling module mentions `.env`.
|
|
|
|
`--index-api.sh` defines functions and nothing else, which is why it is the correct dependency
|
|
edge between modules.
|
|
|
|
Rules:
|
|
|
|
1. Prefer `base/lib/--index-api.sh` from other modules.
|
|
2. Nested lib packages such as `lib/local-storage/` carry their own `--index-api.sh` and are
|
|
sourced from the parent's.
|
|
3. Never log secret values — redact tokens, API keys, passwords, kube config, credentials.
|
|
|
|
---
|
|
|
|
## 3. The logging bootstrap rule
|
|
|
|
**A logger function whose level flag is unset prints nothing and returns 0.**
|
|
|
|
Every `_loggers_*` function is guarded by its level flag:
|
|
|
|
```bash
|
|
if [ "${LOGGER_IS_ENABLED_INFO}" = true ]; then ... fi
|
|
```
|
|
|
|
An unset flag is not `true`, so the call is a silent no-op with a success exit code. Nothing
|
|
fails, nothing warns — the command simply produces no output, which reads like a bug in the
|
|
command rather than in its bootstrap.
|
|
|
|
Those flags are exported by `loggers/lib/--env-vars-reader.sh`. For logging to work, that
|
|
reader must have run before any logger call.
|
|
|
|
In the shipped `assets/loggers/`, `--index-api.sh` sources the reader itself, so any module
|
|
that sources the logger API gets working logging with no extra step. The reader uses
|
|
`${VAR:-default}` throughout, so it is safe to source repeatedly and a caller's override
|
|
still wins.
|
|
|
|
**If you are adapting an existing `loggers` module rather than using the shipped one, check
|
|
this first.** A `--index-api.sh` that sources only the logger function files, without the
|
|
reader, silences every module that depends on it — while `bash -n` passes and every command
|
|
exits 0.
|
|
|
|
Quick check in any repository:
|
|
|
|
```bash
|
|
grep -n 'env-vars-reader' .scripts/loggers/lib/--index-api.sh \
|
|
|| echo "WARNING: loggers API does not bootstrap its level flags — logging may be silent"
|
|
```
|
|
|
|
Direct test:
|
|
|
|
```bash
|
|
bash -c '. ./.scripts/loggers/lib/--index-api.sh; _loggers_info "check" "visible?"'
|
|
```
|
|
|
|
No output means the flags were never exported.
|