cloudevent / cloudevent.js
JavaScript/Node.js implementation of CloudEvents
Current release implements the v1.0.2 of the CloudEvents Spec.
The purpose of this library is to create instances of CloudEvents in a simple way
(with some useful defaults), or in a full way (all attributes).
Optional, it's possible to validate created instances to be sure they are compliant with the standard.
Then, created instances can be serialized, for example to be sent (or saved/stored) somewhere.
Note that many features are exposed directly by the CloudEvent class with standard class instance
methods, and even as class static methods (that operates on a given CloudEvent).
Anyway, to be more future-proof the library now exports a main object, with all features inside
(the class for CloudEvent, its Validator class as CloudEventValidator, etc);
using destructuring assignment (as seen in code samples) usage will be easier.
For changes and release notes, see CHANGELOG.
Usage
Get a reference to the library:
const { CloudEvent, CloudEventValidator: V, CloudEventTransformer: T } = require('cloudevent')
assert(CloudEvent !== null && V !== null && T !== null)
create some sample CloudEvent instances:
const ceEmpty = new CloudEvent()
const ceMinimalMandatoryUndefinedNoStrict = new CloudEvent(undefined, undefined, undefined, undefined, { strict: false })
const ceMinimalMandatoryUndefinedStrict = new CloudEvent(undefined, undefined, undefined, undefined, { strict: true })
const ceCommonOptions = {
time: new Date(),
datacontenttype: 'application/json',
dataschema: 'http://my-schema.localhost.localdomain/v1/',
subject: 'subject',
strict: false
}
const ceCommonOptionsStrict = { ...ceCommonOptions, strict: true }
const ceCommonOptionsForTextData = { ...ceCommonOptions, datacontenttype: 'text/plain' }
const ceCommonExtensions = { exampleextension: 'value' }
const ceNamespace = 'com.github.smartiniOnGitHub.cloudeventjs.testevent-v1.0.0'
const ceServerUrl = '/test'
const ceCommonData = { hello: 'world', year: 2020, enabled: true }
const ceDataAsJSONString = '{ "hello": "world", "year": 2020, "enabled": true }'
const ceDataAsString = 'Hello World, 2020'
const ceDataEncoded = 'SGVsbG8gV29ybGQsIDIwMjA='
const ceMinimalBadSource = new CloudEvent('1', ceNamespace, 'source (bad)', null)
const ceMinimal = new CloudEvent('1',
ceNamespace,
'/',
{}
)
const ceFull = new CloudEvent('1/full',
ceNamespace,
ceServerUrl,
ceCommonData,
ceCommonOptions,
ceCommonExtensions
)
const ceFullStrict = new CloudEvent('2/full-strict',
ceNamespace,
ceServerUrl,
ceCommonData,
ceCommonOptionsStrict,
ceCommonExtensions
)
const ceFullStrictJSONTextData = new CloudEvent('2/full-strict-json-string-data',
ceNamespace,
ceServerUrl,
ceDataAsJSONString,
ceCommonOptionsStrict,
ceCommonExtensions
)
const error = new Error('sample error')
error.code = 1000
const errorToData = T.errorToData(error, {
includeStackTrace: true,
addTimestamp: true
})
const ceErrorStrict = new CloudEvent('3/error-strict',
ceNamespace,
ceServerUrl,
errorToData,
ceCommonOptionsStrict,
ceCommonExtensions
)
const ceFullStrictOtherContentType = new CloudEvent('4/full-strict-other-content-type',
ceNamespace,
ceServerUrl,
ceCommonData,
{ ...ceCommonOptionsStrict, datacontenttype: 'application/xml' },
ceCommonExtensions
)
const ceFullTextData = new CloudEvent('5/no-strict-text-data',
ceNamespace,
ceServerUrl,
ceDataAsString,
ceCommonOptionsForTextData,
ceCommonExtensions
)
console.log(`cloudEvent payload: '${ceFullTextData.payload}', length: ${ceFullTextData.payload.length}`)
const ceFullStrictBinaryData = new CloudEvent('6/full-strict-binary-data',
ceNamespace,
ceServerUrl,
null,
{ ...ceCommonOptionsStrict, datainbase64: ceDataEncoded },
ceCommonExtensions
)
console.log(`cloudEvent payload: '${ceFullStrictBinaryData.payload}', length: ${ceFullStrictBinaryData.payload.length}`)
optional, do some validations/checks on created instances.
As sample, use class static methods like 'isValidEvent' and 'ValidateEvent',
or instance methods like 'isValid', 'validate', etc ...
assert(!ceEmpty.isValid())
assert(!ceMinimalMandatoryUndefinedNoStrict.isValid())
assert(ceMinimalBadSource.isValid())
assert(!ceMinimalBadSource.isValid({ strict: true }))
assert(ceMinimal.isValid())
assert(ceMinimal.isValid({ strict: true }))
assert(ceFull.isValid())
assert(ceFullStrict.isValid())
assert(ceErrorStrict.isValid())
assert(ceFullStrictOtherContentType.isValid())
assert(ceFullTextData.isValid())
assert(ceFullTextData.isValid({ strict: true }))
assert(CloudEvent.isValidEvent(ceFullTextData, { strict: true }))
assert(CloudEvent.isValidEvent(ceFullStrictBinaryData))
console.log(`Validation on ceEmpty: isValid: ${ceEmpty.isValid()}`)
console.log(`Validation output for ceEmpty, default strict mode is: size: ${CloudEvent.validateEvent(ceEmpty).length}, details:\n` + CloudEvent.validateEvent(ceEmpty))
console.log(`Validation output for ceEmpty, force strict mode to true is size: ${CloudEvent.validateEvent(ceEmpty, { strict: true }).length}, details:\n` + CloudEvent.validateEvent(ceEmpty, { strict: true }))
console.log(`Validation output for ceEmpty, alternative way: ${CloudEvent.dumpValidationResults(ceEmpty, { strict: true }, 'ceEmpty')}`)
serialization examples:
const ceFullSerializedStatic = CloudEvent.serializeEvent(ceFull)
const ceFullSerialized = ceFull.serialize()
console.log('Serialization output for ceFull, details:\n' + ceFullSerialized)
const ceFullStrictSerialized = ceFullStrict.serialize()
console.log('Serialization output for ceFullStrict, details:\n' + ceFullStrictSerialized)
const ceFullStrictOtherContentTypeSerializedStatic = CloudEvent.serializeEvent(ceFullStrictOtherContentType, {
encodedData: '<data "hello"="world" "year"="2020" />',
onlyValid: true
})
const ceFullStrictOtherContentTypeSerialized = ceFullStrictOtherContentType.serialize({
encodedData: '<data "hello"="world" "year"="2020" />',
onlyValid: true
})
console.log('Serialization output for ceFullStrictOtherContentType, details:\n' + ceFullStrictOtherContentTypeSerialized)
const ceFullTextDataSerialized = CloudEvent.serializeEvent(ceFullTextData, { onlyValid: true })
console.log('Serialization output for ceFullTextData, details:\n' + ceFullTextDataSerialized)
const ceFullStrictBinaryDataSerialized = CloudEvent.serializeEvent(ceFullStrictBinaryData, { onlyValid: true })
console.log('Serialization output for ceFullStrictBinaryData, details:\n' + ceFullStrictBinaryDataSerialized)
deserialization (parse) examples:
console.log('\nSome deserialization/parse examples:')
const ceFullDeserialized = CloudEvent.deserializeEvent(ceFullSerialized)
console.log(`cloudEvent dump: ${T.dumpObject(ceFullDeserialized, 'ceFullDeserialized')}`)
const ceFullStrictDeserializedOnlyValid = CloudEvent.deserializeEvent(ceFullStrictSerialized, { onlyValid: true })
console.log(`cloudEvent dump: ${T.dumpObject(ceFullStrictDeserializedOnlyValid, 'ceFullStrictDeserializedOnlyValid')}`)
const ceFullStrictOtherContentTypeDeserialized = CloudEvent.deserializeEvent(ceFullStrictOtherContentTypeSerialized, {
decodedData: { hello: 'world', year: 2020 },
onlyValid: true
})
console.log(`cloudEvent dump: ${T.dumpObject(ceFullStrictOtherContentTypeDeserialized, 'ceFullStrictOtherContentTypeDeserialized')}`)
const ceFullTextDataDeserialized = CloudEvent.deserializeEvent(ceFullTextDataSerialized, { onlyValid: true })
console.log(`ce dump: ${T.dumpObject(ceFullTextDataDeserialized, 'ceFullTextDataDeserialized')}`)
const ceFullStrictBinaryDataDeserialized = CloudEvent.deserializeEvent(ceFullStrictBinaryDataSerialized, { onlyValid: true })
console.log(`ce dump: ${T.dumpObject(ceFullStrictBinaryDataDeserialized, 'ceFullStrictBinaryDataDeserialized')}`)
From previous code blocks, I remove most assert statements, to simplify
code reading and usage; but for a deeper comprension and usage,
look into the example folder for more sample scripts that uses the library
(inline but it's the same using it from npm registry);
you can find even examples for using JSONBatch objects (array of CloudEvent instances).
Requirements
Node.js 14 LTS (14.15.0) or later (anyway, recommended an active LTS version).
Sources
Source code is all inside main repo:
cloudevent.js.
Documentation generated from source code (library API):
here.
Note
Note that in this implementation there is even the ability to validate CloudEvent instances
in a stricter way, by setting to true the attribute 'strict' in constructor options;
that attribute (when set) will be put in the extensions of the instance.
Otherwise you can specify it only during validation, in validation options.
See the CloudEvents Specification here.
In the past the name for this package was 'cloudevent.js', but it has been deprecated now
and changed to the simpler 'cloudevent', so it will be easier to get it at npm.
Since v0.2 of the spec, there is no more a standard attribute to specify the version
of any specific event type, so the best if to follow their recommendations,
and for example add a version in the 'type' attribute
(for example '-v1.0.0' at the end of its base value, or at the end of its full value),
or into the 'schemaurl' attribute but only its major version
(like '-v1' or '/v1/' at the end).
Since v0.3 of the spec, there is no more a standard attribute for extensions,
so they are merged into usual properties (but must not use names
of standard properties); a best practice is to use reverse-DNS name
but without dots, so like 'com_github_smartiniOnGitHub_cloudevent'.
Since v1.0 of the spec, some properties has been removed/simplified;
extension properties must be simple (no nested properties)
and must contain only lowercase letters and numbers in the name (and less than 20 chars in total);
so for example my strict extension now is 'strictvalidation' with a boolean value.
Since v1.0.1 of the spec, some properties has been expanded/clarified.
Since v1.0.2 of the spec, the check on 'datacontenttype' if it's JSON-like
has been updated.
Contributing
- Fork it ( https://github.com/smartiniOnGitHub/cloudevent.js/fork )
- Create your feature branch (git checkout -b my-new-feature)
- Commit your changes (git commit -am 'Add some feature')
- Push to the branch (git push origin my-new-feature)
- Create a new Pull Request
License
Licensed under Apache-2.0.