diff --git a/CHANGELOG.md b/CHANGELOG.md index 04f9c23f..ba476c23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +## [Unreleased] + +## [0.3.2] + +### Fixed + +- Fix the special `data` handling: issue +[#33](https://github.com/cloudevents/sdk-javascript/issues/33) + ## [0.3.1] ### Fixed @@ -11,3 +20,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - Axios version to `0.18.1` due the CVE-2019-10742 - Fix the `subject` attribute unmarshal error: issue [#32](https://github.com/cloudevents/sdk-javascript/issues/32) + +[Unreleased]: https://github.com/cloudevents/sdk-javascript/compare/v0.3.2...HEAD +[0.3.2]: https://github.com/cloudevents/sdk-javascript/compare/v0.3.1...v0.3.2 +[0.3.1]: https://github.com/cloudevents/sdk-javascript/compare/v0.3.0...v0.3.1 diff --git a/README.md b/README.md index a5450cd0..a481a2d9 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,10 @@ Official CloudEvents' SDK for JavaScript. CloudEvents logo -__Checkout the [changelog](./CHANGELOG.md) to see what's going on!__ +**NOTE: This SDK is still considered work in progress, things might (and will) +break with every update.** + +**Checkout the [changelog](./CHANGELOG.md) to see what's going on!** ## Contributing @@ -65,7 +68,8 @@ let ce = ### Before Spec reaches 1.0 -- `0.x.p`: where `x` relates to spec version and `p` relates to fixes and releases. +- `0.x.p`: where `x` relates to spec version and `p` relates to fixes, releases +and breaking changes ### After Spec reaches 1.0 diff --git a/lib/specs/spec_0_3.js b/lib/specs/spec_0_3.js index 5dade5d0..34a27ea6 100644 --- a/lib/specs/spec_0_3.js +++ b/lib/specs/spec_0_3.js @@ -5,7 +5,8 @@ const Ajv = require("ajv"); const { equalsOrThrow, isBase64, - clone + clone, + asData } = require("../utils/fun.js"); const RESERVED_ATTRIBUTES = { @@ -209,6 +210,13 @@ Spec03.prototype.data = function(_data){ return this; }; Spec03.prototype.getData = function() { + let dct = this.payload["datacontenttype"]; + let dce = this.payload["datacontentencoding"]; + + if(dct && !dce){ + this.payload["data"] = asData(this.payload["data"], dct); + } + return this.payload["data"]; }; diff --git a/lib/utils/fun.js b/lib/utils/fun.js index e7599dbb..dfba22aa 100644 --- a/lib/utils/fun.js +++ b/lib/utils/fun.js @@ -31,6 +31,16 @@ const isBase64 = (value) => const clone = (o) => JSON.parse(JSON.stringify(o)); +const isJsonContentType = (contentType) => + contentType && contentType.match(/(json)/i); + +const asData = (data, contentType) => + ((typeof data) !== "string" + ? data + : isJsonContentType(contentType) + ? JSON.parse(data) + : data); + module.exports = { isString, isStringOrThrow, @@ -42,5 +52,7 @@ module.exports = { equalsOrThrow, isBase64, - clone + clone, + + asData }; diff --git a/package.json b/package.json index 8e1103bf..d2c90648 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloudevents-sdk", - "version": "0.3.1", + "version": "0.3.2", "description": "CloudEvents SDK for JavaScript", "main": "index.js", "scripts": { diff --git a/test/bindings/http/receiver_strutured_0_3_test.js b/test/bindings/http/receiver_strutured_0_3_test.js index a6caf7c3..0c23f1ee 100644 --- a/test/bindings/http/receiver_strutured_0_3_test.js +++ b/test/bindings/http/receiver_strutured_0_3_test.js @@ -206,5 +206,27 @@ describe("HTTP Transport Binding Structured Receiver for CloudEvents v0.3", () = expect(actualExtensions["extension1"]) .to.equal(extension1); }); + + it("Should parse 'data' stringfied json to json object", () => { + // setup + var payload = v03.event() + .type(type) + .source(source) + .contenttype(ceContentType) + .time(now) + .schemaurl(schemaurl) + .data(JSON.stringify(data)) + .toString(); + + var headers = { + "content-type":"application/cloudevents+json" + }; + + // act + var actual = receiver.parse(payload, headers); + + // assert + expect(actual.getData()).to.deep.equal(data); + }); }); }); diff --git a/test/bindings/http/unmarshaller_0_3_tests.js b/test/bindings/http/unmarshaller_0_3_tests.js index 93044515..08950d0a 100644 --- a/test/bindings/http/unmarshaller_0_3_tests.js +++ b/test/bindings/http/unmarshaller_0_3_tests.js @@ -141,6 +141,37 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.3", () => { }); }); + + it("Should parse 'data' stringfied json to json object", () => { + // setup + var payload = + new Cloudevent(v03.Spec) + .type(type) + .source(source) + .dataContentType(ceContentType) + .time(now) + .schemaurl(schemaurl) + .subject(subject) + .data(JSON.stringify(data)) + .toString(); + + var headers = { + "content-type":"application/cloudevents+json" + }; + + var un = new Unmarshaller(); + + // act and assert + return un.unmarshall(payload, headers) + .then(actual => { + expect(actual.getData()).to.deep.equal(data) + }) + .catch((err) => { + console.log(err); + throw err; + }); + + }); }); describe("Binary", () => { diff --git a/test/fun_tests.js b/test/fun_tests.js index d3700f0a..8f66cad6 100644 --- a/test/fun_tests.js +++ b/test/fun_tests.js @@ -43,4 +43,67 @@ describe("Functional approach", () => { expect(actual).to.equal(true); }); }); + + describe("asData" , () => { + it("should throw error when data is not a valid json", () => { + let data = "not a json"; + + expect(fun.asData.bind(fun, data, "application/json")) + .to + .throws(); + }); + + it("should parse string content type as string", () => { + let expected = "a string"; + + let actual = fun.asData(expected, "text/plain"); + + expect((typeof actual)).to.equal("string"); + expect(actual).to.equal(expected); + }); + + it("should parse 'application/json' as json object", () => { + let expected = { + much: "wow", + myext : { + ext : "x04" + } + }; + + let actual = fun.asData(JSON.stringify(expected), "application/json"); + + expect((typeof actual)).to.equal("object"); + expect(actual).to.deep.equal(expected); + }); + + it("should parse 'application/cloudevents+json' as json object", () => { + let expected = { + much: "wow", + myext : { + ext : "x04" + } + }; + + let actual = fun.asData(JSON.stringify(expected), + "application/cloudevents+json"); + + expect((typeof actual)).to.equal("object"); + expect(actual).to.deep.equal(expected); + }); + + it("should parse 'text/json' as json object", () => { + let expected = { + much: "wow", + myext : { + ext : "x04" + } + }; + + let actual = fun.asData(JSON.stringify(expected), + "text/json"); + + expect((typeof actual)).to.equal("object"); + expect(actual).to.deep.equal(expected); + }); + }); }); diff --git a/test/spec_0_3_tests.js b/test/spec_0_3_tests.js index de7dd837..a4770953 100644 --- a/test/spec_0_3_tests.js +++ b/test/spec_0_3_tests.js @@ -201,6 +201,24 @@ describe("CloudEvents Spec v0.3", () => { }); }); + describe("'data'", () => { + it("should maintain the type of data when no data content type", () =>{ + delete cloudevent.spec.payload.datacontenttype; + cloudevent + .data(JSON.stringify(data)); + + expect(typeof cloudevent.getData()).to.equal("string"); + cloudevent.dataContentType(dataContentType); + }); + + it("should convert data with stringified json to a json object", () => { + cloudevent + .dataContentType(dataContentType) + .data(JSON.stringify(data)); + expect(cloudevent.getData()).to.deep.equal(data); + }); + }); + describe("'subject'", () => { it("should throw an error when is an empty string", () => { cloudevent.subject("");