Skip to content

Adopt TypeScript & Refocus Core APIs #158

Open
@viglucci

Description

@viglucci

This issue proposes that an effort should be made to re-write the core set of rsocket-js packages from Flow to TypeScript, with a focus on adopting a "small core" mentality when designing the projects public API.

This issue is to serve as:

  1. Documentation of the proposal that was discussed and decided upon
  2. A means of tracking progress towards implementing the proposal

Motivation

TypeScript in Favor of Flow

TypeScript is a proven solution for authoring JavaScript libraries for use in NodeJs and browser environments, and will provide a number of benefits to the project:

  • Continued development & support from Microsoft
  • Large community adoption
  • Easier and more familiar tooling
  • Types can be published from source without authoring additional @types

In addition to the above, in a recent post on the Flow Type blog, the Flow team described a refocusing of the projects priorities towards Facebook's internal needs. This is a signal that Flow may not be a suitable solution for projects outside of Facebook's internal infrastructure and ecosystem.

Small Core

New APIs and paradigms should be introduced to adopt a "small core" mentality, with core rsocket-js packages providing only the basic building blocks and implementations for the RSocket protocol. APIs should be easily extendable/composable to support additional packages that can later provide functionality outside of implementing the RSocket protocol, for example, an RxJS interface.

This "small core" approach is intended to assist with maintainability of the project, as well as ease of support for satisfying feature requests through extensions and "addon" packages.

Other RSocket implementations, such as RSocket-Swift, have benefited to a degree from this approach.

Serialization and Encoding

In conformance with the "small core" goal of this initiative, support for payload data encoding should be reduced down to transmitting instances of Buffer, rather than supporting a wide variety of data and metadata payload serialization and encodings. This stance is in contrast to the current support provided by @rsocket packages, where support for serializing objects to JSON and other formats is provided by interfaces such as JsonSerializer, and encoding is provided by interfaces such as BufferEncoders.

Support for user friendly translation of objects and other structures to/from JSON and other serialization formats can be accomplished via extension packages, rather than as a core feature of rsocket-js.

Reactive APIs

rsocket-js has historically leveraged a Reactive Streams implementation (rsocket-flowable) both internally, and as its public API. This implementation has historically been published under @rsocekt/rsocket-flowable. Moving forward, rsocket-js will move away from @rsocket/rsocket-flowable as a key feature of its public API, and instead focus on exposing a core set of Stream APIs that satisfy the core requirements of the RSocket protocol, while also promoting composition and extension with other Reactive Streams implementations, such as RxJS and reactive-streams-js.

Interfaces example:

export interface Cancellable {
  cancel(): void;
}

export interface Requestable {
  request(requestN: number): void;
}

export interface OnExtensionSubscriber {
  onExtension(
    extendedType: number,
    content: Buffer | null | undefined,
    canBeIgnored: boolean
  ): void;
}

export interface OnNextSubscriber {
  onNext(payload: Payload, isComplete: boolean): void;
}

export interface OnTerminalSubscriber {
  onError(error: Error): void;
  onComplete(): void;
}

The intention of this change is two fold:

  • Simplify the internal implementation details of the core rsocket-js libraries
  • Allow for consumers and integrators to easily extend rsocket-js with their Reactive Streams implementation of choice

Desired solution

Core RSocket protocol feature support, and APIs implementations needed:

TODO: complete list of necessary core protocol features

Considered alternatives

N/A

Additional context

Major Version Change

Because of the breaking API changes that this effort will introduce, the version of all @rsocket scoped packages who's APIs are modified will be incremented to an initial major version release of 1.0.

Issues & pull requests related to this work should be/are tagged with the 1.0 tag.

Work in progress

Work for this effort is ongoing in the dev branch.

API Example

const connector = new RSocketConnector({
  transport: new TcpClientTransport({
    connectionOptions: {
      host: "127.0.0.1",
      port: 9090,
    },
  }),
});

const rsocket = await connector.bind();

await new Promise((resolve, reject) =>
  rsocket.requestResponse(
    {
      data: Buffer.from("Hello World"),
    },
    {
      onError: (e) => reject(e),
      onNext: (payload, isComplete) => {
        console.log(
          `payload[data: ${payload.data}; metadata: ${payload.metadata}]|${isComplete}`
        );
        resolve(payload);
      },
      onComplete: () => { },
      onExtension: () => { },
      cancel: () => { },
      request: () => { },
    }
  )
);

Metadata

Metadata

Assignees

Labels

1.0Pullrequests & issues related to the Typescript rewrite and 1.0 releaseenhancementSuggests, requests, or implements a feature or enhancement

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions