@molecule/api-bonds-default-express 1.0.0 → 1.0.1
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 +1038 -0
- package/package.json +197 -191
package/README.md
ADDED
|
@@ -0,0 +1,1038 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
AUTO-GENERATED — DO NOT EDIT THIS FILE.
|
|
3
|
+
Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
|
|
4
|
+
Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
|
|
5
|
+
To change this document, edit the module-level JSDoc in src/index.ts.
|
|
6
|
+
Generated: 2026-08-04T01:47:47.108Z
|
|
7
|
+
-->
|
|
8
|
+
|
|
9
|
+
# @molecule/api-bonds-default-express
|
|
10
|
+
|
|
11
|
+
> **Auto-generated, AI-first package reference** for the [molecule.dev](https://molecule.dev) ecosystem.
|
|
12
|
+
> It is written to be read by coding agents as much as by people, and is generated from this
|
|
13
|
+
> package's source — edit `src/index.ts` JSDoc, not this file.
|
|
14
|
+
|
|
15
|
+
`@molecule/api-bonds-default-express` — default API bond wirings and
|
|
16
|
+
shared route/handler plumbing for Express-based apps.
|
|
17
|
+
|
|
18
|
+
Two halves:
|
|
19
|
+
|
|
20
|
+
1. **`setup<Name>()` bond wirings** (40+): one function per default
|
|
21
|
+
provider (`setupConfigEnv`, `setupDatabasePostgresql`,
|
|
22
|
+
`setupJwtJsonwebtoken`, `setupEmailsMailgun`, `setupUploadsS3`,
|
|
23
|
+
`setupRealtimeSocketio`, `setupAiAnthropic`, …) so per-app
|
|
24
|
+
`api/src/bonds/<name>.ts` files are 1-line re-exports and
|
|
25
|
+
`bonds/index.ts` just calls them in order.
|
|
26
|
+
2. **Shared Express plumbing**: `createBillingRouter` (the fleet's
|
|
27
|
+
Stripe billing endpoints), the `mountDefaultUserAuthRoutes` /
|
|
28
|
+
`mountDefaultDeviceRoutes` / other `mountDefault*Routes` helpers,
|
|
29
|
+
handler guards (`requireAuth`, `requireUser`, `requireOwnership`,
|
|
30
|
+
`getUserId`, `validationError`, `internalError`), zod param schemas,
|
|
31
|
+
`trackAuthEvent`, and a `createMigrator` re-export.
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
// api/src/bonds/index.ts — wire defaults at startup, then validate:
|
|
37
|
+
import { validateBonds } from '@molecule/api-bond'
|
|
38
|
+
import {
|
|
39
|
+
setupConfigEnv,
|
|
40
|
+
setupDatabasePostgresql,
|
|
41
|
+
setupEmailsMailgun,
|
|
42
|
+
setupJwtJsonwebtoken,
|
|
43
|
+
setupSecretsEnv,
|
|
44
|
+
} from '@molecule/api-bonds-default-express'
|
|
45
|
+
|
|
46
|
+
async function setupBonds(): Promise<void> {
|
|
47
|
+
setupConfigEnv()
|
|
48
|
+
setupSecretsEnv()
|
|
49
|
+
setupDatabasePostgresql()
|
|
50
|
+
setupJwtJsonwebtoken()
|
|
51
|
+
setupEmailsMailgun()
|
|
52
|
+
validateBonds()
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
// api/src/routes/billing.ts — the fleet-standard billing endpoints
|
|
58
|
+
// (POST /checkout, POST /cancel, GET /status, GET /tiers), mounted by
|
|
59
|
+
// the app router at /billing (the real file default-exports the router):
|
|
60
|
+
import { createBillingRouter } from '@molecule/api-bonds-default-express'
|
|
61
|
+
|
|
62
|
+
// Your app owns these (typically in api/src/tiers.ts):
|
|
63
|
+
interface AppLimits {
|
|
64
|
+
seats: number
|
|
65
|
+
}
|
|
66
|
+
const getPricingTiers = () => [] // your tiers, each with a stripePriceId + limits
|
|
67
|
+
const appPlanKeys = { free: 'free', pro: 'pro' }
|
|
68
|
+
|
|
69
|
+
const billingRouter = createBillingRouter<AppLimits>({
|
|
70
|
+
getPricingTiers,
|
|
71
|
+
planKeys: appPlanKeys,
|
|
72
|
+
})
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Type
|
|
76
|
+
|
|
77
|
+
`feature`
|
|
78
|
+
|
|
79
|
+
## Installation
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
npm install @molecule/api-bonds-default-express @molecule/api-ai-anthropic @molecule/api-ai-embeddings @molecule/api-ai-embeddings-openai @molecule/api-ai-openai @molecule/api-ai-speech @molecule/api-ai-speech-openai @molecule/api-ai-vector-store @molecule/api-ai-vector-store-pgvector @molecule/api-analytics @molecule/api-audit @molecule/api-audit-database @molecule/api-bond @molecule/api-cache @molecule/api-cache-memory @molecule/api-cache-redis @molecule/api-config @molecule/api-config-env @molecule/api-cron @molecule/api-cron-node-cron @molecule/api-database @molecule/api-database-postgresql @molecule/api-emails @molecule/api-emails-capture @molecule/api-emails-mailgun @molecule/api-encryption @molecule/api-encryption-aes @molecule/api-entitlements @molecule/api-error-tracking @molecule/api-error-tracking-console @molecule/api-error-tracking-sentry @molecule/api-geolocation @molecule/api-geolocation-google @molecule/api-geolocation-mapbox @molecule/api-geolocation-nominatim @molecule/api-http @molecule/api-http-fetch @molecule/api-i18n @molecule/api-image @molecule/api-image-sharp @molecule/api-import-export @molecule/api-import-export-csv @molecule/api-jwt @molecule/api-jwt-jsonwebtoken @molecule/api-logger @molecule/api-media-streaming @molecule/api-media-streaming-hls @molecule/api-middleware-body-parser @molecule/api-middleware-body-parser-express @molecule/api-middleware-cookie-parser @molecule/api-middleware-cookie-parser-express @molecule/api-middleware-cors @molecule/api-middleware-cors-express @molecule/api-middleware-validation @molecule/api-notifications-webhook @molecule/api-password @molecule/api-password-bcrypt @molecule/api-payments @molecule/api-payments-stripe @molecule/api-pdf @molecule/api-pdf-pdfkit @molecule/api-permissions @molecule/api-permissions-custom @molecule/api-push-capture @molecule/api-push-notifications @molecule/api-push-notifications-web-push @molecule/api-queue @molecule/api-queue-memory @molecule/api-queue-redis @molecule/api-rate-limit @molecule/api-rate-limit-memory @molecule/api-realtime @molecule/api-realtime-socketio @molecule/api-realtime-sse @molecule/api-realtime-ws @molecule/api-reporting @molecule/api-reporting-database @molecule/api-resource @molecule/api-resource-device @molecule/api-resource-payment @molecule/api-resource-user @molecule/api-search @molecule/api-search-meilisearch @molecule/api-search-postgres @molecule/api-secrets @molecule/api-secrets-env @molecule/api-two-factor @molecule/api-two-factor-otplib @molecule/api-uploads @molecule/api-uploads-filesystem @molecule/api-uploads-s3 @molecule/api-webhook @molecule/api-webhook-http @molecule/api-workflow @molecule/api-workflow-database
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## API
|
|
86
|
+
|
|
87
|
+
### Types
|
|
88
|
+
|
|
89
|
+
#### `AuthzResult`
|
|
90
|
+
|
|
91
|
+
Result of an ownership check. `ok: true` carries the resolved row;
|
|
92
|
+
`ok: false` carries the HTTP status the handler should return —
|
|
93
|
+
always 404 to avoid leaking row existence to non-owners (the
|
|
94
|
+
"no IDOR" rule).
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
type AuthzResult<T> = { ok: true; row: T } | { ok: false; status: 404 }
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Functions
|
|
101
|
+
|
|
102
|
+
#### `createBillingRouter(opts)`
|
|
103
|
+
|
|
104
|
+
Factory for the default billing router. The router exposes four
|
|
105
|
+
endpoints: `POST /checkout`, `POST /cancel`, `GET /status`, `GET /tiers`.
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
function createBillingRouter(opts: {
|
|
109
|
+
getPricingTiers: () => ReadonlyArray<PricingTier>
|
|
110
|
+
planKeys: { free: string } & Record<string, string>
|
|
111
|
+
}): Router
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
#### `createMigrator(migrationsDir)`
|
|
115
|
+
|
|
116
|
+
Returns a `runMigrations()` function bound to the given directory.
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
function createMigrator(migrationsDir: string): () => Promise<void>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
- `migrationsDir` — Absolute path to the directory containing ordered `*.sql` migration files. Resolve via `join(new URL('.', import.meta.url).pathname, '../../migrations')` from the app's `scripts/migrate.ts`.
|
|
123
|
+
|
|
124
|
+
**Returns:** A no-arg `runMigrations()` that creates the database (if missing) and applies every migration file in lexical order.
|
|
125
|
+
|
|
126
|
+
#### `getParamId(req, name?)`
|
|
127
|
+
|
|
128
|
+
Read a route param as a string, defending against the Express
|
|
129
|
+
type union `string | string[]` (multi-value when the same param
|
|
130
|
+
key appears more than once). Defaults to `'id'`.
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
function getParamId(
|
|
134
|
+
req: Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>,
|
|
135
|
+
name?: string,
|
|
136
|
+
): string
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
#### `getUserId(res)`
|
|
140
|
+
|
|
141
|
+
Read the JWT session userId off `res.locals.session`. Returns null
|
|
142
|
+
when there is no session (the auth middleware never ran, or the
|
|
143
|
+
request is unauthenticated).
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
function getUserId(res: Response<any, Record<string, any>>): string | null
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
#### `internalError(res, error?)`
|
|
150
|
+
|
|
151
|
+
Standard 500 response that logs the underlying cause before responding
|
|
152
|
+
with a generic message. Always pass the original error so silent
|
|
153
|
+
catches don't ship to prod under green tests.
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
function internalError(res: Response<any, Record<string, any>>, error?: unknown): void
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
#### `mountDefaultDeviceRoutes(router, device)`
|
|
160
|
+
|
|
161
|
+
Mounts the standard device routes:
|
|
162
|
+
|
|
163
|
+
- `GET /devices/push/public-key` (public — the VAPID public key browsers
|
|
164
|
+
need for `pushManager.subscribe({ applicationServerKey })`; bond-gated
|
|
165
|
+
404/503 when no push provider is bonded/configured)
|
|
166
|
+
- `GET /devices` (auth+query)
|
|
167
|
+
- `GET /devices/:id` (authUser+read)
|
|
168
|
+
- `PATCH /devices/:id` (authUser+update)
|
|
169
|
+
- `DELETE /devices/:id` (authUser+del)
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
function mountDefaultDeviceRoutes(router: Router, device: DeviceRequestHandlerMap): void
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
#### `mountDefaultUserAuthRoutes(router, user)`
|
|
176
|
+
|
|
177
|
+
Mounts the public auth endpoints:
|
|
178
|
+
|
|
179
|
+
- `POST /users` (create)
|
|
180
|
+
- `POST /users/log-in` (rateLimitAuth + logIn)
|
|
181
|
+
- `POST /users/forgot-password` (rateLimitAuth + forgotPassword)
|
|
182
|
+
|
|
183
|
+
The credential-bearing routes are fronted by `user.rateLimitAuth` — the
|
|
184
|
+
default IP+account brute-force throttle from `@molecule/api-resource-user` —
|
|
185
|
+
so generated apps are not left with unthrottled password / TOTP-via-login
|
|
186
|
+
guessing. The limiter degrades open (logs a warning) when no rate-limit
|
|
187
|
+
provider is bonded, so apps that opt out still boot.
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
function mountDefaultUserAuthRoutes(router: Router, user: UserRequestHandlerMap): void
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
#### `mountDefaultUserBillingRoutes(router, user)`
|
|
194
|
+
|
|
195
|
+
Mounts plan/billing routes:
|
|
196
|
+
|
|
197
|
+
- `PATCH /users/:id/plan` (authSelf+updatePlan)
|
|
198
|
+
- `POST /users/payment-notification/:provider` (requireWebhookAuthenticity+handlePaymentNotification)
|
|
199
|
+
|
|
200
|
+
The notification route is public (providers POST to it), so it is gated by
|
|
201
|
+
`requireWebhookAuthenticity`: signature-verifying webhook providers (Stripe)
|
|
202
|
+
pass through, while unsigned server-to-server providers (Apple/Google) require
|
|
203
|
+
a shared secret — the endpoint is not open by default.
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
function mountDefaultUserBillingRoutes(router: Router, user: UserRequestHandlerMap): void
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
#### `mountDefaultUserCrudRoutes(router, user)`
|
|
210
|
+
|
|
211
|
+
Mounts the authed-self user CRUD routes:
|
|
212
|
+
|
|
213
|
+
- `GET /users/me` (auth+readSelf) — session restore; MUST precede `/users/:id`
|
|
214
|
+
- `GET /users/:id` (authSelf+read)
|
|
215
|
+
- `PATCH /users/:id` (authSelf+update)
|
|
216
|
+
- `DELETE /users/:id` (authSelf+del)
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
function mountDefaultUserCrudRoutes(router: Router, user: UserRequestHandlerMap): void
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
#### `mountDefaultUserOAuthLoginRoute(router, user)`
|
|
223
|
+
|
|
224
|
+
Optional OAuth routes — BOTH halves of the flow:
|
|
225
|
+
|
|
226
|
+
- `GET /users/oauth/:provider` (rateLimitAuth + oauthAuthorize) —
|
|
227
|
+
initiation: sets the CSRF `oauth_state` + PKCE `oauth_verifier` httpOnly
|
|
228
|
+
cookies and 302-redirects to the bonded provider's authorization URL.
|
|
229
|
+
Without this half the state cookie `logInOAuth` validates is never set,
|
|
230
|
+
so every callback fails 403 (this is exactly how the generated-app fleet
|
|
231
|
+
shipped an exchange endpoint with no way to start the dance). The GET
|
|
232
|
+
carries the same `rateLimitAuth` throttle as the POST: it has no body, so
|
|
233
|
+
only the generous per-IP bucket applies — an abuse ceiling on cookie-mint/
|
|
234
|
+
redirect flooding that a legitimate login (one GET + one POST) never
|
|
235
|
+
approaches. A trip is a 429 JSON on a top-level navigation, which is
|
|
236
|
+
acceptable for that ceiling.
|
|
237
|
+
- `POST /users/log-in/oauth` (rateLimitAuth + logInOAuth) — callback
|
|
238
|
+
exchange: verifies state + code with the bonded provider and logs the
|
|
239
|
+
user in.
|
|
240
|
+
|
|
241
|
+
Only mount when the app wires an oauth bond. Handlers check the bond
|
|
242
|
+
registry at request time, so an unbonded provider yields a clean 404.
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
function mountDefaultUserOAuthLoginRoute(router: Router, user: UserRequestHandlerMap): void
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
#### `mountDefaultUserResetPasswordRoute(router, user)`
|
|
249
|
+
|
|
250
|
+
Optional reset-password route: `POST /users/reset-password` (rateLimitAuth +
|
|
251
|
+
resetPassword). Only mount when the app uses the pkg's resetPassword handler
|
|
252
|
+
rather than a custom local handler.
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
function mountDefaultUserResetPasswordRoute(router: Router, user: UserRequestHandlerMap): void
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
#### `mountDefaultUserSecurityRoutes(router, user)`
|
|
259
|
+
|
|
260
|
+
Mounts password + 2FA security routes:
|
|
261
|
+
|
|
262
|
+
- `PATCH /users/:id/password` (authSelf+updatePassword)
|
|
263
|
+
- `POST /users/:id/verify-two-factor` (authSelf + rateLimitTwoFactor + verifyTwoFactor)
|
|
264
|
+
|
|
265
|
+
The 2FA verification route carries a stricter limiter (`user.rateLimitTwoFactor`)
|
|
266
|
+
that temp-locks the second factor per account after consecutive misses.
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
function mountDefaultUserSecurityRoutes(router: Router, user: UserRequestHandlerMap): void
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
#### `mountDefaultUserVerifyPaymentRoutes(router, user)`
|
|
273
|
+
|
|
274
|
+
Optional payment-verification routes for apps that support
|
|
275
|
+
client-driven payment confirmation (Apple/Google receipt verify).
|
|
276
|
+
|
|
277
|
+
Both verbs require `authSelf` ([M3-1]): the handler mutates and returns the
|
|
278
|
+
`:id` user, so an unauthenticated / cross-user call must not reach it. The
|
|
279
|
+
permissive global `verifyMiddleware()` never blocks, so per-route `authSelf`
|
|
280
|
+
is the gate. `authSelf` does NOT break the Stripe Checkout `success_url`
|
|
281
|
+
callback — that is a top-level browser navigation which carries the
|
|
282
|
+
`sameSite:'lax'` session cookie — and in-handler customer/checkout-session
|
|
283
|
+
binding remains as defense-in-depth. This mirrors the hardened declarative
|
|
284
|
+
route table (`resources/user/src/routes.ts`) and molecule-dev's live router;
|
|
285
|
+
the fix had not been propagated to this mounter, which the generated-app
|
|
286
|
+
fleet uses.
|
|
287
|
+
|
|
288
|
+
- `GET /users/:id/verify-payment/:provider` (authSelf+verifyPayment)
|
|
289
|
+
- `POST /users/:id/verify-payment/:provider` (authSelf+verifyPayment)
|
|
290
|
+
|
|
291
|
+
```typescript
|
|
292
|
+
function mountDefaultUserVerifyPaymentRoutes(router: Router, user: UserRequestHandlerMap): void
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
#### `requireAuth(_req, res, next)`
|
|
296
|
+
|
|
297
|
+
Express middleware that 401s any request lacking `res.locals.session.userId`.
|
|
298
|
+
Drop-in for the fleet's 51 inline `requireAuth` copies.
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
function requireAuth(
|
|
302
|
+
_req: Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>,
|
|
303
|
+
res: Response<any, Record<string, any>>,
|
|
304
|
+
next: NextFunction,
|
|
305
|
+
): void
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
#### `requireOwnership(table, id, userId)`
|
|
309
|
+
|
|
310
|
+
Look up a row by id and verify the caller owns it via `owner_id`.
|
|
311
|
+
Returns the row on success, 404 when missing OR owned by a different
|
|
312
|
+
user (so attackers can't probe row existence).
|
|
313
|
+
|
|
314
|
+
```typescript
|
|
315
|
+
function requireOwnership(table: string, id: string, userId: string): Promise<AuthzResult<T>>
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
#### `requireUser(res)`
|
|
319
|
+
|
|
320
|
+
Like `getUserId` but writes a 401 + returns null when there's no
|
|
321
|
+
session. Use at the top of handler bodies to bail early:
|
|
322
|
+
|
|
323
|
+
```ts
|
|
324
|
+
const userId = requireUser(res)
|
|
325
|
+
if (!userId) return
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
```typescript
|
|
329
|
+
function requireUser(res: Response<any, Record<string, any>>): string | null
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
#### `requireUserOwnership(table, id, userId)`
|
|
333
|
+
|
|
334
|
+
Variant of `requireOwnership` for tables that scope by `user_id`
|
|
335
|
+
instead of `owner_id` (notifications, user-bound preferences, etc.).
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
function requireUserOwnership(table: string, id: string, userId: string): Promise<AuthzResult<T>>
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
#### `setupAiAnthropic()`
|
|
342
|
+
|
|
343
|
+
Registers `@molecule/api-ai-anthropic` as a named `'anthropic'` AI provider.
|
|
344
|
+
|
|
345
|
+
```typescript
|
|
346
|
+
function setupAiAnthropic(): Promise<void>
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
#### `setupAiEmbeddingsOpenai()`
|
|
350
|
+
|
|
351
|
+
Wires `@molecule/api-ai-embeddings-openai` to `@molecule/api-ai-embeddings`.
|
|
352
|
+
|
|
353
|
+
```typescript
|
|
354
|
+
function setupAiEmbeddingsOpenai(): Promise<void>
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
#### `setupAiOpenai()`
|
|
358
|
+
|
|
359
|
+
Registers `@molecule/api-ai-openai` as a named `'openai'` AI provider.
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
function setupAiOpenai(): Promise<void>
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
#### `setupAiSpeechOpenai()`
|
|
366
|
+
|
|
367
|
+
Wires `@molecule/api-ai-speech-openai` to `@molecule/api-ai-speech`.
|
|
368
|
+
|
|
369
|
+
```typescript
|
|
370
|
+
function setupAiSpeechOpenai(): Promise<void>
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
#### `setupAiVectorStorePgvector()`
|
|
374
|
+
|
|
375
|
+
Wires `@molecule/api-ai-vector-store-pgvector` to `@molecule/api-ai-vector-store`.
|
|
376
|
+
|
|
377
|
+
```typescript
|
|
378
|
+
function setupAiVectorStorePgvector(): Promise<void>
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
#### `setupApiAnalyticsDefault()`
|
|
382
|
+
|
|
383
|
+
Wires a no-op default analytics provider so `@molecule/api-analytics` calls succeed.
|
|
384
|
+
|
|
385
|
+
```typescript
|
|
386
|
+
function setupApiAnalyticsDefault(): Promise<void>
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
#### `setupAuditDatabase()`
|
|
390
|
+
|
|
391
|
+
Wires `@molecule/api-audit-database` to `@molecule/api-audit`.
|
|
392
|
+
|
|
393
|
+
```typescript
|
|
394
|
+
function setupAuditDatabase(): Promise<void>
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
#### `setupCacheRedis()`
|
|
398
|
+
|
|
399
|
+
Wires `@molecule/api-cache-redis` to `@molecule/api-cache`.
|
|
400
|
+
|
|
401
|
+
```typescript
|
|
402
|
+
function setupCacheRedis(): Promise<void>
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
#### `setupConfigEnv()`
|
|
406
|
+
|
|
407
|
+
Wires `@molecule/api-config-env` to `@molecule/api-config`.
|
|
408
|
+
|
|
409
|
+
```typescript
|
|
410
|
+
function setupConfigEnv(): void
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
#### `setupCronNodeCron()`
|
|
414
|
+
|
|
415
|
+
Wires `@molecule/api-cron-node-cron` to `@molecule/api-cron`.
|
|
416
|
+
|
|
417
|
+
```typescript
|
|
418
|
+
function setupCronNodeCron(): Promise<void>
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
#### `setupDatabasePostgresql()`
|
|
422
|
+
|
|
423
|
+
Wires `@molecule/api-database-postgresql` to `@molecule/api-database`.
|
|
424
|
+
|
|
425
|
+
```typescript
|
|
426
|
+
function setupDatabasePostgresql(): void
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
#### `setupEmailsMailgun()`
|
|
430
|
+
|
|
431
|
+
Wires `@molecule/api-emails-mailgun` to `@molecule/api-emails`.
|
|
432
|
+
|
|
433
|
+
```typescript
|
|
434
|
+
function setupEmailsMailgun(): void
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
#### `setupEncryptionAes()`
|
|
438
|
+
|
|
439
|
+
Wires `@molecule/api-encryption-aes` to `@molecule/api-encryption`.
|
|
440
|
+
|
|
441
|
+
```typescript
|
|
442
|
+
function setupEncryptionAes(): Promise<void>
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
#### `setupErrorTrackingConsole()`
|
|
446
|
+
|
|
447
|
+
Wires `@molecule/api-error-tracking-console` to `@molecule/api-error-tracking`.
|
|
448
|
+
|
|
449
|
+
Zero-credential development default: captures are logged as structured
|
|
450
|
+
lines through the bonded logger instead of being sent to a remote service.
|
|
451
|
+
|
|
452
|
+
```typescript
|
|
453
|
+
function setupErrorTrackingConsole(): Promise<void>
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
#### `setupErrorTrackingSentry()`
|
|
457
|
+
|
|
458
|
+
Wires `@molecule/api-error-tracking-sentry` to `@molecule/api-error-tracking`.
|
|
459
|
+
|
|
460
|
+
Safe to wire unconditionally: without `SENTRY_DSN` the Sentry provider is a
|
|
461
|
+
documented no-op (the boot config report flags the missing key), so an app
|
|
462
|
+
that hasn't configured Sentry yet boots and runs untouched.
|
|
463
|
+
|
|
464
|
+
```typescript
|
|
465
|
+
function setupErrorTrackingSentry(): Promise<void>
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
#### `setupGeolocationGoogle()`
|
|
469
|
+
|
|
470
|
+
Wires `@molecule/api-geolocation-google` to `@molecule/api-geolocation`.
|
|
471
|
+
|
|
472
|
+
```typescript
|
|
473
|
+
function setupGeolocationGoogle(): Promise<void>
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
#### `setupGeolocationMapbox()`
|
|
477
|
+
|
|
478
|
+
Wires `@molecule/api-geolocation-mapbox` to `@molecule/api-geolocation`.
|
|
479
|
+
|
|
480
|
+
```typescript
|
|
481
|
+
function setupGeolocationMapbox(): Promise<void>
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
#### `setupHttpFetch()`
|
|
485
|
+
|
|
486
|
+
Wires `@molecule/api-http-fetch` to `@molecule/api-http`.
|
|
487
|
+
|
|
488
|
+
```typescript
|
|
489
|
+
function setupHttpFetch(): Promise<void>
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
#### `setupImageSharp()`
|
|
493
|
+
|
|
494
|
+
Wires `@molecule/api-image-sharp` to `@molecule/api-image`.
|
|
495
|
+
|
|
496
|
+
```typescript
|
|
497
|
+
function setupImageSharp(): Promise<void>
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
#### `setupImportExportCsv()`
|
|
501
|
+
|
|
502
|
+
Wires `@molecule/api-import-export-csv` to `@molecule/api-import-export`.
|
|
503
|
+
|
|
504
|
+
```typescript
|
|
505
|
+
function setupImportExportCsv(): Promise<void>
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
#### `setupJwtJsonwebtoken()`
|
|
509
|
+
|
|
510
|
+
Wires `@molecule/api-jwt-jsonwebtoken` to `@molecule/api-jwt`.
|
|
511
|
+
|
|
512
|
+
```typescript
|
|
513
|
+
function setupJwtJsonwebtoken(): void
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
#### `setupMediaStreamingHls()`
|
|
517
|
+
|
|
518
|
+
Wires `@molecule/api-media-streaming-hls` to `@molecule/api-media-streaming`.
|
|
519
|
+
|
|
520
|
+
```typescript
|
|
521
|
+
function setupMediaStreamingHls(): Promise<void>
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
#### `setupMiddlewareBodyParserExpress()`
|
|
525
|
+
|
|
526
|
+
Wires `@molecule/api-middleware-body-parser-express` to `@molecule/api-middleware-body-parser`.
|
|
527
|
+
|
|
528
|
+
```typescript
|
|
529
|
+
function setupMiddlewareBodyParserExpress(): void
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
#### `setupMiddlewareCookieParserExpress()`
|
|
533
|
+
|
|
534
|
+
Wires `@molecule/api-middleware-cookie-parser-express` to `@molecule/api-middleware-cookie-parser`.
|
|
535
|
+
|
|
536
|
+
```typescript
|
|
537
|
+
function setupMiddlewareCookieParserExpress(): void
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
#### `setupMiddlewareCorsExpress()`
|
|
541
|
+
|
|
542
|
+
Wires `@molecule/api-middleware-cors-express` to `@molecule/api-middleware-cors`.
|
|
543
|
+
|
|
544
|
+
```typescript
|
|
545
|
+
function setupMiddlewareCorsExpress(): void
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
#### `setupNotificationsWebhook()`
|
|
549
|
+
|
|
550
|
+
Registers `@molecule/api-notifications-webhook` as a named `'webhook'` notifications provider.
|
|
551
|
+
|
|
552
|
+
```typescript
|
|
553
|
+
function setupNotificationsWebhook(): Promise<void>
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
#### `setupPasswordBcrypt()`
|
|
557
|
+
|
|
558
|
+
Wires `@molecule/api-password-bcrypt` to `@molecule/api-password`.
|
|
559
|
+
|
|
560
|
+
```typescript
|
|
561
|
+
function setupPasswordBcrypt(): void
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
#### `setupPaymentsStripe()`
|
|
565
|
+
|
|
566
|
+
Registers `@molecule/api-payments-stripe` as a named `'stripe'` payments provider.
|
|
567
|
+
|
|
568
|
+
```typescript
|
|
569
|
+
function setupPaymentsStripe(): void
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
#### `setupPdfPdfkit()`
|
|
573
|
+
|
|
574
|
+
Wires `@molecule/api-pdf-pdfkit` to `@molecule/api-pdf`.
|
|
575
|
+
|
|
576
|
+
```typescript
|
|
577
|
+
function setupPdfPdfkit(): Promise<void>
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
#### `setupPermissionsCustom()`
|
|
581
|
+
|
|
582
|
+
Wires `@molecule/api-permissions-custom` to `@molecule/api-permissions`.
|
|
583
|
+
|
|
584
|
+
```typescript
|
|
585
|
+
function setupPermissionsCustom(): Promise<void>
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
#### `setupPushNotificationsWebPush()`
|
|
589
|
+
|
|
590
|
+
Wires `@molecule/api-push-notifications-web-push` to `@molecule/api-push-notifications`.
|
|
591
|
+
|
|
592
|
+
```typescript
|
|
593
|
+
function setupPushNotificationsWebPush(): Promise<void>
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
#### `setupQueueMemory()`
|
|
597
|
+
|
|
598
|
+
Wires `@molecule/api-queue-memory` to `@molecule/api-queue` — the
|
|
599
|
+
zero-credential in-process queue (single-process/dev; swap to
|
|
600
|
+
redis/rabbitmq/sqs for multi-instance production).
|
|
601
|
+
|
|
602
|
+
```typescript
|
|
603
|
+
function setupQueueMemory(): Promise<void>
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
#### `setupQueueRedis()`
|
|
607
|
+
|
|
608
|
+
Wires `@molecule/api-queue-redis` to `@molecule/api-queue`. Outside
|
|
609
|
+
production, when `REDIS_URL` is absent, falls back to
|
|
610
|
+
`@molecule/api-queue-memory` — the zero-credential in-process queue — so
|
|
611
|
+
queue-backed features (background jobs, async delivery workers) run out of
|
|
612
|
+
the box, mirroring `setupCacheRedis`.
|
|
613
|
+
|
|
614
|
+
```typescript
|
|
615
|
+
function setupQueueRedis(): Promise<void>
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
#### `setupRateLimitMemory()`
|
|
619
|
+
|
|
620
|
+
Wires `@molecule/api-rate-limit-memory` to `@molecule/api-rate-limit`.
|
|
621
|
+
|
|
622
|
+
This is the default brute-force-protection backend for `mlcl`-generated apps
|
|
623
|
+
(single-instance). Multi-instance deployments should swap in
|
|
624
|
+
`@molecule/api-rate-limit-redis` so the throttle is shared across replicas.
|
|
625
|
+
|
|
626
|
+
```typescript
|
|
627
|
+
function setupRateLimitMemory(): Promise<void>
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
#### `setupRealtimeSocketio()`
|
|
631
|
+
|
|
632
|
+
Wires `@molecule/api-realtime-socketio` to `@molecule/api-realtime`.
|
|
633
|
+
|
|
634
|
+
```typescript
|
|
635
|
+
function setupRealtimeSocketio(): Promise<void>
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
#### `setupRealtimeSse()`
|
|
639
|
+
|
|
640
|
+
Wires `@molecule/api-realtime-sse` to `@molecule/api-realtime`.
|
|
641
|
+
|
|
642
|
+
```typescript
|
|
643
|
+
function setupRealtimeSse(): Promise<void>
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
#### `setupRealtimeWs()`
|
|
647
|
+
|
|
648
|
+
Wires `@molecule/api-realtime-ws` to `@molecule/api-realtime`.
|
|
649
|
+
|
|
650
|
+
```typescript
|
|
651
|
+
function setupRealtimeWs(): Promise<void>
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
#### `setupReportingDatabase()`
|
|
655
|
+
|
|
656
|
+
Wires `@molecule/api-reporting-database` to `@molecule/api-reporting`.
|
|
657
|
+
|
|
658
|
+
```typescript
|
|
659
|
+
function setupReportingDatabase(): Promise<void>
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
#### `setupSearchMeilisearch()`
|
|
663
|
+
|
|
664
|
+
Wires `@molecule/api-search-meilisearch` to `@molecule/api-search`.
|
|
665
|
+
|
|
666
|
+
```typescript
|
|
667
|
+
function setupSearchMeilisearch(): void
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
#### `setupSecretsEnv()`
|
|
671
|
+
|
|
672
|
+
Wires `@molecule/api-secrets-env` to `@molecule/api-secrets`.
|
|
673
|
+
|
|
674
|
+
```typescript
|
|
675
|
+
function setupSecretsEnv(): void
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
#### `setupServiceDevice()`
|
|
679
|
+
|
|
680
|
+
Registers the device service from `@molecule/api-resource-device` on the bond system.
|
|
681
|
+
|
|
682
|
+
```typescript
|
|
683
|
+
function setupServiceDevice(): void
|
|
684
|
+
```
|
|
685
|
+
|
|
686
|
+
#### `setupServicePayment()`
|
|
687
|
+
|
|
688
|
+
Registers the plan + paymentRecord services from `@molecule/api-resource-payment`.
|
|
689
|
+
|
|
690
|
+
```typescript
|
|
691
|
+
function setupServicePayment(): void
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
#### `setupTwoFactorOtplib()`
|
|
695
|
+
|
|
696
|
+
Wires `@molecule/api-two-factor-otplib` to `@molecule/api-two-factor`.
|
|
697
|
+
|
|
698
|
+
```typescript
|
|
699
|
+
function setupTwoFactorOtplib(): void
|
|
700
|
+
```
|
|
701
|
+
|
|
702
|
+
#### `setupUploadsS3()`
|
|
703
|
+
|
|
704
|
+
Wires `@molecule/api-uploads-s3` to `@molecule/api-uploads`.
|
|
705
|
+
|
|
706
|
+
```typescript
|
|
707
|
+
function setupUploadsS3(): void
|
|
708
|
+
```
|
|
709
|
+
|
|
710
|
+
#### `setupWebhookHttp()`
|
|
711
|
+
|
|
712
|
+
Wires `@molecule/api-webhook-http` to `@molecule/api-webhook`.
|
|
713
|
+
|
|
714
|
+
```typescript
|
|
715
|
+
function setupWebhookHttp(): Promise<void>
|
|
716
|
+
```
|
|
717
|
+
|
|
718
|
+
#### `setupWorkflowDatabase()`
|
|
719
|
+
|
|
720
|
+
Wires `@molecule/api-workflow-database` to `@molecule/api-workflow`.
|
|
721
|
+
|
|
722
|
+
```typescript
|
|
723
|
+
function setupWorkflowDatabase(): Promise<void>
|
|
724
|
+
```
|
|
725
|
+
|
|
726
|
+
#### `trackAuthEvent(eventName)`
|
|
727
|
+
|
|
728
|
+
Emits an analytics event AND a log entry for an auth-related mutation
|
|
729
|
+
(signup, login, password reset, plan change, etc.). Logs at info on
|
|
730
|
+
success and warn on auth failure (4xx) so security signal is captured.
|
|
731
|
+
|
|
732
|
+
Replaces the per-app `api/src/middleware/auth-analytics.ts` shipped
|
|
733
|
+
by 10 fleet apps.
|
|
734
|
+
|
|
735
|
+
```typescript
|
|
736
|
+
function trackAuthEvent(
|
|
737
|
+
eventName: string,
|
|
738
|
+
): RequestHandler<ParamsDictionary, any, any, ParsedQs, Record<string, any>>
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
#### `validationError(res, issues)`
|
|
742
|
+
|
|
743
|
+
Standard 400 response for zod / schema validation failures.
|
|
744
|
+
Used by ~21 fleet apps' `api/src/lib/authz.ts` files.
|
|
745
|
+
|
|
746
|
+
```typescript
|
|
747
|
+
function validationError(res: Response<any, Record<string, any>>, issues: unknown): void
|
|
748
|
+
```
|
|
749
|
+
|
|
750
|
+
### Constants
|
|
751
|
+
|
|
752
|
+
#### `deviceRequestHandlerMap`
|
|
753
|
+
|
|
754
|
+
Pre-wired request handler map for `@molecule/api-resource-device`.
|
|
755
|
+
|
|
756
|
+
```typescript
|
|
757
|
+
const deviceRequestHandlerMap: DeviceRequestHandlerMap
|
|
758
|
+
```
|
|
759
|
+
|
|
760
|
+
#### `deviceService`
|
|
761
|
+
|
|
762
|
+
DeviceService implementation for the bond system.
|
|
763
|
+
|
|
764
|
+
Provides device CRUD operations that other resources
|
|
765
|
+
can use through `get('device')` / `require('device')`.
|
|
766
|
+
|
|
767
|
+
```typescript
|
|
768
|
+
const deviceService: DeviceService
|
|
769
|
+
```
|
|
770
|
+
|
|
771
|
+
#### `idParamSchema`
|
|
772
|
+
|
|
773
|
+
Standard route-param schema for `:id`. Accepts any non-empty string.
|
|
774
|
+
Pair with `validateParams(idParamSchema)`.
|
|
775
|
+
|
|
776
|
+
```typescript
|
|
777
|
+
const idParamSchema: z.ZodObject<{ id: z.ZodString }, z.core.$strip>
|
|
778
|
+
```
|
|
779
|
+
|
|
780
|
+
#### `userRequestHandlerMap`
|
|
781
|
+
|
|
782
|
+
Pre-wired request handler map for `@molecule/api-resource-user`.
|
|
783
|
+
|
|
784
|
+
```typescript
|
|
785
|
+
const userRequestHandlerMap: UserRequestHandlerMap
|
|
786
|
+
```
|
|
787
|
+
|
|
788
|
+
#### `uuidParamSchema`
|
|
789
|
+
|
|
790
|
+
Strict variant of `idParamSchema` that requires a UUID. Use when the
|
|
791
|
+
underlying column is a uuid.
|
|
792
|
+
|
|
793
|
+
```typescript
|
|
794
|
+
const uuidParamSchema: z.ZodObject<{ id: z.ZodString }, z.core.$strip>
|
|
795
|
+
```
|
|
796
|
+
|
|
797
|
+
### Namespaces
|
|
798
|
+
|
|
799
|
+
#### `userAuthorization`
|
|
800
|
+
|
|
801
|
+
Members:
|
|
802
|
+
|
|
803
|
+
- `userAuthorization.getAuthCookieName` — const: Resolve the actual cookie name for an auth cookie.
|
|
804
|
+
- `userAuthorization.getAuthCookieOptions` — const: Base cookie attributes shared by EVERY auth cookie this resource sets and
|
|
805
|
+
- `userAuthorization.invalidateDeviceExistsCache` — const: Evict a single device's positive entry from the device-exists cache so the
|
|
806
|
+
- `userAuthorization.invalidateAllDeviceExistsCache` — const: Evict ALL positive entries from the device-exists cache.
|
|
807
|
+
- `userAuthorization.set` — const: Set authorization headers and cookie for a session.
|
|
808
|
+
- `userAuthorization.verifyMiddleware` — const: Middleware that verifies the JWT token from the `Authorization` header and sets `res.locals.session`.
|
|
809
|
+
|
|
810
|
+
## Injection Notes
|
|
811
|
+
|
|
812
|
+
### Requirements
|
|
813
|
+
|
|
814
|
+
Peer dependencies:
|
|
815
|
+
|
|
816
|
+
- `@molecule/api-ai-anthropic` ^1.0.1
|
|
817
|
+
- `@molecule/api-ai-embeddings` ^1.0.1
|
|
818
|
+
- `@molecule/api-ai-embeddings-openai` ^1.0.1
|
|
819
|
+
- `@molecule/api-ai-openai` ^1.0.1
|
|
820
|
+
- `@molecule/api-ai-speech` ^1.0.1
|
|
821
|
+
- `@molecule/api-ai-speech-openai` ^1.0.1
|
|
822
|
+
- `@molecule/api-ai-vector-store` ^1.0.1
|
|
823
|
+
- `@molecule/api-ai-vector-store-pgvector` ^1.0.1
|
|
824
|
+
- `@molecule/api-analytics` ^1.0.1
|
|
825
|
+
- `@molecule/api-audit` ^1.0.1
|
|
826
|
+
- `@molecule/api-audit-database` ^1.0.1
|
|
827
|
+
- `@molecule/api-bond` ^1.0.1
|
|
828
|
+
- `@molecule/api-cache` ^1.0.1
|
|
829
|
+
- `@molecule/api-cache-memory` ^1.0.1
|
|
830
|
+
- `@molecule/api-cache-redis` ^1.0.1
|
|
831
|
+
- `@molecule/api-config` ^1.0.1
|
|
832
|
+
- `@molecule/api-config-env` ^1.0.1
|
|
833
|
+
- `@molecule/api-cron` ^1.0.1
|
|
834
|
+
- `@molecule/api-cron-node-cron` ^1.0.1
|
|
835
|
+
- `@molecule/api-database` ^1.0.1
|
|
836
|
+
- `@molecule/api-database-postgresql` ^1.0.1
|
|
837
|
+
- `@molecule/api-emails` ^1.0.1
|
|
838
|
+
- `@molecule/api-emails-capture` ^1.0.1
|
|
839
|
+
- `@molecule/api-emails-mailgun` ^1.0.1
|
|
840
|
+
- `@molecule/api-encryption` ^1.0.1
|
|
841
|
+
- `@molecule/api-encryption-aes` ^1.0.1
|
|
842
|
+
- `@molecule/api-entitlements` ^1.0.1
|
|
843
|
+
- `@molecule/api-error-tracking` ^1.0.1
|
|
844
|
+
- `@molecule/api-error-tracking-console` ^1.0.1
|
|
845
|
+
- `@molecule/api-error-tracking-sentry` ^1.0.1
|
|
846
|
+
- `@molecule/api-geolocation` ^1.0.1
|
|
847
|
+
- `@molecule/api-geolocation-google` ^1.0.1
|
|
848
|
+
- `@molecule/api-geolocation-mapbox` ^1.0.1
|
|
849
|
+
- `@molecule/api-geolocation-nominatim` ^1.0.1
|
|
850
|
+
- `@molecule/api-http` ^1.0.1
|
|
851
|
+
- `@molecule/api-http-fetch` ^1.0.1
|
|
852
|
+
- `@molecule/api-i18n` ^1.0.1
|
|
853
|
+
- `@molecule/api-image` ^1.0.1
|
|
854
|
+
- `@molecule/api-image-sharp` ^1.0.1
|
|
855
|
+
- `@molecule/api-import-export` ^1.0.1
|
|
856
|
+
- `@molecule/api-import-export-csv` ^1.0.1
|
|
857
|
+
- `@molecule/api-jwt` ^1.0.1
|
|
858
|
+
- `@molecule/api-jwt-jsonwebtoken` ^1.0.1
|
|
859
|
+
- `@molecule/api-logger` ^1.0.1
|
|
860
|
+
- `@molecule/api-media-streaming` ^1.0.1
|
|
861
|
+
- `@molecule/api-media-streaming-hls` ^1.0.1
|
|
862
|
+
- `@molecule/api-middleware-body-parser` ^1.0.1
|
|
863
|
+
- `@molecule/api-middleware-body-parser-express` ^1.0.1
|
|
864
|
+
- `@molecule/api-middleware-cookie-parser` ^1.0.1
|
|
865
|
+
- `@molecule/api-middleware-cookie-parser-express` ^1.0.1
|
|
866
|
+
- `@molecule/api-middleware-cors` ^1.0.1
|
|
867
|
+
- `@molecule/api-middleware-cors-express` ^1.0.1
|
|
868
|
+
- `@molecule/api-middleware-validation` ^1.0.1
|
|
869
|
+
- `@molecule/api-notifications-webhook` ^1.0.1
|
|
870
|
+
- `@molecule/api-password` ^1.0.1
|
|
871
|
+
- `@molecule/api-password-bcrypt` ^1.0.1
|
|
872
|
+
- `@molecule/api-payments` ^1.0.1
|
|
873
|
+
- `@molecule/api-payments-stripe` ^1.0.1
|
|
874
|
+
- `@molecule/api-pdf` ^1.0.1
|
|
875
|
+
- `@molecule/api-pdf-pdfkit` ^1.0.1
|
|
876
|
+
- `@molecule/api-permissions` ^1.0.1
|
|
877
|
+
- `@molecule/api-permissions-custom` ^1.0.1
|
|
878
|
+
- `@molecule/api-push-capture` ^1.0.1
|
|
879
|
+
- `@molecule/api-push-notifications` ^1.0.1
|
|
880
|
+
- `@molecule/api-push-notifications-web-push` ^1.0.1
|
|
881
|
+
- `@molecule/api-queue` ^1.0.1
|
|
882
|
+
- `@molecule/api-queue-memory` ^1.0.1
|
|
883
|
+
- `@molecule/api-queue-redis` ^1.0.1
|
|
884
|
+
- `@molecule/api-rate-limit` ^1.0.1
|
|
885
|
+
- `@molecule/api-rate-limit-memory` ^1.0.1
|
|
886
|
+
- `@molecule/api-realtime` ^1.0.1
|
|
887
|
+
- `@molecule/api-realtime-socketio` ^1.0.1
|
|
888
|
+
- `@molecule/api-realtime-sse` ^1.0.1
|
|
889
|
+
- `@molecule/api-realtime-ws` ^1.0.1
|
|
890
|
+
- `@molecule/api-reporting` ^1.0.1
|
|
891
|
+
- `@molecule/api-reporting-database` ^1.0.1
|
|
892
|
+
- `@molecule/api-resource` ^1.0.1
|
|
893
|
+
- `@molecule/api-resource-device` ^1.0.1
|
|
894
|
+
- `@molecule/api-resource-payment` ^1.0.1
|
|
895
|
+
- `@molecule/api-resource-user` ^1.0.1
|
|
896
|
+
- `@molecule/api-search` ^1.0.1
|
|
897
|
+
- `@molecule/api-search-meilisearch` ^1.0.1
|
|
898
|
+
- `@molecule/api-search-postgres` ^1.0.1
|
|
899
|
+
- `@molecule/api-secrets` ^1.0.1
|
|
900
|
+
- `@molecule/api-secrets-env` ^1.0.1
|
|
901
|
+
- `@molecule/api-two-factor` ^1.0.1
|
|
902
|
+
- `@molecule/api-two-factor-otplib` ^1.0.1
|
|
903
|
+
- `@molecule/api-uploads` ^1.0.1
|
|
904
|
+
- `@molecule/api-uploads-filesystem` ^1.0.1
|
|
905
|
+
- `@molecule/api-uploads-s3` ^1.0.1
|
|
906
|
+
- `@molecule/api-webhook` ^1.0.1
|
|
907
|
+
- `@molecule/api-webhook-http` ^1.0.1
|
|
908
|
+
- `@molecule/api-workflow` ^1.0.1
|
|
909
|
+
- `@molecule/api-workflow-database` ^1.0.1
|
|
910
|
+
|
|
911
|
+
### Runtime Dependencies
|
|
912
|
+
|
|
913
|
+
- `@molecule/api-ai-anthropic`
|
|
914
|
+
- `@molecule/api-ai-embeddings`
|
|
915
|
+
- `@molecule/api-ai-embeddings-openai`
|
|
916
|
+
- `@molecule/api-ai-openai`
|
|
917
|
+
- `@molecule/api-ai-speech`
|
|
918
|
+
- `@molecule/api-ai-speech-openai`
|
|
919
|
+
- `@molecule/api-ai-vector-store`
|
|
920
|
+
- `@molecule/api-ai-vector-store-pgvector`
|
|
921
|
+
- `@molecule/api-analytics`
|
|
922
|
+
- `@molecule/api-audit`
|
|
923
|
+
- `@molecule/api-audit-database`
|
|
924
|
+
- `@molecule/api-bond`
|
|
925
|
+
- `@molecule/api-cache`
|
|
926
|
+
- `@molecule/api-cache-memory`
|
|
927
|
+
- `@molecule/api-cache-redis`
|
|
928
|
+
- `@molecule/api-config`
|
|
929
|
+
- `@molecule/api-config-env`
|
|
930
|
+
- `@molecule/api-cron`
|
|
931
|
+
- `@molecule/api-cron-node-cron`
|
|
932
|
+
- `@molecule/api-database`
|
|
933
|
+
- `@molecule/api-database-postgresql`
|
|
934
|
+
- `@molecule/api-emails`
|
|
935
|
+
- `@molecule/api-emails-capture`
|
|
936
|
+
- `@molecule/api-emails-mailgun`
|
|
937
|
+
- `@molecule/api-encryption`
|
|
938
|
+
- `@molecule/api-encryption-aes`
|
|
939
|
+
- `@molecule/api-entitlements`
|
|
940
|
+
- `@molecule/api-error-tracking`
|
|
941
|
+
- `@molecule/api-error-tracking-console`
|
|
942
|
+
- `@molecule/api-error-tracking-sentry`
|
|
943
|
+
- `@molecule/api-geolocation`
|
|
944
|
+
- `@molecule/api-geolocation-google`
|
|
945
|
+
- `@molecule/api-geolocation-mapbox`
|
|
946
|
+
- `@molecule/api-geolocation-nominatim`
|
|
947
|
+
- `@molecule/api-http`
|
|
948
|
+
- `@molecule/api-http-fetch`
|
|
949
|
+
- `@molecule/api-i18n`
|
|
950
|
+
- `@molecule/api-image`
|
|
951
|
+
- `@molecule/api-image-sharp`
|
|
952
|
+
- `@molecule/api-import-export`
|
|
953
|
+
- `@molecule/api-import-export-csv`
|
|
954
|
+
- `@molecule/api-jwt`
|
|
955
|
+
- `@molecule/api-jwt-jsonwebtoken`
|
|
956
|
+
- `@molecule/api-logger`
|
|
957
|
+
- `@molecule/api-media-streaming`
|
|
958
|
+
- `@molecule/api-media-streaming-hls`
|
|
959
|
+
- `@molecule/api-middleware-body-parser`
|
|
960
|
+
- `@molecule/api-middleware-body-parser-express`
|
|
961
|
+
- `@molecule/api-middleware-cookie-parser`
|
|
962
|
+
- `@molecule/api-middleware-cookie-parser-express`
|
|
963
|
+
- `@molecule/api-middleware-cors`
|
|
964
|
+
- `@molecule/api-middleware-cors-express`
|
|
965
|
+
- `@molecule/api-middleware-validation`
|
|
966
|
+
- `@molecule/api-notifications-webhook`
|
|
967
|
+
- `@molecule/api-password`
|
|
968
|
+
- `@molecule/api-password-bcrypt`
|
|
969
|
+
- `@molecule/api-payments`
|
|
970
|
+
- `@molecule/api-payments-stripe`
|
|
971
|
+
- `@molecule/api-pdf`
|
|
972
|
+
- `@molecule/api-pdf-pdfkit`
|
|
973
|
+
- `@molecule/api-permissions`
|
|
974
|
+
- `@molecule/api-permissions-custom`
|
|
975
|
+
- `@molecule/api-push-capture`
|
|
976
|
+
- `@molecule/api-push-notifications`
|
|
977
|
+
- `@molecule/api-push-notifications-web-push`
|
|
978
|
+
- `@molecule/api-queue`
|
|
979
|
+
- `@molecule/api-queue-memory`
|
|
980
|
+
- `@molecule/api-queue-redis`
|
|
981
|
+
- `@molecule/api-rate-limit`
|
|
982
|
+
- `@molecule/api-rate-limit-memory`
|
|
983
|
+
- `@molecule/api-realtime`
|
|
984
|
+
- `@molecule/api-realtime-socketio`
|
|
985
|
+
- `@molecule/api-realtime-sse`
|
|
986
|
+
- `@molecule/api-realtime-ws`
|
|
987
|
+
- `@molecule/api-reporting`
|
|
988
|
+
- `@molecule/api-reporting-database`
|
|
989
|
+
- `@molecule/api-resource`
|
|
990
|
+
- `@molecule/api-resource-device`
|
|
991
|
+
- `@molecule/api-resource-payment`
|
|
992
|
+
- `@molecule/api-resource-user`
|
|
993
|
+
- `@molecule/api-search`
|
|
994
|
+
- `@molecule/api-search-meilisearch`
|
|
995
|
+
- `@molecule/api-search-postgres`
|
|
996
|
+
- `@molecule/api-secrets`
|
|
997
|
+
- `@molecule/api-secrets-env`
|
|
998
|
+
- `@molecule/api-two-factor`
|
|
999
|
+
- `@molecule/api-two-factor-otplib`
|
|
1000
|
+
- `@molecule/api-uploads`
|
|
1001
|
+
- `@molecule/api-uploads-filesystem`
|
|
1002
|
+
- `@molecule/api-uploads-s3`
|
|
1003
|
+
- `@molecule/api-webhook`
|
|
1004
|
+
- `@molecule/api-webhook-http`
|
|
1005
|
+
- `@molecule/api-workflow`
|
|
1006
|
+
- `@molecule/api-workflow-database`
|
|
1007
|
+
|
|
1008
|
+
- **Development falls back to zero-credential providers; production never
|
|
1009
|
+
does.** When `NODE_ENV !== 'production'` and a provider's required env
|
|
1010
|
+
is missing, the setup wires the capture/local sibling instead and logs
|
|
1011
|
+
the swap: mailgun→emails-capture (`MAILGUN_API_KEY`/`MAILGUN_DOMAIN`),
|
|
1012
|
+
uploads-s3→uploads-filesystem (`AWS_*`), search-meilisearch→
|
|
1013
|
+
search-postgres (`MEILISEARCH_URL`), web-push→push-capture
|
|
1014
|
+
(`VAPID_*`), geolocation-mapbox→nominatim (`MAPBOX_ACCESS_TOKEN`),
|
|
1015
|
+
cache-redis→cache-memory (`REDIS_URL`). In production the credentialed
|
|
1016
|
+
provider is wired regardless — missing env surfaces as loud,
|
|
1017
|
+
actionable 503s and boot-report entries, never a silent provider swap.
|
|
1018
|
+
So "emails don't arrive in dev" usually means they were CAPTURED (read
|
|
1019
|
+
them via the activity/capture tooling), not lost.
|
|
1020
|
+
- **Realtime setups (`setupRealtimeSocketio`, `setupRealtimeWs`,
|
|
1021
|
+
`setupRealtimeSse`) all defer-attach.** Each dynamic-imports its
|
|
1022
|
+
provider's `createProvider({ deferAttach: true })`, calls
|
|
1023
|
+
`setProvider()`, then `registerServerCreatedHook((server) =>
|
|
1024
|
+
provider.attachHttpServer?.(server))` from
|
|
1025
|
+
`@molecule/api-server-default-express` — so the realtime transport
|
|
1026
|
+
shares the API's HTTP server/port once it exists, instead of a
|
|
1027
|
+
standalone port a containerized sandbox / proxied deploy may not
|
|
1028
|
+
expose. Add new realtime bonds by mirroring this pattern exactly.
|
|
1029
|
+
- `createBillingRouter` registers the app's Stripe plan catalogue with
|
|
1030
|
+
`@molecule/api-resource-payment` at construction AND re-registers per
|
|
1031
|
+
checkout (price-id env vars may resolve after startup); webhook
|
|
1032
|
+
handling stays with `@molecule/api-resource-user`'s
|
|
1033
|
+
`handlePaymentNotification`. A paid price whose `planKeys` entry is
|
|
1034
|
+
missing is skipped WITH a warning — that plan could never be granted.
|
|
1035
|
+
- Only wire the setups whose packages your app actually installed —
|
|
1036
|
+
each one imports its provider package (several lazily via dynamic
|
|
1037
|
+
import), so calling a setup for an uninstalled bond fails at that
|
|
1038
|
+
import.
|