@neuralinnovations/dataisland-sdk 0.0.1-dev26 → 0.0.1-dev28

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 (140) hide show
  1. package/README.md +18 -12
  2. package/dist/package.json +6 -2
  3. package/dist/src/commands/startCommandHandler.d.ts.map +1 -1
  4. package/dist/src/commands/startCommandHandler.js +12 -2
  5. package/dist/src/commands/startCommandHandler.js.map +1 -1
  6. package/dist/src/context.d.ts +3 -2
  7. package/dist/src/context.d.ts.map +1 -1
  8. package/dist/src/context.js +2 -2
  9. package/dist/src/context.js.map +1 -1
  10. package/dist/src/credentials.d.ts +5 -0
  11. package/dist/src/credentials.d.ts.map +1 -1
  12. package/dist/src/credentials.js +18 -1
  13. package/dist/src/credentials.js.map +1 -1
  14. package/dist/src/dto/accessGroupResponse.d.ts.map +1 -1
  15. package/dist/src/dto/userInfoResponse.d.ts +1 -0
  16. package/dist/src/dto/userInfoResponse.d.ts.map +1 -1
  17. package/dist/src/index.d.ts +1 -0
  18. package/dist/src/index.d.ts.map +1 -1
  19. package/dist/src/index.js +1 -0
  20. package/dist/src/index.js.map +1 -1
  21. package/dist/src/internal/app.impl.d.ts.map +1 -1
  22. package/dist/src/internal/app.impl.js +20 -2
  23. package/dist/src/internal/app.impl.js.map +1 -1
  24. package/dist/src/middleware.d.ts +2 -0
  25. package/dist/src/middleware.d.ts.map +1 -1
  26. package/dist/src/services/anonymousService.d.ts +8 -0
  27. package/dist/src/services/anonymousService.d.ts.map +1 -0
  28. package/dist/src/services/anonymousService.js +41 -0
  29. package/dist/src/services/anonymousService.js.map +1 -0
  30. package/dist/src/services/commandService.d.ts.map +1 -1
  31. package/dist/src/services/commandService.js.map +1 -1
  32. package/dist/src/services/cookieService.d.ts +7 -0
  33. package/dist/src/services/cookieService.d.ts.map +1 -0
  34. package/dist/src/services/cookieService.js +18 -0
  35. package/dist/src/services/cookieService.js.map +1 -0
  36. package/dist/src/services/httpMethod.d.ts +2 -0
  37. package/dist/src/services/httpMethod.d.ts.map +1 -0
  38. package/dist/src/services/httpMethod.js +3 -0
  39. package/dist/src/services/httpMethod.js.map +1 -0
  40. package/dist/src/services/middlewareService.d.ts +2 -0
  41. package/dist/src/services/middlewareService.d.ts.map +1 -1
  42. package/dist/src/services/middlewareService.js.map +1 -1
  43. package/dist/src/services/requestBuilder.d.ts +2 -0
  44. package/dist/src/services/requestBuilder.d.ts.map +1 -1
  45. package/dist/src/services/requestBuilder.js +11 -10
  46. package/dist/src/services/requestBuilder.js.map +1 -1
  47. package/dist/src/services/responseUtils.d.ts +1 -0
  48. package/dist/src/services/responseUtils.d.ts.map +1 -1
  49. package/dist/src/services/responseUtils.js.map +1 -1
  50. package/dist/src/services/rpcService.d.ts +1 -0
  51. package/dist/src/services/rpcService.d.ts.map +1 -1
  52. package/dist/src/services/rpcService.js +4 -2
  53. package/dist/src/services/rpcService.js.map +1 -1
  54. package/dist/src/services/userProfileService.d.ts +1 -0
  55. package/dist/src/services/userProfileService.d.ts.map +1 -1
  56. package/dist/src/services/userProfileService.js +11 -0
  57. package/dist/src/services/userProfileService.js.map +1 -1
  58. package/dist/src/storages/chats/answer.d.ts +4 -0
  59. package/dist/src/storages/chats/answer.d.ts.map +1 -1
  60. package/dist/src/storages/chats/answer.impl.d.ts +2 -0
  61. package/dist/src/storages/chats/answer.impl.d.ts.map +1 -1
  62. package/dist/src/storages/chats/answer.impl.js +21 -6
  63. package/dist/src/storages/chats/answer.impl.js.map +1 -1
  64. package/dist/src/storages/chats/answer.js.map +1 -1
  65. package/dist/src/storages/chats/chat.impl.js.map +1 -1
  66. package/dist/src/storages/chats/chats.impl.d.ts.map +1 -1
  67. package/dist/src/storages/chats/chats.impl.js.map +1 -1
  68. package/dist/src/storages/files/file.d.ts +13 -5
  69. package/dist/src/storages/files/file.d.ts.map +1 -1
  70. package/dist/src/storages/files/file.impl.d.ts +6 -4
  71. package/dist/src/storages/files/file.impl.d.ts.map +1 -1
  72. package/dist/src/storages/files/file.impl.js +33 -8
  73. package/dist/src/storages/files/file.impl.js.map +1 -1
  74. package/dist/src/storages/files/file.js +7 -1
  75. package/dist/src/storages/files/file.js.map +1 -1
  76. package/dist/src/storages/files/files.d.ts +5 -1
  77. package/dist/src/storages/files/files.d.ts.map +1 -1
  78. package/dist/src/storages/files/files.impl.d.ts +1 -1
  79. package/dist/src/storages/files/files.impl.d.ts.map +1 -1
  80. package/dist/src/storages/files/files.impl.js +7 -4
  81. package/dist/src/storages/files/files.impl.js.map +1 -1
  82. package/dist/src/storages/files/files.js.map +1 -1
  83. package/dist/src/storages/organizations/organization.d.ts.map +1 -1
  84. package/dist/src/storages/organizations/organization.impl.d.ts.map +1 -1
  85. package/dist/src/storages/organizations/organization.impl.js.map +1 -1
  86. package/dist/src/storages/organizations/organization.js.map +1 -1
  87. package/dist/src/storages/organizations/organizations.impl.d.ts.map +1 -1
  88. package/dist/src/storages/organizations/organizations.impl.js.map +1 -1
  89. package/dist/src/storages/user/userProfile.d.ts +4 -0
  90. package/dist/src/storages/user/userProfile.d.ts.map +1 -1
  91. package/dist/src/storages/user/userProfile.impl.d.ts +1 -0
  92. package/dist/src/storages/user/userProfile.impl.d.ts.map +1 -1
  93. package/dist/src/storages/user/userProfile.impl.js +6 -0
  94. package/dist/src/storages/user/userProfile.impl.js.map +1 -1
  95. package/dist/src/storages/user/userProfile.js.map +1 -1
  96. package/dist/src/storages/workspaces/workspace.impl.js.map +1 -1
  97. package/dist/src/storages/workspaces/workspaces.d.ts.map +1 -1
  98. package/dist/src/storages/workspaces/workspaces.impl.d.ts.map +1 -1
  99. package/dist/src/storages/workspaces/workspaces.impl.js.map +1 -1
  100. package/dist/src/storages/workspaces/workspaces.js.map +1 -1
  101. package/dist/src/utils/browserUtils.d.ts +4 -0
  102. package/dist/src/utils/browserUtils.d.ts.map +1 -0
  103. package/dist/src/utils/browserUtils.js +68 -0
  104. package/dist/src/utils/browserUtils.js.map +1 -0
  105. package/package.json +7 -3
  106. package/src/commands/startCommandHandler.ts +16 -5
  107. package/src/context.ts +2 -1
  108. package/src/credentials.ts +22 -0
  109. package/src/dto/accessGroupResponse.ts +15 -16
  110. package/src/dto/userInfoResponse.ts +1 -0
  111. package/src/index.ts +2 -0
  112. package/src/internal/app.impl.ts +30 -4
  113. package/src/middleware.ts +3 -0
  114. package/src/services/anonymousService.ts +43 -0
  115. package/src/services/commandService.ts +4 -2
  116. package/src/services/cookieService.ts +16 -0
  117. package/src/services/httpMethod.ts +1 -0
  118. package/src/services/middlewareService.ts +2 -0
  119. package/src/services/requestBuilder.ts +6 -3
  120. package/src/services/responseUtils.ts +2 -0
  121. package/src/services/rpcService.ts +2 -0
  122. package/src/services/userProfileService.ts +14 -0
  123. package/src/storages/chats/answer.impl.ts +25 -6
  124. package/src/storages/chats/answer.ts +5 -0
  125. package/src/storages/chats/chat.impl.ts +1 -1
  126. package/src/storages/chats/chats.impl.ts +3 -1
  127. package/src/storages/files/file.impl.ts +41 -15
  128. package/src/storages/files/file.ts +16 -7
  129. package/src/storages/files/files.impl.ts +10 -7
  130. package/src/storages/files/files.ts +5 -1
  131. package/src/storages/groups/group.impl.ts +1 -1
  132. package/src/storages/organizations/organization.impl.ts +4 -2
  133. package/src/storages/organizations/organization.ts +3 -4
  134. package/src/storages/organizations/organizations.impl.ts +3 -1
  135. package/src/storages/user/userProfile.impl.ts +7 -0
  136. package/src/storages/user/userProfile.ts +5 -0
  137. package/src/storages/workspaces/workspace.impl.ts +1 -1
  138. package/src/storages/workspaces/workspaces.impl.ts +3 -1
  139. package/src/storages/workspaces/workspaces.ts +5 -1
  140. package/src/utils/browserUtils.ts +72 -0
