@neuralinnovations/dataisland-sdk 0.0.1-dev1 → 0.0.1-dev10

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 (74) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +174 -1
  3. package/dist/dataisland-sdk.d.ts +1594 -0
  4. package/dist/dataisland-sdk.js +2890 -0
  5. package/dist/dataisland-sdk.js.map +1 -0
  6. package/index.d.ts +1 -0
  7. package/index.js +1 -0
  8. package/package.json +41 -3
  9. package/src/appBuilder.ts +24 -5
  10. package/src/commands/startCommandHandler.ts +14 -0
  11. package/src/context.ts +31 -0
  12. package/src/credentials.ts +31 -9
  13. package/src/dataIslandApp.ts +59 -0
  14. package/src/disposable.ts +4 -5
  15. package/src/dto/accessGroupResponse.ts +35 -0
  16. package/src/dto/chatResponse.ts +103 -0
  17. package/src/dto/userInfoResponse.ts +47 -0
  18. package/src/dto/workspacesResponse.ts +49 -0
  19. package/src/events.ts +13 -17
  20. package/src/index.ts +44 -18
  21. package/src/internal/app.impl.ts +97 -32
  22. package/src/internal/appBuilder.impl.ts +39 -12
  23. package/src/internal/createApp.impl.ts +5 -5
  24. package/src/middleware.ts +1 -1
  25. package/src/services/commandService.ts +44 -0
  26. package/src/services/credentialService.ts +3 -3
  27. package/src/services/middlewareService.ts +8 -6
  28. package/src/services/organizationService.ts +28 -0
  29. package/src/services/requestBuilder.ts +127 -0
  30. package/src/services/responseUtils.ts +32 -0
  31. package/src/services/rpcService.ts +129 -52
  32. package/src/services/service.ts +10 -8
  33. package/src/services/userProfileService.ts +38 -0
  34. package/src/storages/chats/answer.impl.ts +163 -0
  35. package/src/storages/chats/answer.ts +42 -0
  36. package/src/storages/chats/chat.impl.ts +87 -0
  37. package/src/storages/chats/chat.ts +38 -0
  38. package/src/storages/chats/chats.impl.ts +142 -0
  39. package/src/storages/chats/chats.ts +47 -0
  40. package/src/storages/files/file.impl.ts +69 -0
  41. package/src/storages/files/file.ts +28 -0
  42. package/src/storages/files/files.impl.ts +213 -0
  43. package/src/storages/files/files.ts +38 -0
  44. package/src/storages/files/filesPage.ts +27 -0
  45. package/src/storages/groups/groups.impl.ts +326 -0
  46. package/src/storages/groups/groups.ts +101 -0
  47. package/src/storages/organizations/organization.impl.ts +95 -0
  48. package/src/storages/organizations/organization.ts +44 -0
  49. package/src/storages/organizations/organizations.impl.ts +197 -0
  50. package/src/storages/organizations/organizations.ts +56 -0
  51. package/src/storages/user/userProfile.impl.ts +56 -0
  52. package/src/storages/user/userProfile.ts +42 -0
  53. package/src/storages/workspaces/workspace.impl.ts +109 -0
  54. package/src/storages/workspaces/workspace.ts +49 -0
  55. package/src/storages/workspaces/workspaces.impl.ts +212 -0
  56. package/src/storages/workspaces/workspaces.ts +53 -0
  57. package/src/unitTest.ts +53 -0
  58. package/.browserslistrc +0 -5
  59. package/.editorconfig +0 -22
  60. package/.eslintrc.json +0 -44
  61. package/.github/workflows/publish-npm.yml +0 -28
  62. package/.prettierignore +0 -1
  63. package/.prettierrc +0 -11
  64. package/.yarnrc +0 -2
  65. package/babel.config.js +0 -6
  66. package/jest.config.ts +0 -199
  67. package/src/appSdk.ts +0 -40
  68. package/src/internal/context.ts +0 -13
  69. package/src/types.ts +0 -110
  70. package/test/disposable.test.ts +0 -39
  71. package/test/events.test.ts +0 -151
  72. package/test/index.test.ts +0 -83
  73. package/test/registry.test.ts +0 -44
  74. package/tsconfig.json +0 -31
