Compare commits
No commits in common. "main" and "v6.0.0" have entirely different histories.
|
@ -8,10 +8,10 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v2
|
||||||
-
|
-
|
||||||
name: Generate API documentation
|
name: Generate API documentation
|
||||||
run: npm install && npm run build:schema && npm run generate-docs
|
run: npm install && npm run generate-docs
|
||||||
-
|
-
|
||||||
name: Deploy to GitHub Pages
|
name: Deploy to GitHub Pages
|
||||||
if: success()
|
if: success()
|
||||||
|
|
|
@ -15,12 +15,12 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [20.x, 22.x, 24.x]
|
node-version: [12.x, 14.x, 16.x]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- name: Test on Node.js ${{ matrix.node-version }}
|
- name: Test on Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
|
@ -31,18 +31,18 @@ jobs:
|
||||||
name: Code coverage
|
name: Code coverage
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Generate coverage report
|
- name: Generate coverage report
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
node-version: 22.x
|
node-version: 16.x
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
- run: npm run build --if-present
|
- run: npm run build --if-present
|
||||||
- run: npm run coverage
|
- run: npm run coverage
|
||||||
- name: Upload coverage report to storage
|
- name: Upload coverage report to storage
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v1
|
||||||
with:
|
with:
|
||||||
name: coverage
|
name: coverage
|
||||||
path: coverage/lcov.info
|
path: coverage/lcov.info
|
||||||
|
@ -52,15 +52,15 @@ jobs:
|
||||||
needs: coverage
|
needs: coverage
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- name: Download coverage report from storage
|
- name: Download coverage report from storage
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v1
|
||||||
with:
|
with:
|
||||||
name: coverage
|
name: coverage
|
||||||
- name: Upload coverage report to codacy
|
- name: Upload coverage report to codacy
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
node-version: 22.x
|
node-version: 16.x
|
||||||
- run: |
|
- run: |
|
||||||
( [[ "${CODACY_PROJECT_TOKEN}" != "" ]] && npm run coverage-publish ) || echo "Coverage report not published"
|
( [[ "${CODACY_PROJECT_TOKEN}" != "" ]] && npm run coverage-publish ) || echo "Coverage report not published"
|
||||||
env:
|
env:
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
name: Publish to npmjs
|
|
||||||
on:
|
|
||||||
release:
|
|
||||||
types: [created]
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
id-token: write
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: '22.x'
|
|
||||||
registry-url: 'https://registry.npmjs.org'
|
|
||||||
- run: npm install -g npm
|
|
||||||
- run: npm ci
|
|
||||||
- run: npm publish --provenance --access public
|
|
||||||
env:
|
|
||||||
NODE_AUTH_TOKEN: ${{ secrets.CLOUDEVENTS_PUBLISH }}
|
|
|
@ -7,11 +7,9 @@ jobs:
|
||||||
release-please:
|
release-please:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: GoogleCloudPlatform/release-please-action@v3
|
- uses: GoogleCloudPlatform/release-please-action@v2.5.5
|
||||||
id: release
|
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.CLOUDEVENTS_RELEASES_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
release-type: node
|
release-type: node
|
||||||
package-name: cloudevents
|
package-name: cloudevents
|
||||||
signoff: "Lucas Holmquist <lholmqui@redhat.com>"
|
|
||||||
changelog-types: '[{"type":"feat","section":"Features","hidden":false},{"type":"fix","section":"Bug Fixes","hidden":false},{"type":"docs","section":"Documentation","hidden":false},{"type":"chore","section":"Miscellaneous","hidden":false},{"type":"src","section":"Miscellaneous","hidden":false},{"type":"style","section":"Miscellaneous","hidden":false},{"type":"refactor","section":"Miscellaneous","hidden":false},{"type":"perf","section":"Performance","hidden":false},{"type":"test","section":"Tests","hidden":false}]'
|
changelog-types: '[{"type":"feat","section":"Features","hidden":false},{"type":"fix","section":"Bug Fixes","hidden":false},{"type":"docs","section":"Documentation","hidden":false},{"type":"chore","section":"Miscellaneous","hidden":false},{"type":"src","section":"Miscellaneous","hidden":false},{"type":"style","section":"Miscellaneous","hidden":false},{"type":"refactor","section":"Miscellaneous","hidden":false},{"type":"perf","section":"Performance","hidden":false},{"type":"test","section":"Tests","hidden":false}]'
|
||||||
|
|
|
@ -91,6 +91,3 @@ typings/
|
||||||
|
|
||||||
# Package lock
|
# Package lock
|
||||||
package-lock.json
|
package-lock.json
|
||||||
|
|
||||||
# Jetbrains IDE directories
|
|
||||||
.idea
|
|
||||||
|
|
154
CHANGELOG.md
154
CHANGELOG.md
|
@ -2,160 +2,6 @@
|
||||||
|
|
||||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||||
|
|
||||||
## [9.0.0](https://github.com/cloudevents/sdk-javascript/compare/v8.0.3...v9.0.0) (2025-04-03)
|
|
||||||
|
|
||||||
|
|
||||||
### ⚠ BREAKING CHANGES
|
|
||||||
|
|
||||||
* remove node 16 ([#610](https://github.com/cloudevents/sdk-javascript/issues/610))
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* remove node 16 ([#610](https://github.com/cloudevents/sdk-javascript/issues/610)) ([3ff6fdd](https://github.com/cloudevents/sdk-javascript/commit/3ff6fdd3bf1a9d77be9cd1d1ed589de47a86f7c1))
|
|
||||||
|
|
||||||
## [8.0.3](https://github.com/cloudevents/sdk-javascript/compare/v8.0.2...v8.0.3) (2025-04-02)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* add generics to `Binding` type ([#604](https://github.com/cloudevents/sdk-javascript/issues/604)) ([f475cdf](https://github.com/cloudevents/sdk-javascript/commit/f475cdfd7ee7e80a375b997ba2f41b1655a44a03))
|
|
||||||
|
|
||||||
## [8.0.2](https://github.com/cloudevents/sdk-javascript/compare/v8.0.1...v8.0.2) (2024-07-22)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* creating an event does not error when the event attribute name is too long ([#593](https://github.com/cloudevents/sdk-javascript/issues/593)) ([6977113](https://github.com/cloudevents/sdk-javascript/commit/6977113d7b49bd2b702632cc09e29cc0c003e2a1))
|
|
||||||
|
|
||||||
## [8.0.1](https://github.com/cloudevents/sdk-javascript/compare/v8.0.0...v8.0.1) (2024-06-12)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* allow Node 22 and use it by default ([#587](https://github.com/cloudevents/sdk-javascript/issues/587)) ([e762607](https://github.com/cloudevents/sdk-javascript/commit/e7626077ed22b2bcbfa71b0403a58ac187c57cba))
|
|
||||||
|
|
||||||
|
|
||||||
### Miscellaneous
|
|
||||||
|
|
||||||
* Update compatible node version ([#573](https://github.com/cloudevents/sdk-javascript/issues/573)) ([245bae9](https://github.com/cloudevents/sdk-javascript/commit/245bae92d1c84b4a44fe7aae2f82c5a90818f1c5))
|
|
||||||
* updated check mark symbol to show some green checkboxes ([#582](https://github.com/cloudevents/sdk-javascript/issues/582)) ([c65afe9](https://github.com/cloudevents/sdk-javascript/commit/c65afe94d2320eae9b8b74de9b1e1bd8793baa6a))
|
|
||||||
|
|
||||||
## [8.0.0](https://github.com/cloudevents/sdk-javascript/compare/v7.0.2...v8.0.0) (2023-07-24)
|
|
||||||
|
|
||||||
### ⚠ BREAKING CHANGES
|
|
||||||
|
|
||||||
* use string instead of enum for Version ([#561](https://github.com/cloudevents/sdk-javascript/issues/561)) ([15f6505](https://github.com/cloudevents/sdk-javascript/commit/15f6505a580b2bbf8d6b2e89feea10cbd40ab827))
|
|
||||||
TypeScript does not consider enum values equivalent, even if the string
|
|
||||||
representation is the same. So, when a module imports `cloudevents` and
|
|
||||||
also has a dependency on `cloudevents` this can cause conflicts where
|
|
||||||
the `CloudEvent.version` attribute is not considered equal when, in
|
|
||||||
fact, it is.
|
|
||||||
|
|
||||||
### Miscellaneous
|
|
||||||
|
|
||||||
* add `npm run build:schema` to the doc generation action ([#557](https://github.com/cloudevents/sdk-javascript/issues/557)) ([fa388f7](https://github.com/cloudevents/sdk-javascript/commit/fa388f7dc65c1739864d7a885d6d28111ce07775))
|
|
||||||
* modify release-please to use Signed-Off-By on commits ([#559](https://github.com/cloudevents/sdk-javascript/issues/559)) ([089520a](https://github.com/cloudevents/sdk-javascript/commit/089520a4cc8304e39ac9bfccf0ed59c76ea8c11a))
|
|
||||||
* release 8.0.0 ([#563](https://github.com/cloudevents/sdk-javascript/issues/563)) ([1ed43c8](https://github.com/cloudevents/sdk-javascript/commit/1ed43c84868ccfd18531deaf6cc9d4e4fcb21a08))
|
|
||||||
|
|
||||||
## [7.0.2](https://github.com/cloudevents/sdk-javascript/compare/v7.0.1...v7.0.2) (2023-07-05)
|
|
||||||
|
|
||||||
|
|
||||||
### Miscellaneous
|
|
||||||
|
|
||||||
* add the provenance flag when publishing to npm ([#556](https://github.com/cloudevents/sdk-javascript/issues/556)) ([a0d8682](https://github.com/cloudevents/sdk-javascript/commit/a0d86826138be31072c9a30edf26f4b91da576ed))
|
|
||||||
* fix the release-please automation script. ([#554](https://github.com/cloudevents/sdk-javascript/issues/554)) ([023171d](https://github.com/cloudevents/sdk-javascript/commit/023171d9a08484c32e24f8228602ef4d5173c749))
|
|
||||||
|
|
||||||
## [7.0.1](https://github.com/cloudevents/sdk-javascript/compare/v7.0.0...v7.0.1) (2023-05-30)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* handle big integers in incoming events ([#495](https://github.com/cloudevents/sdk-javascript/issues/495)) ([43c3584](https://github.com/cloudevents/sdk-javascript/commit/43c3584b984aa170b1c1c4dff7218d027cd28d02))
|
|
||||||
|
|
||||||
|
|
||||||
### Miscellaneous
|
|
||||||
|
|
||||||
* add publish automation ([#550](https://github.com/cloudevents/sdk-javascript/issues/550)) ([3931b22](https://github.com/cloudevents/sdk-javascript/commit/3931b224cb3140ad3ba759edcf564621a2e34542))
|
|
||||||
* remove old Node versions from the readme ([#549](https://github.com/cloudevents/sdk-javascript/issues/549)) ([11442d3](https://github.com/cloudevents/sdk-javascript/commit/11442d32d307a0e8416ed573ce34fc825d3b63c4))
|
|
||||||
* Update compatible node version ([#552](https://github.com/cloudevents/sdk-javascript/issues/552)) ([f3659eb](https://github.com/cloudevents/sdk-javascript/commit/f3659ebfc6251b4c57997f70709688916a061a2d))
|
|
||||||
|
|
||||||
## [7.0.0](https://github.com/cloudevents/sdk-javascript/compare/v6.0.4...v7.0.0) (2023-05-03)
|
|
||||||
|
|
||||||
|
|
||||||
### ⚠ BREAKING CHANGES
|
|
||||||
|
|
||||||
* remove node 12 and node 14 ([#545](https://github.com/cloudevents/sdk-javascript/issues/545))
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* remove node 12 and node 14 ([#545](https://github.com/cloudevents/sdk-javascript/issues/545)) ([2cb9364](https://github.com/cloudevents/sdk-javascript/commit/2cb9364a25a5e82f2a68504dbe19839a7fbfd9d4))
|
|
||||||
|
|
||||||
|
|
||||||
### Miscellaneous
|
|
||||||
|
|
||||||
* add the build script to the pretest script. ([#539](https://github.com/cloudevents/sdk-javascript/issues/539)) ([c06ffc1](https://github.com/cloudevents/sdk-javascript/commit/c06ffc196389fedd7d5141d69fac3f4d95156193))
|
|
||||||
* fix release-please-action ([#543](https://github.com/cloudevents/sdk-javascript/issues/543)) ([ec83abc](https://github.com/cloudevents/sdk-javascript/commit/ec83abc82799159aa1f64c791c92e035ef6f42b8))
|
|
||||||
* release 6.0.5 ([#542](https://github.com/cloudevents/sdk-javascript/issues/542)) ([343382e](https://github.com/cloudevents/sdk-javascript/commit/343382ebdedc9a2efbc5b3ba5cd36e4e069fd38f))
|
|
||||||
* release 7.0.0 ([#546](https://github.com/cloudevents/sdk-javascript/issues/546)) ([0120d22](https://github.com/cloudevents/sdk-javascript/commit/0120d224ab67e804e201625e0a9d59947a5a212d))
|
|
||||||
* Update CI action to node 18.x ([#533](https://github.com/cloudevents/sdk-javascript/issues/533)) ([7ff64f8](https://github.com/cloudevents/sdk-javascript/commit/7ff64f8b82e1c5a824bbe985df4948d79e919e8c))
|
|
||||||
|
|
||||||
### [6.0.3](https://www.github.com/cloudevents/sdk-javascript/compare/v6.0.2...v6.0.3) (2023-02-16)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* improve validation on extension attribute ([#502](https://www.github.com/cloudevents/sdk-javascript/issues/502)) ([ea94a4d](https://www.github.com/cloudevents/sdk-javascript/commit/ea94a4d779d0744ef40abc81d08ab8b7e93e9133))
|
|
||||||
* Make CloudEvent data field immutable and enumerable using Object.keys() ([#515](https://www.github.com/cloudevents/sdk-javascript/issues/515)) ([#516](https://www.github.com/cloudevents/sdk-javascript/issues/516)) ([2d5fab1](https://www.github.com/cloudevents/sdk-javascript/commit/2d5fab1b7133241493bb9327aa26e7de4117616d))
|
|
||||||
* This fixes bug [#525](https://www.github.com/cloudevents/sdk-javascript/issues/525) where the browser version was breaking becuase of process not being found. ([#526](https://www.github.com/cloudevents/sdk-javascript/issues/526)) ([e5ee836](https://www.github.com/cloudevents/sdk-javascript/commit/e5ee8369ba5838aa24c2d99efeb81788757b71d1))
|
|
||||||
|
|
||||||
|
|
||||||
### Miscellaneous
|
|
||||||
|
|
||||||
* added the engines property to the package.json ([bc3aaca](https://www.github.com/cloudevents/sdk-javascript/commit/bc3aaca2ef250e4acd72b909488b326233237c83))
|
|
||||||
* bump cucumber to full release version ([#514](https://www.github.com/cloudevents/sdk-javascript/issues/514)) ([c09a9cc](https://www.github.com/cloudevents/sdk-javascript/commit/c09a9cc20a601ddc36c5c1b56fb52dc9c2161e1b))
|
|
||||||
* bump mocha to 10.1.0 ([#512](https://www.github.com/cloudevents/sdk-javascript/issues/512)) ([4831e6a](https://www.github.com/cloudevents/sdk-javascript/commit/4831e6a1a5003c4c1c7bcbd5a3a2fc5c48e0ba4c))
|
|
||||||
* bump webpack to 5.74.0 ([#509](https://www.github.com/cloudevents/sdk-javascript/issues/509)) ([760a024](https://www.github.com/cloudevents/sdk-javascript/commit/760a0240674c79ca6be142ae9f9b242080c4d59d))
|
|
||||||
* release 6.0.3 ([#503](https://www.github.com/cloudevents/sdk-javascript/issues/503)) ([3619ef2](https://www.github.com/cloudevents/sdk-javascript/commit/3619ef2bbd6e2b3e9e6e5bb5ad904689d40f4b79))
|
|
||||||
* Typos ([953bc2a](https://www.github.com/cloudevents/sdk-javascript/commit/953bc2a143a66d04d850c727305a5a465e843bff))
|
|
||||||
* **examples:** add mqtt example ([#523](https://www.github.com/cloudevents/sdk-javascript/issues/523)) ([b374d9a](https://www.github.com/cloudevents/sdk-javascript/commit/b374d9ac3313023e4f8a59cb22785751bbb0f686))
|
|
||||||
|
|
||||||
### [6.0.3](https://www.github.com/cloudevents/sdk-javascript/compare/v6.0.2...v6.0.3) (2022-11-01)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* improve validation on extension attribute ([#502](https://www.github.com/cloudevents/sdk-javascript/issues/502)) ([ea94a4d](https://www.github.com/cloudevents/sdk-javascript/commit/ea94a4d779d0744ef40abc81d08ab8b7e93e9133))
|
|
||||||
* Make CloudEvent data field immutable and enumerable using Object.keys() ([#515](https://www.github.com/cloudevents/sdk-javascript/issues/515)) ([#516](https://www.github.com/cloudevents/sdk-javascript/issues/516)) ([2d5fab1](https://www.github.com/cloudevents/sdk-javascript/commit/2d5fab1b7133241493bb9327aa26e7de4117616d))
|
|
||||||
|
|
||||||
|
|
||||||
### Miscellaneous
|
|
||||||
|
|
||||||
* bump cucumber to full release version ([#514](https://www.github.com/cloudevents/sdk-javascript/issues/514)) ([c09a9cc](https://www.github.com/cloudevents/sdk-javascript/commit/c09a9cc20a601ddc36c5c1b56fb52dc9c2161e1b))
|
|
||||||
* bump mocha to 10.1.0 ([#512](https://www.github.com/cloudevents/sdk-javascript/issues/512)) ([4831e6a](https://www.github.com/cloudevents/sdk-javascript/commit/4831e6a1a5003c4c1c7bcbd5a3a2fc5c48e0ba4c))
|
|
||||||
* bump webpack to 5.74.0 ([#509](https://www.github.com/cloudevents/sdk-javascript/issues/509)) ([760a024](https://www.github.com/cloudevents/sdk-javascript/commit/760a0240674c79ca6be142ae9f9b242080c4d59d))
|
|
||||||
|
|
||||||
### [6.0.2](https://www.github.com/cloudevents/sdk-javascript/compare/v6.0.1...v6.0.2) (2022-06-21)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* allow `TypedArray` for binary data ([#494](https://www.github.com/cloudevents/sdk-javascript/issues/494)) ([921e273](https://www.github.com/cloudevents/sdk-javascript/commit/921e273ede100ab9a262fdfa1f3d6561d3fab0f9))
|
|
||||||
* HTTP headers for extensions with false values ([#493](https://www.github.com/cloudevents/sdk-javascript/issues/493)) ([d6f52ca](https://www.github.com/cloudevents/sdk-javascript/commit/d6f52ca65f893fdb581bf06b2ff97b3d6eeeb744))
|
|
||||||
* package.json & package-lock.json to reduce vulnerabilities ([ed63f14](https://www.github.com/cloudevents/sdk-javascript/commit/ed63f14339fb7774bff865726370fe72a49abca3))
|
|
||||||
|
|
||||||
|
|
||||||
### Miscellaneous
|
|
||||||
|
|
||||||
* bump ajv and remove old dep dependency ([#496](https://www.github.com/cloudevents/sdk-javascript/issues/496)) ([ce02e0a](https://www.github.com/cloudevents/sdk-javascript/commit/ce02e0a1f3b24624bd8ba443c744b4a6c0cfcb44))
|
|
||||||
* update owners ([#499](https://www.github.com/cloudevents/sdk-javascript/issues/499)) ([a62eb44](https://www.github.com/cloudevents/sdk-javascript/commit/a62eb4466985972cd3112e6f8e3e0b62cb01c1c1))
|
|
||||||
|
|
||||||
### [6.0.1](https://www.github.com/cloudevents/sdk-javascript/compare/v6.0.0...v6.0.1) (2022-03-21)
|
|
||||||
|
|
||||||
|
|
||||||
### Miscellaneous
|
|
||||||
|
|
||||||
* update dependencies to inlude ajv-formats ([#484](https://www.github.com/cloudevents/sdk-javascript/issues/484)) ([c0b1f77](https://www.github.com/cloudevents/sdk-javascript/commit/c0b1f7705a448dda3e6292d872a5bf435d26fab4)), closes [/github.com/cloudevents/sdk-javascript/pull/471/files#diff-7ae45ad102eab3b6d7e7896acd08c427a9b25b346470d7bc6507b6481575d519R128](https://www.github.com/cloudevents//github.com/cloudevents/sdk-javascript/pull/471/files/issues/diff-7ae45ad102eab3b6d7e7896acd08c427a9b25b346470d7bc6507b6481575d519R128)
|
|
||||||
|
|
||||||
## [6.0.0](https://www.github.com/cloudevents/sdk-javascript/compare/v5.3.2...v6.0.0) (2022-03-21)
|
## [6.0.0](https://www.github.com/cloudevents/sdk-javascript/compare/v5.3.2...v6.0.0) (2022-03-21)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
# Maintainers
|
|
||||||
|
|
||||||
Current active maintainers of this SDK:
|
|
||||||
|
|
||||||
- [Lance Ball](https://github.com/lance)
|
|
||||||
- [Daniel Bevenius](https://github.com/danbev)
|
|
||||||
- [Lucas Holmquist](https://github.com/lholmquist)
|
|
||||||
- [Fabio Jose](https://github.com/fabiojose)
|
|
||||||
- [Helio Frota](https://github.com/helio-frota)
|
|
58
README.md
58
README.md
|
@ -12,14 +12,14 @@ The CloudEvents SDK for JavaScript.
|
||||||
|
|
||||||
- Represent CloudEvents in memory
|
- Represent CloudEvents in memory
|
||||||
- Serialize and deserialize CloudEvents in different [event formats](https://github.com/cloudevents/spec/blob/v1.0/spec.md#event-format).
|
- Serialize and deserialize CloudEvents in different [event formats](https://github.com/cloudevents/spec/blob/v1.0/spec.md#event-format).
|
||||||
- Send and receive CloudEvents with via different [protocol bindings](https://github.com/cloudevents/spec/blob/v1.0/spec.md#protocol-binding).
|
- Send and recieve CloudEvents with via different [protocol bindings](https://github.com/cloudevents/spec/blob/v1.0/spec.md#protocol-binding).
|
||||||
|
|
||||||
_Note:_ Supports CloudEvent version 1.0
|
_Note:_ Supports CloudEvent version 1.0
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
The CloudEvents SDK requires a current LTS version of Node.js. At the moment
|
The CloudEvents SDK requires a current LTS version of Node.js. At the moment
|
||||||
those are Node.js 16.x, and Node.js 18.x. To install in your Node.js project:
|
those are Node.js 12.x, Node.js 14.x and Node.js 16.x. To install in your Node.js project:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
npm install cloudevents
|
npm install cloudevents
|
||||||
|
@ -51,7 +51,7 @@ The easiest way to send events is to use the built-in HTTP emitter.
|
||||||
```js
|
```js
|
||||||
const { httpTransport, emitterFor, CloudEvent } = require("cloudevents");
|
const { httpTransport, emitterFor, CloudEvent } = require("cloudevents");
|
||||||
|
|
||||||
// Create an emitter to send events to a receiver
|
// Create an emitter to send events to an to a reciever
|
||||||
const emit = emitterFor(httpTransport("https://my.receiver.com/endpoint"));
|
const emit = emitterFor(httpTransport("https://my.receiver.com/endpoint"));
|
||||||
|
|
||||||
// Create a new CloudEvent
|
// Create a new CloudEvent
|
||||||
|
@ -162,20 +162,6 @@ const event3 = new CloudEvent({
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
### A Note About Big Integers
|
|
||||||
|
|
||||||
When parsing JSON data, if a JSON field value is a number, and that number
|
|
||||||
is really big, JavaScript loses precision. For example, the Twitter API exposes
|
|
||||||
the Tweet ID. This is a large number that exceeds the integer space of `Number`.
|
|
||||||
|
|
||||||
In order to address this situation, you can set the environment variable
|
|
||||||
`CE_USE_BIG_INT` to the string value `"true"` to enable the use of the
|
|
||||||
[`json-bigint`](https://www.npmjs.com/package/json-bigint) package. This
|
|
||||||
package is not used by default due to the resulting slowdown in parse speed
|
|
||||||
by a factor of 7x.
|
|
||||||
|
|
||||||
See for more information: https://github.com/cloudevents/sdk-javascript/issues/489
|
|
||||||
|
|
||||||
### Example Applications
|
### Example Applications
|
||||||
|
|
||||||
There are a few trivial example applications in
|
There are a few trivial example applications in
|
||||||
|
@ -191,37 +177,37 @@ There you will find Express.js, TypeScript and Websocket examples.
|
||||||
|
|
||||||
| Core Specification | [v0.3](https://github.com/cloudevents/spec/blob/v0.3/spec.md) | [v1.0](https://github.com/cloudevents/spec/blob/v1.0/spec.md) |
|
| Core Specification | [v0.3](https://github.com/cloudevents/spec/blob/v0.3/spec.md) | [v1.0](https://github.com/cloudevents/spec/blob/v1.0/spec.md) |
|
||||||
| ------------------ | ------------------------------------------------------------- | ------------------------------------------------------------- |
|
| ------------------ | ------------------------------------------------------------- | ------------------------------------------------------------- |
|
||||||
| CloudEvents Core | :white_check_mark: | :white_check_mark: |
|
| CloudEvents Core | :heavy_check_mark: | :heavy_check_mark: |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
| Event Formats | [v0.3](https://github.com/cloudevents/spec/tree/v0.3) | [v1.0](https://github.com/cloudevents/spec/blob/v1.0/spec.md#event-format) |
|
| Event Formats | [v0.3](https://github.com/cloudevents/spec/tree/v0.3) | [v1.0](https://github.com/cloudevents/spec/blob/v1.0/spec.md#event-format) |
|
||||||
| ----------------- | ----------------------------------------------------- | ----------------------------------------------------- |
|
| ----------------- | ----------------------------------------------------- | ----------------------------------------------------- |
|
||||||
| AVRO Event Format | :x: | :x: |
|
| AVRO Event Format | :x: | :x: |
|
||||||
| JSON Event Format | :white_check_mark: | :white_check_mark: |
|
| JSON Event Format | :heavy_check_mark: | :heavy_check_mark: |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
| Protocol Bindings | [v0.3](https://github.com/cloudevents/spec/tree/v0.3) | [v1.0](https://github.com/cloudevents/spec/blob/v1.0/spec.md#protocol-binding) |
|
| Protocol Bindings | [v0.3](https://github.com/cloudevents/spec/tree/v0.3) | [v1.0](https://github.com/cloudevents/spec/blob/v1.0/spec.md#protocol-binding) |
|
||||||
| ---------------------- | ----------------------------------------------------- | ----------------------------------------------------- |
|
| ---------------------- | ----------------------------------------------------- | ----------------------------------------------------- |
|
||||||
| AMQP Protocol Binding | :x: | :x: |
|
| AMQP Protocol Binding | :x: | :x: |
|
||||||
| HTTP Protocol Binding | :white_check_mark: | :white_check_mark: |
|
| HTTP Protocol Binding | :heavy_check_mark: | :heavy_check_mark: |
|
||||||
| Kafka Protocol Binding | :x: | :white_check_mark: |
|
| Kafka Protocol Binding | :x: | :heavy_check_mark: |
|
||||||
| MQTT Protocol Binding | :white_check_mark: | :x: |
|
| MQTT Protocol Binding | :heavy_check_mark: | :x: |
|
||||||
| NATS Protocol Binding | :x: | :x: |
|
| NATS Protocol Binding | :x: | :x: |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
| Content Modes | [v0.3](https://github.com/cloudevents/spec/tree/v0.3) | [v1.0](https://github.com/cloudevents/spec/blob/v1.0/http-protocol-binding.md#13-content-modes) |
|
| Content Modes | [v0.3](https://github.com/cloudevents/spec/tree/v0.3) | [v1.0](https://github.com/cloudevents/spec/blob/v1.0/http-protocol-binding.md#13-content-modes) |
|
||||||
| ---------------------- | ----------------------------------------------------- | ----------------------------------------------------- |
|
| ---------------------- | ----------------------------------------------------- | ----------------------------------------------------- |
|
||||||
| HTTP Binary | :white_check_mark: | :white_check_mark: |
|
| HTTP Binary | :heavy_check_mark: | :heavy_check_mark: |
|
||||||
| HTTP Structured | :white_check_mark: | :white_check_mark: |
|
| HTTP Structured | :heavy_check_mark: | :heavy_check_mark: |
|
||||||
| HTTP Batch | :white_check_mark: | :white_check_mark: |
|
| HTTP Batch | :heavy_check_mark: | :heavy_check_mark: |
|
||||||
| Kafka Binary | :white_check_mark: | :white_check_mark: |
|
| Kafka Binary | :heavy_check_mark: | :heavy_check_mark: |
|
||||||
| Kafka Structured | :white_check_mark: | :white_check_mark: |
|
| Kafka Structured | :heavy_check_mark: | :heavy_check_mark: |
|
||||||
| Kafka Batch | :white_check_mark: | :white_check_mark:
|
| Kafka Batch | :heavy_check_mark: | :heavy_check_mark:
|
||||||
| MQTT Binary | :white_check_mark: | :white_check_mark: |
|
| MQTT Binary | :heavy_check_mark: | :heavy_check_mark: |
|
||||||
| MQTT Structured | :white_check_mark: | :white_check_mark: |
|
| MQTT Structured | :heavy_check_mark: | :heavy_check_mark: |
|
||||||
|
|
||||||
## Community
|
## Community
|
||||||
|
|
||||||
|
@ -241,6 +227,7 @@ Currently active maintainers who may be found in the CNCF Slack.
|
||||||
|
|
||||||
- Lance Ball (@lance)
|
- Lance Ball (@lance)
|
||||||
- Lucas Holmquist (@lholmquist)
|
- Lucas Holmquist (@lholmquist)
|
||||||
|
- Grant Timmerman (@grant)
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
@ -258,14 +245,3 @@ how SDK projects are
|
||||||
for how PR reviews and approval, and our
|
for how PR reviews and approval, and our
|
||||||
[Code of Conduct](https://github.com/cloudevents/spec/blob/master/community/GOVERNANCE.md#additional-information)
|
[Code of Conduct](https://github.com/cloudevents/spec/blob/master/community/GOVERNANCE.md#additional-information)
|
||||||
information.
|
information.
|
||||||
|
|
||||||
If there is a security concern with one of the CloudEvents specifications, or
|
|
||||||
with one of the project's SDKs, please send an email to
|
|
||||||
[cncf-cloudevents-security@lists.cncf.io](mailto:cncf-cloudevents-security@lists.cncf.io).
|
|
||||||
|
|
||||||
## Additional SDK Resources
|
|
||||||
|
|
||||||
- [List of current active maintainers](MAINTAINERS.md)
|
|
||||||
- [How to contribute to the project](CONTRIBUTING.md)
|
|
||||||
- [SDK's License](LICENSE)
|
|
||||||
- [SDK's Release process](RELEASING.md)
|
|
||||||
|
|
|
@ -28,11 +28,11 @@ app.post("/", (req, res) => {
|
||||||
const responseEventMessage = new CloudEvent({
|
const responseEventMessage = new CloudEvent({
|
||||||
source: '/',
|
source: '/',
|
||||||
type: 'event:response',
|
type: 'event:response',
|
||||||
...event,
|
...event
|
||||||
data: {
|
|
||||||
hello: 'world'
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
responseEventMessage.data = {
|
||||||
|
hello: 'world'
|
||||||
|
};
|
||||||
|
|
||||||
// const message = HTTP.binary(responseEventMessage)
|
// const message = HTTP.binary(responseEventMessage)
|
||||||
const message = HTTP.structured(responseEventMessage)
|
const message = HTTP.structured(responseEventMessage)
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
# MQTT Example
|
|
||||||
|
|
||||||
The MQTT message protocol are available since v5.3.0
|
|
||||||
|
|
||||||
## How To Start
|
|
||||||
|
|
||||||
Install and compile:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm install
|
|
||||||
npm run compile
|
|
||||||
```
|
|
||||||
|
|
||||||
Start a MQTT broker using Docker:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker run -it -d -p 1883:1883 eclipse-mosquitto:2.0 mosquitto -c /mosquitto-no-auth.conf
|
|
||||||
```
|
|
||||||
|
|
||||||
Then, start
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm start
|
|
||||||
```
|
|
|
@ -1,35 +0,0 @@
|
||||||
{
|
|
||||||
"name": "mqtt-ex",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "Simple mqtt example using CloudEvents types",
|
|
||||||
"repository": "https://github.com/cloudevents/sdk-javascript.git",
|
|
||||||
"main": "build/src/index.js",
|
|
||||||
"types": "build/src/index.d.ts",
|
|
||||||
"files": [
|
|
||||||
"build/src"
|
|
||||||
],
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"keywords": [],
|
|
||||||
"scripts": {
|
|
||||||
"start": "node build/index.js",
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
|
||||||
"check": "gts check",
|
|
||||||
"clean": "gts clean",
|
|
||||||
"compile": "tsc -p .",
|
|
||||||
"watch": "tsc -p . --watch",
|
|
||||||
"fix": "gts fix",
|
|
||||||
"prepare": "npm run compile",
|
|
||||||
"pretest": "npm run compile",
|
|
||||||
"posttest": "npm run check"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/node": "^14.14.10",
|
|
||||||
"@types/ws": "^8.5.4",
|
|
||||||
"gts": "^3.0.3",
|
|
||||||
"typescript": "~4.1.3"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"cloudevents": "^6.0.3",
|
|
||||||
"mqtt": "^4.3.7"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
/* eslint-disable */
|
|
||||||
import { CloudEvent, MQTT } from "cloudevents";
|
|
||||||
import * as mqtt from "mqtt";
|
|
||||||
|
|
||||||
const client = mqtt.connect("mqtt://localhost:1883");
|
|
||||||
|
|
||||||
client.on("connect", function () {
|
|
||||||
client.subscribe("presence", function (err) {
|
|
||||||
if (err) return;
|
|
||||||
const event = new CloudEvent({
|
|
||||||
source: "presence",
|
|
||||||
type: "presence.event",
|
|
||||||
datacontenttype: "application/json",
|
|
||||||
data: {
|
|
||||||
hello: "world",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const { body, headers } = MQTT.binary(event);
|
|
||||||
|
|
||||||
client.publish("presence", JSON.stringify(body), {
|
|
||||||
properties: {
|
|
||||||
userProperties: headers as mqtt.UserProperties,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on("message", function (topic, message, packet) {
|
|
||||||
const event = MQTT.toEvent({
|
|
||||||
body: JSON.parse(message.toString()),
|
|
||||||
headers: packet.properties?.userProperties || {},
|
|
||||||
});
|
|
||||||
console.log(event);
|
|
||||||
client.end();
|
|
||||||
});
|
|
|
@ -1,16 +0,0 @@
|
||||||
{
|
|
||||||
"extends": "./node_modules/gts/tsconfig-google.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"rootDir": "./src",
|
|
||||||
"outDir": "./build/",
|
|
||||||
"lib": [
|
|
||||||
"es6",
|
|
||||||
"dom"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"include": [
|
|
||||||
"src/**/*.ts",
|
|
||||||
"test/**/*.ts"
|
|
||||||
],
|
|
||||||
"allowJs": true
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
28
package.json
28
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "cloudevents",
|
"name": "cloudevents",
|
||||||
"version": "9.0.0",
|
"version": "6.0.0",
|
||||||
"description": "CloudEvents SDK for JavaScript",
|
"description": "CloudEvents SDK for JavaScript",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
"lint:js": "eslint 'src/**/*.{js,ts}' 'test/**/*.{js,ts}' cucumber.js",
|
"lint:js": "eslint 'src/**/*.{js,ts}' 'test/**/*.{js,ts}' cucumber.js",
|
||||||
"lint:md": "remark .",
|
"lint:md": "remark .",
|
||||||
"lint:fix": "eslint 'src/**/*.{js,ts}' 'test/**/*.{js,ts}' --fix",
|
"lint:fix": "eslint 'src/**/*.{js,ts}' 'test/**/*.{js,ts}' --fix",
|
||||||
"pretest": "npm run lint && npm run build && npm run conformance",
|
"pretest": "npm run lint && npm run conformance",
|
||||||
"test": "mocha --require ts-node/register ./test/integration/**/*.ts",
|
"test": "mocha --require ts-node/register ./test/integration/**/*.ts",
|
||||||
"test:one": "mocha --require ts-node/register",
|
"test:one": "mocha --require ts-node/register",
|
||||||
"conformance": "cucumber-js ./conformance/features/*-protocol-binding.feature -p default",
|
"conformance": "cucumber-js ./conformance/features/*-protocol-binding.feature -p default",
|
||||||
|
@ -110,19 +110,15 @@
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/cloudevents/sdk-javascript#readme",
|
"homepage": "https://github.com/cloudevents/sdk-javascript#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ajv": "^8.11.0",
|
"ajv": "^8.6.3",
|
||||||
"ajv-formats": "^2.1.1",
|
|
||||||
"process": "^0.11.10",
|
|
||||||
"json-bigint": "^1.0.0",
|
|
||||||
"util": "^0.12.4",
|
"util": "^0.12.4",
|
||||||
"uuid": "^8.3.2"
|
"uuid": "^8.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@cucumber/cucumber": "^8.0.0",
|
"@cucumber/cucumber": "^8.0.0-rc.1",
|
||||||
"@types/chai": "^4.2.11",
|
"@types/chai": "^4.2.11",
|
||||||
"@types/cucumber": "^6.0.1",
|
"@types/cucumber": "^6.0.1",
|
||||||
"@types/got": "^9.6.11",
|
"@types/got": "^9.6.11",
|
||||||
"@types/json-bigint": "^1.0.1",
|
|
||||||
"@types/mocha": "^7.0.2",
|
"@types/mocha": "^7.0.2",
|
||||||
"@types/node": "^14.14.10",
|
"@types/node": "^14.14.10",
|
||||||
"@types/superagent": "^4.1.10",
|
"@types/superagent": "^4.1.10",
|
||||||
|
@ -130,6 +126,7 @@
|
||||||
"@typescript-eslint/eslint-plugin": "^4.29.0",
|
"@typescript-eslint/eslint-plugin": "^4.29.0",
|
||||||
"@typescript-eslint/parser": "^4.29.0",
|
"@typescript-eslint/parser": "^4.29.0",
|
||||||
"ajv-cli": "^5.0.0",
|
"ajv-cli": "^5.0.0",
|
||||||
|
"ajv-formats": "^2.1.1",
|
||||||
"axios": "^0.26.1",
|
"axios": "^0.26.1",
|
||||||
"chai": "~4.2.0",
|
"chai": "~4.2.0",
|
||||||
"eslint": "^7.32.0",
|
"eslint": "^7.32.0",
|
||||||
|
@ -138,9 +135,9 @@
|
||||||
"eslint-plugin-import": "^2.23.4",
|
"eslint-plugin-import": "^2.23.4",
|
||||||
"eslint-plugin-node": "^11.1.0",
|
"eslint-plugin-node": "^11.1.0",
|
||||||
"eslint-plugin-promise": "^5.1.0",
|
"eslint-plugin-promise": "^5.1.0",
|
||||||
"got": "^11.8.5",
|
"got": "^11.7.0",
|
||||||
"http-parser-js": "^0.5.2",
|
"http-parser-js": "^0.5.2",
|
||||||
"mocha": "^10.1.0",
|
"mocha": "~9.2.0",
|
||||||
"nock": "~12.0.3",
|
"nock": "~12.0.3",
|
||||||
"nyc": "~15.0.0",
|
"nyc": "~15.0.0",
|
||||||
"prettier": "^2.0.5",
|
"prettier": "^2.0.5",
|
||||||
|
@ -149,17 +146,14 @@
|
||||||
"remark-lint-list-item-indent": "^2.0.1",
|
"remark-lint-list-item-indent": "^2.0.1",
|
||||||
"remark-preset-lint-recommended": "^5.0.0",
|
"remark-preset-lint-recommended": "^5.0.0",
|
||||||
"superagent": "^7.1.1",
|
"superagent": "^7.1.1",
|
||||||
"ts-node": "^10.8.1",
|
"ts-node": "^8.10.2",
|
||||||
"typedoc": "^0.22.11",
|
"typedoc": "^0.22.11",
|
||||||
"typescript": "^4.3.5",
|
"typescript": "^4.3.5",
|
||||||
"webpack": "^5.76.0",
|
"webpack": "^5.1.1",
|
||||||
"webpack-cli": "^4.10.0"
|
"webpack-cli": "^4.0.0"
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public"
|
"access": "public"
|
||||||
},
|
},
|
||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts"
|
||||||
"engines": {
|
|
||||||
"node": ">=20 <=24"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,6 @@ const CONSTANTS = Object.freeze({
|
||||||
DATA_SCHEMA: "dataschema",
|
DATA_SCHEMA: "dataschema",
|
||||||
DATA_BASE64: "data_base64",
|
DATA_BASE64: "data_base64",
|
||||||
},
|
},
|
||||||
USE_BIG_INT_ENV: "CE_USE_BIG_INT"
|
|
||||||
} as const);
|
} as const);
|
||||||
|
|
||||||
export default CONSTANTS;
|
export default CONSTANTS;
|
||||||
|
|
|
@ -9,13 +9,15 @@ import { Emitter } from "..";
|
||||||
|
|
||||||
import { CloudEventV1 } from "./interfaces";
|
import { CloudEventV1 } from "./interfaces";
|
||||||
import { validateCloudEvent } from "./spec";
|
import { validateCloudEvent } from "./spec";
|
||||||
import { ValidationError, isBinary, asBase64, isValidType, base64AsBinary } from "./validation";
|
import { ValidationError, isBinary, asBase64, isValidType } from "./validation";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constants representing the CloudEvent specification version
|
* An enum representing the CloudEvent specification version
|
||||||
*/
|
*/
|
||||||
export const V1 = "1.0";
|
export const enum Version {
|
||||||
export const V03 = "0.3";
|
V1 = "1.0",
|
||||||
|
V03 = "0.3",
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A CloudEvent describes event data in common formats to provide
|
* A CloudEvent describes event data in common formats to provide
|
||||||
|
@ -26,12 +28,12 @@ export class CloudEvent<T = undefined> implements CloudEventV1<T> {
|
||||||
id: string;
|
id: string;
|
||||||
type: string;
|
type: string;
|
||||||
source: string;
|
source: string;
|
||||||
specversion: string;
|
specversion: Version;
|
||||||
datacontenttype?: string;
|
datacontenttype?: string;
|
||||||
dataschema?: string;
|
dataschema?: string;
|
||||||
subject?: string;
|
subject?: string;
|
||||||
time?: string;
|
time?: string;
|
||||||
data?: T;
|
#_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
|
||||||
|
@ -67,7 +69,7 @@ export class CloudEvent<T = undefined> implements CloudEventV1<T> {
|
||||||
this.source = properties.source as string;
|
this.source = properties.source as string;
|
||||||
delete (properties as any).source;
|
delete (properties as any).source;
|
||||||
|
|
||||||
this.specversion = (properties.specversion) || V1;
|
this.specversion = (properties.specversion as Version) || Version.V1;
|
||||||
delete properties.specversion;
|
delete properties.specversion;
|
||||||
|
|
||||||
this.datacontenttype = properties.datacontenttype;
|
this.datacontenttype = properties.datacontenttype;
|
||||||
|
@ -83,35 +85,26 @@ export class CloudEvent<T = undefined> implements CloudEventV1<T> {
|
||||||
delete properties.dataschema;
|
delete properties.dataschema;
|
||||||
|
|
||||||
this.data_base64 = properties.data_base64 as string;
|
this.data_base64 = properties.data_base64 as string;
|
||||||
|
|
||||||
if (this.data_base64) {
|
|
||||||
this.data = base64AsBinary(this.data_base64) as unknown as T;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete properties.data_base64;
|
delete properties.data_base64;
|
||||||
|
|
||||||
this.schemaurl = properties.schemaurl as string;
|
this.schemaurl = properties.schemaurl as string;
|
||||||
delete properties.schemaurl;
|
delete properties.schemaurl;
|
||||||
|
|
||||||
if (isBinary(properties.data)) {
|
this.data = properties.data;
|
||||||
this.data_base64 = asBase64(properties.data as unknown as Buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.data = typeof properties.data !== "undefined" ? properties.data : this.data;
|
|
||||||
delete properties.data;
|
delete properties.data;
|
||||||
|
|
||||||
// sanity checking
|
// sanity checking
|
||||||
if (this.specversion === V1 && this.schemaurl) {
|
if (this.specversion === Version.V1 && this.schemaurl) {
|
||||||
throw new TypeError("cannot set schemaurl on version 1.0 event");
|
throw new TypeError("cannot set schemaurl on version 1.0 event");
|
||||||
} else if (this.specversion === V03 && this.dataschema) {
|
} else if (this.specversion === Version.V03 && this.dataschema) {
|
||||||
throw new TypeError("cannot set dataschema on version 0.3 event");
|
throw new TypeError("cannot set dataschema on version 0.3 event");
|
||||||
}
|
}
|
||||||
|
|
||||||
// finally process any remaining properties - these are extensions
|
// finally process any remaining properties - these are extensions
|
||||||
for (const [key, value] of Object.entries(properties)) {
|
for (const [key, value] of Object.entries(properties)) {
|
||||||
// Extension names must only allow lowercase a-z and 0-9 in the name
|
// Extension names should only allow lowercase a-z and 0-9 in the name
|
||||||
// names should not exceed 20 characters in length
|
// names should not exceed 20 characters in length
|
||||||
if (!key.match(/^[a-z0-9]+$/) && strict) {
|
if (!key.match(/^[a-z0-9]{1,20}$/) && strict) {
|
||||||
throw new ValidationError(`invalid extension name: ${key}
|
throw new ValidationError(`invalid extension name: ${key}
|
||||||
CloudEvents attribute names MUST consist of lower-case letters ('a' to 'z')
|
CloudEvents attribute names MUST consist of lower-case letters ('a' to 'z')
|
||||||
or digits ('0' to '9') from the ASCII character set. Attribute names SHOULD
|
or digits ('0' to '9') from the ASCII character set. Attribute names SHOULD
|
||||||
|
@ -134,6 +127,17 @@ See: https://github.com/cloudevents/spec/blob/v1.0/spec.md#type-system`);
|
||||||
Object.freeze(this);
|
Object.freeze(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get data(): T | undefined {
|
||||||
|
return this.#_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
set data(value: T | undefined) {
|
||||||
|
if (isBinary(value)) {
|
||||||
|
this.data_base64 = asBase64(value);
|
||||||
|
}
|
||||||
|
this.#_data = value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used by JSON.stringify(). The name is confusing, but this method is called by
|
* Used by JSON.stringify(). The name is confusing, but this method is called by
|
||||||
* JSON.stringify() when converting this object to JSON.
|
* JSON.stringify() when converting this object to JSON.
|
||||||
|
@ -143,11 +147,7 @@ See: https://github.com/cloudevents/spec/blob/v1.0/spec.md#type-system`);
|
||||||
toJSON(): Record<string, unknown> {
|
toJSON(): Record<string, unknown> {
|
||||||
const event = { ...this };
|
const event = { ...this };
|
||||||
event.time = new Date(this.time as string).toISOString();
|
event.time = new Date(this.time as string).toISOString();
|
||||||
|
event.data = this.#_data;
|
||||||
if (event.data_base64 && event.data) {
|
|
||||||
delete event.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,6 +230,9 @@ See: https://github.com/cloudevents/spec/blob/v1.0/spec.md#type-system`);
|
||||||
event: CloudEventV1<any>,
|
event: CloudEventV1<any>,
|
||||||
options: Partial<CloudEventV1<any>>,
|
options: Partial<CloudEventV1<any>>,
|
||||||
strict = true): CloudEvent<any> {
|
strict = true): CloudEvent<any> {
|
||||||
|
if (event instanceof CloudEvent) {
|
||||||
|
event = event.toJSON() as CloudEventV1<any>;
|
||||||
|
}
|
||||||
return new CloudEvent(Object.assign({}, event, options), strict);
|
return new CloudEvent(Object.assign({}, event, options), strict);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,23 +6,22 @@
|
||||||
import { ValidationError } from "./validation";
|
import { ValidationError } from "./validation";
|
||||||
|
|
||||||
import { CloudEventV1 } from "./interfaces";
|
import { CloudEventV1 } from "./interfaces";
|
||||||
import { V1 } from "./cloudevent";
|
import { Version } from "./cloudevent";
|
||||||
import validate from "../schema/v1";
|
import validate from "../schema/v1";
|
||||||
|
|
||||||
|
|
||||||
export function validateCloudEvent<T>(event: CloudEventV1<T>): boolean {
|
export function validateCloudEvent<T>(event: CloudEventV1<T>): boolean {
|
||||||
if (event.specversion === V1) {
|
if (event.specversion === Version.V1) {
|
||||||
if (!validate(event)) {
|
if (!validate(event)) {
|
||||||
throw new ValidationError("invalid payload", (validate as any).errors);
|
throw new ValidationError("invalid payload", (validate as any).errors);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// attribute names must all be [a-z|0-9]
|
// attribute names must all be lowercase
|
||||||
const validation = /^[a-z0-9]+$/;
|
|
||||||
for (const key in event) {
|
for (const key in event) {
|
||||||
if (validation.test(key) === false && key !== "data_base64") {
|
if (key !== key.toLowerCase()) {
|
||||||
throw new ValidationError(`invalid attribute name: "${key}"`);
|
throw new ValidationError(`invalid attribute name: ${key}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -5,23 +5,6 @@
|
||||||
|
|
||||||
import { ErrorObject } from "ajv";
|
import { ErrorObject } from "ajv";
|
||||||
|
|
||||||
export type TypeArray = Int8Array | Uint8Array | Int16Array | Uint16Array |
|
|
||||||
Int32Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array;
|
|
||||||
|
|
||||||
const globalThisPolyfill = (function() {
|
|
||||||
try {
|
|
||||||
return globalThis;
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
try {
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return global;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}());
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An Error class that will be thrown when a CloudEvent
|
* An Error class that will be thrown when a CloudEvent
|
||||||
* cannot be properly validated against a specification.
|
* cannot be properly validated against a specification.
|
||||||
|
@ -53,7 +36,7 @@ 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): v is Date => v instanceof Date;
|
export const isDate = (v: unknown): v is Date => v instanceof Date;
|
||||||
export const isBinary = (v: unknown): boolean => ArrayBuffer.isView(v);
|
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)
|
||||||
|
@ -90,7 +73,7 @@ export const isBase64 = (value: unknown): boolean =>
|
||||||
|
|
||||||
export const isBuffer = (value: unknown): boolean => value instanceof Buffer;
|
export const isBuffer = (value: unknown): boolean => value instanceof Buffer;
|
||||||
|
|
||||||
export const asBuffer = (value: string | Buffer | TypeArray): Buffer =>
|
export const asBuffer = (value: string | Buffer | Uint32Array): Buffer =>
|
||||||
isBinary(value)
|
isBinary(value)
|
||||||
? Buffer.from((value as unknown) as string)
|
? Buffer.from((value as unknown) as string)
|
||||||
: isBuffer(value)
|
: isBuffer(value)
|
||||||
|
@ -99,16 +82,7 @@ export const asBuffer = (value: string | Buffer | TypeArray): Buffer =>
|
||||||
throw new TypeError("is not buffer or a valid binary");
|
throw new TypeError("is not buffer or a valid binary");
|
||||||
})();
|
})();
|
||||||
|
|
||||||
export const base64AsBinary = (base64String: string): Uint8Array => {
|
export const asBase64 = (value: string | Buffer | Uint32Array): string => asBuffer(value).toString("base64");
|
||||||
const toBinaryString = (base64Str: string): string => globalThisPolyfill.atob
|
|
||||||
? globalThisPolyfill.atob(base64Str)
|
|
||||||
: Buffer.from(base64Str, "base64").toString("binary");
|
|
||||||
|
|
||||||
return Uint8Array.from(toBinaryString(base64String), (c) => c.charCodeAt(0));
|
|
||||||
};
|
|
||||||
|
|
||||||
export const asBase64 =
|
|
||||||
(value: string | Buffer | TypeArray): string => asBuffer(value).toString("base64");
|
|
||||||
|
|
||||||
export const clone = (o: Record<string, unknown>): Record<string, unknown> => JSON.parse(JSON.stringify(o));
|
export const clone = (o: Record<string, unknown>): Record<string, unknown> => JSON.parse(JSON.stringify(o));
|
||||||
|
|
||||||
|
@ -123,5 +97,5 @@ export const asData = (data: unknown, contentType: string): string => {
|
||||||
return isBinary(maybeJson) ? asBase64(maybeJson) : maybeJson;
|
return isBinary(maybeJson) ? asBase64(maybeJson) : maybeJson;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isValidType = (v: boolean | number | string | Date | TypeArray | unknown): boolean =>
|
export const isValidType = (v: boolean | number | string | Date | Uint32Array | unknown): boolean =>
|
||||||
isBoolean(v) || isInteger(v) || isString(v) || isDate(v) || isBinary(v) || isObject(v);
|
isBoolean(v) || isInteger(v) || isString(v) || isDate(v) || isBinary(v) || isObject(v);
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
SPDX-License-Identifier: Apache-2.0
|
SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { CloudEvent, V1, V03 } from "./event/cloudevent";
|
import { CloudEvent, Version } from "./event/cloudevent";
|
||||||
import { ValidationError } from "./event/validation";
|
import { ValidationError } from "./event/validation";
|
||||||
import { CloudEventV1, CloudEventV1Attributes } from "./event/interfaces";
|
import { CloudEventV1, CloudEventV1Attributes } from "./event/interfaces";
|
||||||
|
|
||||||
|
@ -18,8 +18,7 @@ import CONSTANTS from "./constants";
|
||||||
export {
|
export {
|
||||||
// From event
|
// From event
|
||||||
CloudEvent,
|
CloudEvent,
|
||||||
V1,
|
Version,
|
||||||
V03,
|
|
||||||
ValidationError,
|
ValidationError,
|
||||||
Mode,
|
Mode,
|
||||||
HTTP,
|
HTTP,
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
import { PassThroughParser, DateParser, MappedParser } from "../../parsers";
|
import { PassThroughParser, DateParser, MappedParser } from "../../parsers";
|
||||||
import { CloudEventV1 } from "../..";
|
import { CloudEventV1 } from "../..";
|
||||||
import { Headers } from "../";
|
import { Headers } from "../";
|
||||||
import { V1 } from "../../event/cloudevent";
|
import { Version } from "../../event/cloudevent";
|
||||||
import CONSTANTS from "../../constants";
|
import CONSTANTS from "../../constants";
|
||||||
|
|
||||||
export const allowedContentTypes = [CONSTANTS.DEFAULT_CONTENT_TYPE, CONSTANTS.MIME_JSON, CONSTANTS.MIME_OCTET_STREAM];
|
export const allowedContentTypes = [CONSTANTS.DEFAULT_CONTENT_TYPE, CONSTANTS.MIME_JSON, CONSTANTS.MIME_OCTET_STREAM];
|
||||||
|
@ -27,7 +27,7 @@ export const requiredHeaders = [
|
||||||
export function headersFor<T>(event: CloudEventV1<T>): Headers {
|
export function headersFor<T>(event: CloudEventV1<T>): Headers {
|
||||||
const headers: Headers = {};
|
const headers: Headers = {};
|
||||||
let headerMap: Readonly<{ [key: string]: MappedParser }>;
|
let headerMap: Readonly<{ [key: string]: MappedParser }>;
|
||||||
if (event.specversion === V1) {
|
if (event.specversion === Version.V1) {
|
||||||
headerMap = v1headerMap;
|
headerMap = v1headerMap;
|
||||||
} else {
|
} else {
|
||||||
headerMap = v03headerMap;
|
headerMap = v03headerMap;
|
||||||
|
@ -36,7 +36,7 @@ export function headersFor<T>(event: CloudEventV1<T>): Headers {
|
||||||
// iterate over the event properties - generate a header for each
|
// iterate over the event properties - generate a header for each
|
||||||
Object.getOwnPropertyNames(event).forEach((property) => {
|
Object.getOwnPropertyNames(event).forEach((property) => {
|
||||||
const value = event[property];
|
const value = event[property];
|
||||||
if (value !== undefined) {
|
if (value) {
|
||||||
const map: MappedParser | undefined = headerMap[property] as MappedParser;
|
const map: MappedParser | undefined = headerMap[property] as MappedParser;
|
||||||
if (map) {
|
if (map) {
|
||||||
headers[map.name] = map.parser.parse(value as string) as string;
|
headers[map.name] = map.parser.parse(value as string) as string;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
import { types } from "util";
|
import { types } from "util";
|
||||||
|
|
||||||
import { CloudEvent, CloudEventV1, CONSTANTS, Mode, V1, V03 } from "../..";
|
import { CloudEvent, CloudEventV1, CONSTANTS, Mode, Version } from "../..";
|
||||||
import { Message, Headers, Binding } from "..";
|
import { Message, Headers, Binding } from "..";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -147,7 +147,7 @@ function getVersion(mode: Mode, headers: Headers, body: string | Record<string,
|
||||||
return (body as Record<string, string>).specversion;
|
return (body as Record<string, string>).specversion;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return V1;
|
return Version.V1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -155,11 +155,11 @@ function getVersion(mode: Mode, headers: Headers, body: string | Record<string,
|
||||||
* instance if it conforms to the Cloud Event specification for this receiver.
|
* instance if it conforms to the Cloud Event specification for this receiver.
|
||||||
*
|
*
|
||||||
* @param {Message} message the incoming HTTP Message
|
* @param {Message} message the incoming HTTP Message
|
||||||
* @param {string} version the spec version of the incoming event
|
* @param {Version} version the spec version of the incoming event
|
||||||
* @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<T>(message: Message, version: string): CloudEvent<T> {
|
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;
|
||||||
|
|
||||||
|
@ -169,7 +169,7 @@ function parseBinary<T>(message: Message, version: string): CloudEvent<T> {
|
||||||
const sanitizedHeaders = sanitize(headers);
|
const sanitizedHeaders = sanitize(headers);
|
||||||
|
|
||||||
const eventObj: { [key: string]: unknown | string | Record<string, unknown> } = {};
|
const eventObj: { [key: string]: unknown | string | Record<string, unknown> } = {};
|
||||||
const parserMap: Record<string, MappedParser> = version === V03 ? v03binaryParsers : v1binaryParsers;
|
const parserMap: Record<string, MappedParser> = version === Version.V03 ? v03binaryParsers : v1binaryParsers;
|
||||||
|
|
||||||
for (const header in parserMap) {
|
for (const header in parserMap) {
|
||||||
if (sanitizedHeaders[header]) {
|
if (sanitizedHeaders[header]) {
|
||||||
|
@ -206,11 +206,11 @@ function parseBinary<T>(message: Message, version: string): CloudEvent<T> {
|
||||||
* Creates a new CloudEvent instance based on the provided payload and headers.
|
* Creates a new CloudEvent instance based on the provided payload and headers.
|
||||||
*
|
*
|
||||||
* @param {Message} message the incoming Message
|
* @param {Message} message the incoming Message
|
||||||
* @param {string} version the spec version of this message (v1 or v03)
|
* @param {Version} version the spec version of this message (v1 or v03)
|
||||||
* @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<T>(message: Message, version: string): CloudEvent<T> {
|
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;
|
||||||
|
|
||||||
|
@ -227,7 +227,7 @@ function parseStructured<T>(message: Message, version: string): CloudEvent<T> {
|
||||||
const incoming = { ...(parser.parse(payload as string) as Record<string, unknown>) };
|
const incoming = { ...(parser.parse(payload as string) as Record<string, unknown>) };
|
||||||
|
|
||||||
const eventObj: { [key: string]: unknown } = {};
|
const eventObj: { [key: string]: unknown } = {};
|
||||||
const parserMap: Record<string, MappedParser> = version === V03 ? v03structuredParsers : v1structuredParsers;
|
const parserMap: Record<string, MappedParser> = version === Version.V03 ? v03structuredParsers : v1structuredParsers;
|
||||||
|
|
||||||
for (const key in parserMap) {
|
for (const key in parserMap) {
|
||||||
const property = incoming[key];
|
const property = incoming[key];
|
||||||
|
|
|
@ -22,9 +22,9 @@ export * from "./mqtt";
|
||||||
* @property {@link Deserializer} `toEvent` - converts a Message into a CloudEvent
|
* @property {@link Deserializer} `toEvent` - converts a Message into a CloudEvent
|
||||||
* @property {@link Detector} `isEvent` - determines if a Message can be converted to a CloudEvent
|
* @property {@link Detector} `isEvent` - determines if a Message can be converted to a CloudEvent
|
||||||
*/
|
*/
|
||||||
export interface Binding<B extends Message = Message, S extends Message = Message> {
|
export interface Binding {
|
||||||
binary: Serializer<B>;
|
binary: Serializer;
|
||||||
structured: Serializer<S>;
|
structured: Serializer;
|
||||||
toEvent: Deserializer;
|
toEvent: Deserializer;
|
||||||
isEvent: Detector;
|
isEvent: Detector;
|
||||||
}
|
}
|
||||||
|
@ -65,8 +65,8 @@ export enum Mode {
|
||||||
* CloudEvent into a Message.
|
* CloudEvent into a Message.
|
||||||
* @interface
|
* @interface
|
||||||
*/
|
*/
|
||||||
export interface Serializer<M extends Message> {
|
export interface Serializer {
|
||||||
<T>(event: CloudEventV1<T>): M;
|
<T>(event: CloudEventV1<T>): Message;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -22,7 +22,7 @@ export type {
|
||||||
* Bindings for Kafka transport
|
* Bindings for Kafka transport
|
||||||
* @implements {@linkcode Binding}
|
* @implements {@linkcode Binding}
|
||||||
*/
|
*/
|
||||||
const Kafka: Binding<KafkaMessage<unknown>, KafkaMessage<string>> = {
|
const Kafka: Binding = {
|
||||||
binary: toBinaryKafkaMessage,
|
binary: toBinaryKafkaMessage,
|
||||||
structured: toStructuredKafkaMessage,
|
structured: toStructuredKafkaMessage,
|
||||||
toEvent: deserializeKafkaMessage,
|
toEvent: deserializeKafkaMessage,
|
||||||
|
@ -35,9 +35,9 @@ type Key = string | Buffer;
|
||||||
* Extends the base Message type to include
|
* Extends the base Message type to include
|
||||||
* Kafka-specific fields
|
* Kafka-specific fields
|
||||||
*/
|
*/
|
||||||
interface KafkaMessage<T = string | Buffer | unknown> extends Message {
|
interface KafkaMessage<T = string> extends Message {
|
||||||
key: Key
|
key: Key
|
||||||
value: T
|
value: T | string | Buffer | unknown
|
||||||
timestamp?: string
|
timestamp?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ interface KafkaEvent<T> extends CloudEventV1<T> {
|
||||||
* @param {KafkaEvent<T>} event The event to serialize
|
* @param {KafkaEvent<T>} event The event to serialize
|
||||||
* @returns {KafkaMessage<T>} a KafkaMessage instance
|
* @returns {KafkaMessage<T>} a KafkaMessage instance
|
||||||
*/
|
*/
|
||||||
function toBinaryKafkaMessage<T>(event: CloudEventV1<T>): KafkaMessage<T | undefined> {
|
function toBinaryKafkaMessage<T>(event: CloudEventV1<T>): KafkaMessage<T> {
|
||||||
// 3.2.1. Content Type
|
// 3.2.1. Content Type
|
||||||
// For the binary mode, the header content-type property MUST be mapped directly
|
// For the binary mode, the header content-type property MUST be mapped directly
|
||||||
// to the CloudEvents datacontenttype attribute.
|
// to the CloudEvents datacontenttype attribute.
|
||||||
|
@ -86,7 +86,7 @@ function toBinaryKafkaMessage<T>(event: CloudEventV1<T>): KafkaMessage<T | undef
|
||||||
* @param {CloudEvent<T>} event the CloudEvent to be serialized
|
* @param {CloudEvent<T>} event the CloudEvent to be serialized
|
||||||
* @returns {KafkaMessage<T>} a KafkaMessage instance
|
* @returns {KafkaMessage<T>} a KafkaMessage instance
|
||||||
*/
|
*/
|
||||||
function toStructuredKafkaMessage<T>(event: CloudEventV1<T>): KafkaMessage<string> {
|
function toStructuredKafkaMessage<T>(event: CloudEventV1<T>): KafkaMessage<T> {
|
||||||
if ((event instanceof CloudEvent) && event.data_base64) {
|
if ((event instanceof CloudEvent) && 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 });
|
||||||
|
@ -130,9 +130,9 @@ function deserializeKafkaMessage<T>(message: Message): CloudEvent<T> | CloudEven
|
||||||
case Mode.BINARY:
|
case Mode.BINARY:
|
||||||
return parseBinary(m);
|
return parseBinary(m);
|
||||||
case Mode.STRUCTURED:
|
case Mode.STRUCTURED:
|
||||||
return parseStructured(m as unknown as KafkaMessage<string>);
|
return parseStructured(m);
|
||||||
case Mode.BATCH:
|
case Mode.BATCH:
|
||||||
return parseBatched(m as unknown as KafkaMessage<string>);
|
return parseBatched(m);
|
||||||
default:
|
default:
|
||||||
throw new ValidationError("Unknown Message mode");
|
throw new ValidationError("Unknown Message mode");
|
||||||
}
|
}
|
||||||
|
@ -212,14 +212,14 @@ function parseBinary<T>(message: KafkaMessage<T>): CloudEvent<T> {
|
||||||
* @param {KafkaMessage<T>} message the message
|
* @param {KafkaMessage<T>} message the message
|
||||||
* @returns {CloudEvent<T>} a KafkaEvent<T>
|
* @returns {CloudEvent<T>} a KafkaEvent<T>
|
||||||
*/
|
*/
|
||||||
function parseStructured<T>(message: KafkaMessage<string>): CloudEvent<T> {
|
function parseStructured<T>(message: KafkaMessage<T>): CloudEvent<T> {
|
||||||
// Although the format of a structured encoded event could be something
|
// Although the format of a structured encoded event could be something
|
||||||
// other than JSON, e.g. XML, we currently only support JSON
|
// other than JSON, e.g. XML, we currently only support JSON
|
||||||
// encoded structured events.
|
// encoded structured events.
|
||||||
if (!message.headers[CONSTANTS.HEADER_CONTENT_TYPE]?.startsWith(CONSTANTS.MIME_CE_JSON)) {
|
if (!message.headers[CONSTANTS.HEADER_CONTENT_TYPE]?.startsWith(CONSTANTS.MIME_CE_JSON)) {
|
||||||
throw new ValidationError(`Unsupported event encoding ${message.headers[CONSTANTS.HEADER_CONTENT_TYPE]}`);
|
throw new ValidationError(`Unsupported event encoding ${message.headers[CONSTANTS.HEADER_CONTENT_TYPE]}`);
|
||||||
}
|
}
|
||||||
const eventObj = JSON.parse(message.value);
|
const eventObj = JSON.parse(message.value as string);
|
||||||
eventObj.time = new Date(eventObj.time).toISOString();
|
eventObj.time = new Date(eventObj.time).toISOString();
|
||||||
return new CloudEvent({
|
return new CloudEvent({
|
||||||
...eventObj,
|
...eventObj,
|
||||||
|
@ -232,14 +232,14 @@ function parseStructured<T>(message: KafkaMessage<string>): CloudEvent<T> {
|
||||||
* @param {KafkaMessage<T>} message the message
|
* @param {KafkaMessage<T>} message the message
|
||||||
* @returns {CloudEvent<T>[]} an array of KafkaEvent<T>
|
* @returns {CloudEvent<T>[]} an array of KafkaEvent<T>
|
||||||
*/
|
*/
|
||||||
function parseBatched<T>(message: KafkaMessage<string>): CloudEvent<T>[] {
|
function parseBatched<T>(message: KafkaMessage<T>): CloudEvent<T>[] {
|
||||||
// Although the format of batch encoded events could be something
|
// Although the format of batch encoded events could be something
|
||||||
// other than JSON, e.g. XML, we currently only support JSON
|
// other than JSON, e.g. XML, we currently only support JSON
|
||||||
// encoded structured events.
|
// encoded structured events.
|
||||||
if (!message.headers[CONSTANTS.HEADER_CONTENT_TYPE]?.startsWith(CONSTANTS.MIME_CE_BATCH)) {
|
if (!message.headers[CONSTANTS.HEADER_CONTENT_TYPE]?.startsWith(CONSTANTS.MIME_CE_BATCH)) {
|
||||||
throw new ValidationError(`Unsupported event encoding ${message.headers[CONSTANTS.HEADER_CONTENT_TYPE]}`);
|
throw new ValidationError(`Unsupported event encoding ${message.headers[CONSTANTS.HEADER_CONTENT_TYPE]}`);
|
||||||
}
|
}
|
||||||
const events = JSON.parse(message.value) as Record<string, unknown>[];
|
const events = JSON.parse(message.value as string) as Record<string, unknown>[];
|
||||||
return events.map((e) => new CloudEvent({ ...e, partitionkey: message.key }, false));
|
return events.map((e) => new CloudEvent({ ...e, partitionkey: message.key }, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Binding, Deserializer, CloudEvent, CloudEventV1, CONSTANTS, Message, ValidationError, Headers } from "../..";
|
import { Binding, Deserializer, CloudEvent, CloudEventV1, CONSTANTS, Message, ValidationError, Headers } from "../..";
|
||||||
import { base64AsBinary } from "../../event/validation";
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
MQTT, MQTTMessageFactory
|
MQTT, MQTTMessageFactory
|
||||||
|
@ -15,7 +14,7 @@ export type { MQTTMessage };
|
||||||
* Extends the base {@linkcode Message} interface to include MQTT attributes, some of which
|
* Extends the base {@linkcode Message} interface to include MQTT attributes, some of which
|
||||||
* are aliases of the {Message} attributes.
|
* are aliases of the {Message} attributes.
|
||||||
*/
|
*/
|
||||||
interface MQTTMessage<T = unknown> extends Message<T> {
|
interface MQTTMessage<T> extends Message<T> {
|
||||||
/**
|
/**
|
||||||
* Identifies this message as a PUBLISH packet. MQTTMessages created with
|
* Identifies this message as a PUBLISH packet. MQTTMessages created with
|
||||||
* the `binary` and `structured` Serializers will contain a "Content Type"
|
* the `binary` and `structured` Serializers will contain a "Content Type"
|
||||||
|
@ -37,7 +36,7 @@ interface MQTTMessage<T = unknown> extends Message<T> {
|
||||||
* Binding for MQTT transport support
|
* Binding for MQTT transport support
|
||||||
* @implements @linkcode Binding
|
* @implements @linkcode Binding
|
||||||
*/
|
*/
|
||||||
const MQTT: Binding<MQTTMessage, MQTTMessage> = {
|
const MQTT: Binding = {
|
||||||
binary,
|
binary,
|
||||||
structured,
|
structured,
|
||||||
toEvent: toEvent as Deserializer,
|
toEvent: toEvent as Deserializer,
|
||||||
|
@ -51,16 +50,14 @@ const MQTT: Binding<MQTTMessage, MQTTMessage> = {
|
||||||
* @implements {Serializer}
|
* @implements {Serializer}
|
||||||
*/
|
*/
|
||||||
function binary<T>(event: CloudEventV1<T>): MQTTMessage<T> {
|
function binary<T>(event: CloudEventV1<T>): MQTTMessage<T> {
|
||||||
const properties = { ...event };
|
let properties;
|
||||||
|
if (event instanceof CloudEvent) {
|
||||||
let body = properties.data as T;
|
properties = event.toJSON();
|
||||||
|
} else {
|
||||||
if (!body && properties.data_base64) {
|
properties = event;
|
||||||
body = base64AsBinary(properties.data_base64) as unknown as T;
|
|
||||||
}
|
}
|
||||||
|
const body = properties.data as T;
|
||||||
delete properties.data;
|
delete properties.data;
|
||||||
delete properties.data_base64;
|
|
||||||
|
|
||||||
return MQTTMessageFactory(event.datacontenttype as string, properties, body);
|
return MQTTMessageFactory(event.datacontenttype as string, properties, body);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,9 @@
|
||||||
SPDX-License-Identifier: Apache-2.0
|
SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import JSONbig from "json-bigint";
|
|
||||||
import CONSTANTS from "./constants";
|
import CONSTANTS from "./constants";
|
||||||
import { isString, isDefinedOrThrow, isStringOrObjectOrThrow, ValidationError } from "./event/validation";
|
import { isString, isDefinedOrThrow, isStringOrObjectOrThrow, ValidationError } from "./event/validation";
|
||||||
|
|
||||||
const __JSON = JSON;
|
|
||||||
export abstract class Parser {
|
export abstract class Parser {
|
||||||
abstract parse(payload: Record<string, unknown> | string | string[] | undefined): unknown;
|
abstract parse(payload: Record<string, unknown> | string | string[] | undefined): unknown;
|
||||||
}
|
}
|
||||||
|
@ -38,13 +36,6 @@ export class JSONParser implements Parser {
|
||||||
|
|
||||||
isDefinedOrThrow(payload, new ValidationError("null or undefined payload"));
|
isDefinedOrThrow(payload, new ValidationError("null or undefined payload"));
|
||||||
isStringOrObjectOrThrow(payload, new ValidationError("invalid payload type, allowed are: string or object"));
|
isStringOrObjectOrThrow(payload, new ValidationError("invalid payload type, allowed are: string or object"));
|
||||||
|
|
||||||
if (process.env[CONSTANTS.USE_BIG_INT_ENV] === "true") {
|
|
||||||
JSON = JSONbig(({ useNativeBigInt: true })) as JSON;
|
|
||||||
} else {
|
|
||||||
JSON = __JSON;
|
|
||||||
}
|
|
||||||
|
|
||||||
const parseJSON = (v: Record<string, unknown> | string): string => (isString(v) ? JSON.parse(v as string) : v);
|
const parseJSON = (v: Record<string, unknown> | string): string => (isString(v) ? JSON.parse(v as string) : v);
|
||||||
return parseJSON(payload);
|
return parseJSON(payload);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,39 +7,24 @@ import path from "path";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
|
|
||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
import { CloudEvent, CloudEventV1, ValidationError, V1 } from "../../src";
|
import { CloudEvent, ValidationError, Version } from "../../src";
|
||||||
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 = Object.freeze({
|
const fixture = {
|
||||||
id,
|
id,
|
||||||
specversion: V1,
|
specversion: Version.V1,
|
||||||
source,
|
source,
|
||||||
type,
|
type,
|
||||||
data: `"some data"`
|
data: `"some data"`,
|
||||||
});
|
};
|
||||||
|
|
||||||
const imageData = new Uint32Array(fs.readFileSync(path.join(process.cwd(), "test", "integration", "ce.png")));
|
const imageData = new Uint32Array(fs.readFileSync(path.join(process.cwd(), "test", "integration", "ce.png")));
|
||||||
const image_base64 = asBase64(imageData);
|
const image_base64 = asBase64(imageData);
|
||||||
|
|
||||||
// Do not replace this with the assignment of a class instance
|
|
||||||
// as we just want to test if we can enumerate all explicitly defined fields!
|
|
||||||
const cloudEventV1InterfaceFields: (keyof CloudEventV1<unknown>)[] = Object.keys({
|
|
||||||
id: "",
|
|
||||||
type: "",
|
|
||||||
data: undefined,
|
|
||||||
data_base64: "",
|
|
||||||
source: "",
|
|
||||||
time: "",
|
|
||||||
datacontenttype: "",
|
|
||||||
dataschema: "",
|
|
||||||
specversion: "",
|
|
||||||
subject: ""
|
|
||||||
} as Required<CloudEventV1<unknown>>);
|
|
||||||
|
|
||||||
describe("A CloudEvent", () => {
|
describe("A CloudEvent", () => {
|
||||||
it("Can be constructed with a typed Message", () => {
|
it("Can be constructed with a typed Message", () => {
|
||||||
const ce = new CloudEvent(fixture);
|
const ce = new CloudEvent(fixture);
|
||||||
|
@ -82,10 +67,10 @@ describe("A CloudEvent", () => {
|
||||||
}).throw("invalid extension name");
|
}).throw("invalid extension name");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Not throw a validation error for invalid extension names, more than 20 chars", () => {
|
it("Throw a validation error for invalid extension names, more than 20 chars", () => {
|
||||||
expect(() => {
|
expect(() => {
|
||||||
new CloudEvent({ "123456789012345678901": "extension1", ...fixture });
|
new CloudEvent({ "123456789012345678901": "extension1", ...fixture });
|
||||||
}).not.throw("invalid extension name");
|
}).throw("invalid extension name");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Throws a validation error for invalid uppercase extension names", () => {
|
it("Throws a validation error for invalid uppercase extension names", () => {
|
||||||
|
@ -93,58 +78,6 @@ describe("A CloudEvent", () => {
|
||||||
new CloudEvent({ ExtensionWithCaps: "extension value", ...fixture });
|
new CloudEvent({ ExtensionWithCaps: "extension value", ...fixture });
|
||||||
}).throw("invalid extension name");
|
}).throw("invalid extension name");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("CloudEventV1 interface fields should be enumerable", () => {
|
|
||||||
const classInstanceKeys = Object.keys(new CloudEvent({ ...fixture }));
|
|
||||||
|
|
||||||
for (const key of cloudEventV1InterfaceFields) {
|
|
||||||
expect(classInstanceKeys).to.contain(key);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it("throws TypeError on trying to set any field value", () => {
|
|
||||||
const ce = new CloudEvent({
|
|
||||||
...fixture,
|
|
||||||
mycustomfield: "initialValue"
|
|
||||||
});
|
|
||||||
|
|
||||||
const keySet = new Set([...cloudEventV1InterfaceFields, ...Object.keys(ce)]);
|
|
||||||
|
|
||||||
expect(keySet).not.to.be.empty;
|
|
||||||
|
|
||||||
for (const cloudEventKey of keySet) {
|
|
||||||
let threw = false;
|
|
||||||
|
|
||||||
try {
|
|
||||||
ce[cloudEventKey] = "newValue";
|
|
||||||
} catch (err) {
|
|
||||||
threw = true;
|
|
||||||
expect(err).to.be.instanceOf(TypeError);
|
|
||||||
expect((err as TypeError).message).to.include("Cannot assign to read only property");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!threw) {
|
|
||||||
expect.fail(`Assigning a value to ${cloudEventKey} did not throw`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("toJSON()", () => {
|
|
||||||
it("does not return data field if data_base64 field is set to comply with JSON format spec 3.1.1", () => {
|
|
||||||
const binaryData = new Uint8Array([1,2,3]);
|
|
||||||
|
|
||||||
const ce = new CloudEvent({
|
|
||||||
...fixture,
|
|
||||||
data: binaryData
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(ce.data).to.be.equal(binaryData);
|
|
||||||
|
|
||||||
const json = ce.toJSON();
|
|
||||||
expect(json.data).to.not.exist;
|
|
||||||
expect(json.data_base64).to.be.equal("AQID");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("A 1.0 CloudEvent", () => {
|
describe("A 1.0 CloudEvent", () => {
|
||||||
|
@ -165,7 +98,7 @@ describe("A 1.0 CloudEvent", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("can be constructed with an ID", () => {
|
it("can be constructed with an ID", () => {
|
||||||
const ce = new CloudEvent({ id: "1234", specversion: V1, source, type });
|
const ce = new CloudEvent({ id: "1234", specversion: Version.V1, source, type });
|
||||||
expect(ce.id).to.equal("1234");
|
expect(ce.id).to.equal("1234");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -280,7 +213,7 @@ describe("A 1.0 CloudEvent", () => {
|
||||||
const obj = JSON.parse(json as string);
|
const obj = JSON.parse(json as string);
|
||||||
expect(obj.type).to.equal(type);
|
expect(obj.type).to.equal(type);
|
||||||
expect(obj.source).to.equal(source);
|
expect(obj.source).to.equal(source);
|
||||||
expect(obj.specversion).to.equal(V1);
|
expect(obj.specversion).to.equal(Version.V1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("throws if the provded source is empty string", () => {
|
it("throws if the provded source is empty string", () => {
|
||||||
|
|
|
@ -26,7 +26,7 @@ describe("Emitter Singleton", () => {
|
||||||
if (typeof body === "string") {
|
if (typeof body === "string") {
|
||||||
body = JSON.parse(body);
|
body = JSON.parse(body);
|
||||||
}
|
}
|
||||||
assertStructured({ ...(body as any), ...(msg as Message).headers });
|
assertStructured({ ...(<any>body), ...(msg as Message).headers });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("emit a Node.js 'cloudevent' event as an EventEmitter with ensureDelivery", async () => {
|
it("emit a Node.js 'cloudevent' event as an EventEmitter with ensureDelivery", async () => {
|
||||||
|
@ -41,7 +41,7 @@ describe("Emitter Singleton", () => {
|
||||||
if (typeof body === "string") {
|
if (typeof body === "string") {
|
||||||
body = JSON.parse(body);
|
body = JSON.parse(body);
|
||||||
}
|
}
|
||||||
assertStructured({ ...(body as any), ...(msg as Message).headers });
|
assertStructured({ ...(<any>body), ...(msg as Message).headers });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("emit a Node.js 'cloudevent' event as an EventEmitter with ensureDelivery Error", async () => {
|
it("emit a Node.js 'cloudevent' event as an EventEmitter with ensureDelivery Error", async () => {
|
||||||
|
|
|
@ -7,7 +7,7 @@ import path from "path";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
|
|
||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
import { CloudEvent, CONSTANTS, V1 } from "../../src";
|
import { CloudEvent, CONSTANTS, Version } from "../../src";
|
||||||
import { asBase64 } from "../../src/event/validation";
|
import { asBase64 } from "../../src/event/validation";
|
||||||
import { Message, Kafka, KafkaMessage, KafkaEvent } from "../../src/message";
|
import { Message, Kafka, KafkaMessage, KafkaEvent } from "../../src/message";
|
||||||
import { KAFKA_CE_HEADERS } from "../../src/message/kafka/headers";
|
import { KAFKA_CE_HEADERS } from "../../src/message/kafka/headers";
|
||||||
|
@ -43,7 +43,7 @@ const imageData = new Uint32Array(fs.readFileSync(path.join(process.cwd(), "test
|
||||||
const image_base64 = asBase64(imageData);
|
const image_base64 = asBase64(imageData);
|
||||||
|
|
||||||
const fixture = new CloudEvent({
|
const fixture = new CloudEvent({
|
||||||
specversion: V1,
|
specversion: Version.V1,
|
||||||
id,
|
id,
|
||||||
type,
|
type,
|
||||||
source,
|
source,
|
||||||
|
@ -131,7 +131,7 @@ describe("Kafka transport", () => {
|
||||||
expect(event.LUNCH).to.equal("tacos");
|
expect(event.LUNCH).to.equal("tacos");
|
||||||
expect(function () {
|
expect(function () {
|
||||||
event.validate();
|
event.validate();
|
||||||
}).to.throw("invalid attribute name: \"LUNCH\"");
|
}).to.throw("invalid attribute name: LUNCH");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Can detect CloudEvent binary Messages with weird versions", () => {
|
it("Can detect CloudEvent binary Messages with weird versions", () => {
|
||||||
|
@ -233,7 +233,7 @@ describe("Kafka transport", () => {
|
||||||
expect(message.body).to.equal(data);
|
expect(message.body).to.equal(data);
|
||||||
// validate all headers
|
// validate all headers
|
||||||
expect(message.headers[CONSTANTS.HEADER_CONTENT_TYPE]).to.equal(datacontenttype);
|
expect(message.headers[CONSTANTS.HEADER_CONTENT_TYPE]).to.equal(datacontenttype);
|
||||||
expect(message.headers[KAFKA_CE_HEADERS.SPEC_VERSION]).to.equal(V1);
|
expect(message.headers[KAFKA_CE_HEADERS.SPEC_VERSION]).to.equal(Version.V1);
|
||||||
expect(message.headers[KAFKA_CE_HEADERS.ID]).to.equal(id);
|
expect(message.headers[KAFKA_CE_HEADERS.ID]).to.equal(id);
|
||||||
expect(message.headers[KAFKA_CE_HEADERS.TYPE]).to.equal(type);
|
expect(message.headers[KAFKA_CE_HEADERS.TYPE]).to.equal(type);
|
||||||
expect(message.headers[KAFKA_CE_HEADERS.SOURCE]).to.equal(source);
|
expect(message.headers[KAFKA_CE_HEADERS.SOURCE]).to.equal(source);
|
||||||
|
@ -249,7 +249,7 @@ describe("Kafka transport", () => {
|
||||||
expect(message.headers[CONSTANTS.HEADER_CONTENT_TYPE]).to.equal(CONSTANTS.DEFAULT_CE_CONTENT_TYPE);
|
expect(message.headers[CONSTANTS.HEADER_CONTENT_TYPE]).to.equal(CONSTANTS.DEFAULT_CE_CONTENT_TYPE);
|
||||||
// Parse the message body as JSON, then validate the attributes
|
// Parse the message body as JSON, then validate the attributes
|
||||||
const body = JSON.parse(message.body as string);
|
const body = JSON.parse(message.body as string);
|
||||||
expect(body[CONSTANTS.CE_ATTRIBUTES.SPEC_VERSION]).to.equal(V1);
|
expect(body[CONSTANTS.CE_ATTRIBUTES.SPEC_VERSION]).to.equal(Version.V1);
|
||||||
expect(body[CONSTANTS.CE_ATTRIBUTES.ID]).to.equal(id);
|
expect(body[CONSTANTS.CE_ATTRIBUTES.ID]).to.equal(id);
|
||||||
expect(body[CONSTANTS.CE_ATTRIBUTES.TYPE]).to.equal(type);
|
expect(body[CONSTANTS.CE_ATTRIBUTES.TYPE]).to.equal(type);
|
||||||
expect(body[CONSTANTS.CE_ATTRIBUTES.SOURCE]).to.equal(source);
|
expect(body[CONSTANTS.CE_ATTRIBUTES.SOURCE]).to.equal(source);
|
||||||
|
|
|
@ -8,7 +8,7 @@ import fs from "fs";
|
||||||
|
|
||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
import { IncomingHttpHeaders } from "http";
|
import { IncomingHttpHeaders } from "http";
|
||||||
import { CloudEvent, CONSTANTS, V1, V03 } from "../../src";
|
import { CloudEvent, CONSTANTS, Version } from "../../src";
|
||||||
import { asBase64 } from "../../src/event/validation";
|
import { asBase64 } from "../../src/event/validation";
|
||||||
import { Message, HTTP } from "../../src/message";
|
import { Message, HTTP } from "../../src/message";
|
||||||
|
|
||||||
|
@ -41,60 +41,6 @@ const imageData = new Uint32Array(fs.readFileSync(path.join(process.cwd(), "test
|
||||||
const image_base64 = asBase64(imageData);
|
const image_base64 = asBase64(imageData);
|
||||||
|
|
||||||
describe("HTTP transport", () => {
|
describe("HTTP transport", () => {
|
||||||
it("validates extension attribute names for incoming messages", () => {
|
|
||||||
// create a new Message
|
|
||||||
const msg: Message = {
|
|
||||||
headers: {
|
|
||||||
"ce-id": "213",
|
|
||||||
"ce-source": "test",
|
|
||||||
"ce-type": "test",
|
|
||||||
"ce-bad-extension": "value"
|
|
||||||
},
|
|
||||||
body: undefined
|
|
||||||
};
|
|
||||||
const evt = HTTP.toEvent(msg) as CloudEvent;
|
|
||||||
expect(() => evt.validate()).to.throw(TypeError);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Includes extensions in binary mode when type is 'boolean' with a false value", () => {
|
|
||||||
const evt = new CloudEvent({ source: "test", type: "test", extboolean: false });
|
|
||||||
expect(evt.hasOwnProperty("extboolean")).to.equal(true);
|
|
||||||
expect(evt["extboolean"]).to.equal(false);
|
|
||||||
const message = HTTP.binary(evt);
|
|
||||||
expect(message.headers.hasOwnProperty("ce-extboolean")).to.equal(true);
|
|
||||||
expect(message.headers["ce-extboolean"]).to.equal(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Includes extensions in structured when type is 'boolean' with a false value", () => {
|
|
||||||
const evt = new CloudEvent({ source: "test", type: "test", extboolean: false });
|
|
||||||
expect(evt.hasOwnProperty("extboolean")).to.equal(true);
|
|
||||||
expect(evt["extboolean"]).to.equal(false);
|
|
||||||
const message = HTTP.structured(evt);
|
|
||||||
const body = JSON.parse(message.body as string);
|
|
||||||
expect(body.hasOwnProperty("extboolean")).to.equal(true);
|
|
||||||
expect(body.extboolean).to.equal(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Handles big integers in structured mode", () => {
|
|
||||||
process.env[CONSTANTS.USE_BIG_INT_ENV] = "true";
|
|
||||||
const ce = HTTP.toEvent({
|
|
||||||
headers: { "content-type": "application/cloudevents+json" },
|
|
||||||
body: `{"data": 1524831183200260097}`
|
|
||||||
}) as CloudEvent;
|
|
||||||
expect(ce.data).to.equal(1524831183200260097n);
|
|
||||||
process.env[CONSTANTS.USE_BIG_INT_ENV] = undefined;
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Handles big integers in binary mode", () => {
|
|
||||||
process.env[CONSTANTS.USE_BIG_INT_ENV] = "true";
|
|
||||||
const ce = HTTP.toEvent({
|
|
||||||
headers: { "content-type": "application/json", "ce-id": "1234" },
|
|
||||||
body: `{"data": 1524831183200260097}`
|
|
||||||
}) as CloudEvent<Record<string, never>>;
|
|
||||||
expect((ce.data as Record<string, never>).data).to.equal(1524831183200260097n);
|
|
||||||
process.env[CONSTANTS.USE_BIG_INT_ENV] = undefined;
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Handles events with no content-type and no datacontenttype", () => {
|
it("Handles events with no content-type and no datacontenttype", () => {
|
||||||
const body = "{Something[Not:valid}JSON";
|
const body = "{Something[Not:valid}JSON";
|
||||||
const message: Message<undefined> = {
|
const message: Message<undefined> = {
|
||||||
|
@ -154,7 +100,7 @@ describe("HTTP transport", () => {
|
||||||
[CONSTANTS.CE_HEADERS.ID]: "1234",
|
[CONSTANTS.CE_HEADERS.ID]: "1234",
|
||||||
[CONSTANTS.CE_HEADERS.SOURCE]: "test",
|
[CONSTANTS.CE_HEADERS.SOURCE]: "test",
|
||||||
[CONSTANTS.CE_HEADERS.TYPE]: "test.event",
|
[CONSTANTS.CE_HEADERS.TYPE]: "test.event",
|
||||||
[CONSTANTS.CE_HEADERS.SPEC_VERSION]: V1,
|
[CONSTANTS.CE_HEADERS.SPEC_VERSION]: Version.V1,
|
||||||
"ce-LUNCH": "tacos",
|
"ce-LUNCH": "tacos",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -163,7 +109,7 @@ describe("HTTP transport", () => {
|
||||||
expect(event.LUNCH).to.equal("tacos");
|
expect(event.LUNCH).to.equal("tacos");
|
||||||
expect(function () {
|
expect(function () {
|
||||||
event.validate();
|
event.validate();
|
||||||
}).to.throw("invalid attribute name: \"LUNCH\"");
|
}).to.throw("invalid attribute name: LUNCH");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Can detect CloudEvent binary Messages with weird versions", () => {
|
it("Can detect CloudEvent binary Messages with weird versions", () => {
|
||||||
|
@ -237,7 +183,7 @@ describe("HTTP transport", () => {
|
||||||
id,
|
id,
|
||||||
type,
|
type,
|
||||||
source,
|
source,
|
||||||
specversion: V1,
|
specversion: Version.V1,
|
||||||
data: { lunch: "tacos" },
|
data: { lunch: "tacos" },
|
||||||
});
|
});
|
||||||
const message: Message<undefined> = {
|
const message: Message<undefined> = {
|
||||||
|
@ -250,7 +196,7 @@ describe("HTTP transport", () => {
|
||||||
|
|
||||||
describe("Specification version V1", () => {
|
describe("Specification version V1", () => {
|
||||||
const fixture = new CloudEvent({
|
const fixture = new CloudEvent({
|
||||||
specversion: V1,
|
specversion: Version.V1,
|
||||||
id,
|
id,
|
||||||
type,
|
type,
|
||||||
source,
|
source,
|
||||||
|
@ -268,7 +214,7 @@ describe("HTTP transport", () => {
|
||||||
expect(message.body).to.equal(JSON.stringify(data));
|
expect(message.body).to.equal(JSON.stringify(data));
|
||||||
// validate all headers
|
// validate all headers
|
||||||
expect(message.headers[CONSTANTS.HEADER_CONTENT_TYPE]).to.equal(datacontenttype);
|
expect(message.headers[CONSTANTS.HEADER_CONTENT_TYPE]).to.equal(datacontenttype);
|
||||||
expect(message.headers[CONSTANTS.CE_HEADERS.SPEC_VERSION]).to.equal(V1);
|
expect(message.headers[CONSTANTS.CE_HEADERS.SPEC_VERSION]).to.equal(Version.V1);
|
||||||
expect(message.headers[CONSTANTS.CE_HEADERS.ID]).to.equal(id);
|
expect(message.headers[CONSTANTS.CE_HEADERS.ID]).to.equal(id);
|
||||||
expect(message.headers[CONSTANTS.CE_HEADERS.TYPE]).to.equal(type);
|
expect(message.headers[CONSTANTS.CE_HEADERS.TYPE]).to.equal(type);
|
||||||
expect(message.headers[CONSTANTS.CE_HEADERS.SOURCE]).to.equal(source);
|
expect(message.headers[CONSTANTS.CE_HEADERS.SOURCE]).to.equal(source);
|
||||||
|
@ -284,7 +230,7 @@ describe("HTTP transport", () => {
|
||||||
expect(message.headers[CONSTANTS.HEADER_CONTENT_TYPE]).to.equal(CONSTANTS.DEFAULT_CE_CONTENT_TYPE);
|
expect(message.headers[CONSTANTS.HEADER_CONTENT_TYPE]).to.equal(CONSTANTS.DEFAULT_CE_CONTENT_TYPE);
|
||||||
// Parse the message body as JSON, then validate the attributes
|
// Parse the message body as JSON, then validate the attributes
|
||||||
const body = JSON.parse(message.body as string);
|
const body = JSON.parse(message.body as string);
|
||||||
expect(body[CONSTANTS.CE_ATTRIBUTES.SPEC_VERSION]).to.equal(V1);
|
expect(body[CONSTANTS.CE_ATTRIBUTES.SPEC_VERSION]).to.equal(Version.V1);
|
||||||
expect(body[CONSTANTS.CE_ATTRIBUTES.ID]).to.equal(id);
|
expect(body[CONSTANTS.CE_ATTRIBUTES.ID]).to.equal(id);
|
||||||
expect(body[CONSTANTS.CE_ATTRIBUTES.TYPE]).to.equal(type);
|
expect(body[CONSTANTS.CE_ATTRIBUTES.TYPE]).to.equal(type);
|
||||||
expect(body[CONSTANTS.CE_ATTRIBUTES.SOURCE]).to.equal(source);
|
expect(body[CONSTANTS.CE_ATTRIBUTES.SOURCE]).to.equal(source);
|
||||||
|
@ -353,7 +299,7 @@ describe("HTTP transport", () => {
|
||||||
|
|
||||||
describe("Specification version V03", () => {
|
describe("Specification version V03", () => {
|
||||||
const fixture = new CloudEvent({
|
const fixture = new CloudEvent({
|
||||||
specversion: V03,
|
specversion: Version.V03,
|
||||||
id,
|
id,
|
||||||
type,
|
type,
|
||||||
source,
|
source,
|
||||||
|
@ -371,7 +317,7 @@ describe("HTTP transport", () => {
|
||||||
expect(message.body).to.equal(JSON.stringify(data));
|
expect(message.body).to.equal(JSON.stringify(data));
|
||||||
// validate all headers
|
// validate all headers
|
||||||
expect(message.headers[CONSTANTS.HEADER_CONTENT_TYPE]).to.equal(datacontenttype);
|
expect(message.headers[CONSTANTS.HEADER_CONTENT_TYPE]).to.equal(datacontenttype);
|
||||||
expect(message.headers[CONSTANTS.CE_HEADERS.SPEC_VERSION]).to.equal(V03);
|
expect(message.headers[CONSTANTS.CE_HEADERS.SPEC_VERSION]).to.equal(Version.V03);
|
||||||
expect(message.headers[CONSTANTS.CE_HEADERS.ID]).to.equal(id);
|
expect(message.headers[CONSTANTS.CE_HEADERS.ID]).to.equal(id);
|
||||||
expect(message.headers[CONSTANTS.CE_HEADERS.TYPE]).to.equal(type);
|
expect(message.headers[CONSTANTS.CE_HEADERS.TYPE]).to.equal(type);
|
||||||
expect(message.headers[CONSTANTS.CE_HEADERS.SOURCE]).to.equal(source);
|
expect(message.headers[CONSTANTS.CE_HEADERS.SOURCE]).to.equal(source);
|
||||||
|
@ -387,7 +333,7 @@ describe("HTTP transport", () => {
|
||||||
expect(message.headers[CONSTANTS.HEADER_CONTENT_TYPE]).to.equal(CONSTANTS.DEFAULT_CE_CONTENT_TYPE);
|
expect(message.headers[CONSTANTS.HEADER_CONTENT_TYPE]).to.equal(CONSTANTS.DEFAULT_CE_CONTENT_TYPE);
|
||||||
// Parse the message body as JSON, then validate the attributes
|
// Parse the message body as JSON, then validate the attributes
|
||||||
const body = JSON.parse(message.body as string);
|
const body = JSON.parse(message.body as string);
|
||||||
expect(body[CONSTANTS.CE_ATTRIBUTES.SPEC_VERSION]).to.equal(V03);
|
expect(body[CONSTANTS.CE_ATTRIBUTES.SPEC_VERSION]).to.equal(Version.V03);
|
||||||
expect(body[CONSTANTS.CE_ATTRIBUTES.ID]).to.equal(id);
|
expect(body[CONSTANTS.CE_ATTRIBUTES.ID]).to.equal(id);
|
||||||
expect(body[CONSTANTS.CE_ATTRIBUTES.TYPE]).to.equal(type);
|
expect(body[CONSTANTS.CE_ATTRIBUTES.TYPE]).to.equal(type);
|
||||||
expect(body[CONSTANTS.CE_ATTRIBUTES.SOURCE]).to.equal(source);
|
expect(body[CONSTANTS.CE_ATTRIBUTES.SOURCE]).to.equal(source);
|
||||||
|
|
|
@ -7,7 +7,7 @@ import path from "path";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
|
|
||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
import { CloudEvent, CONSTANTS, V1, Headers } from "../../src";
|
import { CloudEvent, CONSTANTS, Version, Headers } from "../../src";
|
||||||
import { asBase64 } from "../../src/event/validation";
|
import { asBase64 } from "../../src/event/validation";
|
||||||
import { Message, MQTT, MQTTMessage } from "../../src/message";
|
import { Message, MQTT, MQTTMessage } from "../../src/message";
|
||||||
|
|
||||||
|
@ -32,18 +32,18 @@ const ext2Name = "extension2";
|
||||||
const ext2Value = "acme";
|
const ext2Value = "acme";
|
||||||
|
|
||||||
// Binary data as base64
|
// Binary data as base64
|
||||||
const dataBinary = Uint8Array.from(JSON.stringify(data), (c) => c.codePointAt(0) as number);
|
const dataBinary = Uint32Array.from(JSON.stringify(data), (c) => c.codePointAt(0) as number);
|
||||||
const data_base64 = asBase64(dataBinary);
|
const data_base64 = asBase64(dataBinary);
|
||||||
|
|
||||||
// Since the above is a special case (string as binary), let's test
|
// Since the above is a special case (string as binary), let's test
|
||||||
// with a real binary file one is likely to encounter in the wild
|
// with a real binary file one is likely to encounter in the wild
|
||||||
const imageData = new Uint8Array(fs.readFileSync(path.join(process.cwd(), "test", "integration", "ce.png")));
|
const imageData = new Uint32Array(fs.readFileSync(path.join(process.cwd(), "test", "integration", "ce.png")));
|
||||||
const image_base64 = asBase64(imageData);
|
const image_base64 = asBase64(imageData);
|
||||||
|
|
||||||
const PUBLISH = {"Content Type": "application/json; charset=utf-8"};
|
const PUBLISH = {"Content Type": "application/json; charset=utf-8"};
|
||||||
|
|
||||||
const fixture = new CloudEvent({
|
const fixture = new CloudEvent({
|
||||||
specversion: V1,
|
specversion: Version.V1,
|
||||||
id,
|
id,
|
||||||
type,
|
type,
|
||||||
source,
|
source,
|
||||||
|
@ -134,7 +134,7 @@ describe("MQTT transport", () => {
|
||||||
expect(event.LUNCH).to.equal("tacos");
|
expect(event.LUNCH).to.equal("tacos");
|
||||||
expect(function () {
|
expect(function () {
|
||||||
event.validate();
|
event.validate();
|
||||||
}).to.throw("invalid attribute name: \"LUNCH\"");
|
}).to.throw("invalid attribute name: LUNCH");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Can detect CloudEvent binary Messages with weird versions", () => {
|
it("Can detect CloudEvent binary Messages with weird versions", () => {
|
||||||
|
@ -216,7 +216,7 @@ describe("MQTT transport", () => {
|
||||||
expect(message.body).to.equal(data);
|
expect(message.body).to.equal(data);
|
||||||
// validate all headers
|
// validate all headers
|
||||||
expect(message.headers.datacontenttype).to.equal(datacontenttype);
|
expect(message.headers.datacontenttype).to.equal(datacontenttype);
|
||||||
expect(message.headers.specversion).to.equal(V1);
|
expect(message.headers.specversion).to.equal(Version.V1);
|
||||||
expect(message.headers.id).to.equal(id);
|
expect(message.headers.id).to.equal(id);
|
||||||
expect(message.headers.type).to.equal(type);
|
expect(message.headers.type).to.equal(type);
|
||||||
expect(message.headers.source).to.equal(source);
|
expect(message.headers.source).to.equal(source);
|
||||||
|
@ -232,7 +232,7 @@ describe("MQTT transport", () => {
|
||||||
expect(message.body).to.equal(data);
|
expect(message.body).to.equal(data);
|
||||||
// validate all headers
|
// validate all headers
|
||||||
expect(message["User Properties"]?.datacontenttype).to.equal(datacontenttype);
|
expect(message["User Properties"]?.datacontenttype).to.equal(datacontenttype);
|
||||||
expect(message["User Properties"]?.specversion).to.equal(V1);
|
expect(message["User Properties"]?.specversion).to.equal(Version.V1);
|
||||||
expect(message["User Properties"]?.id).to.equal(id);
|
expect(message["User Properties"]?.id).to.equal(id);
|
||||||
expect(message["User Properties"]?.type).to.equal(type);
|
expect(message["User Properties"]?.type).to.equal(type);
|
||||||
expect(message["User Properties"]?.source).to.equal(source);
|
expect(message["User Properties"]?.source).to.equal(source);
|
||||||
|
@ -249,7 +249,7 @@ describe("MQTT transport", () => {
|
||||||
expect(message.body).to.deep.equal(message.payload);
|
expect(message.body).to.deep.equal(message.payload);
|
||||||
expect(message.payload).to.deep.equal(fixture.toJSON());
|
expect(message.payload).to.deep.equal(fixture.toJSON());
|
||||||
const body = message.body as Record<string, string>;
|
const body = message.body as Record<string, string>;
|
||||||
expect(body[CONSTANTS.CE_ATTRIBUTES.SPEC_VERSION]).to.equal(V1);
|
expect(body[CONSTANTS.CE_ATTRIBUTES.SPEC_VERSION]).to.equal(Version.V1);
|
||||||
expect(body[CONSTANTS.CE_ATTRIBUTES.ID]).to.equal(id);
|
expect(body[CONSTANTS.CE_ATTRIBUTES.ID]).to.equal(id);
|
||||||
expect(body[CONSTANTS.CE_ATTRIBUTES.TYPE]).to.equal(type);
|
expect(body[CONSTANTS.CE_ATTRIBUTES.TYPE]).to.equal(type);
|
||||||
expect(body[CONSTANTS.CE_ATTRIBUTES.SOURCE]).to.equal(source);
|
expect(body[CONSTANTS.CE_ATTRIBUTES.SOURCE]).to.equal(source);
|
||||||
|
@ -281,14 +281,14 @@ describe("MQTT transport", () => {
|
||||||
|
|
||||||
it("Converts base64 encoded data to binary when deserializing structured messages", () => {
|
it("Converts base64 encoded data to binary when deserializing structured messages", () => {
|
||||||
const message = MQTT.structured(fixture.cloneWith({ data: imageData, datacontenttype: "image/png" }));
|
const message = MQTT.structured(fixture.cloneWith({ data: imageData, datacontenttype: "image/png" }));
|
||||||
const eventDeserialized = MQTT.toEvent(message) as CloudEvent<Uint8Array>;
|
const eventDeserialized = MQTT.toEvent(message) as CloudEvent<Uint32Array>;
|
||||||
expect(eventDeserialized.data).to.deep.equal(imageData);
|
expect(eventDeserialized.data).to.deep.equal(imageData);
|
||||||
expect(eventDeserialized.data_base64).to.equal(image_base64);
|
expect(eventDeserialized.data_base64).to.equal(image_base64);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Converts base64 encoded data to binary when deserializing binary messages", () => {
|
it("Converts base64 encoded data to binary when deserializing binary messages", () => {
|
||||||
const message = MQTT.binary(fixture.cloneWith({ data: imageData, datacontenttype: "image/png" }));
|
const message = MQTT.binary(fixture.cloneWith({ data: imageData, datacontenttype: "image/png" }));
|
||||||
const eventDeserialized = MQTT.toEvent(message) as CloudEvent<Uint8Array>;
|
const eventDeserialized = MQTT.toEvent(message) as CloudEvent<Uint32Array>;
|
||||||
expect(eventDeserialized.data).to.deep.equal(imageData);
|
expect(eventDeserialized.data).to.deep.equal(imageData);
|
||||||
expect(eventDeserialized.data_base64).to.equal(image_base64);
|
expect(eventDeserialized.data_base64).to.equal(image_base64);
|
||||||
});
|
});
|
||||||
|
@ -302,7 +302,7 @@ describe("MQTT transport", () => {
|
||||||
|
|
||||||
it("Does not parse binary data from binary messages with content type application/json", () => {
|
it("Does not parse binary data from binary messages with content type application/json", () => {
|
||||||
const message = MQTT.binary(fixture.cloneWith({ data: dataBinary }));
|
const message = MQTT.binary(fixture.cloneWith({ data: dataBinary }));
|
||||||
const eventDeserialized = MQTT.toEvent(message) as CloudEvent<Uint8Array>;
|
const eventDeserialized = MQTT.toEvent(message) as CloudEvent<Uint32Array>;
|
||||||
expect(eventDeserialized.data).to.deep.equal(dataBinary);
|
expect(eventDeserialized.data).to.deep.equal(dataBinary);
|
||||||
expect(eventDeserialized.data_base64).to.equal(data_base64);
|
expect(eventDeserialized.data_base64).to.equal(data_base64);
|
||||||
});
|
});
|
||||||
|
|
|
@ -56,7 +56,7 @@ describe("JSON Event Format Parser", () => {
|
||||||
const parser = new Parser();
|
const parser = new Parser();
|
||||||
|
|
||||||
// TODO: Should the parser catch the SyntaxError and re-throw a ValidationError?
|
// TODO: Should the parser catch the SyntaxError and re-throw a ValidationError?
|
||||||
expect(parser.parse.bind(parser, payload)).to.throw(SyntaxError);
|
expect(parser.parse.bind(parser, payload)).to.throw(SyntaxError, "Unexpected token g in JSON at position 1");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Accepts a string as valid JSON", () => {
|
it("Accepts a string as valid JSON", () => {
|
||||||
|
|
|
@ -5,13 +5,13 @@
|
||||||
|
|
||||||
import "mocha";
|
import "mocha";
|
||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
import { CloudEvent, CloudEventV1, V1, V03 } from "../../src";
|
import { CloudEvent, CloudEventV1, Version } from "../../src";
|
||||||
|
|
||||||
const fixture: CloudEventV1<undefined> = {
|
const fixture: CloudEventV1<undefined> = {
|
||||||
id: "123",
|
id: "123",
|
||||||
type: "org.cloudevents.test",
|
type: "org.cloudevents.test",
|
||||||
source: "http://cloudevents.io",
|
source: "http://cloudevents.io",
|
||||||
specversion: V1,
|
specversion: Version.V1,
|
||||||
};
|
};
|
||||||
|
|
||||||
describe("The SDK Requirements", () => {
|
describe("The SDK Requirements", () => {
|
||||||
|
@ -25,15 +25,15 @@ describe("The SDK Requirements", () => {
|
||||||
expect(
|
expect(
|
||||||
new CloudEvent({
|
new CloudEvent({
|
||||||
...fixture,
|
...fixture,
|
||||||
specversion: V03,
|
specversion: Version.V03,
|
||||||
}, false).specversion,
|
}, false).specversion,
|
||||||
).to.equal(V03);
|
).to.equal(Version.V03);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("v1.0", () => {
|
describe("v1.0", () => {
|
||||||
it("should create an event using the right spec version", () => {
|
it("should create an event using the right spec version", () => {
|
||||||
expect(new CloudEvent(fixture).specversion).to.equal(V1);
|
expect(new CloudEvent(fixture).specversion).to.equal(Version.V1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
import "mocha";
|
import "mocha";
|
||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
import { CloudEvent, V1, ValidationError } from "../../src";
|
import { CloudEvent, Version, ValidationError } from "../../src";
|
||||||
import { asBase64 } from "../../src/event/validation";
|
import { asBase64 } from "../../src/event/validation";
|
||||||
import Constants from "../../src/constants";
|
import Constants from "../../src/constants";
|
||||||
|
|
||||||
|
@ -19,8 +19,8 @@ const data = {
|
||||||
};
|
};
|
||||||
const subject = "subject-x0";
|
const subject = "subject-x0";
|
||||||
|
|
||||||
const cloudevent = new CloudEvent({
|
let cloudevent = new CloudEvent({
|
||||||
specversion: V1,
|
specversion: Version.V1,
|
||||||
id,
|
id,
|
||||||
source,
|
source,
|
||||||
type,
|
type,
|
||||||
|
@ -99,16 +99,6 @@ describe("CloudEvents Spec v1.0", () => {
|
||||||
it("should be ok when the type is an string converted from an object", () => {
|
it("should be ok when the type is an string converted from an object", () => {
|
||||||
expect(cloudevent.cloneWith({ objectextension: JSON.stringify({ some: "object" }) }).validate()).to.equal(true);
|
expect(cloudevent.cloneWith({ objectextension: JSON.stringify({ some: "object" }) }).validate()).to.equal(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should only allow a-z|0-9 in the attribute names", () => {
|
|
||||||
const testCases = [
|
|
||||||
"an extension", "an_extension", "an-extension", "an.extension", "an+extension"
|
|
||||||
];
|
|
||||||
testCases.forEach((testCase) => {
|
|
||||||
const evt = cloudevent.cloneWith({ [testCase]: "a value"}, false);
|
|
||||||
expect(() => evt.validate()).to.throw(ValidationError);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("The Constraints check", () => {
|
describe("The Constraints check", () => {
|
||||||
|
@ -120,8 +110,8 @@ describe("CloudEvents Spec v1.0", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("defaut ID create when an empty string", () => {
|
it("defaut ID create when an empty string", () => {
|
||||||
const testEvent = cloudevent.cloneWith({ id: "" });
|
cloudevent = cloudevent.cloneWith({ id: "" });
|
||||||
expect(testEvent.id.length).to.be.greaterThan(0);
|
expect(cloudevent.id.length).to.be.greaterThan(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -160,11 +150,11 @@ describe("CloudEvents Spec v1.0", () => {
|
||||||
describe("'time'", () => {
|
describe("'time'", () => {
|
||||||
it("must adhere to the format specified in RFC 3339", () => {
|
it("must adhere to the format specified in RFC 3339", () => {
|
||||||
const d = new Date();
|
const d = new Date();
|
||||||
const testEvent = cloudevent.cloneWith({ time: d.toString() }, false);
|
cloudevent = cloudevent.cloneWith({ time: d.toString() }, false);
|
||||||
// ensure that we always get back the same thing we passed in
|
// ensure that we always get back the same thing we passed in
|
||||||
expect(testEvent.time).to.equal(d.toString());
|
expect(cloudevent.time).to.equal(d.toString());
|
||||||
// ensure that when stringified, the timestamp is in RFC3339 format
|
// ensure that when stringified, the timestamp is in RFC3339 format
|
||||||
expect(JSON.parse(JSON.stringify(testEvent)).time).to.equal(new Date(d.toString()).toISOString());
|
expect(JSON.parse(JSON.stringify(cloudevent)).time).to.equal(new Date(d.toString()).toISOString());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -183,60 +173,14 @@ describe("CloudEvents Spec v1.0", () => {
|
||||||
expect(typeof ce.data).to.equal("string");
|
expect(typeof ce.data).to.equal("string");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should be ok when type is 'Uint32Array' for 'Binary'", () => {
|
||||||
const dataString = ")(*~^my data for ce#@#$%";
|
const dataString = ")(*~^my data for ce#@#$%";
|
||||||
const testCases = [
|
|
||||||
{
|
|
||||||
type: Int8Array,
|
|
||||||
data: Int8Array.from(dataString, (c) => c.codePointAt(0) as number),
|
|
||||||
expected: asBase64(Int8Array.from(dataString, (c) => c.codePointAt(0) as number))
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: Uint8Array,
|
|
||||||
data: Uint8Array.from(dataString, (c) => c.codePointAt(0) as number),
|
|
||||||
expected: asBase64(Uint8Array.from(dataString, (c) => c.codePointAt(0) as number))
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: Int16Array,
|
|
||||||
data: Int16Array.from(dataString, (c) => c.codePointAt(0) as number),
|
|
||||||
expected: asBase64(Int16Array.from(dataString, (c) => c.codePointAt(0) as number))
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: Uint16Array,
|
|
||||||
data: Uint16Array.from(dataString, (c) => c.codePointAt(0) as number),
|
|
||||||
expected: asBase64(Uint16Array.from(dataString, (c) => c.codePointAt(0) as number))
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: Int32Array,
|
|
||||||
data: Int32Array.from(dataString, (c) => c.codePointAt(0) as number),
|
|
||||||
expected: asBase64(Int32Array.from(dataString, (c) => c.codePointAt(0) as number))
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: Uint32Array,
|
|
||||||
data: Uint32Array.from(dataString, (c) => c.codePointAt(0) as number),
|
|
||||||
expected: asBase64(Uint32Array.from(dataString, (c) => c.codePointAt(0) as number))
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: Uint8ClampedArray,
|
|
||||||
data: Uint8ClampedArray.from(dataString, (c) => c.codePointAt(0) as number),
|
|
||||||
expected: asBase64(Uint8ClampedArray.from(dataString, (c) => c.codePointAt(0) as number))
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: Float32Array,
|
|
||||||
data: Float32Array.from(dataString, (c) => c.codePointAt(0) as number),
|
|
||||||
expected: asBase64(Float32Array.from(dataString, (c) => c.codePointAt(0) as number))
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: Float64Array,
|
|
||||||
data: Float64Array.from(dataString, (c) => c.codePointAt(0) as number),
|
|
||||||
expected: asBase64(Float64Array.from(dataString, (c) => c.codePointAt(0) as number))
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
testCases.forEach((test) => {
|
const dataBinary = Uint32Array.from(dataString, (c) => c.codePointAt(0) as number);
|
||||||
it(`should be ok when type is '${test.type.name}' for 'Binary'`, () => {
|
const expected = asBase64(dataBinary);
|
||||||
const ce = cloudevent.cloneWith({ datacontenttype: "text/plain", data: test.data });
|
|
||||||
expect(ce.data_base64).to.equal(test.expected);
|
const ce = cloudevent.cloneWith({ datacontenttype: "text/plain", data: dataBinary });
|
||||||
});
|
expect(ce.data_base64).to.equal(expected);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ES2020", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
|
"target": "ES2016", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
|
||||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
|
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
|
||||||
"allowJs": true, /* Allow javascript files to be compiled. */
|
"allowJs": true, /* Allow javascript files to be compiled. */
|
||||||
"checkJs": false, /* Report errors in .js files. */
|
"checkJs": false, /* Report errors in .js files. */
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const webpack = require("webpack");
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
entry: {
|
entry: {
|
||||||
|
@ -12,11 +11,6 @@ module.exports = {
|
||||||
https: false
|
https: false
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [
|
|
||||||
new webpack.ProvidePlugin({
|
|
||||||
process: 'process/browser'
|
|
||||||
})
|
|
||||||
],
|
|
||||||
output: {
|
output: {
|
||||||
path: path.resolve(__dirname, "bundles"),
|
path: path.resolve(__dirname, "bundles"),
|
||||||
filename: "[name].js",
|
filename: "[name].js",
|
||||||
|
|
Loading…
Reference in New Issue