@neuralinnovations/dataisland-sdk 0.0.1-dev7 → 0.0.1-dev9

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.
Files changed (79) hide show
  1. package/.github/workflows/docs.yml +32 -0
  2. package/.github/workflows/format.yml +42 -0
  3. package/.github/workflows/publish-npm.yml +19 -16
  4. package/.github/workflows/tests.yml +38 -0
  5. package/.github/workflows/version.yml +44 -0
  6. package/LICENSE +201 -0
  7. package/README.md +37 -2
  8. package/docs/classes/BasicCredential.md +1 -1
  9. package/docs/classes/BearerCredential.md +1 -1
  10. package/docs/classes/Chat.md +34 -6
  11. package/docs/classes/Chats.md +87 -1
  12. package/docs/classes/CredentialBase.md +1 -1
  13. package/docs/classes/DataIslandApp.md +1 -1
  14. package/docs/classes/DebugCredential.md +1 -1
  15. package/docs/classes/DefaultCredential.md +1 -1
  16. package/docs/classes/DisposableContainer.md +1 -1
  17. package/docs/classes/EventDispatcher.md +1 -1
  18. package/docs/classes/File.md +1 -1
  19. package/docs/classes/Files.md +2 -2
  20. package/docs/classes/FilesPage.md +1 -1
  21. package/docs/classes/Group.md +19 -1
  22. package/docs/classes/Groups.md +27 -3
  23. package/docs/classes/Lifetime.md +1 -1
  24. package/docs/classes/Organization.md +37 -1
  25. package/docs/classes/Organizations.md +1 -1
  26. package/docs/classes/UserProfile.md +1 -1
  27. package/docs/classes/Workspace.md +1 -1
  28. package/docs/classes/Workspaces.md +6 -2
  29. package/docs/enums/ChatAnswerType.md +22 -0
  30. package/docs/enums/ChatsEvent.md +1 -1
  31. package/docs/enums/FilesEvent.md +1 -1
  32. package/docs/enums/GroupEvent.md +3 -1
  33. package/docs/enums/OrganizationsEvent.md +1 -1
  34. package/docs/enums/UserEvent.md +1 -1
  35. package/docs/enums/WorkspaceEvent.md +1 -1
  36. package/docs/enums/WorkspacesEvent.md +1 -1
  37. package/docs/interfaces/Disposable.md +1 -1
  38. package/docs/interfaces/Event.md +1 -1
  39. package/docs/interfaces/EventSubscriber.md +1 -1
  40. package/docs/interfaces/Input.md +1 -1
  41. package/docs/modules.md +5 -3
  42. package/package.json +6 -2
  43. package/src/dataIslandApp.ts +2 -2
  44. package/src/dto/chatResponse.ts +54 -55
  45. package/src/dto/workspacesResponse.ts +2 -2
  46. package/src/index.ts +13 -13
  47. package/src/internal/app.impl.ts +2 -2
  48. package/src/services/organizationService.ts +2 -2
  49. package/src/services/userProfileService.ts +2 -2
  50. package/src/storages/chats/answer.impl.ts +163 -0
  51. package/src/storages/chats/answer.ts +42 -0
  52. package/src/storages/chats/chat.impl.ts +87 -0
  53. package/src/storages/chats/chat.ts +38 -0
  54. package/src/storages/chats/chats.impl.ts +142 -0
  55. package/src/storages/chats/chats.ts +47 -0
  56. package/src/storages/{file.impl.ts → files/file.impl.ts} +5 -5
  57. package/src/storages/{file.ts → files/file.ts} +1 -1
  58. package/src/storages/{files.impl.ts → files/files.impl.ts} +6 -6
  59. package/src/storages/{files.ts → files/files.ts} +2 -2
  60. package/src/storages/{groups.impl.ts → groups/groups.impl.ts} +86 -97
  61. package/src/storages/groups/groups.ts +101 -0
  62. package/src/storages/{organization.impl.ts → organizations/organization.impl.ts} +34 -7
  63. package/src/storages/{organization.ts → organizations/organization.ts} +13 -2
  64. package/src/storages/{organizations.impl.ts → organizations/organizations.impl.ts} +10 -4
  65. package/src/storages/{organizations.ts → organizations/organizations.ts} +1 -1
  66. package/src/storages/{userProfile.impl.ts → user/userProfile.impl.ts} +1 -1
  67. package/src/storages/{userProfile.ts → user/userProfile.ts} +1 -1
  68. package/src/storages/{workspace.impl.ts → workspaces/workspace.impl.ts} +7 -7
  69. package/src/storages/{workspace.ts → workspaces/workspace.ts} +3 -3
  70. package/src/storages/{workspaces.impl.ts → workspaces/workspaces.impl.ts} +11 -11
  71. package/src/storages/{workspaces.ts → workspaces/workspaces.ts} +2 -2
  72. package/test/chats.test.ts +48 -0
  73. package/test/organization.test.ts +13 -1
  74. package/test/setup.ts +7 -0
  75. package/docs/enums/ChatAnswer.md +0 -22
  76. package/src/storages/chat.ts +0 -21
  77. package/src/storages/chats.ts +0 -17
  78. package/src/storages/groups.ts +0 -43
  79. /package/src/storages/{filesPage.ts → files/filesPage.ts} +0 -0
