@elysiumjs/core 0.3.0 → 0.3.2

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/README.md CHANGED
@@ -109,4 +109,4 @@ Feel free to open issues for any bugs or questions you may have. Pull requests a
109
109
 
110
110
  ## License
111
111
 
112
- This project is licensed under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for more information.
112
+ This project is licensed under the Apache License, Version 2.0. See the [LICENSE](../../LICENSE) file for more information.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elysiumjs/core",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "license": "Apache-2.0",
5
5
  "description": "A super-charged web framework for Bun, built on top of ElysiaJS.",
6
6
  "private": false,
@@ -41,7 +41,7 @@
41
41
  "@types/bun": "latest"
42
42
  },
43
43
  "peerDependencies": {
44
- "typescript": "^5"
44
+ "typescript": "^5.8.3"
45
45
  },
46
46
  "trustedDependencies": [
47
47
  "es5-ext"
package/src/env.ts CHANGED
@@ -32,10 +32,14 @@ export namespace Env {
32
32
  * Gets the value of an environment variable.
33
33
  * @author Axel Nana <axel.nana@workbud.com>
34
34
  * @param name The name of the environment variable.
35
+ * @param defaultValue The default value to return if the environment variable is not set.
35
36
  * @returns The value of the environment variable.
36
37
  */
37
- export const get = <TKey extends keyof AppEnv>(name: TKey): AppEnv[TKey] => {
38
- return env.get(name) as AppEnv[TKey];
38
+ export const get = <TKey extends keyof AppEnv>(
39
+ name: TKey,
40
+ defaultValue?: AppEnv[TKey]
41
+ ): AppEnv[TKey] => {
42
+ return (env.get(name) ?? defaultValue) as AppEnv[TKey];
39
43
  };
40
44
 
41
45
  /**
package/src/middleware.ts CHANGED
@@ -30,7 +30,7 @@ import { Symbols } from './utils';
30
30
  export const executeMiddlewareChain = (
31
31
  middlewares: Middleware[],
32
32
  context: any,
33
- method: keyof Middleware
33
+ method: Exclude<keyof Middleware, 'guards'>
34
34
  ): Promise<any> => {
35
35
  return Application.context.run(
36
36
  new Map([
@@ -102,6 +102,25 @@ export abstract class Middleware {
102
102
  };
103
103
  }
104
104
 
105
+ /**
106
+ * Creates a guarded version of the middleware.
107
+ * @author Axel Nana <axel.nana@workbud.com>
108
+ * @param guards The list of guards for the middleware.
109
+ * @returns A middleware class decorated with guards.
110
+ */
111
+ public static guards(guards: string[]): Class<Middleware> {
112
+ class GuardedMiddleware extends this {}
113
+ Reflect.defineMetadata(Symbols.middlewareGuards, guards, GuardedMiddleware);
114
+ return GuardedMiddleware;
115
+ }
116
+
117
+ /**
118
+ * Gets the list of guards for the middleware.
119
+ */
120
+ public get guards(): string[] {
121
+ return Reflect.getMetadata(Symbols.middlewareGuards, this.constructor) ?? [];
122
+ }
123
+
105
124
  /**
106
125
  * Called after the request has been handled, but before the response is sent.
107
126
  * @param ctx The request context.
package/src/model.ts CHANGED
@@ -101,6 +101,7 @@ const parseTypes = (element: PgColumn) => {
101
101
  * @template TTable The drizzle's table schema wrapped by the repository.
102
102
  */
103
103
  export type ModelClass<
104
+ TTableName extends string,
104
105
  TColumnsMap extends Record<string, PgColumnBuilderBase>,
105
106
  TTable extends PgTable = ReturnType<typeof pgTable<string, TColumnsMap>>
106
107
  > = {
@@ -128,7 +129,7 @@ export type ModelClass<
128
129
  /**
129
130
  * The name of the table wrapped by the model.
130
131
  */
131
- readonly tableName: string;
132
+ readonly tableName: TTableName;
132
133
 
133
134
  /**
134
135
  * The table columns configuration.
@@ -173,8 +174,11 @@ export type ModelClass<
173
174
  * @param tableName The name of the table.
174
175
  * @param columns The table columns configuration.
175
176
  */
176
- export const Model = <TColumnsMap extends Record<string, PgColumnBuilderBase>>(
177
- tableName: string,
177
+ export const Model = <
178
+ TTableName extends string,
179
+ TColumnsMap extends Record<string, PgColumnBuilderBase>
180
+ >(
181
+ tableName: TTableName,
178
182
  columns: TColumnsMap
179
183
  ) => {
180
184
  const table = pgTable(tableName, columns);
@@ -198,7 +202,7 @@ export const Model = <TColumnsMap extends Record<string, PgColumnBuilderBase>>(
198
202
  /**
199
203
  * The drizzle's table schema wrapped by this model.
200
204
  */
201
- public static get table(): ReturnType<typeof pgTable<string, TColumnsMap>> {
205
+ public static get table(): ReturnType<typeof pgTable<TTableName, TColumnsMap>> {
202
206
  // If we are not inside an Application context, we can't use the tenancy system
203
207
  if (!Application.instance || !Application.context.getStore) {
204
208
  return table;
@@ -207,7 +211,7 @@ export const Model = <TColumnsMap extends Record<string, PgColumnBuilderBase>>(
207
211
  if (this.supportTenancy) {
208
212
  const tenant = Tenancy.getCurrentTenant() ?? 'public';
209
213
  // @ts-expect-error typeof this strangely doesn't match the ModelClass type
210
- return Tenancy.withTenant(tenant, this);
214
+ return Tenancy.wrapTenant(tenant, this);
211
215
  }
212
216
 
213
217
  return table;
@@ -292,9 +296,13 @@ export namespace Tenancy {
292
296
  * @param model The model class that wraps the `PgTable`.
293
297
  * @returns The drizzle's table schema wrapped by the tenant.
294
298
  */
295
- export const withTenant = <
296
- T extends ModelClass<TColumnsMap>,
299
+ export const wrapTenant = <
300
+ T extends ModelClass<TTableName, TColumnsMap>,
301
+ TTableName extends string = T extends ModelClass<infer TTableName, infer TColumnsMap>
302
+ ? TTableName
303
+ : string,
297
304
  TColumnsMap extends Record<string, PgColumnBuilderBase> = T extends ModelClass<
305
+ TTableName,
298
306
  infer TColumnsMap
299
307
  >
300
308
  ? TColumnsMap
@@ -302,21 +310,21 @@ export namespace Tenancy {
302
310
  >(
303
311
  tenant: string,
304
312
  model: T
305
- ): ReturnType<typeof pgTable<string, TColumnsMap>> => {
313
+ ): ReturnType<typeof pgTable<TTableName, TColumnsMap>> => {
306
314
  if (tenant === 'public') {
307
315
  return pgTable(model.tableName, model.columns);
308
316
  }
309
317
 
310
318
  const tableName = `${tenant}.${model.tableName}`;
311
319
  if (tenantSchemas.has(tableName)) {
312
- return tenantSchemas.get(tableName)! as ReturnType<typeof pgTable<string, TColumnsMap>>;
320
+ return tenantSchemas.get(tableName)! as ReturnType<typeof pgTable<TTableName, TColumnsMap>>;
313
321
  }
314
322
 
315
323
  const tenantSchema = getTenantSchema(tenant);
316
324
  const schemaTable = tenantSchema.table(model.tableName, model.columns);
317
325
  tenantSchemas.set(tableName, schemaTable);
318
326
 
319
- return schemaTable as unknown as ReturnType<typeof pgTable<string, TColumnsMap>>;
327
+ return schemaTable as unknown as ReturnType<typeof pgTable<TTableName, TColumnsMap>>;
320
328
  };
321
329
 
322
330
  /**
@@ -333,4 +341,20 @@ export namespace Tenancy {
333
341
 
334
342
  return tenantSchema;
335
343
  };
344
+
345
+ /**
346
+ * Runs the given callback in a context with the given tenant.
347
+ * @author Axel Nana <axel.nana@workbud.com>
348
+ * @param tenant The name of the tenant.
349
+ * @param callback The callback to run.
350
+ * @returns The result of the callback.
351
+ */
352
+ export const withTenant = <TReturn>(tenant: string, callback: () => TReturn): TReturn => {
353
+ const currentStore = Application.context.getStore();
354
+
355
+ const newStore = new Map(currentStore);
356
+ newStore.set('tenant', tenant);
357
+
358
+ return Application.context.run(newStore, callback);
359
+ };
336
360
  }
package/src/redis.ts CHANGED
@@ -26,7 +26,7 @@ import { Service } from './service';
26
26
  * Properties used to create a new redis connection.
27
27
  * @author Axel Nana <axel.nana@workbud.com>
28
28
  */
29
- export type RedisConnectionProps = Bun.RedisOptions;
29
+ export type RedisConnectionProps = Bun.RedisOptions & { url: string };
30
30
 
31
31
  /**
32
32
  * Keyv adapter for redis. This adapter is based on the Bun's Redis client.
@@ -361,7 +361,7 @@ export namespace Redis {
361
361
  * @param config The configuration for the redis connection.
362
362
  * @returns The newly created and registered redis connection.
363
363
  */
364
- export const registerConnection = (name: string, config: Bun.RedisOptions) => {
364
+ export const registerConnection = (name: string, config: RedisConnectionProps) => {
365
365
  if (Service.exists(getConnectionName(name))) {
366
366
  // TODO: Use logger service here
367
367
  console.error(`A connection with the name ${name} has already been registered.`);
package/src/utils.ts CHANGED
@@ -17,25 +17,27 @@ import type { Elysia } from 'elysia';
17
17
  import { isObject, isPrimitive } from 'radash';
18
18
 
19
19
  export namespace Symbols {
20
- export const app = Symbol('app');
20
+ export const app = Symbol('elysium:Application');
21
21
 
22
- export const controller = Symbol('controller');
22
+ export const controller = Symbol('elysium:Controller');
23
23
 
24
- export const middlewares = Symbol('middlewares');
24
+ export const middlewares = Symbol('elysium:MiddlewaresList');
25
25
 
26
- export const services = Symbol('services');
26
+ export const services = Symbol('elysium:ServicesList');
27
27
 
28
- export const websocket = Symbol('websocket');
28
+ export const websocket = Symbol('elysium:WebSocket');
29
29
 
30
- export const wamp = Symbol('wamp');
30
+ export const wamp = Symbol('elysium:Wamp');
31
31
 
32
- export const http = Symbol('http');
32
+ export const http = Symbol('elysium:Http');
33
33
 
34
- export const job = Symbol('job');
34
+ export const job = Symbol('elysium:Job');
35
35
 
36
- export const arg = Symbol('command:arguments');
36
+ export const arg = Symbol('elysium:CommandArguments');
37
37
 
38
- export const elysiaPlugin = Symbol('elysia:plugin');
38
+ export const elysiaPlugin = Symbol('elysium:ElysiaPlugin');
39
+
40
+ export const middlewareGuards = Symbol('elysium:MiddlewareGuards');
39
41
  }
40
42
 
41
43
  export const nextTick = () => new Promise((resolve) => process.nextTick(resolve));