@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.
- package/LICENSE +201 -0
- package/README.md +174 -1
- package/dist/dataisland-sdk.d.ts +1594 -0
- package/dist/dataisland-sdk.js +2890 -0
- package/dist/dataisland-sdk.js.map +1 -0
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +41 -3
- package/src/appBuilder.ts +24 -5
- package/src/commands/startCommandHandler.ts +14 -0
- package/src/context.ts +31 -0
- package/src/credentials.ts +31 -9
- package/src/dataIslandApp.ts +59 -0
- package/src/disposable.ts +4 -5
- package/src/dto/accessGroupResponse.ts +35 -0
- package/src/dto/chatResponse.ts +103 -0
- package/src/dto/userInfoResponse.ts +47 -0
- package/src/dto/workspacesResponse.ts +49 -0
- package/src/events.ts +13 -17
- package/src/index.ts +44 -18
- package/src/internal/app.impl.ts +97 -32
- package/src/internal/appBuilder.impl.ts +39 -12
- package/src/internal/createApp.impl.ts +5 -5
- package/src/middleware.ts +1 -1
- package/src/services/commandService.ts +44 -0
- package/src/services/credentialService.ts +3 -3
- package/src/services/middlewareService.ts +8 -6
- package/src/services/organizationService.ts +28 -0
- package/src/services/requestBuilder.ts +127 -0
- package/src/services/responseUtils.ts +32 -0
- package/src/services/rpcService.ts +129 -52
- package/src/services/service.ts +10 -8
- package/src/services/userProfileService.ts +38 -0
- package/src/storages/chats/answer.impl.ts +163 -0
- package/src/storages/chats/answer.ts +42 -0
- package/src/storages/chats/chat.impl.ts +87 -0
- package/src/storages/chats/chat.ts +38 -0
- package/src/storages/chats/chats.impl.ts +142 -0
- package/src/storages/chats/chats.ts +47 -0
- package/src/storages/files/file.impl.ts +69 -0
- package/src/storages/files/file.ts +28 -0
- package/src/storages/files/files.impl.ts +213 -0
- package/src/storages/files/files.ts +38 -0
- package/src/storages/files/filesPage.ts +27 -0
- package/src/storages/groups/groups.impl.ts +326 -0
- package/src/storages/groups/groups.ts +101 -0
- package/src/storages/organizations/organization.impl.ts +95 -0
- package/src/storages/organizations/organization.ts +44 -0
- package/src/storages/organizations/organizations.impl.ts +197 -0
- package/src/storages/organizations/organizations.ts +56 -0
- package/src/storages/user/userProfile.impl.ts +56 -0
- package/src/storages/user/userProfile.ts +42 -0
- package/src/storages/workspaces/workspace.impl.ts +109 -0
- package/src/storages/workspaces/workspace.ts +49 -0
- package/src/storages/workspaces/workspaces.impl.ts +212 -0
- package/src/storages/workspaces/workspaces.ts +53 -0
- package/src/unitTest.ts +53 -0
- package/.browserslistrc +0 -5
- package/.editorconfig +0 -22
- package/.eslintrc.json +0 -44
- package/.github/workflows/publish-npm.yml +0 -28
- package/.prettierignore +0 -1
- package/.prettierrc +0 -11
- package/.yarnrc +0 -2
- package/babel.config.js +0 -6
- package/jest.config.ts +0 -199
- package/src/appSdk.ts +0 -40
- package/src/internal/context.ts +0 -13
- package/src/types.ts +0 -110
- package/test/disposable.test.ts +0 -39
- package/test/events.test.ts +0 -151
- package/test/index.test.ts +0 -83
- package/test/registry.test.ts +0 -44
- package/tsconfig.json +0 -31
@@ -0,0 +1,47 @@
|
|
1
|
+
import { WorkspaceDto } from "./workspacesResponse"
|
2
|
+
|
3
|
+
export interface UserInfoResponse {
|
4
|
+
adminInOrganization: string[]
|
5
|
+
organizations: OrganizationDto[]
|
6
|
+
user: UserDto
|
7
|
+
}
|
8
|
+
|
9
|
+
export interface UserDto {
|
10
|
+
id: string
|
11
|
+
isDeleted: boolean
|
12
|
+
created_at: number
|
13
|
+
modified_at: number
|
14
|
+
profile: ProfileDto
|
15
|
+
settings?: UserSettings | null
|
16
|
+
}
|
17
|
+
|
18
|
+
export interface ProfileDto {
|
19
|
+
name: string
|
20
|
+
email: string
|
21
|
+
}
|
22
|
+
|
23
|
+
export interface UserSettings {
|
24
|
+
activeOrganizationId: string
|
25
|
+
activeWorkspaceId: string
|
26
|
+
}
|
27
|
+
|
28
|
+
export interface OrganizationProfileDto {
|
29
|
+
name: string
|
30
|
+
description: string
|
31
|
+
}
|
32
|
+
|
33
|
+
export interface OrganizationDto {
|
34
|
+
id: string
|
35
|
+
createdAt: number
|
36
|
+
modifiedAt: number
|
37
|
+
membersCount: number
|
38
|
+
profile: OrganizationProfileDto
|
39
|
+
}
|
40
|
+
|
41
|
+
export interface OrganizationWorkspaces extends OrganizationDto {
|
42
|
+
workspaces: WorkspaceDto[]
|
43
|
+
}
|
44
|
+
|
45
|
+
export interface MembersResponse {
|
46
|
+
members: UserDto
|
47
|
+
}
|
@@ -0,0 +1,49 @@
|
|
1
|
+
import { WorkspaceId } from "../storages/workspaces/workspaces"
|
2
|
+
import { FileId } from "../storages/files/file"
|
3
|
+
|
4
|
+
export interface WorkspaceProfileDto {
|
5
|
+
name: string
|
6
|
+
description: string
|
7
|
+
}
|
8
|
+
|
9
|
+
export interface WorkspaceDto {
|
10
|
+
id: WorkspaceId
|
11
|
+
createdAt: number
|
12
|
+
modifiedAt: number
|
13
|
+
profile: WorkspaceProfileDto
|
14
|
+
}
|
15
|
+
|
16
|
+
export interface WorkspacesResponse {
|
17
|
+
workspaces: WorkspaceDto[]
|
18
|
+
}
|
19
|
+
|
20
|
+
export interface FileUrlDto {
|
21
|
+
url: string
|
22
|
+
}
|
23
|
+
|
24
|
+
export interface FileProgressDto {
|
25
|
+
file_id: FileId
|
26
|
+
file_parts_count: number
|
27
|
+
completed_parts_count: number
|
28
|
+
success: boolean
|
29
|
+
error?: string
|
30
|
+
}
|
31
|
+
|
32
|
+
export interface FileDto {
|
33
|
+
id: string
|
34
|
+
createdAt: number
|
35
|
+
modifiedAt: number
|
36
|
+
name: string
|
37
|
+
description: string
|
38
|
+
url: string
|
39
|
+
hash: string
|
40
|
+
organizationId: string
|
41
|
+
workspaceId: string
|
42
|
+
isProcessedSuccessfully: boolean
|
43
|
+
}
|
44
|
+
|
45
|
+
export interface FileListResponse {
|
46
|
+
files: FileDto[]
|
47
|
+
totalFilesCount: number
|
48
|
+
filesPerPage: number
|
49
|
+
}
|
package/src/events.ts
CHANGED
@@ -1,29 +1,25 @@
|
|
1
|
-
import { type Disposable, DisposableContainer } from
|
1
|
+
import { type Disposable, DisposableContainer } from "./disposable"
|
2
2
|
|
3
|
-
export interface
|
4
|
-
|
3
|
+
export interface Input<EventType, DataType> {
|
4
|
+
type?: EventType
|
5
|
+
data: DataType
|
5
6
|
}
|
6
7
|
|
7
|
-
export interface Input<
|
8
|
-
type?: ET
|
9
|
-
data: DT
|
10
|
-
}
|
11
|
-
|
12
|
-
export interface Event<ET, DT> extends Input<ET, DT> {
|
8
|
+
export interface Event<EventType, DataType> extends Input<EventType, DataType> {
|
13
9
|
unsubscribe: () => void
|
14
10
|
}
|
15
11
|
|
16
|
-
export interface EventSubscriber<
|
17
|
-
subscribe: (callback: (event: Event<
|
12
|
+
export interface EventSubscriber<EventType, DataType> {
|
13
|
+
subscribe: (callback: (event: Event<EventType, DataType>) => void, type?: EventType) => Disposable
|
18
14
|
}
|
19
15
|
|
20
|
-
export class EventDispatcher<
|
16
|
+
export class EventDispatcher<EventType, DataType> implements EventSubscriber<EventType, DataType> {
|
21
17
|
private _listeners: Array<{
|
22
|
-
callback: (value: Event<
|
18
|
+
callback: (value: Event<EventType, DataType>) => void
|
23
19
|
disposable: Disposable
|
24
20
|
}> = []
|
25
21
|
|
26
|
-
dispatch(input: Input<
|
22
|
+
dispatch(input: Input<EventType, DataType>): void {
|
27
23
|
this._listeners.slice().forEach(it => {
|
28
24
|
const value = {
|
29
25
|
type: input.type,
|
@@ -31,16 +27,16 @@ export class EventDispatcher<ET, DT> implements EventSubscriber<ET, DT> {
|
|
31
27
|
unsubscribe: () => {
|
32
28
|
it.disposable.dispose()
|
33
29
|
}
|
34
|
-
} satisfies Event<
|
30
|
+
} satisfies Event<EventType, DataType>
|
35
31
|
it.callback(value)
|
36
32
|
})
|
37
33
|
}
|
38
34
|
|
39
|
-
subscribe(callback: (event: Event<
|
35
|
+
subscribe(callback: (event: Event<EventType, DataType>) => void, type?: EventType): Disposable {
|
40
36
|
const container = new DisposableContainer()
|
41
37
|
if (type !== undefined) {
|
42
38
|
const cb = callback
|
43
|
-
const listener = (evt: Event<
|
39
|
+
const listener = (evt: Event<EventType, DataType>): void => {
|
44
40
|
if (evt.type === type) {
|
45
41
|
cb(evt)
|
46
42
|
}
|
package/src/index.ts
CHANGED
@@ -1,16 +1,29 @@
|
|
1
|
-
import { version } from
|
2
|
-
import { _createApp } from
|
3
|
-
import { type AppBuilder } from
|
4
|
-
import { type
|
1
|
+
import { version } from "../package.json"
|
2
|
+
import { _createApp } from "./internal/createApp.impl"
|
3
|
+
import { type AppBuilder } from "./appBuilder"
|
4
|
+
import { type DataIslandApp } from "./dataIslandApp"
|
5
5
|
|
6
|
-
export * from
|
7
|
-
export * from
|
8
|
-
export * from
|
9
|
-
export * from
|
10
|
-
export * from
|
6
|
+
export * from "./events"
|
7
|
+
export * from "./disposable"
|
8
|
+
export * from "./credentials"
|
9
|
+
export * from "./dataIslandApp"
|
10
|
+
export * from "./appBuilder"
|
11
|
+
export * from "./context"
|
12
|
+
export * from "./middleware"
|
13
|
+
export * from "./storages/organizations/organizations"
|
14
|
+
export * from "./storages/organizations/organization"
|
15
|
+
export * from "./storages/workspaces/workspaces"
|
16
|
+
export * from "./storages/workspaces/workspace"
|
17
|
+
export * from "./storages/groups/groups"
|
18
|
+
export * from "./storages/user/userProfile"
|
19
|
+
export * from "./storages/files/files"
|
20
|
+
export * from "./storages/files/file"
|
21
|
+
export * from "./storages/files/filesPage"
|
22
|
+
export * from "./storages/chats/chats"
|
23
|
+
export * from "./storages/chats/chat"
|
11
24
|
|
12
|
-
const _appsNotReady = new Map<string, Promise<
|
13
|
-
const _appsReady = new Map<string,
|
25
|
+
const _appsNotReady = new Map<string, Promise<DataIslandApp>>()
|
26
|
+
const _appsReady = new Map<string, DataIslandApp>()
|
14
27
|
|
15
28
|
/**
|
16
29
|
* Current SDK version.
|
@@ -20,14 +33,17 @@ export const SDK_VERSION = version
|
|
20
33
|
/**
|
21
34
|
* Default DataIsland App name.
|
22
35
|
*/
|
23
|
-
export const DEFAULT_NAME =
|
36
|
+
export const DEFAULT_NAME = "[DEFAULT]"
|
24
37
|
|
25
38
|
/**
|
26
39
|
* Default DataIsland App host.
|
27
40
|
*/
|
28
|
-
export const DEFAULT_HOST =
|
41
|
+
export const DEFAULT_HOST = "https://api.dataisland.com.ua"
|
29
42
|
|
30
|
-
|
43
|
+
/**
|
44
|
+
* Returns a list of DataIsland App instances.
|
45
|
+
*/
|
46
|
+
export function dataIslandInstances(): DataIslandApp[] {
|
31
47
|
return Array.from(_appsReady.values())
|
32
48
|
}
|
33
49
|
|
@@ -38,19 +54,19 @@ export function sdks(): AppSdk[] {
|
|
38
54
|
* @returns A DataIsland App instance.
|
39
55
|
* @example
|
40
56
|
* ```js
|
41
|
-
* import {
|
57
|
+
* import { dataIslandApp, DEFAULT_NAME } from '@neuralinnovations/dataisland-sdk'
|
42
58
|
*
|
43
|
-
* const app = await
|
59
|
+
* const app = await dataIslandApp(DEFAULT_NAME, builder => {
|
44
60
|
* builder.useHost("https://dataisland.com.ua")
|
45
61
|
* builder.useAutomaticDataCollectionEnabled(true)
|
46
62
|
* builder.useCredential(new BasicCredential("email", "password"))
|
47
63
|
* })
|
48
64
|
* ```
|
49
65
|
*/
|
50
|
-
export async function
|
66
|
+
export async function dataIslandApp(
|
51
67
|
name?: string,
|
52
68
|
setup?: (builder: AppBuilder) => Promise<void>
|
53
|
-
): Promise<
|
69
|
+
): Promise<DataIslandApp> {
|
54
70
|
name = name ?? DEFAULT_NAME
|
55
71
|
|
56
72
|
let appPromise = _appsNotReady.get(name)
|
@@ -62,8 +78,18 @@ export async function appSdk(
|
|
62
78
|
})
|
63
79
|
.catch(reason => {
|
64
80
|
console.error(`Error: ${reason}`)
|
81
|
+
_appsNotReady.delete(name ?? DEFAULT_NAME)
|
65
82
|
})
|
66
83
|
_appsNotReady.set(name, appPromise)
|
84
|
+
} else {
|
85
|
+
if (setup !== undefined) {
|
86
|
+
throw new Error(
|
87
|
+
`DataIsland ${name} is initializing. You can't setup the same again.`
|
88
|
+
)
|
89
|
+
}
|
67
90
|
}
|
68
91
|
return await appPromise
|
69
92
|
}
|
93
|
+
|
94
|
+
export { File } from "./storages/files/file"
|
95
|
+
export { FilesPage } from "./storages/files/filesPage"
|
package/src/internal/app.impl.ts
CHANGED
@@ -1,17 +1,27 @@
|
|
1
|
-
import { DEFAULT_HOST } from
|
2
|
-
import { type AppBuilder } from
|
3
|
-
import { AppBuilderImplementation } from
|
4
|
-
import { type Constructor, Registry } from
|
5
|
-
import { Context } from
|
6
|
-
import { DisposableContainer, type Lifetime } from
|
7
|
-
import { type Service, ServiceContext } from
|
8
|
-
import { CredentialService } from
|
9
|
-
import { MiddlewareService } from
|
10
|
-
import { type CredentialBase } from
|
11
|
-
import {
|
12
|
-
import { RpcService
|
13
|
-
|
14
|
-
|
1
|
+
import { DEFAULT_HOST } from "../index"
|
2
|
+
import { type AppBuilder } from "../appBuilder"
|
3
|
+
import { AppBuilderImplementation } from "./appBuilder.impl"
|
4
|
+
import { type Constructor, Registry } from "./registry"
|
5
|
+
import { Context } from "../context"
|
6
|
+
import { DisposableContainer, type Lifetime } from "../disposable"
|
7
|
+
import { type Service, ServiceContext } from "../services/service"
|
8
|
+
import { CredentialService } from "../services/credentialService"
|
9
|
+
import { MiddlewareService } from "../services/middlewareService"
|
10
|
+
import { type CredentialBase } from "../credentials"
|
11
|
+
import { DataIslandApp } from "../dataIslandApp"
|
12
|
+
import { RpcService } from "../services/rpcService"
|
13
|
+
import { CommandService } from "../services/commandService"
|
14
|
+
import {
|
15
|
+
StartCommandHandler,
|
16
|
+
StartCommand
|
17
|
+
} from "../commands/startCommandHandler"
|
18
|
+
import { UserProfileService } from "../services/userProfileService"
|
19
|
+
import { OrganizationService } from "../services/organizationService"
|
20
|
+
import { Organizations } from "../storages/organizations/organizations"
|
21
|
+
import { UserProfile } from "../storages/user/userProfile"
|
22
|
+
import { isUnitTest, UnitTest } from "../unitTest"
|
23
|
+
|
24
|
+
export class DataIslandAppImpl extends DataIslandApp {
|
15
25
|
readonly name: string
|
16
26
|
private _host: string = DEFAULT_HOST
|
17
27
|
private _automaticDataCollectionEnabled: boolean = true
|
@@ -20,10 +30,17 @@ export class AppImplementation implements AppSdk {
|
|
20
30
|
private readonly _disposable: DisposableContainer
|
21
31
|
|
22
32
|
constructor(name: string) {
|
33
|
+
super()
|
23
34
|
this.name = name
|
24
35
|
this._registry = new Registry()
|
25
36
|
this._disposable = new DisposableContainer()
|
26
|
-
this._context = new Context(this._registry, this._disposable.lifetime)
|
37
|
+
this._context = new Context(this._registry, this._disposable.lifetime, name)
|
38
|
+
|
39
|
+
this._registry.map(Context).asValue(this._context)
|
40
|
+
}
|
41
|
+
|
42
|
+
get context(): Context {
|
43
|
+
return this._context
|
27
44
|
}
|
28
45
|
|
29
46
|
get credential(): CredentialBase | undefined {
|
@@ -48,12 +65,45 @@ export class AppImplementation implements AppSdk {
|
|
48
65
|
return this._host
|
49
66
|
}
|
50
67
|
|
68
|
+
get organizations(): Organizations {
|
69
|
+
return this.resolve(OrganizationService)?.organizations as Organizations
|
70
|
+
}
|
71
|
+
|
72
|
+
get userProfile(): UserProfile {
|
73
|
+
return this.resolve(UserProfileService)?.userProfile as UserProfile
|
74
|
+
}
|
75
|
+
|
51
76
|
async initialize(
|
52
77
|
setup: ((builder: AppBuilder) => Promise<void>) | undefined
|
53
78
|
): Promise<void> {
|
54
79
|
// create app builder
|
55
80
|
const builder = new AppBuilderImplementation()
|
56
81
|
|
82
|
+
// register commands
|
83
|
+
builder.registerCommand(StartCommand, (context: Context) => {
|
84
|
+
return new StartCommandHandler(context)
|
85
|
+
})
|
86
|
+
|
87
|
+
// register services
|
88
|
+
builder.registerService(CredentialService, (context: ServiceContext) => {
|
89
|
+
return new CredentialService(context)
|
90
|
+
})
|
91
|
+
builder.registerService(MiddlewareService, (context: ServiceContext) => {
|
92
|
+
return new MiddlewareService(context)
|
93
|
+
})
|
94
|
+
builder.registerService(RpcService, (context: ServiceContext) => {
|
95
|
+
return new RpcService(context, builder.host)
|
96
|
+
})
|
97
|
+
builder.registerService(CommandService, (context: ServiceContext) => {
|
98
|
+
return new CommandService(context)
|
99
|
+
})
|
100
|
+
builder.registerService(UserProfileService, (context: ServiceContext) => {
|
101
|
+
return new UserProfileService(context)
|
102
|
+
})
|
103
|
+
builder.registerService(OrganizationService, (context: ServiceContext) => {
|
104
|
+
return new OrganizationService(context)
|
105
|
+
})
|
106
|
+
|
57
107
|
// call customer setup
|
58
108
|
if (setup !== undefined) {
|
59
109
|
await setup(builder)
|
@@ -66,17 +116,6 @@ export class AppImplementation implements AppSdk {
|
|
66
116
|
this._automaticDataCollectionEnabled =
|
67
117
|
builder.automaticDataCollectionEnabled
|
68
118
|
|
69
|
-
// register services
|
70
|
-
builder.registerService(CredentialService, (context: ServiceContext) => {
|
71
|
-
return new CredentialService(context)
|
72
|
-
})
|
73
|
-
builder.registerService(MiddlewareService, (context: ServiceContext) => {
|
74
|
-
return new MiddlewareService(context)
|
75
|
-
})
|
76
|
-
builder.registerService(RpcService, (context: ServiceContext) => {
|
77
|
-
return new RpcServiceImpl(context, builder.host) as RpcService
|
78
|
-
})
|
79
|
-
|
80
119
|
// register services
|
81
120
|
const services: Array<[ServiceContext, Service]> = []
|
82
121
|
builder.services.forEach(serviceFactory => {
|
@@ -89,31 +128,57 @@ export class AppImplementation implements AppSdk {
|
|
89
128
|
}, serviceContext)
|
90
129
|
const serviceInstance = serviceFactory[1](serviceContext)
|
91
130
|
services.push([serviceContext, serviceInstance])
|
92
|
-
this._registry.
|
93
|
-
provide: () => serviceInstance
|
94
|
-
})
|
131
|
+
this._registry.map(serviceFactory[0]).asValue(serviceInstance)
|
95
132
|
})
|
96
133
|
|
97
134
|
builder.middlewares.forEach(middleware => {
|
98
135
|
this.resolve(MiddlewareService)?.useMiddleware(middleware)
|
99
136
|
})
|
100
137
|
|
138
|
+
builder.commands.forEach(command => {
|
139
|
+
this.resolve(CommandService)?.register(command[0], command[1])
|
140
|
+
})
|
141
|
+
|
142
|
+
this.credential = builder.credential
|
143
|
+
|
144
|
+
//-------------------------------------------------------------------------
|
145
|
+
// register services
|
146
|
+
//-------------------------------------------------------------------------
|
101
147
|
const waitList: Array<Promise<void>> = []
|
102
148
|
// call onRegister service's callback
|
103
149
|
services.forEach(([serviceContext]) => {
|
104
|
-
|
150
|
+
if (typeof serviceContext.onRegister === "function") {
|
151
|
+
waitList.push(serviceContext.onRegister())
|
152
|
+
}
|
105
153
|
})
|
106
154
|
|
155
|
+
// wait for all services to register
|
107
156
|
await Promise.all(waitList)
|
157
|
+
//-------------------------------------------------------------------------
|
108
158
|
|
159
|
+
//-------------------------------------------------------------------------
|
160
|
+
// start services
|
161
|
+
//-------------------------------------------------------------------------
|
109
162
|
waitList.length = 0
|
110
163
|
// call onStart service's callback
|
111
164
|
services.forEach(([serviceContext]) => {
|
112
|
-
|
165
|
+
if (typeof serviceContext.onStart === "function") {
|
166
|
+
waitList.push(serviceContext.onStart())
|
167
|
+
}
|
113
168
|
})
|
114
169
|
|
170
|
+
// wait for all services to start
|
115
171
|
await Promise.all(waitList)
|
172
|
+
//-------------------------------------------------------------------------
|
173
|
+
|
174
|
+
// start app, execute start command
|
175
|
+
if (!isUnitTest(UnitTest.DO_NOT_START)) {
|
176
|
+
await this.context.execute(new StartCommand())
|
177
|
+
}
|
116
178
|
|
117
|
-
|
179
|
+
// log app initialized
|
180
|
+
if (!isUnitTest(UnitTest.DO_NOT_PRINT_INITIALIZED_LOG)) {
|
181
|
+
console.log(`DataIsland ${this.name} initialized`)
|
182
|
+
}
|
118
183
|
}
|
119
184
|
}
|
@@ -1,16 +1,29 @@
|
|
1
|
-
import { AppBuilder } from
|
2
|
-
import { DEFAULT_HOST } from
|
3
|
-
import { type CredentialBase, DefaultCredential } from
|
4
|
-
import type { Middleware } from
|
5
|
-
import { type Service, type ServiceContext } from
|
6
|
-
import { type Constructor } from
|
1
|
+
import { AppBuilder } from "../appBuilder"
|
2
|
+
import { DEFAULT_HOST } from "../index"
|
3
|
+
import { type CredentialBase, DefaultCredential } from "../credentials"
|
4
|
+
import type { Middleware } from "../middleware"
|
5
|
+
import { type Service, type ServiceContext } from "../services/service"
|
6
|
+
import { type Constructor } from "./registry"
|
7
|
+
import { Command, CommandHandler } from "../services/commandService"
|
8
|
+
import { Context } from "../context"
|
9
|
+
import { UnitTest } from "../unitTest"
|
7
10
|
|
8
11
|
export class AppBuilderImplementation extends AppBuilder {
|
12
|
+
envData: Record<string, any> = {
|
13
|
+
unitTest: UnitTest.DO_NOTHING
|
14
|
+
}
|
9
15
|
host: string = DEFAULT_HOST
|
10
16
|
automaticDataCollectionEnabled: boolean = true
|
11
17
|
credential: CredentialBase = new DefaultCredential()
|
12
18
|
middlewares: Middleware[] = []
|
13
19
|
services: Array<[Constructor<any>, (context: ServiceContext) => Service]> = []
|
20
|
+
commands: Array<
|
21
|
+
[Constructor<any>, (context: Context) => CommandHandler<any>]
|
22
|
+
> = []
|
23
|
+
|
24
|
+
get env(): Record<string, any> {
|
25
|
+
return this.envData
|
26
|
+
}
|
14
27
|
|
15
28
|
useHost(host: string): AppBuilder {
|
16
29
|
this.host = host ?? DEFAULT_HOST
|
@@ -20,7 +33,7 @@ export class AppBuilderImplementation extends AppBuilder {
|
|
20
33
|
useAutomaticDataCollectionEnabled(value: boolean): AppBuilder {
|
21
34
|
if (value === undefined || value === null) {
|
22
35
|
throw new Error(
|
23
|
-
|
36
|
+
"useAutomaticDataCollectionEnabled, value is undefined|null"
|
24
37
|
)
|
25
38
|
}
|
26
39
|
this.automaticDataCollectionEnabled = value
|
@@ -29,15 +42,15 @@ export class AppBuilderImplementation extends AppBuilder {
|
|
29
42
|
|
30
43
|
useCredential(credential: CredentialBase): AppBuilder {
|
31
44
|
if (credential === undefined || credential === null) {
|
32
|
-
throw new Error(
|
45
|
+
throw new Error("useCredential, credential is undefined|null")
|
33
46
|
}
|
34
47
|
this.credential = credential
|
35
48
|
return this
|
36
49
|
}
|
37
50
|
|
38
|
-
|
51
|
+
registerMiddleware(middleware: Middleware): AppBuilder {
|
39
52
|
if (middleware === undefined || middleware === null) {
|
40
|
-
throw new Error(
|
53
|
+
throw new Error("addMiddleware, middleware is undefined|null")
|
41
54
|
}
|
42
55
|
this.middlewares.push(middleware)
|
43
56
|
return this
|
@@ -48,12 +61,26 @@ export class AppBuilderImplementation extends AppBuilder {
|
|
48
61
|
factory: (context: ServiceContext) => T
|
49
62
|
): AppBuilder {
|
50
63
|
if (type === undefined || type === null) {
|
51
|
-
throw new Error(
|
64
|
+
throw new Error("registerService, type is undefined|null")
|
52
65
|
}
|
53
66
|
if (factory === undefined || factory === null) {
|
54
|
-
throw new Error(
|
67
|
+
throw new Error("registerService, factory is undefined|null")
|
55
68
|
}
|
56
69
|
this.services.push([type, factory])
|
57
70
|
return this
|
58
71
|
}
|
72
|
+
|
73
|
+
registerCommand<T extends Command>(
|
74
|
+
messageType: Constructor<T>,
|
75
|
+
commandFactory: (context: Context) => CommandHandler<T>
|
76
|
+
): AppBuilder {
|
77
|
+
if (messageType === undefined || messageType === null) {
|
78
|
+
throw new Error("registerCommand, messageType is undefined|null")
|
79
|
+
}
|
80
|
+
if (commandFactory === undefined || commandFactory === null) {
|
81
|
+
throw new Error("registerCommand, commandFactory is undefined|null")
|
82
|
+
}
|
83
|
+
this.commands.push([messageType, commandFactory])
|
84
|
+
return this
|
85
|
+
}
|
59
86
|
}
|
@@ -1,12 +1,12 @@
|
|
1
|
-
import {
|
2
|
-
import { type AppBuilder } from
|
3
|
-
import {
|
1
|
+
import { DataIslandAppImpl } from "./app.impl"
|
2
|
+
import { type AppBuilder } from "../appBuilder"
|
3
|
+
import { DataIslandApp } from "../dataIslandApp"
|
4
4
|
|
5
5
|
export async function _createApp(
|
6
6
|
name: string,
|
7
7
|
setup?: (builder: AppBuilder) => Promise<void>
|
8
|
-
): Promise<
|
9
|
-
const app = new
|
8
|
+
): Promise<DataIslandApp> {
|
9
|
+
const app = new DataIslandAppImpl(name)
|
10
10
|
await app.initialize(setup)
|
11
11
|
return app
|
12
12
|
}
|
package/src/middleware.ts
CHANGED
@@ -0,0 +1,44 @@
|
|
1
|
+
import { Service } from "./service"
|
2
|
+
import { Context } from "../context"
|
3
|
+
import { Constructor } from "../internal/registry"
|
4
|
+
|
5
|
+
export abstract class CommandHandler<T> {
|
6
|
+
constructor(protected readonly context: Context) {}
|
7
|
+
|
8
|
+
resolve<T>(type: Constructor<T>): T | undefined {
|
9
|
+
return this.context.resolve<T>(type)
|
10
|
+
}
|
11
|
+
|
12
|
+
abstract execute(message: T): Promise<void>
|
13
|
+
}
|
14
|
+
|
15
|
+
export abstract class Command {}
|
16
|
+
|
17
|
+
export class CommandService extends Service {
|
18
|
+
private readonly _registry: Map<
|
19
|
+
Constructor<any>,
|
20
|
+
(context: Context) => CommandHandler<any>
|
21
|
+
> = new Map()
|
22
|
+
private _lastPromise: Promise<void> = Promise.resolve()
|
23
|
+
|
24
|
+
register<T extends Command>(
|
25
|
+
messageType: Constructor<T>,
|
26
|
+
commandFactory: (context: Context) => CommandHandler<T>
|
27
|
+
): void {
|
28
|
+
this._registry.set(messageType, commandFactory)
|
29
|
+
}
|
30
|
+
|
31
|
+
async execute<T extends Command>(message: T): Promise<void> {
|
32
|
+
const commandFactory = this._registry.get((message as any).constructor)
|
33
|
+
if (commandFactory) {
|
34
|
+
const command = commandFactory(this.context)
|
35
|
+
await this._lastPromise
|
36
|
+
this._lastPromise = command.execute(message)
|
37
|
+
await this._lastPromise
|
38
|
+
} else {
|
39
|
+
throw new Error(
|
40
|
+
`Command not found for message type ${message.constructor.name}`
|
41
|
+
)
|
42
|
+
}
|
43
|
+
}
|
44
|
+
}
|
@@ -1,6 +1,6 @@
|
|
1
|
-
import { type CredentialBase } from
|
2
|
-
import { Service } from
|
3
|
-
import { type DisposableContainer } from
|
1
|
+
import { type CredentialBase } from "../credentials"
|
2
|
+
import { Service } from "./service"
|
3
|
+
import { type DisposableContainer } from "../disposable"
|
4
4
|
|
5
5
|
export class CredentialService extends Service {
|
6
6
|
private _credentialDispose?: DisposableContainer = undefined
|
@@ -1,9 +1,9 @@
|
|
1
|
-
import { Service } from
|
2
|
-
import { type Middleware } from
|
3
|
-
import { type Disposable } from
|
1
|
+
import { Service } from "./service"
|
2
|
+
import { type Middleware } from "../middleware"
|
3
|
+
import { type Disposable } from "../disposable"
|
4
4
|
|
5
5
|
export class MiddlewareService extends Service {
|
6
|
-
_middlewares: Middleware[] = []
|
6
|
+
private _middlewares: Middleware[] = []
|
7
7
|
|
8
8
|
public useMiddleware(middleware: Middleware): Disposable {
|
9
9
|
this._middlewares.push(middleware)
|
@@ -24,10 +24,12 @@ export class MiddlewareService extends Service {
|
|
24
24
|
const processNext = async (request: Request): Promise<Response> => {
|
25
25
|
index++
|
26
26
|
if (index < middlewares.length) {
|
27
|
-
await middlewares[index](request, processNext)
|
27
|
+
return await middlewares[index](request, processNext)
|
28
|
+
} else {
|
29
|
+
return await next(request)
|
28
30
|
}
|
29
|
-
return await next(request)
|
30
31
|
}
|
32
|
+
|
31
33
|
return await processNext(req)
|
32
34
|
}
|
33
35
|
}
|