@zerotal/arch 1.7.0

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.
Files changed (160) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/LICENSE +21 -0
  3. package/README.md +67 -0
  4. package/api-surface.md +283 -0
  5. package/docs/about.md +676 -0
  6. package/docs/admin/actions.md +183 -0
  7. package/docs/admin/auth.md +89 -0
  8. package/docs/admin/dashboard.md +155 -0
  9. package/docs/admin/extending-ui.md +229 -0
  10. package/docs/admin/extending.md +205 -0
  11. package/docs/admin/forms.md +155 -0
  12. package/docs/admin/index.md +144 -0
  13. package/docs/admin/operations.md +224 -0
  14. package/docs/admin/references.md +174 -0
  15. package/docs/admin/resources.md +132 -0
  16. package/docs/admin/structure.md +158 -0
  17. package/docs/admin/tables.md +185 -0
  18. package/docs/admin/testing.md +138 -0
  19. package/docs/ai.md +373 -0
  20. package/docs/application.md +435 -0
  21. package/docs/arch.md +263 -0
  22. package/docs/assets.md +755 -0
  23. package/docs/audit.md +367 -0
  24. package/docs/authentication.md +1000 -0
  25. package/docs/authorization.md +529 -0
  26. package/docs/broadcasting/channels.md +170 -0
  27. package/docs/broadcasting/client.md +108 -0
  28. package/docs/broadcasting/events.md +190 -0
  29. package/docs/broadcasting/index.md +163 -0
  30. package/docs/broadcasting/references.md +84 -0
  31. package/docs/broadcasting/testing.md +132 -0
  32. package/docs/cache.md +387 -0
  33. package/docs/carbon.md +830 -0
  34. package/docs/changelog.md +465 -0
  35. package/docs/client/auth.md +113 -0
  36. package/docs/client/errors.md +139 -0
  37. package/docs/client/files.md +118 -0
  38. package/docs/client/index.md +128 -0
  39. package/docs/client/references.md +58 -0
  40. package/docs/client/requests.md +131 -0
  41. package/docs/client/resilience.md +141 -0
  42. package/docs/client/testing.md +146 -0
  43. package/docs/commands.md +450 -0
  44. package/docs/components.md +2427 -0
  45. package/docs/config-system.md +258 -0
  46. package/docs/container.md +596 -0
  47. package/docs/context.md +579 -0
  48. package/docs/contributing.md +164 -0
  49. package/docs/controllers.md +354 -0
  50. package/docs/conventions.md +466 -0
  51. package/docs/cookies.md +101 -0
  52. package/docs/csrf.md +206 -0
  53. package/docs/database.md +476 -0
  54. package/docs/deployment.md +434 -0
  55. package/docs/devtools.md +1013 -0
  56. package/docs/email-verification.md +320 -0
  57. package/docs/encryption.md +380 -0
  58. package/docs/errors.md +317 -0
  59. package/docs/events.md +420 -0
  60. package/docs/flow/components.md +846 -0
  61. package/docs/flow/decorators.md +458 -0
  62. package/docs/flow/events.md +420 -0
  63. package/docs/flow/forms.md +551 -0
  64. package/docs/flow/index.md +568 -0
  65. package/docs/flow/layouts.md +793 -0
  66. package/docs/flow/lifecycle.md +336 -0
  67. package/docs/flow/pagination.md +402 -0
  68. package/docs/flow/performance.md +262 -0
  69. package/docs/flow/references.md +317 -0
  70. package/docs/flow/routing.md +550 -0
  71. package/docs/flow/testing.md +447 -0
  72. package/docs/getting-started.md +286 -0
  73. package/docs/health.md +269 -0
  74. package/docs/helpers.md +423 -0
  75. package/docs/i18n.md +414 -0
  76. package/docs/index.md +65 -0
  77. package/docs/inertia/build.md +95 -0
  78. package/docs/inertia/devtools.md +197 -0
  79. package/docs/inertia/index.md +267 -0
  80. package/docs/inertia/middleware.md +81 -0
  81. package/docs/inertia/props.md +507 -0
  82. package/docs/inertia/references.md +144 -0
  83. package/docs/inertia/rendering.md +189 -0
  84. package/docs/inertia/ssr.md +102 -0
  85. package/docs/inspirations.md +257 -0
  86. package/docs/lifecycle.md +331 -0
  87. package/docs/lock.md +454 -0
  88. package/docs/logger.md +517 -0
  89. package/docs/media.md +582 -0
  90. package/docs/middleware.md +509 -0
  91. package/docs/migrations.md +529 -0
  92. package/docs/monitor.md +377 -0
  93. package/docs/notifications.md +848 -0
  94. package/docs/orm/casts.md +365 -0
  95. package/docs/orm/factories.md +231 -0
  96. package/docs/orm/index.md +663 -0
  97. package/docs/orm/lifecycle.md +421 -0
  98. package/docs/orm/queries.md +692 -0
  99. package/docs/orm/relationships.md +440 -0
  100. package/docs/orm/serialization.md +251 -0
  101. package/docs/package-development.md +536 -0
  102. package/docs/pagination.md +340 -0
  103. package/docs/password-reset.md +335 -0
  104. package/docs/providers.md +447 -0
  105. package/docs/query-builder.md +465 -0
  106. package/docs/queue.md +549 -0
  107. package/docs/rate-limiting.md +253 -0
  108. package/docs/responses.md +336 -0
  109. package/docs/roles-and-2fa.md +418 -0
  110. package/docs/routing.md +1008 -0
  111. package/docs/scaffolding.md +335 -0
  112. package/docs/scheduler.md +533 -0
  113. package/docs/seeding.md +229 -0
  114. package/docs/session.md +451 -0
  115. package/docs/social.md +524 -0
  116. package/docs/storage.md +622 -0
  117. package/docs/structure.md +230 -0
  118. package/docs/support-policy.md +114 -0
  119. package/docs/telemetry.md +505 -0
  120. package/docs/tenancy.md +608 -0
  121. package/docs/testing/browser.md +153 -0
  122. package/docs/testing/console.md +130 -0
  123. package/docs/testing/database.md +238 -0
  124. package/docs/testing/flow-browser.md +216 -0
  125. package/docs/testing/http.md +441 -0
  126. package/docs/testing/index.md +240 -0
  127. package/docs/testing/mocking.md +410 -0
  128. package/docs/upgrade.md +192 -0
  129. package/docs/validator.md +549 -0
  130. package/docs/view.md +453 -0
  131. package/package.json +60 -0
  132. package/src/bin/mcp.ts +73 -0
  133. package/src/config.ts +63 -0
  134. package/src/errors.ts +27 -0
  135. package/src/index.ts +56 -0
  136. package/src/install/ArchInstallCommand.ts +189 -0
  137. package/src/install/detect.ts +98 -0
  138. package/src/install/guidelines.ts +290 -0
  139. package/src/install/markers.ts +77 -0
  140. package/src/install/mcpConfig.ts +81 -0
  141. package/src/mcp/index.ts +27 -0
  142. package/src/mcp/jsonrpc.ts +133 -0
  143. package/src/mcp/server.ts +307 -0
  144. package/src/mcp/stdio.ts +111 -0
  145. package/src/mcp/types.ts +146 -0
  146. package/src/probe/ArchProbeCommand.ts +48 -0
  147. package/src/probe/sentinel.ts +13 -0
  148. package/src/probe/topics.ts +291 -0
  149. package/src/provider/ArchProvider.ts +101 -0
  150. package/src/tools/_probe.ts +164 -0
  151. package/src/tools/apiSurface.ts +241 -0
  152. package/src/tools/appInfo.ts +88 -0
  153. package/src/tools/baselines.ts +210 -0
  154. package/src/tools/context.ts +37 -0
  155. package/src/tools/doctor.ts +93 -0
  156. package/src/tools/index.ts +50 -0
  157. package/src/tools/logs.ts +265 -0
  158. package/src/tools/routes.ts +133 -0
  159. package/src/tools/schema.ts +119 -0
  160. package/src/tools/searchDocs.ts +345 -0
