@ossy/workspaces 1.4.0 → 1.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ossy/workspaces",
3
3
  "description": "Workspaces feature package — create, select, and manage workspaces, users, and invitations",
4
- "version": "1.4.0",
4
+ "version": "1.5.0",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
7
7
  "module": "./src/index.js",
@@ -27,5 +27,5 @@
27
27
  "/src",
28
28
  "README.md"
29
29
  ],
30
- "gitHead": "ed72d972761405ecc4e12804aefa77f763aa4646"
30
+ "gitHead": "5f1feadf3b630aa96ec61f1d48c11e0e1aa4b095"
31
31
  }
package/src/index.js CHANGED
@@ -7,3 +7,5 @@ export { Users } from './Users.jsx'
7
7
  export { AuthenticationGuard } from './AuthenticationGuard.jsx'
8
8
  export { patchUserWorkspaceId } from './patchUserWorkspaceId.js'
9
9
  export { Definition } from './Definition.js'
10
+ export { Workspace } from './workspace.aggregate.js'
11
+ export { WorkspacesEvents } from './workspaces.events.js'
@@ -0,0 +1,116 @@
1
+ export class Workspace {
2
+
3
+ static AggregateType = 'Workspace'
4
+
5
+ static View(events, state = {}) {
6
+ return events
7
+ .reduce((workspace, event) => {
8
+
9
+ switch (event.type) {
10
+
11
+ case 'Created':
12
+ return {
13
+ ...workspace,
14
+ id: event.aggregateId,
15
+ name: event.payload.name,
16
+ createdBy: event.createdBy,
17
+ created: event.created,
18
+ apiTokens: [],
19
+ users: [event.createdBy],
20
+ invitations: [],
21
+ resourceTemplates: [],
22
+ services: {
23
+ // '@ossy/visual-content-classifiers': true,
24
+ '@ossy/tasks/resize-common-web': true,
25
+ '@ossy/apps': true,
26
+ '@ossy/domains': true,
27
+ }
28
+ }
29
+
30
+ case 'ResourceTemplatesImported':
31
+ return {
32
+ ...workspace,
33
+ resourceTemplates: [
34
+ ...(event.payload.templates || []),
35
+ ]
36
+ }
37
+
38
+ case 'UserInvited': {
39
+ const oneWeek = 1000 * 60 * 60 * 24 * 7
40
+ const expired = event.payload.expiresAt < Date.now()
41
+ // show expired workspace invitations for 7 days
42
+ const showInvitation = (event.payload.expiresAt + oneWeek) > Date.now()
43
+
44
+ if (!showInvitation) {
45
+ return workspace
46
+ }
47
+
48
+ return {
49
+ ...workspace,
50
+ invitations: [
51
+ ...(workspace.invitations || []),
52
+ {
53
+ email: event.payload.email,
54
+ invitedAt: event.created,
55
+ expiresAt: event.payload.expiresAt,
56
+ expired: expired
57
+ }
58
+ ]
59
+ }
60
+ }
61
+
62
+ case 'UserInvitationAccepted': {
63
+ return {
64
+ ...workspace,
65
+ users: [
66
+ ...workspace.users,
67
+ event.createdBy
68
+ ],
69
+ invitations: workspace.invitations.filter(invitation => invitation.email !== event.payload.email)
70
+ }
71
+ }
72
+
73
+ case 'ApiTokenCreated':
74
+ return {
75
+ ...workspace,
76
+ apiTokens: [
77
+ ...(apiTokens || []),
78
+ {
79
+ id: event.id,
80
+ description: event.payload.description
81
+ }
82
+ ]
83
+ }
84
+
85
+ case 'ServiceEnabled':
86
+ return {
87
+ ...workspace,
88
+ services: {
89
+ ...(workspace.services || {}),
90
+ [event.payload.service]: true
91
+ }
92
+ }
93
+
94
+ case 'ServiceDisabled':
95
+ return {
96
+ ...workspace,
97
+ services: {
98
+ ...(workspace.services || {}),
99
+ [event.payload.service]: false
100
+ }
101
+ }
102
+
103
+ case 'UserRemoved':
104
+ return {
105
+ ...workspace,
106
+ users: (workspace.users || []).filter(id => id !== event.payload.userId)
107
+ }
108
+
109
+ default:
110
+ return workspace
111
+
112
+ }
113
+ }, state)
114
+ }
115
+
116
+ }
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Field
3
+ * @typedef {Object} Field
4
+ * @property {string} type - field type
5
+ * @property {string} name - name of field
6
+ */
7
+
8
+ /**
9
+ * ResourceTemplate
10
+ * @typedef {Object} ResourceTemplate
11
+ * @property {string} name - Displayname of the resource template
12
+ * @property {Field[]} fields - Allowed fields
13
+ */
14
+
15
+
16
+ /**
17
+ * @class
18
+ */
19
+ export class WorkspacesEvents {
20
+
21
+ /**
22
+ * Return type of WorkspacesEvents.Created
23
+ * @typedef {Object} Created
24
+ * @property {string} type - Created
25
+ * @property {string} createdBy - userId of user who created the workspace
26
+ * @property {CreatedPayload} payload - event payload
27
+ */
28
+
29
+ /**
30
+ * Payload of Workspace.Created event
31
+ * @typedef {Object} CreatedPayload
32
+ * @property {string} name - Name of workspace
33
+ */
34
+
35
+ /**
36
+ * Input for WorkspacesEvents.Created
37
+ * @typedef {Object} CreatedInput
38
+ * @property {string} name - Name of workspace
39
+ * @property {string} createdBy - userId of user who created the workspace
40
+ */
41
+
42
+ /**
43
+ * Use this to indicate that a new workspace have been created
44
+ *
45
+ * @param {CreatedInput} input
46
+ * @return {Created} - Workspace created event
47
+ *
48
+ * @example
49
+ * const name = 'ossy.se'
50
+ * const createdBy = 'fake-user-id-123'
51
+ *
52
+ * const event = WorkspacesEvents.Created({ name, createdBy })
53
+ *
54
+ * Aggregate.Of(Workspace, event)
55
+ */
56
+ static Created({ createdBy, name }) {
57
+ return ({
58
+ type: 'Created',
59
+ createdBy: createdBy,
60
+ payload: {
61
+ name: name
62
+ }
63
+ })
64
+ }
65
+
66
+ /**
67
+ * Return type of WorkspacesEvents.ResourceTemplatesImported
68
+ * @typedef {Object} ResourceTemplatesImported
69
+ * @property {string} type - ResourceTemplatesImported
70
+ * @property {string} createdBy - userId of user who created the workspace
71
+ * @property {ResourceTemplate[]} payload - event payload
72
+ */
73
+
74
+ /**
75
+ * Input for WorkspacesEvents.Created
76
+ * @typedef {Object} ResourceTemplatesImportedInput
77
+ * @property {ResourceTemplate[]} templates - List of resource templates
78
+ * @property {string} createdBy - userId of user who created the workspace
79
+ */
80
+
81
+ /**
82
+ * Use this to save imported resource templates
83
+ *
84
+ * @param {ResourceTemplatesImportedInput} input
85
+ * @return {ResourceTemplatesImported} - Resource templates imported event
86
+ *
87
+ * @example
88
+ * const templates = []
89
+ * const createdBy = 'fake-user-123'
90
+ *
91
+ * const event = WorkspacesEvents.Created({ templates, createdBy })
92
+ *
93
+ * Aggregate.Of(Workspace, userId)
94
+ * .then(Aggregate.Add(event))
95
+ */
96
+ static ResourceTemplatesImported({ createdBy, templates }) {
97
+ return ({
98
+ type: 'ResourceTemplatesImported',
99
+ createdBy: createdBy,
100
+ payload: {
101
+ templates: templates
102
+ }
103
+ })
104
+ }
105
+
106
+ // Not in use atm, use API TOKENS in the user aggregate instead.
107
+ // Caller is responsible for generating the token value.
108
+ static ApiTokenCreated({ createdBy, description, token }) {
109
+ return ({
110
+ type: 'ApiTokenCreated',
111
+ createdBy: createdBy,
112
+ payload: {
113
+ description: description,
114
+ token: token
115
+ }
116
+ })
117
+ }
118
+
119
+
120
+ static UserInvited({ createdBy, email, expiresAt }) {
121
+ return ({
122
+ type: 'UserInvited',
123
+ createdBy: createdBy,
124
+ payload: {
125
+ email: email,
126
+ expiresAt: new Date().getTime() + 1000 * 60 * 60 * 24 * 7, // One week
127
+ }
128
+ })
129
+ }
130
+
131
+ static UserInvitationAccepted({ createdBy, email }) {
132
+ return ({
133
+ type: 'UserInvitationAccepted',
134
+ createdBy: createdBy,
135
+ payload: {
136
+ email: email
137
+ }
138
+ })
139
+ }
140
+
141
+ static ServiceEnabled({ createdBy, service }) {
142
+ return ({
143
+ type: 'ServiceEnabled',
144
+ createdBy: createdBy,
145
+ payload: {
146
+ service: service
147
+ }
148
+ })
149
+ }
150
+
151
+ static ServiceDisabled({ createdBy, service }) {
152
+ return ({
153
+ type: 'ServiceDisabled',
154
+ createdBy: createdBy,
155
+ payload: {
156
+ service: service
157
+ }
158
+ })
159
+ }
160
+
161
+ static UserRemoved({ createdBy, userId }) {
162
+ return ({
163
+ type: 'UserRemoved',
164
+ createdBy: createdBy,
165
+ payload: {
166
+ userId: userId
167
+ }
168
+ })
169
+ }
170
+
171
+ }