@datrix/api 0.1.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/LICENSE +21 -0
- package/README.md +233 -0
- package/dist/index.d.mts +305 -0
- package/dist/index.d.ts +305 -0
- package/dist/index.js +3354 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +3314 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +59 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import { DefaultPermission, IAuthManager, AuthUser, LoginResult, AuthContext, IUpload, BasePlugin, IApiPlugin, Datrix, QueryContext, PluginContext, SchemaDefinition, DatrixEntry, QueryObject, PermissionAction, ParsedQuery, FallbackInput, ParserError, PermissionValue, PermissionCheckResult, FieldPermissionCheckResult, RawQueryParams, ParserOptions, FallbackWhereClause, PopulateClause, DatrixRecord, DatrixError } from '@datrix/core';
|
|
2
|
+
export { PermissionAction } from '@datrix/core';
|
|
3
|
+
|
|
4
|
+
interface PasswordHash {
|
|
5
|
+
readonly hash: string;
|
|
6
|
+
readonly salt: string;
|
|
7
|
+
}
|
|
8
|
+
interface PasswordConfig {
|
|
9
|
+
readonly iterations?: number;
|
|
10
|
+
readonly keyLength?: number;
|
|
11
|
+
readonly minLength?: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface JwtPayload {
|
|
15
|
+
readonly userId: number;
|
|
16
|
+
readonly role: string;
|
|
17
|
+
readonly iat: number;
|
|
18
|
+
readonly exp: number;
|
|
19
|
+
readonly iss?: string;
|
|
20
|
+
readonly aud?: string;
|
|
21
|
+
readonly [key: string]: unknown;
|
|
22
|
+
}
|
|
23
|
+
interface SessionStore {
|
|
24
|
+
get(sessionId: string): Promise<SessionData | undefined>;
|
|
25
|
+
set(sessionId: string, data: SessionData): Promise<void>;
|
|
26
|
+
delete(sessionId: string): Promise<void>;
|
|
27
|
+
cleanup(): Promise<number>;
|
|
28
|
+
clear(): Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
interface SessionData {
|
|
31
|
+
readonly id: string;
|
|
32
|
+
readonly userId: number;
|
|
33
|
+
readonly role: string;
|
|
34
|
+
readonly createdAt: Date;
|
|
35
|
+
readonly expiresAt: Date;
|
|
36
|
+
readonly lastAccessedAt: Date;
|
|
37
|
+
readonly [key: string]: unknown;
|
|
38
|
+
}
|
|
39
|
+
type JwtAlgorithm = "HS256" | "HS512";
|
|
40
|
+
type TimeUnit = "s" | "m" | "h" | "d";
|
|
41
|
+
type ExpiryString = `${number}${TimeUnit}`;
|
|
42
|
+
interface JwtConfig {
|
|
43
|
+
readonly secret: string;
|
|
44
|
+
readonly expiresIn?: ExpiryString | number;
|
|
45
|
+
readonly algorithm?: JwtAlgorithm;
|
|
46
|
+
readonly issuer?: string;
|
|
47
|
+
readonly audience?: string;
|
|
48
|
+
}
|
|
49
|
+
interface SessionConfig {
|
|
50
|
+
readonly store?: "memory" | SessionStore;
|
|
51
|
+
readonly maxAge?: number;
|
|
52
|
+
readonly checkPeriod?: number;
|
|
53
|
+
readonly prefix?: string;
|
|
54
|
+
}
|
|
55
|
+
interface AuthConfig<TRole extends string = string> {
|
|
56
|
+
readonly roles: readonly TRole[];
|
|
57
|
+
readonly defaultRole: TRole;
|
|
58
|
+
readonly defaultPermission?: DefaultPermission<TRole>;
|
|
59
|
+
readonly jwt?: JwtConfig;
|
|
60
|
+
readonly session?: SessionConfig;
|
|
61
|
+
readonly password?: PasswordConfig;
|
|
62
|
+
readonly authSchemaName?: string;
|
|
63
|
+
readonly userSchema?: {
|
|
64
|
+
readonly name?: string;
|
|
65
|
+
readonly email?: string;
|
|
66
|
+
};
|
|
67
|
+
readonly endpoints?: {
|
|
68
|
+
readonly login?: string;
|
|
69
|
+
readonly register?: string;
|
|
70
|
+
readonly logout?: string;
|
|
71
|
+
readonly me?: string;
|
|
72
|
+
readonly disableRegister?: boolean;
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
declare class JwtStrategy {
|
|
77
|
+
private readonly secret;
|
|
78
|
+
private readonly expiresIn;
|
|
79
|
+
private readonly algorithm;
|
|
80
|
+
private readonly issuer;
|
|
81
|
+
private readonly audience;
|
|
82
|
+
constructor(config: JwtConfig);
|
|
83
|
+
sign(payload: Omit<JwtPayload, "iat" | "exp" | "iss" | "aud">): string;
|
|
84
|
+
verify(token: string): JwtPayload;
|
|
85
|
+
refresh(token: string): string;
|
|
86
|
+
decode(token: string): JwtPayload;
|
|
87
|
+
private createToken;
|
|
88
|
+
private signData;
|
|
89
|
+
private encodeBase64Url;
|
|
90
|
+
private decodeBase64Url;
|
|
91
|
+
private constantTimeCompare;
|
|
92
|
+
private parseExpiry;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
declare class SessionStrategy {
|
|
96
|
+
private readonly store;
|
|
97
|
+
private readonly maxAge;
|
|
98
|
+
private readonly checkPeriod;
|
|
99
|
+
private cleanupTimer;
|
|
100
|
+
constructor(config: SessionConfig);
|
|
101
|
+
create(userId: number, role: string, data?: Record<string, unknown>): Promise<SessionData>;
|
|
102
|
+
get(sessionId: string): Promise<SessionData>;
|
|
103
|
+
update(sessionId: string, data: Partial<Omit<SessionData, "id" | "createdAt">>): Promise<SessionData>;
|
|
104
|
+
delete(sessionId: string): Promise<void>;
|
|
105
|
+
refresh(sessionId: string): Promise<SessionData>;
|
|
106
|
+
validate(sessionId: string): Promise<boolean>;
|
|
107
|
+
startCleanup(): void;
|
|
108
|
+
stopCleanup(): void;
|
|
109
|
+
clear(): Promise<void>;
|
|
110
|
+
private generateSessionId;
|
|
111
|
+
}
|
|
112
|
+
declare class MemorySessionStore implements SessionStore {
|
|
113
|
+
readonly name: "memory";
|
|
114
|
+
private readonly sessions;
|
|
115
|
+
private readonly prefix;
|
|
116
|
+
constructor(prefix?: string);
|
|
117
|
+
get(sessionId: string): Promise<SessionData | undefined>;
|
|
118
|
+
set(sessionId: string, data: SessionData): Promise<void>;
|
|
119
|
+
delete(sessionId: string): Promise<void>;
|
|
120
|
+
cleanup(): Promise<number>;
|
|
121
|
+
clear(): Promise<void>;
|
|
122
|
+
private getKey;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
declare class AuthManager<TRole extends string = string> implements IAuthManager {
|
|
126
|
+
private readonly passwordManager;
|
|
127
|
+
private readonly jwtStrategy;
|
|
128
|
+
private readonly sessionStrategy;
|
|
129
|
+
private readonly config;
|
|
130
|
+
get authConfig(): AuthConfig<TRole>;
|
|
131
|
+
constructor(config: AuthConfig<TRole>);
|
|
132
|
+
hashPassword(password: string): Promise<PasswordHash>;
|
|
133
|
+
verifyPassword(password: string, hash: string, salt: string): Promise<boolean>;
|
|
134
|
+
login(user: AuthUser, options?: {
|
|
135
|
+
createToken?: boolean;
|
|
136
|
+
createSession?: boolean;
|
|
137
|
+
}): Promise<LoginResult>;
|
|
138
|
+
logout(sessionId: string): Promise<void>;
|
|
139
|
+
authenticate(request: Request): Promise<AuthContext | null>;
|
|
140
|
+
private extractToken;
|
|
141
|
+
private extractSessionId;
|
|
142
|
+
getJwtStrategy(): JwtStrategy | undefined;
|
|
143
|
+
getSessionStrategy(): SessionStrategy | undefined;
|
|
144
|
+
destroy(): Promise<void>;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
interface ApiConfig<TRole extends string = string> extends Record<string, unknown> {
|
|
148
|
+
readonly disabled?: boolean;
|
|
149
|
+
readonly prefix?: string;
|
|
150
|
+
readonly defaultPageSize?: number;
|
|
151
|
+
readonly maxPageSize?: number;
|
|
152
|
+
readonly maxPopulateDepth?: number;
|
|
153
|
+
readonly auth?: AuthConfig<TRole>;
|
|
154
|
+
readonly upload?: IUpload;
|
|
155
|
+
readonly excludeSchemas?: readonly string[];
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
declare class ApiPlugin<TRole extends string = string> extends BasePlugin<ApiConfig<TRole>> implements IApiPlugin<TRole> {
|
|
159
|
+
readonly name = "api";
|
|
160
|
+
readonly version = "1.0.0";
|
|
161
|
+
authManager?: AuthManager;
|
|
162
|
+
user: AuthUser | null;
|
|
163
|
+
private datrixInstance?;
|
|
164
|
+
get datrix(): Datrix;
|
|
165
|
+
get upload(): IUpload | undefined;
|
|
166
|
+
setUser(user: AuthUser | null): void;
|
|
167
|
+
private get authConfig();
|
|
168
|
+
private get apiConfig();
|
|
169
|
+
private get authSchemaName();
|
|
170
|
+
private get userSchemaName();
|
|
171
|
+
private get userSchemaEmailField();
|
|
172
|
+
get authDefaultPermission(): DefaultPermission<TRole> | undefined;
|
|
173
|
+
get authDefaultRole(): TRole | undefined;
|
|
174
|
+
get excludeSchemas(): readonly string[];
|
|
175
|
+
private getTableName;
|
|
176
|
+
onCreateQueryContext(context: QueryContext): Promise<QueryContext>;
|
|
177
|
+
init(context: PluginContext): Promise<void>;
|
|
178
|
+
destroy(): Promise<void>;
|
|
179
|
+
getSchemas(): Promise<SchemaDefinition[]>;
|
|
180
|
+
onBeforeQuery<T extends DatrixEntry>(query: QueryObject<T>, context: QueryContext): Promise<QueryObject<T>>;
|
|
181
|
+
onAfterQuery<TResult>(result: TResult, context: QueryContext): Promise<TResult>;
|
|
182
|
+
private createAuthenticationRecord;
|
|
183
|
+
private syncAuthenticationEmail;
|
|
184
|
+
handleRequest(request: Request, datrix: Datrix): Promise<Response>;
|
|
185
|
+
private isAuthPath;
|
|
186
|
+
private handleAuthRequest;
|
|
187
|
+
isEnabled(): boolean;
|
|
188
|
+
isAuthEnabled(): boolean;
|
|
189
|
+
getAuthManager(): AuthManager | undefined;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
declare function handleRequest(datrix: Datrix, request: Request): Promise<Response>;
|
|
193
|
+
|
|
194
|
+
type HttpMethod = "GET" | "POST" | "PATCH" | "PUT" | "DELETE";
|
|
195
|
+
interface RequestContext<TRole extends string = string> {
|
|
196
|
+
readonly schema: SchemaDefinition | null;
|
|
197
|
+
readonly action: PermissionAction;
|
|
198
|
+
readonly id: number | null;
|
|
199
|
+
readonly method: HttpMethod;
|
|
200
|
+
readonly query: ParsedQuery | null;
|
|
201
|
+
readonly body: FallbackInput | null;
|
|
202
|
+
readonly headers: Record<string, string>;
|
|
203
|
+
readonly url: URL;
|
|
204
|
+
readonly request: Request;
|
|
205
|
+
readonly user: AuthUser | null;
|
|
206
|
+
readonly datrix: Datrix;
|
|
207
|
+
readonly api: IApiPlugin<TRole>;
|
|
208
|
+
readonly authEnabled: boolean;
|
|
209
|
+
}
|
|
210
|
+
interface ContextBuilderOptions {
|
|
211
|
+
readonly apiPrefix?: string;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
declare class ContextBuildError extends Error {
|
|
215
|
+
readonly parserError: ParserError;
|
|
216
|
+
constructor(parserError: ParserError);
|
|
217
|
+
}
|
|
218
|
+
declare function buildRequestContext<TRole extends string = string>(request: Request, datrix: Datrix, api: IApiPlugin<TRole>, options?: ContextBuilderOptions): Promise<RequestContext<TRole>>;
|
|
219
|
+
|
|
220
|
+
declare function authenticate(request: Request, authManager?: AuthManager): Promise<AuthUser | null>;
|
|
221
|
+
|
|
222
|
+
declare function evaluatePermissionValue<TRoles extends string>(value: PermissionValue<TRoles> | undefined, ctx: RequestContext): Promise<boolean>;
|
|
223
|
+
declare function checkSchemaPermission<TRoles extends string>(schema: SchemaDefinition<TRoles>, ctx: RequestContext, defaultPermission?: DefaultPermission<TRoles>): Promise<PermissionCheckResult>;
|
|
224
|
+
declare function filterFieldsForRead<TRoles extends string, TRecord extends DatrixEntry>(schema: SchemaDefinition<TRoles>, record: TRecord, ctx: RequestContext): Promise<{
|
|
225
|
+
data: Partial<TRecord>;
|
|
226
|
+
deniedFields: string[];
|
|
227
|
+
}>;
|
|
228
|
+
declare function checkFieldsForWrite<TRoles extends string>(schema: SchemaDefinition<TRoles>, ctx: RequestContext): Promise<FieldPermissionCheckResult>;
|
|
229
|
+
declare function methodToAction(method: string): PermissionAction;
|
|
230
|
+
declare function filterRecordsForRead<TRoles extends string, TRecord extends DatrixEntry>(schema: SchemaDefinition<TRoles>, records: readonly TRecord[], ctx: RequestContext): Promise<Partial<TRecord>[]>;
|
|
231
|
+
|
|
232
|
+
declare function parseQuery(params: RawQueryParams, options?: Partial<ParserOptions>): ParsedQuery<DatrixEntry>;
|
|
233
|
+
|
|
234
|
+
declare function parseWhere(params: RawQueryParams): FallbackWhereClause | undefined;
|
|
235
|
+
|
|
236
|
+
declare function parsePopulate(params: RawQueryParams, maxDepth?: number): PopulateClause<DatrixRecord> | undefined;
|
|
237
|
+
|
|
238
|
+
declare function parseFields(params: RawQueryParams): string[] | "*" | undefined;
|
|
239
|
+
|
|
240
|
+
declare function queryToParams<T extends DatrixEntry = DatrixRecord>(query: ParsedQuery<T> | undefined): string;
|
|
241
|
+
declare function serializeQuery<T extends DatrixEntry = DatrixEntry>(query: ParsedQuery<T>): RawQueryParams;
|
|
242
|
+
|
|
243
|
+
declare function handleCrudRequest<TRole extends string = string>(request: Request, datrix: Datrix, api: IApiPlugin<TRole>, options?: ContextBuilderOptions): Promise<Response>;
|
|
244
|
+
|
|
245
|
+
interface AuthHandlerConfig {
|
|
246
|
+
readonly datrix: Datrix;
|
|
247
|
+
readonly authManager: AuthManager;
|
|
248
|
+
readonly authConfig: AuthConfig;
|
|
249
|
+
}
|
|
250
|
+
declare function createAuthHandlers(config: AuthHandlerConfig): {
|
|
251
|
+
register: (request: Request) => Promise<Response>;
|
|
252
|
+
login: (request: Request) => Promise<Response>;
|
|
253
|
+
logout: (request: Request) => Promise<Response>;
|
|
254
|
+
me: (request: Request) => Promise<Response>;
|
|
255
|
+
};
|
|
256
|
+
declare function createUnifiedAuthHandler(config: AuthHandlerConfig, apiPrefix?: string): (request: Request) => Promise<Response>;
|
|
257
|
+
|
|
258
|
+
declare class DatrixApiError extends DatrixError {
|
|
259
|
+
status: number;
|
|
260
|
+
constructor(message: string, options: ApiErrorOptions);
|
|
261
|
+
toJSON(): {
|
|
262
|
+
status: number;
|
|
263
|
+
type: string;
|
|
264
|
+
message: string;
|
|
265
|
+
code: string;
|
|
266
|
+
timestamp: string;
|
|
267
|
+
operation?: string;
|
|
268
|
+
context?: Record<string, unknown>;
|
|
269
|
+
suggestion?: string;
|
|
270
|
+
expected?: string;
|
|
271
|
+
received?: unknown;
|
|
272
|
+
documentation?: string;
|
|
273
|
+
cause?: {
|
|
274
|
+
readonly message: string;
|
|
275
|
+
readonly name: string;
|
|
276
|
+
};
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
interface ApiErrorOptions {
|
|
280
|
+
code: string;
|
|
281
|
+
status: number;
|
|
282
|
+
operation?: string;
|
|
283
|
+
context?: Record<string, unknown>;
|
|
284
|
+
suggestion?: string;
|
|
285
|
+
expected?: string;
|
|
286
|
+
received?: unknown;
|
|
287
|
+
cause?: Error;
|
|
288
|
+
}
|
|
289
|
+
declare const handlerError: {
|
|
290
|
+
schemaNotFound(tableName: string, availableModels?: string[]): DatrixApiError;
|
|
291
|
+
modelNotSpecified(): DatrixApiError;
|
|
292
|
+
recordNotFound(modelName: string, id: number | string): DatrixApiError;
|
|
293
|
+
invalidBody(reason?: string): DatrixApiError;
|
|
294
|
+
missingId(operation: string): DatrixApiError;
|
|
295
|
+
methodNotAllowed(method: string): DatrixApiError;
|
|
296
|
+
permissionDenied(reason: string, context?: Record<string, unknown>): DatrixApiError;
|
|
297
|
+
unauthorized(reason?: string): DatrixApiError;
|
|
298
|
+
internalError(message: string, cause?: Error): DatrixApiError;
|
|
299
|
+
conflict(reason: string, context?: Record<string, unknown>): DatrixApiError;
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
declare function jsonResponse(data: unknown, status?: number): Response;
|
|
303
|
+
declare function datrixErrorResponse(error: DatrixApiError | DatrixError): Response;
|
|
304
|
+
|
|
305
|
+
export { ApiPlugin, type AuthHandlerConfig, ContextBuildError, type ContextBuilderOptions, DatrixApiError, type HttpMethod, MemorySessionStore, type RequestContext, authenticate, buildRequestContext, checkFieldsForWrite, checkSchemaPermission, createAuthHandlers, createUnifiedAuthHandler, datrixErrorResponse, evaluatePermissionValue, filterFieldsForRead, filterRecordsForRead, handleCrudRequest, handleRequest, handlerError, jsonResponse, methodToAction, parseFields, parsePopulate, parseQuery, parseWhere, queryToParams, serializeQuery };
|