@browserlessapi/inferlo 0.6.0 → 0.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.
- package/README.md +7 -4
- package/dist/ai/ai-sdk.d.ts +48 -0
- package/dist/ai/ai-sdk.js +235 -0
- package/dist/ai/ai-sdk.js.map +1 -0
- package/dist/ai/index.d.ts +37 -3
- package/dist/ai/index.js +96 -7
- package/dist/ai/index.js.map +1 -1
- package/dist/ai/public.d.ts +5 -1
- package/dist/ai/public.js +2 -0
- package/dist/ai/public.js.map +1 -1
- package/dist/ai/ui.d.ts +47 -0
- package/dist/ai/ui.js +33 -0
- package/dist/ai/ui.js.map +1 -0
- package/dist/app.d.ts +31 -4
- package/dist/app.js +106 -29
- package/dist/app.js.map +1 -1
- package/dist/astro.d.ts +60 -0
- package/dist/astro.js +68 -0
- package/dist/astro.js.map +1 -0
- package/dist/audit.d.ts +8 -1
- package/dist/audit.js +9 -2
- package/dist/audit.js.map +1 -1
- package/dist/auth.d.ts +1 -0
- package/dist/auth.js +1 -0
- package/dist/auth.js.map +1 -1
- package/dist/azure.d.ts +66 -0
- package/dist/azure.js +119 -0
- package/dist/azure.js.map +1 -0
- package/dist/cache.d.ts +13 -9
- package/dist/cache.js +11 -9
- package/dist/cache.js.map +1 -1
- package/dist/cli/main.js +4 -4
- package/dist/cli/main.js.map +1 -1
- package/dist/client-ip.d.ts +36 -1
- package/dist/client-ip.js +80 -1
- package/dist/client-ip.js.map +1 -1
- package/dist/db/memory.js +2 -1
- package/dist/db/memory.js.map +1 -1
- package/dist/db/postgres.js +4 -1
- package/dist/db/postgres.js.map +1 -1
- package/dist/db/table.d.ts +37 -5
- package/dist/db/table.js +96 -15
- package/dist/db/table.js.map +1 -1
- package/dist/db/types.d.ts +2 -0
- package/dist/describe.d.ts +15 -4
- package/dist/describe.js +10 -2
- package/dist/describe.js.map +1 -1
- package/dist/events.d.ts +134 -0
- package/dist/events.js +196 -0
- package/dist/events.js.map +1 -0
- package/dist/index.d.ts +12 -5
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/jobs.d.ts +50 -10
- package/dist/jobs.js +66 -13
- package/dist/jobs.js.map +1 -1
- package/dist/langchain.d.ts +58 -0
- package/dist/langchain.js +220 -0
- package/dist/langchain.js.map +1 -0
- package/dist/model.d.ts +23 -6
- package/dist/model.js +35 -6
- package/dist/model.js.map +1 -1
- package/dist/rate-limit.d.ts +5 -3
- package/dist/rate-limit.js +3 -3
- package/dist/rate-limit.js.map +1 -1
- package/dist/redis-events.d.ts +27 -0
- package/dist/redis-events.js +163 -0
- package/dist/redis-events.js.map +1 -0
- package/dist/redis-jobs.d.ts +24 -0
- package/dist/redis-jobs.js +203 -0
- package/dist/redis-jobs.js.map +1 -0
- package/dist/redis.d.ts +30 -0
- package/dist/redis.js +106 -0
- package/dist/redis.js.map +1 -0
- package/dist/response-body.d.ts +6 -0
- package/dist/response-body.js +7 -0
- package/dist/response-body.js.map +1 -0
- package/dist/route.d.ts +14 -1
- package/dist/route.js.map +1 -1
- package/dist/schema.d.ts +2 -2
- package/dist/serve.d.ts +6 -1
- package/dist/serve.js +64 -7
- package/dist/serve.js.map +1 -1
- package/dist/service-client.d.ts +91 -0
- package/dist/service-client.js +177 -0
- package/dist/service-client.js.map +1 -0
- package/dist/sessions.d.ts +2 -0
- package/dist/sessions.js +1 -0
- package/dist/sessions.js.map +1 -1
- package/dist/tracing.d.ts +7 -3
- package/dist/tracing.js +8 -2
- package/dist/tracing.js.map +1 -1
- package/llms.txt +1 -0
- package/package.json +36 -4
- package/templates/app/AGENTS.md +5 -3
package/dist/tracing.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracing.js","sourceRoot":"","sources":["../src/tracing.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAwC3C,4FAA4F;AAC5F,MAAM,WAAW,GAAG,CAAC,CAAC;AACtB,MAAM,aAAa,GAAG,CAAC,CAAC;AAExB,0FAA0F;AAC1F,MAAM,YAAY,GAAG;IACnB,GAAG,CAAC,OAAgB,EAAE,GAAW;QAC/B,OAAO,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC;IACvC,CAAC;IACD,IAAI,CAAC,OAAgB;QACnB,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7B,CAAC;CACF,CAAC;AAEF,MAAM,aAAa,GAAG,kCAAkC,CAAC;AAOzD,oGAAoG;AACpG,MAAM,UAAU,YAAY,CAAC,MAAe,EAAE,
|
|
1
|
+
{"version":3,"file":"tracing.js","sourceRoot":"","sources":["../src/tracing.ts"],"names":[],"mappings":"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"}
|
package/llms.txt
CHANGED
|
@@ -25,6 +25,7 @@ Key rules: routes are private unless `auth: "public"`; validate input with `t.*`
|
|
|
25
25
|
- [Security](https://github.com/BrowserlessAPI/Inferlo/blob/main/docs/security.md): secure defaults and security headers (createApp({ secureHeaders }))
|
|
26
26
|
- [Observability](https://github.com/BrowserlessAPI/Inferlo/blob/main/docs/observability.md): request ids (X-Request-Id, ctx.requestId), request logs and JSON logs with createApp({ logging: { format: "json", requests: true } }), your own logger, Prometheus metrics with createApp({ metrics: { token } })
|
|
27
27
|
- [Deployment](https://github.com/BrowserlessAPI/Inferlo/blob/main/docs/deploy.md): Node, Bun, Deno, edge, health and readiness endpoints, graceful shutdown with app.close()
|
|
28
|
+
- [Performance](https://github.com/BrowserlessAPI/Inferlo/blob/main/docs/performance.md): reproducible throughput and latency benchmark against Fastify, Hono, Express and NestJS (npm run bench:perf) and the latest results
|
|
28
29
|
- [Support policy](https://github.com/BrowserlessAPI/Inferlo/blob/main/docs/support.md): semantic versioning, which versions get fixes, LTS after 1.0, deprecation rules and supported runtime, database and framework versions
|
|
29
30
|
- [Error codes](https://github.com/BrowserlessAPI/Inferlo/blob/main/docs/errors.md): every ILxxxx code with its fix
|
|
30
31
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@browserlessapi/inferlo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "The enterprise-ready TypeScript backend framework, with AI models built in: routing, validation, PostgreSQL and migrations, auth, rate limiting, jobs, OpenAPI and MCP, plus Anthropic, OpenAI, Gemini, Ollama and OpenAI-compatible models.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -43,6 +43,14 @@
|
|
|
43
43
|
"types": "./dist/ai/public.d.ts",
|
|
44
44
|
"default": "./dist/ai/public.js"
|
|
45
45
|
},
|
|
46
|
+
"./astro": {
|
|
47
|
+
"types": "./dist/astro.d.ts",
|
|
48
|
+
"default": "./dist/astro.js"
|
|
49
|
+
},
|
|
50
|
+
"./azure": {
|
|
51
|
+
"types": "./dist/azure.d.ts",
|
|
52
|
+
"default": "./dist/azure.js"
|
|
53
|
+
},
|
|
46
54
|
"./elysia": {
|
|
47
55
|
"types": "./dist/elysia.d.ts",
|
|
48
56
|
"default": "./dist/elysia.js"
|
|
@@ -106,6 +114,10 @@
|
|
|
106
114
|
"./testing": {
|
|
107
115
|
"types": "./dist/testing.d.ts",
|
|
108
116
|
"default": "./dist/testing.js"
|
|
117
|
+
},
|
|
118
|
+
"./langchain": {
|
|
119
|
+
"types": "./dist/langchain.d.ts",
|
|
120
|
+
"default": "./dist/langchain.js"
|
|
109
121
|
}
|
|
110
122
|
},
|
|
111
123
|
"bin": {
|
|
@@ -121,18 +133,25 @@
|
|
|
121
133
|
"scripts": {
|
|
122
134
|
"build": "rm -rf dist && tsc -p tsconfig.build.json && chmod +x dist/cli/main.js",
|
|
123
135
|
"prepare": "npm run build",
|
|
124
|
-
"typecheck": "tsc --noEmit && tsc --noEmit -p examples/helpdesk && tsc --noEmit -p examples/with-hono && tsc --noEmit -p examples/with-express && tsc --noEmit -p examples/with-fastify && tsc --noEmit -p examples/with-elysia && tsc --noEmit -p examples/with-nestjs && tsc --noEmit -p examples/with-trpc && tsc --noEmit -p examples/with-adonisjs && tsc --noEmit -p examples/with-tsed && tsc --noEmit -p examples/with-encore && tsc --noEmit -p examples/with-koa && tsc --noEmit -p examples/with-nextjs && tsc --noEmit -p examples/with-nitro && tsc --noEmit -p examples/with-sveltekit && tsc --noEmit -p examples/with-react-router && tsc --noEmit -p examples/with-lambda && tsc --noEmit -p examples/with-hapi",
|
|
136
|
+
"typecheck": "tsc --noEmit && tsc --noEmit -p examples/helpdesk && tsc --noEmit -p examples/with-hono && tsc --noEmit -p examples/with-express && tsc --noEmit -p examples/with-fastify && tsc --noEmit -p examples/with-elysia && tsc --noEmit -p examples/with-nestjs && tsc --noEmit -p examples/with-trpc && tsc --noEmit -p examples/with-adonisjs && tsc --noEmit -p examples/with-tsed && tsc --noEmit -p examples/with-encore && tsc --noEmit -p examples/with-koa && tsc --noEmit -p examples/with-nextjs && tsc --noEmit -p examples/with-nitro && tsc --noEmit -p examples/with-sveltekit && tsc --noEmit -p examples/with-react-router && tsc --noEmit -p examples/with-lambda && tsc --noEmit -p examples/with-hapi && tsc --noEmit -p examples/with-azure && tsc --noEmit -p examples/with-cloud-run-functions && tsc --noEmit -p examples/with-cloudflare-workers && tsc --noEmit -p examples/with-vercel && tsc --noEmit -p examples/with-netlify && tsc --noEmit -p examples/with-astro && tsc --noEmit -p examples/with-drizzle",
|
|
125
137
|
"test": "node --test --test-reporter=spec \"test/**/*.test.ts\" \"examples/*/test/*.test.ts\"",
|
|
126
138
|
"test:bun": "bun test test/",
|
|
139
|
+
"test:deno": "deno test -A --no-check --ignore=test/tsed.test.ts test/ && deno test -A --no-check --ignore=examples/with-tsed examples/ && deno test -A --no-check --unsafe-proto test/tsed.test.ts examples/with-tsed/",
|
|
127
140
|
"llms": "node scripts/build-llms.ts",
|
|
128
141
|
"check": "npm run typecheck && npm test && node scripts/build-llms.ts --check",
|
|
129
|
-
"bench": "node bench/run.ts"
|
|
142
|
+
"bench": "node bench/run.ts",
|
|
143
|
+
"bench:perf": "node bench/perf/run.ts",
|
|
144
|
+
"bench:perf:check": "node bench/perf/check.ts"
|
|
130
145
|
},
|
|
131
146
|
"peerDependencies": {
|
|
147
|
+
"@langchain/core": ">=0.3.0",
|
|
132
148
|
"@opentelemetry/api": ">=1.3.0",
|
|
133
149
|
"pg": ">=8"
|
|
134
150
|
},
|
|
135
151
|
"peerDependenciesMeta": {
|
|
152
|
+
"@langchain/core": {
|
|
153
|
+
"optional": true
|
|
154
|
+
},
|
|
136
155
|
"@opentelemetry/api": {
|
|
137
156
|
"optional": true
|
|
138
157
|
},
|
|
@@ -142,7 +161,12 @@
|
|
|
142
161
|
},
|
|
143
162
|
"devDependencies": {
|
|
144
163
|
"@adonisjs/core": "^6.21.0",
|
|
164
|
+
"@ai-sdk/openai-compatible": "^3.0.85",
|
|
165
|
+
"@azure/functions": "^4.17.0",
|
|
166
|
+
"@google-cloud/functions-framework": "^5.0.5",
|
|
145
167
|
"@hapi/hapi": "^21.4.13",
|
|
168
|
+
"@hono/node-server": "^2.1.6",
|
|
169
|
+
"@langchain/core": "^1.3.5",
|
|
146
170
|
"@nestjs/common": "^12.3.3",
|
|
147
171
|
"@nestjs/core": "^12.3.3",
|
|
148
172
|
"@nestjs/platform-express": "^12.3.3",
|
|
@@ -155,10 +179,15 @@
|
|
|
155
179
|
"@tsed/platform-http": "^8.45.0",
|
|
156
180
|
"@tsed/platform-params": "^8.45.0",
|
|
157
181
|
"@tsed/schema": "^8.45.0",
|
|
182
|
+
"@types/autocannon": "^7.12.7",
|
|
158
183
|
"@types/express": "^5.0.6",
|
|
159
184
|
"@types/koa": "^3.0.3",
|
|
160
185
|
"@types/node": "^22.18.0",
|
|
161
186
|
"@types/pg": "^8.15.0",
|
|
187
|
+
"ai": "^7.0.163",
|
|
188
|
+
"astro": "^7.4.7",
|
|
189
|
+
"autocannon": "^8.0.0",
|
|
190
|
+
"drizzle-orm": "^0.45.4",
|
|
162
191
|
"elysia": "^1.4.30",
|
|
163
192
|
"encore.dev": "^1.58.8",
|
|
164
193
|
"express": "^5.3.0",
|
|
@@ -166,13 +195,16 @@
|
|
|
166
195
|
"h3": "^2.0.8",
|
|
167
196
|
"hono": "^4.13.16",
|
|
168
197
|
"koa": "^3.3.0",
|
|
198
|
+
"miniflare": "^4.20260730.0",
|
|
169
199
|
"next": "^16.4.5",
|
|
170
200
|
"pg": "^8.16.0",
|
|
171
201
|
"react": "^19.3.1",
|
|
172
202
|
"react-router": "^8.5.1",
|
|
203
|
+
"redis": "^6.3.1",
|
|
173
204
|
"reflect-metadata": "^0.2.2",
|
|
174
205
|
"rxjs": "^7.8.2",
|
|
175
|
-
"typescript": "^5.9.3"
|
|
206
|
+
"typescript": "^5.9.3",
|
|
207
|
+
"zod": "^4.6.7"
|
|
176
208
|
},
|
|
177
209
|
"publishConfig": {
|
|
178
210
|
"access": "public"
|
package/templates/app/AGENTS.md
CHANGED
|
@@ -34,20 +34,22 @@ Do not finish until `inferlo check` passes.
|
|
|
34
34
|
3. **Validate every input with a schema.** `body`, `query` and `params` options. Reuse model schemas: `Ticket.pick("title", "body")`, `Ticket.omit("ownerId")`, `.partial()` for PATCH.
|
|
35
35
|
4. **Check ownership.** Fetch with `db.x.get(id)` (throws 404) and compare `ownerId` to `user.id`; throw `notFound()` when it does not match, so other users' ids are not revealed. When more than one rule decides access (owners, admins, teams), define named permissions once in `src/permissions.ts` with `export const access = permissions({ "notes.update": ({ user, note }) => note.ownerId === user.id || (user.roles ?? []).includes("admin") })`, pass `permissions: access` to `createApp`, and call `await access.authorize("notes.update", { user, note })` in routes and jobs (403 IL3004 when denied). Permissions that need only the user go on the route: `{ permission: "reports.view" }`; add `permissions: typeof access` to `Register` (with `import type`) so permission names are type-checked. When changes must be on record (who changed what), add `AuditLog` to the models and call `await audit("notes.update", { model: "notes", before: note, after: updated })` after the change, in routes and jobs (jobs pass `userId`).
|
|
36
36
|
5. **Related rows:** a `t.ref` field named `<name>Id` is a relation: `db.notes.findMany({ include: { owner: true } })` adds `note.owner` with one extra query, and `db.users.findMany({ include: { notes: true } })` adds `user.notes` (the rows that point to each user). Never load related rows in a loop. For lists clients page through, use `db.notes.paginate({ where, orderBy: { createdAt: "desc" }, cursor: query.cursor, limit: query.limit })`, which returns `{ items, nextCursor }`.
|
|
37
|
-
6. **Never write raw SQL with string concatenation.** Use the table methods. If you really need SQL, use `db.$sql(text, params)` with `$1` placeholders.
|
|
37
|
+
6. **Never write raw SQL with string concatenation.** Use the table methods. If you really need SQL, use `db.$sql(text, params)` with `$1` placeholders. Code that takes a pg client (Drizzle, plain `pg`) gets it from `db.$pgClient()`, and inside `db.$transaction(async (tx) => ...)` from `tx.$pgClient()`, so it runs in the same transaction.
|
|
38
38
|
7. **Model ids, timestamps:** every model already has `id`, `createdAt`, `updatedAt`. Never define them or send them as input.
|
|
39
39
|
8. **New field?** Add it to the model in `src/models.ts`, then run `npx inferlo db push` in development, or `npx inferlo db migrate <name>` to write a migration file for production (applied with `npx inferlo db migrate --apply`). Use `.optional()` or `.default()` for new fields on existing tables. Never edit `migrations/snapshot.json`, and never edit a migration file that has been applied (`--apply` warns with IL4018 and does not run the change): put changes in a new migration. Removing a model or field needs `npx inferlo db migrate <name> --allow-drop` (it deletes that data); never use it for a rename. Changing a field's type or default, making it required or optional, or changing an enum's values needs `--allow-change`; give a newly required field a `.default()` so existing NULL rows get a value, and before removing an enum value add an `UPDATE` in the new migration file (before its `ADD CONSTRAINT`) that moves rows off it (IL4021).
|
|
40
40
|
9. **New resource?** `npx inferlo add resource <plural_name>` generates the model and CRUD routes. Then edit them.
|
|
41
|
-
10. **AI calls** use aliases from `src/app.ts` (`model: "fast"`), never hard-coded provider model ids in routes. Use `output: schema` for structured data and `for: user.id` so usage is tracked per user. To let the model act, pass routes as tools: `ai.generate({ prompt, tools: [createNote, getNote], for: user.id })`. Each tool call runs as the current user with that route's auth and validation. For work that is not a route (an external API, a calculation), make a function tool: `tool("getWeather", { description, input: t.object({ ... }) }).handle(async ({ input }) => ...)`. To send images: `ai.generate({ prompt, images: [{ url }] })` or `[{ base64, mediaType: "image/png" }]`. Give routes that call AI models, send email or check passwords a `rateLimit: { max, per, by }` (IL2005 is the 429 it returns).
|
|
41
|
+
10. **AI calls** use aliases from `src/app.ts` (`model: "fast"`), never hard-coded provider model ids in routes. Use `output: schema` for structured data and `for: user.id` so usage is tracked per user. A provider without a built-in adapter (Mistral, Bedrock, Azure, Vertex, Groq, ...) is added through its Vercel AI SDK package: `providers: { mistral: aiSdk(createMistral({ apiKey: settings.MISTRAL_API_KEY })) }`, then aliases name `"mistral:<model id>"`. When the app uses LangChain agents, give them Inferlo's model and tools: `toLangChainModel(ai, { model: "fast", for: user.id })` and `toLangChainTools([getWeather, createNote], { ai })` from `@browserlessapi/inferlo/langchain`, never a second set of provider keys. To let the model act, pass routes as tools: `ai.generate({ prompt, tools: [createNote, getNote], for: user.id })`. Each tool call runs as the current user with that route's auth and validation. For work that is not a route (an external API, a calculation), make a function tool: `tool("getWeather", { description, input: t.object({ ... }) }).handle(async ({ input }) => ...)`. To send images: `ai.generate({ prompt, images: [{ url }] })` or `[{ base64, mediaType: "image/png" }]`. Give routes that call AI models, send email or check passwords a `rateLimit: { max, per, by }` (IL2005 is the 429 it returns). Streaming to a chat UI built with the Vercel AI SDK (`useChat`): `route.post("/chat", { body: uiChatBody }).handle(({ body, ai, user }) => ai.stream({ model: "fast", messages: fromUIMessages(body.messages), for: user.id }).toResponse({ format: "ai-sdk" }))`.
|
|
42
42
|
11. **Errors:** throw `notFound()`, `forbidden()`, `badRequest()` or `httpError(status, message)`. Every Inferlo error has a code (ILxxxx), a fix and a docs link: read the fix before changing code.
|
|
43
43
|
12. **Imports:** relative imports end in `.ts` (`import { Note } from "../models.ts"`).
|
|
44
44
|
13. **Configuration:** read environment variables only through `settings` from `src/config.ts`. A new variable is a new field in its `t.object({ ... })` schema (`.default(...)` or `.optional()` unless the app cannot start without it), and API keys, passwords and connection URLs go in `secrets` so they are never logged. Never read `process.env` in routes.
|
|
45
45
|
14. **Expose to AI agents:** add `tool: true` to a route to make it an MCP tool at `/mcp`. Same auth applies.
|
|
46
|
-
15. **Slow work after the response** (email, slow AI calls) is a background job: `export const x = job("send-email", { input: t.object({ ... }) }).handle(async ({ input, db, ai }) => { ... })` in `src/jobs.ts`, registered with `createApp({ jobs: [jobs] })`, queued with `await ctx.jobs.enqueue(x, { ... })`. Pass ids in the input, not rows. In tests, run queued jobs with `await app.jobs.runDue()`. Jobs run in the server process (`app.jobs.start()` in `src/server.ts`); with `createApp({ jobQueue: { store: "database" } })` they are kept in Postgres and `npm run worker` (`inferlo worker`) runs them in separate processes. Scheduled work is a cron next to its job: `export const nightly = cron("0 3 * * *", cleanupJob)` (UTC; the job's input must be `t.object({})`).
|
|
46
|
+
15. **Slow work after the response** (email, slow AI calls) is a background job: `export const x = job("send-email", { input: t.object({ ... }) }).handle(async ({ input, db, ai }) => { ... })` in `src/jobs.ts`, registered with `createApp({ jobs: [jobs] })`, queued with `await ctx.jobs.enqueue(x, { ... })`. Pass ids in the input, not rows. In tests, run queued jobs with `await app.jobs.runDue()`. Jobs run in the server process (`app.jobs.start()` in `src/server.ts`); with `createApp({ jobQueue: { store: "database" } })` they are kept in Postgres (or with `createApp({ redis, jobQueue: { store: "redis" } })` in Redis) and `npm run worker` (`inferlo worker`) runs them in separate processes. Scheduled work is a cron next to its job: `export const nightly = cron("0 3 * * *", cleanupJob)` (UTC; the job's input must be `t.object({})`). When other parts of the app react to something that happened, publish an event instead of enqueuing each job: `export const orderPaid = event("order.paid", { payload: t.object({ ... }) })` in `src/events.ts`, jobs subscribed with `on(orderPaid, sendReceipt)` (the job's input is `orderPaid.payload`) in `src/jobs.ts`, and `await ctx.events.publish(orderPaid, { ... })` after the change is saved. To send events to other services, give each service a `name` and set `createApp({ name, redis, events: { transport: "redis" } })`; subscribers use the same `on(event, job)`.
|
|
47
47
|
16. **Security headers and health:** every response already gets security headers (CSP, HSTS over HTTPS, nosniff, frame and referrer policies) and `GET /health` and `GET /ready` are built in (`health: true` in `src/app.ts`). Change a header with `createApp({ secureHeaders: { "Content-Security-Policy": "..." } })` instead of setting it in every route, never turn them all off without a proxy that adds them, and never add your own `/health` route. On SIGTERM, `src/server.ts` calls `app.close()`, which finishes in-flight requests and jobs first. Prometheus metrics (`GET /metrics`: requests, jobs, AI calls, tokens and cost) are served when `METRICS_TOKEN` is set; never add your own `/metrics` route.
|
|
48
48
|
17. **Large apps: feature modules.** When the app grows to several features, group each feature's models, routes and jobs in `src/<feature>/module.ts` with `export const billing = module("billing", { imports: [users], models: [...], routes: [routes], jobs: [jobs], provides: { createInvoice } })` and register it with `createApp({ modules: [users, billing] })`. A module that uses another module's models or `provides` lists it in `imports` (IL6023 and IL6024 tell you when one is missing). Call other modules only through their `provides`; never import their internal files. Keep every model in `Register` in `src/models.ts`.
|
|
49
49
|
18. **Replacing a route:** do not delete a route clients use. Add the new one and mark the old one `deprecated: { since: "YYYY-MM-DD", sunset: "YYYY-MM-DD", link: "https://..." }` in its options; it then sends the standard Deprecation and Sunset headers and is marked in OpenAPI and MCP. Remove it after the sunset date. For a breaking change to many routes, publish a new API version instead: `createApp({ routes: [apiVersion("v1", [notesV1]), apiVersion("v2", [notes])] })` serves them under `/v1` and `/v2`, each with its own OpenAPI document (`/v1/openapi.json`); write route paths without the version prefix.
|
|
50
50
|
19. **Caching:** for results that are slow or expensive to compute, use the built-in cache instead of a module-level `Map`: `` return cache.getOrSet(`notes:stats:${user.id}`, { ttlMs: 60_000, tags: ["notes"] }, () => computeStats(db, user.id)) `` in routes and jobs (`ctx.cache`), and `await cache.invalidate("notes")` after notes change. `ttlMs` is required; put the user id in the key of anything that differs per user; values come back as JSON (dates as strings). To cache a whole GET route instead, add the route option `cache: { ttlMs: 60_000, tags: ["notes"] }` (one response per user by default; `by: "public"` only for data that is the same for everyone) and invalidate the tag where the data changes. With several instances, use `createApp({ cache: { store: "database" } })`.
|
|
51
|
+
20. **Calling another Inferlo service:** `const tickets = serviceClient({ baseUrl: settings.TICKETS_URL, token: settings.TICKETS_TOKEN })`, then in a handler `await tickets.call(getTicket, { params: { id }, ctx })` with the other service's route imported, so the call is typed. Catch `ServiceCallError` and check `error.remoteStatus` for answers you expect (404). Never build these URLs with `fetch` by hand. When the app uses `tracing: { api: otel }`, pass the same `tracing` to `serviceClient` so calls join the trace.
|
|
52
|
+
21. **Data of many organisations (multi-tenant):** give the signed-in user a `tenantId` (the organisation's id) and make tables whose rows belong to one organisation tenant-scoped: `model("projects", { ... }, { tenant: true })`. `ctx.db` then filters every query by and stamps every insert with the user's tenant, so never add `tenantId` to a `where`, a body schema or an insert. Jobs queued (or events published) by a request run for the request's tenant: their `ctx.db` is scoped the same way, so do not pass the tenant id in the job input. In scripts use `app.db.$tenant(tenantId).projects`, and `app.jobs.enqueue(job, input, { tenantId })`. For limits and caches shared by an organisation use `rateLimit: { max, per, by: "tenant" }` and `cache: { ttlMs, by: "tenant" }`; `ctx.audit` records the tenant itself.
|
|
51
53
|
|
|
52
54
|
## Testing
|
|
53
55
|
|