@getstrata/core 0.3.9 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bootstrap/httpKernel.d.ts +2 -0
- package/dist/config/queue.d.ts +8 -0
- package/dist/config/rateLimit.d.ts +2 -1
- package/dist/core/database/baseRepository.d.ts +16 -4
- package/dist/core/database/boundConnection.d.ts +5 -0
- package/dist/core/database/index.d.ts +10 -4
- package/dist/core/database/migrations/advisoryLock.d.ts +6 -0
- package/dist/core/database/migrations/runner.d.ts +8 -2
- package/dist/core/database/migrations/types.d.ts +1 -0
- package/dist/core/database/model.d.ts +46 -17
- package/dist/core/database/query.d.ts +26 -14
- package/dist/core/database/relationships.d.ts +32 -2
- package/dist/core/database/repositoryConnection.d.ts +4 -0
- package/dist/core/database/repositoryQuery.d.ts +16 -1
- package/dist/core/database/schema/blueprint.d.ts +47 -0
- package/dist/core/database/schema/columnDefinition.d.ts +36 -0
- package/dist/core/database/schema/driver.d.ts +8 -0
- package/dist/core/database/schema/errors.d.ts +4 -0
- package/dist/core/database/schema/grammars/compileStatements.d.ts +8 -0
- package/dist/core/database/schema/grammars/createGrammar.d.ts +4 -0
- package/dist/core/database/schema/grammars/grammar.d.ts +10 -0
- package/dist/core/database/schema/grammars/index.d.ts +7 -0
- package/dist/core/database/schema/grammars/mysqlGrammar.d.ts +2 -0
- package/dist/core/database/schema/grammars/postgresGrammar.d.ts +2 -0
- package/dist/core/database/schema/grammars/sqliteGrammar.d.ts +2 -0
- package/dist/core/database/schema/index.d.ts +12 -0
- package/dist/core/database/schema/schema.d.ts +21 -0
- package/dist/core/database/seeders/runner.d.ts +6 -0
- package/dist/core/database/seeders/types.d.ts +8 -0
- package/dist/core/database/types.d.ts +39 -2
- package/dist/core/database/whereBuilder.d.ts +17 -0
- package/dist/core/http/index.d.ts +1 -1
- package/dist/core/http/securedRouteModelBinding.d.ts +2 -1
- package/dist/core/lifecycle/gracefulShutdown.d.ts +6 -0
- package/dist/core/pagination/index.d.ts +11 -1
- package/dist/core/queue/failedJobRepository.d.ts +6 -0
- package/dist/core/queue/failedJobService.d.ts +15 -0
- package/dist/core/queue/failedJobTable.d.ts +3 -0
- package/dist/core/queue/jobRegistry.d.ts +14 -0
- package/dist/core/queue/jobRunner.d.ts +9 -0
- package/dist/core/queue/publicQueue.d.ts +15 -0
- package/dist/core/queue/redisQueue.d.ts +29 -0
- package/dist/core/queue/resilientQueue.d.ts +9 -0
- package/dist/core/queue/types.d.ts +8 -0
- package/dist/core/scheduler/schedule.d.ts +15 -0
- package/dist/entries/auth/accessControl.js +113 -0
- package/dist/entries/auth/authContext.js +15 -0
- package/dist/entries/auth/guard.js +2870 -0
- package/dist/entries/auth/membershipContext.js +276 -0
- package/dist/entries/auth/membershipScope.js +390 -0
- package/dist/entries/auth/membershipService.js +477 -0
- package/dist/entries/auth/oauth/oidcProvider.js +49 -0
- package/dist/entries/auth/oauth/providers.js +71 -0
- package/dist/entries/auth/oauth/samlProvider.js +26 -0
- package/dist/entries/auth/oauth/types.js +1 -0
- package/dist/entries/auth/password.js +15 -0
- package/dist/entries/auth/policy.js +134 -0
- package/dist/entries/auth/sessionCookie.js +75 -0
- package/dist/entries/auth/tokenHash.js +17 -0
- package/dist/entries/cache/tags.js +13 -0
- package/dist/entries/crypto/fieldEncryption.js +93 -0
- package/dist/entries/crypto/mfaSecret.js +105 -0
- package/dist/entries/database/factory.js +17 -0
- package/dist/entries/database/seeders.js +30 -0
- package/dist/entries/database/types.js +1 -0
- package/dist/entries/database.js +2218 -0
- package/dist/entries/errors/http.js +78 -0
- package/dist/entries/http/contentNegotiation.js +26 -0
- package/dist/entries/http/csrfToken.js +147 -0
- package/dist/entries/http/etag.js +170 -0
- package/dist/entries/http/flashSession.js +106 -0
- package/dist/entries/http/middleware.js +68 -0
- package/dist/entries/http/parseFormBody.js +88 -0
- package/dist/entries/http/requestMetaContext.js +18 -0
- package/dist/entries/http/resources.js +19 -0
- package/dist/entries/http/webErrorResponse.js +3143 -0
- package/dist/entries/http/webFormRequest.js +293 -0
- package/dist/entries/http.js +3924 -0
- package/dist/entries/jobs/dispatchWebhookJob.js +342 -0
- package/dist/entries/lifecycle/gracefulShutdown.js +50 -0
- package/dist/entries/metrics/prometheus.js +70 -0
- package/dist/entries/pagination.js +14 -0
- package/dist/entries/queue/createAppQueue.js +2848 -0
- package/dist/entries/queue/failedJobService.js +38 -0
- package/dist/entries/queue/jobRegistry.js +32 -0
- package/dist/entries/queue/jobRunner.js +75 -0
- package/dist/entries/queue/publicQueue.js +2476 -0
- package/dist/entries/queue/queueMetrics.js +2898 -0
- package/dist/entries/queue/types.js +1 -0
- package/dist/entries/security/oauthState.js +75 -0
- package/dist/entries/security/publicReads.js +33 -0
- package/dist/entries/security/safeUrl.js +143 -0
- package/dist/entries/security/securityEvents.js +41 -0
- package/dist/entries/security/stripeWebhook.js +115 -0
- package/dist/entries/security/tokenExpiry.js +16 -0
- package/dist/entries/security/totp.js +51 -0
- package/dist/entries/storage/storage.js +123 -0
- package/dist/entries/tenant/tenantContext.js +30 -0
- package/dist/entries/tenant/tenantMiddleware.js +312 -0
- package/dist/entries/tracing/traceContext.js +15 -0
- package/dist/entries/validation/rules.js +232 -0
- package/dist/entries/view.js +3072 -0
- package/dist/framework/public-api.d.ts +65 -38
- package/dist/index.js +3213 -281
- package/dist/modules/user/apiTokenRepository.d.ts +1 -1
- package/dist/modules/user/apiTokenTable.d.ts +1 -1
- package/dist/modules/user/authService.d.ts +1 -1
- package/dist/modules/user/notificationRepository.d.ts +1 -1
- package/dist/modules/user/notificationService.d.ts +1 -1
- package/dist/modules/user/notificationTable.d.ts +1 -1
- package/dist/modules/user/oauthIdentityRepository.d.ts +2 -2
- package/dist/modules/user/provider.d.ts +1 -1
- package/dist/modules/user/repository.d.ts +1 -1
- package/dist/modules/user/table.d.ts +1 -1
- package/dist/modules/user/tokenService.d.ts +1 -1
- package/package.json +289 -3
|
@@ -8,14 +8,47 @@ type QueryOperator = {
|
|
|
8
8
|
lt?: DatabaseComparable;
|
|
9
9
|
lte?: DatabaseComparable;
|
|
10
10
|
isNull?: boolean;
|
|
11
|
+
ilike?: string;
|
|
12
|
+
tsMatch?: string;
|
|
11
13
|
};
|
|
12
14
|
type QueryFilterValue = DatabaseScalar | readonly DatabaseScalar[] | QueryOperator;
|
|
13
|
-
type QueryWhere<TEntity> = Partial<Record<keyof TEntity & string, QueryFilterValue>>;
|
|
15
|
+
type QueryWhere<TEntity> = Partial<Record<keyof TEntity & string, QueryFilterValue>> & Partial<Record<string, QueryFilterValue>>;
|
|
14
16
|
type QueryOrder<TEntity> = {
|
|
15
17
|
column: keyof TEntity & string;
|
|
16
18
|
direction?: "ASC" | "DESC" | "asc" | "desc";
|
|
17
19
|
};
|
|
18
20
|
type QueryOrderShorthand<TEntity> = Partial<Record<keyof TEntity & string, "ASC" | "DESC" | "asc" | "desc">>;
|
|
21
|
+
type QueryJoinOn = {
|
|
22
|
+
left: {
|
|
23
|
+
table: string;
|
|
24
|
+
column: string;
|
|
25
|
+
};
|
|
26
|
+
right: {
|
|
27
|
+
table: string;
|
|
28
|
+
column: string;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
type QueryJoin = {
|
|
32
|
+
type: "inner" | "left";
|
|
33
|
+
table: string;
|
|
34
|
+
on: QueryJoinOn[];
|
|
35
|
+
};
|
|
36
|
+
type QuerySelectItem = {
|
|
37
|
+
kind: "column";
|
|
38
|
+
table: string;
|
|
39
|
+
column: string;
|
|
40
|
+
as?: string;
|
|
41
|
+
} | {
|
|
42
|
+
kind: "literalText";
|
|
43
|
+
value: string;
|
|
44
|
+
as: string;
|
|
45
|
+
} | {
|
|
46
|
+
kind: "tsRank";
|
|
47
|
+
table: string;
|
|
48
|
+
column: string;
|
|
49
|
+
query: string;
|
|
50
|
+
as: string;
|
|
51
|
+
};
|
|
19
52
|
interface QueryOptions<TEntity> {
|
|
20
53
|
where?: QueryWhere<TEntity>;
|
|
21
54
|
orderBy?: QueryOrder<TEntity> | QueryOrder<TEntity>[] | QueryOrderShorthand<TEntity>;
|
|
@@ -23,7 +56,11 @@ interface QueryOptions<TEntity> {
|
|
|
23
56
|
offset?: number;
|
|
24
57
|
withTrashed?: boolean;
|
|
25
58
|
onlyTrashed?: boolean;
|
|
59
|
+
joins?: QueryJoin[];
|
|
60
|
+
groupBy?: string | string[];
|
|
61
|
+
having?: QueryWhere<TEntity>;
|
|
62
|
+
select?: QuerySelectItem[];
|
|
26
63
|
}
|
|
27
64
|
type MutationValues<TEntity> = Partial<TEntity>;
|
|
28
65
|
type UpdateValues<TEntity, PrimaryKey extends keyof TEntity & string = keyof TEntity & string> = Partial<Omit<TEntity, PrimaryKey>>;
|
|
29
|
-
export type { DatabaseComparable, DatabaseScalar, MutationValues, QueryFilterValue, QueryOperator, QueryOptions, QueryOrder, QueryWhere, UpdateValues, };
|
|
66
|
+
export type { DatabaseComparable, DatabaseScalar, MutationValues, QueryFilterValue, QueryJoin, QueryJoinOn, QueryOperator, QueryOptions, QueryOrder, QuerySelectItem, QueryWhere, UpdateValues, };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { QueryWhere } from "./types.ts";
|
|
2
|
+
type WhereNode<TEntity extends object> = {
|
|
3
|
+
kind: "and" | "or";
|
|
4
|
+
where: QueryWhere<TEntity>;
|
|
5
|
+
} | {
|
|
6
|
+
kind: "and" | "or";
|
|
7
|
+
group: WhereNode<TEntity>[];
|
|
8
|
+
};
|
|
9
|
+
declare class WhereBuilder<TEntity extends object> {
|
|
10
|
+
readonly nodes: WhereNode<TEntity>[];
|
|
11
|
+
where(where: QueryWhere<TEntity>): this;
|
|
12
|
+
orWhere(where: QueryWhere<TEntity>): this;
|
|
13
|
+
whereGroup(fn: (builder: WhereBuilder<TEntity>) => void): this;
|
|
14
|
+
orWhereGroup(fn: (builder: WhereBuilder<TEntity>) => void): this;
|
|
15
|
+
}
|
|
16
|
+
export type { WhereNode };
|
|
17
|
+
export { WhereBuilder };
|
|
@@ -13,7 +13,7 @@ export { createRequireAuthMiddleware } from "./requireAuthMiddleware";
|
|
|
13
13
|
export { serializeDate, toPaginatedResourceCollection, toResourceCollection } from "./resources";
|
|
14
14
|
export { withMiddleware } from "./routeMiddleware";
|
|
15
15
|
export { bindRouteModel } from "./routeModelBinding";
|
|
16
|
-
export { securedBindRouteModel } from "./securedRouteModelBinding";
|
|
16
|
+
export { securedBindRouteModel, securedBindRouteModelByKey, } from "./securedRouteModelBinding";
|
|
17
17
|
export { buildRequestCacheKey, expectObject, getQueryParams, parseJsonBody, parseOptionalBooleanQueryParam, parseOptionalEnumQueryParam, parseOptionalPositiveIntQueryParam, parsePositiveIntParam, readOptionalEnum, readOptionalPositiveInt, readOptionalString, readRequiredEnum, readRequiredPositiveInt, readRequiredString, } from "./validation";
|
|
18
18
|
declare function jsonResponse(data: unknown, init?: ResponseInit): Response;
|
|
19
19
|
declare function createdResponse(data: unknown, init?: ResponseInit): Response;
|
|
@@ -6,5 +6,6 @@ interface RouteModelAuthorization {
|
|
|
6
6
|
requireIfMatch?: boolean;
|
|
7
7
|
}
|
|
8
8
|
declare function securedBindRouteModel<TParams extends Record<string, string>, TModel, TParam extends keyof TParams & string>(param: TParam, resolver: (id: number, request: RouteRequest<TParams>) => Promise<TModel>, authorization: RouteModelAuthorization, handler: (request: RouteRequest<TParams>, model: TModel) => Response | Promise<Response>): (request: RouteRequest<TParams>) => Promise<Response>;
|
|
9
|
+
declare function securedBindRouteModelByKey<TParams extends Record<string, string>, TModel, TParam extends keyof TParams & string>(param: TParam, resolver: (key: string, request: RouteRequest<TParams>) => Promise<TModel>, authorization: RouteModelAuthorization, handler: (request: RouteRequest<TParams>, model: TModel) => Response | Promise<Response>): (request: RouteRequest<TParams>) => Promise<Response>;
|
|
9
10
|
export type { RouteModelAuthorization };
|
|
10
|
-
export { securedBindRouteModel };
|
|
11
|
+
export { securedBindRouteModel, securedBindRouteModelByKey };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
type ShutdownHandler = () => void | Promise<void>;
|
|
2
|
+
declare function registerShutdownHandler(name: string, handler: ShutdownHandler): () => void;
|
|
3
|
+
declare function runGracefulShutdown(signal: string): Promise<void>;
|
|
4
|
+
declare function installGracefulShutdownSignals(signals?: NodeJS.Signals[]): void;
|
|
5
|
+
declare function resetGracefulShutdownForTests(): void;
|
|
6
|
+
export { installGracefulShutdownSignals, registerShutdownHandler, resetGracefulShutdownForTests, runGracefulShutdown, };
|
|
@@ -8,10 +8,20 @@ interface PaginatedResult<T> {
|
|
|
8
8
|
data: T[];
|
|
9
9
|
meta: PaginationMeta;
|
|
10
10
|
}
|
|
11
|
+
interface CursorPaginationMeta<Cursor = unknown> {
|
|
12
|
+
per_page: number;
|
|
13
|
+
next_cursor: Cursor | null;
|
|
14
|
+
prev_cursor: Cursor | null;
|
|
15
|
+
has_more: boolean;
|
|
16
|
+
}
|
|
17
|
+
interface CursorPaginatedResult<T, Cursor = unknown> {
|
|
18
|
+
data: T[];
|
|
19
|
+
meta: CursorPaginationMeta<Cursor>;
|
|
20
|
+
}
|
|
11
21
|
declare function buildPaginationMeta(input: {
|
|
12
22
|
page: number;
|
|
13
23
|
perPage: number;
|
|
14
24
|
total: number;
|
|
15
25
|
}): PaginationMeta;
|
|
16
|
-
export type { PaginatedResult, PaginationMeta };
|
|
26
|
+
export type { CursorPaginatedResult, CursorPaginationMeta, PaginatedResult, PaginationMeta };
|
|
17
27
|
export { buildPaginationMeta };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type FailedJobRepository from "./failedJobRepository";
|
|
2
|
+
import type { FailedJobRecord } from "./types";
|
|
3
|
+
declare class FailedJobService {
|
|
4
|
+
private readonly repository;
|
|
5
|
+
constructor(repository: FailedJobRepository);
|
|
6
|
+
recordFailure(input: {
|
|
7
|
+
jobName: string;
|
|
8
|
+
payload: Record<string, unknown>;
|
|
9
|
+
exception: string;
|
|
10
|
+
}): Promise<FailedJobRecord>;
|
|
11
|
+
listRecent(limit?: number): Promise<FailedJobRecord[]>;
|
|
12
|
+
retry(id: number): Promise<FailedJobRecord>;
|
|
13
|
+
flush(): Promise<number>;
|
|
14
|
+
}
|
|
15
|
+
export default FailedJobService;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Job } from "./index";
|
|
2
|
+
type JobFactory = () => Job;
|
|
3
|
+
declare class JobRegistry {
|
|
4
|
+
constructor();
|
|
5
|
+
private readonly factories;
|
|
6
|
+
private readonly instances;
|
|
7
|
+
register(name: string, factory: JobFactory): void;
|
|
8
|
+
resolveName(job: Job): string | undefined;
|
|
9
|
+
track(name: string, job: Job): Job;
|
|
10
|
+
create(name: string): Job | undefined;
|
|
11
|
+
names(): string[];
|
|
12
|
+
}
|
|
13
|
+
declare const jobRegistry: JobRegistry;
|
|
14
|
+
export { JobRegistry, jobRegistry };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type FailedJobService from "./failedJobService";
|
|
2
|
+
interface QueueJobEnvelope {
|
|
3
|
+
name: string;
|
|
4
|
+
payload: Record<string, unknown>;
|
|
5
|
+
attempts?: number;
|
|
6
|
+
}
|
|
7
|
+
declare function runQueueJob(envelope: QueueJobEnvelope, failedJobs: FailedJobService): Promise<void>;
|
|
8
|
+
export type { QueueJobEnvelope };
|
|
9
|
+
export { runQueueJob };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import FailedJobRepository from "./failedJobRepository.ts";
|
|
2
|
+
import FailedJobService from "./failedJobService.ts";
|
|
3
|
+
import type { Job, Queue } from "./index.ts";
|
|
4
|
+
import { jobRegistry } from "./jobRegistry.ts";
|
|
5
|
+
import { QueueWorker, RedisQueue } from "./redisQueue.ts";
|
|
6
|
+
import { ResilientQueue } from "./resilientQueue.ts";
|
|
7
|
+
declare function createFailedJobService(): FailedJobService;
|
|
8
|
+
declare function createTrackedJob<TPayload extends object>(name: string, job: Job<TPayload>): Job<TPayload>;
|
|
9
|
+
declare function createProductionQueue(driver: "sync" | "async" | "redis", options?: {
|
|
10
|
+
redisUrl?: string;
|
|
11
|
+
failedJobs?: FailedJobService;
|
|
12
|
+
registerJobs?: () => void;
|
|
13
|
+
}): Queue;
|
|
14
|
+
declare function createQueueWorker(redisUrl: string, failedJobs?: FailedJobService): QueueWorker;
|
|
15
|
+
export { createFailedJobService, createProductionQueue, createQueueWorker, createTrackedJob, FailedJobRepository, FailedJobService, jobRegistry, QueueWorker, RedisQueue, ResilientQueue, };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type FailedJobService from "./failedJobService";
|
|
2
|
+
import type { Job, Queue, QueuePriority } from "./index";
|
|
3
|
+
import { type QueueJobEnvelope } from "./jobRunner";
|
|
4
|
+
declare const QUEUE_LIST_KEY = "workhub:queue:default";
|
|
5
|
+
declare const QUEUE_HIGH_KEY = "workhub:queue:high";
|
|
6
|
+
declare const QUEUE_LOW_KEY = "workhub:queue:low";
|
|
7
|
+
declare function queueKeyForPriority(priority?: QueuePriority): string;
|
|
8
|
+
declare function parseQueueJobEnvelope(rawPayload: string): QueueJobEnvelope | null;
|
|
9
|
+
declare class RedisQueue implements Queue {
|
|
10
|
+
private readonly client;
|
|
11
|
+
constructor(redisUrl: string);
|
|
12
|
+
dispatch<TPayload extends object>(job: Job<TPayload>, payload: TPayload): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
declare class QueueWorker {
|
|
15
|
+
private readonly failedJobs;
|
|
16
|
+
private readonly timeoutSeconds;
|
|
17
|
+
private running;
|
|
18
|
+
private stopping;
|
|
19
|
+
private readonly client;
|
|
20
|
+
constructor(redisUrl: string, failedJobs: FailedJobService, timeoutSeconds?: number);
|
|
21
|
+
requestStop(): void;
|
|
22
|
+
isRunning(): boolean;
|
|
23
|
+
processNext(): Promise<boolean>;
|
|
24
|
+
run(): Promise<void>;
|
|
25
|
+
close(): void;
|
|
26
|
+
}
|
|
27
|
+
declare function countPendingQueueJobs(redisUrl: string): Promise<number>;
|
|
28
|
+
export type { QueueJobEnvelope };
|
|
29
|
+
export { countPendingQueueJobs, parseQueueJobEnvelope, QUEUE_HIGH_KEY, QUEUE_LIST_KEY, QUEUE_LOW_KEY, QueueWorker, queueKeyForPriority, RedisQueue, };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type FailedJobService from "./failedJobService";
|
|
2
|
+
import type { Job, Queue } from "./index";
|
|
3
|
+
declare class ResilientQueue implements Queue {
|
|
4
|
+
private readonly failedJobs;
|
|
5
|
+
private readonly asyncDispatch;
|
|
6
|
+
constructor(failedJobs: FailedJobService, asyncDispatch?: boolean);
|
|
7
|
+
dispatch<TPayload extends object>(job: Job<TPayload>, payload: TPayload): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
export { ResilientQueue };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
type ScheduledTask = {
|
|
2
|
+
expression: string;
|
|
3
|
+
name: string;
|
|
4
|
+
run: () => void | Promise<void>;
|
|
5
|
+
};
|
|
6
|
+
declare class Schedule {
|
|
7
|
+
private readonly tasks;
|
|
8
|
+
command(expression: string, name: string, run: () => void | Promise<void>): this;
|
|
9
|
+
dueTasks(now?: Date): ScheduledTask[];
|
|
10
|
+
tasksList(): ScheduledTask[];
|
|
11
|
+
}
|
|
12
|
+
declare const appSchedule: Schedule;
|
|
13
|
+
declare function runDueScheduledTasks(schedule?: Schedule, now?: Date): Promise<number>;
|
|
14
|
+
export type { ScheduledTask };
|
|
15
|
+
export { appSchedule, runDueScheduledTasks, Schedule };
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// ../../src/core/errors/http.ts
|
|
3
|
+
class HttpError extends Error {
|
|
4
|
+
status;
|
|
5
|
+
details;
|
|
6
|
+
constructor(status, message, details) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = new.target.name;
|
|
9
|
+
this.status = status;
|
|
10
|
+
this.details = details;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
class BadRequestError extends HttpError {
|
|
15
|
+
constructor(message = "Bad Request", details) {
|
|
16
|
+
super(400, message, details);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
class NotFoundError extends HttpError {
|
|
21
|
+
constructor(message = "Not Found", details) {
|
|
22
|
+
super(404, message, details);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
class ConflictError extends HttpError {
|
|
27
|
+
constructor(message = "Conflict", details) {
|
|
28
|
+
super(409, message, details);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
class UnprocessableEntityError extends HttpError {
|
|
33
|
+
constructor(message = "Unprocessable Entity", details) {
|
|
34
|
+
super(422, message, details);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
class ValidationError extends HttpError {
|
|
39
|
+
constructor(message = "Validation failed", details) {
|
|
40
|
+
super(422, message, details);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
class ForbiddenError extends HttpError {
|
|
45
|
+
constructor(message = "Forbidden", details) {
|
|
46
|
+
super(403, message, details);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
class UnauthorizedError extends HttpError {
|
|
51
|
+
constructor(message = "Unauthorized", details) {
|
|
52
|
+
super(401, message, details);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
class PayloadTooLargeError extends HttpError {
|
|
57
|
+
constructor(message = "Payload Too Large", details) {
|
|
58
|
+
super(413, message, details);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
class PreconditionFailedError extends HttpError {
|
|
63
|
+
constructor(message = "Precondition Failed", details) {
|
|
64
|
+
super(412, message, details);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// ../../src/core/auth/authContext.ts
|
|
69
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
70
|
+
var authContext = new AsyncLocalStorage;
|
|
71
|
+
function runWithAuthUser(user, callback) {
|
|
72
|
+
return authContext.run(user, callback);
|
|
73
|
+
}
|
|
74
|
+
function currentAuthUser() {
|
|
75
|
+
return authContext.getStore() ?? null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// ../../src/core/auth/accessControl.ts
|
|
79
|
+
var ROLE_RANK = {
|
|
80
|
+
member: 1,
|
|
81
|
+
admin: 2,
|
|
82
|
+
owner: 3
|
|
83
|
+
};
|
|
84
|
+
function isGlobalAdmin(user) {
|
|
85
|
+
return user?.role === "admin";
|
|
86
|
+
}
|
|
87
|
+
function hasMinimumOrgRole(role, minimum) {
|
|
88
|
+
if (!role) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
return ROLE_RANK[role] >= ROLE_RANK[minimum];
|
|
92
|
+
}
|
|
93
|
+
function requireAuthenticatedUser() {
|
|
94
|
+
const user = currentAuthUser();
|
|
95
|
+
if (!user) {
|
|
96
|
+
throw new ForbiddenError("Authentication required.");
|
|
97
|
+
}
|
|
98
|
+
return user;
|
|
99
|
+
}
|
|
100
|
+
function resolveUserId(user) {
|
|
101
|
+
const userId = typeof user.id === "number" ? user.id : Number(user.id);
|
|
102
|
+
if (!Number.isInteger(userId) || userId <= 0) {
|
|
103
|
+
throw new ForbiddenError("Invalid authenticated user.");
|
|
104
|
+
}
|
|
105
|
+
return userId;
|
|
106
|
+
}
|
|
107
|
+
export {
|
|
108
|
+
resolveUserId,
|
|
109
|
+
requireAuthenticatedUser,
|
|
110
|
+
isGlobalAdmin,
|
|
111
|
+
hasMinimumOrgRole,
|
|
112
|
+
ROLE_RANK
|
|
113
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// ../../src/core/auth/authContext.ts
|
|
3
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
4
|
+
var authContext = new AsyncLocalStorage;
|
|
5
|
+
function runWithAuthUser(user, callback) {
|
|
6
|
+
return authContext.run(user, callback);
|
|
7
|
+
}
|
|
8
|
+
function currentAuthUser() {
|
|
9
|
+
return authContext.getStore() ?? null;
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
runWithAuthUser,
|
|
13
|
+
currentAuthUser,
|
|
14
|
+
authContext
|
|
15
|
+
};
|