@toa.io/core 0.2.0-dev.3 → 0.2.1-dev.1
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/package.json +5 -4
- package/src/assignment.js +7 -7
- package/src/cascade.js +1 -1
- package/src/{runtime.js → component.js} +7 -4
- package/src/composition.js +6 -7
- package/src/connector.js +89 -24
- package/src/context.js +23 -11
- package/src/contract/reply.js +4 -1
- package/src/contract/request.js +13 -3
- package/src/contract/schemas/index.js +4 -3
- package/src/discovery.js +11 -0
- package/src/entities/changeset.js +4 -3
- package/src/entities/entity.js +17 -6
- package/src/entities/factory.js +3 -3
- package/src/event.js +12 -5
- package/src/exceptions.js +9 -1
- package/src/exposition.js +12 -9
- package/src/index.js +4 -2
- package/src/locator.js +21 -35
- package/src/observation.js +6 -6
- package/src/operation.js +20 -13
- package/src/query/options.js +4 -7
- package/src/query.js +6 -1
- package/src/receiver.js +36 -7
- package/src/reflection.js +28 -0
- package/src/remote.js +3 -3
- package/src/state.js +33 -25
- package/src/transition.js +24 -16
- package/test/call.fixtures.js +1 -0
- package/test/{runtime.fixtures.js → component.fixtures.js} +4 -2
- package/test/{runtime.test.js → component.test.js} +7 -7
- package/test/connector.fixtures.js +1 -1
- package/test/connector.test.js +6 -29
- package/test/context.fixtures.js +18 -0
- package/test/context.test.js +29 -0
- package/test/contract/contract.fixtures.js +8 -3
- package/test/contract/request.test.js +14 -3
- package/test/emission.fixtures.js +1 -0
- package/test/entities/entity.fixtures.js +4 -4
- package/test/entities/entity.test.js +22 -10
- package/test/entities/factory.test.js +6 -6
- package/test/event.fixtures.js +1 -0
- package/test/event.test.js +16 -4
- package/test/locator.test.js +76 -19
- package/test/receiver.fixtures.js +6 -5
- package/test/receiver.test.js +36 -7
- package/test/reflection.test.js +30 -0
- package/test/state.fixtures.js +6 -5
- package/test/state.test.js +8 -16
- package/types/bindings.d.ts +39 -0
- package/types/bridges.d.ts +35 -0
- package/types/component.ts +16 -0
- package/types/connector.d.ts +22 -0
- package/types/context.d.ts +24 -0
- package/types/entity.d.ts +46 -0
- package/types/event.d.ts +11 -0
- package/types/exception.d.ts +10 -0
- package/types/extensions.d.ts +36 -0
- package/types/index.d.ts +14 -0
- package/types/locator.d.ts +16 -0
- package/types/message.d.ts +9 -0
- package/types/query.d.ts +15 -0
- package/types/receiver.d.ts +12 -0
- package/types/reflection.d.ts +16 -0
- package/types/reply.d.ts +15 -0
- package/types/request.d.ts +25 -0
- package/types/state.d.ts +35 -0
- package/types/storages.d.ts +71 -0
- package/LICENSE +0 -22
package/test/state.test.js
CHANGED
|
@@ -5,34 +5,26 @@ const fixtures = require('./state.fixtures')
|
|
|
5
5
|
|
|
6
6
|
let state
|
|
7
7
|
|
|
8
|
-
beforeAll(() => {
|
|
9
|
-
delete global.TOA_INTEGRATION_OMIT_EMISSION
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
afterAll(() => {
|
|
13
|
-
global.TOA_INTEGRATION_OMIT_EMISSION = true
|
|
14
|
-
})
|
|
15
|
-
|
|
16
8
|
beforeEach(() => {
|
|
17
9
|
jest.clearAllMocks()
|
|
18
10
|
|
|
19
11
|
state = new State(fixtures.storage, fixtures.factory, fixtures.emitter)
|
|
20
12
|
})
|
|
21
13
|
|
|
22
|
-
it('should provide
|
|
23
|
-
const entity = await state.
|
|
14
|
+
it('should provide object', async () => {
|
|
15
|
+
const entity = await state.object(fixtures.query)
|
|
24
16
|
|
|
25
17
|
expect(fixtures.storage.get).toHaveBeenCalledWith(fixtures.query)
|
|
26
|
-
expect(entity).toStrictEqual(fixtures.factory.
|
|
27
|
-
expect(fixtures.factory.
|
|
18
|
+
expect(entity).toStrictEqual(fixtures.factory.object.mock.results[0].value)
|
|
19
|
+
expect(fixtures.factory.object).toHaveBeenCalledWith(fixtures.storage.get.mock.results[0].value)
|
|
28
20
|
})
|
|
29
21
|
|
|
30
|
-
it('should provide
|
|
31
|
-
const set = await state.
|
|
22
|
+
it('should provide objects', async () => {
|
|
23
|
+
const set = await state.objects(fixtures.query)
|
|
32
24
|
|
|
33
25
|
expect(fixtures.storage.find).toHaveBeenCalledWith(fixtures.query)
|
|
34
|
-
expect(set).toStrictEqual(fixtures.factory.
|
|
35
|
-
expect(fixtures.factory.
|
|
26
|
+
expect(set).toStrictEqual(fixtures.factory.objects.mock.results[0].value)
|
|
27
|
+
expect(fixtures.factory.objects).toHaveBeenCalledWith(fixtures.storage.find.mock.results[0].value)
|
|
36
28
|
})
|
|
37
29
|
|
|
38
30
|
it('should store entity', async () => {
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as _core from './index'
|
|
2
|
+
|
|
3
|
+
declare namespace toa.core.bindings {
|
|
4
|
+
|
|
5
|
+
type Properties = {
|
|
6
|
+
async?: boolean
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface Consumer extends _core.Connector {
|
|
10
|
+
request(request: Request): Promise<_core.Reply>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface Emitter extends _core.Connector {
|
|
14
|
+
emit(message: _core.Message): Promise<void>
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface Broadcaster extends _core.Connector {
|
|
18
|
+
send(label: string, payload: Object): Promise<void>
|
|
19
|
+
|
|
20
|
+
receive(label: string, callback: (payload: object) => Promise<void>): Promise<void>
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface Factory {
|
|
24
|
+
producer?(locator: _core.Locator, endpoints: Array<string>, producer: _core.Component): _core.Connector
|
|
25
|
+
|
|
26
|
+
consumer?(locator: _core.Locator, endpoint: string): Consumer
|
|
27
|
+
|
|
28
|
+
emitter?(locator: _core.Locator, label: string): Emitter
|
|
29
|
+
|
|
30
|
+
receiver?(locator: _core.Locator, label: string, id: string, receiver: _core.Receiver): _core.Connector
|
|
31
|
+
|
|
32
|
+
broadcaster?(name: string, group?: string): Broadcaster
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export type Emitter = toa.core.bindings.Emitter
|
|
38
|
+
export type Factory = toa.core.bindings.Factory
|
|
39
|
+
export type Properties = toa.core.bindings.Properties
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as _core from '@toa.io/core/types'
|
|
2
|
+
import type * as reply from './reply'
|
|
3
|
+
import type * as context from './context'
|
|
4
|
+
import type * as connector from './connector'
|
|
5
|
+
|
|
6
|
+
declare namespace toa.core.bridges {
|
|
7
|
+
|
|
8
|
+
interface Algorithm extends connector.Connector {
|
|
9
|
+
run(input: Object, state: Object | Object[]): Promise<reply.Reply>
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface Event {
|
|
13
|
+
condition(object): Promise<boolean>
|
|
14
|
+
|
|
15
|
+
payload(object): Promise<object>
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface Receiver {
|
|
19
|
+
condition(object): Promise<boolean>
|
|
20
|
+
|
|
21
|
+
request(object): Promise<_core.Request>
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface Factory {
|
|
25
|
+
algorithm(path: string, name: string, context: context.Context): Algorithm
|
|
26
|
+
|
|
27
|
+
event(path: string, label: string): Event
|
|
28
|
+
|
|
29
|
+
receiver(path: string, label: string): Receiver
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type Algorithm = toa.core.bridges.Algorithm
|
|
35
|
+
export type Factory = toa.core.bridges.Factory
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as _connector from './connector'
|
|
2
|
+
import * as _locator from './locator'
|
|
3
|
+
import * as _request from './request'
|
|
4
|
+
import * as _reply from './reply'
|
|
5
|
+
|
|
6
|
+
declare namespace toa.core {
|
|
7
|
+
|
|
8
|
+
interface Component extends _connector.Connector {
|
|
9
|
+
locator: _locator.Locator
|
|
10
|
+
|
|
11
|
+
invoke(endpoint: string, request: _request.Request): Promise<_reply.Reply>
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type Component = toa.core.Component
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
declare namespace toa.core {
|
|
2
|
+
|
|
3
|
+
interface Connector {
|
|
4
|
+
id: string
|
|
5
|
+
connected: boolean
|
|
6
|
+
|
|
7
|
+
depends(connector: Connector): Connector
|
|
8
|
+
|
|
9
|
+
link(connector: Connector): void
|
|
10
|
+
|
|
11
|
+
connect(): Promise<void>
|
|
12
|
+
|
|
13
|
+
disconnect(interrupt?: boolean): Promise<void>
|
|
14
|
+
|
|
15
|
+
connection(): Promise<void>
|
|
16
|
+
|
|
17
|
+
disconnection(): Promise<void>
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type Connector = toa.core.Connector
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as _request from './request'
|
|
2
|
+
import * as _reply from './reply'
|
|
3
|
+
import * as _extensions from './extensions'
|
|
4
|
+
import * as _connector from './connector'
|
|
5
|
+
|
|
6
|
+
declare namespace toa.core {
|
|
7
|
+
|
|
8
|
+
interface Context extends _connector.Connector {
|
|
9
|
+
aspects: _extensions.Aspect[]
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Calls local endpoint
|
|
13
|
+
*/
|
|
14
|
+
apply(endpoint: string, request: _request.Request): Promise<_reply.Reply>
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Calls remote endpoint
|
|
18
|
+
*/
|
|
19
|
+
call(namespace: string, name: string, endpoint: string, request: _request.Request): Promise<_reply.Reply>
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type Context = toa.core.Context
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as _event from './event'
|
|
2
|
+
import * as _storages from './storages'
|
|
3
|
+
|
|
4
|
+
declare namespace toa.core {
|
|
5
|
+
|
|
6
|
+
namespace entity {
|
|
7
|
+
|
|
8
|
+
interface Factory {
|
|
9
|
+
init(id: string): Entity
|
|
10
|
+
|
|
11
|
+
object(record: Object): Entity
|
|
12
|
+
|
|
13
|
+
objects(recordset: Object[]): Entity[]
|
|
14
|
+
|
|
15
|
+
changeset(query: _storages.Query): Changeset
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface Entity {
|
|
21
|
+
get(): _storages.Record
|
|
22
|
+
|
|
23
|
+
set(value: _storages.Record): void
|
|
24
|
+
|
|
25
|
+
event(): _event.Event
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
type Upsert = {
|
|
29
|
+
changeset: Object
|
|
30
|
+
insert: Object
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface Changeset {
|
|
34
|
+
query: _storages.Query
|
|
35
|
+
|
|
36
|
+
get(): Object
|
|
37
|
+
|
|
38
|
+
set(value: Object): void
|
|
39
|
+
|
|
40
|
+
export(): Upsert
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export type Entity = toa.core.Entity
|
|
46
|
+
export type Changeset = toa.core.Changeset
|
package/types/event.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as _core from './index'
|
|
2
|
+
import * as _component from './component'
|
|
3
|
+
import * as _context from './context'
|
|
4
|
+
import * as _storages from './storages'
|
|
5
|
+
import * as _bindings from './bindings'
|
|
6
|
+
|
|
7
|
+
declare namespace toa.core.extensions {
|
|
8
|
+
|
|
9
|
+
interface Factory {
|
|
10
|
+
tenant?(locator: _core.Locator, declaration: Object): _core.Connector
|
|
11
|
+
|
|
12
|
+
aspect?(locator: _core.Locator, declaration: Object): Aspect
|
|
13
|
+
|
|
14
|
+
service?(name?: string): _core.Connector
|
|
15
|
+
|
|
16
|
+
component?(component: _component.Component): _component.Component
|
|
17
|
+
|
|
18
|
+
context?(context: _context.Context): _context.Context
|
|
19
|
+
|
|
20
|
+
storage?(storage: _storages.Storage): _storages.Storage
|
|
21
|
+
|
|
22
|
+
emitter?(emitter: _bindings.Emitter, label: string): _bindings.Emitter
|
|
23
|
+
|
|
24
|
+
receiver?(receiver: _core.Receiver, locator: _core.Locator): _core.Receiver
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface Aspect extends _core.Connector {
|
|
28
|
+
name: string
|
|
29
|
+
|
|
30
|
+
invoke(...args: any[]): Promise<any>
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type Factory = toa.core.extensions.Factory
|
|
36
|
+
export type Aspect = toa.core.extensions.Aspect
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * as bindings from './bindings'
|
|
2
|
+
export * as extensions from './extensions'
|
|
3
|
+
export * as storages from './storages'
|
|
4
|
+
export * as bridges from './bridges'
|
|
5
|
+
|
|
6
|
+
export { Component } from './component'
|
|
7
|
+
export { Connector } from './connector'
|
|
8
|
+
export { Context } from './context'
|
|
9
|
+
export { Exception } from './exception'
|
|
10
|
+
export { Locator } from './locator'
|
|
11
|
+
export { Receiver } from './receiver'
|
|
12
|
+
export { Message } from './message'
|
|
13
|
+
export { Reply } from './reply'
|
|
14
|
+
export { Request, Query } from './request'
|
package/types/query.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as _message from './message'
|
|
2
|
+
import * as _connector from './connector'
|
|
3
|
+
|
|
4
|
+
declare namespace toa.core {
|
|
5
|
+
|
|
6
|
+
interface Receiver extends _connector.Connector {
|
|
7
|
+
receive(message: _message.Message): Promise<void>
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type Receiver = toa.core.Receiver
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// noinspection ES6UnusedImports
|
|
2
|
+
|
|
3
|
+
import { Connector } from './connector'
|
|
4
|
+
|
|
5
|
+
declare namespace toa.core {
|
|
6
|
+
|
|
7
|
+
namespace reflection {
|
|
8
|
+
type Source = () => Promise<any>
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface Reflection<T> extends Connector {
|
|
12
|
+
value: T
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type Source = toa.core.reflection.Source
|
package/types/reply.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
declare namespace toa.core {
|
|
2
|
+
|
|
3
|
+
namespace request {
|
|
4
|
+
|
|
5
|
+
interface Query {
|
|
6
|
+
id?: string
|
|
7
|
+
criteria?: string
|
|
8
|
+
omit?: number
|
|
9
|
+
limit?: number
|
|
10
|
+
sort?: Array<string>
|
|
11
|
+
projection?: Array<string>
|
|
12
|
+
version?: number
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface Request {
|
|
18
|
+
input?: any
|
|
19
|
+
query?: request.Query
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type Request = toa.core.Request
|
|
25
|
+
export type Query = toa.core.request.Query
|
package/types/state.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as _entity from './entity'
|
|
2
|
+
import * as _storages from './storages'
|
|
3
|
+
|
|
4
|
+
declare namespace toa.core {
|
|
5
|
+
|
|
6
|
+
namespace transition {
|
|
7
|
+
|
|
8
|
+
type Event = {
|
|
9
|
+
origin: Object
|
|
10
|
+
state: Object
|
|
11
|
+
changeset: Object
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface State {
|
|
17
|
+
init(id: string): _entity.Entity
|
|
18
|
+
|
|
19
|
+
object(query: _storages.Query): Promise<_entity.Entity>
|
|
20
|
+
|
|
21
|
+
objects(query: _storages.Query): Promise<_entity.Entity[]>
|
|
22
|
+
|
|
23
|
+
changeset(query: _storages.Query): _entity.Changeset
|
|
24
|
+
|
|
25
|
+
none(): null
|
|
26
|
+
|
|
27
|
+
commit(entity: _entity.Entity): Promise<boolean>
|
|
28
|
+
|
|
29
|
+
apply(changeset: _entity.Changeset): Promise<void>
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type State = toa.core.State
|
|
35
|
+
export type Event = toa.core.transition.Event
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// noinspection ES6UnusedImports
|
|
2
|
+
|
|
3
|
+
import { Locator } from './locator'
|
|
4
|
+
import { Connector } from './connector'
|
|
5
|
+
|
|
6
|
+
declare namespace toa.core {
|
|
7
|
+
|
|
8
|
+
namespace storages {
|
|
9
|
+
namespace ast {
|
|
10
|
+
|
|
11
|
+
interface Node {
|
|
12
|
+
type: 'LOGIC' | 'COMPARISON' | 'SELECTOR' | 'VALUE'
|
|
13
|
+
left?: Node
|
|
14
|
+
right?: Node
|
|
15
|
+
operator?: string
|
|
16
|
+
selector?: string
|
|
17
|
+
value?: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface Record {
|
|
23
|
+
id: string
|
|
24
|
+
_version: number
|
|
25
|
+
|
|
26
|
+
[key: string]: any
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface Query {
|
|
30
|
+
id?: string
|
|
31
|
+
version?: number
|
|
32
|
+
criteria?: ast.Node
|
|
33
|
+
options?: Object
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface Migration {
|
|
37
|
+
disconnect(): Promise<void>
|
|
38
|
+
|
|
39
|
+
database(name: string): Promise<void>
|
|
40
|
+
|
|
41
|
+
table(database: string, locator: Locator, schema: Object, reset?: boolean): Promise<string>
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface Factory {
|
|
45
|
+
storage(locator: Locator): Storage
|
|
46
|
+
|
|
47
|
+
migration(driver?: string): Migration
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
interface Storage extends Connector {
|
|
52
|
+
// object observation
|
|
53
|
+
get?(query: storages.Query): Promise<storages.Record | null>
|
|
54
|
+
|
|
55
|
+
// objects observation
|
|
56
|
+
find?(query: storages.Query): Promise<storages.Record[]>
|
|
57
|
+
|
|
58
|
+
// commit
|
|
59
|
+
store?(record: storages.Record): Promise<boolean>
|
|
60
|
+
|
|
61
|
+
// assignment
|
|
62
|
+
upsert?(query: storages.Query, changeset: Object, insert: storages.Record): Promise<storages.Record>
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export type Storage = toa.core.Storage
|
|
68
|
+
export type Record = toa.core.storages.Record
|
|
69
|
+
export type Factory = toa.core.storages.Factory
|
|
70
|
+
export type Query = toa.core.storages.Query
|
|
71
|
+
export type Migration = toa.core.storages.Migration
|
package/LICENSE
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
Copyright (c) 2020-present Artem Gurtovoi
|
|
2
|
-
|
|
3
|
-
MIT License
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
-
a copy of this software and associated documentation files (the
|
|
7
|
-
"Software"), to deal in the Software without restriction, including
|
|
8
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
-
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
-
the following conditions:
|
|
12
|
-
|
|
13
|
-
The above copyright notice and this permission notice shall be
|
|
14
|
-
included in all copies or substantial portions of the Software.
|
|
15
|
-
|
|
16
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|