@@ -2,12 +2,20 @@ import { Injectable, type OnModuleDestroy } from '@nestjs/common';
2
2
import { AsyncLocalStorage } from 'async_hooks' ;
3
3
import { BehaviorSubject } from 'rxjs' ;
4
4
import { type Session } from '~/common' ;
5
+ import { AsyncLocalStorageNoContextException } from '~/core/async-local-storage-no-context.exception' ;
5
6
import { NoSessionException } from './no-session.exception' ;
6
7
7
8
/**
8
9
* A service holding the current session / user
9
10
*/
10
11
export abstract class SessionHost {
12
+ /**
13
+ * Retrieve the current session.
14
+ *
15
+ * If this call is not within a {@link withSession} stack, a server error is thrown.
16
+ *
17
+ * If there is no current session, a {@link NoSessionException} is thrown.
18
+ */
11
19
get current ( ) {
12
20
const value = this . current$ . value ;
13
21
if ( value ) {
@@ -16,8 +24,34 @@ export abstract class SessionHost {
16
24
throw new NoSessionException ( ) ;
17
25
}
18
26
27
+ /**
28
+ * Retrieve the current session or undefined.
29
+ *
30
+ * If this call is not within a {@link withSession} stack, a server error is thrown.
31
+ */
32
+ get currentMaybe ( ) {
33
+ return this . current$ . value ;
34
+ }
35
+
36
+ /**
37
+ * Retrieve the current session subject.
38
+ *
39
+ * It must exist, meaning that this call is within a {@link withSession} stack.
40
+ * This subject could still not (yet) have an actual session value.
41
+ */
19
42
abstract get current$ ( ) : BehaviorSubject < Session | undefined > ;
20
43
44
+ /**
45
+ * Retrieve the current session or undefined.
46
+ *
47
+ * This is allowed to be called outside a {@link withSession} stack
48
+ * and will just return undefined.
49
+ */
50
+ abstract get currentIfInCtx ( ) : Session | undefined ;
51
+
52
+ /**
53
+ * Run a function with a given session.
54
+ */
21
55
abstract withSession < R > (
22
56
session : BehaviorSubject < Session | undefined > | Session | undefined ,
23
57
fn : ( ) => R ,
@@ -30,10 +64,18 @@ export class SessionHostImpl extends SessionHost implements OnModuleDestroy {
30
64
BehaviorSubject < Session | undefined >
31
65
> ( ) ;
32
66
67
+ get currentIfInCtx ( ) {
68
+ return this . als . getStore ( ) ?. value ;
69
+ }
70
+
33
71
get current$ ( ) {
34
- return (
35
- this . als . getStore ( ) ?? new BehaviorSubject < Session | undefined > ( undefined )
36
- ) ;
72
+ const subject = this . als . getStore ( ) ;
73
+ if ( ! subject ) {
74
+ throw new AsyncLocalStorageNoContextException (
75
+ 'A session context has not been declared' ,
76
+ ) ;
77
+ }
78
+ return subject ;
37
79
}
38
80
39
81
withSession < R > (
0 commit comments