@@ -0,0 +1,258 @@
1
+ ---
2
+ title: Configuration
3
+ description: Read deployment state, structure it in typed config files, and access it anywhere at runtime.
4
+ ---
5
+
6
+ # Configuration
7
+
8
+ Zerotal separates three things: deployment state (`env()`), code-level structure (`config/*.ts`), and runtime access (`config()`). You only need all three when your config has genuine structure or conditional logic — simple apps can rely on `env()` alone.
9
+
10
+ ## Mental model
11
+
12
+ Think of configuration as a pipeline from the environment to your code:
13
+
14
+ ```
15
+ .env / process env config/*.ts files anywhere in the app
16
+ ────────────────── ───────────────── ───────────────────
17
+ env("PORT") ─────► AppConfig({ ... }) ─────► config("app.port")
18
+ (raw strings) (typed structure) (typed dot-path read)
19
+ ```
20
+
21
+ - `env()` pulls a single value out of the environment, coercing it to the type of your fallback.
22
+ - A `config/<name>.ts` file assembles those values into a typed object via a package helper (`AppConfig`, `DatabaseConfig`, …).
23
+ - At boot, every `config/*.ts` file is loaded into the config store; `config()` reads from it by dot-path.
24
+
25
+ > **Tip** — Reach for the next layer only when you need it. A value used in exactly one place can stay an `env()` call; promote it to a config file when it gains structure, defaults, or conditional logic.
26
+
27
+ ## The env helper
28
+
29
+ Read environment variables with optional type coercion and a fallback. The fallback's type decides how the raw string is coerced:
30
+
31
+ ```typescript
32
+ // config/app.ts (or anywhere)
33
+ import { env } from "zerotal";
34
+
35
+ const port = env("PORT", 3000); // number fallback → coerced to number
36
+ const debug = env("APP_DEBUG", false); // boolean fallback → "true"/"1" become true
37
+ const appName = env("APP_NAME", "Zerotal App"); // string fallback
38
+ const apiKey = env("API_KEY"); // no fallback → string | undefined
39
+ ```
40
+
41
+ `env()` reads `Bun.env` at call time. Use it in config files, providers, and anywhere you need deployment-time values.
42
+
43
+ > **Note** — When you need a value to be present, use `requireEnv("APP_KEY")` instead — it throws a `ConfigError` at boot if the variable is unset, rather than returning `undefined`.
44
+
45
+ ## Config files
46
+
47
+ Config files live in `config/`. Each file exports a typed object via a package helper:
48
+
49
+ ```typescript
50
+ // config/database.ts
51
+ import { DatabaseConfig } from "@zerotal/orm";
52
+ import { env } from "zerotal";
53
+
54
+ export default DatabaseConfig({
55
+ url: env("DATABASE_URL", "sqlite://./database.sqlite"),
56
+ });
57
+ ```
58
+
59
+ ```typescript
60
+ // config/session.ts
61
+ import { SessionConfig } from "@zerotal/session";
62
+ import { env } from "zerotal";
63
+
64
+ export default SessionConfig({
65
+ driver: env("SESSION_DRIVER", "cookie") as "cookie" | "redis",
66
+ secret: env("SESSION_SECRET", ""),
67
+ lifetime: 86400,
68
+ secure: env("APP_ENV") === "production",
69
+ });
70
+ ```
71
+
72
+ Config helpers (`DatabaseConfig`, `SessionConfig`, etc.) are typed factory functions that give you autocomplete and catch typos. Some — like `AppConfig` — also fill in defaults for fields you omit.
73
+
74
+ ## The config helper
75
+
76
+ Access any loaded config value at runtime:
77
+
78
+ ```typescript
79
+ // in a provider, middleware, or controller
80
+ import { config } from "zerotal";
81
+
82
+ config("app.name"); // get — typed as string (see below)
83
+ config("app.name", "Zerotal"); // get with fallback — fallback must match the path's type
84
+ config.require("app.key"); // throws ConfigError if absent
85
+ config.set("app.debug", true); // override at runtime (useful in tests)
86
+ config.all(); // dump all loaded config as a flat record
87
+ ```
88
+
89
+ Dot-notation maps to the config file path and the key within it. `config('database.url')` reads `url` from `config/database.ts`.
90
+
91
+ > **Note** — `config()` resolves against the booted application's config store. When no app is booted (some test or script contexts), use `config.safe("app.name", "fallback")`, which returns the fallback instead of throwing.
92
+
93
+ ### Typed dot-paths
94
+
95
+ `config()` is type-aware. Each path resolves to the type declared in the owning package's `*ConfigShape`, with autocomplete on the path string:
96
+
97
+ ```typescript
98
+ // in application code
99
+ config("app.name"); // string
100
+ config("app.port"); // number
101
+ config("cache.ttl"); // number
102
+ config("app.throttle.maxAttempts"); // number — nested paths work too
103
+ config.set("app.debug", "yes"); // type error: expected boolean
104
+ ```
105
+
106
+ This works exactly like the container's `ContainerBindings`: there's a `ConfigRegistry` interface that every config-owning package augments by namespace. Core registers `app` and `health`; each package registers its own next to its `*ConfigShape`:
107
+
108
+ ```typescript
109
+ // in a package's config registry declaration
110
+ declare module "zerotal" {
111
+ interface ConfigRegistry {
112
+ cache: CacheConfigShape;
113
+ }
114
+ }
115
+ ```
116
+
117
+ A namespace lights up as typed once its package is imported (which an app does by referencing its `XConfig` factory in `config/<namespace>.ts`). Paths outside any registered namespace still compile — they fall back to the untyped `config(path: string)` overload returning `unknown`, so dynamic access is never blocked.
118
+
119
+ ## Which layer do I use?
120
+
121
+ | Layer | What it does | Reach for it when |
122
+ | ------------- | ---------------------------------------- | ---------------------------------------------------------------------------------------------- |
123
+ | `env()` | Reads deployment state (env vars) | Credentials, URLs, driver names — anything that changes per environment |
124
+ | `config/*.ts` | Assembles code-level structure and logic | Multi-field configs, conditional logic, code references (class constructors, strategy objects) |
125
+ | `config()` | Runtime access to loaded config | In service providers, middleware, and application code that needs cross-cutting config values |
126
+
127
+ The rule of thumb: read raw values with `env()`, shape and default them in a `config/*.ts` file, and read the shaped result anywhere with `config()`.
128
+
129
+ ## How config loads at boot
130
+
131
+ Zerotal loads config **eagerly** when the application boots, before any provider registers:
132
+
133
+ - During `boot()`, the app auto-discovers and imports every `config/*.ts` file, taking each file's `default` export.
134
+ - Those exports are merged into the `ConfigManager` (bound in the container under the `"config"` key) before the provider `onRegister` → `onBooting` → `onBooted` phases run.
135
+ - A file that throws on import (for example, a missing required env var) is skipped during auto-discovery rather than crashing the whole boot.
136
+
137
+ Because every file is loaded as a normal module, a config file may `import` and read other modules at the top level — just avoid circular config imports between files.
138
+
139
+ > **Warning** — Auto-discovery silently skips a config file that throws while importing. If a namespace seems to be missing all its values, check that the file imports cleanly and that its required env vars are set.
140
+
141
+ ## Overriding config in tests
142
+
143
+ ```typescript
144
+ // in a test setup file
145
+ import { config } from "zerotal";
146
+
147
+ beforeEach(() => {
148
+ config.set("mail.driver", "log"); // force log driver in tests
149
+ config.set("queue.driver", "sync");
150
+ });
151
+ ```
152
+
153
+ > **Note** — `config.set()` overrides in-memory only. `.env` is never modified.
154
+
155
+ ## Application-level config
156
+
157
+ Create `config/app.ts` for app-wide settings:
158
+
159
+ ```typescript
160
+ // config/app.ts
161
+ import { env } from "zerotal";
162
+ import { AppConfig } from "zerotal/config";
163
+
164
+ export default AppConfig({
165
+ name: "Example",
166
+ url: env("APP_URL", "http://localhost:3000"),
167
+ key: env("APP_KEY", "changeme-in-production"),
168
+
169
+ cors: {
170
+ origin: env("CORS_ORIGIN", "*"),
171
+ credentials: false,
172
+ },
173
+
174
+ throttle: {
175
+ maxAttempts: 120,
176
+ windowSeconds: 60,
177
+ },
178
+
179
+ secureHeaders: {
180
+ frameOptions: "SAMEORIGIN",
181
+ },
182
+ });
183
+ ```
184
+
185
+ `AppConfig()` fills in sensible defaults for everything you omit (`env`, `key`, `debug`, `url`, `port`, `locale`, `timezone`, `http3`, `health`, `cors`, `throttle`, `secureHeaders`, and the `conventions` auto-discovery settings). Read any value with `config('app.name')`, `config('app.cors.origin')`, etc. The auto-discovery settings live under the `conventions` key — see [Conventions](/docs/conventions).
186
+
187
+ ## Loading config explicitly
188
+
189
+ The CLI entry (`zt.ts`) can load config **synchronously** at the top level and inject it into the app, so it's available before anything boots:
190
+
191
+ ```typescript
192
+ // zt.ts
193
+ import { Application } from "zerotal";
194
+ import { configLoader } from "zerotal/config";
195
+
196
+ const config = configLoader("./config"); // sync — scans config/*.ts, safe at top level
197
+ config.validate(); // runs each file's optional validate() export
198
+
199
+ const app = Application.create({ config }); // …or app.useConfig(config)
200
+ ```
201
+
202
+ `configLoader(dir)` returns a `ConfigLoader` with `all()`, `get("dot.path", fallback)`, `has(path)`, and `validate()`. A config file may export a named `validate(config)` function; `ConfigLoader.validate()` runs them all and throws on the first failure.
203
+
204
+ **One source of truth.** If config was passed to `Application.create({ config })`, a later `useConfig(...)` is **ignored** (create wins) — so the framework-managed `zt.ts`, which always calls `useConfig(...)`, never conflicts with an app that prefers to pass config to `create()`. When neither is used, the app auto-discovers `config/*.ts` at boot as described above.
205
+
206
+ ## Environment files
207
+
208
+ Zerotal automatically loads `.env` in development. For production, set variables in your deployment platform.
209
+
210
+ > **Danger** — Never commit `.env` to version control. It holds real secrets. Commit `.env.example` with safe defaults instead.
211
+
212
+ ```bash
213
+ # .env.example (committed — safe defaults, no secrets)
214
+ APP_NAME=My App
215
+ APP_ENV=local
216
+ APP_KEY=
217
+ DATABASE_URL=sqlite://./database.sqlite
218
+ SESSION_SECRET=
219
+ ```
220
+
221
+ ```bash
222
+ # .env (gitignored — real values)
223
+ APP_KEY=base64:abcdef...
224
+ DATABASE_URL=mysql://user:pass@localhost:3306/mydb
225
+ SESSION_SECRET=super-secret
226
+ ```
227
+
228
+ Use `APP_ENV` to differentiate behaviour:
229
+
230
+ ```typescript
231
+ // in application code
232
+ if (config("app.env") === "production") {
233
+ // production-only logic
234
+ }
235
+ ```
236
+
237
+ ## References
238
+
239
+ | Member | Signature | Description |
240
+ | ----------------------- | ---------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
241
+ | `env` | `env(key: string, fallback?: string \| boolean \| number)` | Read an env var, coercing to the fallback's type; `string \| undefined` with no fallback. |
242
+ | `requireEnv` | `requireEnv(key: string): string` | Read a required env var; throws `ConfigError` if unset. |
243
+ | `config` | `config(path: string, fallback?): value` | Read a config value by dot-path, optionally with a fallback. |
244
+ | `config.require` | `config.require(path: string): value` | Read a config value; throws `ConfigError` if absent or null. |
245
+ | `config.set` | `config.set(path: string, value): void` | Set a config value at runtime (in-memory only). |
246
+ | `config.all` | `config.all(): Record<string, unknown>` | Return all loaded config as a record. |
247
+ | `config.safe` | `config.safe(path: string, fallback): value` | Read without throwing when no app is booted; returns the fallback. |
248
+ | `AppConfig` | `AppConfig(options): AppConfigShape` | Build the `app` namespace config, filling defaults for omitted fields. |
249
+ | `configLoader` | `configLoader(dir = "./config"): ConfigLoader` | Synchronously load a `config/` directory into a `ConfigLoader`. |
250
+ | `ConfigLoader.get` | `get(key: string, fallback?): value` | Dot-path read against the loaded map. |
251
+ | `ConfigLoader.validate` | `validate(): this` | Run each file's optional `validate(config)` export, throwing on failure. |
252
+
253
+ ## Next steps
254
+
255
+ - [Conventions](/docs/conventions) — the auto-discovery settings under the `conventions` key.
256
+ - [Providers](/docs/providers) — where `config()` is most often read.
257
+ - [Application](/docs/application) — how config is injected and loaded at boot.
258
+ - [Deployment](/docs/deployment) — setting env vars in production.