Skip to content

Commit

Permalink
[core] Introducing core-websockets
Browse files Browse the repository at this point in the history
  • Loading branch information
deyaaeldeen committed Jan 14, 2025
1 parent d55186f commit b169150
Show file tree
Hide file tree
Showing 18 changed files with 1,968 additions and 682 deletions.
1,594 changes: 912 additions & 682 deletions common/config/rush/pnpm-lock.yaml

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions rush.json
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,11 @@
"projectFolder": "sdk/core/core-util",
"versionPolicyName": "core"
},
{
"packageName": "@azure/core-websockets",
"projectFolder": "sdk/core/core-websockets",
"versionPolicyName": "core"
},
{
"packageName": "@azure/core-xml",
"projectFolder": "sdk/core/core-xml",
Expand Down
40 changes: 40 additions & 0 deletions sdk/core/core-websockets/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Azure Core WebSockets library for JavaScript

This is an implementation of web sockets which work in the browser and Node.js. This library is primarily intended to be used in code generated by [AutoRest](https://github.com/Azure/Autorest) and [`autorest.typescript`](https://github.com/Azure/autorest.typescript).

## Getting started

### Requirements

### Currently supported environments

- [LTS versions of Node.js](https://github.com/nodejs/release#release-schedule)
- Latest versions of Safari, Chrome, Edge, and Firefox.

See our [support policy](https://github.com/Azure/azure-sdk-for-js/blob/main/SUPPORT.md) for more details.

### Installation

This package is primarily used in generated code and not meant to be consumed directly by end users.

## Key concepts

UNDER CONSTRUCTION

## Examples

Examples can be found in the `samples` folder.

## Next steps

You can build and run the tests locally by executing `rushx test`. Explore the `test` folder to see advanced usage and behavior of the public classes.

## Troubleshooting

If you run into issues while using this library, please feel free to [file an issue](https://github.com/Azure/azure-sdk-for-js/issues/new).

## Contributing

If you'd like to contribute to this library, please read the [contributing guide](https://github.com/Azure/azure-sdk-for-js/blob/main/CONTRIBUTING.md) to learn more about how to build and test the code.

![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-js%2Fsdk%2Fcore%2Fcore-rest-pipeline%2FREADME.png)
18 changes: 18 additions & 0 deletions sdk/core/core-websockets/api-extractor.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
"mainEntryPointFilePath": "./dist/esm/index.d.ts",
"docModel": { "enabled": true },
"apiReport": { "enabled": true, "reportFolder": "./review" },
"dtsRollup": {
"enabled": true,
"untrimmedFilePath": "",
"publicTrimmedFilePath": "./dist/core-websockets.d.ts"
},
"messages": {
"tsdocMessageReporting": { "default": { "logLevel": "none" } },
"extractorMessageReporting": {
"ae-missing-release-tag": { "logLevel": "none" },
"ae-unresolved-link": { "logLevel": "none" }
}
}
}
131 changes: 131 additions & 0 deletions sdk/core/core-websockets/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
{
"name": "@azure/core-websockets",
"version": "1.0.0-beta.1",
"description": "Implementation of a websockets client for Node.js and browsers.",
"sdk-type": "client",
"type": "module",
"main": "./dist/commonjs/index.js",
"types": "./dist/commonjs/index.d.ts",
"browser": "./dist/browser/index.js",
"react-native": "./dist/react-native/index.js",
"exports": {
"./package.json": "./package.json",
".": {
"browser": {
"types": "./dist/browser/index.d.ts",
"default": "./dist/browser/index.js"
},
"react-native": {
"types": "./dist/react-native/index.d.ts",
"default": "./dist/react-native/index.js"
},
"import": {
"types": "./dist/esm/index.d.ts",
"default": "./dist/esm/index.js"
},
"require": {
"types": "./dist/commonjs/index.d.ts",
"default": "./dist/commonjs/index.js"
}
}
},
"files": [
"dist/",
"README.md",
"LICENSE"
],
"repository": "github:Azure/azure-sdk-for-js",
"engines": {
"node": ">=18.0.0"
},
"keywords": [
"node",
"azure",
"cloud",
"typescript",
"browser",
"isomorphic"
],
"author": "Microsoft Corporation",
"license": "MIT",
"bugs": {
"url": "https://github.com/Azure/azure-sdk-for-js/issues"
},
"homepage": "https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-sse/README.md",
"sideEffects": false,
"prettier": "@azure/eslint-plugin-azure-sdk/prettier.json",
"scripts": {
"build": "npm run clean && dev-tool run build-package && dev-tool run extract-api",
"build:samples": "echo Obsolete",
"build:test": "echo skipped. actual commands inlined in browser test scripts",
"check-format": "dev-tool run vendored prettier --list-different --config ../../../.prettierrc.json --ignore-path ../../../.prettierignore \"src/**/*.{ts,cts,mts}\" \"test/**/*.{ts,cts,mts}\" \"*.{js,cjs,mjs,json}\"",
"clean": "dev-tool run vendored rimraf --glob dist dist-* temp types *.tgz *.log",
"execute:samples": "dev-tool samples run samples-dev",
"extract-api": "dev-tool run build-package && dev-tool run extract-api",
"format": "dev-tool run vendored prettier --write --config ../../../.prettierrc.json --ignore-path ../../../.prettierignore \"src/**/*.{ts,cts,mts}\" \"test/**/*.{ts,cts,mts}\" \"samples-dev/**/*.{ts,cts,mts}\" \"*.{js,cjs,mjs,json}\"",
"integration-test": "npm run integration-test:node && npm run integration-test:browser",
"integration-test:browser": "echo skipped",
"integration-test:node": "echo skipped",
"lint": "eslint README.md package.json api-extractor.json src test",
"lint:fix": "eslint README.md package.json api-extractor.json src test --fix --fix-type [problem,suggestion]",
"pack": "npm pack 2>&1",
"start-server": "tsx test/server/start.mts",
"test": "npm run clean && dev-tool run build-package && npm run unit-test:node && dev-tool run build-test && npm run unit-test:browser && npm run integration-test",
"test:browser": "npm run clean && npm run build && npm run integration-test:browser",
"test:node": "npm run clean && dev-tool run build-package && npm run integration-test:node",
"unit-test": "npm run unit-test:node && npm run unit-test:browser",
"unit-test:browser": "npm run clean && dev-tool run build-package && dev-tool run build-test && dev-tool run test:vitest --no-test-proxy --browser",
"unit-test:node": "dev-tool run test:vitest --no-test-proxy",
"update-snippets": "dev-tool run update-snippets"
},
"devDependencies": {
"@azure-tools/test-utils-vitest": "^1.0.0",
"@azure-tools/vite-plugin-browser-test-map": "^1.0.0",
"@azure/dev-tool": "^1.0.0",
"@azure/eslint-plugin-azure-sdk": "^3.0.0",
"@types/express": "^5.0.0",
"@types/node": "^20.3.0",
"@types/ws": "^8.5.13",
"@vitest/browser": "^2.1.8",
"@vitest/coverage-istanbul": "^2.1.8",
"dotenv": "^16.4.7",
"eslint": "^9.18.0",
"express": "^4.21.2",
"playwright": "^1.49.1",
"typescript": "~5.7.3",
"vitest": "^2.1.8"
},
"dependencies": {
"@azure/core-util": "^1.11.0",
"@azure/logger": "^1.1.4",
"bufferutil": "^4.0.9",
"tslib": "^2.8.1",
"ws": "^8.18.0"
},
"//metadata": {
"sampleConfiguration": {
"disableDocsMs": true,
"productName": "Azure SDK Core",
"productSlugs": [
"azure"
]
}
},
"tshy": {
"exports": {
"./package.json": "./package.json",
".": "./src/index.ts"
},
"dialects": [
"esm",
"commonjs"
],
"esmDialects": [
"browser",
"react-native"
],
"selfLink": false,
"project": "./tsconfig.src.json"
},
"module": "./dist/esm/index.js"
}
107 changes: 107 additions & 0 deletions sdk/core/core-websockets/review/core-websockets.api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
## API Report File for "@azure/core-websockets"

> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts

// @public
export type BufferLike = string | Buffer | DataView | number | ArrayBufferView | Uint8Array | ArrayBuffer | SharedArrayBuffer | readonly any[] | readonly number[] | {
valueOf(): ArrayBuffer;
} | {
valueOf(): SharedArrayBuffer;
} | {
valueOf(): Uint8Array;
} | {
valueOf(): readonly number[];
} | {
valueOf(): string;
} | {
[Symbol.toPrimitive](hint: string): string;
};

// @public
export interface CloseInfo {
code?: string;
reason?: string;
}

// @public
export interface CloseOptions {
abortSignal?: AbortSignal;
info?: CloseInfo;
}

// @public
export interface ConnectionManager<SendDataT, ReceiveDataT> {
close(opts?: CloseOptions): Promise<void>;
isOpen(opts?: IsOpenOptions): Promise<boolean>;
onclose: (fn: (info: CloseInfo) => void) => void;
onerror: (fn: (error: unknown) => void) => void;
onmessage: (fn: (data: ReceiveDataT) => void) => void;
onopen: (fn: () => void) => void;
open(opts?: OpenOptions): Promise<void>;
send(data: SendDataT, opts?: SendOptions): Promise<void>;
shouldReconnect(info: CloseInfo): boolean;
}

// @public
export function createReliableConnectionClient<SendDataT, ReceiveDataT>(client: ConnectionManager<SendDataT, ReceiveDataT>, createOptions?: CreateReliableConnectionOptions): (opts?: ReliableConnectionOptions) => ReliableConnectionClient<SendDataT, ReceiveDataT>;

// @public
export interface CreateReliableConnectionOptions {
isRetryable?: (err: unknown) => boolean;
resolveOnUnsuccessful?: boolean;
}

// @public
export interface IsOpenOptions {
abortSignal?: AbortSignal;
}

// @public
export interface OpenOptions {
abortSignal?: AbortSignal;
}

// @public
export interface ReliableConnectionClient<SendDataT, ReceiveDataT> {
close(opts?: CloseOptions): Promise<void>;
isOpen(opts?: IsOpenOptions): Promise<boolean>;
onclose: (fn: (info: CloseInfo) => void) => void;
onerror: (fn: (error: unknown) => void) => void;
onmessage: (fn: (data: ReceiveDataT) => void) => void;
onopen: (fn: () => void) => void;
open(opts?: OpenOptions): Promise<void>;
send(data: SendDataT, opts?: SendOptions): Promise<void>;
readonly status: Status;
}

// @public
export interface ReliableConnectionOptions {
identifier?: string;
retryOptions?: RetryOptions;
}

// @public
export type RetryMode = "Exponential" | "Fixed";

// @public
export interface RetryOptions {
maxRetries?: number;
maxRetryDelayInMs?: number;
mode?: RetryMode;
retryDelayInMs?: number;
timeoutInMs?: number;
}

// @public
export interface SendOptions {
abortSignal?: AbortSignal;
}

// @public
export type Status = "connecting" | "connected" | "disconnecting" | "disconnected";

// (No @packageDocumentation comment for this package)

```
74 changes: 74 additions & 0 deletions sdk/core/core-websockets/samples-dev/reliableConnectionClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

/**
* @summary demonstrates how to create a WebSocket client using ReliableConnectionClient.
*/
import {
type BufferLike,
createReliableConnectionClient,
type ReliableConnectionOptions,
} from "@azure/core-websockets";
import WebSocket from "ws";

function createClient(url: string, opts?: ReliableConnectionOptions) {
let ws: WebSocket | undefined = undefined;
const clientFactory = createReliableConnectionClient<BufferLike, WebSocket.Data>({
open: async () => {
ws = new WebSocket(url);
},
close: async ({ info } = {}) => {
const { code, reason } = info || {};
ws?.close(code ? parseInt(code) : undefined, reason);
},
send: async (data) => {
ws?.send(data);
},
isOpen: async () => {
return ws?.readyState === WebSocket.OPEN;
},
onclose(fn) {
if (!ws) {
return;
}
ws.onclose = (event) => fn({ code: `${event.code}`, reason: event.reason });
},
onerror(fn) {
if (!ws) {
return;
}
ws.onerror = (event) => fn(event.error);
},
onmessage(fn) {
if (!ws) {
return;
}
ws.onmessage = (event) => fn(event.data);
},
onopen(fn) {
if (!ws) {
return;
}
ws.onopen = fn;
},
shouldReconnect(info) {
return info.code !== "1008";
},
});
return clientFactory(opts);
}

async function main(): Promise<void> {
const client = createClient("wss://echo.websocket.org", { retryOptions: { timeoutInMs: 2000 } });
await client.open();
client.onmessage((data) => {
console.log("received:", data);
});
await client.send("Hello, World!");
await client.close();
}

main().catch((err) => {
console.error("The sample encountered an error:", err);
process.exit(1);
});
6 changes: 6 additions & 0 deletions sdk/core/core-websockets/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

export * from "./reliableConnectionClient.js";
export type { RetryOptions, RetryMode } from "./retry.js";
export type { BufferLike } from "./websockets.js";
Loading

0 comments on commit b169150

Please sign in to comment.