@toa.io/core 1.0.0-alpha.0 → 1.0.0-alpha.2

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toa.io/core",
3
- "version": "1.0.0-alpha.0",
3
+ "version": "1.0.0-alpha.2",
4
4
  "description": "Toa Core",
5
5
  "author": "temich <tema.gurtovoy@gmail.com>",
6
6
  "homepage": "https://github.com/toa-io/toa#readme",
@@ -12,7 +12,7 @@
12
12
  "url": "https://github.com/toa-io/toa/issues"
13
13
  },
14
14
  "main": "src/index.js",
15
- "types": "types/index.d.ts",
15
+ "types": "types/index.ts",
16
16
  "publishConfig": {
17
17
  "access": "public"
18
18
  },
@@ -21,11 +21,13 @@
21
21
  },
22
22
  "dependencies": {
23
23
  "@rsql/parser": "1.2.4",
24
- "@toa.io/console": "1.0.0-alpha.0",
25
- "@toa.io/generic": "1.0.0-alpha.0",
26
- "@toa.io/yaml": "1.0.0-alpha.0",
27
- "clone-deep": "4.0.1",
24
+ "@toa.io/console": "1.0.0-alpha.2",
25
+ "@toa.io/generic": "1.0.0-alpha.2",
26
+ "@toa.io/yaml": "1.0.0-alpha.2",
28
27
  "error-value": "0.3.0"
29
28
  },
30
- "gitHead": "06c64546f6292cc07c52f74b31415101037f7616"
29
+ "devDependencies": {
30
+ "clone-deep": "4.0.1"
31
+ },
32
+ "gitHead": "7688e6e980a65c82ac2e459be4e355eebf406cd0"
31
33
  }
@@ -1,7 +1,5 @@
1
1
  'use strict'
2
2
 
3
- const clone = require('clone-deep')
4
-
5
3
  const schemas = require('./schemas')
6
4
  const { RequestContractException } = require('../exceptions')
7
5
  const { Conditions } = require('./conditions')
