@stratal/framework 0.0.17 → 0.0.18
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/auth/index.d.mts +12 -9
- package/dist/auth/index.d.mts.map +1 -1
- package/dist/auth/index.mjs +32 -17
- package/dist/auth/index.mjs.map +1 -1
- package/dist/{auth-context-CV3Ko1ew.mjs → auth-context-BfekHvM9.mjs} +2 -2
- package/dist/{auth-context-CV3Ko1ew.mjs.map → auth-context-BfekHvM9.mjs.map} +1 -1
- package/dist/context/index.mjs +1 -1
- package/dist/database/index.d.mts +1 -1
- package/dist/database/index.mjs +2 -2
- package/dist/database/index.mjs.map +1 -1
- package/dist/{decorate-RSane8dy.mjs → decorate-C12QolJF.mjs} +1 -1
- package/dist/{decorateMetadata-CETItPez.mjs → decorateMetadata-rWbWGUuO.mjs} +1 -1
- package/dist/{decorateParam-CcTvpNsw.mjs → decorateParam-WGqsyT5s.mjs} +1 -1
- package/dist/factory/index.d.mts +1 -1
- package/dist/guards/index.mjs +4 -4
- package/dist/{index-eukGTmI8.d.mts → index-B1iGBJcO.d.mts} +5 -6
- package/dist/index-B1iGBJcO.d.mts.map +1 -0
- package/dist/rbac/index.mjs +3 -3
- package/package.json +18 -18
- package/dist/index-eukGTmI8.d.mts.map +0 -1
package/dist/auth/index.d.mts
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { AsyncModuleOptions, DynamicModule } from "stratal/module";
|
|
2
2
|
import { ApplicationError } from "stratal/errors";
|
|
3
|
+
import { LoggerService } from "stratal/logger";
|
|
3
4
|
import { Auth, BetterAuthOptions } from "better-auth";
|
|
4
5
|
import { APIError } from "better-auth/api";
|
|
5
|
-
import {
|
|
6
|
-
import { Middleware, RouterContext } from "stratal/router";
|
|
6
|
+
import { Middleware, Next, RouteConfigurable, Router, RouterContext } from "stratal/router";
|
|
7
7
|
|
|
8
8
|
//#region src/auth/auth.module.d.ts
|
|
9
|
-
declare class AuthModule implements
|
|
9
|
+
declare class AuthModule implements RouteConfigurable {
|
|
10
10
|
/**
|
|
11
|
-
* Configure auth middleware.
|
|
11
|
+
* Configure auth middleware globally.
|
|
12
12
|
*
|
|
13
13
|
* Registers middlewares in order:
|
|
14
14
|
* 1. AuthContextMiddleware - Creates and registers AuthContext in request container
|
|
15
15
|
* 2. SessionVerificationMiddleware - Verifies session and populates AuthContext with userId
|
|
16
16
|
*/
|
|
17
|
-
|
|
17
|
+
configureRoutes(router: Router): void;
|
|
18
18
|
/**
|
|
19
19
|
* Configure AuthModule with async options factory
|
|
20
20
|
*/
|
|
@@ -125,7 +125,7 @@ declare class VerificationFailedError extends ApplicationError {
|
|
|
125
125
|
* that depends on AuthContext.
|
|
126
126
|
*/
|
|
127
127
|
declare class AuthContextMiddleware implements Middleware {
|
|
128
|
-
handle(ctx: RouterContext, next:
|
|
128
|
+
handle(ctx: RouterContext, next: Next): Promise<void>;
|
|
129
129
|
}
|
|
130
130
|
//#endregion
|
|
131
131
|
//#region src/auth/services/auth.service.d.ts
|
|
@@ -173,8 +173,9 @@ declare class AuthService<TOptions extends BetterAuthOptions = BetterAuthOptions
|
|
|
173
173
|
*/
|
|
174
174
|
declare class SessionVerificationMiddleware implements Middleware {
|
|
175
175
|
private readonly authService;
|
|
176
|
-
|
|
177
|
-
|
|
176
|
+
private logger;
|
|
177
|
+
constructor(authService: AuthService, logger: LoggerService);
|
|
178
|
+
handle(ctx: RouterContext, next: Next): Promise<void>;
|
|
178
179
|
}
|
|
179
180
|
//#endregion
|
|
180
181
|
//#region src/auth/utils/auth-helpers.d.ts
|
|
@@ -194,7 +195,9 @@ declare const wrapBetterAuth: <T>(fn: () => Promise<T>) => Promise<T>;
|
|
|
194
195
|
*/
|
|
195
196
|
declare function mapBetterAuthError(error: APIError): ApplicationError;
|
|
196
197
|
/**
|
|
197
|
-
* Type guard to check if an error is a Better Auth APIError
|
|
198
|
+
* Type guard to check if an error is a Better Auth APIError.
|
|
199
|
+
* Uses duck typing to handle bundler environments (e.g. Vite)
|
|
200
|
+
* where instanceof may fail across module boundaries.
|
|
198
201
|
*/
|
|
199
202
|
declare function isAPIError(error: unknown): error is APIError;
|
|
200
203
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/auth/auth.module.ts","../../src/auth/auth.tokens.ts","../../src/auth/errors/auth-errors.ts","../../src/auth/errors/invalid-token.error.ts","../../src/auth/errors/token-required.error.ts","../../src/auth/errors/verification-failed.error.ts","../../src/auth/middleware/auth-context.middleware.ts","../../src/auth/services/auth.service.ts","../../src/auth/middleware/session-verification.middleware.ts","../../src/auth/utils/auth-helpers.ts","../../src/auth/utils/better-auth-error-handler.ts"],"mappings":";;;;;;;;cAgCa,UAAA,YAAsB,
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/auth/auth.module.ts","../../src/auth/auth.tokens.ts","../../src/auth/errors/auth-errors.ts","../../src/auth/errors/invalid-token.error.ts","../../src/auth/errors/token-required.error.ts","../../src/auth/errors/verification-failed.error.ts","../../src/auth/middleware/auth-context.middleware.ts","../../src/auth/services/auth.service.ts","../../src/auth/middleware/session-verification.middleware.ts","../../src/auth/utils/auth-helpers.ts","../../src/auth/utils/better-auth-error-handler.ts"],"mappings":"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"}
|
package/dist/auth/index.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import "../
|
|
2
|
-
import { t as
|
|
3
|
-
import { t as
|
|
4
|
-
import { t as
|
|
5
|
-
import { t as __decorateParam } from "../decorateParam-CcTvpNsw.mjs";
|
|
1
|
+
import { t as __decorate } from "../decorate-C12QolJF.mjs";
|
|
2
|
+
import { t as AuthContext } from "../auth-context-BfekHvM9.mjs";
|
|
3
|
+
import { t as __decorateMetadata } from "../decorateMetadata-rWbWGUuO.mjs";
|
|
4
|
+
import { t as __decorateParam } from "../decorateParam-WGqsyT5s.mjs";
|
|
6
5
|
import { Module } from "stratal/module";
|
|
7
6
|
import { DI_TOKENS, Transient } from "stratal/di";
|
|
8
7
|
import { ApplicationError, ERROR_CODES, InternalError } from "stratal/errors";
|
|
8
|
+
import { LOGGER_TOKENS } from "stratal/logger";
|
|
9
9
|
import { inject } from "tsyringe";
|
|
10
10
|
import { betterAuth } from "better-auth";
|
|
11
11
|
import { APIError } from "better-auth/api";
|
|
@@ -28,19 +28,26 @@ AuthContextMiddleware = __decorate([Transient()], AuthContextMiddleware);
|
|
|
28
28
|
//#endregion
|
|
29
29
|
//#region src/auth/middleware/session-verification.middleware.ts
|
|
30
30
|
let SessionVerificationMiddleware = class SessionVerificationMiddleware {
|
|
31
|
-
constructor(authService) {
|
|
31
|
+
constructor(authService, logger) {
|
|
32
32
|
this.authService = authService;
|
|
33
|
+
this.logger = logger;
|
|
33
34
|
}
|
|
34
35
|
async handle(ctx, next) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
try {
|
|
37
|
+
const session = await this.authService.auth.api.getSession({ headers: ctx.c.req.raw.headers });
|
|
38
|
+
if (session) ctx.getContainer().resolve(DI_TOKENS.AuthContext).setAuthContext({ userId: session.user.id });
|
|
39
|
+
await next();
|
|
40
|
+
} catch (error) {
|
|
41
|
+
this.logger.debug("Session validation failed (e.g., invalidated in DB)", { error });
|
|
42
|
+
await next();
|
|
43
|
+
}
|
|
38
44
|
}
|
|
39
45
|
};
|
|
40
46
|
SessionVerificationMiddleware = __decorate([
|
|
41
47
|
Transient(),
|
|
42
48
|
__decorateParam(0, inject(AUTH_SERVICE)),
|
|
43
|
-
|
|
49
|
+
__decorateParam(1, inject(LOGGER_TOKENS.LoggerService)),
|
|
50
|
+
__decorateMetadata("design:paramtypes", [Object, Object])
|
|
44
51
|
], SessionVerificationMiddleware);
|
|
45
52
|
//#endregion
|
|
46
53
|
//#region src/auth/errors/auth-errors.ts
|
|
@@ -193,7 +200,13 @@ var VerificationFailedError = class extends ApplicationError {
|
|
|
193
200
|
function mapBetterAuthError(error) {
|
|
194
201
|
const errorCode = error.body?.code;
|
|
195
202
|
if (error.status === "FOUND") {
|
|
196
|
-
|
|
203
|
+
const location = error.headers.get("location") ?? "";
|
|
204
|
+
if (location.includes("INVALID_TOKEN")) return new InvalidTokenError();
|
|
205
|
+
if (location.includes("EXPIRED_TOKEN")) return new TokenExpiredError();
|
|
206
|
+
if (location.includes("ATTEMPTS_EXCEEDED")) return new InvalidTokenError();
|
|
207
|
+
if (location.includes("new_user_signup_disabled")) return new UserNotFoundError();
|
|
208
|
+
if (location.includes("failed_to_create_user")) return new FailedToCreateUserError();
|
|
209
|
+
if (location.includes("failed_to_create_session")) return new FailedToCreateSessionError();
|
|
197
210
|
}
|
|
198
211
|
if (!errorCode) return new InternalError({
|
|
199
212
|
originalError: `Better Auth error: ${error.message}`,
|
|
@@ -230,10 +243,13 @@ function mapBetterAuthError(error) {
|
|
|
230
243
|
});
|
|
231
244
|
}
|
|
232
245
|
/**
|
|
233
|
-
* Type guard to check if an error is a Better Auth APIError
|
|
246
|
+
* Type guard to check if an error is a Better Auth APIError.
|
|
247
|
+
* Uses duck typing to handle bundler environments (e.g. Vite)
|
|
248
|
+
* where instanceof may fail across module boundaries.
|
|
234
249
|
*/
|
|
235
250
|
function isAPIError(error) {
|
|
236
|
-
|
|
251
|
+
if (error instanceof APIError) return true;
|
|
252
|
+
return error instanceof Error && error.name === "APIError" && "status" in error && "statusCode" in error;
|
|
237
253
|
}
|
|
238
254
|
//#endregion
|
|
239
255
|
//#region src/auth/utils/auth-helpers.ts
|
|
@@ -289,15 +305,14 @@ AuthService = __decorate([
|
|
|
289
305
|
var _AuthModule;
|
|
290
306
|
let AuthModule = _AuthModule = class AuthModule {
|
|
291
307
|
/**
|
|
292
|
-
* Configure auth middleware.
|
|
308
|
+
* Configure auth middleware globally.
|
|
293
309
|
*
|
|
294
310
|
* Registers middlewares in order:
|
|
295
311
|
* 1. AuthContextMiddleware - Creates and registers AuthContext in request container
|
|
296
312
|
* 2. SessionVerificationMiddleware - Verifies session and populates AuthContext with userId
|
|
297
313
|
*/
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
consumer.apply(SessionVerificationMiddleware).forRoutes("*");
|
|
314
|
+
configureRoutes(router) {
|
|
315
|
+
router.use(AuthContextMiddleware, SessionVerificationMiddleware);
|
|
301
316
|
}
|
|
302
317
|
/**
|
|
303
318
|
* Configure AuthModule with async options factory
|
package/dist/auth/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/auth/auth.tokens.ts","../../src/auth/middleware/auth-context.middleware.ts","../../src/auth/middleware/session-verification.middleware.ts","../../src/auth/errors/auth-errors.ts","../../src/auth/errors/invalid-token.error.ts","../../src/auth/errors/token-required.error.ts","../../src/auth/errors/verification-failed.error.ts","../../src/auth/utils/better-auth-error-handler.ts","../../src/auth/utils/auth-helpers.ts","../../src/auth/services/auth.service.ts","../../src/auth/auth.module.ts"],"sourcesContent":["/** Token for AuthService - core authentication service */\nexport const AUTH_SERVICE = Symbol.for('stratal:auth:service')\n\n/** Token for Better Auth options configuration */\nexport const AUTH_OPTIONS = Symbol.for('stratal:auth:options')\n","import { Transient, DI_TOKENS } from 'stratal/di'\nimport type { Middleware, RouterContext } from 'stratal/router'\nimport { AuthContext } from '../../context/auth-context'\n\n/**\n * Auth Context Middleware\n *\n * Registers AuthContext in the request container at the start of each request.\n * This MUST run before SessionVerificationMiddleware and any other middleware\n * that depends on AuthContext.\n */\n@Transient()\nexport class AuthContextMiddleware implements Middleware {\n async handle(ctx: RouterContext, next: () => Promise<void>): Promise<void> {\n const requestContainer = ctx.getContainer()\n\n const authContext = new AuthContext()\n requestContainer.registerValue(DI_TOKENS.AuthContext, authContext)\n\n await next()\n }\n}\n","import { inject } from 'tsyringe'\nimport { Transient, DI_TOKENS } from 'stratal/di'\nimport type { Middleware, RouterContext } from 'stratal/router'\nimport { AuthContext } from '../../context/auth-context'\nimport { AUTH_SERVICE } from '../auth.tokens'\nimport type { AuthService } from '../services/auth.service'\n\n/**\n * Session Verification Middleware\n *\n * Verifies user session via Better Auth and populates AuthContext with userId.\n *\n * **Responsibilities:**\n * - Calls Better Auth's getSession() API\n * - Populates AuthContext with userId if session is valid\n * - Continues request chain regardless of session status\n */\n@Transient()\nexport class SessionVerificationMiddleware implements Middleware {\n constructor(\n @inject(AUTH_SERVICE)\n private readonly authService: AuthService\n ) {}\n\n async handle(ctx: RouterContext, next: () => Promise<void>): Promise<void> {\n const session = await this.authService.auth.api.getSession({\n headers: ctx.c.req.raw.headers\n })\n\n if (session) {\n const authContext = ctx.getContainer().resolve<AuthContext>(DI_TOKENS.AuthContext)\n authContext.setAuthContext({ userId: session.user.id })\n }\n\n await next()\n }\n}\n","import { ApplicationError, ERROR_CODES } from 'stratal/errors'\n\nexport class UserNotFoundError extends ApplicationError {\n constructor(email?: string) {\n super('errors.auth.userNotFound', ERROR_CODES.RESOURCE.NOT_FOUND, email ? { email } : undefined)\n }\n}\n\nexport class InvalidCredentialsError extends ApplicationError {\n constructor() {\n super('errors.auth.invalidCredentials', ERROR_CODES.AUTH.INVALID_CREDENTIALS)\n }\n}\n\nexport class InvalidPasswordError extends ApplicationError {\n constructor() {\n super('errors.auth.invalidPassword', ERROR_CODES.AUTH.INVALID_CREDENTIALS)\n }\n}\n\nexport class InvalidEmailError extends ApplicationError {\n constructor(email?: string) {\n super('errors.auth.invalidEmail', ERROR_CODES.VALIDATION.INVALID_FORMAT, email ? { email } : undefined)\n }\n}\n\nexport class SessionExpiredError extends ApplicationError {\n constructor() {\n super('errors.auth.sessionExpired', ERROR_CODES.AUTH.SESSION_EXPIRED)\n }\n}\n\nexport class EmailNotVerifiedError extends ApplicationError {\n constructor(email?: string) {\n super('errors.auth.emailNotVerified', ERROR_CODES.AUTH.EMAIL_NOT_VERIFIED, email ? { email } : undefined)\n }\n}\n\nexport class PasswordTooShortError extends ApplicationError {\n constructor(minLength: number) {\n super('errors.auth.passwordTooShort', ERROR_CODES.AUTH.PASSWORD_TOO_SHORT, { minLength })\n }\n}\n\nexport class PasswordTooLongError extends ApplicationError {\n constructor(maxLength: number) {\n super('errors.auth.passwordTooLong', ERROR_CODES.AUTH.PASSWORD_TOO_LONG, { maxLength })\n }\n}\n\nexport class AccountAlreadyExistsError extends ApplicationError {\n constructor(email?: string) {\n super('errors.auth.accountAlreadyExists', ERROR_CODES.AUTH.ACCOUNT_ALREADY_EXISTS, email ? { email } : undefined)\n }\n}\n\nexport class FailedToCreateUserError extends ApplicationError {\n constructor(reason?: string) {\n super('errors.auth.failedToCreateUser', ERROR_CODES.AUTH.FAILED_TO_CREATE_USER, reason ? { reason } : undefined)\n }\n}\n\nexport class FailedToCreateSessionError extends ApplicationError {\n constructor(reason?: string) {\n super('errors.auth.failedToCreateSession', ERROR_CODES.AUTH.FAILED_TO_CREATE_SESSION, reason ? { reason } : undefined)\n }\n}\n\nexport class FailedToUpdateUserError extends ApplicationError {\n constructor(reason?: string) {\n super('errors.auth.failedToUpdateUser', ERROR_CODES.AUTH.FAILED_TO_UPDATE_USER, reason ? { reason } : undefined)\n }\n}\n\nexport class SocialAccountLinkedError extends ApplicationError {\n constructor(provider?: string) {\n super('errors.auth.socialAccountLinked', ERROR_CODES.AUTH.SOCIAL_ACCOUNT_LINKED, provider ? { provider } : undefined)\n }\n}\n\nexport class CannotUnlinkLastAccountError extends ApplicationError {\n constructor() {\n super('errors.auth.cannotUnlinkLastAccount', ERROR_CODES.AUTH.CANNOT_UNLINK_LAST_ACCOUNT)\n }\n}\n\nexport class ProviderNotFoundError extends ApplicationError {\n constructor(provider?: string) {\n super('errors.auth.providerNotFound', ERROR_CODES.RESOURCE.NOT_FOUND, provider ? { provider } : undefined)\n }\n}\n\nexport class UserEmailNotFoundError extends ApplicationError {\n constructor() {\n super('errors.auth.userEmailNotFound', ERROR_CODES.RESOURCE.NOT_FOUND)\n }\n}\n\nexport class AccountNotFoundError extends ApplicationError {\n constructor() {\n super('errors.auth.accountNotFound', ERROR_CODES.RESOURCE.NOT_FOUND)\n }\n}\n\nexport class CredentialAccountNotFoundError extends ApplicationError {\n constructor() {\n super('errors.auth.credentialAccountNotFound', ERROR_CODES.RESOURCE.NOT_FOUND)\n }\n}\n\nexport class UserAlreadyHasPasswordError extends ApplicationError {\n constructor() {\n super('errors.auth.userAlreadyHasPassword', ERROR_CODES.RESOURCE.CONFLICT)\n }\n}\n\nexport class EmailCannotBeUpdatedError extends ApplicationError {\n constructor(reason?: string) {\n super('errors.auth.emailCannotBeUpdated', ERROR_CODES.VALIDATION.GENERIC, reason ? { reason } : undefined)\n }\n}\n\nexport class FailedToGetSessionError extends ApplicationError {\n constructor(reason?: string) {\n super('errors.auth.failedToGetSession', ERROR_CODES.SYSTEM.INTERNAL_ERROR, reason ? { reason } : undefined)\n }\n}\n\nexport class FailedToGetUserInfoError extends ApplicationError {\n constructor(reason?: string) {\n super('errors.auth.failedToGetUserInfo', ERROR_CODES.SYSTEM.INTERNAL_ERROR, reason ? { reason } : undefined)\n }\n}\n\nexport class IdTokenNotSupportedError extends ApplicationError {\n constructor() {\n super('errors.auth.invalidToken', ERROR_CODES.VALIDATION.GENERIC)\n }\n}\n\nexport class TokenExpiredError extends ApplicationError {\n constructor() {\n super('errors.auth.tokenExpired', ERROR_CODES.VALIDATION.GENERIC)\n }\n}\n","import { ApplicationError, ERROR_CODES } from 'stratal/errors'\n\nexport class InvalidTokenError extends ApplicationError {\n constructor() {\n super('errors.auth.invalidToken', ERROR_CODES.AUTH.INVALID_TOKEN)\n }\n}\n","import { ApplicationError, ERROR_CODES } from 'stratal/errors'\n\nexport class TokenRequiredError extends ApplicationError {\n constructor() {\n super('errors.auth.tokenRequired', ERROR_CODES.VALIDATION.REQUIRED_FIELD, { field: 'token' })\n }\n}\n","import { ApplicationError, ERROR_CODES } from 'stratal/errors'\n\nexport class VerificationFailedError extends ApplicationError {\n constructor() {\n super('errors.auth.verificationFailed', ERROR_CODES.AUTH.INVALID_CREDENTIALS)\n }\n}\n","import { type BASE_ERROR_CODES } from '@better-auth/core/error'\nimport { APIError } from 'better-auth/api'\nimport type { ApplicationError } from 'stratal/errors'\nimport { InternalError } from 'stratal/errors'\nimport {\n AccountAlreadyExistsError,\n AccountNotFoundError,\n CannotUnlinkLastAccountError,\n CredentialAccountNotFoundError,\n EmailCannotBeUpdatedError,\n EmailNotVerifiedError,\n FailedToCreateSessionError,\n FailedToCreateUserError,\n FailedToGetSessionError,\n FailedToGetUserInfoError,\n FailedToUpdateUserError,\n IdTokenNotSupportedError,\n InvalidCredentialsError,\n InvalidEmailError,\n InvalidPasswordError,\n InvalidTokenError,\n PasswordTooLongError,\n PasswordTooShortError,\n ProviderNotFoundError,\n SessionExpiredError,\n SocialAccountLinkedError,\n TokenExpiredError,\n UserAlreadyHasPasswordError,\n UserEmailNotFoundError,\n UserNotFoundError,\n} from '../errors'\n\n/**\n * Maps Better Auth API error codes to ApplicationError instances.\n */\nexport function mapBetterAuthError(error: APIError): ApplicationError {\n const errorCode = error.body?.code as keyof typeof BASE_ERROR_CODES | 'TOKEN_EXPIRED' | undefined\n\n if (error.status === 'FOUND') {\n const headers = error.headers as Headers\n const hasInvalidToken = headers.get('location')?.includes('INVALID_TOKEN')\n\n if (hasInvalidToken) {\n return new InvalidTokenError()\n }\n }\n\n if (!errorCode) {\n return new InternalError({\n originalError: `Better Auth error: ${error.message}`,\n stack: error.stack,\n })\n }\n\n // User errors\n if (errorCode === 'USER_NOT_FOUND') return new UserNotFoundError()\n if (errorCode === 'USER_EMAIL_NOT_FOUND') return new UserEmailNotFoundError()\n\n // Credential errors\n if (errorCode === 'INVALID_EMAIL_OR_PASSWORD') return new InvalidCredentialsError()\n if (errorCode === 'INVALID_PASSWORD') return new InvalidPasswordError()\n if (errorCode === 'INVALID_EMAIL') return new InvalidEmailError()\n\n // Session errors\n if (errorCode === 'SESSION_EXPIRED') return new SessionExpiredError()\n if (errorCode === 'FAILED_TO_CREATE_SESSION') return new FailedToCreateSessionError()\n if (errorCode === 'FAILED_TO_GET_SESSION') return new FailedToGetSessionError()\n\n // Email verification\n if (errorCode === 'EMAIL_NOT_VERIFIED') return new EmailNotVerifiedError()\n if (errorCode === 'EMAIL_CAN_NOT_BE_UPDATED') return new EmailCannotBeUpdatedError()\n\n // Password validation\n if (errorCode === 'PASSWORD_TOO_SHORT') return new PasswordTooShortError(8)\n if (errorCode === 'PASSWORD_TOO_LONG') return new PasswordTooLongError(128)\n\n // Account errors\n if (errorCode === 'USER_ALREADY_EXISTS' || errorCode === 'USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL') {\n return new AccountAlreadyExistsError()\n }\n if (errorCode === 'ACCOUNT_NOT_FOUND') return new AccountNotFoundError()\n if (errorCode === 'CREDENTIAL_ACCOUNT_NOT_FOUND') return new CredentialAccountNotFoundError()\n if (errorCode === 'FAILED_TO_UNLINK_LAST_ACCOUNT') return new CannotUnlinkLastAccountError()\n\n // User creation/update errors\n if (errorCode === 'FAILED_TO_CREATE_USER') return new FailedToCreateUserError()\n if (errorCode === 'FAILED_TO_UPDATE_USER') return new FailedToUpdateUserError()\n if (errorCode === 'FAILED_TO_GET_USER_INFO') return new FailedToGetUserInfoError()\n\n // Social account errors\n if (errorCode === 'SOCIAL_ACCOUNT_ALREADY_LINKED') return new SocialAccountLinkedError()\n if (errorCode === 'PROVIDER_NOT_FOUND') return new ProviderNotFoundError()\n\n // Token errors\n if (errorCode === 'ID_TOKEN_NOT_SUPPORTED') return new IdTokenNotSupportedError()\n if (errorCode === 'INVALID_TOKEN') return new IdTokenNotSupportedError()\n if (errorCode === 'TOKEN_EXPIRED') return new TokenExpiredError()\n\n // Password management\n if (errorCode === 'USER_ALREADY_HAS_PASSWORD') return new UserAlreadyHasPasswordError()\n\n // Unknown error code\n return new InternalError({\n originalError: `Better Auth error [${errorCode}]: ${error.message}`,\n stack: error.stack,\n })\n}\n\n/**\n * Type guard to check if an error is a Better Auth APIError\n */\nexport function isAPIError(error: unknown): error is APIError {\n return error instanceof APIError\n}\n","import type { BetterAuthOptions } from 'better-auth'\nimport { isAPIError, mapBetterAuthError } from './better-auth-error-handler'\n\n/**\n * Get shared Better Auth error handler configuration.\n * Use this in Better Auth config's onAPIError option.\n */\nexport function getErrorHandlerConfig(): BetterAuthOptions['onAPIError'] {\n return {\n throw: false,\n onError: (error) => {\n if (isAPIError(error)) {\n throw mapBetterAuthError(error)\n }\n throw error\n },\n }\n}\n\n/**\n * Wrap a Better Auth function in a try/catch block and map errors to ApplicationError.\n */\nexport const wrapBetterAuth = async <T>(fn: () => Promise<T>): Promise<T> => {\n try {\n return await fn()\n } catch (error) {\n if (isAPIError(error)) {\n throw mapBetterAuthError(error)\n }\n throw error\n }\n}\n","import type { Auth, BetterAuthOptions } from 'better-auth'\nimport { betterAuth } from 'better-auth'\nimport { inject } from 'tsyringe'\nimport { Transient } from 'stratal/di'\nimport { AUTH_OPTIONS, AUTH_SERVICE } from '../auth.tokens'\nimport { getErrorHandlerConfig } from '../utils'\n\n/**\n * AuthService\n *\n * Base authentication service using Better Auth.\n * Configured via AuthModule.forRootAsync() from the application layer.\n *\n * **Extensibility:**\n * Extend this class in application layer to add custom methods.\n *\n * @example\n * ```typescript\n * @Transient(AUTH_SERVICE)\n * export class AppAuthService extends AuthService<AuthOptions> {\n * async signInMagicLink(email: string) {\n * return wrapBetterAuth(async () => {\n * return this.auth.api.signInMagicLink({ body: { email }, headers: new Headers() })\n * })\n * }\n * }\n * ```\n */\n@Transient(AUTH_SERVICE)\nexport class AuthService<TOptions extends BetterAuthOptions = BetterAuthOptions> {\n private authInstance: Auth<TOptions>\n\n constructor(\n @inject(AUTH_OPTIONS) protected readonly options: TOptions\n ) {\n this.authInstance = betterAuth({\n ...this.options,\n onAPIError: getErrorHandlerConfig()\n }) as Auth<TOptions>\n }\n\n /**\n * Get the Better Auth instance\n */\n get auth(): Auth<TOptions> {\n return this.authInstance\n }\n}\n","/**\n * Auth Module\n *\n * Provides configurable authentication using Better Auth.\n * Use `forRootAsync` to configure Better Auth options from the application layer.\n *\n * @example\n * ```typescript\n * @Module({\n * imports: [\n * AuthModule.forRootAsync({\n * inject: [DI_TOKENS.Database, CONFIG_TOKENS.ConfigService],\n * useFactory: (db, config) => createAuthOptions(db, config)\n * })\n * ]\n * })\n * export class AppModule {}\n * ```\n */\n\nimport type { BetterAuthOptions } from 'better-auth'\nimport type { MiddlewareConfigurable, MiddlewareConsumer } from 'stratal/middleware'\nimport { Module } from 'stratal/module'\nimport type { AsyncModuleOptions, DynamicModule } from 'stratal/module'\nimport { AUTH_OPTIONS, AUTH_SERVICE } from './auth.tokens'\nimport { AuthContextMiddleware } from './middleware/auth-context.middleware'\nimport { SessionVerificationMiddleware } from './middleware/session-verification.middleware'\nimport { AuthService } from './services/auth.service'\n\n@Module({\n providers: []\n})\nexport class AuthModule implements MiddlewareConfigurable {\n /**\n * Configure auth middleware.\n *\n * Registers middlewares in order:\n * 1. AuthContextMiddleware - Creates and registers AuthContext in request container\n * 2. SessionVerificationMiddleware - Verifies session and populates AuthContext with userId\n */\n configure(consumer: MiddlewareConsumer): void {\n consumer\n .apply(AuthContextMiddleware)\n .forRoutes('*')\n\n consumer\n .apply(SessionVerificationMiddleware)\n .forRoutes('*')\n }\n\n /**\n * Configure AuthModule with async options factory\n */\n static forRootAsync<TOptions extends BetterAuthOptions>(\n options: AsyncModuleOptions<TOptions>\n ): DynamicModule {\n return {\n module: AuthModule,\n providers: [\n {\n provide: AUTH_OPTIONS,\n useFactory: options.useFactory,\n inject: options.inject\n },\n {\n provide: AUTH_SERVICE,\n useClass: AuthService\n }\n ]\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/auth/auth.tokens.ts","../../src/auth/middleware/auth-context.middleware.ts","../../src/auth/middleware/session-verification.middleware.ts","../../src/auth/errors/auth-errors.ts","../../src/auth/errors/invalid-token.error.ts","../../src/auth/errors/token-required.error.ts","../../src/auth/errors/verification-failed.error.ts","../../src/auth/utils/better-auth-error-handler.ts","../../src/auth/utils/auth-helpers.ts","../../src/auth/services/auth.service.ts","../../src/auth/auth.module.ts"],"sourcesContent":["/** Token for AuthService - core authentication service */\nexport const AUTH_SERVICE = Symbol.for('stratal:auth:service')\n\n/** Token for Better Auth options configuration */\nexport const AUTH_OPTIONS = Symbol.for('stratal:auth:options')\n","import { DI_TOKENS, Transient } from 'stratal/di'\nimport type { Middleware, Next, RouterContext } from 'stratal/router'\nimport { AuthContext } from '../../context/auth-context'\n\n/**\n * Auth Context Middleware\n *\n * Registers AuthContext in the request container at the start of each request.\n * This MUST run before SessionVerificationMiddleware and any other middleware\n * that depends on AuthContext.\n */\n@Transient()\nexport class AuthContextMiddleware implements Middleware {\n async handle(ctx: RouterContext, next: Next): Promise<void> {\n const requestContainer = ctx.getContainer()\n\n const authContext = new AuthContext()\n requestContainer.registerValue(DI_TOKENS.AuthContext, authContext)\n\n await next()\n }\n}\n","import { DI_TOKENS, Transient } from 'stratal/di'\nimport { LOGGER_TOKENS, type LoggerService } from 'stratal/logger'\nimport type { Middleware, Next, RouterContext } from 'stratal/router'\nimport { inject } from 'tsyringe'\nimport { type AuthContext } from '../../context/auth-context'\nimport { AUTH_SERVICE } from '../auth.tokens'\nimport type { AuthService } from '../services/auth.service'\n\n/**\n * Session Verification Middleware\n *\n * Verifies user session via Better Auth and populates AuthContext with userId.\n *\n * **Responsibilities:**\n * - Calls Better Auth's getSession() API\n * - Populates AuthContext with userId if session is valid\n * - Continues request chain regardless of session status\n */\n@Transient()\nexport class SessionVerificationMiddleware implements Middleware {\n constructor(\n @inject(AUTH_SERVICE)\n private readonly authService: AuthService,\n @inject(LOGGER_TOKENS.LoggerService) private logger: LoggerService\n ) { }\n\n async handle(ctx: RouterContext, next: Next): Promise<void> {\n try {\n const session = await this.authService.auth.api.getSession({\n headers: ctx.c.req.raw.headers\n })\n\n if (session) {\n const authContext = ctx.getContainer().resolve<AuthContext>(DI_TOKENS.AuthContext)\n authContext.setAuthContext({ userId: session.user.id })\n }\n\n await next()\n } catch (error: unknown) {\n this.logger.debug('Session validation failed (e.g., invalidated in DB)', { error });\n await next()\n }\n }\n}\n","import { ApplicationError, ERROR_CODES } from 'stratal/errors'\n\nexport class UserNotFoundError extends ApplicationError {\n constructor(email?: string) {\n super('errors.auth.userNotFound', ERROR_CODES.RESOURCE.NOT_FOUND, email ? { email } : undefined)\n }\n}\n\nexport class InvalidCredentialsError extends ApplicationError {\n constructor() {\n super('errors.auth.invalidCredentials', ERROR_CODES.AUTH.INVALID_CREDENTIALS)\n }\n}\n\nexport class InvalidPasswordError extends ApplicationError {\n constructor() {\n super('errors.auth.invalidPassword', ERROR_CODES.AUTH.INVALID_CREDENTIALS)\n }\n}\n\nexport class InvalidEmailError extends ApplicationError {\n constructor(email?: string) {\n super('errors.auth.invalidEmail', ERROR_CODES.VALIDATION.INVALID_FORMAT, email ? { email } : undefined)\n }\n}\n\nexport class SessionExpiredError extends ApplicationError {\n constructor() {\n super('errors.auth.sessionExpired', ERROR_CODES.AUTH.SESSION_EXPIRED)\n }\n}\n\nexport class EmailNotVerifiedError extends ApplicationError {\n constructor(email?: string) {\n super('errors.auth.emailNotVerified', ERROR_CODES.AUTH.EMAIL_NOT_VERIFIED, email ? { email } : undefined)\n }\n}\n\nexport class PasswordTooShortError extends ApplicationError {\n constructor(minLength: number) {\n super('errors.auth.passwordTooShort', ERROR_CODES.AUTH.PASSWORD_TOO_SHORT, { minLength })\n }\n}\n\nexport class PasswordTooLongError extends ApplicationError {\n constructor(maxLength: number) {\n super('errors.auth.passwordTooLong', ERROR_CODES.AUTH.PASSWORD_TOO_LONG, { maxLength })\n }\n}\n\nexport class AccountAlreadyExistsError extends ApplicationError {\n constructor(email?: string) {\n super('errors.auth.accountAlreadyExists', ERROR_CODES.AUTH.ACCOUNT_ALREADY_EXISTS, email ? { email } : undefined)\n }\n}\n\nexport class FailedToCreateUserError extends ApplicationError {\n constructor(reason?: string) {\n super('errors.auth.failedToCreateUser', ERROR_CODES.AUTH.FAILED_TO_CREATE_USER, reason ? { reason } : undefined)\n }\n}\n\nexport class FailedToCreateSessionError extends ApplicationError {\n constructor(reason?: string) {\n super('errors.auth.failedToCreateSession', ERROR_CODES.AUTH.FAILED_TO_CREATE_SESSION, reason ? { reason } : undefined)\n }\n}\n\nexport class FailedToUpdateUserError extends ApplicationError {\n constructor(reason?: string) {\n super('errors.auth.failedToUpdateUser', ERROR_CODES.AUTH.FAILED_TO_UPDATE_USER, reason ? { reason } : undefined)\n }\n}\n\nexport class SocialAccountLinkedError extends ApplicationError {\n constructor(provider?: string) {\n super('errors.auth.socialAccountLinked', ERROR_CODES.AUTH.SOCIAL_ACCOUNT_LINKED, provider ? { provider } : undefined)\n }\n}\n\nexport class CannotUnlinkLastAccountError extends ApplicationError {\n constructor() {\n super('errors.auth.cannotUnlinkLastAccount', ERROR_CODES.AUTH.CANNOT_UNLINK_LAST_ACCOUNT)\n }\n}\n\nexport class ProviderNotFoundError extends ApplicationError {\n constructor(provider?: string) {\n super('errors.auth.providerNotFound', ERROR_CODES.RESOURCE.NOT_FOUND, provider ? { provider } : undefined)\n }\n}\n\nexport class UserEmailNotFoundError extends ApplicationError {\n constructor() {\n super('errors.auth.userEmailNotFound', ERROR_CODES.RESOURCE.NOT_FOUND)\n }\n}\n\nexport class AccountNotFoundError extends ApplicationError {\n constructor() {\n super('errors.auth.accountNotFound', ERROR_CODES.RESOURCE.NOT_FOUND)\n }\n}\n\nexport class CredentialAccountNotFoundError extends ApplicationError {\n constructor() {\n super('errors.auth.credentialAccountNotFound', ERROR_CODES.RESOURCE.NOT_FOUND)\n }\n}\n\nexport class UserAlreadyHasPasswordError extends ApplicationError {\n constructor() {\n super('errors.auth.userAlreadyHasPassword', ERROR_CODES.RESOURCE.CONFLICT)\n }\n}\n\nexport class EmailCannotBeUpdatedError extends ApplicationError {\n constructor(reason?: string) {\n super('errors.auth.emailCannotBeUpdated', ERROR_CODES.VALIDATION.GENERIC, reason ? { reason } : undefined)\n }\n}\n\nexport class FailedToGetSessionError extends ApplicationError {\n constructor(reason?: string) {\n super('errors.auth.failedToGetSession', ERROR_CODES.SYSTEM.INTERNAL_ERROR, reason ? { reason } : undefined)\n }\n}\n\nexport class FailedToGetUserInfoError extends ApplicationError {\n constructor(reason?: string) {\n super('errors.auth.failedToGetUserInfo', ERROR_CODES.SYSTEM.INTERNAL_ERROR, reason ? { reason } : undefined)\n }\n}\n\nexport class IdTokenNotSupportedError extends ApplicationError {\n constructor() {\n super('errors.auth.invalidToken', ERROR_CODES.VALIDATION.GENERIC)\n }\n}\n\nexport class TokenExpiredError extends ApplicationError {\n constructor() {\n super('errors.auth.tokenExpired', ERROR_CODES.VALIDATION.GENERIC)\n }\n}\n","import { ApplicationError, ERROR_CODES } from 'stratal/errors'\n\nexport class InvalidTokenError extends ApplicationError {\n constructor() {\n super('errors.auth.invalidToken', ERROR_CODES.AUTH.INVALID_TOKEN)\n }\n}\n","import { ApplicationError, ERROR_CODES } from 'stratal/errors'\n\nexport class TokenRequiredError extends ApplicationError {\n constructor() {\n super('errors.auth.tokenRequired', ERROR_CODES.VALIDATION.REQUIRED_FIELD, { field: 'token' })\n }\n}\n","import { ApplicationError, ERROR_CODES } from 'stratal/errors'\n\nexport class VerificationFailedError extends ApplicationError {\n constructor() {\n super('errors.auth.verificationFailed', ERROR_CODES.AUTH.INVALID_CREDENTIALS)\n }\n}\n","import { type BASE_ERROR_CODES } from '@better-auth/core/error'\nimport { APIError } from 'better-auth/api'\nimport type { ApplicationError } from 'stratal/errors'\nimport { InternalError } from 'stratal/errors'\nimport {\n AccountAlreadyExistsError,\n AccountNotFoundError,\n CannotUnlinkLastAccountError,\n CredentialAccountNotFoundError,\n EmailCannotBeUpdatedError,\n EmailNotVerifiedError,\n FailedToCreateSessionError,\n FailedToCreateUserError,\n FailedToGetSessionError,\n FailedToGetUserInfoError,\n FailedToUpdateUserError,\n IdTokenNotSupportedError,\n InvalidCredentialsError,\n InvalidEmailError,\n InvalidPasswordError,\n InvalidTokenError,\n PasswordTooLongError,\n PasswordTooShortError,\n ProviderNotFoundError,\n SessionExpiredError,\n SocialAccountLinkedError,\n TokenExpiredError,\n UserAlreadyHasPasswordError,\n UserEmailNotFoundError,\n UserNotFoundError,\n} from '../errors'\n\n/**\n * Maps Better Auth API error codes to ApplicationError instances.\n */\nexport function mapBetterAuthError(error: APIError): ApplicationError {\n const errorCode = error.body?.code as keyof typeof BASE_ERROR_CODES | 'TOKEN_EXPIRED' | undefined\n\n if (error.status === 'FOUND') {\n const headers = error.headers as Headers\n const location = headers.get('location') ?? ''\n\n if (location.includes('INVALID_TOKEN')) return new InvalidTokenError()\n if (location.includes('EXPIRED_TOKEN')) return new TokenExpiredError()\n if (location.includes('ATTEMPTS_EXCEEDED')) return new InvalidTokenError()\n if (location.includes('new_user_signup_disabled')) return new UserNotFoundError()\n if (location.includes('failed_to_create_user')) return new FailedToCreateUserError()\n if (location.includes('failed_to_create_session')) return new FailedToCreateSessionError()\n }\n\n if (!errorCode) {\n return new InternalError({\n originalError: `Better Auth error: ${error.message}`,\n stack: error.stack,\n })\n }\n\n // User errors\n if (errorCode === 'USER_NOT_FOUND') return new UserNotFoundError()\n if (errorCode === 'USER_EMAIL_NOT_FOUND') return new UserEmailNotFoundError()\n\n // Credential errors\n if (errorCode === 'INVALID_EMAIL_OR_PASSWORD') return new InvalidCredentialsError()\n if (errorCode === 'INVALID_PASSWORD') return new InvalidPasswordError()\n if (errorCode === 'INVALID_EMAIL') return new InvalidEmailError()\n\n // Session errors\n if (errorCode === 'SESSION_EXPIRED') return new SessionExpiredError()\n if (errorCode === 'FAILED_TO_CREATE_SESSION') return new FailedToCreateSessionError()\n if (errorCode === 'FAILED_TO_GET_SESSION') return new FailedToGetSessionError()\n\n // Email verification\n if (errorCode === 'EMAIL_NOT_VERIFIED') return new EmailNotVerifiedError()\n if (errorCode === 'EMAIL_CAN_NOT_BE_UPDATED') return new EmailCannotBeUpdatedError()\n\n // Password validation\n if (errorCode === 'PASSWORD_TOO_SHORT') return new PasswordTooShortError(8)\n if (errorCode === 'PASSWORD_TOO_LONG') return new PasswordTooLongError(128)\n\n // Account errors\n if (errorCode === 'USER_ALREADY_EXISTS' || errorCode === 'USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL') {\n return new AccountAlreadyExistsError()\n }\n if (errorCode === 'ACCOUNT_NOT_FOUND') return new AccountNotFoundError()\n if (errorCode === 'CREDENTIAL_ACCOUNT_NOT_FOUND') return new CredentialAccountNotFoundError()\n if (errorCode === 'FAILED_TO_UNLINK_LAST_ACCOUNT') return new CannotUnlinkLastAccountError()\n\n // User creation/update errors\n if (errorCode === 'FAILED_TO_CREATE_USER') return new FailedToCreateUserError()\n if (errorCode === 'FAILED_TO_UPDATE_USER') return new FailedToUpdateUserError()\n if (errorCode === 'FAILED_TO_GET_USER_INFO') return new FailedToGetUserInfoError()\n\n // Social account errors\n if (errorCode === 'SOCIAL_ACCOUNT_ALREADY_LINKED') return new SocialAccountLinkedError()\n if (errorCode === 'PROVIDER_NOT_FOUND') return new ProviderNotFoundError()\n\n // Token errors\n if (errorCode === 'ID_TOKEN_NOT_SUPPORTED') return new IdTokenNotSupportedError()\n if (errorCode === 'INVALID_TOKEN') return new IdTokenNotSupportedError()\n if (errorCode === 'TOKEN_EXPIRED') return new TokenExpiredError()\n\n // Password management\n if (errorCode === 'USER_ALREADY_HAS_PASSWORD') return new UserAlreadyHasPasswordError()\n\n // Unknown error code\n return new InternalError({\n originalError: `Better Auth error [${errorCode}]: ${error.message}`,\n stack: error.stack,\n })\n}\n\n/**\n * Type guard to check if an error is a Better Auth APIError.\n * Uses duck typing to handle bundler environments (e.g. Vite)\n * where instanceof may fail across module boundaries.\n */\nexport function isAPIError(error: unknown): error is APIError {\n if (error instanceof APIError) return true\n\n return (\n error instanceof Error\n && error.name === 'APIError'\n && 'status' in error\n && 'statusCode' in error\n )\n}\n","import type { BetterAuthOptions } from 'better-auth'\nimport { isAPIError, mapBetterAuthError } from './better-auth-error-handler'\n\n/**\n * Get shared Better Auth error handler configuration.\n * Use this in Better Auth config's onAPIError option.\n */\nexport function getErrorHandlerConfig(): BetterAuthOptions['onAPIError'] {\n return {\n throw: false,\n onError: (error) => {\n if (isAPIError(error)) {\n throw mapBetterAuthError(error)\n }\n throw error\n },\n }\n}\n\n/**\n * Wrap a Better Auth function in a try/catch block and map errors to ApplicationError.\n */\nexport const wrapBetterAuth = async <T>(fn: () => Promise<T>): Promise<T> => {\n try {\n return await fn()\n } catch (error) {\n if (isAPIError(error)) {\n throw mapBetterAuthError(error)\n }\n throw error\n }\n}\n","import type { Auth, BetterAuthOptions } from 'better-auth'\nimport { betterAuth } from 'better-auth'\nimport { inject } from 'tsyringe'\nimport { Transient } from 'stratal/di'\nimport { AUTH_OPTIONS, AUTH_SERVICE } from '../auth.tokens'\nimport { getErrorHandlerConfig } from '../utils'\n\n/**\n * AuthService\n *\n * Base authentication service using Better Auth.\n * Configured via AuthModule.forRootAsync() from the application layer.\n *\n * **Extensibility:**\n * Extend this class in application layer to add custom methods.\n *\n * @example\n * ```typescript\n * @Transient(AUTH_SERVICE)\n * export class AppAuthService extends AuthService<AuthOptions> {\n * async signInMagicLink(email: string) {\n * return wrapBetterAuth(async () => {\n * return this.auth.api.signInMagicLink({ body: { email }, headers: new Headers() })\n * })\n * }\n * }\n * ```\n */\n@Transient(AUTH_SERVICE)\nexport class AuthService<TOptions extends BetterAuthOptions = BetterAuthOptions> {\n private authInstance: Auth<TOptions>\n\n constructor(\n @inject(AUTH_OPTIONS) protected readonly options: TOptions\n ) {\n this.authInstance = betterAuth({\n ...this.options,\n onAPIError: getErrorHandlerConfig()\n }) as Auth<TOptions>\n }\n\n /**\n * Get the Better Auth instance\n */\n get auth(): Auth<TOptions> {\n return this.authInstance\n }\n}\n","/**\n * Auth Module\n *\n * Provides configurable authentication using Better Auth.\n * Use `forRootAsync` to configure Better Auth options from the application layer.\n *\n * @example\n * ```typescript\n * @Module({\n * imports: [\n * AuthModule.forRootAsync({\n * inject: [DI_TOKENS.Database, CONFIG_TOKENS.ConfigService],\n * useFactory: (db, config) => createAuthOptions(db, config)\n * })\n * ]\n * })\n * export class AppModule {}\n * ```\n */\n\nimport type { BetterAuthOptions } from 'better-auth'\nimport type { RouteConfigurable, Router } from 'stratal/router'\nimport { Module } from 'stratal/module'\nimport type { AsyncModuleOptions, DynamicModule } from 'stratal/module'\nimport { AUTH_OPTIONS, AUTH_SERVICE } from './auth.tokens'\nimport { AuthContextMiddleware } from './middleware/auth-context.middleware'\nimport { SessionVerificationMiddleware } from './middleware/session-verification.middleware'\nimport { AuthService } from './services/auth.service'\n\n@Module({\n providers: []\n})\nexport class AuthModule implements RouteConfigurable {\n /**\n * Configure auth middleware globally.\n *\n * Registers middlewares in order:\n * 1. AuthContextMiddleware - Creates and registers AuthContext in request container\n * 2. SessionVerificationMiddleware - Verifies session and populates AuthContext with userId\n */\n configureRoutes(router: Router): void {\n router.use(AuthContextMiddleware, SessionVerificationMiddleware)\n }\n\n /**\n * Configure AuthModule with async options factory\n */\n static forRootAsync<TOptions extends BetterAuthOptions>(\n options: AsyncModuleOptions<TOptions>\n ): DynamicModule {\n return {\n module: AuthModule,\n providers: [\n {\n provide: AUTH_OPTIONS,\n useFactory: options.useFactory,\n inject: options.inject\n },\n {\n provide: AUTH_SERVICE,\n useClass: AuthService\n }\n ]\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as UserNotAuthenticatedError, r as ContextNotInitializedError } from "./errors-C_KIIU1v.mjs";
|
|
2
|
-
import { t as __decorate } from "./decorate-
|
|
2
|
+
import { t as __decorate } from "./decorate-C12QolJF.mjs";
|
|
3
3
|
import { DI_TOKENS, Transient } from "stratal/di";
|
|
4
4
|
//#region src/context/auth-context.ts
|
|
5
5
|
let AuthContext = class AuthContext {
|
|
@@ -52,4 +52,4 @@ AuthContext = __decorate([Transient(DI_TOKENS.AuthContext)], AuthContext);
|
|
|
52
52
|
//#endregion
|
|
53
53
|
export { AuthContext as t };
|
|
54
54
|
|
|
55
|
-
//# sourceMappingURL=auth-context-
|
|
55
|
+
//# sourceMappingURL=auth-context-BfekHvM9.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-context-
|
|
1
|
+
{"version":3,"file":"auth-context-BfekHvM9.mjs","names":[],"sources":["../src/context/auth-context.ts"],"sourcesContent":["import { Transient, DI_TOKENS } from 'stratal/di'\nimport {\n ContextNotInitializedError,\n UserNotAuthenticatedError\n} from './errors'\n\nexport interface AuthInfo {\n userId?: string\n}\n\n@Transient(DI_TOKENS.AuthContext)\nexport class AuthContext {\n protected userId?: string\n\n /**\n * Set authentication context.\n * This should be called once per request with user information.\n */\n setAuthContext(info: AuthInfo): void {\n this.userId = info.userId\n }\n\n /**\n * Get user ID if available.\n * Returns undefined if no user is authenticated.\n */\n getUserId(): string | undefined {\n return this.userId\n }\n\n /**\n * Get user ID or throw if not authenticated.\n * Use this when authentication is required.\n */\n requireUserId(): string {\n const userId = this.getUserId()\n if (!userId) {\n throw new UserNotAuthenticatedError()\n }\n return userId\n }\n\n /**\n * Get full authentication context or throw if not initialized.\n */\n getAuthContext(): AuthInfo {\n if (!this.userId) {\n throw new ContextNotInitializedError('Authentication')\n }\n return {\n userId: this.userId\n }\n }\n\n /**\n * Check if user is authenticated.\n */\n isAuthenticated(): boolean {\n return !!this.userId\n }\n\n /**\n * Clear authentication context.\n * Useful for testing or cleanup.\n */\n clearAuthContext(): void {\n this.userId = undefined\n }\n}\n"],"mappings":";;;;AAWO,IAAA,cAAA,MAAM,YAAY;CACvB;;;;;CAMA,eAAe,MAAsB;AACnC,OAAK,SAAS,KAAK;;;;;;CAOrB,YAAgC;AAC9B,SAAO,KAAK;;;;;;CAOd,gBAAwB;EACtB,MAAM,SAAS,KAAK,WAAW;AAC/B,MAAI,CAAC,OACH,OAAM,IAAI,2BAA2B;AAEvC,SAAO;;;;;CAMT,iBAA2B;AACzB,MAAI,CAAC,KAAK,OACR,OAAM,IAAI,2BAA2B,iBAAiB;AAExD,SAAO,EACL,QAAQ,KAAK,QACd;;;;;CAMH,kBAA2B;AACzB,SAAO,CAAC,CAAC,KAAK;;;;;;CAOhB,mBAAyB;AACvB,OAAK,SAAS,KAAA;;;0BAxDjB,UAAU,UAAU,YAAY,CAAA,EAAA,YAAA"}
|
package/dist/context/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { n as UserNotAuthenticatedError, r as ContextNotInitializedError, t as UserNotAuthorizedError } from "../errors-C_KIIU1v.mjs";
|
|
2
|
-
import { t as AuthContext } from "../auth-context-
|
|
2
|
+
import { t as AuthContext } from "../auth-context-BfekHvM9.mjs";
|
|
3
3
|
export { AuthContext, ContextNotInitializedError, UserNotAuthenticatedError, UserNotAuthorizedError };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { a as InternalDatabaseEventContext, i as InferConnectionSchema, n as DefaultConnectionName, o as StratalDatabase, r as InferAnySchema, t as ConnectionName } from "../types-Gjk0d2qB.mjs";
|
|
2
|
-
import { A as InjectDB, C as fromZenStackError, D as ForeignKeyConstraintError, E as InvalidErrorCodeRangeError, F as DatabaseModule, I as DatabaseModuleConfig, M as connectionSymbol, N as DatabaseService, O as DatabaseConfigError, P as DatabaseConnectionConfig, S as ParseEvent, T as RecordNotFoundError, _ as DatabaseOperation, a as DbPushCommand, b as GetResult, c as ZenStackCommand, d as EventEmitterPlugin, f as EventEmitterPluginOptions, g as DatabaseEvents, h as DatabaseEventName, i as MigrateDeployCommand, j as DATABASE_TOKENS, k as DatabaseError, l as SchemaSwitcherPlugin, m as databaseI18n, n as MigrateResetCommand, o as DbPullCommand, p as ErrorHandlerPlugin, r as MigrateDevCommand, s as DbGenerateCommand, t as MigrateStatusCommand, u as SchemaSwitcherPluginOptions, v as EventPhase, w as UniqueConstraintError, x as ModelName, y as GetData } from "../index-
|
|
2
|
+
import { A as InjectDB, C as fromZenStackError, D as ForeignKeyConstraintError, E as InvalidErrorCodeRangeError, F as DatabaseModule, I as DatabaseModuleConfig, M as connectionSymbol, N as DatabaseService, O as DatabaseConfigError, P as DatabaseConnectionConfig, S as ParseEvent, T as RecordNotFoundError, _ as DatabaseOperation, a as DbPushCommand, b as GetResult, c as ZenStackCommand, d as EventEmitterPlugin, f as EventEmitterPluginOptions, g as DatabaseEvents, h as DatabaseEventName, i as MigrateDeployCommand, j as DATABASE_TOKENS, k as DatabaseError, l as SchemaSwitcherPlugin, m as databaseI18n, n as MigrateResetCommand, o as DbPullCommand, p as ErrorHandlerPlugin, r as MigrateDevCommand, s as DbGenerateCommand, t as MigrateStatusCommand, u as SchemaSwitcherPluginOptions, v as EventPhase, w as UniqueConstraintError, x as ModelName, y as GetData } from "../index-B1iGBJcO.mjs";
|
|
3
3
|
export { ConnectionName, DATABASE_TOKENS, DatabaseConfigError, DatabaseConnectionConfig, DatabaseError, DatabaseEventName, DatabaseEvents, DatabaseModule, DatabaseModuleConfig, DatabaseOperation, DatabaseService, DbGenerateCommand, DbPullCommand, DbPushCommand, DefaultConnectionName, ErrorHandlerPlugin, EventEmitterPlugin, EventEmitterPluginOptions, EventPhase, ForeignKeyConstraintError, GetData, GetResult, InferAnySchema, InferConnectionSchema, InjectDB, InternalDatabaseEventContext, InvalidErrorCodeRangeError, MigrateDeployCommand, MigrateDevCommand, MigrateResetCommand, MigrateStatusCommand, ModelName, ParseEvent, RecordNotFoundError, SchemaSwitcherPlugin, SchemaSwitcherPluginOptions, StratalDatabase, UniqueConstraintError, ZenStackCommand, connectionSymbol, databaseI18n, fromZenStackError };
|
package/dist/database/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as __decorate } from "../decorate-
|
|
2
|
-
import { t as __decorateMetadata } from "../decorateMetadata-
|
|
1
|
+
import { t as __decorate } from "../decorate-C12QolJF.mjs";
|
|
2
|
+
import { t as __decorateMetadata } from "../decorateMetadata-rWbWGUuO.mjs";
|
|
3
3
|
import { Module } from "stratal/module";
|
|
4
4
|
import { DI_TOKENS, Scope, Transient, delay } from "stratal/di";
|
|
5
5
|
import { ApplicationError, ERROR_CODES } from "stratal/errors";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/database/commands/zenstack.command.ts","../../src/database/commands/db-generate.command.ts","../../src/database/commands/db-pull.command.ts","../../src/database/commands/db-push.command.ts","../../src/database/commands/migrate-deploy.command.ts","../../src/database/commands/migrate-dev.command.ts","../../src/database/commands/migrate-reset.command.ts","../../src/database/commands/migrate-status.command.ts","../../src/database/errors/invalid-error-code-range.error.ts","../../src/database/errors/database-error.ts","../../src/database/errors/database-config.error.ts","../../src/database/errors/foreign-key-constraint.error.ts","../../src/database/errors/record-not-found.error.ts","../../src/database/errors/unique-constraint.error.ts","../../src/database/errors/from-zenstack-error.ts","../../src/database/plugins/error-handler.plugin.ts","../../src/database/plugins/event-emitter.plugin.ts","../../src/database/plugins/schema-switcher.plugin.ts","../../src/database/database.helpers.ts","../../src/database/database.tokens.ts","../../src/database/database.module.ts","../../src/database/decorators/inject-db.decorator.ts","../../src/database/i18n/en.ts"],"sourcesContent":["import { Command } from 'stratal/quarry'\n\n/**\n * Base command for ZenStack CLI wrappers.\n * Uses execFileSync with array arguments to prevent shell injection.\n */\nexport abstract class ZenStackCommand extends Command {\n protected async zenstack(args: string[]): Promise<number> {\n // Dynamic import — node:child_process is only available in the Quarry CLI (Node) context\n const { execFileSync } = await import('node:child_process')\n\n try {\n const output = execFileSync('npx', ['zenstack', ...args], {\n encoding: 'utf-8',\n stdio: 'pipe',\n })\n if (output) this.info(output.trim())\n return 0\n } catch (err) {\n const error = err as { stderr?: string; stdout?: string; status?: number }\n if (error.stderr) this.error(error.stderr.trim())\n if (error.stdout) this.info(error.stdout.trim())\n return error.status ?? 1\n }\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class DbGenerateCommand extends ZenStackCommand {\n static command = 'db:generate {--schema= : Path to schema file} {--watch : Enable watch mode}'\n static description = 'Generate ZenStack ORM client'\n\n async handle(): Promise<number> {\n const args = ['generate']\n const schema = this.string('schema')\n\n if (schema) args.push('--schema', schema)\n if (this.boolean('watch')) args.push('--watch')\n\n return this.zenstack(args)\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class DbPullCommand extends ZenStackCommand {\n static command = 'db:pull {--schema= : Path to schema file}'\n static description = 'Introspect database and generate schema'\n\n async handle(): Promise<number> {\n const args = ['db', 'pull']\n const schema = this.string('schema')\n\n if (schema) args.push('--schema', schema)\n\n return this.zenstack(args)\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class DbPushCommand extends ZenStackCommand {\n static command = 'db:push {--schema= : Path to schema file} {--accept-data-loss : Accept data loss} {--force-reset : Force reset database}'\n static description = 'Push database schema changes'\n\n async handle(): Promise<number> {\n const args = ['db', 'push']\n const schema = this.string('schema')\n\n if (schema) args.push('--schema', schema)\n if (this.boolean('accept-data-loss')) args.push('--accept-data-loss')\n if (this.boolean('force-reset')) args.push('--force-reset')\n\n return this.zenstack(args)\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class MigrateDeployCommand extends ZenStackCommand {\n static command = 'migrate:deploy {--schema= : Path to schema file}'\n static description = 'Deploy pending migrations'\n\n async handle(): Promise<number> {\n const args = ['migrate', 'deploy']\n const schema = this.string('schema')\n\n if (schema) args.push('--schema', schema)\n\n return this.zenstack(args)\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class MigrateDevCommand extends ZenStackCommand {\n static command = 'migrate:dev {--schema= : Path to schema file} {--name= : Migration name} {--create-only : Create without applying}'\n static description = 'Create and apply migration'\n\n async handle(): Promise<number> {\n const args = ['migrate', 'dev']\n const schema = this.string('schema')\n const name = this.string('name')\n\n if (schema) args.push('--schema', schema)\n if (name) args.push('--name', name)\n if (this.boolean('create-only')) args.push('--create-only')\n\n return this.zenstack(args)\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class MigrateResetCommand extends ZenStackCommand {\n static command = 'migrate:reset {--schema= : Path to schema file} {--force : Skip confirmation} {--skip-seed : Skip seeding}'\n static description = 'Reset database'\n\n async handle(): Promise<number> {\n const args = ['migrate', 'reset']\n const schema = this.string('schema')\n\n if (schema) args.push('--schema', schema)\n if (this.boolean('force')) args.push('--force')\n if (this.boolean('skip-seed')) args.push('--skip-seed')\n\n return this.zenstack(args)\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class MigrateStatusCommand extends ZenStackCommand {\n static command = 'migrate:status {--schema= : Path to schema file}'\n static description = 'Check migration status'\n\n async handle(): Promise<number> {\n const args = ['migrate', 'status']\n const schema = this.string('schema')\n\n if (schema) args.push('--schema', schema)\n\n return this.zenstack(args)\n }\n}\n","import { ApplicationError, ERROR_CODES } from 'stratal/errors'\n\n/**\n * InvalidErrorCodeRangeError\n *\n * Thrown when a DatabaseError subclass is constructed with an error code\n * outside the valid database error range (2000-2999).\n * This is a developer-facing error to enforce error code conventions.\n */\nexport class InvalidErrorCodeRangeError extends ApplicationError {\n constructor(code: number, expectedRange: string) {\n super(\n 'errors.invalidErrorCodeRange',\n ERROR_CODES.SYSTEM.INVALID_ERROR_CODE_RANGE,\n { code, expectedRange }\n )\n }\n}\n","import type { MessageKeys } from 'stratal/i18n'\nimport { ApplicationError, ERROR_CODES, type ErrorCode } from 'stratal/errors'\nimport { InvalidErrorCodeRangeError } from './invalid-error-code-range.error'\n\n/**\n * DatabaseError\n *\n * Generic database error thrown when a database operation fails\n * and doesn't fit into a more specific error category.\n *\n * This is the base class for all database-related errors.\n */\nexport class DatabaseError extends ApplicationError {\n constructor(\n messageKey: MessageKeys = 'errors.databaseGeneric',\n code: ErrorCode = ERROR_CODES.DATABASE.GENERIC,\n metadata?: Record<string, unknown>\n ) {\n // Validate that code is in the database error range\n if (code < 2000 || code >= 3000) {\n throw new InvalidErrorCodeRangeError(code, '2000-2999')\n }\n\n super(messageKey, code, metadata)\n }\n}\n","import { ERROR_CODES } from 'stratal/errors'\nimport { DatabaseError } from './database-error'\n\nexport class DatabaseConfigError extends DatabaseError {\n constructor(details: string) {\n super('errors.databaseGeneric', ERROR_CODES.DATABASE.GENERIC, { details })\n }\n}\n","import { ERROR_CODES } from 'stratal/errors'\nimport { DatabaseError } from './database-error'\n\n/**\n * ForeignKeyConstraintError\n *\n * Thrown when a database foreign key constraint is violated.\n * This typically occurs when:\n * - Trying to insert a record with a foreign key that doesn't exist\n * - Trying to delete a record that is referenced by other records\n * - Trying to update a foreign key to a non-existent value\n */\nexport class ForeignKeyConstraintError extends DatabaseError {\n constructor(field?: string) {\n super('errors.databaseForeignKeyConstraint', ERROR_CODES.DATABASE.FOREIGN_KEY_CONSTRAINT, {\n field,\n })\n }\n}\n","import { ERROR_CODES } from 'stratal/errors'\nimport { DatabaseError } from './database-error'\n\n/**\n * RecordNotFoundError\n *\n * Generic error thrown when a database record is not found.\n * This is typically thrown when a findUnique or findFirst operation\n * returns null, or when a required record doesn't exist.\n *\n * Services should catch this and optionally refine it to a more specific\n * domain error (e.g., NoteNotFoundError, UserNotFoundError).\n */\nexport class RecordNotFoundError extends DatabaseError {\n constructor(details?: string) {\n super('errors.databaseRecordNotFound', ERROR_CODES.DATABASE.RECORD_NOT_FOUND, {\n details,\n })\n }\n}\n","import { ERROR_CODES } from 'stratal/errors'\nimport { DatabaseError } from './database-error'\n\n/**\n * UniqueConstraintError\n *\n * Thrown when a database unique constraint is violated.\n * This typically occurs when trying to insert or update a record\n * with a value that already exists in a unique column.\n *\n * Services should catch this and optionally refine it to a more specific\n * domain error (e.g., UserEmailAlreadyExistsError).\n */\nexport class UniqueConstraintError extends DatabaseError {\n constructor(fields?: string[]) {\n super('errors.databaseUniqueConstraint', ERROR_CODES.DATABASE.UNIQUE_CONSTRAINT, {\n fields,\n })\n }\n}\n","import { ORMError, ORMErrorReason } from '@zenstackhq/orm'\nimport { ERROR_CODES } from 'stratal/errors'\nimport { DatabaseError } from './database-error'\nimport { ForeignKeyConstraintError } from './foreign-key-constraint.error'\nimport { RecordNotFoundError } from './record-not-found.error'\nimport { UniqueConstraintError } from './unique-constraint.error'\n\n/**\n * Transform ZenStack ORM errors into ApplicationError instances\n *\n * This function maps ORMError codes to generic database error classes.\n * Services can catch these generic errors and optionally refine them to\n * more specific domain errors if needed.\n *\n * @param error - The error thrown by ZenStack ORM\n * @returns An ApplicationError instance\n *\n * @example\n * ```typescript\n * try {\n * await db.user.create({ data: { email: 'existing@example.com' } })\n * } catch (error) {\n * throw fromZenStackError(error) // Becomes UniqueConstraintError or other\n * }\n * ```\n */\nexport function fromZenStackError(error: unknown): DatabaseError {\n // Handle ZenStack ORM Errors\n if (error instanceof ORMError) {\n const ormError = error\n\n switch (ormError.reason) {\n case ORMErrorReason.NOT_FOUND:\n return new RecordNotFoundError(ormError.model)\n\n case ORMErrorReason.DB_QUERY_ERROR:\n // Parse database-specific error codes\n return parseDatabaseError(ormError)\n\n case ORMErrorReason.INVALID_INPUT:\n return new DatabaseError(\n 'errors.databaseInvalidQuery',\n ERROR_CODES.DATABASE.GENERIC,\n { message: ormError.message }\n )\n\n case ORMErrorReason.CONFIG_ERROR:\n return new DatabaseError(\n 'errors.databaseConnectionFailed',\n ERROR_CODES.DATABASE.CONNECTION_FAILED,\n { message: ormError.message }\n )\n\n case ORMErrorReason.NOT_SUPPORTED:\n return new DatabaseError(\n 'errors.databaseGeneric',\n ERROR_CODES.DATABASE.GENERIC,\n { message: ormError.message, reason: 'Operation not supported' }\n )\n\n case ORMErrorReason.INTERNAL_ERROR:\n return new DatabaseError(\n 'errors.databaseGeneric',\n ERROR_CODES.DATABASE.GENERIC,\n { message: ormError.message }\n )\n\n default:\n return new DatabaseError(\n 'errors.databaseGeneric',\n ERROR_CODES.DATABASE.GENERIC,\n { message: ormError.message, reason: ormError.reason }\n )\n }\n }\n\n // Handle unknown errors\n return new DatabaseError(\n 'errors.databaseGeneric',\n ERROR_CODES.DATABASE.GENERIC,\n { originalError: String(error) }\n )\n}\n\n/**\n * Parse database-specific errors from the dbErrorCode field\n */\nfunction parseDatabaseError(error: ORMError): DatabaseError {\n // Cast dbErrorCode to string since ZenStack types it loosely\n const dbErrorCode = error.dbErrorCode as string | undefined\n\n // PostgreSQL error codes\n // https://www.postgresql.org/docs/current/errcodes-appendix.html\n if (dbErrorCode) {\n // Class 23 - Integrity Constraint Violation\n if (dbErrorCode === '23505') {\n // Unique violation\n return new UniqueConstraintError([error.model ?? 'unknown'])\n }\n\n if (dbErrorCode === '23503') {\n // Foreign key violation\n return new ForeignKeyConstraintError(error.model ?? 'unknown')\n }\n\n if (dbErrorCode === '23502') {\n // Not null violation\n return new DatabaseError(\n 'errors.databaseNullConstraint',\n ERROR_CODES.DATABASE.NULL_CONSTRAINT,\n { dbErrorCode, message: error.dbErrorMessage }\n )\n }\n\n if (dbErrorCode === '23514') {\n // Check constraint violation\n return new DatabaseError(\n 'errors.databaseConstraintFailed',\n ERROR_CODES.DATABASE.GENERIC,\n { dbErrorCode, message: error.dbErrorMessage }\n )\n }\n\n // Class 42 - Syntax Error or Access Rule Violation\n if (dbErrorCode.startsWith('42')) {\n if (dbErrorCode === '42P01') {\n // Undefined table\n return new DatabaseError(\n 'errors.databaseTableNotFound',\n ERROR_CODES.DATABASE.GENERIC,\n { dbErrorCode, message: error.dbErrorMessage }\n )\n }\n\n if (dbErrorCode === '42703') {\n // Undefined column\n return new DatabaseError(\n 'errors.databaseColumnNotFound',\n ERROR_CODES.DATABASE.GENERIC,\n { dbErrorCode, message: error.dbErrorMessage }\n )\n }\n }\n\n // Class 08 - Connection Exception\n if (dbErrorCode.startsWith('08')) {\n return new DatabaseError(\n 'errors.databaseConnectionFailed',\n ERROR_CODES.DATABASE.CONNECTION_FAILED,\n { dbErrorCode, message: error.dbErrorMessage }\n )\n }\n\n // Class 57 - Operator Intervention\n if (dbErrorCode === '57014') {\n // Query cancelled\n return new DatabaseError(\n 'errors.databaseTimeout',\n ERROR_CODES.DATABASE.TIMEOUT,\n { dbErrorCode, message: error.dbErrorMessage }\n )\n }\n\n // Class 40 - Transaction Rollback\n if (dbErrorCode.startsWith('40')) {\n return new DatabaseError(\n 'errors.databaseTransactionConflict',\n ERROR_CODES.DATABASE.TRANSACTION_CONFLICT,\n { dbErrorCode, message: error.dbErrorMessage }\n )\n }\n\n // Class 53 - Insufficient Resources\n if (dbErrorCode === '53300') {\n // Too many connections\n return new DatabaseError(\n 'errors.databaseTooManyConnections',\n ERROR_CODES.DATABASE.TOO_MANY_CONNECTIONS,\n { dbErrorCode, message: error.dbErrorMessage }\n )\n }\n }\n\n // Default database error\n return new DatabaseError(\n 'errors.databaseGeneric',\n ERROR_CODES.DATABASE.GENERIC,\n {\n dbErrorCode,\n dbErrorMessage: error.dbErrorMessage,\n sql: error.sql,\n }\n )\n}\n","import { type RuntimePlugin } from '@zenstackhq/orm'\nimport { type SchemaDef } from '@zenstackhq/orm/schema'\nimport { fromZenStackError } from '../errors'\n\n/**\n * ZenStack runtime plugin that transforms ORM errors into ApplicationError instances.\n *\n * @example\n * ```typescript\n * super(schema, {\n * dialect: new PostgresDialect({ pool }),\n * plugins: [new ErrorHandlerPlugin()]\n * })\n * ```\n */\nexport class ErrorHandlerPlugin implements RuntimePlugin<SchemaDef, Record<string, unknown>, Record<string, unknown>> {\n readonly id = 'error-handler'\n\n onQuery = async ({ args, proceed }: {\n args: Record<string, unknown> | undefined\n proceed: (args: Record<string, unknown> | undefined) => Promise<unknown>\n }): Promise<unknown> => {\n try {\n return await proceed(args)\n } catch (error) {\n throw fromZenStackError(error)\n }\n }\n}\n","import { type RuntimePlugin } from '@zenstackhq/orm'\nimport { type SchemaDef } from '@zenstackhq/orm/schema'\nimport type { EventName, IEventRegistry } from 'stratal/events'\n\nexport interface EventEmitterPluginOptions {\n eventRegistry: IEventRegistry\n}\n\n/**\n * ZenStack runtime plugin that emits before/after events for database operations.\n *\n * Emits events in the format:\n * - `before.{Model}.{operation}` - Before the database operation\n * - `after.{Model}.{operation}` - After the database operation\n *\n * @example\n * ```typescript\n * super(schema, {\n * dialect: new PostgresDialect({ pool }),\n * plugins: [\n * new EventEmitterPlugin({\n * eventRegistry,\n * })\n * ]\n * })\n * ```\n */\nexport class EventEmitterPlugin implements RuntimePlugin<SchemaDef, Record<string, unknown>, Record<string, unknown>> {\n readonly id = 'event-emitter'\n\n constructor(private options: EventEmitterPluginOptions) { }\n\n onQuery = async ({ model, operation, args, proceed }: {\n model: string\n operation: string\n args: Record<string, unknown> | undefined\n proceed: (args: Record<string, unknown> | undefined) => Promise<unknown>\n }): Promise<unknown> => {\n const { eventRegistry } = this.options\n const eventBase = `${model}.${operation}`\n\n // Emit BEFORE event\n await eventRegistry.emit(`before.${eventBase}` as EventName, {\n data: args,\n })\n\n // Execute the actual database operation\n const result = await proceed(args)\n\n // Emit AFTER event\n await eventRegistry.emit(`after.${eventBase}` as EventName, {\n data: args,\n result,\n })\n\n return result\n }\n}\n","import { type RuntimePlugin } from \"@zenstackhq/orm\"\nimport { type SchemaDef } from \"@zenstackhq/orm/schema\"\n\nexport interface SchemaSwitcherPluginOptions {\n schemaName: string\n}\n\n/**\n * ZenStack runtime plugin that sets PostgreSQL search_path before each query.\n * Used for tenant isolation in multi-tenant applications.\n *\n * @example\n * ```typescript\n * super(schema, {\n * dialect: new PostgresDialect({ pool }),\n * plugins: [\n * new SchemaSwitcherPlugin({ schemaName: `tenant_${tenantId}` })\n * ]\n * })\n * ```\n */\nexport class SchemaSwitcherPlugin implements RuntimePlugin<SchemaDef, Record<string, unknown>, Record<string, unknown>> {\n readonly id = 'schema-switcher'\n\n constructor(private options: SchemaSwitcherPluginOptions) { }\n\n onQuery = async ({ args, proceed, client }: {\n args: Record<string, unknown> | undefined\n proceed: (args: Record<string, unknown> | undefined) => Promise<unknown>\n client: { $executeRawUnsafe: (sql: string) => Promise<unknown> }\n }): Promise<unknown> => {\n // Set search_path before each query\n await client.$executeRawUnsafe(`SET search_path TO \"${this.options.schemaName}\"`)\n return proceed(args)\n }\n}\n","import { ZenStackClient, type AnyPlugin } from '@zenstackhq/orm'\nimport { Transient } from 'stratal/di'\nimport type { IEventRegistry } from 'stratal/events'\nimport { withI18n, z } from 'stratal/validation'\nimport type { DatabaseConnectionConfig } from './database.module'\nimport { ErrorHandlerPlugin, EventEmitterPlugin } from './plugins'\n\nconst databaseConnectionSchema = z.object({\n name: z.string().min(1, withI18n('database.connectionNameRequired')),\n schema: z.object({}).loose(),\n dialect: z.function(),\n plugins: z.array(z.object({}).loose()).optional(),\n})\n\nexport const databaseModuleConfigSchema = z.object({\n default: z.string().min(1, withI18n('database.defaultConnectionRequired')),\n connections: z.array(databaseConnectionSchema).min(1, withI18n('database.connectionRequired')),\n}).refine(\n (config) => {\n const names = config.connections.map(c => c.name)\n return new Set(names).size === names.length\n },\n withI18n('database.duplicateConnections')\n).refine(\n (config) => config.connections.some(c => c.name === config.default),\n withI18n('database.defaultConnectionNotFound')\n)\n\nexport function createDatabaseService(\n conn: DatabaseConnectionConfig,\n eventRegistry: IEventRegistry,\n): new () => InstanceType<typeof ZenStackClient> {\n const plugins: AnyPlugin[] = [\n new ErrorHandlerPlugin(),\n new EventEmitterPlugin({\n eventRegistry,\n }),\n ...(conn.plugins ?? []),\n ]\n\n @Transient()\n class DatabaseClient extends ZenStackClient<typeof conn.schema> {\n constructor() {\n const dialect = conn.dialect()\n super(conn.schema, { dialect, plugins })\n }\n }\n\n return DatabaseClient\n}\n","export const DATABASE_TOKENS = {\n Options: Symbol.for('stratal:database:options'),\n Services: Symbol.for('stratal:database:services'),\n} as const\n\nimport type { ConnectionName } from './types'\n\nexport function connectionSymbol(name: ConnectionName): symbol {\n return Symbol.for(`stratal:database:connection:${name}`)\n}\n","import type { AnyPlugin } from '@zenstackhq/orm'\nimport type { SchemaDef } from '@zenstackhq/schema'\nimport type { Dialect } from 'kysely'\nimport { DI_TOKENS, Scope, delay } from 'stratal/di'\nimport type { IEventRegistry } from 'stratal/events'\nimport {\n InjectionToken,\n Module,\n type AsyncModuleOptions,\n type DynamicModule,\n type ModuleContext,\n type OnInitialize,\n type OnShutdown,\n} from 'stratal/module'\nimport { DbGenerateCommand } from './commands/db-generate.command'\nimport { DbPullCommand } from './commands/db-pull.command'\nimport { DbPushCommand } from './commands/db-push.command'\nimport { MigrateDeployCommand } from './commands/migrate-deploy.command'\nimport { MigrateDevCommand } from './commands/migrate-dev.command'\nimport { MigrateResetCommand } from './commands/migrate-reset.command'\nimport { MigrateStatusCommand } from './commands/migrate-status.command'\nimport { createDatabaseService } from './database.helpers'\nimport { DATABASE_TOKENS, connectionSymbol } from './database.tokens'\nimport type { ConnectionName, DefaultConnectionName } from './types'\n\nexport interface DatabaseConnectionConfig<\n Schema extends SchemaDef = SchemaDef,\n Name extends ConnectionName = ConnectionName,\n> {\n name: Name\n schema: Schema\n dialect: () => Dialect\n plugins?: AnyPlugin[]\n}\n\nexport interface DatabaseModuleConfig {\n default: DefaultConnectionName\n connections: DatabaseConnectionConfig[]\n}\n\n@Module({\n providers: [\n DbGenerateCommand,\n DbPushCommand,\n DbPullCommand,\n MigrateDevCommand,\n MigrateDeployCommand,\n MigrateStatusCommand,\n MigrateResetCommand,\n ],\n})\nexport class DatabaseModule implements OnInitialize, OnShutdown {\n static forRoot(config: DatabaseModuleConfig): DynamicModule {\n return {\n module: DatabaseModule,\n providers: [\n { provide: DATABASE_TOKENS.Options, useValue: config as unknown as object },\n ],\n }\n }\n\n static forRootAsync(options: AsyncModuleOptions<DatabaseModuleConfig>): DynamicModule {\n return {\n module: DatabaseModule,\n providers: [\n {\n provide: DATABASE_TOKENS.Options,\n useFactory: options.useFactory,\n inject: options.inject,\n },\n ],\n }\n }\n\n onInitialize(context: ModuleContext): void {\n const config = context.container.resolve<DatabaseModuleConfig>(DATABASE_TOKENS.Options)\n const eventRegistry = context.container.resolve<IEventRegistry>(DI_TOKENS.EventRegistry)\n const container = context.container.getTsyringeContainer();\n\n for (const conn of config.connections) {\n const Service = createDatabaseService(conn, eventRegistry)\n\n container.register(connectionSymbol(conn.name) as InjectionToken<symbol>,\n // @ts-expect-error Overload error\n delay(() => Service),\n { lifecycle: Scope.Request })\n }\n\n context.container.registerExisting(DI_TOKENS.Database, connectionSymbol(config.default))\n\n context.logger.info('DatabaseModule initialized')\n }\n\n onShutdown(context: ModuleContext): void {\n context.logger.info('DatabaseModule shutdown')\n }\n}\n","import { inject } from 'tsyringe'\nimport type { ConnectionName } from '../types'\nimport { connectionSymbol } from '../database.tokens'\n\nexport function InjectDB(name: ConnectionName): ParameterDecorator {\n return inject(connectionSymbol(name))\n}\n","export const databaseI18n = {\n database: {\n connectionNameRequired: 'Connection name is required',\n defaultConnectionRequired: 'Default connection name is required',\n connectionRequired: 'At least one connection is required',\n duplicateConnections: 'Duplicate connection names found',\n defaultConnectionNotFound: 'Default connection not found in connections',\n },\n} as const\n\ndeclare module 'stratal/i18n' {\n interface AppMessages {\n database: typeof databaseI18n['database']\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/database/commands/zenstack.command.ts","../../src/database/commands/db-generate.command.ts","../../src/database/commands/db-pull.command.ts","../../src/database/commands/db-push.command.ts","../../src/database/commands/migrate-deploy.command.ts","../../src/database/commands/migrate-dev.command.ts","../../src/database/commands/migrate-reset.command.ts","../../src/database/commands/migrate-status.command.ts","../../src/database/errors/invalid-error-code-range.error.ts","../../src/database/errors/database-error.ts","../../src/database/errors/database-config.error.ts","../../src/database/errors/foreign-key-constraint.error.ts","../../src/database/errors/record-not-found.error.ts","../../src/database/errors/unique-constraint.error.ts","../../src/database/errors/from-zenstack-error.ts","../../src/database/plugins/error-handler.plugin.ts","../../src/database/plugins/event-emitter.plugin.ts","../../src/database/plugins/schema-switcher.plugin.ts","../../src/database/database.helpers.ts","../../src/database/database.tokens.ts","../../src/database/database.module.ts","../../src/database/decorators/inject-db.decorator.ts","../../src/database/i18n/en.ts"],"sourcesContent":["import { Command } from 'stratal/quarry'\n\n/**\n * Base command for ZenStack CLI wrappers.\n * Uses execFileSync with array arguments to prevent shell injection.\n */\nexport abstract class ZenStackCommand extends Command {\n protected async zenstack(args: string[]): Promise<number> {\n // Dynamic import — node:child_process is only available in the Quarry CLI (Node) context\n const { execFileSync } = await import('node:child_process')\n\n try {\n const output = execFileSync('npx', ['zenstack', ...args], {\n encoding: 'utf-8',\n stdio: 'pipe',\n })\n if (output) this.info(output.trim())\n return 0\n } catch (err) {\n const error = err as { stderr?: string; stdout?: string; status?: number }\n if (error.stderr) this.error(error.stderr.trim())\n if (error.stdout) this.info(error.stdout.trim())\n return error.status ?? 1\n }\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class DbGenerateCommand extends ZenStackCommand {\n static command = 'db:generate {--schema= : Path to schema file} {--watch : Enable watch mode}'\n static description = 'Generate ZenStack ORM client'\n\n async handle(): Promise<number> {\n const args = ['generate']\n const schema = this.string('schema')\n\n if (schema) args.push('--schema', schema)\n if (this.boolean('watch')) args.push('--watch')\n\n return this.zenstack(args)\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class DbPullCommand extends ZenStackCommand {\n static command = 'db:pull {--schema= : Path to schema file}'\n static description = 'Introspect database and generate schema'\n\n async handle(): Promise<number> {\n const args = ['db', 'pull']\n const schema = this.string('schema')\n\n if (schema) args.push('--schema', schema)\n\n return this.zenstack(args)\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class DbPushCommand extends ZenStackCommand {\n static command = 'db:push {--schema= : Path to schema file} {--accept-data-loss : Accept data loss} {--force-reset : Force reset database}'\n static description = 'Push database schema changes'\n\n async handle(): Promise<number> {\n const args = ['db', 'push']\n const schema = this.string('schema')\n\n if (schema) args.push('--schema', schema)\n if (this.boolean('accept-data-loss')) args.push('--accept-data-loss')\n if (this.boolean('force-reset')) args.push('--force-reset')\n\n return this.zenstack(args)\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class MigrateDeployCommand extends ZenStackCommand {\n static command = 'migrate:deploy {--schema= : Path to schema file}'\n static description = 'Deploy pending migrations'\n\n async handle(): Promise<number> {\n const args = ['migrate', 'deploy']\n const schema = this.string('schema')\n\n if (schema) args.push('--schema', schema)\n\n return this.zenstack(args)\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class MigrateDevCommand extends ZenStackCommand {\n static command = 'migrate:dev {--schema= : Path to schema file} {--name= : Migration name} {--create-only : Create without applying}'\n static description = 'Create and apply migration'\n\n async handle(): Promise<number> {\n const args = ['migrate', 'dev']\n const schema = this.string('schema')\n const name = this.string('name')\n\n if (schema) args.push('--schema', schema)\n if (name) args.push('--name', name)\n if (this.boolean('create-only')) args.push('--create-only')\n\n return this.zenstack(args)\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class MigrateResetCommand extends ZenStackCommand {\n static command = 'migrate:reset {--schema= : Path to schema file} {--force : Skip confirmation} {--skip-seed : Skip seeding}'\n static description = 'Reset database'\n\n async handle(): Promise<number> {\n const args = ['migrate', 'reset']\n const schema = this.string('schema')\n\n if (schema) args.push('--schema', schema)\n if (this.boolean('force')) args.push('--force')\n if (this.boolean('skip-seed')) args.push('--skip-seed')\n\n return this.zenstack(args)\n }\n}\n","import { ZenStackCommand } from './zenstack.command'\n\nexport class MigrateStatusCommand extends ZenStackCommand {\n static command = 'migrate:status {--schema= : Path to schema file}'\n static description = 'Check migration status'\n\n async handle(): Promise<number> {\n const args = ['migrate', 'status']\n const schema = this.string('schema')\n\n if (schema) args.push('--schema', schema)\n\n return this.zenstack(args)\n }\n}\n","import { ApplicationError, ERROR_CODES } from 'stratal/errors'\n\n/**\n * InvalidErrorCodeRangeError\n *\n * Thrown when a DatabaseError subclass is constructed with an error code\n * outside the valid database error range (2000-2999).\n * This is a developer-facing error to enforce error code conventions.\n */\nexport class InvalidErrorCodeRangeError extends ApplicationError {\n constructor(code: number, expectedRange: string) {\n super(\n 'errors.invalidErrorCodeRange',\n ERROR_CODES.SYSTEM.INVALID_ERROR_CODE_RANGE,\n { code, expectedRange }\n )\n }\n}\n","import type { MessageKeys } from 'stratal/i18n'\nimport { ApplicationError, ERROR_CODES, type ErrorCode } from 'stratal/errors'\nimport { InvalidErrorCodeRangeError } from './invalid-error-code-range.error'\n\n/**\n * DatabaseError\n *\n * Generic database error thrown when a database operation fails\n * and doesn't fit into a more specific error category.\n *\n * This is the base class for all database-related errors.\n */\nexport class DatabaseError extends ApplicationError {\n constructor(\n messageKey: MessageKeys = 'errors.databaseGeneric',\n code: ErrorCode = ERROR_CODES.DATABASE.GENERIC,\n metadata?: Record<string, unknown>\n ) {\n // Validate that code is in the database error range\n if (code < 2000 || code >= 3000) {\n throw new InvalidErrorCodeRangeError(code, '2000-2999')\n }\n\n super(messageKey, code, metadata)\n }\n}\n","import { ERROR_CODES } from 'stratal/errors'\nimport { DatabaseError } from './database-error'\n\nexport class DatabaseConfigError extends DatabaseError {\n constructor(details: string) {\n super('errors.databaseGeneric', ERROR_CODES.DATABASE.GENERIC, { details })\n }\n}\n","import { ERROR_CODES } from 'stratal/errors'\nimport { DatabaseError } from './database-error'\n\n/**\n * ForeignKeyConstraintError\n *\n * Thrown when a database foreign key constraint is violated.\n * This typically occurs when:\n * - Trying to insert a record with a foreign key that doesn't exist\n * - Trying to delete a record that is referenced by other records\n * - Trying to update a foreign key to a non-existent value\n */\nexport class ForeignKeyConstraintError extends DatabaseError {\n constructor(field?: string) {\n super('errors.databaseForeignKeyConstraint', ERROR_CODES.DATABASE.FOREIGN_KEY_CONSTRAINT, {\n field,\n })\n }\n}\n","import { ERROR_CODES } from 'stratal/errors'\nimport { DatabaseError } from './database-error'\n\n/**\n * RecordNotFoundError\n *\n * Generic error thrown when a database record is not found.\n * This is typically thrown when a findUnique or findFirst operation\n * returns null, or when a required record doesn't exist.\n *\n * Services should catch this and optionally refine it to a more specific\n * domain error (e.g., NoteNotFoundError, UserNotFoundError).\n */\nexport class RecordNotFoundError extends DatabaseError {\n constructor(details?: string) {\n super('errors.databaseRecordNotFound', ERROR_CODES.DATABASE.RECORD_NOT_FOUND, {\n details,\n })\n }\n}\n","import { ERROR_CODES } from 'stratal/errors'\nimport { DatabaseError } from './database-error'\n\n/**\n * UniqueConstraintError\n *\n * Thrown when a database unique constraint is violated.\n * This typically occurs when trying to insert or update a record\n * with a value that already exists in a unique column.\n *\n * Services should catch this and optionally refine it to a more specific\n * domain error (e.g., UserEmailAlreadyExistsError).\n */\nexport class UniqueConstraintError extends DatabaseError {\n constructor(fields?: string[]) {\n super('errors.databaseUniqueConstraint', ERROR_CODES.DATABASE.UNIQUE_CONSTRAINT, {\n fields,\n })\n }\n}\n","import { ORMError, ORMErrorReason } from '@zenstackhq/orm'\nimport { ERROR_CODES } from 'stratal/errors'\nimport { DatabaseError } from './database-error'\nimport { ForeignKeyConstraintError } from './foreign-key-constraint.error'\nimport { RecordNotFoundError } from './record-not-found.error'\nimport { UniqueConstraintError } from './unique-constraint.error'\n\n/**\n * Transform ZenStack ORM errors into ApplicationError instances\n *\n * This function maps ORMError codes to generic database error classes.\n * Services can catch these generic errors and optionally refine them to\n * more specific domain errors if needed.\n *\n * @param error - The error thrown by ZenStack ORM\n * @returns An ApplicationError instance\n *\n * @example\n * ```typescript\n * try {\n * await db.user.create({ data: { email: 'existing@example.com' } })\n * } catch (error) {\n * throw fromZenStackError(error) // Becomes UniqueConstraintError or other\n * }\n * ```\n */\nexport function fromZenStackError(error: unknown): DatabaseError {\n // Handle ZenStack ORM Errors\n if (error instanceof ORMError) {\n const ormError = error\n\n switch (ormError.reason) {\n case ORMErrorReason.NOT_FOUND:\n return new RecordNotFoundError(ormError.model)\n\n case ORMErrorReason.DB_QUERY_ERROR:\n // Parse database-specific error codes\n return parseDatabaseError(ormError)\n\n case ORMErrorReason.INVALID_INPUT:\n return new DatabaseError(\n 'errors.databaseInvalidQuery',\n ERROR_CODES.DATABASE.GENERIC,\n { message: ormError.message }\n )\n\n case ORMErrorReason.CONFIG_ERROR:\n return new DatabaseError(\n 'errors.databaseConnectionFailed',\n ERROR_CODES.DATABASE.CONNECTION_FAILED,\n { message: ormError.message }\n )\n\n case ORMErrorReason.NOT_SUPPORTED:\n return new DatabaseError(\n 'errors.databaseGeneric',\n ERROR_CODES.DATABASE.GENERIC,\n { message: ormError.message, reason: 'Operation not supported' }\n )\n\n case ORMErrorReason.INTERNAL_ERROR:\n return new DatabaseError(\n 'errors.databaseGeneric',\n ERROR_CODES.DATABASE.GENERIC,\n { message: ormError.message }\n )\n\n default:\n return new DatabaseError(\n 'errors.databaseGeneric',\n ERROR_CODES.DATABASE.GENERIC,\n { message: ormError.message, reason: ormError.reason }\n )\n }\n }\n\n // Handle unknown errors\n return new DatabaseError(\n 'errors.databaseGeneric',\n ERROR_CODES.DATABASE.GENERIC,\n { originalError: String(error) }\n )\n}\n\n/**\n * Parse database-specific errors from the dbErrorCode field\n */\nfunction parseDatabaseError(error: ORMError): DatabaseError {\n // Cast dbErrorCode to string since ZenStack types it loosely\n const dbErrorCode = error.dbErrorCode as string | undefined\n\n // PostgreSQL error codes\n // https://www.postgresql.org/docs/current/errcodes-appendix.html\n if (dbErrorCode) {\n // Class 23 - Integrity Constraint Violation\n if (dbErrorCode === '23505') {\n // Unique violation\n return new UniqueConstraintError([error.model ?? 'unknown'])\n }\n\n if (dbErrorCode === '23503') {\n // Foreign key violation\n return new ForeignKeyConstraintError(error.model ?? 'unknown')\n }\n\n if (dbErrorCode === '23502') {\n // Not null violation\n return new DatabaseError(\n 'errors.databaseNullConstraint',\n ERROR_CODES.DATABASE.NULL_CONSTRAINT,\n { dbErrorCode, message: error.dbErrorMessage }\n )\n }\n\n if (dbErrorCode === '23514') {\n // Check constraint violation\n return new DatabaseError(\n 'errors.databaseConstraintFailed',\n ERROR_CODES.DATABASE.GENERIC,\n { dbErrorCode, message: error.dbErrorMessage }\n )\n }\n\n // Class 42 - Syntax Error or Access Rule Violation\n if (dbErrorCode.startsWith('42')) {\n if (dbErrorCode === '42P01') {\n // Undefined table\n return new DatabaseError(\n 'errors.databaseTableNotFound',\n ERROR_CODES.DATABASE.GENERIC,\n { dbErrorCode, message: error.dbErrorMessage }\n )\n }\n\n if (dbErrorCode === '42703') {\n // Undefined column\n return new DatabaseError(\n 'errors.databaseColumnNotFound',\n ERROR_CODES.DATABASE.GENERIC,\n { dbErrorCode, message: error.dbErrorMessage }\n )\n }\n }\n\n // Class 08 - Connection Exception\n if (dbErrorCode.startsWith('08')) {\n return new DatabaseError(\n 'errors.databaseConnectionFailed',\n ERROR_CODES.DATABASE.CONNECTION_FAILED,\n { dbErrorCode, message: error.dbErrorMessage }\n )\n }\n\n // Class 57 - Operator Intervention\n if (dbErrorCode === '57014') {\n // Query cancelled\n return new DatabaseError(\n 'errors.databaseTimeout',\n ERROR_CODES.DATABASE.TIMEOUT,\n { dbErrorCode, message: error.dbErrorMessage }\n )\n }\n\n // Class 40 - Transaction Rollback\n if (dbErrorCode.startsWith('40')) {\n return new DatabaseError(\n 'errors.databaseTransactionConflict',\n ERROR_CODES.DATABASE.TRANSACTION_CONFLICT,\n { dbErrorCode, message: error.dbErrorMessage }\n )\n }\n\n // Class 53 - Insufficient Resources\n if (dbErrorCode === '53300') {\n // Too many connections\n return new DatabaseError(\n 'errors.databaseTooManyConnections',\n ERROR_CODES.DATABASE.TOO_MANY_CONNECTIONS,\n { dbErrorCode, message: error.dbErrorMessage }\n )\n }\n }\n\n // Default database error\n return new DatabaseError(\n 'errors.databaseGeneric',\n ERROR_CODES.DATABASE.GENERIC,\n {\n dbErrorCode,\n dbErrorMessage: error.dbErrorMessage,\n sql: error.sql,\n }\n )\n}\n","import { type RuntimePlugin } from '@zenstackhq/orm'\nimport { type SchemaDef } from '@zenstackhq/orm/schema'\nimport { fromZenStackError } from '../errors'\n\n/**\n * ZenStack runtime plugin that transforms ORM errors into ApplicationError instances.\n *\n * @example\n * ```typescript\n * super(schema, {\n * dialect: new PostgresDialect({ pool }),\n * plugins: [new ErrorHandlerPlugin()]\n * })\n * ```\n */\nexport class ErrorHandlerPlugin implements RuntimePlugin<SchemaDef, Record<string, unknown>, Record<string, unknown>, {}> {\n readonly id = 'error-handler'\n\n onQuery = async ({ args, proceed }: {\n args: Record<string, unknown> | undefined\n proceed: (args: Record<string, unknown> | undefined) => Promise<unknown>\n }): Promise<unknown> => {\n try {\n return await proceed(args)\n } catch (error) {\n throw fromZenStackError(error)\n }\n }\n}\n","import { type RuntimePlugin } from '@zenstackhq/orm'\nimport { type SchemaDef } from '@zenstackhq/orm/schema'\nimport type { EventName, IEventRegistry } from 'stratal/events'\n\nexport interface EventEmitterPluginOptions {\n eventRegistry: IEventRegistry\n}\n\n/**\n * ZenStack runtime plugin that emits before/after events for database operations.\n *\n * Emits events in the format:\n * - `before.{Model}.{operation}` - Before the database operation\n * - `after.{Model}.{operation}` - After the database operation\n *\n * @example\n * ```typescript\n * super(schema, {\n * dialect: new PostgresDialect({ pool }),\n * plugins: [\n * new EventEmitterPlugin({\n * eventRegistry,\n * })\n * ]\n * })\n * ```\n */\nexport class EventEmitterPlugin implements RuntimePlugin<SchemaDef, Record<string, unknown>, Record<string, unknown>, {}> {\n readonly id = 'event-emitter'\n\n constructor(private options: EventEmitterPluginOptions) { }\n\n onQuery = async ({ model, operation, args, proceed }: {\n model: string\n operation: string\n args: Record<string, unknown> | undefined\n proceed: (args: Record<string, unknown> | undefined) => Promise<unknown>\n }): Promise<unknown> => {\n const { eventRegistry } = this.options\n const eventBase = `${model}.${operation}`\n\n // Emit BEFORE event\n await eventRegistry.emit(`before.${eventBase}` as EventName, {\n data: args,\n })\n\n // Execute the actual database operation\n const result = await proceed(args)\n\n // Emit AFTER event\n await eventRegistry.emit(`after.${eventBase}` as EventName, {\n data: args,\n result,\n })\n\n return result\n }\n}\n","import { type RuntimePlugin } from \"@zenstackhq/orm\"\nimport { type SchemaDef } from \"@zenstackhq/orm/schema\"\n\nexport interface SchemaSwitcherPluginOptions {\n schemaName: string\n}\n\n/**\n * ZenStack runtime plugin that sets PostgreSQL search_path before each query.\n * Used for tenant isolation in multi-tenant applications.\n *\n * @example\n * ```typescript\n * super(schema, {\n * dialect: new PostgresDialect({ pool }),\n * plugins: [\n * new SchemaSwitcherPlugin({ schemaName: `tenant_${tenantId}` })\n * ]\n * })\n * ```\n */\nexport class SchemaSwitcherPlugin implements RuntimePlugin<SchemaDef, Record<string, unknown>, Record<string, unknown>, {}> {\n readonly id = 'schema-switcher'\n\n constructor(private options: SchemaSwitcherPluginOptions) { }\n\n onQuery = async ({ args, proceed, client }: {\n args: Record<string, unknown> | undefined\n proceed: (args: Record<string, unknown> | undefined) => Promise<unknown>\n client: { $executeRawUnsafe: (sql: string) => Promise<unknown> }\n }): Promise<unknown> => {\n // Set search_path before each query\n await client.$executeRawUnsafe(`SET search_path TO \"${this.options.schemaName}\"`)\n return proceed(args)\n }\n}\n","import { ZenStackClient, type AnyPlugin } from '@zenstackhq/orm'\nimport { Transient } from 'stratal/di'\nimport type { IEventRegistry } from 'stratal/events'\nimport { withI18n, z } from 'stratal/validation'\nimport type { DatabaseConnectionConfig } from './database.module'\nimport { ErrorHandlerPlugin, EventEmitterPlugin } from './plugins'\n\nconst databaseConnectionSchema = z.object({\n name: z.string().min(1, withI18n('database.connectionNameRequired')),\n schema: z.object({}).loose(),\n dialect: z.function(),\n plugins: z.array(z.object({}).loose()).optional(),\n})\n\nexport const databaseModuleConfigSchema = z.object({\n default: z.string().min(1, withI18n('database.defaultConnectionRequired')),\n connections: z.array(databaseConnectionSchema).min(1, withI18n('database.connectionRequired')),\n}).refine(\n (config) => {\n const names = config.connections.map(c => c.name)\n return new Set(names).size === names.length\n },\n withI18n('database.duplicateConnections')\n).refine(\n (config) => config.connections.some(c => c.name === config.default),\n withI18n('database.defaultConnectionNotFound')\n)\n\nexport function createDatabaseService(\n conn: DatabaseConnectionConfig,\n eventRegistry: IEventRegistry,\n): new () => InstanceType<typeof ZenStackClient> {\n const plugins: AnyPlugin[] = [\n new ErrorHandlerPlugin(),\n new EventEmitterPlugin({\n eventRegistry,\n }),\n ...(conn.plugins ?? []),\n ]\n\n @Transient()\n class DatabaseClient extends ZenStackClient<typeof conn.schema> {\n constructor() {\n const dialect = conn.dialect()\n super(conn.schema, { dialect, plugins })\n }\n }\n\n return DatabaseClient\n}\n","export const DATABASE_TOKENS = {\n Options: Symbol.for('stratal:database:options'),\n Services: Symbol.for('stratal:database:services'),\n} as const\n\nimport type { ConnectionName } from './types'\n\nexport function connectionSymbol(name: ConnectionName): symbol {\n return Symbol.for(`stratal:database:connection:${name}`)\n}\n","import type { AnyPlugin, ClientOptions } from '@zenstackhq/orm'\nimport type { SchemaDef } from '@zenstackhq/schema'\nimport { DI_TOKENS, Scope, delay } from 'stratal/di'\nimport type { IEventRegistry } from 'stratal/events'\nimport {\n Module,\n type AsyncModuleOptions,\n type DynamicModule,\n type InjectionToken,\n type ModuleContext,\n type OnInitialize,\n type OnShutdown,\n} from 'stratal/module'\nimport { DbGenerateCommand } from './commands/db-generate.command'\nimport { DbPullCommand } from './commands/db-pull.command'\nimport { DbPushCommand } from './commands/db-push.command'\nimport { MigrateDeployCommand } from './commands/migrate-deploy.command'\nimport { MigrateDevCommand } from './commands/migrate-dev.command'\nimport { MigrateResetCommand } from './commands/migrate-reset.command'\nimport { MigrateStatusCommand } from './commands/migrate-status.command'\nimport { createDatabaseService } from './database.helpers'\nimport { DATABASE_TOKENS, connectionSymbol } from './database.tokens'\nimport type { ConnectionName, DefaultConnectionName } from './types'\n\nexport interface DatabaseConnectionConfig<\n Schema extends SchemaDef = SchemaDef,\n Name extends ConnectionName = ConnectionName,\n> {\n name: Name\n schema: Schema\n dialect: () => ClientOptions<SchemaDef>['dialect']\n plugins?: AnyPlugin[]\n}\n\nexport interface DatabaseModuleConfig {\n default: DefaultConnectionName\n connections: DatabaseConnectionConfig[]\n}\n\n@Module({\n providers: [\n DbGenerateCommand,\n DbPushCommand,\n DbPullCommand,\n MigrateDevCommand,\n MigrateDeployCommand,\n MigrateStatusCommand,\n MigrateResetCommand,\n ],\n})\nexport class DatabaseModule implements OnInitialize, OnShutdown {\n static forRoot(config: DatabaseModuleConfig): DynamicModule {\n return {\n module: DatabaseModule,\n providers: [\n { provide: DATABASE_TOKENS.Options, useValue: config as unknown as object },\n ],\n }\n }\n\n static forRootAsync(options: AsyncModuleOptions<DatabaseModuleConfig>): DynamicModule {\n return {\n module: DatabaseModule,\n providers: [\n {\n provide: DATABASE_TOKENS.Options,\n useFactory: options.useFactory,\n inject: options.inject,\n },\n ],\n }\n }\n\n onInitialize(context: ModuleContext): void {\n const config = context.container.resolve<DatabaseModuleConfig>(DATABASE_TOKENS.Options)\n const eventRegistry = context.container.resolve<IEventRegistry>(DI_TOKENS.EventRegistry)\n const container = context.container.getTsyringeContainer();\n\n for (const conn of config.connections) {\n const Service = createDatabaseService(conn, eventRegistry)\n\n container.register(connectionSymbol(conn.name) as InjectionToken<symbol>,\n // @ts-expect-error Overload error\n delay(() => Service),\n { lifecycle: Scope.Request })\n }\n\n context.container.registerExisting(DI_TOKENS.Database, connectionSymbol(config.default))\n\n context.logger.info('DatabaseModule initialized')\n }\n\n onShutdown(context: ModuleContext): void {\n context.logger.info('DatabaseModule shutdown')\n }\n}\n","import { inject } from 'tsyringe'\nimport type { ConnectionName } from '../types'\nimport { connectionSymbol } from '../database.tokens'\n\nexport function InjectDB(name: ConnectionName): ParameterDecorator {\n return inject(connectionSymbol(name))\n}\n","export const databaseI18n = {\n database: {\n connectionNameRequired: 'Connection name is required',\n defaultConnectionRequired: 'Default connection name is required',\n connectionRequired: 'At least one connection is required',\n duplicateConnections: 'Duplicate connection names found',\n defaultConnectionNotFound: 'Default connection not found in connections',\n },\n} as const\n\ndeclare module 'stratal/i18n' {\n interface AppMessages {\n database: typeof databaseI18n['database']\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region \0@oxc-project+runtime@0.
|
|
1
|
+
//#region \0@oxc-project+runtime@0.122.0/helpers/decorate.js
|
|
2
2
|
function __decorate(decorators, target, key, desc) {
|
|
3
3
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
4
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region \0@oxc-project+runtime@0.
|
|
1
|
+
//#region \0@oxc-project+runtime@0.122.0/helpers/decorateMetadata.js
|
|
2
2
|
function __decorateMetadata(k, v) {
|
|
3
3
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
4
4
|
}
|
package/dist/factory/index.d.mts
CHANGED
package/dist/guards/index.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { n as UserNotAuthenticatedError } from "../errors-C_KIIU1v.mjs";
|
|
2
|
-
import { t as __decorate } from "../decorate-
|
|
3
|
-
import { t as __decorateMetadata } from "../decorateMetadata-
|
|
4
|
-
import { t as __decorateParam } from "../decorateParam-
|
|
2
|
+
import { t as __decorate } from "../decorate-C12QolJF.mjs";
|
|
3
|
+
import { t as __decorateMetadata } from "../decorateMetadata-rWbWGUuO.mjs";
|
|
4
|
+
import { t as __decorateParam } from "../decorateParam-WGqsyT5s.mjs";
|
|
5
5
|
import { n as InsufficientPermissionsError, t as RBAC_TOKENS } from "../tokens-Di1ofovy.mjs";
|
|
6
6
|
import { DI_TOKENS, Transient } from "stratal/di";
|
|
7
|
+
import { LOGGER_TOKENS } from "stratal/logger";
|
|
7
8
|
import { inject } from "tsyringe";
|
|
8
9
|
import { GUARD_METADATA_KEY, GuardExecutionService, UseGuards, getControllerGuards, getMethodGuards } from "stratal/guards";
|
|
9
|
-
import { LOGGER_TOKENS } from "stratal/logger";
|
|
10
10
|
//#region src/guards/auth.guard.ts
|
|
11
11
|
/**
|
|
12
12
|
* AuthGuard Factory
|
|
@@ -4,7 +4,6 @@ import { ApplicationError, ErrorCode } from "stratal/errors";
|
|
|
4
4
|
import { Command } from "stratal/quarry";
|
|
5
5
|
import { AggregateArgs, AllCrudOperations, AnyPlugin, ClientContract, ClientOptions, CountArgs, CreateArgs, CreateManyArgs, DeleteArgs, DeleteManyArgs, FindFirstArgs, FindManyArgs, FindUniqueArgs, GroupByArgs, ModelResult, RuntimePlugin, UpdateArgs, UpdateManyArgs, UpsertArgs } from "@zenstackhq/orm";
|
|
6
6
|
import { SchemaDef } from "@zenstackhq/schema";
|
|
7
|
-
import { Dialect } from "kysely";
|
|
8
7
|
import { MessageKeys } from "stratal/i18n";
|
|
9
8
|
import { SchemaDef as SchemaDef$1 } from "@zenstackhq/orm/schema";
|
|
10
9
|
import { IEventRegistry } from "stratal/events";
|
|
@@ -13,7 +12,7 @@ import { IEventRegistry } from "stratal/events";
|
|
|
13
12
|
interface DatabaseConnectionConfig<Schema extends SchemaDef = SchemaDef, Name extends ConnectionName = ConnectionName> {
|
|
14
13
|
name: Name;
|
|
15
14
|
schema: Schema;
|
|
16
|
-
dialect: () =>
|
|
15
|
+
dialect: () => ClientOptions<SchemaDef>['dialect'];
|
|
17
16
|
plugins?: AnyPlugin[];
|
|
18
17
|
}
|
|
19
18
|
interface DatabaseModuleConfig {
|
|
@@ -313,7 +312,7 @@ declare module 'stratal/i18n' {
|
|
|
313
312
|
* })
|
|
314
313
|
* ```
|
|
315
314
|
*/
|
|
316
|
-
declare class ErrorHandlerPlugin implements RuntimePlugin<SchemaDef$1, Record<string, unknown>, Record<string, unknown
|
|
315
|
+
declare class ErrorHandlerPlugin implements RuntimePlugin<SchemaDef$1, Record<string, unknown>, Record<string, unknown>, {}> {
|
|
317
316
|
readonly id = "error-handler";
|
|
318
317
|
onQuery: ({
|
|
319
318
|
args,
|
|
@@ -347,7 +346,7 @@ interface EventEmitterPluginOptions {
|
|
|
347
346
|
* })
|
|
348
347
|
* ```
|
|
349
348
|
*/
|
|
350
|
-
declare class EventEmitterPlugin implements RuntimePlugin<SchemaDef$1, Record<string, unknown>, Record<string, unknown
|
|
349
|
+
declare class EventEmitterPlugin implements RuntimePlugin<SchemaDef$1, Record<string, unknown>, Record<string, unknown>, {}> {
|
|
351
350
|
private options;
|
|
352
351
|
readonly id = "event-emitter";
|
|
353
352
|
constructor(options: EventEmitterPluginOptions);
|
|
@@ -382,7 +381,7 @@ interface SchemaSwitcherPluginOptions {
|
|
|
382
381
|
* })
|
|
383
382
|
* ```
|
|
384
383
|
*/
|
|
385
|
-
declare class SchemaSwitcherPlugin implements RuntimePlugin<SchemaDef$1, Record<string, unknown>, Record<string, unknown
|
|
384
|
+
declare class SchemaSwitcherPlugin implements RuntimePlugin<SchemaDef$1, Record<string, unknown>, Record<string, unknown>, {}> {
|
|
386
385
|
private options;
|
|
387
386
|
readonly id = "schema-switcher";
|
|
388
387
|
constructor(options: SchemaSwitcherPluginOptions);
|
|
@@ -458,4 +457,4 @@ declare class MigrateStatusCommand extends ZenStackCommand {
|
|
|
458
457
|
}
|
|
459
458
|
//#endregion
|
|
460
459
|
export { InjectDB as A, fromZenStackError as C, ForeignKeyConstraintError as D, InvalidErrorCodeRangeError as E, DatabaseModule as F, DatabaseModuleConfig as I, connectionSymbol as M, DatabaseService as N, DatabaseConfigError as O, DatabaseConnectionConfig as P, ParseEvent as S, RecordNotFoundError as T, DatabaseOperation as _, DbPushCommand as a, GetResult as b, ZenStackCommand as c, EventEmitterPlugin as d, EventEmitterPluginOptions as f, DatabaseEvents as g, DatabaseEventName as h, MigrateDeployCommand as i, DATABASE_TOKENS as j, DatabaseError as k, SchemaSwitcherPlugin as l, databaseI18n as m, MigrateResetCommand as n, DbPullCommand as o, ErrorHandlerPlugin as p, MigrateDevCommand as r, DbGenerateCommand as s, MigrateStatusCommand as t, SchemaSwitcherPluginOptions as u, EventPhase as v, UniqueConstraintError as w, ModelName as x, GetData as y };
|
|
461
|
-
//# sourceMappingURL=index-
|
|
460
|
+
//# sourceMappingURL=index-B1iGBJcO.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-B1iGBJcO.d.mts","names":[],"sources":["../src/database/database.module.ts","../src/database/database.service.ts","../src/database/database.tokens.ts","../src/database/decorators/inject-db.decorator.ts","../src/database/errors/database-error.ts","../src/database/errors/database-config.error.ts","../src/database/errors/foreign-key-constraint.error.ts","../src/database/errors/invalid-error-code-range.error.ts","../src/database/errors/record-not-found.error.ts","../src/database/errors/unique-constraint.error.ts","../src/database/errors/from-zenstack-error.ts","../src/database/event-types.ts","../src/database/i18n/en.ts","../src/database/plugins/error-handler.plugin.ts","../src/database/plugins/event-emitter.plugin.ts","../src/database/plugins/schema-switcher.plugin.ts","../src/database/commands/zenstack.command.ts","../src/database/commands/db-generate.command.ts","../src/database/commands/db-pull.command.ts","../src/database/commands/db-push.command.ts","../src/database/commands/migrate-deploy.command.ts","../src/database/commands/migrate-dev.command.ts","../src/database/commands/migrate-reset.command.ts","../src/database/commands/migrate-status.command.ts"],"mappings":"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"}
|
package/dist/rbac/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { t as __decorate } from "../decorate-
|
|
2
|
-
import { t as __decorateMetadata } from "../decorateMetadata-
|
|
3
|
-
import { t as __decorateParam } from "../decorateParam-
|
|
1
|
+
import { t as __decorate } from "../decorate-C12QolJF.mjs";
|
|
2
|
+
import { t as __decorateMetadata } from "../decorateMetadata-rWbWGUuO.mjs";
|
|
3
|
+
import { t as __decorateParam } from "../decorateParam-WGqsyT5s.mjs";
|
|
4
4
|
import { n as InsufficientPermissionsError, t as RBAC_TOKENS } from "../tokens-Di1ofovy.mjs";
|
|
5
5
|
import { Module } from "stratal/module";
|
|
6
6
|
import { DI_TOKENS, Transient } from "stratal/di";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stratal/framework",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.18",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Temitayo Fadojutimi",
|
|
@@ -63,40 +63,40 @@
|
|
|
63
63
|
"test:coverage": "vitest run --coverage",
|
|
64
64
|
"test:db": "docker compose -f test/docker-compose.yml up -d",
|
|
65
65
|
"typecheck": "yarn tsc --noEmit",
|
|
66
|
-
"lint": "npx
|
|
67
|
-
"lint:fix": "npx
|
|
66
|
+
"lint": "npx oxlint .",
|
|
67
|
+
"lint:fix": "npx oxlint --fix ."
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
|
-
"@better-auth/core": "^1.5.
|
|
71
|
-
"@faker-js/faker": "^10.
|
|
72
|
-
"@zenstackhq/cli": "^3.
|
|
73
|
-
"@zenstackhq/orm": "^3.
|
|
74
|
-
"better-auth": "^1.5.
|
|
70
|
+
"@better-auth/core": "^1.5.6",
|
|
71
|
+
"@faker-js/faker": "^10.4.0",
|
|
72
|
+
"@zenstackhq/cli": "^3.5.1",
|
|
73
|
+
"@zenstackhq/orm": "^3.5.1",
|
|
74
|
+
"better-auth": "^1.5.6",
|
|
75
75
|
"casbin": "^5.49.0",
|
|
76
76
|
"postgres-array": "^3.0.4"
|
|
77
77
|
},
|
|
78
78
|
"peerDependencies": {
|
|
79
79
|
"pg": "^8.0.0",
|
|
80
80
|
"reflect-metadata": "^0.2.2",
|
|
81
|
-
"stratal": "^0.0.
|
|
81
|
+
"stratal": "^0.0.18"
|
|
82
82
|
},
|
|
83
83
|
"devDependencies": {
|
|
84
|
-
"@cloudflare/vitest-pool-workers": "^0.13.
|
|
84
|
+
"@cloudflare/vitest-pool-workers": "^0.13.5",
|
|
85
85
|
"@cloudflare/workers-types": "4.20260317.1",
|
|
86
86
|
"@stratal/testing": "workspace:^",
|
|
87
87
|
"@types/node": "^25.5.0",
|
|
88
88
|
"@types/pg": "^8.20.0",
|
|
89
|
-
"@vitest/coverage-istanbul": "~4.1.
|
|
90
|
-
"@vitest/runner": "~4.1.
|
|
91
|
-
"@vitest/snapshot": "~4.1.
|
|
92
|
-
"@zenstackhq/better-auth": "^3.
|
|
89
|
+
"@vitest/coverage-istanbul": "~4.1.2",
|
|
90
|
+
"@vitest/runner": "~4.1.2",
|
|
91
|
+
"@vitest/snapshot": "~4.1.2",
|
|
92
|
+
"@zenstackhq/better-auth": "^3.5.1",
|
|
93
93
|
"dotenv-cli": "^11.0.0",
|
|
94
94
|
"pg": "^8.20.0",
|
|
95
95
|
"reflect-metadata": "^0.2.2",
|
|
96
96
|
"stratal": "workspace:*",
|
|
97
|
-
"tsdown": "^0.21.
|
|
98
|
-
"typescript": "^
|
|
99
|
-
"vitest": "~4.1.
|
|
100
|
-
"wrangler": "^4.
|
|
97
|
+
"tsdown": "^0.21.6",
|
|
98
|
+
"typescript": "^6.0.2",
|
|
99
|
+
"vitest": "~4.1.2",
|
|
100
|
+
"wrangler": "^4.78.0"
|
|
101
101
|
}
|
|
102
102
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-eukGTmI8.d.mts","names":[],"sources":["../src/database/database.module.ts","../src/database/database.service.ts","../src/database/database.tokens.ts","../src/database/decorators/inject-db.decorator.ts","../src/database/errors/database-error.ts","../src/database/errors/database-config.error.ts","../src/database/errors/foreign-key-constraint.error.ts","../src/database/errors/invalid-error-code-range.error.ts","../src/database/errors/record-not-found.error.ts","../src/database/errors/unique-constraint.error.ts","../src/database/errors/from-zenstack-error.ts","../src/database/event-types.ts","../src/database/i18n/en.ts","../src/database/plugins/error-handler.plugin.ts","../src/database/plugins/event-emitter.plugin.ts","../src/database/plugins/schema-switcher.plugin.ts","../src/database/commands/zenstack.command.ts","../src/database/commands/db-generate.command.ts","../src/database/commands/db-pull.command.ts","../src/database/commands/db-push.command.ts","../src/database/commands/migrate-deploy.command.ts","../src/database/commands/migrate-dev.command.ts","../src/database/commands/migrate-reset.command.ts","../src/database/commands/migrate-status.command.ts"],"mappings":"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"}
|