@@ -7,7 +7,11 @@ import { DisposableContainer, type Lifetime } from "../disposable"
7
7
  import { type Service, ServiceContext } from "../services/service"
8
8
  import { CredentialService } from "../services/credentialService"
9
9
  import { MiddlewareService } from "../services/middlewareService"
10
- import { type CredentialBase } from "../credentials"
10
+ import {
11
+ DefaultCredential,
12
+ type CredentialBase,
13
+ AnonymousCredential
14
+ } from "../credentials"
11
15
  import { DataIslandApp } from "../dataIslandApp"
12
16
  import { RpcService } from "../services/rpcService"
13
17
  import { CommandService } from "../services/commandService"
@@ -24,6 +28,8 @@ import {
24
28
  DeleteUserFullCommand,
25
29
  DeleteUserFullCommandHandler
26
30
  } from "../commands/deleteUserFullCommandHandler"
31
+ import { CookieService } from "../services/cookieService"
32
+ import { AnonymousService } from "../services/anonymousService"
27
33
 
28
34
  export class DataIslandAppImpl extends DataIslandApp {
29
35
  readonly name: string
@@ -38,7 +44,7 @@ export class DataIslandAppImpl extends DataIslandApp {
38
44
  this.name = name
39
45
  this._registry = new Registry()
40
46
  this._disposable = new DisposableContainer()
41
- this._context = new Context(this._registry, this._disposable.lifetime, name)
47
+ this._context = new Context(this._registry, this._disposable.lifetime, this)
42
48
 
43
49
  this._registry.map(Context).asValue(this._context)
44
50
  }
@@ -92,6 +98,9 @@ export class DataIslandAppImpl extends DataIslandApp {
92
98
  })
