@getstrata/core 0.5.91 → 0.5.97
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/CHANGELOG.md +8 -0
- package/dist/core/database/errors.d.ts +1 -1
- package/dist/core/errors/http.d.ts +8 -1
- package/dist/entries/database/errors.js +4 -3
- package/dist/entries/http/response.js +10 -9
- package/dist/entries/http/webErrorResponse.js +8 -7
- package/dist/framework/public-api.d.ts +2 -2
- package/dist/index.js +30 -8
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @getstrata/core changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.97
|
|
4
|
+
|
|
5
|
+
- `mapDatabaseError()` recognizes HTTP errors by `status` + `message`, not only `instanceof HttpError`. Subpath builds duplicate the class, so a thrown `ForbiddenError` was remapped to `400 Bad Request`.
|
|
6
|
+
|
|
7
|
+
## 0.5.92
|
|
8
|
+
|
|
9
|
+
- Re-export `resolveMembershipLookup` and `runWithMembershipContext` from the public barrel. Shared subpath shims re-export that barrel, so published `@getstrata/bootstrap` can import `@getstrata/core/auth/membershipContext` without a missing-export boot failure.
|
|
10
|
+
|
|
3
11
|
## 0.5.91
|
|
4
12
|
|
|
5
13
|
- `Schedule.command()` accepts any expression `Bun.cron.parse` understands. `dueTasks()` uses the next fire time in the current minute instead of a `*/N` whitelist.
|
|
@@ -30,4 +30,11 @@ declare class PayloadTooLargeError extends HttpError {
|
|
|
30
30
|
declare class PreconditionFailedError extends HttpError {
|
|
31
31
|
constructor(message?: string, details?: unknown);
|
|
32
32
|
}
|
|
33
|
-
|
|
33
|
+
interface HttpErrorLike {
|
|
34
|
+
status: number;
|
|
35
|
+
message: string;
|
|
36
|
+
details?: unknown;
|
|
37
|
+
}
|
|
38
|
+
declare function isHttpErrorLike(error: unknown): error is HttpErrorLike;
|
|
39
|
+
declare function toHttpError(error: unknown): HttpError | null;
|
|
40
|
+
export { BadRequestError, ConflictError, ForbiddenError, HttpError, isHttpErrorLike, NotFoundError, PayloadTooLargeError, PreconditionFailedError, toHttpError, UnauthorizedError, UnprocessableEntityError, ValidationError, };
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import {
|
|
4
4
|
BadRequestError,
|
|
5
5
|
ConflictError,
|
|
6
|
-
|
|
6
|
+
toHttpError,
|
|
7
7
|
UnprocessableEntityError
|
|
8
8
|
} from "@getstrata/core/errors/http";
|
|
9
9
|
function isPostgresError(error) {
|
|
@@ -22,8 +22,9 @@ function getPostgresSqlState(error) {
|
|
|
22
22
|
return;
|
|
23
23
|
}
|
|
24
24
|
function mapDatabaseError(error) {
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
const httpError = toHttpError(error);
|
|
26
|
+
if (httpError) {
|
|
27
|
+
return httpError;
|
|
27
28
|
}
|
|
28
29
|
if (!isPostgresError(error)) {
|
|
29
30
|
const message = error instanceof Error ? error.message : "Database operation failed.";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// ../../src/core/http/response.ts
|
|
3
|
-
import {
|
|
3
|
+
import { toHttpError as toHttpError3 } from "@getstrata/core/errors/http";
|
|
4
4
|
|
|
5
5
|
// ../../src/core/database/errors.ts
|
|
6
6
|
import {
|
|
7
7
|
BadRequestError,
|
|
8
8
|
ConflictError,
|
|
9
|
-
|
|
9
|
+
toHttpError,
|
|
10
10
|
UnprocessableEntityError
|
|
11
11
|
} from "@getstrata/core/errors/http";
|
|
12
12
|
function isPostgresError(error) {
|
|
@@ -25,8 +25,9 @@ function getPostgresSqlState(error) {
|
|
|
25
25
|
return;
|
|
26
26
|
}
|
|
27
27
|
function mapDatabaseError(error) {
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
const httpError = toHttpError(error);
|
|
29
|
+
if (httpError) {
|
|
30
|
+
return httpError;
|
|
30
31
|
}
|
|
31
32
|
if (!isPostgresError(error)) {
|
|
32
33
|
const message = error instanceof Error ? error.message : "Database operation failed.";
|
|
@@ -66,7 +67,7 @@ async function withDatabaseErrorHandling(operation) {
|
|
|
66
67
|
}
|
|
67
68
|
|
|
68
69
|
// ../../src/core/http/webErrorResponse.ts
|
|
69
|
-
import {
|
|
70
|
+
import { toHttpError as toHttpError2, ValidationError } from "@getstrata/core/errors/http";
|
|
70
71
|
|
|
71
72
|
// ../../src/core/runtime/frontendMode.ts
|
|
72
73
|
function readFrontendMode() {
|
|
@@ -301,11 +302,11 @@ async function webErrorResponse(error, request) {
|
|
|
301
302
|
if (!request || !isViewsEnabled() || requestPrefersJson(request)) {
|
|
302
303
|
return null;
|
|
303
304
|
}
|
|
304
|
-
const mappedError = error
|
|
305
|
-
if (mappedError
|
|
305
|
+
const mappedError = toHttpError2(error) ?? mapDatabaseError(error);
|
|
306
|
+
if (mappedError.status === 401) {
|
|
306
307
|
return Response.redirect(loginRedirectLocation(request), 302);
|
|
307
308
|
}
|
|
308
|
-
const errors = mappedError instanceof ValidationError ? normalizeFieldErrors(mappedError.details) : undefined;
|
|
309
|
+
const errors = mappedError instanceof ValidationError || mappedError.name === "ValidationError" ? normalizeFieldErrors(mappedError.details) : undefined;
|
|
309
310
|
return htmlErrorResponse({
|
|
310
311
|
status: mappedError.status,
|
|
311
312
|
title: errorPageTitle(mappedError.status, mappedError.message),
|
|
@@ -329,7 +330,7 @@ function noContentResponse() {
|
|
|
329
330
|
return new Response(null, { status: 204 });
|
|
330
331
|
}
|
|
331
332
|
function errorResponse(error) {
|
|
332
|
-
const mappedError = error
|
|
333
|
+
const mappedError = toHttpError3(error) ?? mapDatabaseError(error);
|
|
333
334
|
return Response.json({
|
|
334
335
|
error: mappedError.message,
|
|
335
336
|
...mappedError.details === undefined ? {} : { details: mappedError.details }
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// ../../src/core/http/webErrorResponse.ts
|
|
3
|
-
import {
|
|
3
|
+
import { toHttpError as toHttpError2, ValidationError } from "@getstrata/core/errors/http";
|
|
4
4
|
|
|
5
5
|
// ../../src/core/database/errors.ts
|
|
6
6
|
import {
|
|
7
7
|
BadRequestError,
|
|
8
8
|
ConflictError,
|
|
9
|
-
|
|
9
|
+
toHttpError,
|
|
10
10
|
UnprocessableEntityError
|
|
11
11
|
} from "@getstrata/core/errors/http";
|
|
12
12
|
function isPostgresError(error) {
|
|
@@ -25,8 +25,9 @@ function getPostgresSqlState(error) {
|
|
|
25
25
|
return;
|
|
26
26
|
}
|
|
27
27
|
function mapDatabaseError(error) {
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
const httpError = toHttpError(error);
|
|
29
|
+
if (httpError) {
|
|
30
|
+
return httpError;
|
|
30
31
|
}
|
|
31
32
|
if (!isPostgresError(error)) {
|
|
32
33
|
const message = error instanceof Error ? error.message : "Database operation failed.";
|
|
@@ -298,11 +299,11 @@ async function webErrorResponse(error, request) {
|
|
|
298
299
|
if (!request || !isViewsEnabled() || requestPrefersJson(request)) {
|
|
299
300
|
return null;
|
|
300
301
|
}
|
|
301
|
-
const mappedError = error
|
|
302
|
-
if (mappedError
|
|
302
|
+
const mappedError = toHttpError2(error) ?? mapDatabaseError(error);
|
|
303
|
+
if (mappedError.status === 401) {
|
|
303
304
|
return Response.redirect(loginRedirectLocation(request), 302);
|
|
304
305
|
}
|
|
305
|
-
const errors = mappedError instanceof ValidationError ? normalizeFieldErrors(mappedError.details) : undefined;
|
|
306
|
+
const errors = mappedError instanceof ValidationError || mappedError.name === "ValidationError" ? normalizeFieldErrors(mappedError.details) : undefined;
|
|
306
307
|
return htmlErrorResponse({
|
|
307
308
|
status: mappedError.status,
|
|
308
309
|
title: errorPageTitle(mappedError.status, mappedError.message),
|
|
@@ -10,7 +10,7 @@ export type { AuthUser } from "../core/auth/authContext.ts";
|
|
|
10
10
|
export { authContext, currentAuthUser, runWithAuthUser } from "../core/auth/authContext.ts";
|
|
11
11
|
export type { AuthGuard } from "../core/auth/guard.ts";
|
|
12
12
|
export { ApiTokenGuard, AuthManager, CompositeGuard, DatabaseTokenGuard, GuestGuard, } from "../core/auth/guard.ts";
|
|
13
|
-
export { configureMembershipLookup, currentOrganizationIds, currentOrgRole, hasMinimumOrgRole, hasOrgMembership, } from "../core/auth/membershipContext.ts";
|
|
13
|
+
export { configureMembershipLookup, currentOrganizationIds, currentOrgRole, hasMinimumOrgRole, hasOrgMembership, resolveMembershipLookup, runWithMembershipContext, } from "../core/auth/membershipContext.ts";
|
|
14
14
|
export { createMembershipMiddleware } from "../core/auth/membershipMiddleware.ts";
|
|
15
15
|
export { appendOrganizationScope, appendProjectScope, assertOrganizationReadable, assertResourceInCurrentTenant, emptyPaginateResult, resolveOrganizationScope, scopedOrganizationIds, } from "../core/auth/membershipScope.ts";
|
|
16
16
|
export { default as MembershipService, resolveMembershipService, } from "../core/auth/membershipService.ts";
|
|
@@ -48,7 +48,7 @@ export { runInTransaction } from "../core/database/transaction.ts";
|
|
|
48
48
|
export type { QueryJoin, QueryJoinOn, QueryOptions, QueryOrder, QuerySelectItem, QueryWhere, } from "../core/database/types.ts";
|
|
49
49
|
export type { WhereNode } from "../core/database/whereBuilder.ts";
|
|
50
50
|
export { WhereBuilder } from "../core/database/whereBuilder.ts";
|
|
51
|
-
export { BadRequestError, ConflictError, ForbiddenError, HttpError, NotFoundError, PayloadTooLargeError, PreconditionFailedError, UnauthorizedError, UnprocessableEntityError, ValidationError, } from "../core/errors/http.ts";
|
|
51
|
+
export { BadRequestError, ConflictError, ForbiddenError, HttpError, isHttpErrorLike, NotFoundError, PayloadTooLargeError, PreconditionFailedError, toHttpError, UnauthorizedError, UnprocessableEntityError, ValidationError, } from "../core/errors/http.ts";
|
|
52
52
|
export type { EventListener } from "../core/events/eventBus.ts";
|
|
53
53
|
export { EventBus, eventBus } from "../core/events/eventBus.ts";
|
|
54
54
|
export { modelEventName } from "../core/events/index.ts";
|
package/dist/index.js
CHANGED
|
@@ -120,6 +120,22 @@ class PreconditionFailedError extends HttpError {
|
|
|
120
120
|
super(412, message, details);
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
|
+
function isHttpErrorLike(error) {
|
|
124
|
+
if (typeof error !== "object" || error === null) {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
const candidate = error;
|
|
128
|
+
return typeof candidate.status === "number" && Number.isInteger(candidate.status) && candidate.status >= 400 && candidate.status < 600 && typeof candidate.message === "string";
|
|
129
|
+
}
|
|
130
|
+
function toHttpError(error) {
|
|
131
|
+
if (error instanceof HttpError) {
|
|
132
|
+
return error;
|
|
133
|
+
}
|
|
134
|
+
if (!isHttpErrorLike(error)) {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
return new HttpError(error.status, error.message, error.details);
|
|
138
|
+
}
|
|
123
139
|
|
|
124
140
|
// ../../src/core/runtime/asyncContextStore.ts
|
|
125
141
|
import { AsyncLocalStorage } from "async_hooks";
|
|
@@ -1575,8 +1591,9 @@ function getPostgresSqlState(error) {
|
|
|
1575
1591
|
return;
|
|
1576
1592
|
}
|
|
1577
1593
|
function mapDatabaseError(error) {
|
|
1578
|
-
|
|
1579
|
-
|
|
1594
|
+
const httpError = toHttpError(error);
|
|
1595
|
+
if (httpError) {
|
|
1596
|
+
return httpError;
|
|
1580
1597
|
}
|
|
1581
1598
|
if (!isPostgresError(error)) {
|
|
1582
1599
|
const message = error instanceof Error ? error.message : "Database operation failed.";
|
|
@@ -5298,11 +5315,11 @@ async function webErrorResponse(error, request) {
|
|
|
5298
5315
|
if (!request || !isViewsEnabled() || requestPrefersJson(request)) {
|
|
5299
5316
|
return null;
|
|
5300
5317
|
}
|
|
5301
|
-
const mappedError = error
|
|
5302
|
-
if (mappedError
|
|
5318
|
+
const mappedError = toHttpError(error) ?? mapDatabaseError(error);
|
|
5319
|
+
if (mappedError.status === 401) {
|
|
5303
5320
|
return Response.redirect(loginRedirectLocation(request), 302);
|
|
5304
5321
|
}
|
|
5305
|
-
const errors = mappedError instanceof ValidationError ? normalizeFieldErrors(mappedError.details) : undefined;
|
|
5322
|
+
const errors = mappedError instanceof ValidationError || mappedError.name === "ValidationError" ? normalizeFieldErrors(mappedError.details) : undefined;
|
|
5306
5323
|
return htmlErrorResponse({
|
|
5307
5324
|
status: mappedError.status,
|
|
5308
5325
|
title: errorPageTitle(mappedError.status, mappedError.message),
|
|
@@ -5326,7 +5343,7 @@ function noContentResponse() {
|
|
|
5326
5343
|
return new Response(null, { status: 204 });
|
|
5327
5344
|
}
|
|
5328
5345
|
function errorResponse(error) {
|
|
5329
|
-
const mappedError = error
|
|
5346
|
+
const mappedError = toHttpError(error) ?? mapDatabaseError(error);
|
|
5330
5347
|
return Response.json({
|
|
5331
5348
|
error: mappedError.message,
|
|
5332
5349
|
...mappedError.details === undefined ? {} : { details: mappedError.details }
|
|
@@ -6699,8 +6716,9 @@ function createTenantMiddleware() {
|
|
|
6699
6716
|
});
|
|
6700
6717
|
});
|
|
6701
6718
|
} catch (error) {
|
|
6702
|
-
|
|
6703
|
-
|
|
6719
|
+
const httpError = toHttpError(error);
|
|
6720
|
+
if (httpError) {
|
|
6721
|
+
return Response.json({ error: httpError.message }, { status: httpError.status });
|
|
6704
6722
|
}
|
|
6705
6723
|
throw error;
|
|
6706
6724
|
}
|
|
@@ -7309,6 +7327,7 @@ export {
|
|
|
7309
7327
|
isEtagEnabled,
|
|
7310
7328
|
isGlobalAdmin,
|
|
7311
7329
|
isHtmxRequest,
|
|
7330
|
+
isHttpErrorLike,
|
|
7312
7331
|
isInsideTenantDatabaseScope,
|
|
7313
7332
|
isPublicReadsEnabled,
|
|
7314
7333
|
isTenancyEnabled,
|
|
@@ -7371,6 +7390,7 @@ export {
|
|
|
7371
7390
|
resolveCsrfTokenForRequest,
|
|
7372
7391
|
resolveDatabaseDriver,
|
|
7373
7392
|
resolveHtmlContentSecurityPolicy,
|
|
7393
|
+
resolveMembershipLookup,
|
|
7374
7394
|
resolveMembershipService,
|
|
7375
7395
|
resolveOrganizationScope,
|
|
7376
7396
|
resolveRepositoryConnection,
|
|
@@ -7387,6 +7407,7 @@ export {
|
|
|
7387
7407
|
runSeedersFromDirectory,
|
|
7388
7408
|
runWithAuthUser,
|
|
7389
7409
|
runWithDatabaseConnection,
|
|
7410
|
+
runWithMembershipContext,
|
|
7390
7411
|
runWithRequestMeta,
|
|
7391
7412
|
runWithTenant,
|
|
7392
7413
|
runWithTenantDatabase,
|
|
@@ -7409,6 +7430,7 @@ export {
|
|
|
7409
7430
|
stripMarkdown,
|
|
7410
7431
|
temporarySignedUrl,
|
|
7411
7432
|
textResponse,
|
|
7433
|
+
toHttpError,
|
|
7412
7434
|
toPaginatedResourceCollection,
|
|
7413
7435
|
toResourceCollection,
|
|
7414
7436
|
trustForwardedFor,
|