@odla-ai/chapter 0.5.0 → 0.8.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 +111 -28
- package/dist/index.cjs +175 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +157 -9
- package/dist/index.d.ts +157 -9
- package/dist/index.js +175 -17
- package/dist/index.js.map +1 -1
- package/dist/ui/index.d.ts +5 -1
- package/dist/ui/index.js +3 -2
- package/dist/ui/index.js.map +1 -1
- package/dist/worker/index.cjs +369 -17
- package/dist/worker/index.cjs.map +1 -1
- package/dist/worker/index.d.cts +69 -6
- package/dist/worker/index.d.ts +69 -6
- package/dist/worker/index.js +369 -17
- package/dist/worker/index.js.map +1 -1
- package/package.json +3 -3
package/dist/worker/index.d.cts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CrmConfig, Crm } from '@odla-ai/crm';
|
|
2
|
+
import { initAdmin } from '@odla-ai/db';
|
|
2
3
|
|
|
3
4
|
/** Which feature profile a site runs. `chapter` is the full public member site
|
|
4
5
|
* (join, Stripe membership, booking, member area, admin, CRM); `hub` is
|
|
@@ -188,7 +189,14 @@ interface ChapterConfig {
|
|
|
188
189
|
auth?: ChapterAuth;
|
|
189
190
|
/** odla services (db implied). Default `["db","calendar","o11y"]`. */
|
|
190
191
|
services?: readonly string[];
|
|
192
|
+
/** Apply-time account provisioning: `"invite"` (default) mints a Clerk
|
|
193
|
+
* invitation, `"create"` makes the account server-side (so join can say the
|
|
194
|
+
* account is ready), `"none"` skips it. Any of these needs a `clerk_secret_key`
|
|
195
|
+
* vault secret to act. */
|
|
196
|
+
account?: AccountModel;
|
|
191
197
|
}
|
|
198
|
+
/** Apply-time Clerk account provisioning model. */
|
|
199
|
+
type AccountModel = "invite" | "create" | "none";
|
|
192
200
|
/** The resolved engine `defineChapter()` returns. */
|
|
193
201
|
interface Chapter {
|
|
194
202
|
config: ChapterConfig;
|
|
@@ -208,6 +216,8 @@ interface Chapter {
|
|
|
208
216
|
schema: DbSchema;
|
|
209
217
|
rules: DbRules;
|
|
210
218
|
services: readonly string[];
|
|
219
|
+
/** Resolved apply-time account provisioning model (default `"invite"`). */
|
|
220
|
+
account: AccountModel;
|
|
211
221
|
/** The seed `groups` row derived from config (chapter mode), else `null`. */
|
|
212
222
|
groupSeed(): Record<string, unknown> | null;
|
|
213
223
|
}
|
|
@@ -246,15 +256,68 @@ interface ChapterWorkerOptions {
|
|
|
246
256
|
chapter: Chapter;
|
|
247
257
|
/** CRM mount point. Default "/api/crm". */
|
|
248
258
|
crmBasePath?: string;
|
|
259
|
+
/** Host routes, tried BEFORE the built-ins — so a wrapping site can add its own
|
|
260
|
+
* routes (or override/alias a built-in path) and reuse chapter's auth via the
|
|
261
|
+
* shared {@link WorkerContext}, instead of re-verifying JWTs itself. */
|
|
262
|
+
routes?: Route[];
|
|
249
263
|
}
|
|
264
|
+
/** The registry public-config a site reads to boot Clerk sign-in. */
|
|
265
|
+
type PublicConfig = {
|
|
266
|
+
env?: string;
|
|
267
|
+
clerkPublishableKey?: string | null;
|
|
268
|
+
issuer?: string | null;
|
|
269
|
+
};
|
|
270
|
+
/** The odla-db admin client type. */
|
|
271
|
+
type Db = ReturnType<typeof initAdmin>;
|
|
272
|
+
/** A verified session: the Clerk `sub`, optional email, and the raw JWT payload
|
|
273
|
+
* (so the role claim can be read for auth source "claim"). */
|
|
274
|
+
interface Verified {
|
|
275
|
+
userId: string;
|
|
276
|
+
email?: string;
|
|
277
|
+
payload: Record<string, unknown>;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Build the per-site Worker context: env-independent helpers closing over the
|
|
281
|
+
* public-config and JWKS caches, plus the source-aware auth gate (JWT claim or
|
|
282
|
+
* the odla-db `admins` allowlist). Constructed once per `chapterWorker` and
|
|
283
|
+
* shared by every route module.
|
|
284
|
+
*/
|
|
285
|
+
declare function createWorkerContext(options: ChapterWorkerOptions): {
|
|
286
|
+
chapter: Chapter;
|
|
287
|
+
auth: ResolvedAuth;
|
|
288
|
+
crmBase: string;
|
|
289
|
+
getPublicConfig: (env: ChapterEnv) => Promise<PublicConfig>;
|
|
290
|
+
verifyUser: (req: Request, env: ChapterEnv) => Promise<Verified | null>;
|
|
291
|
+
makeDb: (env: ChapterEnv) => Db;
|
|
292
|
+
isAdminEmail: (db: Db, email: string | undefined) => Promise<boolean>;
|
|
293
|
+
isSuperAdminEmail: (db: Db, email: string | undefined) => Promise<boolean>;
|
|
294
|
+
roleFor: (db: Db, u: Verified) => Promise<string>;
|
|
295
|
+
isAdmin: (db: Db, u: Verified) => Promise<boolean>;
|
|
296
|
+
crmSender: (env: ChapterEnv) => {
|
|
297
|
+
send(payload: EmailPayload): Promise<{
|
|
298
|
+
messageId: string;
|
|
299
|
+
}>;
|
|
300
|
+
} | undefined;
|
|
301
|
+
};
|
|
302
|
+
/** The value returned by {@link createWorkerContext}, threaded to every route. */
|
|
303
|
+
type WorkerContext = ReturnType<typeof createWorkerContext>;
|
|
304
|
+
/** A worker route handler: owns the request (returns a Response) or falls through
|
|
305
|
+
* (returns null). Host routes passed to `chapterWorker` compose against the same
|
|
306
|
+
* {@link WorkerContext} the built-ins receive. */
|
|
307
|
+
type Route = (req: Request, url: URL, env: ChapterEnv, ctx: WorkerContext) => Promise<Response | null>;
|
|
250
308
|
|
|
251
309
|
/**
|
|
252
310
|
* Build the Cloudflare `ExportedHandler` for a chapter/hub site: Clerk-JWT
|
|
253
|
-
* verification, the
|
|
254
|
-
*
|
|
255
|
-
*
|
|
256
|
-
*
|
|
257
|
-
*
|
|
311
|
+
* verification, the source-aware admin gate, the mounted @odla-ai/crm routes, the
|
|
312
|
+
* hub→chapter network projection, and the static-asset fallback. Hub mode serves
|
|
313
|
+
* /api/health, /api/config, /api/me, /api/crm/*, /api/network/shared; chapter mode
|
|
314
|
+
* adds the public member surface (join/apply/pay/book) and the admin surface
|
|
315
|
+
* (/api/admin/*).
|
|
316
|
+
*
|
|
317
|
+
* A wrapping site adds its own routes via `options.routes` — each receives the
|
|
318
|
+
* same {@link WorkerContext} the built-ins get (so it reuses chapter's JWT
|
|
319
|
+
* verify, db client, and role resolution instead of duplicating them), and runs
|
|
320
|
+
* BEFORE the built-ins so it can override or alias a path.
|
|
258
321
|
*
|
|
259
322
|
* Observability is a host concern, not a chapter dependency. To trace, wrap the
|
|
260
323
|
* result in your worker entry — `export default withObservability(chapterWorker(
|
|
@@ -265,4 +328,4 @@ declare function chapterWorker(options: ChapterWorkerOptions): {
|
|
|
265
328
|
fetch(req: Request, env: ChapterEnv): Promise<Response>;
|
|
266
329
|
};
|
|
267
330
|
|
|
268
|
-
export { type ChapterEnv, type ChapterWorkerOptions, chapterWorker };
|
|
331
|
+
export { type ChapterEnv, type ChapterWorkerOptions, type Route, type WorkerContext, chapterWorker, createWorkerContext };
|
package/dist/worker/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CrmConfig, Crm } from '@odla-ai/crm';
|
|
2
|
+
import { initAdmin } from '@odla-ai/db';
|
|
2
3
|
|
|
3
4
|
/** Which feature profile a site runs. `chapter` is the full public member site
|
|
4
5
|
* (join, Stripe membership, booking, member area, admin, CRM); `hub` is
|
|
@@ -188,7 +189,14 @@ interface ChapterConfig {
|
|
|
188
189
|
auth?: ChapterAuth;
|
|
189
190
|
/** odla services (db implied). Default `["db","calendar","o11y"]`. */
|
|
190
191
|
services?: readonly string[];
|
|
192
|
+
/** Apply-time account provisioning: `"invite"` (default) mints a Clerk
|
|
193
|
+
* invitation, `"create"` makes the account server-side (so join can say the
|
|
194
|
+
* account is ready), `"none"` skips it. Any of these needs a `clerk_secret_key`
|
|
195
|
+
* vault secret to act. */
|
|
196
|
+
account?: AccountModel;
|
|
191
197
|
}
|
|
198
|
+
/** Apply-time Clerk account provisioning model. */
|
|
199
|
+
type AccountModel = "invite" | "create" | "none";
|
|
192
200
|
/** The resolved engine `defineChapter()` returns. */
|
|
193
201
|
interface Chapter {
|
|
194
202
|
config: ChapterConfig;
|
|
@@ -208,6 +216,8 @@ interface Chapter {
|
|
|
208
216
|
schema: DbSchema;
|
|
209
217
|
rules: DbRules;
|
|
210
218
|
services: readonly string[];
|
|
219
|
+
/** Resolved apply-time account provisioning model (default `"invite"`). */
|
|
220
|
+
account: AccountModel;
|
|
211
221
|
/** The seed `groups` row derived from config (chapter mode), else `null`. */
|
|
212
222
|
groupSeed(): Record<string, unknown> | null;
|
|
213
223
|
}
|
|
@@ -246,15 +256,68 @@ interface ChapterWorkerOptions {
|
|
|
246
256
|
chapter: Chapter;
|
|
247
257
|
/** CRM mount point. Default "/api/crm". */
|
|
248
258
|
crmBasePath?: string;
|
|
259
|
+
/** Host routes, tried BEFORE the built-ins — so a wrapping site can add its own
|
|
260
|
+
* routes (or override/alias a built-in path) and reuse chapter's auth via the
|
|
261
|
+
* shared {@link WorkerContext}, instead of re-verifying JWTs itself. */
|
|
262
|
+
routes?: Route[];
|
|
249
263
|
}
|
|
264
|
+
/** The registry public-config a site reads to boot Clerk sign-in. */
|
|
265
|
+
type PublicConfig = {
|
|
266
|
+
env?: string;
|
|
267
|
+
clerkPublishableKey?: string | null;
|
|
268
|
+
issuer?: string | null;
|
|
269
|
+
};
|
|
270
|
+
/** The odla-db admin client type. */
|
|
271
|
+
type Db = ReturnType<typeof initAdmin>;
|
|
272
|
+
/** A verified session: the Clerk `sub`, optional email, and the raw JWT payload
|
|
273
|
+
* (so the role claim can be read for auth source "claim"). */
|
|
274
|
+
interface Verified {
|
|
275
|
+
userId: string;
|
|
276
|
+
email?: string;
|
|
277
|
+
payload: Record<string, unknown>;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Build the per-site Worker context: env-independent helpers closing over the
|
|
281
|
+
* public-config and JWKS caches, plus the source-aware auth gate (JWT claim or
|
|
282
|
+
* the odla-db `admins` allowlist). Constructed once per `chapterWorker` and
|
|
283
|
+
* shared by every route module.
|
|
284
|
+
*/
|
|
285
|
+
declare function createWorkerContext(options: ChapterWorkerOptions): {
|
|
286
|
+
chapter: Chapter;
|
|
287
|
+
auth: ResolvedAuth;
|
|
288
|
+
crmBase: string;
|
|
289
|
+
getPublicConfig: (env: ChapterEnv) => Promise<PublicConfig>;
|
|
290
|
+
verifyUser: (req: Request, env: ChapterEnv) => Promise<Verified | null>;
|
|
291
|
+
makeDb: (env: ChapterEnv) => Db;
|
|
292
|
+
isAdminEmail: (db: Db, email: string | undefined) => Promise<boolean>;
|
|
293
|
+
isSuperAdminEmail: (db: Db, email: string | undefined) => Promise<boolean>;
|
|
294
|
+
roleFor: (db: Db, u: Verified) => Promise<string>;
|
|
295
|
+
isAdmin: (db: Db, u: Verified) => Promise<boolean>;
|
|
296
|
+
crmSender: (env: ChapterEnv) => {
|
|
297
|
+
send(payload: EmailPayload): Promise<{
|
|
298
|
+
messageId: string;
|
|
299
|
+
}>;
|
|
300
|
+
} | undefined;
|
|
301
|
+
};
|
|
302
|
+
/** The value returned by {@link createWorkerContext}, threaded to every route. */
|
|
303
|
+
type WorkerContext = ReturnType<typeof createWorkerContext>;
|
|
304
|
+
/** A worker route handler: owns the request (returns a Response) or falls through
|
|
305
|
+
* (returns null). Host routes passed to `chapterWorker` compose against the same
|
|
306
|
+
* {@link WorkerContext} the built-ins receive. */
|
|
307
|
+
type Route = (req: Request, url: URL, env: ChapterEnv, ctx: WorkerContext) => Promise<Response | null>;
|
|
250
308
|
|
|
251
309
|
/**
|
|
252
310
|
* Build the Cloudflare `ExportedHandler` for a chapter/hub site: Clerk-JWT
|
|
253
|
-
* verification, the
|
|
254
|
-
*
|
|
255
|
-
*
|
|
256
|
-
*
|
|
257
|
-
*
|
|
311
|
+
* verification, the source-aware admin gate, the mounted @odla-ai/crm routes, the
|
|
312
|
+
* hub→chapter network projection, and the static-asset fallback. Hub mode serves
|
|
313
|
+
* /api/health, /api/config, /api/me, /api/crm/*, /api/network/shared; chapter mode
|
|
314
|
+
* adds the public member surface (join/apply/pay/book) and the admin surface
|
|
315
|
+
* (/api/admin/*).
|
|
316
|
+
*
|
|
317
|
+
* A wrapping site adds its own routes via `options.routes` — each receives the
|
|
318
|
+
* same {@link WorkerContext} the built-ins get (so it reuses chapter's JWT
|
|
319
|
+
* verify, db client, and role resolution instead of duplicating them), and runs
|
|
320
|
+
* BEFORE the built-ins so it can override or alias a path.
|
|
258
321
|
*
|
|
259
322
|
* Observability is a host concern, not a chapter dependency. To trace, wrap the
|
|
260
323
|
* result in your worker entry — `export default withObservability(chapterWorker(
|
|
@@ -265,4 +328,4 @@ declare function chapterWorker(options: ChapterWorkerOptions): {
|
|
|
265
328
|
fetch(req: Request, env: ChapterEnv): Promise<Response>;
|
|
266
329
|
};
|
|
267
330
|
|
|
268
|
-
export { type ChapterEnv, type ChapterWorkerOptions, chapterWorker };
|
|
331
|
+
export { type ChapterEnv, type ChapterWorkerOptions, type Route, type WorkerContext, chapterWorker, createWorkerContext };
|