@neuralinnovations/dataisland-sdk 0.0.1-dev1
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/.browserslistrc +5 -0
- package/.editorconfig +22 -0
- package/.eslintrc.json +44 -0
- package/.github/workflows/publish-npm.yml +28 -0
- package/.prettierignore +1 -0
- package/.prettierrc +11 -0
- package/.yarnrc +2 -0
- package/README.md +7 -0
- package/babel.config.js +6 -0
- package/jest.config.ts +199 -0
- package/package.json +60 -0
- package/src/appBuilder.ts +39 -0
- package/src/appSdk.ts +40 -0
- package/src/credentials.ts +63 -0
- package/src/disposable.ts +151 -0
- package/src/events.ts +71 -0
- package/src/index.ts +69 -0
- package/src/internal/app.impl.ts +119 -0
- package/src/internal/appBuilder.impl.ts +59 -0
- package/src/internal/context.ts +13 -0
- package/src/internal/createApp.impl.ts +12 -0
- package/src/internal/registry.ts +83 -0
- package/src/middleware.ts +7 -0
- package/src/services/credentialService.ts +24 -0
- package/src/services/middlewareService.ts +33 -0
- package/src/services/rpcService.ts +72 -0
- package/src/services/service.ts +46 -0
- package/src/types.ts +110 -0
- package/test/disposable.test.ts +39 -0
- package/test/events.test.ts +151 -0
- package/test/index.test.ts +83 -0
- package/test/registry.test.ts +44 -0
- package/tsconfig.json +31 -0
package/src/types.ts
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
import { type Events, type Event } from './events'
|
2
|
+
import { type Disposable } from './disposable'
|
3
|
+
|
4
|
+
export interface Collection<T> {
|
5
|
+
get collection(): T[]
|
6
|
+
}
|
7
|
+
|
8
|
+
export type OrganizationId = string
|
9
|
+
export type WorkspaceId = string
|
10
|
+
export type ChatId = string
|
11
|
+
export type FileId = string
|
12
|
+
|
13
|
+
export enum OrganizationEvent {
|
14
|
+
ADDED,
|
15
|
+
REMOVED,
|
16
|
+
UPDATED
|
17
|
+
}
|
18
|
+
|
19
|
+
export enum FileEvent {
|
20
|
+
ADDED,
|
21
|
+
REMOVED,
|
22
|
+
UPDATED
|
23
|
+
}
|
24
|
+
|
25
|
+
export enum ChatEvent {
|
26
|
+
ADDED,
|
27
|
+
REMOVED,
|
28
|
+
UPDATED
|
29
|
+
}
|
30
|
+
|
31
|
+
export enum ChatMessageEvent {
|
32
|
+
ADDED,
|
33
|
+
REMOVED,
|
34
|
+
UPDATED
|
35
|
+
}
|
36
|
+
|
37
|
+
export interface File {
|
38
|
+
id: FileId
|
39
|
+
name: string
|
40
|
+
|
41
|
+
download: () => Promise<void>
|
42
|
+
}
|
43
|
+
|
44
|
+
export interface Files {
|
45
|
+
files: File[]
|
46
|
+
on: (callback: (event: Event<FileEvent, File>) => void) => Disposable
|
47
|
+
fetch: () => Promise<void>
|
48
|
+
upload: (path: string, name: string) => Promise<File>
|
49
|
+
}
|
50
|
+
|
51
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
52
|
+
export interface ChatMessage {}
|
53
|
+
|
54
|
+
export interface Chat {
|
55
|
+
id: ChatId
|
56
|
+
name: string
|
57
|
+
on: (
|
58
|
+
callback: (event: Event<ChatMessageEvent, ChatMessage>) => void
|
59
|
+
) => Disposable
|
60
|
+
messages: ChatMessage[]
|
61
|
+
fetch: () => Promise<void>
|
62
|
+
subscribe: () => void
|
63
|
+
unsubscribe: () => void
|
64
|
+
}
|
65
|
+
|
66
|
+
export interface Chats {
|
67
|
+
chats: Chat[]
|
68
|
+
newChat: (name: string) => Promise<Chat>
|
69
|
+
on: (callback: (event: Event<ChatEvent, Chat>) => void) => Disposable
|
70
|
+
fetch: () => Promise<void>
|
71
|
+
}
|
72
|
+
|
73
|
+
export interface Invites {
|
74
|
+
invite: (email: string) => Promise<void>
|
75
|
+
accept: (id: OrganizationId) => Promise<void>
|
76
|
+
decline: (id: OrganizationId) => Promise<void>
|
77
|
+
on: (
|
78
|
+
callback: (organization: Event<OrganizationEvent, Organization>) => void
|
79
|
+
) => Disposable
|
80
|
+
}
|
81
|
+
|
82
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
83
|
+
export interface Statistics {}
|
84
|
+
|
85
|
+
export interface Organization {
|
86
|
+
name: string
|
87
|
+
description: string
|
88
|
+
id: OrganizationId
|
89
|
+
chats: Chats
|
90
|
+
files: Files
|
91
|
+
invites: Invites
|
92
|
+
statistics: Statistics
|
93
|
+
workspaces: Workspaces
|
94
|
+
}
|
95
|
+
|
96
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
97
|
+
export interface Workspace {}
|
98
|
+
|
99
|
+
export interface Workspaces {
|
100
|
+
newWorkspace: (name: string) => Promise<Workspace>
|
101
|
+
|
102
|
+
delete: (id: WorkspaceId) => Promise<void>
|
103
|
+
}
|
104
|
+
|
105
|
+
export interface Organizations
|
106
|
+
extends Events<OrganizationEvent, Organization>,
|
107
|
+
Collection<Organization> {
|
108
|
+
create: (name: string) => Promise<Organization>
|
109
|
+
delete: (id: OrganizationId) => Promise<void>
|
110
|
+
}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
import { DisposableContainer } from '../src'
|
2
|
+
|
3
|
+
test('DisposableContainer', () => {
|
4
|
+
const disposable = new DisposableContainer()
|
5
|
+
expect(disposable.isDisposed).toBe(false)
|
6
|
+
expect(disposable.lifetime.isDisposed).toBe(false)
|
7
|
+
disposable.dispose()
|
8
|
+
expect(disposable.isDisposed).toBe(true)
|
9
|
+
expect(disposable.lifetime.isDisposed).toBe(true)
|
10
|
+
})
|
11
|
+
|
12
|
+
test('DisposableContainer, dispose order', () => {
|
13
|
+
const indexes: number[] = []
|
14
|
+
const disposable = new DisposableContainer()
|
15
|
+
disposable.addCallback(() => {
|
16
|
+
indexes.push(1)
|
17
|
+
})
|
18
|
+
|
19
|
+
const nested = disposable.defineNested()
|
20
|
+
nested.addCallback(() => {
|
21
|
+
indexes.push(2)
|
22
|
+
})
|
23
|
+
|
24
|
+
nested.lifetime.addCallback(() => {
|
25
|
+
indexes.push(3)
|
26
|
+
})
|
27
|
+
|
28
|
+
nested.lifetime.defineNested().addCallback(() => {
|
29
|
+
indexes.push(4)
|
30
|
+
})
|
31
|
+
|
32
|
+
nested.lifetime.defineNested().addCallback(() => {
|
33
|
+
indexes.push(5)
|
34
|
+
})
|
35
|
+
|
36
|
+
disposable.dispose()
|
37
|
+
|
38
|
+
expect(indexes).toEqual([5, 4, 3, 2, 1])
|
39
|
+
})
|
@@ -0,0 +1,151 @@
|
|
1
|
+
import { EventDispatcher } from '../src'
|
2
|
+
|
3
|
+
test('Events, test general', () => {
|
4
|
+
enum ET {
|
5
|
+
A,
|
6
|
+
B
|
7
|
+
}
|
8
|
+
|
9
|
+
const dispatch = new EventDispatcher<ET, number>()
|
10
|
+
|
11
|
+
let a1 = 0
|
12
|
+
let a2 = 0
|
13
|
+
let b1 = 0
|
14
|
+
let b2 = 0
|
15
|
+
|
16
|
+
const aDisposable1 = dispatch.subscribe((evt: { data: number }) => {
|
17
|
+
a1 += evt.data
|
18
|
+
}, ET.A)
|
19
|
+
const aDisposable2 = dispatch.subscribe(evt => {
|
20
|
+
if (evt.type === ET.A) a2 += evt.data
|
21
|
+
})
|
22
|
+
const bDisposable1 = dispatch.subscribe(evt => {
|
23
|
+
b1 += evt.data
|
24
|
+
}, ET.B)
|
25
|
+
const bDisposable2 = dispatch.subscribe(evt => {
|
26
|
+
if (evt.type === ET.B) b2 += evt.data
|
27
|
+
})
|
28
|
+
|
29
|
+
dispatch.dispatch({
|
30
|
+
type: ET.A,
|
31
|
+
data: 1
|
32
|
+
})
|
33
|
+
|
34
|
+
expect(a1).toBe(1)
|
35
|
+
expect(a2).toBe(1)
|
36
|
+
expect(b1).toBe(0)
|
37
|
+
expect(b2).toBe(0)
|
38
|
+
|
39
|
+
aDisposable1.dispose()
|
40
|
+
|
41
|
+
dispatch.dispatch({
|
42
|
+
type: ET.A,
|
43
|
+
data: 2
|
44
|
+
})
|
45
|
+
dispatch.dispatch({
|
46
|
+
type: ET.B,
|
47
|
+
data: 3
|
48
|
+
})
|
49
|
+
|
50
|
+
expect(a1).toBe(1)
|
51
|
+
expect(a2).toBe(3)
|
52
|
+
expect(b1).toBe(3)
|
53
|
+
expect(b2).toBe(3)
|
54
|
+
|
55
|
+
aDisposable2.dispose()
|
56
|
+
|
57
|
+
dispatch.dispatch({
|
58
|
+
type: ET.A,
|
59
|
+
data: 3
|
60
|
+
})
|
61
|
+
|
62
|
+
expect(a1).toBe(1)
|
63
|
+
expect(a2).toBe(3)
|
64
|
+
expect(b1).toBe(3)
|
65
|
+
expect(b2).toBe(3)
|
66
|
+
|
67
|
+
bDisposable1.dispose()
|
68
|
+
bDisposable2.dispose()
|
69
|
+
|
70
|
+
dispatch.dispatch({
|
71
|
+
type: ET.B,
|
72
|
+
data: 4
|
73
|
+
})
|
74
|
+
|
75
|
+
expect(a1).toBe(1)
|
76
|
+
expect(a2).toBe(3)
|
77
|
+
expect(b1).toBe(3)
|
78
|
+
expect(b2).toBe(3)
|
79
|
+
})
|
80
|
+
|
81
|
+
test('Events, test this', () => {
|
82
|
+
enum ET {
|
83
|
+
A,
|
84
|
+
B
|
85
|
+
}
|
86
|
+
|
87
|
+
const dispatch = new EventDispatcher<ET, number>()
|
88
|
+
|
89
|
+
const a = {
|
90
|
+
value: 0
|
91
|
+
}
|
92
|
+
const b = {
|
93
|
+
value: 0
|
94
|
+
}
|
95
|
+
|
96
|
+
const aDisposable = dispatch.subscribe((evt: { data: number }) => {
|
97
|
+
a.value += evt.data
|
98
|
+
}, ET.A)
|
99
|
+
const bDisposable = dispatch.subscribe((evt: { data: number }) => {
|
100
|
+
b.value += evt.data
|
101
|
+
}, ET.B)
|
102
|
+
|
103
|
+
dispatch.dispatch({
|
104
|
+
type: ET.A,
|
105
|
+
data: 1
|
106
|
+
})
|
107
|
+
dispatch.dispatch({
|
108
|
+
type: ET.B,
|
109
|
+
data: 2
|
110
|
+
})
|
111
|
+
|
112
|
+
expect(a.value).toBe(1)
|
113
|
+
expect(b.value).toBe(2)
|
114
|
+
|
115
|
+
aDisposable.dispose()
|
116
|
+
bDisposable.dispose()
|
117
|
+
|
118
|
+
dispatch.dispatch({
|
119
|
+
type: ET.A,
|
120
|
+
data: 3
|
121
|
+
})
|
122
|
+
dispatch.dispatch({
|
123
|
+
type: ET.B,
|
124
|
+
data: 4
|
125
|
+
})
|
126
|
+
|
127
|
+
expect(a.value).toBe(1)
|
128
|
+
expect(b.value).toBe(2)
|
129
|
+
})
|
130
|
+
|
131
|
+
test('Events, test unsubscribe', () => {
|
132
|
+
const dispatch = new EventDispatcher<unknown, number>()
|
133
|
+
|
134
|
+
let index = 0
|
135
|
+
|
136
|
+
dispatch.subscribe(evt => {
|
137
|
+
index += evt.data
|
138
|
+
evt.unsubscribe()
|
139
|
+
})
|
140
|
+
dispatch.subscribe(evt => {
|
141
|
+
index += evt.data
|
142
|
+
})
|
143
|
+
|
144
|
+
dispatch.dispatch({ data: 1 })
|
145
|
+
|
146
|
+
expect(index).toBe(2)
|
147
|
+
|
148
|
+
dispatch.dispatch({ data: 1 })
|
149
|
+
|
150
|
+
expect(index).toBe(3)
|
151
|
+
})
|
@@ -0,0 +1,83 @@
|
|
1
|
+
import { version } from '../package.json'
|
2
|
+
import {
|
3
|
+
BasicCredential,
|
4
|
+
appSdk,
|
5
|
+
SDK_VERSION,
|
6
|
+
DEFAULT_NAME,
|
7
|
+
DEFAULT_HOST
|
8
|
+
} from '../src'
|
9
|
+
import { MiddlewareService } from '../src/services/middlewareService'
|
10
|
+
import { CredentialService } from '../src/services/credentialService'
|
11
|
+
import { RpcService, RpcServiceImpl } from '../src/services/rpcService'
|
12
|
+
import { AppBuilder } from '../src/appBuilder'
|
13
|
+
|
14
|
+
test('SDK_VERSION', () => {
|
15
|
+
expect(SDK_VERSION).toBe(version)
|
16
|
+
})
|
17
|
+
|
18
|
+
test('Default SDK', async () => {
|
19
|
+
// default
|
20
|
+
const app = await appSdk()
|
21
|
+
expect(app.name).toBe(DEFAULT_NAME)
|
22
|
+
expect(app.host).toBe(DEFAULT_HOST)
|
23
|
+
expect(app.automaticDataCollectionEnabled).toBe(true)
|
24
|
+
})
|
25
|
+
|
26
|
+
test('Custom SDK settings', async () => {
|
27
|
+
const app = await appSdk('test', async (builder: AppBuilder) => {
|
28
|
+
builder.useHost('https://test.com')
|
29
|
+
builder.useAutomaticDataCollectionEnabled(false)
|
30
|
+
builder.useCredential(new BasicCredential('email', 'password'))
|
31
|
+
builder.addMiddleware(async (req, next) => {
|
32
|
+
req.headers.set('X-Test', 'test')
|
33
|
+
await next(req)
|
34
|
+
})
|
35
|
+
})
|
36
|
+
expect(app.name).toBe('test')
|
37
|
+
expect(app.host).toBe('https://test.com')
|
38
|
+
expect(app.automaticDataCollectionEnabled).toBe(false)
|
39
|
+
})
|
40
|
+
|
41
|
+
test('SDK, services', async () => {
|
42
|
+
const app = await appSdk('test')
|
43
|
+
const middlewareService = app.resolve(MiddlewareService)
|
44
|
+
expect(middlewareService).not.toBeUndefined()
|
45
|
+
expect(app.resolve(MiddlewareService)).toBe(middlewareService)
|
46
|
+
expect(app.resolve(CredentialService)).not.toBeUndefined()
|
47
|
+
expect(app.resolve(RpcService)).not.toBeUndefined()
|
48
|
+
expect(app.resolve(RpcService)).toBeInstanceOf(RpcServiceImpl)
|
49
|
+
})
|
50
|
+
|
51
|
+
test('SDK, middleware', async () => {
|
52
|
+
const app = await appSdk('test')
|
53
|
+
const middlewareService = app.resolve(MiddlewareService)
|
54
|
+
expect(middlewareService).not.toBeUndefined()
|
55
|
+
expect(app.resolve(MiddlewareService)).toBe(middlewareService)
|
56
|
+
expect(app.resolve(CredentialService)).not.toBeUndefined()
|
57
|
+
|
58
|
+
const response = await middlewareService?.process(
|
59
|
+
new Request('http://localhost:8080'),
|
60
|
+
async (req: Request): Promise<Response> => {
|
61
|
+
const headerXTest = req.headers.get('Custom-Test-Header')
|
62
|
+
expect(headerXTest).toBeNull()
|
63
|
+
return new Response('', { status: 200 })
|
64
|
+
}
|
65
|
+
)
|
66
|
+
expect(response).not.toBeUndefined()
|
67
|
+
expect(response?.status).toBe(200)
|
68
|
+
|
69
|
+
middlewareService?.useMiddleware(async (req, next) => {
|
70
|
+
req.headers.set('X-Test', 'test-value')
|
71
|
+
await next(req)
|
72
|
+
})
|
73
|
+
|
74
|
+
const response2 = await middlewareService?.process(
|
75
|
+
new Request('https://localhost:8080'),
|
76
|
+
async (req: Request): Promise<Response> => {
|
77
|
+
expect(req.headers.get('X-Test')).toBe('test-value')
|
78
|
+
return new Response('', { status: 400 })
|
79
|
+
}
|
80
|
+
)
|
81
|
+
expect(response2).not.toBeUndefined()
|
82
|
+
expect(response2?.status).toBe(400)
|
83
|
+
})
|
@@ -0,0 +1,44 @@
|
|
1
|
+
import { Registry } from '../src/internal/registry'
|
2
|
+
|
3
|
+
class TestClass {
|
4
|
+
constructor(public readonly value: string) {}
|
5
|
+
}
|
6
|
+
|
7
|
+
test('Registry, test factory', () => {
|
8
|
+
const registry = new Registry()
|
9
|
+
|
10
|
+
const item = new TestClass('test1')
|
11
|
+
registry.map(TestClass).asValue(item)
|
12
|
+
expect(registry.get(TestClass)).toBe(item)
|
13
|
+
|
14
|
+
let index = 0
|
15
|
+
|
16
|
+
registry.map(TestClass).asFactory(() => {
|
17
|
+
index++
|
18
|
+
return new TestClass(`test_${index}`)
|
19
|
+
})
|
20
|
+
|
21
|
+
expect(registry.get(TestClass)).toBeInstanceOf(TestClass)
|
22
|
+
expect(registry.get(TestClass)).not.toBe(item)
|
23
|
+
expect(registry.get(TestClass)).not.toBe(registry.get(TestClass))
|
24
|
+
|
25
|
+
expect(registry.get(TestClass)?.value).toBe('test_5')
|
26
|
+
})
|
27
|
+
|
28
|
+
test('Registry, test value', () => {
|
29
|
+
const registry = new Registry()
|
30
|
+
|
31
|
+
const item = new TestClass('test1')
|
32
|
+
registry.map(TestClass).asValue(item)
|
33
|
+
expect(registry.get(TestClass)).toBeInstanceOf(TestClass)
|
34
|
+
expect(registry.get(TestClass)).toBe(item)
|
35
|
+
})
|
36
|
+
|
37
|
+
test('Registry, test singleton', () => {
|
38
|
+
const registry = new Registry()
|
39
|
+
|
40
|
+
registry.map(TestClass).asSingleton(() => new TestClass('test1'))
|
41
|
+
const singleton = registry.get(TestClass)
|
42
|
+
expect(singleton).toBeInstanceOf(TestClass)
|
43
|
+
expect(singleton).toBe(registry.get(TestClass))
|
44
|
+
})
|
package/tsconfig.json
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
{
|
2
|
+
"compileOnSave": false,
|
3
|
+
"compilerOptions": {
|
4
|
+
"target": "ES2015",
|
5
|
+
"module": "amd",
|
6
|
+
"moduleResolution": "node",
|
7
|
+
"typeRoots": [
|
8
|
+
"node_modules/@types"
|
9
|
+
],
|
10
|
+
"resolveJsonModule": true,
|
11
|
+
"declaration": true,
|
12
|
+
"sourceMap": true,
|
13
|
+
"importHelpers": true,
|
14
|
+
"esModuleInterop": true,
|
15
|
+
"forceConsistentCasingInFileNames": true,
|
16
|
+
"strict": true,
|
17
|
+
"skipLibCheck": true,
|
18
|
+
"outDir": "dist",
|
19
|
+
"outFile": "dist/dataisland-sdk.js",
|
20
|
+
"rootDir": ".",
|
21
|
+
"allowJs": true,
|
22
|
+
"checkJs": true,
|
23
|
+
"downlevelIteration": true
|
24
|
+
},
|
25
|
+
"exclude": [
|
26
|
+
"dist/**/*"
|
27
|
+
],
|
28
|
+
"include": [
|
29
|
+
"src/**/*"
|
30
|
+
]
|
31
|
+
}
|