@@ -0,0 +1,142 @@
1
+ import { Context } from "../../context"
2
+ import { ChatDto, ChatListResponse } from "../../dto/chatResponse"
3
+ import { ResponseUtils } from "../../services/responseUtils"
4
+ import { RpcService } from "../../services/rpcService"
5
+ import { OrganizationImpl } from "../organizations/organization.impl"
6
+ import { OrganizationId } from "../organizations/organizations"
7
+ import { Chat } from "./chat"
8
+ import { ChatImpl } from "./chat.impl"
9
+ import { Chats, ChatsEvent } from "./chats"
10
+
11
+ export class ChatsImpl extends Chats {
12
+ private readonly _chats: Chat[] = []
13
+
14
+ constructor(
15
+ public readonly organization: OrganizationImpl,
16
+ private readonly context: Context
17
+ ) {
18
+ super()
19
+ }
20
+
21
+ async initFrom(organizationId: OrganizationId): Promise<void> {
22
+ // init chats from the server's response
23
+ const limit = 100
24
+ const page = 0
25
+ const response = await this.context
26
+ .resolve(RpcService)
27
+ ?.requestBuilder("api/v1/Chats/list")
28
+ .searchParam("organizationId", organizationId)
29
+ .searchParam("limit", limit.toString())
30
+ .searchParam("page", page.toString())
31
+ .sendGet()
32
+
33
+ // check response status
34
+ if (ResponseUtils.isFail(response)) {
35
+ await ResponseUtils.throwError(
36
+ `Chats list org id:${organizationId}, page:${page}, limit:${limit}, failed`,
37
+ response
38
+ )
39
+ }
40
+
41
+ // parse chats from the server's response
42
+ const chats = (await response!.json()) as ChatListResponse
43
+
44
+ // init chats
45
+ for (const cht of chats.chats) {
46
+ // create chat implementation
47
+ const chat = await new ChatImpl(this.context, this.organization).initFrom(cht)
48
+
49
+ // add chat to the collection
50
+ this._chats.push(chat)
51
+
52
+ // dispatch event
53
+ this.dispatch({
54
+ type: ChatsEvent.ADDED,
55
+ data: chat
56
+ })
57
+ }
58
+
59
+ }
60
+
61
+ get collection(): readonly Chat[] {
62
+ return this._chats
63
+ }
64
+
65
+ get(id: string): Chat {
66
+ return <Chat>this.tryGet(id)
67
+ }
68
+
69
+ tryGet(id: string): Chat | undefined {
70
+ return this._chats.find(chat => chat.id === id)
71
+ }
72
+
73
+ async create(): Promise<Chat> {
74
+
75
+ // send create request to the server
76
+ const response = await this.context
77
+ .resolve(RpcService)
78
+ ?.requestBuilder("api/v1/Chats")
79
+ .sendPostJson({ organizationId: this.organization.id })
80
+
81
+ // check response status
82
+ if (ResponseUtils.isFail(response)) {
83
+ await ResponseUtils.throwError(`Failed to create chat, organization: ${this.organization.id}`, response)
84
+ }
85
+
86
+ // parse workspace from the server's response
87
+ const content = (await response!.json()).chat as ChatDto
88
+
89
+ // create workspace implementation
90
+ const chat = new ChatImpl(this.context, this.organization)
91
+ await chat.initFrom(content)
92
+
93
+ // add chat to the collection
94
+ this._chats.push(chat)
95
+
96
+ // dispatch event
97
+ this.dispatch({
98
+ type: ChatsEvent.ADDED,
99
+ data: chat
100
+ })
101
+
102
+ return chat
103
+ }
104
+
105
+ async delete(id: string): Promise<void> {
106
+ // get chat by id
107
+ const chat = <ChatImpl>this.tryGet(id)
108
+
109
+ // check if chat is found
110
+ if (!chat) {
111
+ throw new Error(`Chat ${id} is not found, organization: ${this.organization.id}`)
112
+ }
113
+
114
+ // send delete request to the server
115
+ const response = await this.context
116
+ .resolve(RpcService)
117
+ ?.requestBuilder("api/v1/Chats")
118
+ .searchParam("id", id)
119
+ .sendDelete()
120
+
121
+ // check response status
122
+ if (ResponseUtils.isFail(response)) {
123
+ await ResponseUtils.throwError(
124
+ `Failed to delete chat: ${id}, organization: ${this.organization.id}`,
125
+ response
126
+ )
127
+ }
128
+
129
+ // remove chat from the collection
130
+ const index = this._chats.indexOf(<ChatImpl>chat)
131
+ if (index < 0) {
132
+ throw new Error(`Chat ${id} is not found, organization: ${this.organization.id}`)
133
+ }
134
+ this._chats.splice(index, 1)
135
+
136
+ // dispatch event
137
+ this.dispatch({
138
+ type: ChatsEvent.REMOVED,
139
+ data: chat
140
+ })
141
+ }
142
+ }
@@ -0,0 +1,47 @@
1
+ import { EventDispatcher } from "../../events"
2
+ import { Chat, ChatId } from "./chat"
3
+ import { Organization } from "../organizations/organization"
4
+
5
+ export enum ChatsEvent {
6
+ ADDED = "added",
7
+ REMOVED = "removed"
8
+ }
9
+
10
+ /**
11
+ * Chats storage.
12
+ */
13
+ export abstract class Chats extends EventDispatcher<ChatsEvent, Chat> {
14
+
15
+ /**
16
+ * Organization.
17
+ */
18
+ abstract get organization(): Organization
19
+
20
+ /**
21
+ * Chats list.
22
+ */
23
+ abstract get collection(): ReadonlyArray<Chat>
24
+
25
+ /**
26
+ * Create new chat.
27
+ */
28
+ abstract create(): Promise<Chat>
29
+
30
+ /**
31
+ * Get chat by id.
32
+ * @param id
33
+ */
34
+ abstract get(id: ChatId): Chat
35
+
36
+ /**
37
+ * Try to get chat by id.
38
+ * @param id
39
+ */
40
+ abstract tryGet(id: ChatId): Chat | undefined
41
+
42
+ /**
43
+ * Delete chat.
44
+ * @param id
45
+ */
46
+ abstract delete(id: ChatId): Promise<void>
47
+ }
@@ -1,8 +1,8 @@
1
- import { Context } from "../context"
2
- import { Disposable } from "../disposable"
3
- import { FileDto, FileProgressDto } from "../dto/workspacesResponse"
4
- import { RpcService } from "../services/rpcService"
5
- import { ResponseUtils } from "../services/responseUtils"
1
+ import { Context } from "../../context"
2
+ import { Disposable } from "../../disposable"
3
+ import { FileDto, FileProgressDto } from "../../dto/workspacesResponse"
4
+ import { RpcService } from "../../services/rpcService"
5
+ import { ResponseUtils } from "../../services/responseUtils"
6
6
  import { File } from "./file"