@@ -12,8 +10,13 @@ class Request extends Conditions {
12
10
  /**
13
11
  * @returns {toa.schema.JSON}
14
12
  */
15
- static schema (definition) {
16
- const schema = { type: 'object', properties: { authentic: { type: 'boolean' } }, additionalProperties: true }
13
+ static schema (definition, entity) {
14
+ const schema = {
15
+ type: 'object',
16
+ properties: { authentic: { type: 'boolean' } },
17
+ additionalProperties: true
18
+ }
19
+
17
20
  const required = []
18
21
 
19
22
  if (definition.input !== undefined) {
@@ -23,14 +26,19 @@ class Request extends Conditions {
23
26
  schema.properties.input = { type: 'null' }
24
27
  }
25
28
 
26
- if (definition.query === true) required.push('query')
29
+ if (entity === undefined)
30
+ definition.query = false
27
31
 
28
- if (definition.query === false) {
29
- schema.not = { required: ['query'] }
30
- }
32
+ if (definition.query === true)
33
+ required.push('query')
34
+
35
+ if (definition.query === false)
36
+ schema.properties.query = { type: 'null' }
31
37
 
32
38
  if (definition.query !== false) {
33
- const query = clone(schemas.query)
39
+ const query = structuredClone(schemas.query)
40
+
41
+ query.properties.id = entity.schema.properties.id
34
42
 
35
43
  if (definition.type === 'observation') {
36
44
  delete query.properties.version
@@ -49,7 +57,8 @@ class Request extends Conditions {
49
57
  schema.properties.query = query
50
58
  }
51
59
 
52
- if (required.length > 0) schema.required = required
60
+ if (required.length > 0)
61
+ schema.required = required
53
62
 
54
63
  return schema
55
64
  }
@@ -2,7 +2,6 @@
2
2
 
3
3
  const { resolve } = require('path')
4
4
  const { load } = require('@toa.io/yaml')
5
- const { freeze } = require('@toa.io/generic')
6
5
 
7
- exports.query = freeze(load.sync(resolve(__dirname, './query.yaml')))
8
- exports.error = freeze(load.sync(resolve(__dirname, './error.yaml')))
6
+ exports.query = load.sync(resolve(__dirname, './query.yaml'))
7
+ exports.error = load.sync(resolve(__dirname, './error.yaml'))
@@ -1,7 +1,6 @@
1
1
  type: object
2
2
  properties:
3
- id:
4
- $ref: https://schemas.toa.io/0.0.0/definitions#/definitions/id
3
+ id: { }
5
4
  version:
6
5
  type: integer
7
6
  minimum: 0
@@ -1,6 +1,5 @@
1
1
  'use strict'
2
2
 
3
- const clone = require('clone-deep')
4
3
  const { difference, newid } = require('@toa.io/generic')
5
4
 
6
5
  const { EntityContractException } = require('../exceptions')
@@ -14,11 +13,11 @@ class Entity {
14
13
  this.#schema = schema
15
14
 
16
15
  if (typeof argument === 'object') {
17
- const object = clone(argument)
16
+ const object = structuredClone(argument)
18
17
  this.set(object)
19
18
  this.#origin = argument
20
19
  } else {
21
- const id = typeof argument === 'string' ? argument : newid()
20
+ const id = argument === undefined ? newid() : argument
22
21
  this.#init(id)
23
22
  }
24
23
  }
package/src/exposition.js CHANGED
@@ -20,8 +20,8 @@ class Exposition extends Connector {
20
20
  }
21
21
 
22
22
  const expose = (manifest) => {
23
- const { namespace, name, operations, events } = manifest
24
- return { namespace, name, operations, events }
23
+ const { namespace, name, operations, events, entity } = manifest
24
+ return { namespace, name, operations, events, entity }
25
25
  }
26
26
 
27
27
  exports.Exposition = Exposition
@@ -1,7 +1,5 @@
1
1
  'use strict'
2
2
 
3
- const { freeze } = require('@toa.io/generic')
4
-
5
3
  const { Operation } = require('./operation')
6
4
 
7
5
  class Observation extends Operation {
@@ -9,8 +7,6 @@ class Observation extends Operation {
9
7
  const scope = await this.query(store.request.query)
10
8
  const state = scope === null ? null : scope.get()
11
9
 
12
- freeze(state)
13
-
14
10
  store.scope = scope
15
11
  store.state = state
16
12
  }
@@ -32,6 +32,9 @@ const projection = (projection, properties) => {
32
32
  throw new QuerySyntaxException(`Projection property '${property}' is not defined`)
33
33
  }
34
34
  }
35
+
36
+ if (projection.includes('_version') === false)
37
+ projection.push('_version')
35
38
  }
36
39
 
37
40
  exports.options = options
package/src/state.js CHANGED
@@ -18,20 +18,16 @@ class State {
18
18
  /** @type {toa.core.entity.Factory} */
19
19
  #entity
20
20
  #emission
21
- #initialized
21
+ #dependent
22
22
 
23
- constructor (storage, entity, emission, initialized) {
23
+ constructor (storage, entity, emission, dependent) {
24
24
  this.#storage = storage
25
25
  this.#entity = entity
26
26
  this.#emission = emission
27
- this.#initialized = initialized
27
+ this.#dependent = dependent === true
28
28
  }
29
29
 
30
30
  init (id) {
31
- // if (this.#initialized === true && id === undefined) {
32
- // throw new StateInitializationException('Cannot initialize entity which is initialized. Use request.query.id to access.')
33
- // }
34
-
35
31
  return this.#entity.init(id)
36
32
  }
37
33
 
@@ -39,7 +35,7 @@ class State {
39
35
  const record = await this.#storage.get(query)
40
36
 
41
37
  if (record === null) {
42
- if (this.#initialized && query.id !== undefined && query.version === undefined) return this.init(query.id)
38
+ if (this.#dependent && query.id !== undefined && query.version === undefined) return this.init(query.id)
43
39
  else if (query.version !== undefined) throw new StatePreconditionException()
44
40
  }
45
41
 
@@ -83,7 +79,7 @@ class State {
83
79
 
84
80
  let upsert
85
81
 
86
- if (this.#initialized && state.query.id !== undefined && state.query.version === undefined) {
82
+ if (this.#dependent && state.query.id !== undefined && state.query.version === undefined) {
87
83
  upsert = insert
88
84
  }
89
85
 
@@ -17,6 +17,8 @@ beforeEach(() => {
17
17
  contract = new Request(fixtures.schema)
18
18
  })
19
19
 
20
+ const dummy = { schema: { properties: {} } }
21
+
20
22
  it('should extend Conditions', () => {
21
23
  expect(contract).toBeInstanceOf(Conditions)
22
24
  expect(Conditions).toHaveBeenCalledWith(fixtures.schema)
@@ -38,73 +40,73 @@ describe('schema', () => {
38
40
  })
39
41
 
40
42
  it('should provide schema', () => {
41
- expect(Request.schema({})).toBeDefined()
43
+ expect(Request.schema({}, dummy)).toBeDefined()
42
44
  })
43
45
 
44
46
  it('should add required input if defined', () => {
45
47
  const input = { type: 'number' }
46
48
 
47
- expect(Request.schema({ input }).properties.input).toStrictEqual(input)
49
+ expect(Request.schema({ input }, dummy).properties.input).toStrictEqual(input)
48
50
  })
49
51
 
50
52
  it('should set input as null if undefined', async () => {
51
- expect(Request.schema({}).properties.input).toStrictEqual({ type: 'null' })
53
+ expect(Request.schema({}, dummy).properties.input).toStrictEqual({ type: 'null' })
52
54
  })
53
55
 
54
56
  it('should contain query if declaration.query is not defined', () => {
55
- expect(Request.schema({}).properties.query).toBeDefined()
57
+ expect(Request.schema({}, dummy).properties.query).toBeDefined()
56
58
  })
57
59
 
58
60
  it('should not contain query if declaration.query is false', () => {
59
- delete schema.properties.query
60
- schema.not = { required: ['query'] }
61
- expect(Request.schema({ query: false })).toStrictEqual(schema)
61
+ schema.properties.query = { type: 'null' }
62
+ expect(Request.schema({ query: false }, dummy)).toStrictEqual(schema)
62
63
  })
63
64
 
64
65
  it('should require query if declaration.query is true', () => {
65
66
  schema.required = ['query']
66
- expect(Request.schema({ query: true }).required).toStrictEqual(expect.arrayContaining(['query']))
67
+ expect(Request.schema({ query: true }, dummy).required).toStrictEqual(expect.arrayContaining(['query']))
67
68
  })
68
69
 
69
70
  it('should forbid projection for non observations', () => {
70
- expect(Request.schema({ type: 'transition' }).properties.query.properties.projection)
71
+ expect(Request.schema({ type: 'transition' }, dummy).properties.query.properties.projection)
71
72
  .toBe(undefined)
72
73
 
73
- expect(Request.schema({ type: 'assignment' }).properties.query.properties.projection)
74
+ expect(Request.schema({ type: 'assignment' }, dummy).properties.query.properties.projection)
74
75
  .toBe(undefined)
75
76
 
76
- expect(Request.schema({ type: 'observation' }).properties.query.properties.projection)
77
+ expect(Request.schema({ type: 'observation' }, dummy).properties.query.properties.projection)
77
78
  .toBeDefined()
78
79
  })
79
80
 
80
81
  it('should forbid version for observations', () => {
81
- expect(Request.schema({ type: 'transition' }).properties.query.properties.version)
82
+ expect(Request.schema({ type: 'transition' }, dummy).properties.query.properties.version)
82
83
  .toBeDefined()
83
84
 
84
- expect(Request.schema({ type: 'observation' }).properties.query.properties.version)
85
+ expect(Request.schema({ type: 'observation' }, dummy).properties.query.properties.version)
85
86
  .toBe(undefined)
86
87
  })
87
88
 
88
89
  it('should allow omit, limit only for set observations', () => {
89
- const transition = Request.schema({ type: 'transition' }).properties.query.properties
90
+ const schema = Request.schema({ type: 'transition' }, dummy)
91
+ const transition = schema.properties.query.properties
90
92
 
91
93
  expect(transition.omit).toBeUndefined()
92
94
  expect(transition.limit).toBeUndefined()
93
95
 
94
- const entity = Request.schema({
96
+ const object = Request.schema({
95
97
  type: 'observation',
96
98
  scope: 'object'
97
- }).properties.query.properties
99
+ }, dummy).properties.query.properties
98
100
 
99
- expect(entity.omit).toBeUndefined()
100
- expect(entity.limit).toBeUndefined()
101
+ expect(object.omit).toBeUndefined()
102
+ expect(object.limit).toBeUndefined()
101
103
 
102
- const set = Request.schema({
104
+ const objects = Request.schema({
103
105
  type: 'observation',
104
106
  scope: 'objects'
105
- }).properties.query.properties
107
+ }, dummy).properties.query.properties
106
108
 
107
- expect(set.omit).toBeDefined()
108
- expect(set.limit).toBeDefined()
109
+ expect(objects.omit).toBeDefined()
110
+ expect(objects.limit).toBeDefined()
109
111
  })
110
112
  })
@@ -37,7 +37,7 @@ describe('argument', () => {
37
37
  const state = fixtures.state()
38
38
  const entity = new Entity(fixtures.schema, state)
39
39
 
40
- expect(entity.get()).toStrictEqual(state)
40
+ expect(entity.get()).toEqual(state)
41
41
  })
42
42
  })
43
43
 
@@ -51,7 +51,7 @@ it('should provide event', () => {
51
51
 
52
52
  const event = entity.event()
53
53
 
54
- expect(event).toStrictEqual({
54
+ expect(event).toEqual({
55
55
  state,
56
56
  origin,
57
57
  changeset: { foo: 'new value' }
@@ -1,26 +1,26 @@
1
1
  import * as _core from './index'
2
2
 
3
- declare namespace toa.core.bindings {
3
+ declare namespace toa.core.bindings{
4
4
 
5
5
  type Properties = {
6
6
  async?: boolean
7
7
  }
8
8
 
9
- interface Consumer extends _core.Connector {
9
+ interface Consumer extends _core.Connector{
10
10
  request (request: Request): Promise<_core.Reply>
11
11
  }
12
12
 
13
- interface Emitter extends _core.Connector {
13
+ interface Emitter extends _core.Connector{
14
14
  emit (message: _core.Message): Promise<void>
15
15
  }
16
16
 
17
- interface Broadcast<L> extends _core.Connector {
17
+ interface Broadcast<L> extends _core.Connector{
18
18
  transmit<T> (label: L, payload: T): Promise<void>
19
19
 
20
20
  receive<T> (label: L, callback: (payload: T) => void | Promise<void>): Promise<void>
21
21
  }
22
22
 
23
- interface Factory {
23
+ interface Factory{
24
24
  producer? (locator: _core.Locator, endpoints: Array<string>, producer: _core.Component): _core.Connector
25
25
 
26
26
  consumer? (locator: _core.Locator, endpoint: string): Consumer
@@ -37,4 +37,4 @@ declare namespace toa.core.bindings {
37
37
  export type Emitter = toa.core.bindings.Emitter
38
38
  export type Factory = toa.core.bindings.Factory
39
39
  export type Properties = toa.core.bindings.Properties
40
- export type Broadcast<L> = toa.core.bindings.Broadcast<L>
40
+ export type Broadcast<L = any> = toa.core.bindings.Broadcast<L>
@@ -0,0 +1,30 @@
1
+ import type { Request, Reply } from './request'
2
+ import type { Context } from './context'
3
+
4
+ export interface Algorithm {
5
+ mount: (context?: Context) => Promise<void>
6
+
7
+ execute: ((input: any, scope: object | object[]) => Promise<Reply>) |
8
+ ((input: any) => Promise<Reply>) |
9
+ (() => Promise<Reply>)
10
+ }
11
+
12
+ export interface Event {
13
+ condition: (object: object) => Promise<boolean>
14
+
15
+ payload: (object: object) => Promise<object>
16
+ }
17
+
18
+ export interface Receiver {
19
+ condition: (object: object) => Promise<boolean>
20
+
21
+ request: (object: object) => Promise<Request>
22
+ }
23
+
24
+ export interface Factory {
25
+ algorithm?: (path: string, name: string, context: Context) => Algorithm
26
+
27
+ event?: (path: string, label: string) => Event
28
+
29
+ receiver?: (path: string, label: string) => Receiver
30
+ }
@@ -3,25 +3,19 @@ import * as _reply from './reply'
3
3
  import * as _extensions from './extensions'
4
4
  import * as _connector from './connector'
5
5
 
6
- declare namespace toa.core {
6
+ export interface Context extends _connector.Connector{
7
+ aspects: _extensions.Aspect[]
7
8
 
8
- interface Context extends _connector.Connector {
9
- aspects: _extensions.Aspect[]
9
+ /**
10
+ * Calls local endpoint
11
+ */
12
+ apply (endpoint: string, request: _request.Request): Promise<_reply.Reply>
10
13
 
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
- // shortcuts
22
- [key: string]: any
23
- }
14
+ /**
15
+ * Calls remote endpoint
16
+ */
17
+ call (namespace: string, name: string, endpoint: string, request: _request.Request): Promise<_reply.Reply>
24
18
 
19
+ // shortcuts
20
+ [key: string]: any
25
21
  }
26
-
27
- export type Context = toa.core.Context
@@ -4,11 +4,11 @@ export * as storages from './storages'
4
4
  export * as bridges from './bridges'
5
5
  export * as operations from './operations'
6
6
 
7
- export { Component } from './component'
7
+ export type { Component } from './component'
8
8
  export { Connector } from './connector'
9
- export { Context } from './context'
10
- export { Exception } from './exception'
9
+ export type { Context } from './context'
10
+ export type { Exception } from './exception'
11
11
  export { Locator } from './locator'
12
- export { Receiver } from './receiver'
13
- export { Message } from './message'
14
- export { Request, Query, Reply } from './request'
12
+ export type { Receiver } from './receiver'
13
+ export type { Message } from './message'
14
+ export type { Request, Query, Reply } from './request'
@@ -1,41 +0,0 @@
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
- mount(context?: context.Context): Promise<void>
10
-
11
- execute(input: any, scope: object | object[]): Promise<reply.Reply>
12
-
13
- execute(input: any): Promise<reply.Reply>
14
-
15
- execute(): Promise<reply.Reply>
16
- }
17
-
18
- interface Event {
19
- condition(object): Promise<boolean>
20
-
21
- payload(object): Promise<object>
22
- }
23
-
24
- interface Receiver {
25
- condition(object): Promise<boolean>
26
-
27
- request(object): Promise<_core.Request>
28
- }
29
-
30
- interface Factory {
31
- algorithm(path: string, name: string, context: context.Context): Algorithm
32
-
33
- event(path: string, label: string): Event
34
-
35
- receiver(path: string, label: string): Receiver
36
- }
37
-
38
- }
39
-
40
- export type Algorithm = toa.core.bridges.Algorithm
41
- export type Factory = toa.core.bridges.Factory