@vertz/server 0.2.15 → 0.2.17
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/index.d.ts +440 -201
- package/dist/index.js +1488 -395
- package/package.json +5 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { AccumulateProvides, AppBuilder as AppBuilder2, AppConfig as AppConfig2, CorsConfig, Ctx, DeepReadonly, Deps, EnvConfig, HandlerCtx, HttpMethod, HttpStatusCode, Infer, InferSchema, ListenOptions, MiddlewareDef, NamedMiddlewareDef, RawRequest, ServerAdapter, ServerHandle } from "@vertz/core";
|
|
1
|
+
import { AccumulateProvides, AppBuilder as AppBuilder2, AppConfig as AppConfig2, CorsConfig, Ctx, DeepReadonly, Deps, EnvConfig, HandlerCtx, HttpMethod, HttpStatusCode, Infer as Infer2, InferSchema, ListenOptions, MiddlewareDef, NamedMiddlewareDef, RawRequest, ServerAdapter, ServerHandle } from "@vertz/core";
|
|
2
2
|
import { BadRequestException, ConflictException, createEnv, createImmutableProxy, createMiddleware, deepFreeze, ForbiddenException, InternalServerErrorException, makeImmutable, NotFoundException, ServiceUnavailableException, UnauthorizedException, ValidationException, VertzException, vertz } from "@vertz/core";
|
|
3
3
|
import { ModelEntry } from "@vertz/db";
|
|
4
4
|
import { AuthError, Result } from "@vertz/errors";
|
|
5
|
+
import { Infer, ObjectSchema, StringSchema } from "@vertz/schema";
|
|
5
6
|
/**
|
|
6
7
|
* rules.* builders — declarative access rule data structures.
|
|
7
8
|
*
|
|
@@ -280,15 +281,101 @@ declare class InMemoryRoleAssignmentStore implements RoleAssignmentStore {
|
|
|
280
281
|
* Used by Layer 1 of access context to gate entitlements on feature flags.
|
|
281
282
|
*/
|
|
282
283
|
interface FlagStore {
|
|
283
|
-
setFlag(
|
|
284
|
-
getFlag(
|
|
285
|
-
getFlags(
|
|
284
|
+
setFlag(tenantId: string, flag: string, enabled: boolean): void;
|
|
285
|
+
getFlag(tenantId: string, flag: string): boolean;
|
|
286
|
+
getFlags(tenantId: string): Record<string, boolean>;
|
|
286
287
|
}
|
|
287
288
|
declare class InMemoryFlagStore implements FlagStore {
|
|
288
289
|
private flags;
|
|
289
|
-
setFlag(
|
|
290
|
-
getFlag(
|
|
291
|
-
getFlags(
|
|
290
|
+
setFlag(tenantId: string, flag: string, enabled: boolean): void;
|
|
291
|
+
getFlag(tenantId: string, flag: string): boolean;
|
|
292
|
+
getFlags(tenantId: string): Record<string, boolean>;
|
|
293
|
+
}
|
|
294
|
+
/** Per-tenant limit override. Only affects the cap, not the billing period. */
|
|
295
|
+
interface LimitOverride {
|
|
296
|
+
max: number;
|
|
297
|
+
}
|
|
298
|
+
interface Subscription {
|
|
299
|
+
tenantId: string;
|
|
300
|
+
planId: string;
|
|
301
|
+
startedAt: Date;
|
|
302
|
+
expiresAt: Date | null;
|
|
303
|
+
overrides: Record<string, LimitOverride>;
|
|
304
|
+
}
|
|
305
|
+
interface SubscriptionStore {
|
|
306
|
+
/**
|
|
307
|
+
* Assign a plan to a tenant. Resets per-tenant overrides (overrides are plan-specific).
|
|
308
|
+
* To preserve overrides across plan changes, re-apply them after calling assign().
|
|
309
|
+
*/
|
|
310
|
+
assign(tenantId: string, planId: string, startedAt?: Date, expiresAt?: Date | null): Promise<void>;
|
|
311
|
+
get(tenantId: string): Promise<Subscription | null>;
|
|
312
|
+
updateOverrides(tenantId: string, overrides: Record<string, LimitOverride>): Promise<void>;
|
|
313
|
+
remove(tenantId: string): Promise<void>;
|
|
314
|
+
/** Attach an add-on to a tenant. */
|
|
315
|
+
attachAddOn?(tenantId: string, addOnId: string): Promise<void>;
|
|
316
|
+
/** Detach an add-on from a tenant. */
|
|
317
|
+
detachAddOn?(tenantId: string, addOnId: string): Promise<void>;
|
|
318
|
+
/** Get all active add-on IDs for a tenant. */
|
|
319
|
+
getAddOns?(tenantId: string): Promise<string[]>;
|
|
320
|
+
/** List all tenant IDs assigned to a specific plan. */
|
|
321
|
+
listByPlan?(planId: string): Promise<string[]>;
|
|
322
|
+
dispose(): void;
|
|
323
|
+
}
|
|
324
|
+
declare class InMemorySubscriptionStore implements SubscriptionStore {
|
|
325
|
+
private subscriptions;
|
|
326
|
+
private addOns;
|
|
327
|
+
assign(tenantId: string, planId: string, startedAt?: Date, expiresAt?: Date | null): Promise<void>;
|
|
328
|
+
get(tenantId: string): Promise<Subscription | null>;
|
|
329
|
+
updateOverrides(tenantId: string, overrides: Record<string, LimitOverride>): Promise<void>;
|
|
330
|
+
remove(tenantId: string): Promise<void>;
|
|
331
|
+
attachAddOn(tenantId: string, addOnId: string): Promise<void>;
|
|
332
|
+
detachAddOn(tenantId: string, addOnId: string): Promise<void>;
|
|
333
|
+
getAddOns(tenantId: string): Promise<string[]>;
|
|
334
|
+
listByPlan(planId: string): Promise<string[]>;
|
|
335
|
+
dispose(): void;
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Check if an add-on is compatible with a given base plan.
|
|
339
|
+
* Returns true if the add-on has no `requires` or if the plan is in the requires list.
|
|
340
|
+
*/
|
|
341
|
+
declare function checkAddOnCompatibility(accessDef: AccessDefinition, addOnId: string, currentPlanId: string): boolean;
|
|
342
|
+
/**
|
|
343
|
+
* Get add-ons that are incompatible with a target plan.
|
|
344
|
+
* Used to flag incompatible add-ons when a tenant downgrades.
|
|
345
|
+
*/
|
|
346
|
+
declare function getIncompatibleAddOns(accessDef: AccessDefinition, activeAddOnIds: string[], targetPlanId: string): string[];
|
|
347
|
+
/**
|
|
348
|
+
* WalletStore — consumption tracking for plan-limited entitlements.
|
|
349
|
+
*
|
|
350
|
+
* Tracks per-tenant usage within billing periods with atomic
|
|
351
|
+
* check-and-increment operations.
|
|
352
|
+
*/
|
|
353
|
+
interface WalletEntry {
|
|
354
|
+
tenantId: string;
|
|
355
|
+
entitlement: string;
|
|
356
|
+
periodStart: Date;
|
|
357
|
+
periodEnd: Date;
|
|
358
|
+
consumed: number;
|
|
359
|
+
}
|
|
360
|
+
interface ConsumeResult {
|
|
361
|
+
success: boolean;
|
|
362
|
+
consumed: number;
|
|
363
|
+
limit: number;
|
|
364
|
+
remaining: number;
|
|
365
|
+
}
|
|
366
|
+
interface WalletStore {
|
|
367
|
+
consume(tenantId: string, entitlement: string, periodStart: Date, periodEnd: Date, limit: number, amount?: number): Promise<ConsumeResult>;
|
|
368
|
+
unconsume(tenantId: string, entitlement: string, periodStart: Date, periodEnd: Date, amount?: number): Promise<void>;
|
|
369
|
+
getConsumption(tenantId: string, entitlement: string, periodStart: Date, periodEnd: Date): Promise<number>;
|
|
370
|
+
dispose(): void;
|
|
371
|
+
}
|
|
372
|
+
declare class InMemoryWalletStore implements WalletStore {
|
|
373
|
+
private entries;
|
|
374
|
+
private key;
|
|
375
|
+
consume(tenantId: string, entitlement: string, periodStart: Date, periodEnd: Date, limit: number, amount?: number): Promise<ConsumeResult>;
|
|
376
|
+
unconsume(tenantId: string, entitlement: string, periodStart: Date, _periodEnd: Date, amount?: number): Promise<void>;
|
|
377
|
+
getConsumption(tenantId: string, entitlement: string, periodStart: Date, _periodEnd: Date): Promise<number>;
|
|
378
|
+
dispose(): void;
|
|
292
379
|
}
|
|
293
380
|
/** Limit override: add (additive) or max (hard cap) */
|
|
294
381
|
interface LimitOverrideDef {
|
|
@@ -324,59 +411,6 @@ declare class InMemoryOverrideStore implements OverrideStore {
|
|
|
324
411
|
* Throws on invalid limit keys, invalid feature names, or invalid max values.
|
|
325
412
|
*/
|
|
326
413
|
declare function validateOverrides(accessDef: AccessDefinition, overrides: TenantOverrides): void;
|
|
327
|
-
/** Per-customer limit override. Only affects the cap, not the billing period. */
|
|
328
|
-
interface LimitOverride {
|
|
329
|
-
max: number;
|
|
330
|
-
}
|
|
331
|
-
interface OrgPlan {
|
|
332
|
-
orgId: string;
|
|
333
|
-
planId: string;
|
|
334
|
-
startedAt: Date;
|
|
335
|
-
expiresAt: Date | null;
|
|
336
|
-
overrides: Record<string, LimitOverride>;
|
|
337
|
-
}
|
|
338
|
-
interface PlanStore {
|
|
339
|
-
/**
|
|
340
|
-
* Assign a plan to an org. Resets per-customer overrides (overrides are plan-specific).
|
|
341
|
-
* To preserve overrides across plan changes, re-apply them after calling assignPlan().
|
|
342
|
-
*/
|
|
343
|
-
assignPlan(orgId: string, planId: string, startedAt?: Date, expiresAt?: Date | null): Promise<void>;
|
|
344
|
-
getPlan(orgId: string): Promise<OrgPlan | null>;
|
|
345
|
-
updateOverrides(orgId: string, overrides: Record<string, LimitOverride>): Promise<void>;
|
|
346
|
-
removePlan(orgId: string): Promise<void>;
|
|
347
|
-
/** Attach an add-on to an org. */
|
|
348
|
-
attachAddOn?(orgId: string, addOnId: string): Promise<void>;
|
|
349
|
-
/** Detach an add-on from an org. */
|
|
350
|
-
detachAddOn?(orgId: string, addOnId: string): Promise<void>;
|
|
351
|
-
/** Get all active add-on IDs for an org. */
|
|
352
|
-
getAddOns?(orgId: string): Promise<string[]>;
|
|
353
|
-
/** List all org IDs assigned to a specific plan. */
|
|
354
|
-
listByPlan?(planId: string): Promise<string[]>;
|
|
355
|
-
dispose(): void;
|
|
356
|
-
}
|
|
357
|
-
declare class InMemoryPlanStore implements PlanStore {
|
|
358
|
-
private plans;
|
|
359
|
-
private addOns;
|
|
360
|
-
assignPlan(orgId: string, planId: string, startedAt?: Date, expiresAt?: Date | null): Promise<void>;
|
|
361
|
-
getPlan(orgId: string): Promise<OrgPlan | null>;
|
|
362
|
-
updateOverrides(orgId: string, overrides: Record<string, LimitOverride>): Promise<void>;
|
|
363
|
-
removePlan(orgId: string): Promise<void>;
|
|
364
|
-
attachAddOn(orgId: string, addOnId: string): Promise<void>;
|
|
365
|
-
detachAddOn(orgId: string, addOnId: string): Promise<void>;
|
|
366
|
-
getAddOns(orgId: string): Promise<string[]>;
|
|
367
|
-
listByPlan(planId: string): Promise<string[]>;
|
|
368
|
-
dispose(): void;
|
|
369
|
-
}
|
|
370
|
-
/**
|
|
371
|
-
* Check if an add-on is compatible with a given base plan.
|
|
372
|
-
* Returns true if the add-on has no `requires` or if the plan is in the requires list.
|
|
373
|
-
*/
|
|
374
|
-
declare function checkAddOnCompatibility(accessDef: AccessDefinition, addOnId: string, currentPlanId: string): boolean;
|
|
375
|
-
/**
|
|
376
|
-
* Get add-ons that are incompatible with a target plan.
|
|
377
|
-
* Used to flag incompatible add-ons when a tenant downgrades.
|
|
378
|
-
*/
|
|
379
|
-
declare function getIncompatibleAddOns(accessDef: AccessDefinition, activeAddOnIds: string[], targetPlanId: string): string[];
|
|
380
414
|
/**
|
|
381
415
|
* Plan Version Store — tracks versioned snapshots of plan configurations.
|
|
382
416
|
*
|
|
@@ -425,39 +459,6 @@ declare class InMemoryPlanVersionStore implements PlanVersionStore {
|
|
|
425
459
|
getCurrentHash(planId: string): Promise<string | null>;
|
|
426
460
|
dispose(): void;
|
|
427
461
|
}
|
|
428
|
-
/**
|
|
429
|
-
* WalletStore — consumption tracking for plan-limited entitlements.
|
|
430
|
-
*
|
|
431
|
-
* Tracks per-org usage within billing periods with atomic
|
|
432
|
-
* check-and-increment operations.
|
|
433
|
-
*/
|
|
434
|
-
interface WalletEntry {
|
|
435
|
-
orgId: string;
|
|
436
|
-
entitlement: string;
|
|
437
|
-
periodStart: Date;
|
|
438
|
-
periodEnd: Date;
|
|
439
|
-
consumed: number;
|
|
440
|
-
}
|
|
441
|
-
interface ConsumeResult {
|
|
442
|
-
success: boolean;
|
|
443
|
-
consumed: number;
|
|
444
|
-
limit: number;
|
|
445
|
-
remaining: number;
|
|
446
|
-
}
|
|
447
|
-
interface WalletStore {
|
|
448
|
-
consume(orgId: string, entitlement: string, periodStart: Date, periodEnd: Date, limit: number, amount?: number): Promise<ConsumeResult>;
|
|
449
|
-
unconsume(orgId: string, entitlement: string, periodStart: Date, periodEnd: Date, amount?: number): Promise<void>;
|
|
450
|
-
getConsumption(orgId: string, entitlement: string, periodStart: Date, periodEnd: Date): Promise<number>;
|
|
451
|
-
dispose(): void;
|
|
452
|
-
}
|
|
453
|
-
declare class InMemoryWalletStore implements WalletStore {
|
|
454
|
-
private entries;
|
|
455
|
-
private key;
|
|
456
|
-
consume(orgId: string, entitlement: string, periodStart: Date, periodEnd: Date, limit: number, amount?: number): Promise<ConsumeResult>;
|
|
457
|
-
unconsume(orgId: string, entitlement: string, periodStart: Date, _periodEnd: Date, amount?: number): Promise<void>;
|
|
458
|
-
getConsumption(orgId: string, entitlement: string, periodStart: Date, _periodEnd: Date): Promise<number>;
|
|
459
|
-
dispose(): void;
|
|
460
|
-
}
|
|
461
462
|
interface ResourceRef {
|
|
462
463
|
type: string;
|
|
463
464
|
id: string;
|
|
@@ -471,8 +472,8 @@ interface AccessContextConfig {
|
|
|
471
472
|
fva?: number;
|
|
472
473
|
/** Flag store — required for Layer 1 feature flag checks */
|
|
473
474
|
flagStore?: FlagStore;
|
|
474
|
-
/**
|
|
475
|
-
|
|
475
|
+
/** Subscription store — required for Layer 4 plan checks */
|
|
476
|
+
subscriptionStore?: SubscriptionStore;
|
|
476
477
|
/** Wallet store — required for Layer 5 wallet checks and canAndConsume() */
|
|
477
478
|
walletStore?: WalletStore;
|
|
478
479
|
/** Override store — per-tenant feature and limit overrides */
|
|
@@ -482,20 +483,28 @@ interface AccessContextConfig {
|
|
|
482
483
|
/** Plan version store — required for versioned plan resolution (grandfathered tenants) */
|
|
483
484
|
planVersionStore?: PlanVersionStore;
|
|
484
485
|
}
|
|
486
|
+
/**
|
|
487
|
+
* Entitlement registry — augmented by @vertz/codegen to narrow entitlement strings.
|
|
488
|
+
* When empty (no codegen), Entitlement falls back to `string`.
|
|
489
|
+
* When codegen runs, it populates this with `{ 'entity:action': true }` entries.
|
|
490
|
+
*/
|
|
491
|
+
interface EntitlementRegistry {}
|
|
492
|
+
/** Entitlement type — narrows to literal union when codegen populates EntitlementRegistry. */
|
|
493
|
+
type Entitlement = keyof EntitlementRegistry extends never ? string : Extract<keyof EntitlementRegistry, string>;
|
|
485
494
|
interface AccessContext {
|
|
486
|
-
can(entitlement:
|
|
487
|
-
check(entitlement:
|
|
488
|
-
authorize(entitlement:
|
|
495
|
+
can(entitlement: Entitlement, resource?: ResourceRef): Promise<boolean>;
|
|
496
|
+
check(entitlement: Entitlement, resource?: ResourceRef): Promise<AccessCheckResult>;
|
|
497
|
+
authorize(entitlement: Entitlement, resource?: ResourceRef): Promise<void>;
|
|
489
498
|
canAll(checks: Array<{
|
|
490
|
-
entitlement:
|
|
499
|
+
entitlement: Entitlement;
|
|
491
500
|
resource?: ResourceRef;
|
|
492
501
|
}>): Promise<Map<string, boolean>>;
|
|
493
502
|
/** Batch check: single entitlement across multiple entities. Returns Map<entityId, boolean>. */
|
|
494
|
-
canBatch(entitlement:
|
|
503
|
+
canBatch(entitlement: Entitlement, resources: ResourceRef[]): Promise<Map<string, boolean>>;
|
|
495
504
|
/** Atomic check + consume. Runs full can() then increments wallet if all layers pass. */
|
|
496
|
-
canAndConsume(entitlement:
|
|
505
|
+
canAndConsume(entitlement: Entitlement, resource?: ResourceRef, amount?: number): Promise<boolean>;
|
|
497
506
|
/** Rollback a previous canAndConsume(). Use when the operation fails after consumption. */
|
|
498
|
-
unconsume(entitlement:
|
|
507
|
+
unconsume(entitlement: Entitlement, resource?: ResourceRef, amount?: number): Promise<void>;
|
|
499
508
|
}
|
|
500
509
|
declare function createAccessContext(config: AccessContextConfig): AccessContext;
|
|
501
510
|
interface AccessCheckData {
|
|
@@ -515,17 +524,16 @@ interface ComputeAccessSetConfig {
|
|
|
515
524
|
accessDef: AccessDefinition;
|
|
516
525
|
roleStore: RoleAssignmentStore;
|
|
517
526
|
closureStore: ClosureStore;
|
|
518
|
-
plan?: string | null;
|
|
519
527
|
/** Flag store — for feature flag state in access set */
|
|
520
528
|
flagStore?: FlagStore;
|
|
521
|
-
/**
|
|
522
|
-
|
|
529
|
+
/** Subscription store — for limit info in access set */
|
|
530
|
+
subscriptionStore?: SubscriptionStore;
|
|
523
531
|
/** Wallet store — for consumption info in access set */
|
|
524
532
|
walletStore?: WalletStore;
|
|
525
533
|
/** Org resolver — for plan/wallet lookups */
|
|
526
534
|
orgResolver?: (resource?: ResourceRef) => Promise<string | null>;
|
|
527
|
-
/**
|
|
528
|
-
|
|
535
|
+
/** Tenant ID — direct tenant ID for global access set (bypass orgResolver) */
|
|
536
|
+
tenantId?: string | null;
|
|
529
537
|
}
|
|
530
538
|
declare function computeAccessSet(config: ComputeAccessSetConfig): Promise<AccessSet>;
|
|
531
539
|
/** Sparse encoding for JWT. Only includes allowed + denied-with-meta entries. */
|
|
@@ -593,6 +601,7 @@ interface SessionStore {
|
|
|
593
601
|
expiresAt: Date;
|
|
594
602
|
currentTokens?: AuthTokens;
|
|
595
603
|
}): Promise<StoredSession>;
|
|
604
|
+
findActiveSessionById(id: string): Promise<StoredSession | null>;
|
|
596
605
|
findByRefreshHash(hash: string): Promise<StoredSession | null>;
|
|
597
606
|
findByPreviousRefreshHash(hash: string): Promise<StoredSession | null>;
|
|
598
607
|
revokeSession(id: string): Promise<void>;
|
|
@@ -632,6 +641,8 @@ interface UserStore {
|
|
|
632
641
|
findById(id: string): Promise<AuthUser | null>;
|
|
633
642
|
updatePasswordHash(userId: string, passwordHash: string): Promise<void>;
|
|
634
643
|
updateEmailVerified(userId: string, verified: boolean): Promise<void>;
|
|
644
|
+
/** Delete a user by id. Used for rollback when onUserCreated fails. */
|
|
645
|
+
deleteUser(id: string): Promise<void>;
|
|
635
646
|
}
|
|
636
647
|
interface MfaConfig {
|
|
637
648
|
enabled?: boolean;
|
|
@@ -673,8 +684,7 @@ interface OAuthUserInfo {
|
|
|
673
684
|
providerId: string;
|
|
674
685
|
email: string;
|
|
675
686
|
emailVerified: boolean;
|
|
676
|
-
|
|
677
|
-
avatarUrl?: string;
|
|
687
|
+
raw: Record<string, unknown>;
|
|
678
688
|
}
|
|
679
689
|
interface OAuthProvider {
|
|
680
690
|
id: string;
|
|
@@ -695,6 +705,45 @@ interface OAuthAccountStore {
|
|
|
695
705
|
unlinkAccount(userId: string, provider: string): Promise<void>;
|
|
696
706
|
dispose(): void;
|
|
697
707
|
}
|
|
708
|
+
/** Context provided to auth lifecycle callbacks. */
|
|
709
|
+
interface AuthCallbackContext {
|
|
710
|
+
/**
|
|
711
|
+
* System-level entity access — bypasses access rules.
|
|
712
|
+
* During sign-up, the user isn't authenticated yet,
|
|
713
|
+
* so access rules like rules.authenticated() would block the callback.
|
|
714
|
+
*/
|
|
715
|
+
entities: Record<string, AuthEntityProxy>;
|
|
716
|
+
}
|
|
717
|
+
/** Minimal CRUD interface for entity access within auth callbacks. */
|
|
718
|
+
interface AuthEntityProxy {
|
|
719
|
+
get(id: string): Promise<unknown>;
|
|
720
|
+
list(options?: unknown): Promise<unknown>;
|
|
721
|
+
create(data: Record<string, unknown>): Promise<unknown>;
|
|
722
|
+
update(id: string, data: Record<string, unknown>): Promise<unknown>;
|
|
723
|
+
delete(id: string): Promise<void>;
|
|
724
|
+
}
|
|
725
|
+
/**
|
|
726
|
+
* Discriminated union for onUserCreated callback payload.
|
|
727
|
+
* OAuth and email/password sign-ups provide different data shapes.
|
|
728
|
+
*/
|
|
729
|
+
type OnUserCreatedPayload = {
|
|
730
|
+
/** The auth user that was just created. */
|
|
731
|
+
user: AuthUser;
|
|
732
|
+
/** The OAuth provider that created this user. */
|
|
733
|
+
provider: {
|
|
734
|
+
id: string;
|
|
735
|
+
name: string;
|
|
736
|
+
};
|
|
737
|
+
/** Full provider API response (cast to GithubProfile, GoogleProfile, etc.). */
|
|
738
|
+
profile: Record<string, unknown>;
|
|
739
|
+
} | {
|
|
740
|
+
/** The auth user that was just created. */
|
|
741
|
+
user: AuthUser;
|
|
742
|
+
/** null for email/password sign-up. */
|
|
743
|
+
provider: null;
|
|
744
|
+
/** Extra fields from the sign-up form (via schema passthrough). */
|
|
745
|
+
signUpData: Record<string, unknown>;
|
|
746
|
+
};
|
|
698
747
|
interface EmailVerificationConfig {
|
|
699
748
|
enabled: boolean;
|
|
700
749
|
tokenTtl?: string | number;
|
|
@@ -790,6 +839,21 @@ interface AuthConfig {
|
|
|
790
839
|
passwordResetStore?: PasswordResetStore;
|
|
791
840
|
/** Access control configuration — enables ACL claim in JWT */
|
|
792
841
|
access?: AuthAccessConfig;
|
|
842
|
+
/** Tenant switching configuration — enables POST /auth/switch-tenant */
|
|
843
|
+
tenant?: TenantConfig;
|
|
844
|
+
/**
|
|
845
|
+
* Called after a new user is created in the auth system.
|
|
846
|
+
* Fires before the session is created.
|
|
847
|
+
* If this throws, the auth user is rolled back (deleted).
|
|
848
|
+
*/
|
|
849
|
+
onUserCreated?: (payload: OnUserCreatedPayload, ctx: AuthCallbackContext) => Promise<void>;
|
|
850
|
+
/** @internal Entity proxy for onUserCreated callback. Set by createServer(). */
|
|
851
|
+
_entityProxy?: Record<string, AuthEntityProxy>;
|
|
852
|
+
}
|
|
853
|
+
/** Configuration for multi-tenant session switching. */
|
|
854
|
+
interface TenantConfig {
|
|
855
|
+
/** Verify that user has membership in the target tenant. Return false to deny. */
|
|
856
|
+
verifyMembership: (userId: string, tenantId: string) => Promise<boolean>;
|
|
793
857
|
}
|
|
794
858
|
/** Access control configuration for JWT acl claim computation. */
|
|
795
859
|
interface AuthAccessConfig {
|
|
@@ -797,16 +861,16 @@ interface AuthAccessConfig {
|
|
|
797
861
|
roleStore: RoleAssignmentStore;
|
|
798
862
|
closureStore: ClosureStore;
|
|
799
863
|
flagStore?: FlagStore;
|
|
864
|
+
subscriptionStore?: SubscriptionStore;
|
|
865
|
+
walletStore?: WalletStore;
|
|
800
866
|
}
|
|
801
867
|
interface AuthUser {
|
|
802
868
|
id: string;
|
|
803
869
|
email: string;
|
|
804
870
|
role: string;
|
|
805
|
-
plan?: string;
|
|
806
871
|
emailVerified?: boolean;
|
|
807
872
|
createdAt: Date;
|
|
808
873
|
updatedAt: Date;
|
|
809
|
-
[key: string]: unknown;
|
|
810
874
|
}
|
|
811
875
|
interface SessionPayload {
|
|
812
876
|
sub: string;
|
|
@@ -816,6 +880,7 @@ interface SessionPayload {
|
|
|
816
880
|
exp: number;
|
|
817
881
|
jti: string;
|
|
818
882
|
sid: string;
|
|
883
|
+
tenantId?: string;
|
|
819
884
|
claims?: Record<string, unknown>;
|
|
820
885
|
fva?: number;
|
|
821
886
|
acl?: AclClaim;
|
|
@@ -850,16 +915,18 @@ interface SessionInfo {
|
|
|
850
915
|
expiresAt: Date;
|
|
851
916
|
isCurrent: boolean;
|
|
852
917
|
}
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
}
|
|
859
|
-
|
|
860
|
-
email:
|
|
861
|
-
password:
|
|
862
|
-
}
|
|
918
|
+
type ReservedSignUpField = "role" | "emailVerified" | "id" | "createdAt" | "updatedAt";
|
|
919
|
+
type ReservedSignUpFields = { [K in ReservedSignUpField]? : never };
|
|
920
|
+
declare const signUpInputSchema: ObjectSchema<{
|
|
921
|
+
email: StringSchema;
|
|
922
|
+
password: StringSchema;
|
|
923
|
+
}>;
|
|
924
|
+
declare const signInInputSchema: ObjectSchema<{
|
|
925
|
+
email: StringSchema;
|
|
926
|
+
password: StringSchema;
|
|
927
|
+
}>;
|
|
928
|
+
type SignUpInput = Infer<typeof signUpInputSchema> & ReservedSignUpFields & Record<string, unknown>;
|
|
929
|
+
type SignInInput = Infer<typeof signInInputSchema>;
|
|
863
930
|
interface AuthApi {
|
|
864
931
|
signUp: (data: SignUpInput, ctx?: {
|
|
865
932
|
headers: Headers;
|
|
@@ -889,6 +956,19 @@ interface AuthInstance {
|
|
|
889
956
|
initialize: () => Promise<void>;
|
|
890
957
|
/** Dispose stores and cleanup intervals */
|
|
891
958
|
dispose: () => void;
|
|
959
|
+
/**
|
|
960
|
+
* JWT-only session resolver for SSR injection.
|
|
961
|
+
* Reads the session cookie, verifies JWT (no DB lookup), and returns
|
|
962
|
+
* minimal session data + optional access set for client hydration.
|
|
963
|
+
*/
|
|
964
|
+
resolveSessionForSSR: (request: Request) => Promise<{
|
|
965
|
+
session: {
|
|
966
|
+
user: Record<string, unknown>;
|
|
967
|
+
expiresAt: number;
|
|
968
|
+
};
|
|
969
|
+
/** AccessSet | null at runtime; typed as unknown to avoid cross-package dependency on @vertz/ui */
|
|
970
|
+
accessSet?: unknown;
|
|
971
|
+
} | null>;
|
|
892
972
|
}
|
|
893
973
|
interface AuthContext {
|
|
894
974
|
headers: Headers;
|
|
@@ -914,9 +994,6 @@ interface UserTableEntry extends ModelEntry<any, any> {
|
|
|
914
994
|
role: {
|
|
915
995
|
type: string;
|
|
916
996
|
};
|
|
917
|
-
plan?: {
|
|
918
|
-
type: string;
|
|
919
|
-
};
|
|
920
997
|
createdAt: {
|
|
921
998
|
type: Date;
|
|
922
999
|
};
|
|
@@ -945,9 +1022,8 @@ import { AuthValidationError } from "@vertz/errors";
|
|
|
945
1022
|
declare function hashPassword(password: string): Promise<string>;
|
|
946
1023
|
declare function verifyPassword(password: string, hash: string): Promise<boolean>;
|
|
947
1024
|
declare function validatePassword(password: string, requirements?: PasswordRequirements): AuthValidationError | null;
|
|
948
|
-
type Entitlement = string;
|
|
949
1025
|
interface RoleDefinition {
|
|
950
|
-
entitlements:
|
|
1026
|
+
entitlements: string[];
|
|
951
1027
|
}
|
|
952
1028
|
interface EntitlementDefinition {
|
|
953
1029
|
roles: string[];
|
|
@@ -960,20 +1036,20 @@ interface AccessConfig {
|
|
|
960
1036
|
}
|
|
961
1037
|
interface AccessInstance {
|
|
962
1038
|
/** Check if user has a specific entitlement */
|
|
963
|
-
can(entitlement:
|
|
1039
|
+
can(entitlement: string, user: AuthUser | null): Promise<boolean>;
|
|
964
1040
|
/** Check with resource context */
|
|
965
|
-
canWithResource(entitlement:
|
|
1041
|
+
canWithResource(entitlement: string, resource: Resource, user: AuthUser | null): Promise<boolean>;
|
|
966
1042
|
/** Throws if not authorized */
|
|
967
|
-
authorize(entitlement:
|
|
1043
|
+
authorize(entitlement: string, user: AuthUser | null): Promise<void>;
|
|
968
1044
|
/** Authorize with resource context */
|
|
969
|
-
authorizeWithResource(entitlement:
|
|
1045
|
+
authorizeWithResource(entitlement: string, resource: Resource, user: AuthUser | null): Promise<void>;
|
|
970
1046
|
/** Check multiple entitlements at once */
|
|
971
1047
|
canAll(checks: Array<{
|
|
972
|
-
entitlement:
|
|
1048
|
+
entitlement: string;
|
|
973
1049
|
resource?: Resource;
|
|
974
1050
|
}>, user: AuthUser | null): Promise<Map<string, boolean>>;
|
|
975
1051
|
/** Get all entitlements for a role */
|
|
976
|
-
getEntitlementsForRole(role: string):
|
|
1052
|
+
getEntitlementsForRole(role: string): string[];
|
|
977
1053
|
/** Middleware that adds ctx.can() and ctx.authorize() to context */
|
|
978
1054
|
middleware: () => any;
|
|
979
1055
|
}
|
|
@@ -984,9 +1060,9 @@ interface Resource {
|
|
|
984
1060
|
[key: string]: unknown;
|
|
985
1061
|
}
|
|
986
1062
|
declare class AuthorizationError extends Error {
|
|
987
|
-
readonly entitlement:
|
|
1063
|
+
readonly entitlement: string;
|
|
988
1064
|
readonly userId?: string | undefined;
|
|
989
|
-
constructor(message: string, entitlement:
|
|
1065
|
+
constructor(message: string, entitlement: string, userId?: string | undefined);
|
|
990
1066
|
}
|
|
991
1067
|
declare function createAccess(config: AccessConfig): AccessInstance;
|
|
992
1068
|
declare const defaultAccess: AccessInstance;
|
|
@@ -1071,22 +1147,17 @@ interface BunWebSocket<T> {
|
|
|
1071
1147
|
declare function createAccessEventBroadcaster(config: AccessEventBroadcasterConfig): AccessEventBroadcaster;
|
|
1072
1148
|
import { ModelDef } from "@vertz/db";
|
|
1073
1149
|
declare const authModels: Record<string, ModelDef>;
|
|
1074
|
-
import {
|
|
1075
|
-
|
|
1076
|
-
import { Result as Result2 } from "@vertz/errors";
|
|
1150
|
+
import { DatabaseClient } from "@vertz/db";
|
|
1151
|
+
type AuthModels = typeof authModels;
|
|
1077
1152
|
/**
|
|
1078
1153
|
* Minimal database interface for auth stores.
|
|
1079
|
-
*
|
|
1154
|
+
*
|
|
1155
|
+
* Keeps raw query support for legacy stores, but exposes the typed
|
|
1156
|
+
* `auth_sessions` delegate so session lookups can go through the generated
|
|
1157
|
+
* client instead of ad hoc SQL strings. Includes `transaction` for atomic
|
|
1158
|
+
* multi-statement writes in plan and closure stores.
|
|
1080
1159
|
*/
|
|
1081
|
-
|
|
1082
|
-
query<T = Record<string, unknown>>(fragment: SqlFragment): Promise<Result2<QueryResult<T>, ReadError>>;
|
|
1083
|
-
_internals: {
|
|
1084
|
-
readonly models: Record<string, unknown>;
|
|
1085
|
-
readonly dialect: {
|
|
1086
|
-
readonly name: "postgres" | "sqlite";
|
|
1087
|
-
};
|
|
1088
|
-
};
|
|
1089
|
-
}
|
|
1160
|
+
type AuthDbClient = Pick<DatabaseClient<AuthModels>, "auth_sessions" | "query" | "_internals" | "transaction">;
|
|
1090
1161
|
/**
|
|
1091
1162
|
* Dialect-aware DDL helpers for auth table creation.
|
|
1092
1163
|
*
|
|
@@ -1218,7 +1289,7 @@ interface StripeBillingAdapterConfig {
|
|
|
1218
1289
|
}
|
|
1219
1290
|
declare function createStripeBillingAdapter(config: StripeBillingAdapterConfig): BillingAdapter;
|
|
1220
1291
|
interface WebhookHandlerConfig {
|
|
1221
|
-
|
|
1292
|
+
subscriptionStore: SubscriptionStore;
|
|
1222
1293
|
emitter: BillingEventEmitter;
|
|
1223
1294
|
defaultPlan: string;
|
|
1224
1295
|
webhookSecret: string;
|
|
@@ -1269,19 +1340,6 @@ declare class DbOAuthAccountStore implements OAuthAccountStore {
|
|
|
1269
1340
|
unlinkAccount(userId: string, provider: string): Promise<void>;
|
|
1270
1341
|
dispose(): void;
|
|
1271
1342
|
}
|
|
1272
|
-
declare class DbPlanStore implements PlanStore {
|
|
1273
|
-
private db;
|
|
1274
|
-
constructor(db: AuthDbClient);
|
|
1275
|
-
assignPlan(orgId: string, planId: string, startedAt?: Date, expiresAt?: Date | null): Promise<void>;
|
|
1276
|
-
getPlan(orgId: string): Promise<OrgPlan | null>;
|
|
1277
|
-
updateOverrides(orgId: string, overrides: Record<string, LimitOverride>): Promise<void>;
|
|
1278
|
-
removePlan(orgId: string): Promise<void>;
|
|
1279
|
-
attachAddOn(orgId: string, addOnId: string): Promise<void>;
|
|
1280
|
-
detachAddOn(orgId: string, addOnId: string): Promise<void>;
|
|
1281
|
-
getAddOns(orgId: string): Promise<string[]>;
|
|
1282
|
-
dispose(): void;
|
|
1283
|
-
private loadOverrides;
|
|
1284
|
-
}
|
|
1285
1343
|
declare class DbRoleAssignmentStore implements RoleAssignmentStore {
|
|
1286
1344
|
private db;
|
|
1287
1345
|
constructor(db: AuthDbClient);
|
|
@@ -1304,6 +1362,7 @@ declare class DbSessionStore implements SessionStore {
|
|
|
1304
1362
|
currentTokens?: AuthTokens;
|
|
1305
1363
|
}): Promise<StoredSession>;
|
|
1306
1364
|
findByRefreshHash(hash: string): Promise<StoredSession | null>;
|
|
1365
|
+
findActiveSessionById(id: string): Promise<StoredSession | null>;
|
|
1307
1366
|
findByPreviousRefreshHash(hash: string): Promise<StoredSession | null>;
|
|
1308
1367
|
revokeSession(id: string): Promise<void>;
|
|
1309
1368
|
listActiveSessions(userId: string): Promise<StoredSession[]>;
|
|
@@ -1316,7 +1375,23 @@ declare class DbSessionStore implements SessionStore {
|
|
|
1316
1375
|
currentTokens?: AuthTokens;
|
|
1317
1376
|
}): Promise<void>;
|
|
1318
1377
|
dispose(): void;
|
|
1378
|
+
/** Map a raw SQL row (snake_case) to StoredSession. */
|
|
1319
1379
|
private rowToSession;
|
|
1380
|
+
/** Map an ORM record (camelCase) to StoredSession. */
|
|
1381
|
+
private recordToSession;
|
|
1382
|
+
}
|
|
1383
|
+
declare class DbSubscriptionStore implements SubscriptionStore {
|
|
1384
|
+
private db;
|
|
1385
|
+
constructor(db: AuthDbClient);
|
|
1386
|
+
assign(tenantId: string, planId: string, startedAt?: Date, expiresAt?: Date | null): Promise<void>;
|
|
1387
|
+
get(tenantId: string): Promise<Subscription | null>;
|
|
1388
|
+
updateOverrides(tenantId: string, overrides: Record<string, LimitOverride>): Promise<void>;
|
|
1389
|
+
remove(tenantId: string): Promise<void>;
|
|
1390
|
+
attachAddOn(tenantId: string, addOnId: string): Promise<void>;
|
|
1391
|
+
detachAddOn(tenantId: string, addOnId: string): Promise<void>;
|
|
1392
|
+
getAddOns(tenantId: string): Promise<string[]>;
|
|
1393
|
+
dispose(): void;
|
|
1394
|
+
private loadOverrides;
|
|
1320
1395
|
}
|
|
1321
1396
|
declare class DbUserStore implements UserStore {
|
|
1322
1397
|
private db;
|
|
@@ -1329,6 +1404,7 @@ declare class DbUserStore implements UserStore {
|
|
|
1329
1404
|
findById(id: string): Promise<AuthUser | null>;
|
|
1330
1405
|
updatePasswordHash(userId: string, passwordHash: string): Promise<void>;
|
|
1331
1406
|
updateEmailVerified(userId: string, verified: boolean): Promise<void>;
|
|
1407
|
+
deleteUser(id: string): Promise<void>;
|
|
1332
1408
|
private rowToUser;
|
|
1333
1409
|
}
|
|
1334
1410
|
declare class InMemoryEmailVerificationStore implements EmailVerificationStore {
|
|
@@ -1476,7 +1552,7 @@ interface PlanManagerConfig {
|
|
|
1476
1552
|
plans: Record<string, PlanDef>;
|
|
1477
1553
|
versionStore: PlanVersionStore;
|
|
1478
1554
|
grandfatheringStore: GrandfatheringStore;
|
|
1479
|
-
|
|
1555
|
+
subscriptionStore: SubscriptionStore;
|
|
1480
1556
|
clock?: () => Date;
|
|
1481
1557
|
}
|
|
1482
1558
|
interface PlanManager {
|
|
@@ -1531,6 +1607,7 @@ declare class InMemorySessionStore implements SessionStore {
|
|
|
1531
1607
|
currentTokens?: AuthTokens;
|
|
1532
1608
|
}): Promise<StoredSession>;
|
|
1533
1609
|
findByRefreshHash(hash: string): Promise<StoredSession | null>;
|
|
1610
|
+
findActiveSessionById(id: string): Promise<StoredSession | null>;
|
|
1534
1611
|
findByPreviousRefreshHash(hash: string): Promise<StoredSession | null>;
|
|
1535
1612
|
revokeSession(id: string): Promise<void>;
|
|
1536
1613
|
listActiveSessions(userId: string): Promise<StoredSession[]>;
|
|
@@ -1556,14 +1633,78 @@ declare class InMemoryUserStore implements UserStore {
|
|
|
1556
1633
|
findById(id: string): Promise<AuthUser | null>;
|
|
1557
1634
|
updatePasswordHash(userId: string, passwordHash: string): Promise<void>;
|
|
1558
1635
|
updateEmailVerified(userId: string, verified: boolean): Promise<void>;
|
|
1636
|
+
deleteUser(id: string): Promise<void>;
|
|
1559
1637
|
}
|
|
1560
1638
|
declare function createAuth(config: AuthConfig): AuthInstance;
|
|
1639
|
+
import { SchemaLike } from "@vertz/db";
|
|
1640
|
+
/**
|
|
1641
|
+
* A content type descriptor that implements SchemaLike.
|
|
1642
|
+
* Carries HTTP metadata alongside parse/validate behavior.
|
|
1643
|
+
*/
|
|
1644
|
+
interface ContentDescriptor<T> extends SchemaLike<T> {
|
|
1645
|
+
/** Discriminator — distinguishes from plain SchemaLike */
|
|
1646
|
+
readonly _kind: "content";
|
|
1647
|
+
/** MIME type for HTTP headers */
|
|
1648
|
+
readonly _contentType: string;
|
|
1649
|
+
}
|
|
1650
|
+
/**
|
|
1651
|
+
* Runtime check: is the given SchemaLike a ContentDescriptor?
|
|
1652
|
+
*/
|
|
1653
|
+
declare function isContentDescriptor(value: SchemaLike<unknown>): value is ContentDescriptor<unknown>;
|
|
1654
|
+
declare const content: {
|
|
1655
|
+
/** application/xml → string */
|
|
1656
|
+
readonly xml: () => ContentDescriptor<string>;
|
|
1657
|
+
/** text/html → string */
|
|
1658
|
+
readonly html: () => ContentDescriptor<string>;
|
|
1659
|
+
/** text/plain → string */
|
|
1660
|
+
readonly text: () => ContentDescriptor<string>;
|
|
1661
|
+
/** application/octet-stream → Uint8Array */
|
|
1662
|
+
readonly binary: () => ContentDescriptor<Uint8Array>;
|
|
1663
|
+
};
|
|
1561
1664
|
import { AppBuilder, AppConfig } from "@vertz/core";
|
|
1562
|
-
import { DatabaseClient, EntityDbAdapter as EntityDbAdapter3, ModelEntry as ModelEntry2 } from "@vertz/db";
|
|
1563
|
-
import { ModelDef as
|
|
1564
|
-
import { ModelDef as
|
|
1565
|
-
import { EntityDbAdapter, ListOptions } from "@vertz/db";
|
|
1665
|
+
import { DatabaseClient as DatabaseClient2, EntityDbAdapter as EntityDbAdapter3, ModelEntry as ModelEntry2 } from "@vertz/db";
|
|
1666
|
+
import { ModelDef as ModelDef4, RelationDef as RelationDef2, SchemaLike as SchemaLike2, TableDef } from "@vertz/db";
|
|
1667
|
+
import { ListOptions as ListOptions3, ModelDef as ModelDef3 } from "@vertz/db";
|
|
1668
|
+
import { EntityDbAdapter, GetOptions, ListOptions, ModelDef as ModelDef2 } from "@vertz/db";
|
|
1566
1669
|
import { EntityError, Result as Result3 } from "@vertz/errors";
|
|
1670
|
+
import { RelationDef, TenantGraph } from "@vertz/db";
|
|
1671
|
+
/** One hop in the relation chain from entity to tenant root. */
|
|
1672
|
+
interface TenantChainHop {
|
|
1673
|
+
/** Target table name (e.g., 'projects') */
|
|
1674
|
+
readonly tableName: string;
|
|
1675
|
+
/** FK column on the current table (e.g., 'projectId') */
|
|
1676
|
+
readonly foreignKey: string;
|
|
1677
|
+
/** PK column on the target table (e.g., 'id') */
|
|
1678
|
+
readonly targetColumn: string;
|
|
1679
|
+
}
|
|
1680
|
+
/** Full chain from an indirectly scoped entity to the tenant root. */
|
|
1681
|
+
interface TenantChain {
|
|
1682
|
+
/** Ordered hops from entity → ... → directly-scoped table */
|
|
1683
|
+
readonly hops: readonly TenantChainHop[];
|
|
1684
|
+
/** The tenant FK column on the final hop's target table (e.g., 'organizationId') */
|
|
1685
|
+
readonly tenantColumn: string;
|
|
1686
|
+
}
|
|
1687
|
+
interface ModelRegistryEntry {
|
|
1688
|
+
readonly table: {
|
|
1689
|
+
readonly _name: string;
|
|
1690
|
+
readonly _columns: Record<string, unknown>;
|
|
1691
|
+
};
|
|
1692
|
+
readonly relations: Record<string, RelationDef>;
|
|
1693
|
+
readonly _tenant?: string | null;
|
|
1694
|
+
}
|
|
1695
|
+
type ModelRegistry = Record<string, ModelRegistryEntry>;
|
|
1696
|
+
/**
|
|
1697
|
+
* Resolves the relation chain from an indirectly scoped entity back to the
|
|
1698
|
+
* tenant root.
|
|
1699
|
+
*
|
|
1700
|
+
* Returns null if the entity is not indirectly scoped (i.e., it's the root,
|
|
1701
|
+
* directly scoped, shared, or unscoped).
|
|
1702
|
+
*
|
|
1703
|
+
* The chain is computed by walking `ref.one` relations from the entity until
|
|
1704
|
+
* we reach a directly-scoped model. The tenant column is read from the
|
|
1705
|
+
* directly-scoped model's `_tenant` relation FK.
|
|
1706
|
+
*/
|
|
1707
|
+
declare function resolveTenantChain(entityKey: string, tenantGraph: TenantGraph, registry: ModelRegistry): TenantChain | null;
|
|
1567
1708
|
import { EntityDbAdapter as EntityDbAdapter2, ListOptions as ListOptions2 } from "@vertz/db";
|
|
1568
1709
|
interface ListResult<T = Record<string, unknown>> {
|
|
1569
1710
|
items: T[];
|
|
@@ -1576,29 +1717,38 @@ interface CrudResult<T = unknown> {
|
|
|
1576
1717
|
status: number;
|
|
1577
1718
|
body: T;
|
|
1578
1719
|
}
|
|
1579
|
-
interface CrudHandlers {
|
|
1580
|
-
list(ctx: EntityContext
|
|
1581
|
-
get(ctx: EntityContext
|
|
1582
|
-
create(ctx: EntityContext
|
|
1583
|
-
update(ctx: EntityContext
|
|
1584
|
-
delete(ctx: EntityContext
|
|
1585
|
-
}
|
|
1586
|
-
|
|
1720
|
+
interface CrudHandlers<TModel extends ModelDef2 = ModelDef2> {
|
|
1721
|
+
list(ctx: EntityContext<TModel>, options?: ListOptions): Promise<Result3<CrudResult<ListResult<TModel["table"]["$response"]>>, EntityError>>;
|
|
1722
|
+
get(ctx: EntityContext<TModel>, id: string, options?: GetOptions): Promise<Result3<CrudResult<TModel["table"]["$response"]>, EntityError>>;
|
|
1723
|
+
create(ctx: EntityContext<TModel>, data: Record<string, unknown>): Promise<Result3<CrudResult<TModel["table"]["$response"]>, EntityError>>;
|
|
1724
|
+
update(ctx: EntityContext<TModel>, id: string, data: Record<string, unknown>): Promise<Result3<CrudResult<TModel["table"]["$response"]>, EntityError>>;
|
|
1725
|
+
delete(ctx: EntityContext<TModel>, id: string): Promise<Result3<CrudResult<null>, EntityError>>;
|
|
1726
|
+
}
|
|
1727
|
+
/** Resolves IDs from a table matching a where condition. Used for indirect tenant filtering. */
|
|
1728
|
+
type QueryParentIdsFn = (tableName: string, where: Record<string, unknown>) => Promise<string[]>;
|
|
1729
|
+
/** Options for the CRUD pipeline factory. */
|
|
1730
|
+
interface CrudPipelineOptions {
|
|
1731
|
+
/** Tenant chain for indirectly scoped entities. */
|
|
1732
|
+
tenantChain?: TenantChain | null;
|
|
1733
|
+
/** Resolves parent IDs for indirect tenant chain traversal. */
|
|
1734
|
+
queryParentIds?: QueryParentIdsFn;
|
|
1735
|
+
}
|
|
1736
|
+
declare function createCrudHandlers<TModel extends ModelDef2 = ModelDef2>(def: EntityDefinition<TModel>, db: EntityDbAdapter, options?: CrudPipelineOptions): CrudHandlers<TModel>;
|
|
1587
1737
|
/**
|
|
1588
1738
|
* EntityOperations — typed CRUD facade for a single entity.
|
|
1589
1739
|
*
|
|
1590
1740
|
* When used as `ctx.entity`, TModel fills in actual column types.
|
|
1591
1741
|
* When used as `ctx.entities.*`, TModel defaults to `ModelDef` (loose typing).
|
|
1592
1742
|
*/
|
|
1593
|
-
interface EntityOperations<TModel extends
|
|
1743
|
+
interface EntityOperations<TModel extends ModelDef3 = ModelDef3> {
|
|
1594
1744
|
get(id: string): Promise<TModel["table"]["$response"]>;
|
|
1595
|
-
list(options?:
|
|
1745
|
+
list(options?: ListOptions3<TModel>): Promise<ListResult<TModel["table"]["$response"]>>;
|
|
1596
1746
|
create(data: TModel["table"]["$create_input"]): Promise<TModel["table"]["$response"]>;
|
|
1597
1747
|
update(id: string, data: TModel["table"]["$update_input"]): Promise<TModel["table"]["$response"]>;
|
|
1598
1748
|
delete(id: string): Promise<void>;
|
|
1599
1749
|
}
|
|
1600
1750
|
/** Extracts the model type from an EntityDefinition */
|
|
1601
|
-
type ExtractModel<T> = T extends EntityDefinition<infer M> ? M :
|
|
1751
|
+
type ExtractModel<T> = T extends EntityDefinition<infer M> ? M : ModelDef4;
|
|
1602
1752
|
/**
|
|
1603
1753
|
* Maps an inject config `{ key: EntityDefinition<TModel> }` to
|
|
1604
1754
|
* `{ key: EntityOperations<TModel> }` for typed ctx.entities access.
|
|
@@ -1606,12 +1756,13 @@ type ExtractModel<T> = T extends EntityDefinition<infer M> ? M : ModelDef3;
|
|
|
1606
1756
|
type InjectToOperations<TInject extends Record<string, EntityDefinition> = {}> = { readonly [K in keyof TInject] : EntityOperations<ExtractModel<TInject[K]>> };
|
|
1607
1757
|
interface BaseContext {
|
|
1608
1758
|
readonly userId: string | null;
|
|
1759
|
+
readonly tenantId: string | null;
|
|
1609
1760
|
authenticated(): boolean;
|
|
1610
1761
|
tenant(): boolean;
|
|
1611
1762
|
role(...roles: string[]): boolean;
|
|
1612
1763
|
}
|
|
1613
1764
|
interface EntityContext<
|
|
1614
|
-
TModel extends
|
|
1765
|
+
TModel extends ModelDef4 = ModelDef4,
|
|
1615
1766
|
TInject extends Record<string, EntityDefinition> = {}
|
|
1616
1767
|
> extends BaseContext {
|
|
1617
1768
|
/** Typed CRUD on the current entity */
|
|
@@ -1619,7 +1770,7 @@ interface EntityContext<
|
|
|
1619
1770
|
/** Typed access to injected entities only */
|
|
1620
1771
|
readonly entities: InjectToOperations<TInject>;
|
|
1621
1772
|
}
|
|
1622
|
-
type AccessRule2 = false |
|
|
1773
|
+
type AccessRule2 = false | AccessRule | ((ctx: BaseContext, row: Record<string, unknown>) => boolean | Promise<boolean>);
|
|
1623
1774
|
interface EntityBeforeHooks<
|
|
1624
1775
|
TCreateInput = unknown,
|
|
1625
1776
|
TUpdateInput = unknown
|
|
@@ -1640,20 +1791,72 @@ interface EntityActionDef<
|
|
|
1640
1791
|
> {
|
|
1641
1792
|
readonly method?: string;
|
|
1642
1793
|
readonly path?: string;
|
|
1643
|
-
readonly body:
|
|
1644
|
-
readonly response:
|
|
1794
|
+
readonly body: SchemaLike2<TInput>;
|
|
1795
|
+
readonly response: SchemaLike2<TOutput>;
|
|
1645
1796
|
readonly handler: (input: TInput, ctx: TCtx, row: TResponse | null) => Promise<TOutput>;
|
|
1646
1797
|
}
|
|
1647
1798
|
/** Extract column keys from a RelationDef's target table. */
|
|
1648
|
-
type RelationColumnKeys<R> = R extends
|
|
1649
|
-
|
|
1799
|
+
type RelationColumnKeys<R> = R extends RelationDef2<infer TTarget> ? TTarget extends TableDef<infer TCols> ? Extract<keyof TCols, string> : string : string;
|
|
1800
|
+
/** Structured relation config with select, allowWhere, allowOrderBy, maxLimit. */
|
|
1801
|
+
interface RelationConfigObject<TColumnKeys extends string = string> {
|
|
1802
|
+
/** Which fields can be selected. Record<field, true>. */
|
|
1803
|
+
readonly select?: { readonly [F in TColumnKeys]? : true };
|
|
1804
|
+
/** Which fields can be filtered via `where`. */
|
|
1805
|
+
readonly allowWhere?: readonly string[];
|
|
1806
|
+
/** Which fields can be sorted via `orderBy`. */
|
|
1807
|
+
readonly allowOrderBy?: readonly string[];
|
|
1808
|
+
/** Max items per parent row. Defaults to DEFAULT_RELATION_LIMIT (100). */
|
|
1809
|
+
readonly maxLimit?: number;
|
|
1810
|
+
}
|
|
1811
|
+
type EntityRelationsConfig<TRelations extends Record<string, RelationDef2> = Record<string, RelationDef2>> = { [K in keyof TRelations]? : true | false | RelationConfigObject<RelationColumnKeys<TRelations[K]>> };
|
|
1812
|
+
/** Extract the target table type from a RelationDef. */
|
|
1813
|
+
type RelationTargetTable<R> = R extends RelationDef2<infer T> ? T : TableDef;
|
|
1814
|
+
/** Structured expose config for a relation. Controls field, filter, sort, and nested relation exposure. */
|
|
1815
|
+
interface RelationExposeConfig<R extends RelationDef2 = RelationDef2> {
|
|
1816
|
+
/** Which fields of the related entity to expose. */
|
|
1817
|
+
readonly select: { [K in PublicColumnKeys<RelationTargetTable<R>>]? : true | AccessRule };
|
|
1818
|
+
/** Which fields clients can filter on via VertzQL `where`. */
|
|
1819
|
+
readonly allowWhere?: { [K in PublicColumnKeys<RelationTargetTable<R>>]? : true | AccessRule };
|
|
1820
|
+
/** Which fields clients can sort on via VertzQL `orderBy`. */
|
|
1821
|
+
readonly allowOrderBy?: { [K in PublicColumnKeys<RelationTargetTable<R>>]? : true | AccessRule };
|
|
1822
|
+
/** Max items returned per parent row. Defaults to DEFAULT_RELATION_LIMIT. */
|
|
1823
|
+
readonly maxLimit?: number;
|
|
1824
|
+
/** Nested relation exposure (loosely typed — target model relations not available from RelationDef). */
|
|
1825
|
+
readonly include?: Record<string, true | false | RelationExposeConfig>;
|
|
1826
|
+
}
|
|
1827
|
+
/** Controls which fields, filters, sorts, and relations are exposed through the entity API. */
|
|
1828
|
+
interface ExposeConfig<
|
|
1829
|
+
TTable extends TableDef = TableDef,
|
|
1830
|
+
TModel extends ModelDef4 = ModelDef4
|
|
1831
|
+
> {
|
|
1832
|
+
/** Which fields of the entity to expose. Required when expose is present. */
|
|
1833
|
+
readonly select: { [K in PublicColumnKeys<TTable>]? : true | AccessRule };
|
|
1834
|
+
/** Which fields clients can filter on via VertzQL `where`. */
|
|
1835
|
+
readonly allowWhere?: { [K in PublicColumnKeys<TTable>]? : true | AccessRule };
|
|
1836
|
+
/** Which fields clients can sort on via VertzQL `orderBy`. */
|
|
1837
|
+
readonly allowOrderBy?: { [K in PublicColumnKeys<TTable>]? : true | AccessRule };
|
|
1838
|
+
/** Which relations to expose and how. */
|
|
1839
|
+
readonly include?: { [K in keyof TModel["relations"]]? : true | false | RelationExposeConfig<TModel["relations"][K] extends RelationDef2 ? TModel["relations"][K] : RelationDef2> };
|
|
1840
|
+
}
|
|
1841
|
+
/** Extract non-hidden column keys from a table (public fields). */
|
|
1842
|
+
type PublicColumnKeys<TTable extends TableDef> = TTable extends TableDef<infer TCols> ? { [K in keyof TCols & string] : TCols[K] extends {
|
|
1843
|
+
_meta: {
|
|
1844
|
+
_annotations: {
|
|
1845
|
+
hidden: true;
|
|
1846
|
+
};
|
|
1847
|
+
};
|
|
1848
|
+
} ? never : K }[keyof TCols & string] : string;
|
|
1650
1849
|
interface EntityConfig<
|
|
1651
|
-
TModel extends
|
|
1850
|
+
TModel extends ModelDef4 = ModelDef4,
|
|
1652
1851
|
TActions extends Record<string, EntityActionDef<any, any, any, any>> = {},
|
|
1653
1852
|
TInject extends Record<string, EntityDefinition> = {}
|
|
1654
1853
|
> {
|
|
1655
1854
|
readonly model: TModel;
|
|
1656
1855
|
readonly inject?: TInject;
|
|
1856
|
+
/** Override the DB table name (defaults to entity name). For admin entities over shared tables. */
|
|
1857
|
+
readonly table?: string;
|
|
1858
|
+
/** Whether CRUD auto-filters by tenantId. Defaults to true when model has tenantId column. */
|
|
1859
|
+
readonly tenantScoped?: boolean;
|
|
1657
1860
|
readonly access?: Partial<Record<"list" | "get" | "create" | "update" | "delete" | Extract<keyof NoInfer<TActions>, string>, AccessRule2>>;
|
|
1658
1861
|
readonly before?: {
|
|
1659
1862
|
readonly create?: (data: TModel["table"]["$create_input"], ctx: EntityContext<TModel, TInject>) => TModel["table"]["$create_input"] | Promise<TModel["table"]["$create_input"]>;
|
|
@@ -1665,9 +1868,9 @@ interface EntityConfig<
|
|
|
1665
1868
|
readonly delete?: (row: TModel["table"]["$response"], ctx: EntityContext<TModel, TInject>) => void | Promise<void>;
|
|
1666
1869
|
};
|
|
1667
1870
|
readonly actions?: { readonly [K in keyof TActions] : TActions[K] };
|
|
1668
|
-
readonly
|
|
1871
|
+
readonly expose?: ExposeConfig<TModel["table"], TModel>;
|
|
1669
1872
|
}
|
|
1670
|
-
interface EntityDefinition<TModel extends
|
|
1873
|
+
interface EntityDefinition<TModel extends ModelDef4 = ModelDef4> {
|
|
1671
1874
|
readonly kind: "entity";
|
|
1672
1875
|
readonly name: string;
|
|
1673
1876
|
readonly model: TModel;
|
|
@@ -1676,9 +1879,15 @@ interface EntityDefinition<TModel extends ModelDef3 = ModelDef3> {
|
|
|
1676
1879
|
readonly before: EntityBeforeHooks;
|
|
1677
1880
|
readonly after: EntityAfterHooks;
|
|
1678
1881
|
readonly actions: Record<string, EntityActionDef>;
|
|
1679
|
-
readonly
|
|
1680
|
-
|
|
1681
|
-
|
|
1882
|
+
readonly expose?: ExposeConfig<TModel["table"], TModel>;
|
|
1883
|
+
/** DB table name (defaults to entity name). */
|
|
1884
|
+
readonly table: string;
|
|
1885
|
+
/** Whether CRUD auto-filters by tenantId. */
|
|
1886
|
+
readonly tenantScoped: boolean;
|
|
1887
|
+
/** Relation chain for indirect tenant scoping. Null for direct or unscoped. */
|
|
1888
|
+
readonly tenantChain: TenantChain | null;
|
|
1889
|
+
}
|
|
1890
|
+
import { SchemaLike as SchemaLike3 } from "@vertz/db";
|
|
1682
1891
|
/** Extracts the model type from an EntityDefinition */
|
|
1683
1892
|
type ExtractModel2<T> = T extends EntityDefinition<infer M> ? M : never;
|
|
1684
1893
|
/**
|
|
@@ -1686,9 +1895,18 @@ type ExtractModel2<T> = T extends EntityDefinition<infer M> ? M : never;
|
|
|
1686
1895
|
* `{ key: EntityOperations<TModel> }` for typed ctx.entities access.
|
|
1687
1896
|
*/
|
|
1688
1897
|
type InjectToOperations2<TInject extends Record<string, EntityDefinition> = {}> = { readonly [K in keyof TInject] : EntityOperations<ExtractModel2<TInject[K]>> };
|
|
1898
|
+
/** Raw request metadata exposed to service handlers */
|
|
1899
|
+
interface ServiceRequestInfo {
|
|
1900
|
+
readonly url: string;
|
|
1901
|
+
readonly method: string;
|
|
1902
|
+
readonly headers: Headers;
|
|
1903
|
+
readonly body: unknown;
|
|
1904
|
+
}
|
|
1689
1905
|
interface ServiceContext<TInject extends Record<string, EntityDefinition> = {}> extends BaseContext {
|
|
1690
1906
|
/** Typed access to injected entities only */
|
|
1691
1907
|
readonly entities: InjectToOperations2<TInject>;
|
|
1908
|
+
/** Raw request metadata — URL, method, headers, pre-parsed body */
|
|
1909
|
+
readonly request: ServiceRequestInfo;
|
|
1692
1910
|
}
|
|
1693
1911
|
interface ServiceActionDef<
|
|
1694
1912
|
TInput = unknown,
|
|
@@ -1697,8 +1915,8 @@ interface ServiceActionDef<
|
|
|
1697
1915
|
> {
|
|
1698
1916
|
readonly method?: string;
|
|
1699
1917
|
readonly path?: string;
|
|
1700
|
-
readonly body
|
|
1701
|
-
readonly response:
|
|
1918
|
+
readonly body?: SchemaLike3<TInput>;
|
|
1919
|
+
readonly response: SchemaLike3<TOutput>;
|
|
1702
1920
|
readonly handler: (input: TInput, ctx: TCtx) => Promise<TOutput>;
|
|
1703
1921
|
}
|
|
1704
1922
|
interface ServiceConfig<
|
|
@@ -1719,6 +1937,8 @@ interface ServiceDefinition {
|
|
|
1719
1937
|
interface ServerInstance extends AppBuilder {
|
|
1720
1938
|
auth: AuthInstance;
|
|
1721
1939
|
initialize(): Promise<void>;
|
|
1940
|
+
/** Routes auth requests (/api/auth/*) to auth.handler, everything else to entity handler */
|
|
1941
|
+
readonly requestHandler: (request: Request) => Promise<Response>;
|
|
1722
1942
|
}
|
|
1723
1943
|
interface ServerConfig extends Omit<AppConfig, "_entityDbFactory" | "entities"> {
|
|
1724
1944
|
/** Entity definitions created via entity() from @vertz/server */
|
|
@@ -1731,9 +1951,13 @@ interface ServerConfig extends Omit<AppConfig, "_entityDbFactory" | "entities">
|
|
|
1731
1951
|
* - A DatabaseClient from createDb() (recommended — auto-bridged per entity)
|
|
1732
1952
|
* - An EntityDbAdapter (deprecated — simple adapter with get/list/create/update/delete)
|
|
1733
1953
|
*/
|
|
1734
|
-
db?:
|
|
1954
|
+
db?: DatabaseClient2<Record<string, ModelEntry2>> | EntityDbAdapter3;
|
|
1735
1955
|
/** @internal Factory to create a DB adapter for each entity. Prefer `db` instead. */
|
|
1736
1956
|
_entityDbFactory?: (entityDef: EntityDefinition) => EntityDbAdapter3;
|
|
1957
|
+
/** @internal Resolves parent IDs for indirect tenant chain traversal. For testing only. */
|
|
1958
|
+
_queryParentIds?: QueryParentIdsFn;
|
|
1959
|
+
/** @internal Tenant chains for indirect scoping. For testing without DatabaseClient. */
|
|
1960
|
+
_tenantChains?: Map<string, TenantChain>;
|
|
1737
1961
|
/** Auth configuration — when combined with db, auto-wires DB-backed stores */
|
|
1738
1962
|
auth?: AuthConfig;
|
|
1739
1963
|
}
|
|
@@ -1747,11 +1971,17 @@ interface ServerConfig extends Omit<AppConfig, "_entityDbFactory" | "entities">
|
|
|
1747
1971
|
* - Returns ServerInstance with `.auth` and `.initialize()`
|
|
1748
1972
|
*/
|
|
1749
1973
|
declare function createServer(config: ServerConfig & {
|
|
1750
|
-
db:
|
|
1974
|
+
db: DatabaseClient2<Record<string, ModelEntry2>>;
|
|
1751
1975
|
auth: AuthConfig;
|
|
1752
1976
|
}): ServerInstance;
|
|
1753
1977
|
declare function createServer(config: ServerConfig): AppBuilder;
|
|
1754
1978
|
import { EntityForbiddenError, Result as Result4 } from "@vertz/errors";
|
|
1979
|
+
interface EnforceAccessOptions {
|
|
1980
|
+
/** Evaluate an entitlement via the access context (defineAccess) */
|
|
1981
|
+
readonly can?: (entitlement: string) => Promise<boolean>;
|
|
1982
|
+
/** Seconds since last MFA verification (for rules.fva) */
|
|
1983
|
+
readonly fvaAge?: number;
|
|
1984
|
+
}
|
|
1755
1985
|
/**
|
|
1756
1986
|
* Evaluates an access rule for the given operation.
|
|
1757
1987
|
* Returns err(EntityForbiddenError) if access is denied.
|
|
@@ -1760,11 +1990,16 @@ import { EntityForbiddenError, Result as Result4 } from "@vertz/errors";
|
|
|
1760
1990
|
*
|
|
1761
1991
|
* - No rule defined → deny (deny by default)
|
|
1762
1992
|
* - Rule is false → operation is disabled
|
|
1763
|
-
* -
|
|
1764
|
-
* -
|
|
1993
|
+
* - Descriptor rule → dispatch by type
|
|
1994
|
+
* - Function rule → evaluate and deny if returns false
|
|
1995
|
+
*
|
|
1996
|
+
* When `skipWhere` is true, `where` rules are treated as ok() — used
|
|
1997
|
+
* when where conditions have already been pushed to the DB query.
|
|
1765
1998
|
*/
|
|
1766
|
-
declare function enforceAccess(operation: string, accessRules: Partial<Record<string, AccessRule2>>, ctx: BaseContext, row?: Record<string, unknown
|
|
1767
|
-
|
|
1999
|
+
declare function enforceAccess(operation: string, accessRules: Partial<Record<string, AccessRule2>>, ctx: BaseContext, row?: Record<string, unknown>, options?: EnforceAccessOptions & {
|
|
2000
|
+
skipWhere?: boolean;
|
|
2001
|
+
}): Promise<Result4<void, EntityForbiddenError>>;
|
|
2002
|
+
import { ModelDef as ModelDef6 } from "@vertz/db";
|
|
1768
2003
|
/**
|
|
1769
2004
|
* Request info extracted from HTTP context / auth middleware.
|
|
1770
2005
|
*/
|
|
@@ -1776,10 +2011,10 @@ interface RequestInfo {
|
|
|
1776
2011
|
/**
|
|
1777
2012
|
* Creates an EntityContext from request info, entity operations, and registry proxy.
|
|
1778
2013
|
*/
|
|
1779
|
-
declare function createEntityContext<TModel extends
|
|
1780
|
-
import { ModelDef as
|
|
2014
|
+
declare function createEntityContext<TModel extends ModelDef6 = ModelDef6>(request: RequestInfo, entityOps: EntityOperations<TModel>, registryProxy: Record<string, EntityOperations>): EntityContext<TModel>;
|
|
2015
|
+
import { ModelDef as ModelDef7 } from "@vertz/db";
|
|
1781
2016
|
declare function entity<
|
|
1782
|
-
TModel extends
|
|
2017
|
+
TModel extends ModelDef7,
|
|
1783
2018
|
TInject extends Record<string, EntityDefinition> = {},
|
|
1784
2019
|
TActions extends Record<string, EntityActionDef<any, any, TModel["table"]["$response"], EntityContext<TModel, TInject>>> = {}
|
|
1785
2020
|
>(name: string, config: EntityConfig<TModel, TActions, TInject>): EntityDefinition<TModel>;
|
|
@@ -1827,6 +2062,10 @@ declare function stripReadOnlyFields(table: TableDef2, data: Record<string, unkn
|
|
|
1827
2062
|
import { EntityRouteEntry } from "@vertz/core";
|
|
1828
2063
|
interface EntityRouteOptions {
|
|
1829
2064
|
apiPrefix?: string;
|
|
2065
|
+
/** Tenant chain for indirectly scoped entities. */
|
|
2066
|
+
tenantChain?: TenantChain | null;
|
|
2067
|
+
/** Resolves parent IDs for indirect tenant chain traversal. */
|
|
2068
|
+
queryParentIds?: QueryParentIdsFn;
|
|
1830
2069
|
}
|
|
1831
2070
|
/**
|
|
1832
2071
|
* Generates HTTP route entries for a single entity definition.
|
|
@@ -1840,4 +2079,4 @@ declare function service<
|
|
|
1840
2079
|
TInject extends Record<string, EntityDefinition> = {},
|
|
1841
2080
|
TActions extends Record<string, ServiceActionDef<any, any, any>> = Record<string, ServiceActionDef<any, any, any>>
|
|
1842
2081
|
>(name: string, config: ServiceConfig<TActions, TInject>): ServiceDefinition;
|
|
1843
|
-
export { vertz, verifyPassword, validatePassword, validateOverrides, validateAuthModels, stripReadOnlyFields, stripHiddenFields, service, rules, makeImmutable, initializeAuthTables, hashPassword, google, github, getIncompatibleAddOns, generateEntityRoutes, entityErrorHandler, entity, enforceAccess, encodeAccessSet, discord, defineAccess, defaultAccess, deepFreeze, decodeAccessSet, createWebhookHandler, createStripeBillingAdapter, createServer, createPlanManager, createMiddleware, createImmutableProxy, createEnv, createEntityContext, createCrudHandlers, createBillingEventEmitter, createAuth, createAccessEventBroadcaster, createAccessContext, createAccess, computePlanHash, computeOverage, computeEntityAccess, computeAccessSet, checkFva, checkAddOnCompatibility, calculateBillingPeriod, authModels, WebhookHandlerConfig, WalletStore, WalletEntry, VertzException, ValidationException, UserTableEntry, UserStore, UnauthorizedException, TenantOverrides, StripeProduct, StripePrice, StripeClient, StripeBillingAdapterConfig, StoredSession, StoredPasswordReset, StoredEmailVerification, SignUpInput, SignInInput, SessionStrategy, SessionStore, SessionPayload, SessionInfo, SessionConfig, Session, ServiceUnavailableException, ServiceDefinition, ServiceContext, ServiceConfig, ServiceActionDef, ServerInstance, ServerHandle, ServerConfig, ServerAdapter, RuleContext, RoleAssignmentTableEntry, RoleAssignmentStore, RoleAssignment, ResourceRef, Resource, RequestInfo, RawRequest, RateLimitStore, RateLimitResult, RateLimitConfig, PriceInterval, PlanVersionStore, PlanVersionInfo,
|
|
2082
|
+
export { vertz, verifyPassword, validatePassword, validateOverrides, validateAuthModels, stripReadOnlyFields, stripHiddenFields, service, rules, resolveTenantChain, makeImmutable, isContentDescriptor, initializeAuthTables, hashPassword, google, github, getIncompatibleAddOns, generateEntityRoutes, entityErrorHandler, entity, enforceAccess, encodeAccessSet, discord, defineAccess, defaultAccess, deepFreeze, decodeAccessSet, createWebhookHandler, createStripeBillingAdapter, createServer, createPlanManager, createMiddleware, createImmutableProxy, createEnv, createEntityContext, createCrudHandlers, createBillingEventEmitter, createAuth, createAccessEventBroadcaster, createAccessContext, createAccess, content, computePlanHash, computeOverage, computeEntityAccess, computeAccessSet, checkFva, checkAddOnCompatibility, calculateBillingPeriod, authModels, WebhookHandlerConfig, WalletStore, WalletEntry, VertzException, ValidationException, UserTableEntry, UserStore, UnauthorizedException, TenantOverrides, TenantChainHop, TenantChain, SubscriptionStore, Subscription, StripeProduct, StripePrice, StripeClient, StripeBillingAdapterConfig, StoredSession, StoredPasswordReset, StoredEmailVerification, SignUpInput, SignInInput, SessionStrategy, SessionStore, SessionPayload, SessionInfo, SessionConfig, Session, ServiceUnavailableException, ServiceRequestInfo, ServiceDefinition, ServiceContext, ServiceConfig, ServiceActionDef, ServerInstance, ServerHandle, ServerConfig, ServerAdapter, RuleContext, RoleAssignmentTableEntry, RoleAssignmentStore, RoleAssignment, ResourceRef, Resource, RequestInfo, RelationExposeConfig, RawRequest, RateLimitStore, RateLimitResult, RateLimitConfig, PriceInterval, PlanVersionStore, PlanVersionInfo, PlanSnapshot, PlanPrice, PlanHashInput, PlanDef, Period, PasswordResetStore, PasswordResetConfig, PasswordRequirements, ParentRef, OverrideStore, OverageInput, OverageConfig, OnUserCreatedPayload, OAuthUserInfo, OAuthTokens, OAuthProviderConfig, OAuthProvider, OAuthAccountStore, NotFoundException, NamedMiddlewareDef, MiddlewareDef, MfaSetupData, MfaConfig, MfaChallengeData, MFAStore, ListenOptions, ListResult, ListOptions2 as ListOptions, LimitOverrideDef, LimitOverride, LimitDef, InternalServerErrorException, InferSchema, Infer2 as Infer, InMemoryWalletStore, InMemoryUserStore, InMemorySubscriptionStore, InMemorySessionStore, InMemoryRoleAssignmentStore, InMemoryRateLimitStore, InMemoryPlanVersionStore, InMemoryPasswordResetStore, InMemoryOverrideStore, InMemoryOAuthAccountStore, InMemoryMFAStore, InMemoryGrandfatheringStore, InMemoryFlagStore, InMemoryEmailVerificationStore, InMemoryClosureStore, HttpStatusCode, HttpMethod, HandlerCtx, GrandfatheringStore, GrandfatheringState, ForbiddenException, FlagStore, ExposeConfig, EnvConfig, EntityRouteOptions, EntityRelationsConfig, EntityRegistry, EntityOperations, EntityErrorResult, EntityDefinition, EntityDef, EntityDbAdapter2 as EntityDbAdapter, EntityContext, EntityConfig, EntityActionDef, EntitlementValue, EntitlementRegistry, EntitlementDefinition, EntitlementDef, Entitlement, EncodedAccessSet, EmailVerificationStore, EmailVerificationConfig, EmailPasswordConfig, Deps, DenialReason, DenialMeta, DefineAccessInput, DeepReadonly, DbUserStore, DbSubscriptionStore, DbSessionStore, DbRoleAssignmentStore, DbOAuthAccountStore, DbFlagStore, DbDialectName, DbClosureStore, Ctx, CrudResult, CrudHandlers, CorsConfig, CookieConfig, ContentDescriptor, ConsumeResult, ConflictException, ComputeAccessSetConfig, ClosureStore, ClosureRow, ClosureEntry, BillingPeriod, BillingEventType, BillingEventHandler, BillingEventEmitter, BillingEvent, BillingAdapter, BaseContext, BadRequestException, AuthorizationError, AuthUser, AuthTokens, AuthInstance, AuthEntityProxy, AuthDbClient, AuthContext, AuthConfig, AuthCallbackContext, AuthApi, AppConfig2 as AppConfig, AppBuilder2 as AppBuilder, AddOnRequires, AclClaim, AccumulateProvides, AccessWsData, AccessSet, AccessRule2 as AccessRule, AccessInstance, AccessEventBroadcasterConfig, AccessEventBroadcaster, AccessEvent, AccessDefinition, AccessContextConfig, AccessContext, AccessConfig, AccessCheckResult, AccessCheckData, AUTH_TABLE_NAMES };
|