@1mill/cloudevents 4.0.0 → 4.1.0

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/src/index.js CHANGED
@@ -1,12 +1,13 @@
1
+ import { fetchNodeEnv } from './utils/fetchNodeEnv/index.js'
1
2
  import { nanoid } from 'nanoid'
2
-
3
- const fetchNodeEnv = name => (typeof process !== 'undefined') && process && process.env && process.env[name]
3
+ import { setAttribute } from './utils/setAttribute/index.js'
4
4
 
5
5
  export class Cloudevent {
6
6
  constructor({
7
7
  data,
8
8
  datacontenttype,
9
9
  dataschema,
10
+ originatorid,
10
11
  originid,
11
12
  originsource,
12
13
  origintime,
@@ -16,54 +17,58 @@ export class Cloudevent {
16
17
  subject,
17
18
  type,
18
19
  }) {
19
- // * Required fields by CloudEvent specification
20
- this.id = nanoid(fetchNodeEnv('MILL_CLOUDEVENTS_NANOID_LENGTH') || 21)
21
- if (!this.id) throw new Error('Cloudevent "id" is required')
22
- if (typeof this.id !== 'string') throw new Error('Cloudevent "id" must be a string')
20
+ const cloudevent = this
21
+
22
+ // *******
23
+ // * Required fields by Cloudevent v1 specification
24
+ const idValue = nanoid(fetchNodeEnv('MILL_CLOUDEVENTS_NANOID_LENGTH', 21))
25
+ setAttribute({ cloudevent, name: 'id', types: ['string'], value: idValue })
26
+
27
+ const sourceValue = source || fetchNodeEnv('MILL_CLOUDEVENTS_SOURCE')
28
+ setAttribute({ cloudevent, name: 'source', types: ['string'], value: sourceValue })
23
29
 
24
- this.source = source || fetchNodeEnv('MILL_CLOUDEVENTS_SOURCE')
25
- if (!this.source) throw new Error('Cloudevent "source" is required')
26
- if (typeof this.source !== 'string') throw new Error('Cloudevent "source" must be a string')
30
+ const typeValue = type
31
+ setAttribute({ cloudevent, name: 'type', types: ['string'], value: typeValue })
27
32
 
28
- this.type = type
29
- if (!this.type) throw new Error('Cloudevent "type" is required')
30
- if (typeof this.type !== 'string') throw new Error('Cloudevent "type" must be a string')
33
+ const specversionValue = specversion || '1.0'
34
+ setAttribute({ cloudevent, name: 'specversion', types: ['string'], value: specversionValue })
31
35
 
32
- this.specversion = specversion || '1.0'
33
- if (!this.specversion) throw new Error('Cloudevent "specversion" is required')
34
- if (typeof this.specversion !== 'string') throw new Error('Cloudevent "specversion" must be a string')
36
+ const timeValue = new Date().toISOString()
37
+ setAttribute({ cloudevent, name: 'time', types: ['string'], value: timeValue })
38
+ // *******
35
39
 
36
- // * Optional fields by CloudEvent specification
37
- this.data = data
40
+ // *******
41
+ // * Optional fields by Cloudevent v1 specification
42
+ setAttribute({ cloudevent, name: 'data', value: data })
38
43
 
39
- this.datacontenttype = typeof this.data !== 'undefined'
44
+ const datacontenttypeValue = typeof data !== 'undefined'
40
45
  ? datacontenttype || 'application/json'
41
46
  : datacontenttype
42
- if (this.datacontenttype && typeof this.datacontenttype !== 'string') throw new Error('Cloudevent "datacontenttype" must be a string')
47
+ setAttribute({ cloudevent, name: 'datacontenttype', types: ['string', 'undefined'], value: datacontenttypeValue })
43
48
 
44
- this.dataschema = dataschema
45
- if (this.dataschema && typeof this.dataschema !== 'string') throw new Error('Cloudevent "dataschema" must be a string')
49
+ setAttribute({ cloudevent, name: 'dataschema', types: ['string', 'undefined'], value: dataschema })
46
50
 
47
- this.subject = subject
48
- if (this.subject && typeof this.subject !== 'string') throw new Error('Cloudevent "subject" must be a string')
51
+ setAttribute({ cloudevent, name: 'subject', types: ['string', 'undefined'], value: subject })
52
+ // *******
49
53
 
50
- this.time = new Date().toISOString()
54
+ // *******
55
+ // * Required in-house extentions
56
+ const origintimeValue = origintime || timeValue
57
+ setAttribute({ cloudevent, name: 'origintime', types: ['string'], value: origintimeValue })
51
58
 
52
- // * In-house extentions
53
- this.origintime = origintime || this.time
54
- if (!this.origintime) throw new Error('Cloudevent "origintime" is required')
55
- if (typeof this.origintime !== 'string') throw new Error('Cloudevent "origintime" must be a string')
59
+ const originidValue = originid || idValue
60
+ setAttribute({ cloudevent, name: 'originid', types: ['string'], value: originidValue })
56
61
 
57
- this.originid = originid || this.id
58
- if (!this.originid) throw new Error('Cloudevent "originid" is required')
59
- if (typeof this.originid !== 'string') throw new Error('Cloudevent "originid" must be a string')
62
+ const originsourceValue = originsource || sourceValue
63
+ setAttribute({ cloudevent, name: 'originsource', types: ['string'], value: originsourceValue })
60
64
 
61
- this.originsource = originsource || this.source
62
- if (!this.originsource) throw new Error('Cloudevent "originsource" is required')
63
- if (typeof this.originsource !== 'string') throw new Error('Cloudevent "originsource" must be a string')
65
+ const origintypeValue = origintype || typeValue
66
+ setAttribute({ cloudevent, name: 'origintype', types: ['string'], value: origintypeValue })
67
+ // *******
64
68
 
65
- this.origintype = origintype || this.type
66
- if (!this.origintype) throw new Error('Cloudevent "origintype" is required')
67
- if (typeof this.origintype !== 'string') throw new Error('Cloudevent "origintype" must be a string')
69
+ // *******
70
+ // * Optional in-house extentions
71
+ setAttribute({ cloudevent, name: 'originatorid', types: ['string', 'undefined'], value: originatorid })
72
+ // *******
68
73
  }
69
74
  }
@@ -0,0 +1,29 @@
1
+ import { Cloudevent } from '../index.js'
2
+ import { expect } from 'chai'
3
+
4
+ describe('cloudevent#data', () => {
5
+ let params
6
+
7
+ beforeEach(() => {
8
+ params = {
9
+ // * Required base defaults
10
+ source: 'some-source',
11
+ type: 'some-type',
12
+ }
13
+ })
14
+
15
+ describe('when a #data value is not input', () => {
16
+ it('returns undefined', () => {
17
+ const { data } = new Cloudevent(params)
18
+ expect(data).to.be.undefined
19
+ })
20
+ })
21
+
22
+ describe('when a #data value is input', () => {
23
+ it('returns the input value', () => {
24
+ params.data = JSON.stringify({ someData: 'yes' })
25
+ const { data } = new Cloudevent(params)
26
+ expect(data).to.eq(params.data)
27
+ })
28
+ })
29
+ })
@@ -0,0 +1,77 @@
1
+ import { Cloudevent } from '../index.js'
2
+ import { expect } from 'chai'
3
+
4
+ describe('cloudevent#datacontenttype', () => {
5
+ let params
6
+
7
+ beforeEach(() => {
8
+ params = {
9
+ // * Required base defaults
10
+ source: 'some-source',
11
+ type: 'some-type',
12
+ }
13
+ })
14
+
15
+ describe('when a #data value is not input', () => {
16
+ describe('when #datacontenttype is not input', () => {
17
+ it('returns undefined', () => {
18
+ const { datacontenttype } = new Cloudevent(params)
19
+ expect(datacontenttype).to.be.undefined
20
+ })
21
+ })
22
+
23
+ describe('when #datacontenttype is input', () => {
24
+ const validValues = ['some-string', undefined]
25
+
26
+ validValues.forEach(value => {
27
+ describe(`when #datacontenttype is a ${typeof value}`, () => {
28
+ it('returns the input value', () => {
29
+ params.datacontenttype = value
30
+ const { datacontenttype } = new Cloudevent(params)
31
+ expect(datacontenttype).to.eq(params.datacontenttype)
32
+ })
33
+ })
34
+ })
35
+
36
+ describe(`when #datacontenttype is not of type ${validValues.map(item => typeof item).join(' or ')}`, () => {
37
+ it('throws the proper error', () => {
38
+ const expected = `Cloudevent "datacontenttype" must be of type STRING or UNDEFINED`
39
+ params.datacontenttype = 1234
40
+ expect(() => new Cloudevent(params)).to.throw(expected)
41
+ })
42
+ })
43
+ })
44
+ })
45
+
46
+ describe('when a #data value is input', () => {
47
+ describe('when #datacontenttype is not input', () => {
48
+ it('returns "application/json"', () => {
49
+ params.data = JSON.stringify({ some: 'data' })
50
+ const { datacontenttype } = new Cloudevent(params)
51
+ expect(datacontenttype).to.eq('application/json')
52
+ })
53
+ })
54
+
55
+ describe('when #datacontenttype is input', () => {
56
+ const validValues = ['some-string', undefined]
57
+
58
+ validValues.forEach(value => {
59
+ describe(`when #datacontenttype is a ${typeof value}`, () => {
60
+ it('returns the input value', () => {
61
+ params.datacontenttype = value
62
+ const { datacontenttype } = new Cloudevent(params)
63
+ expect(datacontenttype).to.eq(params.datacontenttype)
64
+ })
65
+ })
66
+ })
67
+
68
+ describe(`when #datacontenttype is not of type ${validValues.map(item => typeof item).join(' or ')}`, () => {
69
+ it('throws the proper error', () => {
70
+ const expected = `Cloudevent "datacontenttype" must be of type STRING or UNDEFINED`
71
+ params.datacontenttype = 1234
72
+ expect(() => new Cloudevent(params)).to.throw(expected)
73
+ })
74
+ })
75
+ })
76
+ })
77
+ })
@@ -0,0 +1,39 @@
1
+ import { Cloudevent } from '../index.js'
2
+ import { expect } from 'chai'
3
+
4
+ describe('cloudevent#dataschema', () => {
5
+ let params
6
+
7
+ beforeEach(() => {
8
+ params = {
9
+ // * Required base defaults
10
+ source: 'some-source',
11
+ type: 'some-type',
12
+ }
13
+ })
14
+
15
+ describe('when #dataschema is not input', () => {
16
+ it('returns undefined', () => {
17
+ const { dataschema } = new Cloudevent(params)
18
+ expect(dataschema).to.be.undefined
19
+ })
20
+ })
21
+
22
+ describe('when #dataschema is input', () => {
23
+ describe('when the input value is invalid', () => {
24
+ it('throws the proper error', () => {
25
+ const expected = 'Cloudevent "dataschema" must be of type STRING or UNDEFINED'
26
+ params.dataschema = 1234
27
+ expect(() => new Cloudevent(params)).to.throw(expected)
28
+ })
29
+ })
30
+
31
+ describe('when the input value is valid', () => {
32
+ it('sets cloudevent#dataschema to the input value', () => {
33
+ params.dataschema = 'some-string'
34
+ const { dataschema } = new Cloudevent(params)
35
+ expect(dataschema).to.eq(params.dataschema)
36
+ })
37
+ })
38
+ })
39
+ })
@@ -0,0 +1,45 @@
1
+ import { Cloudevent } from '../index.js'
2
+ import { createSandbox } from 'sinon'
3
+ import { expect } from 'chai'
4
+
5
+ describe('cloudevent#id', () => {
6
+ const sandbox = createSandbox()
7
+ let params
8
+
9
+ beforeEach(() => {
10
+ params = {
11
+ // * Required base defaults
12
+ source: 'some-source',
13
+ type: 'some-type',
14
+ }
15
+ })
16
+
17
+ afterEach(() => {
18
+ sandbox.restore()
19
+ })
20
+
21
+ it('returns a string', () => {
22
+ const { id } = new Cloudevent(params)
23
+ expect(id).to.be.a('string')
24
+ })
25
+
26
+ describe('when process.env.MILL_CLOUDEVENTS_NANOID_LENGTH is not input', () => {
27
+ it('returns a string with the proper length', () => {
28
+ sandbox.stub(process, 'env').value({})
29
+ const { id } = new Cloudevent(params)
30
+ expect(id).to.have.lengthOf(21)
31
+ })
32
+ })
33
+
34
+ describe('when process.env.MILL_CLOUDEVENTS_NANOID_LENGTH is input', () => {
35
+ it('returns a string with the proper length', () => {
36
+ const expected = '123'
37
+
38
+ const env = { MILL_CLOUDEVENTS_NANOID_LENGTH: expected }
39
+ sandbox.stub(process, 'env').value(env)
40
+
41
+ const { id } = new Cloudevent(params)
42
+ expect(id).to.have.lengthOf(expected)
43
+ })
44
+ })
45
+ })
@@ -0,0 +1,39 @@
1
+ import { Cloudevent } from '../index.js'
2
+ import { expect } from 'chai'
3
+
4
+ describe('cloudevent#originatorid', () => {
5
+ let params
6
+
7
+ beforeEach(() => {
8
+ params = {
9
+ // * Required base defaults
10
+ source: 'some-source',
11
+ type: 'some-type',
12
+ }
13
+ })
14
+
15
+ describe('when #originatorid is not input', () => {
16
+ it('returns #id', () => {
17
+ const { originatorid } = new Cloudevent(params)
18
+ expect(originatorid).to.be.undefined
19
+ })
20
+ })
21
+
22
+ describe('when #originatorid is input', () => {
23
+ describe('when the input value is invalid', () => {
24
+ it('throws the proper error', () => {
25
+ const expected = 'Cloudevent "originatorid" must be of type STRING or UNDEFINED'
26
+ params.originatorid = 1234
27
+ expect(() => new Cloudevent(params)).to.throw(expected)
28
+ })
29
+ })
30
+
31
+ describe('when the input value is valid', () => {
32
+ it('sets cloudevent[originatorid] to the input value', () => {
33
+ params.originatorid = 'some-originator-id'
34
+ const { originatorid } = new Cloudevent(params)
35
+ expect(originatorid).to.eq(params.originatorid)
36
+ })
37
+ })
38
+ })
39
+ })
@@ -0,0 +1,40 @@
1
+ import { Cloudevent } from '../index.js'
2
+ import { expect } from 'chai'
3
+
4
+ describe('cloudevent#originid', () => {
5
+ let params
6
+
7
+ beforeEach(() => {
8
+ params = {
9
+ // * Required base defaults
10
+ source: 'some-source',
11
+ type: 'some-type',
12
+ }
13
+ })
14
+
15
+ describe('when #originid is not input', () => {
16
+ it('returns #id', () => {
17
+ params.originid = null
18
+ const { id, originid } = new Cloudevent(params)
19
+ expect(originid).to.eq(id)
20
+ })
21
+ })
22
+
23
+ describe('when #originid is input', () => {
24
+ describe('when the input value is invalid', () => {
25
+ it('throws the proper error', () => {
26
+ const expected = 'Cloudevent "originid" must be of type STRING'
27
+ params.originid = 1234
28
+ expect(() => new Cloudevent(params)).to.throw(expected)
29
+ })
30
+ })
31
+
32
+ describe('when the input value is valid', () => {
33
+ it('sets cloudevent#originid to the input value', () => {
34
+ params.originid = 'some-origin-id'
35
+ const { originid } = new Cloudevent(params)
36
+ expect(originid).to.eq(params.originid)
37
+ })
38
+ })
39
+ })
40
+ })
@@ -0,0 +1,40 @@
1
+ import { Cloudevent } from '../index.js'
2
+ import { expect } from 'chai'
3
+
4
+ describe('cloudevent#originsource', () => {
5
+ let params
6
+
7
+ beforeEach(() => {
8
+ params = {
9
+ // * Required base defaults
10
+ source: 'some-source',
11
+ type: 'some-type',
12
+ }
13
+ })
14
+
15
+ describe('when #originsource is not input', () => {
16
+ it('returns #source', () => {
17
+ params.originsource = null
18
+ const { source, originsource } = new Cloudevent(params)
19
+ expect(originsource).to.eq(source)
20
+ })
21
+ })
22
+
23
+ describe('when #originsource is input', () => {
24
+ describe('when the input value is invalid', () => {
25
+ it('throws the proper error', () => {
26
+ const expected = 'Cloudevent "originsource" must be of type STRING'
27
+ params.originsource = 1234
28
+ expect(() => new Cloudevent(params)).to.throw(expected)
29
+ })
30
+ })
31
+
32
+ describe('when the input value is valid', () => {
33
+ it('sets cloudevent#originsource to the input value', () => {
34
+ params.originsource = 'some-origin-source'
35
+ const { originsource } = new Cloudevent(params)
36
+ expect(originsource).to.eq(params.originsource)
37
+ })
38
+ })
39
+ })
40
+ })
@@ -0,0 +1,39 @@
1
+ import { Cloudevent } from '../index.js'
2
+ import { expect } from 'chai'
3
+
4
+ describe('cloudevent#origintime', () => {
5
+ let params
6
+
7
+ beforeEach(() => {
8
+ params = {
9
+ // * Required base defaults
10
+ source: 'some-source',
11
+ type: 'some-type',
12
+ }
13
+ })
14
+
15
+ describe('when #origintime is not input', () => {
16
+ it('returns #time', () => {
17
+ const { origintime, time } = new Cloudevent(params)
18
+ expect(origintime).to.eq(time)
19
+ })
20
+ })
21
+
22
+ describe('when #origintime is input', () => {
23
+ describe('when the input value is invalid', () => {
24
+ it('throws the proper error', () => {
25
+ const expected = 'Cloudevent "origintime" must be of type STRING'
26
+ params.origintime = 1234
27
+ expect(() => new Cloudevent(params)).to.throw(expected)
28
+ })
29
+ })
30
+
31
+ describe('when the input value is valid', () => {
32
+ it('sets cloudevent#origintime to the input value', () => {
33
+ params.origintime = new Date().toISOString()
34
+ const { origintime } = new Cloudevent(params)
35
+ expect(origintime).to.eq(params.origintime)
36
+ })
37
+ })
38
+ })
39
+ })
@@ -0,0 +1,40 @@
1
+ import { Cloudevent } from '../index.js'
2
+ import { expect } from 'chai'
3
+
4
+ describe('cloudevent#origintype', () => {
5
+ let params
6
+
7
+ beforeEach(() => {
8
+ params = {
9
+ // * Required base defaults
10
+ type: 'some-type',
11
+ source: 'some-source',
12
+ }
13
+ })
14
+
15
+ describe('when #origintype is not input', () => {
16
+ it('returns #type', () => {
17
+ params.origintype = null
18
+ const { type, origintype } = new Cloudevent(params)
19
+ expect(origintype).to.eq(type)
20
+ })
21
+ })
22
+
23
+ describe('when #origintype is input', () => {
24
+ describe('when the input value is invalid', () => {
25
+ it('throws the proper error', () => {
26
+ const expected = 'Cloudevent "origintype" must be of type STRING'
27
+ params.origintype = 1234
28
+ expect(() => new Cloudevent(params)).to.throw(expected)
29
+ })
30
+ })
31
+
32
+ describe('when the input value is valtype', () => {
33
+ it('sets cloudevent#origintype to the input value', () => {
34
+ params.origintype = 'some-origin-type'
35
+ const { origintype } = new Cloudevent(params)
36
+ expect(origintype).to.eq(params.origintype)
37
+ })
38
+ })
39
+ })
40
+ })
@@ -0,0 +1,63 @@
1
+ import { Cloudevent } from '../index.js'
2
+ import { createSandbox } from 'sinon'
3
+ import { expect } from 'chai'
4
+
5
+ describe('cloudevent#source', () => {
6
+ const sandbox = createSandbox()
7
+ let params
8
+
9
+ beforeEach(() => {
10
+ params = {
11
+ // * Required base defaults
12
+ source: 'some-source',
13
+ type: 'some-type',
14
+ }
15
+ })
16
+
17
+ afterEach(() => {
18
+ sandbox.restore()
19
+ })
20
+
21
+ describe('when a #source value is not input', () => {
22
+ beforeEach(() => {
23
+ params.source = null
24
+ })
25
+
26
+ describe('when process.env.MILL_CLOUDEVENTS_SOURCE is not input', () => {
27
+ it('throws the proper error', () => {
28
+ const expected = 'Cloudevent "source" must be of type STRING'
29
+ sandbox.stub(process, 'env').value({})
30
+ expect(() => new Cloudevent(params)).to.throw(expected)
31
+ })
32
+ })
33
+
34
+ describe('when process.env.MILL_CLOUDEVENTS_SOURCE is input', () => {
35
+ it('returns the input input value', () => {
36
+ const expected = 'some-env-var-value'
37
+
38
+ const env = { MILL_CLOUDEVENTS_SOURCE: expected }
39
+ sandbox.stub(process, 'env').value(env)
40
+
41
+ const { source } = new Cloudevent(params)
42
+ expect(source).to.eq(expected)
43
+ })
44
+ })
45
+ })
46
+
47
+ describe('when a #source value is input', () => {
48
+ describe('when the input value is not a string', () => {
49
+ it('throws the proper error', () => {
50
+ const expected = 'Cloudevent "source" must be of type STRING'
51
+ params.source = 1234
52
+ expect(() => new Cloudevent(params)).to.throw(expected)
53
+ })
54
+ })
55
+
56
+ describe('when the input value is a string', () => {
57
+ it('returns the input value', () => {
58
+ const { source } = new Cloudevent(params)
59
+ expect(source).to.eq(params.source)
60
+ })
61
+ })
62
+ })
63
+ })
@@ -0,0 +1,41 @@
1
+ import { Cloudevent } from '../index.js'
2
+ import { expect } from 'chai'
3
+
4
+ describe('cloudevent#specversion', () => {
5
+ let params
6
+
7
+ beforeEach(() => {
8
+ params = {
9
+ // * Required base defaults
10
+ source: 'some-source',
11
+ type: 'some-type',
12
+ }
13
+ })
14
+
15
+ describe('when a #specversion value is not input', () => {
16
+ it('returns the proper value', () => {
17
+ const expected = '1.0'
18
+ const { specversion } = new Cloudevent(params)
19
+ expect(specversion).to.eq(expected)
20
+ })
21
+ })
22
+
23
+ describe('when a #specversion value is input', () => {
24
+ describe('when the input value is not a string', () => {
25
+ it('throws the proper error', () => {
26
+ params.specversion = 1234
27
+ const expected = 'Cloudevent "specversion" must be of type STRING'
28
+ expect(() => new Cloudevent(params)).to.throw(expected)
29
+ })
30
+ })
31
+
32
+ describe('when the input value is a string', () => {
33
+ it('returns the input value', () => {
34
+ const expected = '4.3.2.1'
35
+ params.specversion = expected
36
+ const { specversion } = new Cloudevent(params)
37
+ expect(specversion).to.eq(expected)
38
+ })
39
+ })
40
+ })
41
+ })
@@ -0,0 +1,39 @@
1
+ import { Cloudevent } from '../index.js'
2
+ import { expect } from 'chai'
3
+
4
+ describe('cloudevent#subject', () => {
5
+ let params
6
+
7
+ beforeEach(() => {
8
+ params = {
9
+ // * Required base defaults
10
+ source: 'some-source',
11
+ type: 'some-type',
12
+ }
13
+ })
14
+
15
+ describe('when #subject is not input', () => {
16
+ it('returns undefined', () => {
17
+ const { subject } = new Cloudevent(params)
18
+ expect(subject).to.be.undefined
19
+ })
20
+ })
21
+
22
+ describe('when #subject is not input', () => {
23
+ describe('when the input value is invalid', () => {
24
+ it('throws the proper error', () => {
25
+ const expected = 'Cloudevent "subject" must be of type STRING or UNDEFINED'
26
+ params.subject = 1234
27
+ expect(() => new Cloudevent(params)).to.throw(expected)
28
+ })
29
+ })
30
+
31
+ describe('when the input value is valid', () => {
32
+ it('sets cloudevent#subject to the input value', () => {
33
+ params.subject = 'some-string'
34
+ const { subject } = new Cloudevent(params)
35
+ expect(subject).to.eq(params.subject)
36
+ })
37
+ })
38
+ })
39
+ })