7
7
 
8
8
  export class FileImpl extends File implements Disposable {
@@ -1,4 +1,4 @@
1
- import { FileProgressDto } from "../dto/workspacesResponse"
1
+ import { FileProgressDto } from "../../dto/workspacesResponse"
2
2
 
3
3
  export type FileId = string
4
4
 
@@ -1,11 +1,11 @@
1
- import { Context } from "../context"
2
- import { Disposable } from "../disposable"
3
- import { FileDto, FileListResponse } from "../dto/workspacesResponse"
4
- import { RpcService } from "../services/rpcService"
1
+ import { Context } from "../../context"
2
+ import { Disposable } from "../../disposable"
3
+ import { FileDto, FileListResponse } from "../../dto/workspacesResponse"
4
+ import { RpcService } from "../../services/rpcService"
5
5
  import { FileImpl } from "./file.impl"
6
6
  import { Files, FilesEvent, UploadFile } from "./files"
7
- import { WorkspaceImpl } from "./workspace.impl"
8
- import { ResponseUtils } from "../services/responseUtils"
7
+ import { WorkspaceImpl } from "../workspaces/workspace.impl"
8
+ import { ResponseUtils } from "../../services/responseUtils"
9
9
  import { File } from "./file"
10
10
  import { FilesPage } from "./filesPage"
11
11
 
@@ -1,4 +1,4 @@
1
- import { EventDispatcher } from "../events"
1
+ import { EventDispatcher } from "../../events"
2
2
  import { File, FileId } from "./file"
3
3
  import { FilesPage } from "./filesPage"
4
4
 
@@ -20,7 +20,7 @@ export type UploadFile = globalThis.File
20
20
  */
21
21
  export abstract class Files extends EventDispatcher<FilesEvent, File> {
22
22
  /**
23
- * Get file by id.
23
+ * Upload file.
24
24
  */
25
25
  abstract upload(file: UploadFile): Promise<File>
26
26
 
@@ -1,12 +1,18 @@
1
- import { Context } from "../context"
2
- import { Disposable } from "../disposable"
3
- import { AccessGroupDto, AccessGroupResponse, AccessGroupsResponse } from "../dto/accessGroupResponse"
4
- import { UserDto } from "../dto/userInfoResponse"
5
- import { WorkspaceDto, WorkspacesResponse } from "../dto/workspacesResponse"
6
- import { RpcService } from "../services/rpcService"
1
+ import { Context } from "../../context"
2
+ import { Disposable } from "../../disposable"
3
+ import {
4
+ AccessGroupDto,
5
+ AccessGroupResponse,
6
+ AccessGroupsResponse
7
+ } from "../../dto/accessGroupResponse"
8
+ import { UserDto } from "../../dto/userInfoResponse"
9
+ import { WorkspaceDto, WorkspacesResponse } from "../../dto/workspacesResponse"
10
+ import { RpcService } from "../../services/rpcService"
7
11
  import { Group, GroupEvent, GroupId, Groups } from "./groups"
8
- import { OrganizationImpl } from "./organization.impl"
9
- import { OrganizationId } from "./organizations"
12
+ import { OrganizationImpl } from "../organizations/organization.impl"
13
+ import { OrganizationId } from "../organizations/organizations"
14
+ import { ResponseUtils } from "../../services/responseUtils"
15
+ import { Organization } from "../organizations/organization"
10
16
 
11
17
  export class GroupImpl extends Group implements Disposable {
12
18
  private _isDisposed: boolean = false
@@ -14,32 +20,28 @@ export class GroupImpl extends Group implements Disposable {
14
20
  private _members?: UserDto[]
15
21
 
16
22
  constructor(
17
- private readonly context: Context
23
+ private readonly context: Context,
24
+ public readonly organization: Organization
18
25
  ) {
19
26
  super()
20
27
  }
21
28
 
22
- async initFrom(id: GroupId): Promise<Group>{
29
+ async initFrom(id: GroupId): Promise<Group> {
30
+ // fetch group
23
31
  const response = await this.context.resolve(RpcService)
24
32
  ?.requestBuilder("api/v1/AccessGroups")
25
33
  .searchParam("id", id)
26
34
  .sendGet()
27
35
 
28
- if (!response?.ok) {
29
- let text: string = ""
30
- try {
31
- text = (await response?.text()) ?? ""
32
- } catch (e) {
33
- console.error(e)
34
- }
35
-
36
- throw new Error(
37
- `Get group, response is not ok, status: ${response?.status},${response?.statusText} ${text}`
38
- )
36
+ // check response status
37
+ if (ResponseUtils.isFail(response)) {
38
+ await ResponseUtils.throwError(`Failed to get group: ${id}, organization: ${this}`, response)
39
39
  }
40
40
 
41
- const group = (await response.json()) as AccessGroupResponse
41
+ // parse group from the server's response
42
+ const group = (await response!.json()) as AccessGroupResponse
42
43
 
44
+ // init group
43
45
  this._content = group.group
44
46
  this._members = group.members
45
47
 
@@ -61,31 +63,24 @@ export class GroupImpl extends Group implements Disposable {
61
63
  }
62
64
 
63
65
  async getWorkspaces(): Promise<WorkspaceDto[]> {
66
+ // fetch workspaces
64
67
  const response = await this.context.resolve(RpcService)
65
68
  ?.requestBuilder("api/v1/Organizations/workspaces")
66
69
  .searchParam("groupId", this.id)
67
70
  .sendGet()
68
71
 
69
- if (!response?.ok) {
70
- let text: string = ""
71
- try {
72
- text = (await response?.text()) ?? ""
73
- } catch (e) {
74
- console.error(e)
75
- }
76
-
77
- throw new Error(
78
- `Groups get workspaces, response is not ok, status: ${response?.status},${response?.statusText} ${text}`
79
- )
72
+ if (ResponseUtils.isFail(response)) {
73
+ await ResponseUtils.throwError(`Failed to get workspaces for group: ${this.id}, organization: ${this.organization.id}`, response)
80
74
  }
81
75
 
82
- const workspaces = (await response.json()) as WorkspacesResponse
76
+ // parse workspaces from the server's response
77
+ const workspaces = (await response!.json()) as WorkspacesResponse
83
78
 
84
79
  return workspaces.workspaces
85
80
  }
86
81
 
87
82
  get members(): UserDto[] {
88
- if (this._members){
83
+ if (this._members) {
89
84
  return this._members
90
85
  }
91
86
  throw new Error("Access group is not loaded.")
@@ -98,6 +93,7 @@ export class GroupImpl extends Group implements Disposable {
98
93
  if (name.length === 0 || name.trim().length === 0) {
99
94
  throw new Error("Groups change, name is empty")
100
95
  }
96
+ // send request to the server
101
97
  const response = await this.context
102
98
  .resolve(RpcService)
103
99
  ?.requestBuilder("api/v1/AccessGroups/name")
@@ -106,14 +102,14 @@ export class GroupImpl extends Group implements Disposable {
106
102
  name: name
107
103
  })
108
104
 
109
- if (!response?.ok) {
110
- throw new Error(
111
- `Failed to set new name. ${response?.status}, ${response?.statusText}`
112
- )
105
+ // check response status
106
+ if (ResponseUtils.isFail(response)) {
107
+ await ResponseUtils.throwError(`Failed to change group name, group: ${this.id}, organization: ${this.organization.id}`, response)
113
108
  }
114
109
  }
115
110
 
116
- async setPermits(permits: {isAdmin: boolean}) : Promise<void> {
111
+ async setPermits(permits: { isAdmin: boolean }): Promise<void> {
112
+ // send request to the server
117
113
  const response = await this.context
118
114
  .resolve(RpcService)
119
115
  ?.requestBuilder("api/v1/AccessGroups/permits")
@@ -122,19 +118,17 @@ export class GroupImpl extends Group implements Disposable {
122
118
  permits: permits
123
119
  })
124
120
 
125
- if (!response?.ok) {
126
- throw new Error(
127
- `Failed to set new permits. ${response?.status}, ${response?.statusText}`
128
- )
121
+ if (ResponseUtils.isFail(response)) {
122
+ await ResponseUtils.throwError(`Failed to change group permits, group: ${this.id}, organization: ${this.organization.id}`, response)
129
123
  }
130
124
  }
131
125
 
132
-
133
126
  async setWorkspaces(workspaces: string[]): Promise<void> {
134
- if (workspaces === null || workspaces === undefined){
127
+ if (workspaces === null || workspaces === undefined) {
135
128
  throw new Error("Group add workspaces, workspaces is undefined or null")
136
129
  }
137
130
 
131
+ // send request to the server
138
132
  const response = await this.context
139
133
  .resolve(RpcService)
140
134
  ?.requestBuilder("api/v1/AccessGroups/workspaces")
@@ -143,19 +137,17 @@ export class GroupImpl extends Group implements Disposable {
143
137
  actualWorkspaceIds: workspaces
144
138
  })
145
139
 
146
- if (!response?.ok) {
147
- throw new Error(
148
- `Failed to set new member Ids. ${response?.status}, ${response?.statusText}`
149
- )
140
+ if (ResponseUtils.isFail(response)) {
141
+ await ResponseUtils.throwError(`Failed to set workspaces for group: ${this.id}, organization: ${this.organization.id}`, response)
150
142
  }
151
143
  }
152
144
 
153
-
154
145
  async setMembersIds(members: string[]) {
155
- if (members === null || members === undefined){
146
+ if (members === null || members === undefined) {
156
147
  throw new Error("Group add members, members is undefined or null")
157
148
  }
158
149
 
150
+ // send request to the server
159
151
  const response = await this.context
160
152
  .resolve(RpcService)
161
153
  ?.requestBuilder("api/v1/AccessGroups/members")
@@ -164,12 +156,9 @@ export class GroupImpl extends Group implements Disposable {
164
156
  memberIds: members
165
157
  })
166
158
 
167
- if (!response?.ok) {
168
- throw new Error(
169
- `Failed to set new member Ids. ${response?.status}, ${response?.statusText}`
170
- )
159
+ if (ResponseUtils.isFail(response)) {
160
+ await ResponseUtils.throwError(`Failed to set members for group: ${this.id}, organization: ${this.organization.id}`, response)
171
161
  }
172
-
173
162
  }
174
163
 
175
164
  get isDisposed(): boolean {
@@ -186,27 +175,30 @@ export class GroupsImpl extends Groups {
186
175
  private _groups: Group[] = []
187
176
 
188
177
  constructor(
189
- private readonly organization: OrganizationImpl,
178
+ public readonly organization: OrganizationImpl,
190
179
  private readonly context: Context
191
180
  ) {
192
181
  super()
193
182
  }
194
183
 
195
- async initialize(){
184
+ async initialize() {
196
185
  await this.internalInit()
197
186
  }
198
187
 
199
- async create(name: string, organizationId: OrganizationId, permits: { isAdmin: boolean }, memberIds: string[]): Promise<Group> {
188
+ async create(name: string, organizationId: OrganizationId, permits: {
189
+ isAdmin: boolean
190
+ }, memberIds: string[]): Promise<Group> {
200
191
  return await this.internalCreate(name, organizationId, permits, memberIds)
201
192
  }
202
- async get(id: GroupId): Promise<Group | undefined> {
203
- return await this._groups.find(group => group.id === id)
193
+
194
+ get(id: GroupId): Group | undefined {
195
+ return this._groups.find(group => group.id === id)
204
196
  }
197
+
205
198
  async delete(id: GroupId): Promise<void> {
206
199
  return await this.internalDeleteGroup(id)
207
200
  }
208
201
 
209
-
210
202
  //----------------------------------------------------------------------------
211
203
  // INTERNALS
212
204
  //----------------------------------------------------------------------------
@@ -215,31 +207,29 @@ export class GroupsImpl extends Groups {
215
207
  * Init access groups.
216
208
  */
217
209
  async internalInit(): Promise<void> {
210
+ // fetch groups
218
211
  const response = await this.context.resolve(RpcService)
219
212
  ?.requestBuilder("api/v1/Organizations/access_groups")
220
213
  .searchParam("id", this.organization.id)
221
214
  .sendGet()
222
215
 
223
- if (!response?.ok) {
224
- let text: string = ""
225
- try {
226
- text = (await response?.text()) ?? ""
227
- } catch (e) {
228
- console.error(e)
229
- }
230
-
231
- throw new Error(
232
- `Groups init, response is not ok, status: ${response?.status},${response?.statusText} ${text}`
233
- )
216
+ // check response status
217
+ if (ResponseUtils.isFail(response)) {
218
+ await ResponseUtils.throwError(`Failed to get groups for organization: ${this.organization.id}`, response)
234
219
  }
235
220
 
236
- const groups = (await response.json()) as AccessGroupsResponse
221
+ // parse groups from the server's response
222
+ const groups = (await response!.json()) as AccessGroupsResponse
237
223
 
238
- for (const gr of groups.groups){
239
- const group = await new GroupImpl(this.context).initFrom(gr.id)
224
+ // init groups
225
+ for (const gr of groups.groups) {
226
+ // create group implementation
227
+ const group = await new GroupImpl(this.context, this.organization).initFrom(gr.id)
240
228
 
229
+ // add group to the collection
241
230
  this._groups.push(group)
242
231
 
232
+ // dispatch event
243
233
  this.dispatch({
244
234
  type: GroupEvent.ADDED,
245
235
  data: group
@@ -247,7 +237,9 @@ export class GroupsImpl extends Groups {
247
237
  }
248
238
  }
249
239
 
250
- async internalCreate(name: string, organizationId: OrganizationId, permits: { isAdmin: boolean }, memberIds: string[]): Promise<Group>{
240
+ async internalCreate(name: string, organizationId: OrganizationId, permits: {
241
+ isAdmin: boolean
242
+ }, memberIds: string[]): Promise<Group> {
251
243
  if (name === undefined || name === null) {
252
244
  throw new Error("Group create, name is undefined or null")
253
245
  }
@@ -255,6 +247,7 @@ export class GroupsImpl extends Groups {
255
247
  throw new Error("Group create, name is empty")
256
248
  }
257
249
 
250
+ // send request to the server
258
251
  const response = await this.context
259
252
  .resolve(RpcService)
260
253
  ?.requestBuilder("api/v1/AccessGroups")
@@ -265,17 +258,20 @@ export class GroupsImpl extends Groups {
265
258
  memberIds: memberIds
266
259
  })
267
260
 
268
- if (!response?.ok) {
269
- throw new Error(
270
- `Organization create, response is not ok: ${response?.status}/${response?.statusText}`
271
- )
261
+ // check response status
262
+ if (ResponseUtils.isFail(response)) {
263
+ await ResponseUtils.throwError(`Failed to create group, organization: ${this.organization.id}`, response)
272
264
  }
273
- const content = (await response.json()) as AccessGroupResponse
265
+ // parse group from the server's response
266
+ const content = (await response!.json()) as AccessGroupResponse
274
267
 
275
- const group = await new GroupImpl(this.context).initFrom(content.group.id)
268
+ // create group implementation
269
+ const group = await new GroupImpl(this.context, this.organization).initFrom(content.group.id)
276
270
 
271
+ // add group to the collection
277
272
  this._groups.push(group)
278
273
 
274
+ // dispatch event
279
275
  this.dispatch({
280
276
  type: GroupEvent.ADDED,
281
277
  data: group
@@ -296,24 +292,19 @@ export class GroupsImpl extends Groups {
296
292
  throw new Error("Group delete, id is empty")
297
293
  }
298
294
 
295
+ // send request to the server
299
296
  const response = await this.context
300
297
  .resolve(RpcService)
301
298
  ?.requestBuilder("/api/v1/AccessGroups")
302
299
  .searchParam("groupId", id)
303
300
  .sendDelete()
304
- if (!response?.ok) {
305
- let text: string = ""
306
- try {
307
- text = (await response?.text()) ?? ""
308
- } catch (e) {
309
- console.error(e)
310
- }
311
-
312
- throw new Error(
313
- `Group ${id} delete, response is not ok, status: ${response?.status},${response?.statusText} ${text}`
314
- )
301
+
302
+ // check response status
303
+ if (ResponseUtils.isFail(response)) {
304
+ await ResponseUtils.throwError(`Failed to delete group: ${id}, organization: ${this.organization.id}`, response)
315
305
  }
316
306
 
307
+ // delete group from collection
317
308
  const group = <GroupImpl>this._groups.find(f => f.id === id)
318
309
  const index = this._groups.indexOf(group)
319
310
  if (index < 0) {
@@ -332,6 +323,4 @@ export class GroupsImpl extends Groups {
332
323
  // dispose group
333
324
  group.dispose()
334
325
  }
335
-
336
-
337
326
  }