Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: introduce CloudEventV1 and CloudEventV03 interfaces #194

Merged
merged 7 commits into from
May 29, 2020

Conversation

lance
Copy link
Member

@lance lance commented May 28, 2020

This commit introduces CloudEventV1 and CloudEventV03 TypeScript interfaces. Additionally, it changes all of the user facing API to be .ts instead of .js files. Those are:

  • lib/cloudevent.ts
  • lib/bindings/http/http_receiver.ts
  • lib/bindings/http/http_emitter.ts
  • lib/bindings/http/constants.ts

Usage in JavaScript

The pure JS API has not changed. You still create a CloudEvent like this.

const { CloudEvent } = require('cloudevents-sdk');

const ce = new CloudEvent({
  source: 'a source',
  type: 'type'
});
console.log(ce);
node index.js
CloudEvent {
  spec:
   Spec1 {
     payload:
      { specversion: '1.0',
        id: 'b3b875c3-f7f0-410f-8aca-6ddcc61625b4',
        time: '2020-05-28T20:51:07.033Z',
        source: 'a source',
        type: 'type',
        datacontenttype: undefined,
        data: undefined,
        subject: undefined } },
  formatter: JSONFormatter {},
  extensions: [] }

Usage in TypeScript

This change resolves the auto-completion issue with raw JavaScript objects through the use of the new interfaces.

Example:

import { CloudEvent } from 'cloudevents-sdk';
import { Event } from 'cloudevents-sdk/lib/cloudevent';
import { CloudEventV1 } from 'cloudevents-sdk/lib/v1';
import { CloudEventV1Attributes } from 'cloudevents-sdk/lib/v1';

const ce: CloudEventV1 = {
  specversion: '1.0',
  source: '/some/source',
  type: 'example',
  id: '1234',
};
const event = new CloudEvent(ce);

const ce2: CloudEventV1Attributes = {
  source: '/',
  type: 'example'
};
const event2 = new CloudEvent(ce2);

const event3 = new CloudEvent({
  source: '/',
  type: 'example'
});

const e: Event = {
  source: '/',
  type: 'example'
};
const ce4 = new CloudEvent(e);

Documentation

The existing documentation in ./docs was removed and should replaced with generated
HTML from tsdocs, pending some other method of publishing API documentation. To keep
this commit relatively small and focused on the code, that will come as a separate docs-only PR.

Fixes: #184
Fixes: #188

Signed-off-by: Lance Ball lball@redhat.com

Additionaly, this commit changes all of the user facing API to be `.ts` instead
of `.js` files.

The existing documentation in `./docs` was removed. It should be replaced with generated
HTML from tsdocs, pending some other method of publishing API documentation. That will
come as a separate, docs-only PR.

Fixes: https://github.com/cloudevents/skd-javascript/issues/188

Signed-off-by: Lance Ball <lball@redhat.com>
@lance lance added the type/fix A change that fixes something that is broken label May 28, 2020
@lance lance requested a review from a team May 28, 2020 20:56
@lance lance self-assigned this May 28, 2020
@lance lance requested review from danbev, grant and fabiojose and removed request for a team May 28, 2020 20:57
Signed-off-by: Lance Ball <lball@redhat.com>
Copy link
Member

@grant grant left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool. 1 comment.

tsconfig.json Outdated Show resolved Hide resolved
@lance
Copy link
Member Author

lance commented May 29, 2020

@grant what do you think about the tradeoffs re: auto completion? As this PR stands now, the only way to create a CloudEvent in a TypeScript project is with id and specversion required. Two options to eliminate the requirement that I see. Change the interface or accept any.

Copy link
Member

@grant grant left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TLDR: Create a different interface for the unique constructor required params.

Maybe we can use TypeScript unions to not duplicate TypeScript interfaces.

Example: https://codingblast.com/typescript-union-types-type-guards-type-aliases/

interface CloudEventV1Constructor { ... };
interface CloudEventV1 { ... } | CloudEventV1Constructor;

The easiest solution would be to indicate that id and specversion are optional in the interfaces. But I'm not sure I like doing that, since a cloud event must have these attributes. They are optional in the ctor for the CloudEvent class because they are either generated or have a default value if not provided.

I don't think we should make required CE fields optional if they aren't optional.
For the constructor, we can make them optional by accepting a different interface.

For generated fields like specversion, we could have a constructor that accepts JSON objects that accepts either interface.

One option here would be to make the CloudEvent constructor accept CloudEventV1, CloudEventV03, or any.

How about CloudEventV1Constructor | CloudEventV03Constructor?

In general, it is bad practice to use type any. We should try to keep the usage of this type to a minimum and eventually add a no-any rule to our tsconfig. We do not want to accept a new CloudEvent(1) for example.

test/bindings/http/promiscuous_receiver_test.js Outdated Show resolved Hide resolved
test/bindings/http/receiver_structured_1_test.js Outdated Show resolved Hide resolved
lance added 3 commits May 29, 2020 14:08
Signed-off-by: Lance Ball <lball@redhat.com>
This commit extracts all of the attributes from a `CloudEventVX` that
are not generated by the constructor (id and specversion) into their
own `CloudEventVXAttributes` interface which the `CloudEventVX`
interface now extends. This allows TS devs to optionally provide `id`
and `specversion` with proper autocompletion.

Additionally, I have added a union type, `Event` in `cloudevent.ts` which
represents any of `CloudEventV1`, `CloudEventv03`, `CloudEventV1Attributes`
and `CloudEventV03Attributes`.

Signed-off-by: Lance Ball <lball@redhat.com>
Signed-off-by: Lance Ball <lball@redhat.com>
@lance lance requested a review from grant May 29, 2020 19:43
@lance
Copy link
Member Author

lance commented May 29, 2020

@grant please re-review with these new changes: 26095e7

src/lib/cloudevent.ts Outdated Show resolved Hide resolved
Copy link
Member

@grant grant left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should go with this. There are some nits like no-any but they probably require a bit of work to fix.
Ref: microsoft/TypeScript#1897

src/lib/v1/index.ts Outdated Show resolved Hide resolved
const headers = {};
let headerMap;
if (version === SPEC_V1) {
headerMap = EmitterV1;
} else if (version === SPEC_V03) {
headerMap = EmitterV03;
}
headerMap.forEach((parser, getterName) => {
headerMap.forEach((parser: any, getterName: string) => {
Copy link
Member

@grant grant May 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the type of parser? We probably want to make the Base64Parser and JSONParser extend the same parser class.

We probably don't need classes though, since these parsers should really be methods and simplified.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to open a new issue/pr for this. There are a bunch of changes that still could be done to the codebase to improve it overall - nits like no-any as you mention above as well as some of these bigger style/architecture concerns.

@grant
Copy link
Member

grant commented May 29, 2020

Nice job applying the interface union suggestion @lance. 👍

lance added 2 commits May 29, 2020 17:43
Signed-off-by: Lance Ball <lball@redhat.com>
Signed-off-by: Lance Ball <lball@redhat.com>
@lance
Copy link
Member Author

lance commented May 29, 2020

OK - this is landing! I will cut a 2.0.1 release either over the weekend or on Monday.

@lance lance merged commit a5befbe into cloudevents:master May 29, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type/fix A change that fixes something that is broken
Projects
None yet
2 participants