93
99
 
94
100
  // register services
101
+ builder.registerService(CookieService, (context: ServiceContext) => {
102
+ return new CookieService(context)
103
+ })
95
104
  builder.registerService(CredentialService, (context: ServiceContext) => {
96
105
  return new CredentialService(context)
97
106
  })
@@ -110,6 +119,9 @@ export class DataIslandAppImpl extends DataIslandApp {
110
119
  builder.registerService(OrganizationService, (context: ServiceContext) => {
111
120
  return new OrganizationService(context)
112
121
  })
122
+ builder.registerService(AnonymousService, (context: ServiceContext) => {
123
+ return new AnonymousService(context)
124
+ })
113
125
 
114
126
  // call customer setup
115
127
  if (setup !== undefined) {
@@ -146,8 +158,6 @@ export class DataIslandAppImpl extends DataIslandApp {
146
158
  this.resolve(CommandService)?.register(command[0], command[1])
147
159
  })
148
160
 
149
- this.credential = builder.credential
150
-
151
161
  //-------------------------------------------------------------------------
152
162
  // register services
153
163
  //-------------------------------------------------------------------------
@@ -178,6 +188,22 @@ export class DataIslandAppImpl extends DataIslandApp {
178
188
  await Promise.all(waitList)
179
189
  //-------------------------------------------------------------------------
180
190
 
191
+ // set credential
192
+ this.credential = builder.credential
193
+
194
+ // Check anonymous authorization
195
+ if (!isUnitTest(UnitTest.DO_NOT_START) && builder.credential instanceof DefaultCredential) {
196
+ const anonymous = this.resolve(AnonymousService)!
197
+ const {
198
+ token,
199
+ isValid
200
+ } = await anonymous.getToken()
201
+
202
+ if (isValid) {
203
+ this.credential = new AnonymousCredential(token)
204
+ }
205
+ }
206
+
181
207
  // start app, execute start command
182
208
  if (!isUnitTest(UnitTest.DO_NOT_START)) {
183
209
  await this.context.execute(new StartCommand())
package/src/middleware.ts CHANGED
@@ -1,3 +1,6 @@
1
+ // import { Request } from "./services/request"
2
+ import { Request } from "node-fetch"
3
+ import { Response } from "node-fetch"
1
4
  /**
2
5
  * DataIsland App request middleware.
3
6
  */
@@ -0,0 +1,43 @@
1
+ import { Service } from "./service"
2
+ import { CookieService } from "./cookieService"
3
+ import { createFingerprint } from "../utils/browserUtils"
4
+ import { RpcService } from "./rpcService"
5
+ import { ResponseUtils } from "./responseUtils"
6
+
7
+ export class AnonymousService extends Service {
8
+
9
+ async getToken(): Promise<{ token: string, isValid: boolean }> {
10
+ const cookie = this.resolve(CookieService)!
11
+ let token = cookie.anonymousToken
12
+ if (token === undefined || token === null || token.length === 0) {
13
+ const fingerprint = createFingerprint()
14
+ const response = await this.context
15
+ .resolve(RpcService)
16
+ ?.requestBuilder("api/v1/Users/anonymous")
17
+ .sendPutJson({
18
+ info: {
19
+ fingerprint: JSON.stringify({
20
+ userAgent: fingerprint.get("userAgent"),
21
+ language: fingerprint.get("language"),
22
+ hardwareConcurrency: fingerprint.get("hardware_concurrency"),
23
+ cookieEnabled: fingerprint.get("cookie_enabled"),
24
+ pixelRatio: fingerprint.get("pixel_ratio")
25
+ })
26
+ }
27
+ })
28
+
29
+ if (ResponseUtils.isFail(response)) {
30
+ await ResponseUtils.throwError("Failed to create anonymous token", response)
31
+ }
32
+
33
+ token = (await response!.json() as { token: string }).token
34
+
35
+ cookie.anonymousToken = token!
36
+ }
37
+
38
+ return {
39
+ token: token!,
40
+ isValid: token !== undefined && token !== null && token.length > 0
41
+ }
42
+ }
43
+ }
@@ -3,7 +3,8 @@ import { Context } from "../context"
3
3
  import { Constructor } from "../internal/registry"
4
4
 
5
5
  export abstract class CommandHandler<T> {
6
- constructor(protected readonly context: Context) {}
6
+ constructor(protected readonly context: Context) {
7
+ }
7
8
 
8
9
  resolve<T>(type: Constructor<T>): T | undefined {
9
10
  return this.context.resolve<T>(type)
@@ -12,7 +13,8 @@ export abstract class CommandHandler<T> {
12
13
  abstract execute(message: T): Promise<void>
13
14
  }
14
15
 
15
- export abstract class Command {}
16
+ export abstract class Command {
17
+ }
16
18
 
17
19
  export class CommandService extends Service {
18
20
  private readonly _registry: Map<
@@ -0,0 +1,16 @@
1
+ import { Service } from "./service"
2
+ import { getCookie, setCookie } from "../utils/browserUtils"
3
+
4
+ export class CookieService extends Service {
5
+ get anonymousToken(): string | undefined {
6
+ return getCookie("anonymous-token")
7
+ }
8
+
9
+ get anonymousTokenIsValid(): boolean {
10
+ return this.anonymousToken !== undefined && this.anonymousToken !== null && this.anonymousToken.length > 0
11
+ }
12
+
13
+ set anonymousToken(value: string | undefined) {
14
+ setCookie("anonymous-token", value)
15
+ }
16
+ }
@@ -0,0 +1 @@
1
+ export type HttpMethod = "POST" | "GET" | "PUT" | "DELETE" | "PATCH"
@@ -1,6 +1,8 @@
1
1
  import { Service } from "./service"
2
2
  import { type Middleware } from "../middleware"
3
3
  import { type Disposable } from "../disposable"
4
+ import { Request } from "node-fetch"
5
+ import { Response } from "node-fetch"
4
6
 
5
7
  export class MiddlewareService extends Service {
6
8
  private _middlewares: Middleware[] = []
@@ -1,3 +1,6 @@
1
+ import { Request, Response, Headers } from "node-fetch"
2
+ import FormData from "form-data"
3
+
1
4
  export class RequestBuilder {
2
5
  private readonly _headers: Headers
3
6
  private readonly _searchParams: URLSearchParams
@@ -58,7 +61,7 @@ export class RequestBuilder {
58
61
  const req = new Request(url, {
59
62
  method: "POST",
60
63
  headers: this._headers,
61
- body
64
+ body: body
62
65
  })
63
66
 
64
67
  // discard content type
@@ -73,7 +76,7 @@ export class RequestBuilder {
73
76
  public async sendPostJson(body: object | null | undefined): Promise<Response> {
74
77
  const url = this._url
75
78
  url.search = this._searchParams.toString()
76
- let json: string | null | undefined = null
79
+ let json: string | undefined = undefined
77
80
  if (body !== undefined && body !== null && typeof body === "object") {
78
81
  json = JSON.stringify(body)
79
82
  }
@@ -112,7 +115,7 @@ export class RequestBuilder {
112
115
  public async sendPutJson(body: object | null | undefined): Promise<Response> {
113
116
  const url = this._url
114
117
  url.search = this._searchParams.toString()
115
- let json: string | null | undefined = null
118
+ let json: string | undefined = undefined
116
119
  if (body !== undefined && body !== null && typeof body === "object") {
117
120
  json = JSON.stringify(body)
118
121
  }
@@ -1,3 +1,5 @@
1
+ import { Response } from "node-fetch"
2
+
1
3
  export class ResponseUtils {
2
4
  public static isOk(response?: Response | null): boolean {
3
5
  return response !== undefined && response !== null && response.ok
@@ -1,6 +1,8 @@
1
1
  import { Service, type ServiceContext } from "./service"
2
2
  import { MiddlewareService } from "./middlewareService"
3
3
  import { RequestBuilder } from "./requestBuilder"
4
+ import { Request, Response, Headers } from "node-fetch"
5
+ import fetch from "node-fetch"
4
6
 
5
7
  /**
6
8
  * Options for the RpcService.
@@ -13,6 +13,20 @@ export class UserProfileService extends Service {
13
13
  return this.impl
14
14
  }
15
15
 
16
+ async merge(anonymous_token: string) {
17
+ const rpc = this.resolve(RpcService) as RpcService
18
+ const response = await rpc.requestBuilder("api/v1/Users/anonymous/merge")
19
+ .sendPostJson({
20
+ anonymousToken: anonymous_token
21
+ })
22
+
23
+ if (ResponseUtils.isFail(response)) {
24
+ await ResponseUtils.throwError("Failed to merge anonymous user", response)
25
+ }
26
+
27
+ await this.fetch()
28
+ }
29
+
16
30
  async fetch() {
17
31
  const rpc = this.resolve(RpcService) as RpcService
18
32
  const response = await rpc.requestBuilder("api/v1/Users/self2").sendGet()
@@ -20,6 +20,7 @@ export class AnswerImpl extends Answer {
20
20
  private _question?: string
21
21
  private _sources?: SourceDto[]
22
22
  private _answer?: string
23
+ private _timestamp?: number
23
24
 
24
25
  constructor(
25
26
  private readonly chat: Chat,
@@ -32,6 +33,7 @@ export class AnswerImpl extends Answer {
32
33
  this._question = answer.question
33
34
  this._answer = answer.context
34
35
  this._sources = answer.sources
36
+ this._timestamp = answer.timestamp
35
37
 
36
38
  return this
37
39
  }
@@ -66,6 +68,10 @@ export class AnswerImpl extends Answer {
66
68
  return <string>this._answer
67
69
  }
68
70
 
71
+ get timestamp(): number {
72
+ return <number>this._timestamp
73
+ }
74
+
69
75
  public fetchAfter() {
70
76
  if (this._status === undefined || this._status === AnswerStatus.RUNNING) {
71
77
  setTimeout(async () => await this.fetch(), 300)
@@ -102,18 +108,31 @@ export class AnswerImpl extends Answer {
102
108
 
103
109
  if (this.getStep(StepType.GENERATE_ANSWER) !== undefined) {
104
110
  const step = this.getStep(StepType.GENERATE_ANSWER)
105
- this._answer = step?.tokens.join("")
111
+ const step_tokens = step?.tokens.join("")
112
+ if (this._answer !== step_tokens) {
113
+ this._answer = step_tokens
114
+
115
+ this.dispatch({
116
+ type: AnswerEvent.UPDATED,
117
+ data: this
118
+ })
119
+ }
106
120
  }
107
121
 
108
- if (this.getStep(StepType.SOURCES) !== undefined) {
122
+ if (this.getStep(StepType.SOURCES) !== undefined && this._sources === undefined) {
109
123
  const sources_step = this.getStep(StepType.SOURCES)
110
124
  this._sources = sources_step?.sources
125
+
126
+ this.dispatch({
127
+ type: AnswerEvent.UPDATED,
128
+ data: this
129
+ })
111
130
  }
112
131
 
113
- this.dispatch({
114
- type: AnswerEvent.UPDATED,
115
- data: this
116
- })
132
+ if (this.getStep(StepType.DONE) !== undefined) {
133
+ const step = this.getStep(StepType.DONE)
134
+ this._timestamp = Date.parse(step!.end_at)
135
+ }
117
136
 
118
137
  this.fetchAfter()
119
138
  }
@@ -41,6 +41,11 @@ export abstract class Answer extends EventDispatcher<AnswerEvent, Answer> {
41
41
  */
42
42
  abstract get sources(): SourceDto[]
43
43
 
44
+ /**
45
+ * Answer time.
46
+ */
47
+ abstract get timestamp(): number
48
+
44
49
  /**
45
50
  * Cancel answer
46
51
  */
@@ -77,7 +77,7 @@ export class ChatImpl extends Chat implements Disposable {
77
77
  }
78
78
 
79
79
  // parse answer id from the server's response
80
- const id = (await response!.json()).id
80
+ const id = (await response!.json() as { id: string }).id
81
81
 
82
82
  // create answer implementation
83
83
  const answer = await new AnswerImpl(this, this.context).initNew(id, message)
@@ -84,7 +84,9 @@ export class ChatsImpl extends Chats {
84
84
  }
85
85
 
86
86
  // parse workspace from the server's response
87
- const content = (await response!.json()).chat as ChatDto
87
+ const content = (await response!.json() as {
88
+ chat: ChatDto
89
+ }).chat as ChatDto
88
90
 
89
91
  // create workspace implementation
90
92
  const chat = new ChatImpl(this.context, this.organization)
@@ -3,22 +3,23 @@ import { Disposable } from "../../disposable"
3
3
  import { FileDto, FileProgressDto } from "../../dto/workspacesResponse"
4
4
  import { RpcService } from "../../services/rpcService"
5
5
  import { ResponseUtils } from "../../services/responseUtils"
6
- import { File } from "./file"
6
+ import { File, FileStatus } from "./file"
7
7
  import { FilesEvent } from "./files"
8
8
 
9
9
  export class FileImpl extends File implements Disposable {
10
10
  private _isDisposed: boolean = false
11
11
  private _content?: FileDto
12
- private _status?: FileProgressDto
13
-
12
+ private _progress?: FileProgressDto
14
13
 
15
14
  constructor(private readonly context: Context) {
16
15
  super()
17
16
  }
18
17
 
19
- public initFrom(file: FileDto): File {
18
+ async initFrom(file: FileDto): Promise<File> {
20
19
  this._content = file
21
20
 
21
+ await this.updateStatus()
22
+
22
23
  return this
23
24
  }
24
25
 
@@ -42,8 +43,19 @@ export class FileImpl extends File implements Disposable {
42
43
  return <number>this._content?.createdAt
43
44
  }
44
45
 
45
- get status(): FileProgressDto {
46
- return <FileProgressDto>this._status
46
+ get progress(): FileProgressDto {
47
+ return <FileProgressDto>this._progress
48
+ }
49
+
50
+ get status(): FileStatus {
51
+ if (this._progress === undefined || this._progress.success === null ||
52
+ (this._progress.success && this._progress.completed_parts_count !== this._progress.file_parts_count)) {
53
+ return FileStatus.UPLOADING
54
+ } else if (this._progress.success) {
55
+ return FileStatus.SUCCESS
56
+ } else {
57
+ return FileStatus.FAILED
58
+ }
47
59
  }
48
60
 
49
61
  async url(): Promise<string> {
@@ -60,7 +72,13 @@ export class FileImpl extends File implements Disposable {
60
72
  )
61
73
  }
62
74
 
63
- return (await response!.json()).url
75
+ return (await response!.json() as { url: string }).url
76
+ }
77
+
78
+ public fetchAfter() {
79
+ if (this.status === FileStatus.UPLOADING) {
80
+ setTimeout(async () => await this.updateStatus(), 500)
81
+ }
64
82
  }
65
83
 
66
84
  async updateStatus(): Promise<void> {
@@ -74,14 +92,22 @@ export class FileImpl extends File implements Disposable {
74
92
  await ResponseUtils.throwError(`Failed to get file ${this.id}`, response)
75
93
  }
76
94
 
77
- this._status = (await response!.json()).progress as FileProgressDto
78
-
79
-
80
- // dispatch event, file updated
81
- this.dispatch({
82
- type: FilesEvent.UPDATED,
83
- data: this
84
- })
95
+ const prev_progress = this._progress
96
+ this._progress = (await response!.json() as {
97
+ progress: FileProgressDto
98
+ }).progress as FileProgressDto
99
+
100
+ if (prev_progress === undefined ||
101
+ (this.progress.success !== null && this.progress.completed_parts_count > prev_progress.completed_parts_count) ||
102
+ this.status === FileStatus.SUCCESS ||
103
+ this.status === FileStatus.FAILED) {
104
+ // dispatch event, file updated
105
+ this.dispatch({
106
+ type: FilesEvent.UPDATED,
107
+ data: this
108
+ })
109
+ }
85
110
 
111
+ this.fetchAfter()
86
112
  }
87
113
  }
@@ -4,12 +4,18 @@ import { FilesEvent } from "./files"
4
4
 
5
5
  export type FileId = string
6
6
 
7
+ export enum FileStatus {
8
+ UPLOADING = "uploading",
9
+ SUCCESS = "success",
10
+ FAILED = "failed"
11
+ }
12
+
7
13
  /**
8
14
  * File.
9
15
  */
10
16
  export abstract class File extends EventDispatcher<
11
- FilesEvent,
12
- File
17
+ FilesEvent,
18
+ File
13
19
  > {
14
20
  /**
15
21
  * File id.
@@ -26,15 +32,18 @@ File
26
32
  */
27
33
  abstract get createdAt(): number
28
34
 
29
- abstract get status(): FileProgressDto
35
+ /**
36
+ * File uploading progress
37
+ */
38
+ abstract get progress(): FileProgressDto
30
39
 
31
40
  /**
32
- * Get temporary url.
41
+ * File uploading status
33
42
  */
34
- abstract url(): Promise<string>
43
+ abstract get status(): FileStatus
35
44
 
36
45
  /**
37
- * Get file status.
46
+ * Get temporary url.
38
47
  */
39
- abstract updateStatus(): Promise<void>
48
+ abstract url(): Promise<string>
40
49
  }
@@ -8,6 +8,7 @@ import { ResponseUtils } from "../../services/responseUtils"
8
8
  import { File } from "./file"
9
9
  import { FilesPage } from "./filesPage"
10
10
  import { FilesPageImpl } from "./filesPage.impl"
11
+ import FormData from "form-data"
11
12
 
12
13
  export class FilesImpl extends Files {
13
14
  constructor(
@@ -20,16 +21,16 @@ export class FilesImpl extends Files {
20
21
  // Object used as files page data, returned by "query"
21
22
  public filesList?: FilesPage
22
23
 
23
- async upload(files: any[]): Promise<File[]> {
24
+ async upload(files: UploadFile[]): Promise<File[]> {
24
25
  const loaded_files = []
25
- for ( const file of files ){
26
+ for (const file of files) {
26
27
  loaded_files.push(await this.internalUpload(file))
27
28
  }
28
29
  return loaded_files
29
30
  }
30
31
 
31
32
  async delete(ids: string[]): Promise<void> {
32
- for ( const id of ids ){
33
+ for (const id of ids) {
33
34
  await this.internalDeleteFile(id)
34
35
  }
35
36
  }
@@ -135,7 +136,7 @@ export class FilesImpl extends Files {
135
136
  for (const fl of files.files) {
136
137
 
137
138
  // create file implementation
138
- const file = new FileImpl(this.context).initFrom(fl)
139
+ const file = await new FileImpl(this.context).initFrom(fl)
139
140
 
140
141
  // add file to the collection
141
142
  filesList.files.push(file)
@@ -158,7 +159,7 @@ export class FilesImpl extends Files {
158
159
  form.append("organizationId", this.workspace.organization.id)
159
160
  form.append("workspaceId", this.workspace.id)
160
161
  form.append("name", file.name)
161
- form.append("file", file, file.name)
162
+ form.append("file", file.stream, file.name)
162
163
 
163
164
  // send request to the server
164
165
  const response = await this.context
@@ -172,10 +173,12 @@ export class FilesImpl extends Files {
172
173
  }
173
174
 
174
175
  // parse file from the server's response
175
- const result = (await response!.json()).file as FileDto
176
+ const result = (await response!.json() as { file: FileDto }).file as FileDto
176
177
 
177
178
  // create file implementation
178
- const fileImpl = new FileImpl(this.context).initFrom(result)
179
+ const fileImpl = new FileImpl(this.context)
180
+
181
+ await fileImpl.initFrom(result)
179
182
 
180
183
  // TODO: why is this here?
181
184
  this.filesList?.files.push(fileImpl)
@@ -14,7 +14,11 @@ export enum FilesEvent {
14
14
  /**
15
15
  * Upload file.
16
16
  */
17
- export type UploadFile = globalThis.File
17
+ export type UploadFile = {
18
+ name: string
19
+ type: "application/pdf"
20
+ stream: ReadableStream
21
+ }
18
22
 
19
23
  /**
20
24
  * Files storage.
@@ -38,7 +38,7 @@ export class GroupImpl extends Group implements Disposable {
38
38
 
39
39
  // wait for all promises
40
40
  await Promise.all([groupPromise, workspacePromise])
41
-
41
+
42
42
  return this
43
43
  }
44
44
 
@@ -94,7 +94,9 @@ export class OrganizationImpl extends Organization implements Disposable {
94
94
  )
95
95
  }
96
96
 
97
- return (await response!.json()).members as UserDto[]
97
+ return (await response!.json() as {
98
+ members: UserDto[]
99
+ }).members as UserDto[]
98
100
  }
99
101
 
100
102
  async change(name: string, description: string): Promise<void> {
@@ -143,7 +145,7 @@ export class OrganizationImpl extends Organization implements Disposable {
143
145
  data: this
144
146
  })
145
147
  }
146
-
148
+
147
149
  async createInviteLink(emails: string[], accessGroups: string[]): Promise<void> {
148
150
  const response = await this.context
149
151
  .resolve(RpcService)
@@ -6,7 +6,6 @@ import { EventDispatcher } from "../../events"
6
6
  import { UserDto } from "../../dto/userInfoResponse"
7
7
  import { GroupId } from "../groups/group"
8
8
 
9
-
10
9
  /**
11
10
  * Organization event.
12
11
  */
@@ -18,9 +17,9 @@ export enum OrganizationEvent {
18
17
  * Organization.
19
18
  */
20
19
  export abstract class Organization extends EventDispatcher<
21
- OrganizationEvent,
22
- Organization
23
- > {
20
+ OrganizationEvent,
21
+ Organization
22
+ > {
24
23
  /**
25
24
  * Organization id.
26
25
  */
@@ -147,7 +147,9 @@ export class OrganizationsImpl extends Organizations {
147
147
  response
148
148
  )
149
149
  }
150
- const content = (await response!.json()).organization as OrganizationDto
150
+ const content = (await response!.json() as {
151
+ organization: OrganizationDto
152
+ }).organization as OrganizationDto
151
153
 
152
154
  // create organization and init from content
153
155
  const org = await new OrganizationImpl(this.context).initFrom(content, true)
@@ -32,6 +32,13 @@ export class UserProfileImpl extends UserProfile {
32
32
  throw new Error("The profile is not loaded.")
33
33
  }
34
34
 
35
+ get isAnonymous(): boolean {
36
+ if (this.content) {
37
+ return this.content.user.isAnonymousMode
38
+ }
39
+ throw new Error("The profile is not loaded.")
40
+ }
41
+
35
42
  get createdAt(): Date {
36
43
  if (this.content) {
37
44
  return new Date(this.content.user.created_at)
@@ -30,6 +30,11 @@ export abstract class UserProfile extends EventDispatcher<
30
30
  */
31
31
  abstract get isDeleted(): boolean
32
32
 
33
+ /**
34
+ * Is user anonymous
35
+ */
36
+ abstract get isAnonymous(): boolean
37
+
33
38
  /**
34
39
  * Created at.
35
40
  */
@@ -63,7 +63,7 @@ export class WorkspaceImpl extends Workspace {
63
63
  )
64
64
  }
65
65
 
66
- return (await response!.json()).count
66
+ return ((await response!.json()) as { count: number }).count
67
67
  }
68
68
 
69
69
  async change(name: string, description: string): Promise<void> {