@tulipes/cli 0.2.0-rc.2 → 0.3.0-rc.2
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.
- package/dist/agent.d.ts +5 -5
- package/dist/config-check.js +1 -1
- package/dist/env-check.d.ts +5 -3
- package/dist/env-check.js +26 -19
- package/dist/env-check.js.map +1 -1
- package/dist/main.js +83 -19
- package/dist/main.js.map +1 -1
- package/dist/migrate-0.12-env.d.ts +36 -0
- package/dist/migrate-0.12-env.js +250 -0
- package/dist/migrate-0.12-env.js.map +1 -0
- package/dist/migrate-0.12-scaffold.d.ts +1 -0
- package/dist/migrate-0.12-scaffold.js +197 -0
- package/dist/migrate-0.12-scaffold.js.map +1 -0
- package/dist/migrate-0.12.d.ts +47 -0
- package/dist/migrate-0.12.js +210 -0
- package/dist/migrate-0.12.js.map +1 -0
- package/dist/migrate.d.ts +3 -1
- package/dist/migrate.js +44 -5
- package/dist/migrate.js.map +1 -1
- package/dist/new-module.d.ts +7 -0
- package/dist/new-module.js +35 -16
- package/dist/new-module.js.map +1 -1
- package/dist/roles.d.ts +15 -0
- package/dist/roles.js +54 -0
- package/dist/roles.js.map +1 -0
- package/dist/routes.d.ts +7 -2
- package/dist/routes.js +19 -10
- package/dist/routes.js.map +1 -1
- package/dist/spec.d.ts +2 -0
- package/dist/spec.js +13 -11
- package/dist/spec.js.map +1 -1
- package/dist/sync.js +66 -53
- package/dist/sync.js.map +1 -1
- package/dist/update.js +1 -1
- package/dist/update.js.map +1 -1
- package/package.json +4 -4
- package/templates/AGENTS.md +41 -29
- package/templates/app/.envs/.env.development +2 -1
- package/templates/app/.envs/.env.production +2 -2
- package/templates/app/.envs/.env.staging +2 -2
- package/templates/app/README.md +44 -29
- package/templates/app/config/app.config.ts +60 -7
- package/templates/app/docs/agent-manifest.json +8 -681
- package/templates/app/modules/agent/controllers/{agent.controllers.ts → web.agent.controllers.ts} +4 -5
- package/templates/app/modules/agent/routes/{agent.routes.ts → web.agent.routes.ts} +4 -6
- package/templates/app/modules/auth/bootstrap/credentials.bootstrap.ts +20 -12
- package/templates/app/modules/auth/bootstrap/seed-admin.bootstrap.ts +4 -2
- package/templates/app/modules/auth/controllers/{auth.controllers.ts → web.auth.controllers.ts} +1 -1
- package/templates/app/modules/auth/helpers/passport.ts +1 -1
- package/templates/app/modules/auth/helpers/session-cache.ts +3 -3
- package/templates/app/modules/auth/helpers/tokens.ts +3 -5
- package/templates/app/modules/auth/module.acl.ts +31 -9
- package/templates/app/modules/auth/module.config.ts +5 -3
- package/templates/app/modules/auth/package.json +10 -10
- package/templates/app/modules/auth/routes/{auth.routes.ts → web.auth.routes.ts} +15 -10
- package/templates/app/modules/auth/tests/auth.test.ts +1 -1
- package/templates/app/modules/config/controllers/{config.controllers.ts → bo.config.controllers.ts} +3 -2
- package/templates/app/modules/config/helpers/audit.ts +1 -1
- package/templates/app/modules/config/helpers/describe.ts +35 -26
- package/templates/app/modules/config/module.acl.ts +1 -1
- package/templates/app/modules/config/routes/{config.routes.ts → bo.config.routes.ts} +5 -5
- package/templates/app/modules/config/tests/config.test.ts +14 -6
- package/templates/app/modules/core/helpers/cache/index.ts +8 -7
- package/templates/app/modules/core/helpers/lazy.ts +3 -3
- package/templates/app/modules/core/helpers/logger/index.ts +24 -16
- package/templates/app/modules/core/module.config.ts +5 -3
- package/templates/app/modules/core/package.json +46 -19
- package/templates/app/modules/core/routes/core.routes.ts +4 -4
- package/templates/app/modules/hello/agent/hello.agent.ts +18 -14
- package/templates/app/modules/hello/controllers/{hello.controllers.ts → web/hello.controllers.ts} +1 -1
- package/templates/app/modules/hello/controllers/{greetings.controllers.ts → web/hello.greetings.controllers.ts} +4 -8
- package/templates/app/modules/hello/helpers/greetings.ts +14 -0
- package/templates/app/modules/hello/module.acl.ts +12 -7
- package/templates/app/modules/hello/queues/hello.queues.ts +1 -1
- package/templates/app/modules/hello/routes/{greetings.routes.ts → web/hello.greetings.routes.ts} +4 -4
- package/templates/app/modules/hello/routes/{hello.routes.ts → web/hello.routes.ts} +14 -8
- package/templates/app/modules/security/helpers/rate-limit.ts +3 -2
- package/templates/app/modules/security/routes/security.routes.ts +4 -4
- package/templates/app/modules/settings/bootstrap/log-streams.bootstrap.ts +2 -2
- package/templates/app/modules/settings/controllers/{settings.controllers.ts → bo.settings.controllers.ts} +7 -6
- package/templates/app/modules/settings/helpers/log-stream.ts +6 -5
- package/templates/app/modules/settings/routes/{settings.routes.ts → bo.settings.routes.ts} +3 -4
- package/templates/app/modules/settings/tests/settings.test.ts +21 -25
- package/templates/app/modules/users/controllers/{users.controllers.ts → bo.users.controllers.ts} +5 -55
- package/templates/{overlays/no-queues/modules/users/controllers/users.controllers.ts → app/modules/users/controllers/web.users.controllers.ts} +4 -42
- package/templates/app/modules/users/module.acl.ts +4 -4
- package/templates/app/modules/users/queues/users.queues.ts +1 -1
- package/templates/app/modules/users/routes/bo.users.routes.ts +39 -0
- package/templates/app/modules/users/routes/web.users.routes.ts +45 -0
- package/templates/app/nginx/production.conf +1 -1
- package/templates/app/scripts/deploy-nginx.ts +3 -2
- package/templates/app/tests/support.ts +4 -3
- package/templates/claude/skills/tulipes-agent-tool/SKILL.md +49 -34
- package/templates/claude/skills/tulipes-boot-errors/SKILL.md +13 -7
- package/templates/claude/skills/tulipes-config/SKILL.md +6 -4
- package/templates/claude/skills/tulipes-endpoint/SKILL.md +36 -19
- package/templates/claude/skills/tulipes-env-variable/SKILL.md +62 -37
- package/templates/claude/skills/tulipes-i18n/SKILL.md +20 -1
- package/templates/claude/skills/tulipes-module/SKILL.md +10 -5
- package/templates/claude/skills/tulipes-permissions/SKILL.md +123 -35
- package/templates/claude/skills/tulipes-queue/SKILL.md +3 -2
- package/templates/claude/skills/tulipes-settings/SKILL.md +9 -8
- package/templates/claude/skills/tulipes-spec/SKILL.md +12 -2
- package/templates/minimal/config/app.config.ts +13 -3
- package/templates/minimal/modules/agent/routes/{agent.routes.ts → web.agent.routes.ts} +2 -2
- package/templates/minimal/modules/core/module.acl.ts +7 -1
- package/templates/minimal/modules/core/package.json +4 -4
- package/templates/minimal/modules/hello/module.acl.ts +1 -1
- package/templates/minimal/modules/hello/routes/{health.routes.ts → web.hello.health.routes.ts} +1 -1
- package/templates/minimal/modules/hello/routes/{hello.routes.ts → web.hello.routes.ts} +1 -1
- package/templates/overlays/no-queues/modules/hello/controllers/{greetings.controllers.ts → web/hello.greetings.controllers.ts} +1 -1
- package/templates/overlays/no-queues/modules/users/controllers/bo.users.controllers.ts +57 -0
- package/templates/versions.json +8 -8
- package/templates/app/modules/users/routes/users.routes.ts +0 -60
package/templates/app/README.md
CHANGED
|
@@ -10,9 +10,10 @@ pnpm install
|
|
|
10
10
|
pnpm dev # boot the backend process → http://localhost:3000/api/v1/hello
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
Needs mongo and redis running — see `MONGO_URI`
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
Needs mongo and redis running — see `MONGO_URI` (or the `MONGO_HOST`,
|
|
14
|
+
`MONGO_USERNAME`, `MONGO_PASSWORD` and `MONGO_DBNAME` parts) and
|
|
15
|
+
`REDIS_URL` in `.envs/.env.development`. Run `pnpm worker` in a second
|
|
16
|
+
terminal to consume queued jobs.
|
|
16
17
|
|
|
17
18
|
`.envs/` is git-ignored: those files hold working credentials. On a
|
|
18
19
|
fresh clone there is nothing in it, so copy `.env.example` — which is
|
|
@@ -23,7 +24,7 @@ declared variables — and fill it in:
|
|
|
23
24
|
pnpm sync # refresh .env.example and types
|
|
24
25
|
mkdir -p .envs # git does not track empty dirs
|
|
25
26
|
cp .env.example .envs/.env.development
|
|
26
|
-
pnpm check #
|
|
27
|
+
pnpm check # resolve it without booting, and see where each value lands
|
|
27
28
|
```
|
|
28
29
|
|
|
29
30
|
## Verify
|
|
@@ -33,7 +34,8 @@ services: `TEST_MONGO_URI=mongodb://127.0.0.1:27017/tulipes_tests TEST_REDIS_URL
|
|
|
33
34
|
Use test-only data: the suite creates users and sessions. `pnpm spec` writes
|
|
34
35
|
OpenAPI/Postman documents offline, without services or runtime secrets.
|
|
35
36
|
Change the shared API prefix in `config/routes.ts`. Runtime middleware stays
|
|
36
|
-
with endpoints in `routes
|
|
37
|
+
with endpoints in `routes/`, plain functions of the context, named
|
|
38
|
+
scope-first (`routes/web.users.routes.ts`, `routes/bo.users.routes.ts`).
|
|
37
39
|
Staging/production boot rejects development credentials and equal JWT keys.
|
|
38
40
|
Auth, settings and deployment examples are application policy you own.
|
|
39
41
|
|
|
@@ -44,11 +46,11 @@ before writing your own:
|
|
|
44
46
|
|
|
45
47
|
| File | Contract |
|
|
46
48
|
|---|---|
|
|
47
|
-
| `package.json` `tulipes.env` | the module's environment
|
|
49
|
+
| `package.json` `tulipes.env` | the module's environment values, read at `ctx.config.hello.<name>` (hello declares none) |
|
|
48
50
|
| `module.config.ts` | `defineConfig({ schema })`: this module's settings |
|
|
49
|
-
| `module.acl.ts` | permission grants on `hello:*` |
|
|
50
|
-
| `routes/*.routes.ts` | native routers, shared middleware and RAI schemas |
|
|
51
|
-
| `controllers/` | the work; constructed from the context while routes build |
|
|
51
|
+
| `module.acl.ts` | permission grants on `hello:web:*` ids, with prefix wildcards |
|
|
52
|
+
| `routes/web/*.routes.ts` | native routers, shared middleware and RAI schemas; one folder per scope |
|
|
53
|
+
| `controllers/web/` | the work; constructed from the context while routes build |
|
|
52
54
|
| `helpers/` | pure logic, no framework |
|
|
53
55
|
| `i18n/<locale>.json` | this module's strings — the module is the namespace |
|
|
54
56
|
| `sockets/*.sockets.ts` | a claimed Socket.IO namespace | <!-- feature:sockets -->
|
|
@@ -64,7 +66,9 @@ before writing your own:
|
|
|
64
66
|
| `pnpm worker` | run the queue-consumer process (needs a queue first) | <!-- feature:queues -->
|
|
65
67
|
| `pnpm sync` | regenerate `types/tulipes.d.ts` + `.env.example` |
|
|
66
68
|
| `pnpm check` | validate env against every module contract — CI gate |
|
|
67
|
-
| `pnpm tulipes new module <name>` | scaffold a module |
|
|
69
|
+
| `pnpm tulipes new module <name>` | scaffold a module (`--scope bo` for the back office) |
|
|
70
|
+
| `pnpm tulipes routes` | every endpoint and the roles that reach it (`--scope bo` for one surface) |
|
|
71
|
+
| `pnpm tulipes roles` | every role, its description and the grants it holds |
|
|
68
72
|
| `pnpm tulipes update` | upgrade the framework everywhere it is declared |
|
|
69
73
|
|
|
70
74
|
## Authentication
|
|
@@ -75,21 +79,29 @@ becomes the **guest** caller, which is what makes a public endpoint
|
|
|
75
79
|
an ordinary ACL grant instead of a second mechanism:
|
|
76
80
|
|
|
77
81
|
```ts
|
|
78
|
-
acl.allow("guest", "auth:login"); // that is why login is reachable
|
|
82
|
+
acl.allow("guest", "auth:web:login"); // that is why login is reachable
|
|
79
83
|
```
|
|
80
84
|
|
|
81
85
|
Guarding is the RAI itself — its `id` IS the permission, so there is
|
|
82
|
-
no second call to forget.
|
|
83
|
-
|
|
86
|
+
no second call to forget. An id is always `module:scope:resource[:extra]`:
|
|
87
|
+
`users:web:list`, `users:bo:list:deleted`. 401 means "sign in"; 403 means
|
|
88
|
+
"signed in, still not allowed":
|
|
84
89
|
|
|
85
90
|
```ts
|
|
86
91
|
router.get(
|
|
87
92
|
`${base}/invoices`,
|
|
88
|
-
rai({ id: "invoices
|
|
93
|
+
rai({ id: "billing:web:invoices", name: "List invoices" }),
|
|
89
94
|
billing.list(),
|
|
90
95
|
);
|
|
91
96
|
```
|
|
92
97
|
|
|
98
|
+
Roles are defined once in `modules/auth/module.acl.ts`, each with a
|
|
99
|
+
description and any extra the app reads back (`level` here):
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
acl.defineRole("admin", { description: "Runs the back office", level: 2 });
|
|
103
|
+
```
|
|
104
|
+
|
|
93
105
|
A route that declares no RAI would be reachable by guest, so core
|
|
94
106
|
scans the router stack after mounting and refuses to boot when it
|
|
95
107
|
finds one. Run `pnpm tulipes routes` to see every endpoint with the
|
|
@@ -139,8 +151,9 @@ TTL indexes.
|
|
|
139
151
|
## The console
|
|
140
152
|
|
|
141
153
|
`modules/config` is the operator's console: `GET /api/v1/config`
|
|
142
|
-
describes every module — manifest,
|
|
143
|
-
|
|
154
|
+
describes every module — manifest, environment values (config name,
|
|
155
|
+
variable, type and source; a secret's value never), settings with their
|
|
156
|
+
schema, live values
|
|
144
157
|
and stored version, endpoints with the roles that reach them — and
|
|
145
158
|
`PATCH /api/v1/config/:module` changes a module's settings: validated by
|
|
146
159
|
its schema, refused on a stale version, audited (names, never values)
|
|
@@ -149,7 +162,7 @@ writing needs `sysadmin`. Settings live in MongoDB (`settings` and
|
|
|
149
162
|
`settings_history`) because the root `package.json` declares
|
|
150
163
|
`@tulipes/mongoose/settings`; the request pipeline — proxy trust, CORS,
|
|
151
164
|
HSTS, the body limit, the rate limits — is configured from
|
|
152
|
-
`config.security` this way, so none of it is an environment
|
|
165
|
+
`config.security` this way, so none of it is an environment value.
|
|
153
166
|
|
|
154
167
|
## Logging
|
|
155
168
|
|
|
@@ -158,7 +171,7 @@ The logger lives in the core module and is shared by every other one:
|
|
|
158
171
|
```ts
|
|
159
172
|
import { moduleLogger } from "@app/core";
|
|
160
173
|
|
|
161
|
-
const log = moduleLogger(ctx
|
|
174
|
+
const log = moduleLogger(ctx, "billing");
|
|
162
175
|
log.info({ invoiceId }, "invoice sent");
|
|
163
176
|
```
|
|
164
177
|
|
|
@@ -173,9 +186,10 @@ Files carry the process mode — `app-backend.log`, `app-worker.log` —
|
|
|
173
186
|
because backend and worker run at the same time and two processes
|
|
174
187
|
rotating one file will race.
|
|
175
188
|
|
|
176
|
-
The destinations are environment, because the logger exists before
|
|
177
|
-
settings store answers: `LOG_LEVEL`, `LOG_CONSOLE`, `LOG_FILE` and
|
|
178
|
-
`LOG_DIR`, declared in `modules/core/package.json
|
|
189
|
+
The destinations are environment values, because the logger exists before
|
|
190
|
+
the settings store answers: `LOG_LEVEL`, `LOG_CONSOLE`, `LOG_FILE` and
|
|
191
|
+
`LOG_DIR`, declared in `modules/core/package.json` and read as
|
|
192
|
+
`config.core.logLevel`, `logConsole`, `logFile` and `logDir`. The file names and
|
|
179
193
|
the rotation (daily or 20m, whichever trips first; fourteen rotated
|
|
180
194
|
files kept) never needed to differ per deployment, so they are the
|
|
181
195
|
`LOG_FILES` constants in `modules/core/helpers/logger/`. A `sysadmin`
|
|
@@ -268,8 +282,8 @@ redis hold the event loop open, so a script that forgets
|
|
|
268
282
|
`nginx/{development,staging,production}.conf` are templates with
|
|
269
283
|
`{{DOMAIN}}` and `{{PORT}}` placeholders. The deploy script renders
|
|
270
284
|
the one matching `APP_ENV`, using that same environment's
|
|
271
|
-
|
|
272
|
-
disagree:
|
|
285
|
+
`core.publicDomain` setting and the port `config/app.config.ts` wired from
|
|
286
|
+
`PORT`, so template, domain and port can never disagree:
|
|
273
287
|
|
|
274
288
|
```sh
|
|
275
289
|
APP_ENV=production pnpm script scripts/deploy-nginx.ts --dry-run
|
|
@@ -309,12 +323,13 @@ PM2 remembers the environment a process was started with:
|
|
|
309
323
|
|
|
310
324
|
`.envs/` holds one file per mode and is **git-ignored** — those files
|
|
311
325
|
carry working credentials. What is committed is `.env.example`,
|
|
312
|
-
generated by `pnpm sync`, naming every variable any module declares
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
fail on configuration before it fails
|
|
326
|
+
generated by `pnpm sync`, naming every variable any module declares
|
|
327
|
+
and the `config.<module>.<name>` it lands on: a clone copies it into
|
|
328
|
+
`.envs/.env.<mode>` and fills it in. Servers usually skip the file
|
|
329
|
+
entirely and inject variables through the container environment, which
|
|
330
|
+
always wins over it. `pnpm check` resolves the current environment
|
|
331
|
+
without booting, so a deploy can fail on configuration before it fails
|
|
332
|
+
on traffic.
|
|
318
333
|
|
|
319
334
|
PM2 is a devDependency so the scripts work straight after install;
|
|
320
335
|
servers usually install it globally instead (`npm i -g pm2`), in
|
|
@@ -3,24 +3,35 @@ import type { AppConfigFn } from "@tulipes/core/boot";
|
|
|
3
3
|
/**
|
|
4
4
|
* ── The app-wide config seed ──────────────────────────────────────────
|
|
5
5
|
*
|
|
6
|
-
* Runs FIRST in boot phase
|
|
6
|
+
* Runs FIRST in boot phase 4, before any module's settings are loaded, and
|
|
7
7
|
* whatever it returns becomes the base of the global config. Modules read
|
|
8
8
|
* it through `ctx.config.<key>`.
|
|
9
9
|
*
|
|
10
|
+
* It receives `env`: every module's environment values, resolved from the
|
|
11
|
+
* container, `.envs/.env.<APP_ENV>` and the defaults each module declares
|
|
12
|
+
* in its package.json `tulipes.env` — `env.core.port`, `env.auth.adminEmail`
|
|
13
|
+
* — typed by `pnpm sync`. This is the one place the environment is wired
|
|
14
|
+
* to what the framework and the providers read: `server.port` for core,
|
|
15
|
+
* `mongoose.*` for @tulipes/mongoose, `bullmq.redisUrl` for @tulipes/bullmq.
|
|
16
|
+
* Modules never need this wiring: each reads its own values as
|
|
17
|
+
* `ctx.config.<module>.<name>`, beside its settings.
|
|
18
|
+
*
|
|
10
19
|
* Add a key here when two or more modules share a value. Config belonging
|
|
11
20
|
* to ONE feature goes in that module's `module.config.ts` instead, where
|
|
12
21
|
* `pnpm sync` types it for you — that is where `users.maxSessions` and
|
|
13
22
|
* `users.signupMode` live. A value that differs per deployment belongs in
|
|
14
|
-
* neither: declare it in a module's
|
|
15
|
-
* `
|
|
23
|
+
* neither: declare it under `tulipes.env` in a module's package.json and
|
|
24
|
+
* read it as `ctx.config.<module>.<name>`, the way MONGO_URI and REDIS_URL
|
|
25
|
+
* are declared by the core module.
|
|
16
26
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
27
|
+
* Under inspection (`tulipes routes`, `tulipes spec`) a value that is
|
|
28
|
+
* missing or invalid is `undefined` rather than an error, so this file
|
|
29
|
+
* only wires values and never requires one.
|
|
19
30
|
*/
|
|
20
31
|
|
|
21
32
|
// `satisfies` (not a type annotation) so TypeScript keeps the exact shape
|
|
22
33
|
// of this object for the augmentation at the bottom of the file.
|
|
23
|
-
const appConfig = (() => ({
|
|
34
|
+
const appConfig = ((env) => ({
|
|
24
35
|
app: {
|
|
25
36
|
name: "tulipes-example",
|
|
26
37
|
},
|
|
@@ -34,6 +45,31 @@ const appConfig = (() => ({
|
|
|
34
45
|
prefix: "/api/v1",
|
|
35
46
|
},
|
|
36
47
|
|
|
48
|
+
/** What core listens on. */
|
|
49
|
+
server: {
|
|
50
|
+
port: env.core.port,
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* How @tulipes/mongoose reaches MongoDB. A full MONGO_URI wins — it is the
|
|
55
|
+
* only way to name a replica set, an Atlas cluster or driver options;
|
|
56
|
+
* otherwise the host, credentials and database name are handed to the
|
|
57
|
+
* driver separately, so nothing is URL-encoded by hand.
|
|
58
|
+
*/
|
|
59
|
+
mongoose: env.core.mongodbUri
|
|
60
|
+
? { uri: env.core.mongodbUri }
|
|
61
|
+
: {
|
|
62
|
+
uri: env.core.mongodbHost,
|
|
63
|
+
user: env.core.mongodbUsername,
|
|
64
|
+
pass: env.core.mongodbPassword,
|
|
65
|
+
dbName: env.core.mongodbDbName,
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
/** How @tulipes/bullmq reaches Redis. */
|
|
69
|
+
bullmq: {
|
|
70
|
+
redisUrl: env.core.redisUrl,
|
|
71
|
+
},
|
|
72
|
+
|
|
37
73
|
/**
|
|
38
74
|
* The languages this app speaks. Every module owns its own strings in
|
|
39
75
|
* `modules/<name>/i18n/<locale>.json` — the module is the namespace —
|
|
@@ -50,6 +86,21 @@ const appConfig = (() => ({
|
|
|
50
86
|
supportedLocales: ["en", "fr"],
|
|
51
87
|
},
|
|
52
88
|
|
|
89
|
+
/**
|
|
90
|
+
* How instants are read. Dates are stored and returned as UTC; a zone is
|
|
91
|
+
* what "today", "02:00" and a timestamp in an email mean. A request picks
|
|
92
|
+
* its own with `?tz=Europe/Paris` or an X-Timezone header (narrowed to
|
|
93
|
+
* `supported` when you list it), and handlers read it as `req.timezone`
|
|
94
|
+
* with helpers on `req.time`; code with no request uses `ctx.time`.
|
|
95
|
+
*
|
|
96
|
+
* `default` is also the zone of cron patterns given to `ctx.queues`, and
|
|
97
|
+
* — unless `applyToProcess: false` — the process zone, so log times,
|
|
98
|
+
* daily log rotation and `Date#getHours()` agree with it.
|
|
99
|
+
*/
|
|
100
|
+
timezone: {
|
|
101
|
+
default: "UTC",
|
|
102
|
+
},
|
|
103
|
+
|
|
53
104
|
/**
|
|
54
105
|
* List-endpoint defaults, so every module paginates identically and no
|
|
55
106
|
* caller can ask for ten thousand rows. → modules/users/routes
|
|
@@ -67,7 +118,9 @@ export default appConfig;
|
|
|
67
118
|
* number, not `unknown`. `pnpm sync` does this automatically for
|
|
68
119
|
* module.config.ts factories; the app-level seed types itself here.
|
|
69
120
|
* Partial because the config object is empty until this factory runs.
|
|
121
|
+
* `server`, `mongoose` and `bullmq` are left out: core and the providers
|
|
122
|
+
* already type the keys they read.
|
|
70
123
|
*/
|
|
71
124
|
declare module "@tulipes/core/config" {
|
|
72
|
-
interface GlobalConfig extends Partial<ReturnType<typeof appConfig>> {}
|
|
125
|
+
interface GlobalConfig extends Partial<Omit<ReturnType<typeof appConfig>, "server" | "mongoose" | "bullmq">> {}
|
|
73
126
|
}
|