@@ -0,0 +1,87 @@
1
+ import { Chat, ChatAnswerType } from "./chat"
2
+ import { Disposable } from "../../disposable"
3
+ import { Answer } from "./answer"
4
+ import { ChatDto } from "../../dto/chatResponse"
5
+ import { Context } from "../../context"
6
+ import { AnswerImpl } from "./answer.impl"
7
+ import { RpcService } from "../../services/rpcService"
8
+ import { ResponseUtils } from "../../services/responseUtils"
9
+ import { Organization } from "../organizations/organization"
10
+
11
+ export class ChatImpl extends Chat implements Disposable {
12
+ private _isDisposed: boolean = false
13
+ private readonly _answers: Answer[] = []
14
+
15
+ private _content?: ChatDto
16
+
17
+ constructor(
18
+ private readonly context: Context,
19
+ public readonly organization: Organization
20
+ ) {
21
+ super()
22
+ }
23
+
24
+ async initFrom(chat: ChatDto): Promise<ChatImpl> {
25
+ this._content = chat
26
+
27
+ // init answers
28
+ for (const ans of chat.answers) {
29
+ // create answer implementation
30
+ const answer = await new AnswerImpl(this, this.context).initFromData(ans)
31
+
32
+ // add answer to the collection
33
+ this._answers.push(answer)
34
+ }
35
+
36
+ return this
37
+ }
38
+
39
+ get id(): string {
40
+ return <string>this._content?.id
41
+ }
42
+
43
+ get name(): string {
44
+ return <string>this._content?.name
45
+ }
46
+
47
+ get collection(): readonly Answer[] {
48
+ return this._answers
49
+ }
50
+
51
+ get isDisposed(): boolean {
52
+ return this._isDisposed
53
+ }
54
+
55
+ async ask(message: string, answerType: ChatAnswerType): Promise<Answer> {
56
+ // send request to the server
57
+ const response = await this.context
58
+ .resolve(RpcService)
59
+ ?.requestBuilder("api/v1/Chats/question")
60
+ .sendPutJson({
61
+ chatId: this.id,
62
+ questionMessage: message,
63
+ isLongAnswer: (answerType === ChatAnswerType.LONG)
64
+ })
65
+
66
+ // check response status
67
+ if (ResponseUtils.isFail(response)) {
68
+ await ResponseUtils.throwError(`Failed to ask a question, organization: ${this.organization.id}`, response)
69
+ }
70
+
71
+ // parse answer id from the server's response
72
+ const id = (await response!.json()).id
73
+
74
+ // create answer implementation
75
+ const answer = await new AnswerImpl(this, this.context).initFromId(id)
76
+
77
+ // add answer to the collection
78
+ this._answers.push(answer)
79
+
80
+ return answer
81
+ }
82
+
83
+ dispose(): void {
84
+ this._isDisposed = true
85
+ }
86
+
87
+ }
@@ -0,0 +1,38 @@
1
+ import { Answer } from "./answer"
2
+ import { Organization } from "../organizations/organization"
3
+
4
+ export type ChatId = string
5
+
6
+ export enum ChatAnswerType {
7
+ SHORT = "short",
8
+ LONG = "long"
9
+ }
10
+
11
+ export abstract class Chat {
12
+
13
+ /**
14
+ * Organization.
15
+ */
16
+ abstract get organization(): Organization
17
+
18
+ /**
19
+ * Chat id.
20
+ */
21
+ abstract get id(): ChatId
22
+
23
+ /**
24
+ * Chat name.
25
+ */
26
+ abstract get name(): string
27
+
28
+ /**
29
+ * Answers list.
30
+ */
31
+ abstract get collection(): ReadonlyArray<Answer>
32
+
33
+ /**
34
+ * Ask new question in chat.
35
+ */
36
+ abstract ask(message: string, answerType: ChatAnswerType): Promise<Answer>
37
+ }
38
+
@@ -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
+ }
@@ -0,0 +1,69 @@
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
+ import { File } from "./file"
7
+
8
+ export class FileImpl extends File implements Disposable {
9
+ private _isDisposed: boolean = false
10
+ private _content?: FileDto
11
+
12
+ constructor(private readonly context: Context) {
13
+ super()
14
+ }
15
+
16
+ public initFrom(file: FileDto): File {
17
+ this._content = file
18
+
19
+ return this
20
+ }
21
+
22
+ get isDisposed(): boolean {
23
+ return this._isDisposed
24
+ }
25
+
26
+ dispose(): void {
27
+ this._isDisposed = true
28
+ }
29
+
30
+ get id(): string {
31
+ return <string>this._content?.id
32
+ }
33
+
34
+ get name(): string {
35
+ return <string>this._content?.name
36
+ }
37
+
38
+ async url(): Promise<string> {
39
+ const response = await this.context
40
+ .resolve(RpcService)
41
+ ?.requestBuilder("api/v1/Files/url")
42
+ .searchParam("id", this.id)
43
+ .sendGet()
44
+
45
+ if (ResponseUtils.isFail(response)) {
46
+ await ResponseUtils.throwError(
47
+ `Failed to get file ${this.id} url`,
48
+ response
49
+ )
50
+ }
51
+
52
+ return (await response!.json()).url
53
+ }
54
+
55
+ async status(): Promise<FileProgressDto> {
56
+ const response = await this.context
57
+ .resolve(RpcService)
58
+ ?.requestBuilder("api/v1/Files/fetch")
59
+ .searchParam("id", this.id)
60
+ .sendGet()
61
+
62
+ if (ResponseUtils.isFail(response)) {
63
+ await ResponseUtils.throwError(`Failed to get file ${this.id}`, response)
64
+ }
65
+
66
+ const content = await response!.json()
67
+ return content.progress as FileProgressDto
68
+ }
69
+ }
@@ -0,0 +1,28 @@
1
+ import { FileProgressDto } from "../../dto/workspacesResponse"
2
+
3
+ export type FileId = string
4
+
5
+ /**
6
+ * File.
7
+ */
8
+ export abstract class File {
9
+ /**
10
+ * File id.
11
+ */
12
+ abstract get id(): FileId
13
+
14
+ /**
15
+ * File name.
16
+ */
17
+ abstract get name(): string
18
+
19
+ /**
20
+ * Get temporary url.
21
+ */
22
+ abstract url(): Promise<string>
23
+
24
+ /**
25
+ * Get file status.
26
+ */
27
+ abstract status(): Promise<FileProgressDto>
28
+ }
@@ -0,0 +1,213 @@
1
+ import { Context } from "../../context"
2
+ import { Disposable } from "../../disposable"
3
+ import { FileDto, FileListResponse } from "../../dto/workspacesResponse"
4
+ import { RpcService } from "../../services/rpcService"
5
+ import { FileImpl } from "./file.impl"
6
+ import { Files, FilesEvent, UploadFile } from "./files"
7
+ import { WorkspaceImpl } from "../workspaces/workspace.impl"
8
+ import { ResponseUtils } from "../../services/responseUtils"
9
+ import { File } from "./file"
10
+ import { FilesPage } from "./filesPage"
11
+
12
+ export class FilesPageImpl extends FilesPage implements Disposable {
13
+ private _isDisposed: boolean = false
14
+
15
+ public files: File[] = []
16
+ public total: number = 0
17
+ public filesPerPage: number = 0
18
+ public page: number = 0
19
+
20
+ get pages(): number {
21
+ return Math.ceil(Math.max(this.total / this.filesPerPage, 1.0))
22
+ }
23
+
24
+ get isDisposed(): boolean {
25
+ return this._isDisposed
26
+ }
27
+
28
+ dispose(): void {
29
+ this._isDisposed = true
30
+ }
31
+ }
32
+
33
+ export class FilesImpl extends Files {
34
+ constructor(
35
+ private readonly workspace: WorkspaceImpl,
36
+ private readonly context: Context
37
+ ) {
38
+ super()
39
+ }
40
+
41
+ // Object used as files page data, returned by "query"
42
+ public filesList?: FilesPage
43
+
44
+ async upload(file: any): Promise<File> {
45
+ return await this.internalUpload(file)
46
+ }
47
+
48
+ async delete(id: string): Promise<void> {
49
+ return await this.internalDeleteFile(id)
50
+ }
51
+
52
+ async query(query: string, page: number, limit: number): Promise<FilesPage> {
53
+ return await this.internalQuery(query, page, limit)
54
+ }
55
+
56
+ //----------------------------------------------------------------------------
57
+ // INTERNALS
58
+ //----------------------------------------------------------------------------
59
+
60
+ /**
61
+ * Delete organization.
62
+ * @param id
63
+ */
64
+ async internalDeleteFile(id: string): Promise<void> {
65
+ if (id === undefined || id === null) {
66
+ throw new Error("File delete, id is undefined or null")
67
+ }
68
+ if (id.length === 0 || id.trim().length === 0) {
69
+ throw new Error("File delete, id is empty")
70
+ }
71
+
72
+ const response = await this.context
73
+ .resolve(RpcService)
74
+ ?.requestBuilder("/api/v1/Files")
75
+ .searchParam("id", id)
76
+ .sendDelete()
77
+ if (ResponseUtils.isFail(response)) {
78
+ await ResponseUtils.throwError(`File ${id} delete, failed`, response)
79
+ }
80
+ const file = <FileImpl>this.filesList!.files.find(f => f.id === id)
81
+ const index = this.filesList!.files.indexOf(file)
82
+ if (index < 0) {
83
+ throw new Error("Organization delete, index is not found")
84
+ }
85
+
86
+ // remove file from collection
87
+ this.filesList!.files.splice(index, 1)
88
+
89
+ // dispatch event, file removed
90
+ this.dispatch({
91
+ type: FilesEvent.REMOVED,
92
+ data: file
93
+ })
94
+
95
+ // dispose file
96
+ file.dispose()
97
+ }
98
+
99
+ async internalQuery(
100
+ query: string,
101
+ page: number,
102
+ limit: number
103
+ ): Promise<FilesPage> {
104
+
105
+ // check page
106
+ if (page === undefined || page === null) {
107
+ throw new Error("File fetch, page is undefined or null")
108
+ }
109
+ if (page < 0) {
110
+ throw new Error("File fetch, page is negative")
111
+ }
112
+
113
+ // check limit
114
+ if (limit === undefined || limit === null) {
115
+ throw new Error("File fetch, limit is undefined or null")
116
+ }
117
+ if (limit === 0) {
118
+ throw new Error("File fetch, limit is 0")
119
+ }
120
+
121
+ // send request to the server
122
+ const response = await this.context
123
+ .resolve(RpcService)
124
+ ?.requestBuilder("api/v1/Files/list")
125
+
126
+ .searchParam("workspaceId", this.workspace.id)
127
+ .searchParam("organizationId", this.workspace.organization.id)
128
+ .searchParam("query", query)
129
+ .searchParam("page", page.toString())
130
+ .searchParam("limit", limit.toString())
131
+ .sendGet()
132
+
133
+ // check response status
134
+ if (ResponseUtils.isFail(response)) {
135
+ await ResponseUtils.throwError(
136
+ `Files fetch query:${query}, page:${page}, limit:${limit}, failed`,
137
+ response
138
+ )
139
+ }
140
+
141
+ // parse files from the server's response
142
+ const files = (await response!.json()) as FileListResponse
143
+
144
+ // create files list
145
+ const filesList = new FilesPageImpl()
146
+ filesList.total = files.totalFilesCount
147
+ filesList.filesPerPage = files.filesPerPage
148
+ filesList.page = page
149
+
150
+ // init files from the server's response
151
+ for (const fl of files.files) {
152
+
153
+ // create file implementation
154
+ const file = new FileImpl(this.context).initFrom(fl)
155
+
156
+ // add file to the collection
157
+ filesList.files.push(file)
158
+
159
+ // dispatch event, file added
160
+ this.dispatch({
161
+ type: FilesEvent.ADDED,
162
+ data: file
163
+ })
164
+ }
165
+
166
+ // set files list
167
+ this.filesList = filesList
168
+
169
+ return filesList
170
+ }
171
+
172
+ async internalUpload(file: UploadFile): Promise<File> {
173
+ // check file
174
+ if (file === undefined || file === null) {
175
+ throw new Error("File upload, file is undefined or null")
176
+ }
177
+
178
+ // form data to send
179
+ const form = new FormData()
180
+ form.append("organizationId", this.workspace.organization.id)
181
+ form.append("workspaceId", this.workspace.id)
182
+ form.append("name", file.name)
183
+ form.append("file", file, file.name)
184
+
185
+ // send request to the server
186
+ const response = await this.context
187
+ .resolve(RpcService)
188
+ ?.requestBuilder("api/v1/Files")
189
+ .sendPostFormData(form)
190
+
191
+ // check response status
192
+ if (ResponseUtils.isFail(response)) {
193
+ await ResponseUtils.throwError(`File upload ${file.name}`, response)
194
+ }
195
+
196
+ // parse file from the server's response
197
+ const result = (await response!.json()).file as FileDto
198
+
199
+ // create file implementation
200
+ const fileImpl = new FileImpl(this.context).initFrom(result)
201
+
202
+ // TODO: why is this here?
203
+ this.filesList?.files.push(fileImpl)
204
+
205
+ // dispatch event, file added
206
+ this.dispatch({
207
+ type: FilesEvent.ADDED,
208
+ data: fileImpl
209
+ })
210
+
211
+ return fileImpl
212
+ }
213
+ }
@@ -0,0 +1,38 @@
1
+ import { EventDispatcher } from "../../events"
2
+ import { File, FileId } from "./file"
3
+ import { FilesPage } from "./filesPage"
4
+
5
+ /**
6
+ * Files event.
7
+ */
8
+ export enum FilesEvent {
9
+ ADDED = "added",
10
+ REMOVED = "removed"
11
+ }
12
+
13
+ /**
14
+ * Upload file.
15
+ */
16
+ export type UploadFile = globalThis.File
17
+
18
+ /**
19
+ * Files storage.
20
+ */
21
+ export abstract class Files extends EventDispatcher<FilesEvent, File> {
22
+ /**
23
+ * Upload file.
24
+ */
25
+ abstract upload(file: UploadFile): Promise<File>
26
+
27
+ /**
28
+ * Delete file.
29
+ * @param id
30
+ */
31
+ abstract delete(id: FileId): Promise<void>
32
+
33
+ /**
34
+ * Query files.
35
+ */
36
+ abstract query(query: string, page: number, limit: number): Promise<FilesPage>
37
+ }
38
+
@@ -0,0 +1,27 @@
1
+ import { File } from "./file"
2
+
3
+ /**
4
+ * Files page.
5
+ */
6
+ export abstract class FilesPage {
7
+
8
+ /**
9
+ * Get files.
10
+ */
11
+ abstract get files(): File[]
12
+
13
+ /**
14
+ * Get pages count.
15
+ */
16
+ abstract get pages(): number
17
+
18
+ /**
19
+ * Get total count.
20
+ */
21
+ abstract get total(): number
22
+
23
+ /**
24
+ * Get current page.
25
+ */
26
+ abstract get page(): number
27
+ }