@ossy/users 1.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/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@ossy/users",
3
+ "description": "User domain — aggregate, events, and validators for the Ossy user model",
4
+ "version": "1.1.0",
5
+ "private": false,
6
+ "type": "module",
7
+ "main": "./src/index.js",
8
+ "module": "./src/index.js",
9
+ "exports": {
10
+ ".": "./src/index.js"
11
+ },
12
+ "author": "Ossy <yourfriends@ossy.se> (https://ossy.se)",
13
+ "license": "MIT",
14
+ "ossy": {
15
+ "src": "./src"
16
+ },
17
+ "publishConfig": {
18
+ "access": "public",
19
+ "registry": "https://registry.npmjs.org"
20
+ },
21
+ "dependencies": {
22
+ "nanoid": "^5.1.11"
23
+ },
24
+ "files": [
25
+ "/src",
26
+ "README.md"
27
+ ],
28
+ "gitHead": "5f1feadf3b630aa96ec61f1d48c11e0e1aa4b095"
29
+ }
package/src/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from './user.aggregate.js'
2
+ export * from './users.events.js'
3
+ export * from './users.validators.js'
@@ -0,0 +1,84 @@
1
+
2
+ export class User {
3
+
4
+ static AggregateType = 'User'
5
+
6
+ static View(events, savedState = {}) {
7
+ return events.reduce((user, event) => {
8
+
9
+ switch (event.type) {
10
+
11
+ case 'SignedUp':
12
+ return {
13
+ ...user,
14
+ id: event.aggregateId,
15
+ type: event.payload.type,
16
+ created: event.created,
17
+ email: event.payload.email,
18
+ verificationToken: event.payload.verificationToken,
19
+ firstName: event.payload.firstName,
20
+ lastName: event.payload.lastName,
21
+ workspaces: user.workspaces ?? []
22
+ }
23
+
24
+ case 'SignInVerified':
25
+ return {
26
+ ...user,
27
+ verifiedAt: user.verifiedAt ?? event.created
28
+ }
29
+
30
+ case 'NameUpdated': {
31
+ const firstName = event.payload.firstName || user.firstName
32
+ const lastName = event.payload.lastName || user.lastName
33
+ return {
34
+ ...user,
35
+ firstName,
36
+ lastName
37
+ }
38
+ }
39
+
40
+ // TODO: #415
41
+ // case 'EmailUpdated':
42
+ // return {
43
+ // ...user,
44
+ // email: event.payload.email
45
+ // }
46
+
47
+ case 'WorkspaceJoined':
48
+ return {
49
+ ...user,
50
+ workspaces: [...new Set([...(user.workspaces ?? []), event.payload.workspaceId])]
51
+ }
52
+
53
+ case 'WorkspaceLeft':
54
+ return {
55
+ ...user,
56
+ workspaces: (user.workspaces ?? []).filter(id => id !== event.payload.workspaceId)
57
+ }
58
+
59
+ default:
60
+ return user
61
+
62
+ }
63
+ }, savedState)
64
+ }
65
+
66
+ static UserForWorkspace(events, aggregate) {
67
+ const user = User.View(events, aggregate)
68
+ return {
69
+ id: user.id,
70
+ firstName: user.firstName,
71
+ lastName: user.lastName,
72
+ email: user.email,
73
+ type: user.type
74
+ }
75
+ }
76
+
77
+ static History(events) {
78
+ // TODO: add aggregate
79
+ return events
80
+ .sort((a, b) => b.created - a.created)
81
+ .map(event => ({ type: event.type, created: event.created }))
82
+ }
83
+
84
+ }
@@ -0,0 +1,121 @@
1
+ import { nanoid } from 'nanoid'
2
+
3
+ /**
4
+ * Database queries related to workspace events
5
+ * @class
6
+ */
7
+ export class UsersEvents {
8
+
9
+ static SignedUp({
10
+ email,
11
+ lastName,
12
+ firstName,
13
+ userId: _userId,
14
+ type = 'User' // is 'User' or 'Bot'
15
+ }) {
16
+ const userId = _userId || nanoid()
17
+ return ({
18
+ type: 'SignedUp',
19
+ aggregateId: userId,
20
+ createdBy: userId,
21
+ payload: {
22
+ email: email,
23
+ lastName,
24
+ firstName,
25
+ type: type
26
+ }
27
+ })
28
+ }
29
+
30
+ // static SignInRequested({ createdBy }) {
31
+ // return ({
32
+ // type: 'SignInRequested',
33
+ // createdBy: createdBy,
34
+ // payload: { verificationToken: TokenService.new() }
35
+ // })
36
+ // }
37
+
38
+ /** Same JWT as the `auth` cookie / WebAuth token aggregate — see `UsersQueries.getIdByAuthToken`. */
39
+ static SignInVerified({ createdBy, token }) {
40
+ return ({
41
+ type: 'SignInVerified',
42
+ createdBy,
43
+ payload: { token }
44
+ })
45
+ }
46
+
47
+ // static SignedOff({ token, createdBy }) {
48
+ // return ({
49
+ // type: 'SignedOff',
50
+ // createdBy: createdBy,
51
+ // payload: { token }
52
+ // })
53
+ // }
54
+
55
+ // static ApiTokenCreated({ name, createdBy, description, token, expiresAt }) {
56
+ // return ({
57
+ // type: 'ApiTokenCreated',
58
+ // createdBy: createdBy,
59
+ // payload: {
60
+ // name,
61
+ // expiresAt: expiresAt,
62
+ // description: description,
63
+ // token: token
64
+ // }
65
+ // })
66
+ // }
67
+
68
+ // static ApiTokenInvalidated({ createdBy, tokenId }) {
69
+ // return ({
70
+ // type: 'ApiTokenInvalidated',
71
+ // createdBy: createdBy,
72
+ // payload: { tokenId }
73
+ // })
74
+ // }
75
+
76
+ static NameUpdated({ lastName, firstName, createdBy }) {
77
+ return ({
78
+ type: 'NameUpdated',
79
+ createdBy: createdBy,
80
+ payload: {
81
+ lastName,
82
+ firstName
83
+ }
84
+ })
85
+ }
86
+
87
+ // TODO: #415
88
+ // static EmailChangeRequested({ email, createdBy }) {
89
+ // return ({
90
+ // type: 'EmailUpdated',
91
+ // createdBy: createdBy,
92
+ // payload: { email }
93
+ // })
94
+ // }
95
+
96
+ // TODO: #415
97
+ // static EmailUpdated({ email, createdBy }) {
98
+ // return ({
99
+ // type: 'EmailUpdated',
100
+ // createdBy: createdBy,
101
+ // payload: { email }
102
+ // })
103
+ // }
104
+
105
+ static WorkspaceJoined({ workspaceId, createdBy }) {
106
+ return ({
107
+ type: 'WorkspaceJoined',
108
+ createdBy,
109
+ payload: { workspaceId }
110
+ })
111
+ }
112
+
113
+ static WorkspaceLeft({ workspaceId, createdBy }) {
114
+ return ({
115
+ type: 'WorkspaceLeft',
116
+ createdBy,
117
+ payload: { workspaceId }
118
+ })
119
+ }
120
+
121
+ }
@@ -0,0 +1,6 @@
1
+ import { User } from './user.aggregate.js'
2
+
3
+ export class UsersValidators {
4
+
5
+
6
+ }