319 lines
8.7 KiB
JavaScript
319 lines
8.7 KiB
JavaScript
const Spec1 = require("./bindings/http/v1/spec_1.js");
|
|
const Spec03 = require("./bindings/http/v03/spec_0_3.js");
|
|
const Formatter = require("./formats/json/formatter.js");
|
|
|
|
const { SPEC_V1, SPEC_V03 } = require("./bindings/http/constants.js");
|
|
const { isBinary } = require("./bindings/http/validation/fun.js");
|
|
|
|
/**
|
|
* An CloudEvent describes event data in common formats to provide
|
|
* interoperability across services, platforms and systems.
|
|
* @see https://github.com/cloudevents/spec/blob/v1.0/spec.md
|
|
*/
|
|
class CloudEvent {
|
|
/**
|
|
* Creates a new CloudEvent instance
|
|
* @param {object} options CloudEvent properties as a simple object
|
|
* @param {string} options.source Identifies the context in which an event happened as a URI reference
|
|
* @param {string} options.type Describes the type of event related to the originating occurrence
|
|
* @param {string} [options.id] A unique ID for this event - if not supplied, will be autogenerated
|
|
* @param {string} [options.time] A timestamp for this event. May also be provided as a Date
|
|
* @param {string} [options.subject] Describes the subject of the event in the context of the event producer
|
|
* @param {string} [options.dataContentType] The mime content type for the event data
|
|
* @param {string} [options.dataSchema] The URI of the schema that the event data adheres to (v1.0 events)
|
|
* @param {string} [options.schemaURL] The URI of the schema that the event data adheres to (v0.3 events)
|
|
* @param {string} [options.dataContentEncoding] The content encoding for the event data (v0.3 events)
|
|
* @param {string} [options.specversion] The CloudEvent specification version for this event - default: 1.0
|
|
* @param {*} [options.data] The event payload
|
|
*/
|
|
constructor({
|
|
id,
|
|
source,
|
|
type,
|
|
dataContentType,
|
|
time,
|
|
subject,
|
|
dataSchema,
|
|
schemaURL,
|
|
dataContentEncoding,
|
|
data,
|
|
specversion = SPEC_V1 } = {
|
|
id: undefined,
|
|
source: undefined,
|
|
type: undefined,
|
|
dataContentType: undefined,
|
|
time: undefined,
|
|
subject: undefined,
|
|
dataSchema: undefined,
|
|
schemaURL: undefined,
|
|
dataContentEncoding: undefined,
|
|
data: undefined
|
|
}) {
|
|
|
|
if (!type || !source) {
|
|
throw new TypeError("event type and source are required");
|
|
}
|
|
|
|
switch (specversion) {
|
|
case SPEC_V1:
|
|
this.spec = new Spec1();
|
|
break;
|
|
case SPEC_V03:
|
|
this.spec = new Spec03();
|
|
break;
|
|
default:
|
|
throw new TypeError(`unknown specification version ${specversion}`);
|
|
}
|
|
this.source = source;
|
|
this.type = type;
|
|
this.dataContentType = dataContentType;
|
|
this.data = data;
|
|
this.subject = subject;
|
|
|
|
if (dataSchema) {
|
|
this.dataSchema = dataSchema;
|
|
}
|
|
|
|
// TODO: Deprecated in 1.0
|
|
if (dataContentEncoding) {
|
|
this.dataContentEncoding = dataContentEncoding;
|
|
}
|
|
|
|
// TODO: Deprecated in 1.0
|
|
if (schemaURL) {
|
|
this.schemaURL = schemaURL;
|
|
}
|
|
|
|
if (id) {
|
|
this.id = id;
|
|
}
|
|
|
|
if (time) {
|
|
this.time = time;
|
|
}
|
|
this.formatter = new Formatter();
|
|
}
|
|
|
|
/**
|
|
* Gets or sets the event id. Source + id must be unique for each distinct event.
|
|
* @see https://github.com/cloudevents/spec/blob/master/spec.md#id
|
|
* @type {string}
|
|
*/
|
|
get id() {
|
|
return this.spec.id;
|
|
}
|
|
|
|
set id(id) {
|
|
this.spec.id = id;
|
|
}
|
|
|
|
/**
|
|
* Gets or sets the origination source of this event as a URI.
|
|
* @type {string}
|
|
* @see https://github.com/cloudevents/spec/blob/master/spec.md#source-1
|
|
*/
|
|
get source() {
|
|
return this.spec.source;
|
|
}
|
|
|
|
set source(source) {
|
|
this.spec.source = source;
|
|
}
|
|
|
|
/**
|
|
* Gets the CloudEvent specification version
|
|
* @type {string}
|
|
* @see https://github.com/cloudevents/spec/blob/master/spec.md#specversion
|
|
*/
|
|
get specversion() {
|
|
return this.spec.specversion;
|
|
}
|
|
|
|
/**
|
|
* Gets or sets the event type
|
|
* @type {string}
|
|
* @see https://github.com/cloudevents/spec/blob/master/spec.md#type
|
|
*/
|
|
get type() {
|
|
return this.spec.type;
|
|
}
|
|
|
|
set type(type) {
|
|
this.spec.type = type;
|
|
}
|
|
|
|
/**
|
|
* Gets or sets the content type of the data value for this event
|
|
* @type {string}
|
|
* @see https://github.com/cloudevents/spec/blob/master/spec.md#datacontenttype
|
|
*/
|
|
get dataContentType() {
|
|
return this.spec.dataContentType;
|
|
}
|
|
|
|
set dataContentType(contenttype) {
|
|
this.spec.dataContentType = contenttype;
|
|
}
|
|
|
|
/**
|
|
* Gets or sets the event's data schema
|
|
* @type {string}
|
|
* @see https://github.com/cloudevents/spec/blob/v1.0/spec.md#dataschema
|
|
*/
|
|
get dataSchema() {
|
|
if (this.spec instanceof Spec1) {
|
|
return this.spec.dataSchema;
|
|
}
|
|
throw new TypeError("cannot get dataSchema from version 0.3 event");
|
|
}
|
|
|
|
set dataSchema(dataschema) {
|
|
if (this.spec instanceof Spec1) {
|
|
this.spec.dataSchema = dataschema;
|
|
} else {
|
|
throw new TypeError("cannot set dataSchema on version 0.3 event");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets or sets the event's data content encoding
|
|
* @type {string}
|
|
* @see https://github.com/cloudevents/spec/blob/v0.3/spec.md#datacontentencoding
|
|
*/
|
|
get dataContentEncoding() {
|
|
if (this.spec instanceof Spec03) {
|
|
return this.spec.dataContentEncoding;
|
|
}
|
|
throw new TypeError("cannot get dataContentEncoding from version 1.0 event");
|
|
}
|
|
|
|
set dataContentEncoding(dataContentEncoding) {
|
|
if (this.spec instanceof Spec03) {
|
|
this.spec.dataContentEncoding = dataContentEncoding;
|
|
} else {
|
|
throw new TypeError("cannot set dataContentEncoding on version 1.0 event");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets or sets the event subject
|
|
* @type {string}
|
|
* @see https://github.com/cloudevents/spec/blob/v1.0/spec.md#subject
|
|
*/
|
|
get subject() {
|
|
return this.spec.subject;
|
|
}
|
|
|
|
set subject(subject) {
|
|
this.spec.subject = subject;
|
|
}
|
|
|
|
/**
|
|
* Gets or sets the timestamp for this event as an ISO formatted date string
|
|
* @type {string}
|
|
* @see https://github.com/cloudevents/spec/blob/master/spec.md#time
|
|
*/
|
|
get time() {
|
|
return this.spec.time;
|
|
}
|
|
|
|
set time(time) {
|
|
this.spec.time = new Date(time).toISOString();
|
|
}
|
|
|
|
/**
|
|
* DEPRECATED: Gets or sets the schema URL for this event. Throws {TypeError}
|
|
* if this is a version 1.0 event.
|
|
* @type {string}
|
|
* @see https://github.com/cloudevents/spec/blob/v0.3/spec.md#schemaurl
|
|
*/
|
|
get schemaURL() {
|
|
if (this.spec instanceof Spec03) {
|
|
return this.spec.schemaURL;
|
|
}
|
|
throw new TypeError("cannot get schemaURL from version 1.0 event");
|
|
}
|
|
|
|
// TODO: Deprecated in 1.0
|
|
set schemaURL(schemaurl) {
|
|
if (schemaurl && (this.spec instanceof Spec03)) {
|
|
this.spec.schemaURL = schemaurl;
|
|
} else if (schemaurl) {
|
|
throw new TypeError("cannot set schemaURL on version 1.0 event");
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Gets or sets the data for this event
|
|
* @see https://github.com/cloudevents/spec/blob/master/spec.md#event-data
|
|
* @type {*}
|
|
*/
|
|
get data() {
|
|
return this.spec.data;
|
|
}
|
|
|
|
set data(data) {
|
|
this.spec.data = data;
|
|
}
|
|
|
|
/**
|
|
* Formats the CloudEvent as JSON. Validates the event according
|
|
* to the CloudEvent specification and throws an exception if
|
|
* it's invalid.
|
|
* @returns {JSON} the CloudEvent in JSON form
|
|
* @throws {ValidationError} if this event cannot be validated against the specification
|
|
*/
|
|
format() {
|
|
this.spec.check();
|
|
const payload = {
|
|
data: undefined,
|
|
data_base64: undefined,
|
|
...this.spec.payload
|
|
};
|
|
|
|
// Handle when is binary, creating the data_base64
|
|
if (isBinary(payload.data)) {
|
|
// TODO: The call to this.spec.data formats the binary data
|
|
// I think having a side effect like this is an anti-pattern.
|
|
// FIXIT
|
|
payload.data_base64 = this.spec.data;
|
|
delete payload.data;
|
|
} else {
|
|
delete payload.data_base64;
|
|
}
|
|
return this.formatter.format(payload);
|
|
}
|
|
|
|
/**
|
|
* Formats the CloudEvent as JSON. No specification validation is performed.
|
|
* @returns {string} the CloudEvent as a JSON string
|
|
*/
|
|
toString() {
|
|
return this.formatter.toString(this.spec.payload);
|
|
}
|
|
|
|
/**
|
|
* Adds an extension attribute to this CloudEvent
|
|
* @see https://github.com/cloudevents/spec/blob/master/spec.md#extension-context-attributes
|
|
* @param {string} key the name of the extension attribute
|
|
* @param {*} value the value of the extension attribute
|
|
* @returns {void}
|
|
*/
|
|
addExtension(key, value) {
|
|
this.spec.addExtension(key, value);
|
|
this.extensions = { [key]: value, ...this.extensions };
|
|
}
|
|
|
|
/**
|
|
* Gets the extension attributes, if any, associated with this event
|
|
* @see https://github.com/cloudevents/spec/blob/master/spec.md#extension-context-attributes
|
|
* @returns {Object} the extensions attributes - if none exist will will be {}
|
|
*/
|
|
getExtensions() {
|
|
return this.extensions;
|
|
}
|
|
}
|
|
|
|
module.exports = CloudEvent;
|