feat: use generic type for CloudEvent data (#446)
Instead of using a big union of types, use a generic type for event data. Fixes: https://github.com/cloudevents/sdk-javascript/issues/445 Signed-off-by: Lance Ball <lball@redhat.com>
This commit is contained in:
parent
52ea7de80d
commit
d941e2d4d9
|
@ -6,7 +6,7 @@
|
||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from "uuid";
|
||||||
import { Emitter } from "..";
|
import { Emitter } from "..";
|
||||||
|
|
||||||
import { CloudEventV1, CloudEventV1Attributes, CloudEventV1OptionalAttributes } from "./interfaces";
|
import { CloudEventV1 } from "./interfaces";
|
||||||
import { validateCloudEvent } from "./spec";
|
import { validateCloudEvent } from "./spec";
|
||||||
import { ValidationError, isBinary, asBase64, isValidType } from "./validation";
|
import { ValidationError, isBinary, asBase64, isValidType } from "./validation";
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ export const enum Version {
|
||||||
* interoperability across services, platforms and systems.
|
* interoperability across services, platforms and systems.
|
||||||
* @see https://github.com/cloudevents/spec/blob/v1.0/spec.md
|
* @see https://github.com/cloudevents/spec/blob/v1.0/spec.md
|
||||||
*/
|
*/
|
||||||
export class CloudEvent implements CloudEventV1 {
|
export class CloudEvent<T = undefined> implements CloudEventV1<T> {
|
||||||
id: string;
|
id: string;
|
||||||
type: string;
|
type: string;
|
||||||
source: string;
|
source: string;
|
||||||
|
@ -32,7 +32,7 @@ export class CloudEvent implements CloudEventV1 {
|
||||||
dataschema?: string;
|
dataschema?: string;
|
||||||
subject?: string;
|
subject?: string;
|
||||||
time?: string;
|
time?: string;
|
||||||
#_data?: Record<string, unknown | string | number | boolean> | string | number | boolean | null | unknown;
|
#_data?: T;
|
||||||
data_base64?: string;
|
data_base64?: string;
|
||||||
|
|
||||||
// Extensions should not exist as it's own object, but instead
|
// Extensions should not exist as it's own object, but instead
|
||||||
|
@ -51,7 +51,7 @@ export class CloudEvent implements CloudEventV1 {
|
||||||
* @param {object} event the event properties
|
* @param {object} event the event properties
|
||||||
* @param {boolean?} strict whether to perform event validation when creating the object - default: true
|
* @param {boolean?} strict whether to perform event validation when creating the object - default: true
|
||||||
*/
|
*/
|
||||||
constructor(event: CloudEventV1 | CloudEventV1Attributes, strict = true) {
|
constructor(event: Partial<CloudEventV1<T>>, strict = true) {
|
||||||
// copy the incoming event so that we can delete properties as we go
|
// copy the incoming event so that we can delete properties as we go
|
||||||
// everything left after we have deleted know properties becomes an extension
|
// everything left after we have deleted know properties becomes an extension
|
||||||
const properties = { ...event };
|
const properties = { ...event };
|
||||||
|
@ -62,10 +62,10 @@ export class CloudEvent implements CloudEventV1 {
|
||||||
this.time = properties.time || new Date().toISOString();
|
this.time = properties.time || new Date().toISOString();
|
||||||
delete properties.time;
|
delete properties.time;
|
||||||
|
|
||||||
this.type = properties.type;
|
this.type = properties.type as string;
|
||||||
delete (properties as any).type;
|
delete (properties as any).type;
|
||||||
|
|
||||||
this.source = properties.source;
|
this.source = properties.source as string;
|
||||||
delete (properties as any).source;
|
delete (properties as any).source;
|
||||||
|
|
||||||
this.specversion = (properties.specversion as Version) || Version.V1;
|
this.specversion = (properties.specversion as Version) || Version.V1;
|
||||||
|
@ -126,13 +126,13 @@ See: https://github.com/cloudevents/spec/blob/v1.0/spec.md#type-system`);
|
||||||
Object.freeze(this);
|
Object.freeze(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
get data(): unknown {
|
get data(): T | undefined {
|
||||||
return this.#_data;
|
return this.#_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
set data(value: unknown) {
|
set data(value: T | undefined) {
|
||||||
if (isBinary(value)) {
|
if (isBinary(value)) {
|
||||||
this.data_base64 = asBase64(value as Uint32Array);
|
this.data_base64 = asBase64(value);
|
||||||
}
|
}
|
||||||
this.#_data = value;
|
this.#_data = value;
|
||||||
}
|
}
|
||||||
|
@ -184,16 +184,29 @@ See: https://github.com/cloudevents/spec/blob/v1.0/spec.md#type-system`);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clone a CloudEvent with new/update attributes
|
* Clone a CloudEvent with new/update attributes
|
||||||
* @param {object} options attributes to augment the CloudEvent with
|
* @param {object} options attributes to augment the CloudEvent with an `data` property
|
||||||
|
* @param {boolean} strict whether or not to use strict validation when cloning (default: true)
|
||||||
|
* @throws if the CloudEvent does not conform to the schema
|
||||||
|
* @return {CloudEvent} returns a new CloudEvent<T>
|
||||||
|
*/
|
||||||
|
public cloneWith(options: Partial<Exclude<CloudEventV1<never>, "data">>, strict?: boolean): CloudEvent<T>;
|
||||||
|
/**
|
||||||
|
* Clone a CloudEvent with new/update attributes
|
||||||
|
* @param {object} options attributes to augment the CloudEvent with a `data` property
|
||||||
|
* @param {boolean} strict whether or not to use strict validation when cloning (default: true)
|
||||||
|
* @throws if the CloudEvent does not conform to the schema
|
||||||
|
* @return {CloudEvent} returns a new CloudEvent<D>
|
||||||
|
*/
|
||||||
|
public cloneWith<D>(options: Partial<CloudEvent<D>>, strict?: boolean): CloudEvent<D>;
|
||||||
|
/**
|
||||||
|
* Clone a CloudEvent with new/update attributes
|
||||||
|
* @param {object} options attributes to augment the CloudEvent
|
||||||
* @param {boolean} strict whether or not to use strict validation when cloning (default: true)
|
* @param {boolean} strict whether or not to use strict validation when cloning (default: true)
|
||||||
* @throws if the CloudEvent does not conform to the schema
|
* @throws if the CloudEvent does not conform to the schema
|
||||||
* @return {CloudEvent} returns a new CloudEvent
|
* @return {CloudEvent} returns a new CloudEvent
|
||||||
*/
|
*/
|
||||||
public cloneWith(
|
public cloneWith<D>(options: Partial<CloudEventV1<D>>, strict = true): CloudEvent<D | T> {
|
||||||
options: CloudEventV1 | CloudEventV1Attributes | CloudEventV1OptionalAttributes,
|
return new CloudEvent(Object.assign({}, this.toJSON(), options), strict);
|
||||||
strict = true,
|
|
||||||
): CloudEvent {
|
|
||||||
return new CloudEvent(Object.assign({}, this.toJSON(), options) as CloudEvent, strict);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* The object interface for CloudEvents 1.0.
|
* The object interface for CloudEvents 1.0.
|
||||||
* @see https://github.com/cloudevents/spec/blob/v1.0/spec.md
|
* @see https://github.com/cloudevents/spec/blob/v1.0/spec.md
|
||||||
*/
|
*/
|
||||||
export interface CloudEventV1 extends CloudEventV1Attributes {
|
export interface CloudEventV1<T> extends CloudEventV1Attributes<T> {
|
||||||
// REQUIRED Attributes
|
// REQUIRED Attributes
|
||||||
/**
|
/**
|
||||||
* [REQUIRED] Identifies the event. Producers MUST ensure that `source` + `id`
|
* [REQUIRED] Identifies the event. Producers MUST ensure that `source` + `id`
|
||||||
|
@ -30,7 +30,7 @@ export interface CloudEventV1 extends CloudEventV1Attributes {
|
||||||
specversion: string;
|
specversion: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CloudEventV1Attributes extends CloudEventV1OptionalAttributes {
|
export interface CloudEventV1Attributes<T> extends CloudEventV1OptionalAttributes<T> {
|
||||||
/**
|
/**
|
||||||
* [REQUIRED] Identifies the context in which an event happened. Often this
|
* [REQUIRED] Identifies the context in which an event happened. Often this
|
||||||
* will include information such as the type of the event source, the
|
* will include information such as the type of the event source, the
|
||||||
|
@ -65,7 +65,7 @@ export interface CloudEventV1Attributes extends CloudEventV1OptionalAttributes {
|
||||||
type: string;
|
type: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CloudEventV1OptionalAttributes {
|
export interface CloudEventV1OptionalAttributes<T> {
|
||||||
/**
|
/**
|
||||||
* The following fields are optional.
|
* The following fields are optional.
|
||||||
*/
|
*/
|
||||||
|
@ -126,7 +126,7 @@ export interface CloudEventV1OptionalAttributes {
|
||||||
* specified by the datacontenttype attribute (e.g. application/json), and adheres
|
* specified by the datacontenttype attribute (e.g. application/json), and adheres
|
||||||
* to the dataschema format when those respective attributes are present.
|
* to the dataschema format when those respective attributes are present.
|
||||||
*/
|
*/
|
||||||
data?: Record<string, unknown | string | number | boolean> | string | number | boolean | null | unknown;
|
data?: T;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [OPTIONAL] The event payload encoded as base64 data. This is used when the
|
* [OPTIONAL] The event payload encoded as base64 data. This is used when the
|
||||||
|
|
|
@ -21,7 +21,7 @@ ajv.addFormat("js-date-time", function (dateTimeString) {
|
||||||
|
|
||||||
const isValidAgainstSchemaV1 = ajv.compile(schemaV1);
|
const isValidAgainstSchemaV1 = ajv.compile(schemaV1);
|
||||||
|
|
||||||
export function validateCloudEvent(event: CloudEventV1): boolean {
|
export function validateCloudEvent<T>(event: CloudEventV1<T>): boolean {
|
||||||
if (event.specversion === Version.V1) {
|
if (event.specversion === Version.V1) {
|
||||||
if (!isValidAgainstSchemaV1(event)) {
|
if (!isValidAgainstSchemaV1(event)) {
|
||||||
throw new ValidationError("invalid payload", isValidAgainstSchemaV1.errors);
|
throw new ValidationError("invalid payload", isValidAgainstSchemaV1.errors);
|
||||||
|
|
|
@ -35,8 +35,8 @@ export const isDefined = (v: unknown): boolean => v !== null && typeof v !== "un
|
||||||
|
|
||||||
export const isBoolean = (v: unknown): boolean => typeof v === "boolean";
|
export const isBoolean = (v: unknown): boolean => typeof v === "boolean";
|
||||||
export const isInteger = (v: unknown): boolean => Number.isInteger(v as number);
|
export const isInteger = (v: unknown): boolean => Number.isInteger(v as number);
|
||||||
export const isDate = (v: unknown): boolean => v instanceof Date;
|
export const isDate = (v: unknown): v is Date => v instanceof Date;
|
||||||
export const isBinary = (v: unknown): boolean => v instanceof Uint32Array;
|
export const isBinary = (v: unknown): v is Uint32Array => v instanceof Uint32Array;
|
||||||
|
|
||||||
export const isStringOrThrow = (v: unknown, t: Error): boolean =>
|
export const isStringOrThrow = (v: unknown, t: Error): boolean =>
|
||||||
isString(v)
|
isString(v)
|
||||||
|
@ -75,7 +75,7 @@ export const isBuffer = (value: unknown): boolean => value instanceof Buffer;
|
||||||
|
|
||||||
export const asBuffer = (value: string | Buffer | Uint32Array): Buffer =>
|
export const asBuffer = (value: string | Buffer | Uint32Array): Buffer =>
|
||||||
isBinary(value)
|
isBinary(value)
|
||||||
? Buffer.from(value as string)
|
? Buffer.from((value as unknown) as string)
|
||||||
: isBuffer(value)
|
: isBuffer(value)
|
||||||
? (value as Buffer)
|
? (value as Buffer)
|
||||||
: (() => {
|
: (() => {
|
||||||
|
|
|
@ -24,7 +24,7 @@ export const requiredHeaders = [
|
||||||
* @param {CloudEvent} event a CloudEvent
|
* @param {CloudEvent} event a CloudEvent
|
||||||
* @returns {Object} the headers that will be sent for the event
|
* @returns {Object} the headers that will be sent for the event
|
||||||
*/
|
*/
|
||||||
export function headersFor(event: CloudEvent): Headers {
|
export function headersFor<T>(event: CloudEvent<T>): Headers {
|
||||||
const headers: Headers = {};
|
const headers: Headers = {};
|
||||||
let headerMap: Readonly<{ [key: string]: MappedParser }>;
|
let headerMap: Readonly<{ [key: string]: MappedParser }>;
|
||||||
if (event.specversion === Version.V1) {
|
if (event.specversion === Version.V1) {
|
||||||
|
|
|
@ -25,13 +25,13 @@ import { JSONParser, MappedParser, Parser, parserByContentType } from "../../par
|
||||||
* @param {CloudEvent} event The event to serialize
|
* @param {CloudEvent} event The event to serialize
|
||||||
* @returns {Message} a Message object with headers and body
|
* @returns {Message} a Message object with headers and body
|
||||||
*/
|
*/
|
||||||
export function binary(event: CloudEvent): Message {
|
export function binary<T>(event: CloudEvent<T>): Message {
|
||||||
const contentType: Headers = { [CONSTANTS.HEADER_CONTENT_TYPE]: CONSTANTS.DEFAULT_CONTENT_TYPE };
|
const contentType: Headers = { [CONSTANTS.HEADER_CONTENT_TYPE]: CONSTANTS.DEFAULT_CONTENT_TYPE };
|
||||||
const headers: Headers = { ...contentType, ...headersFor(event) };
|
const headers: Headers = { ...contentType, ...headersFor(event) };
|
||||||
let body = event.data;
|
let body = event.data;
|
||||||
if (typeof event.data === "object" && !(event.data instanceof Uint32Array)) {
|
if (typeof event.data === "object" && !(event.data instanceof Uint32Array)) {
|
||||||
// we'll stringify objects, but not binary data
|
// we'll stringify objects, but not binary data
|
||||||
body = JSON.stringify(event.data);
|
body = (JSON.stringify(event.data) as unknown) as T;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
headers,
|
headers,
|
||||||
|
@ -47,7 +47,7 @@ export function binary(event: CloudEvent): Message {
|
||||||
* @param {CloudEvent} event the CloudEvent to be serialized
|
* @param {CloudEvent} event the CloudEvent to be serialized
|
||||||
* @returns {Message} a Message object with headers and body
|
* @returns {Message} a Message object with headers and body
|
||||||
*/
|
*/
|
||||||
export function structured(event: CloudEvent): Message {
|
export function structured<T>(event: CloudEvent<T>): Message {
|
||||||
if (event.data_base64) {
|
if (event.data_base64) {
|
||||||
// The event's data is binary - delete it
|
// The event's data is binary - delete it
|
||||||
event = event.cloneWith({ data: undefined });
|
event = event.cloneWith({ data: undefined });
|
||||||
|
@ -84,7 +84,7 @@ export function isEvent(message: Message): boolean {
|
||||||
* @param {Message} message the incoming message
|
* @param {Message} message the incoming message
|
||||||
* @return {CloudEvent} A new {CloudEvent} instance
|
* @return {CloudEvent} A new {CloudEvent} instance
|
||||||
*/
|
*/
|
||||||
export function deserialize(message: Message): CloudEvent {
|
export function deserialize<T>(message: Message): CloudEvent<T> {
|
||||||
const cleanHeaders: Headers = sanitize(message.headers);
|
const cleanHeaders: Headers = sanitize(message.headers);
|
||||||
const mode: Mode = getMode(cleanHeaders);
|
const mode: Mode = getMode(cleanHeaders);
|
||||||
const version = getVersion(mode, cleanHeaders, message.body);
|
const version = getVersion(mode, cleanHeaders, message.body);
|
||||||
|
@ -133,7 +133,11 @@ function getVersion(mode: Mode, headers: Headers, body: string | Record<string,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// structured mode - the version is in the body
|
// structured mode - the version is in the body
|
||||||
return typeof body === "string" ? JSON.parse(body).specversion : (body as CloudEvent).specversion;
|
if (typeof body === "string") {
|
||||||
|
return JSON.parse(body).specversion;
|
||||||
|
} else {
|
||||||
|
return (body as Record<string, string>).specversion;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Version.V1;
|
return Version.V1;
|
||||||
}
|
}
|
||||||
|
@ -147,7 +151,7 @@ function getVersion(mode: Mode, headers: Headers, body: string | Record<string,
|
||||||
* @returns {CloudEvent} an instance of CloudEvent representing the incoming request
|
* @returns {CloudEvent} an instance of CloudEvent representing the incoming request
|
||||||
* @throws {ValidationError} of the event does not conform to the spec
|
* @throws {ValidationError} of the event does not conform to the spec
|
||||||
*/
|
*/
|
||||||
function parseBinary(message: Message, version: Version): CloudEvent {
|
function parseBinary<T>(message: Message, version: Version): CloudEvent<T> {
|
||||||
const headers = { ...message.headers };
|
const headers = { ...message.headers };
|
||||||
let body = message.body;
|
let body = message.body;
|
||||||
|
|
||||||
|
@ -187,7 +191,7 @@ function parseBinary(message: Message, version: Version): CloudEvent {
|
||||||
delete eventObj.datacontentencoding;
|
delete eventObj.datacontentencoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CloudEvent({ ...eventObj, data: body } as CloudEventV1, false);
|
return new CloudEvent<T>({ ...eventObj, data: body } as CloudEventV1<T>, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -198,7 +202,7 @@ function parseBinary(message: Message, version: Version): CloudEvent {
|
||||||
* @returns {CloudEvent} a new CloudEvent instance for the provided headers and payload
|
* @returns {CloudEvent} a new CloudEvent instance for the provided headers and payload
|
||||||
* @throws {ValidationError} if the payload and header combination do not conform to the spec
|
* @throws {ValidationError} if the payload and header combination do not conform to the spec
|
||||||
*/
|
*/
|
||||||
function parseStructured(message: Message, version: Version): CloudEvent {
|
function parseStructured<T>(message: Message, version: Version): CloudEvent<T> {
|
||||||
const payload = message.body;
|
const payload = message.body;
|
||||||
const headers = message.headers;
|
const headers = message.headers;
|
||||||
|
|
||||||
|
@ -240,5 +244,5 @@ function parseStructured(message: Message, version: Version): CloudEvent {
|
||||||
delete eventObj.data_base64;
|
delete eventObj.data_base64;
|
||||||
delete eventObj.datacontentencoding;
|
delete eventObj.datacontentencoding;
|
||||||
}
|
}
|
||||||
return new CloudEvent(eventObj as CloudEventV1, false);
|
return new CloudEvent<T>(eventObj as CloudEventV1<T>, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ export enum Mode {
|
||||||
* @interface
|
* @interface
|
||||||
*/
|
*/
|
||||||
export interface Serializer {
|
export interface Serializer {
|
||||||
(event: CloudEvent): Message;
|
<T>(event: CloudEvent<T>): Message;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,7 +70,7 @@ export interface Serializer {
|
||||||
* @interface
|
* @interface
|
||||||
*/
|
*/
|
||||||
export interface Deserializer {
|
export interface Deserializer {
|
||||||
(message: Message): CloudEvent;
|
<T>(message: Message): CloudEvent<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -23,7 +23,7 @@ export interface Options {
|
||||||
* @interface
|
* @interface
|
||||||
*/
|
*/
|
||||||
export interface EmitterFunction {
|
export interface EmitterFunction {
|
||||||
(event: CloudEvent, options?: Options): Promise<unknown>;
|
<T>(event: CloudEvent<T>, options?: Options): Promise<unknown>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -56,7 +56,7 @@ export function emitterFor(fn: TransportFunction, options = emitterDefaults): Em
|
||||||
throw new TypeError("A TransportFunction is required");
|
throw new TypeError("A TransportFunction is required");
|
||||||
}
|
}
|
||||||
const { binding, mode }: any = { ...emitterDefaults, ...options };
|
const { binding, mode }: any = { ...emitterDefaults, ...options };
|
||||||
return function emit(event: CloudEvent, opts?: Options): Promise<unknown> {
|
return function emit<T>(event: CloudEvent<T>, opts?: Options): Promise<unknown> {
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
|
@ -109,7 +109,7 @@ export class Emitter {
|
||||||
* @param {boolean} ensureDelivery fail the promise if one listener fails
|
* @param {boolean} ensureDelivery fail the promise if one listener fails
|
||||||
* @return {void}
|
* @return {void}
|
||||||
*/
|
*/
|
||||||
static async emitEvent(event: CloudEvent, ensureDelivery = true): Promise<void> {
|
static async emitEvent<T>(event: CloudEvent<T>, ensureDelivery = true): Promise<void> {
|
||||||
if (!ensureDelivery) {
|
if (!ensureDelivery) {
|
||||||
// Ensure delivery is disabled so we don't wait for Promise
|
// Ensure delivery is disabled so we don't wait for Promise
|
||||||
Emitter.getInstance().emit("cloudevent", event);
|
Emitter.getInstance().emit("cloudevent", event);
|
||||||
|
|
|
@ -8,14 +8,13 @@ import fs from "fs";
|
||||||
|
|
||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
import { CloudEvent, ValidationError, Version } from "../../src";
|
import { CloudEvent, ValidationError, Version } from "../../src";
|
||||||
import { CloudEventV1 } from "../../src/event/interfaces";
|
|
||||||
import { asBase64 } from "../../src/event/validation";
|
import { asBase64 } from "../../src/event/validation";
|
||||||
|
|
||||||
const type = "org.cncf.cloudevents.example";
|
const type = "org.cncf.cloudevents.example";
|
||||||
const source = "http://unit.test";
|
const source = "http://unit.test";
|
||||||
const id = "b46cf653-d48a-4b90-8dfa-355c01061361";
|
const id = "b46cf653-d48a-4b90-8dfa-355c01061361";
|
||||||
|
|
||||||
const fixture: CloudEventV1 = {
|
const fixture = {
|
||||||
id,
|
id,
|
||||||
specversion: Version.V1,
|
specversion: Version.V1,
|
||||||
source,
|
source,
|
||||||
|
@ -34,17 +33,17 @@ describe("A CloudEvent", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Can be constructed with loose validation", () => {
|
it("Can be constructed with loose validation", () => {
|
||||||
const ce = new CloudEvent({} as CloudEventV1, false);
|
const ce = new CloudEvent({}, false);
|
||||||
expect(ce).to.be.instanceOf(CloudEvent);
|
expect(ce).to.be.instanceOf(CloudEvent);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Loosely validated events can be cloned", () => {
|
it("Loosely validated events can be cloned", () => {
|
||||||
const ce = new CloudEvent({} as CloudEventV1, false);
|
const ce = new CloudEvent({}, false);
|
||||||
expect(ce.cloneWith({}, false)).to.be.instanceOf(CloudEvent);
|
expect(ce.cloneWith({}, false)).to.be.instanceOf(CloudEvent);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Loosely validated events throw when validated", () => {
|
it("Loosely validated events throw when validated", () => {
|
||||||
const ce = new CloudEvent({} as CloudEventV1, false);
|
const ce = new CloudEvent({}, false);
|
||||||
expect(ce.validate).to.throw(ValidationError, "invalid payload");
|
expect(ce.validate).to.throw(ValidationError, "invalid payload");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -105,7 +105,7 @@ describe("HTTP transport", () => {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
expect(HTTP.isEvent(message)).to.be.true;
|
expect(HTTP.isEvent(message)).to.be.true;
|
||||||
const event: CloudEvent = HTTP.toEvent(message);
|
const event = HTTP.toEvent(message);
|
||||||
expect(event.LUNCH).to.equal("tacos");
|
expect(event.LUNCH).to.equal("tacos");
|
||||||
expect(function () {
|
expect(function () {
|
||||||
event.validate();
|
event.validate();
|
||||||
|
@ -124,7 +124,7 @@ describe("HTTP transport", () => {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
expect(HTTP.isEvent(message)).to.be.true;
|
expect(HTTP.isEvent(message)).to.be.true;
|
||||||
const event: CloudEvent = HTTP.toEvent(message);
|
const event = HTTP.toEvent(message);
|
||||||
expect(event.specversion).to.equal("11.8");
|
expect(event.specversion).to.equal("11.8");
|
||||||
expect(event.validate()).to.be.false;
|
expect(event.validate()).to.be.false;
|
||||||
});
|
});
|
||||||
|
@ -195,7 +195,7 @@ describe("HTTP transport", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Specification version V1", () => {
|
describe("Specification version V1", () => {
|
||||||
const fixture: CloudEvent = new CloudEvent({
|
const fixture = new CloudEvent({
|
||||||
specversion: Version.V1,
|
specversion: Version.V1,
|
||||||
id,
|
id,
|
||||||
type,
|
type,
|
||||||
|
@ -298,7 +298,7 @@ describe("HTTP transport", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Specification version V03", () => {
|
describe("Specification version V03", () => {
|
||||||
const fixture: CloudEvent = new CloudEvent({
|
const fixture = new CloudEvent({
|
||||||
specversion: Version.V03,
|
specversion: Version.V03,
|
||||||
id,
|
id,
|
||||||
type,
|
type,
|
||||||
|
|
|
@ -164,13 +164,13 @@ describe("CloudEvents Spec v1.0", () => {
|
||||||
expect(cloudevent.data).to.deep.equal(data);
|
expect(cloudevent.data).to.deep.equal(data);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should maintain the type of data when no data content type", () => {
|
it("should maintain the type of data when no datacontenttype is provided", () => {
|
||||||
const dct = cloudevent.datacontenttype;
|
const ce = new CloudEvent({
|
||||||
cloudevent = cloudevent.cloneWith({ datacontenttype: undefined });
|
source: "/cloudevents/test",
|
||||||
cloudevent.data = JSON.stringify(data);
|
type: "cloudevents.test",
|
||||||
|
data: JSON.stringify(data),
|
||||||
expect(typeof cloudevent.data).to.equal("string");
|
});
|
||||||
cloudevent = cloudevent.cloneWith({ datacontenttype: dct });
|
expect(typeof ce.data).to.equal("string");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be ok when type is 'Uint32Array' for 'Binary'", () => {
|
it("should be ok when type is 'Uint32Array' for 'Binary'", () => {
|
||||||
|
@ -179,9 +179,8 @@ describe("CloudEvents Spec v1.0", () => {
|
||||||
const dataBinary = Uint32Array.from(dataString, (c) => c.codePointAt(0) as number);
|
const dataBinary = Uint32Array.from(dataString, (c) => c.codePointAt(0) as number);
|
||||||
const expected = asBase64(dataBinary);
|
const expected = asBase64(dataBinary);
|
||||||
|
|
||||||
cloudevent = cloudevent.cloneWith({ datacontenttype: "text/plain", data: dataBinary });
|
const ce = cloudevent.cloneWith({ datacontenttype: "text/plain", data: dataBinary });
|
||||||
|
expect(ce.data_base64).to.equal(expected);
|
||||||
expect(cloudevent.data_base64).to.equal(expected);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue