Skip to content
This repository was archived by the owner on Oct 12, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
81b47d2
Remove ms-rest-azure, add @azure/ms-rest-nodeauth and browserauth
bterlson Feb 9, 2019
19bd8a3
Add browser support
bterlson Feb 12, 2019
9995861
Add rollup configs
bterlson Feb 12, 2019
1d0be5a
Add browser and dist-esm to .gitignore
bterlson Feb 15, 2019
61b73b0
Add options for passing WebSocket constructor and setting WS endpoint
bterlson Feb 15, 2019
8f76557
Add comment with purpose of index.browser.ts stub
bterlson Feb 15, 2019
a171997
Remove @azure/ms-rest-browserauth dependency as it isn't needed for now
bterlson Feb 15, 2019
97ec8f6
Update typescript version
bterlson Feb 15, 2019
c904d84
Fix TS error with an any cast
bterlson Feb 15, 2019
8159dcc
Make tests run properly
bterlson Feb 15, 2019
85fdba0
Fix circular reference
bterlson Mar 8, 2019
0214698
Fix audit warnings (except nyc)
bterlson Mar 8, 2019
adc9eb7
Explicitly import buffer
bterlson Mar 8, 2019
a0a62bd
Add shim for process.env
bterlson Mar 8, 2019
a6a0c38
Don't explicitly import mocha (the test harness will take care of that)
bterlson Mar 8, 2019
15d6b29
Fix browser build and audit warnings, implement browser tests via karma
bterlson Mar 8, 2019
45b34aa
Properly use configured WebSocket constructor
bterlson Mar 8, 2019
9f8554a
Add tests for passing web sockets to ConnectionContextBase.create
bterlson Mar 9, 2019
f98cd50
Use WebSocket by default in the browser
bterlson Mar 11, 2019
f21c38f
Version 1.0.0-preview.2
bterlson Mar 11, 2019
9c605fc
Move browser build deps to dependencies
bterlson Mar 13, 2019
aa95e9f
Fix syntax error in package.json
bterlson Mar 13, 2019
06f62d4
Clean up lib dependencies; DOM not required anymore
bterlson Mar 14, 2019
35422c5
Move rhea and rhea-promise to dev dep and peer dep
bterlson Mar 14, 2019
94f9fa8
Move WebSocket types to public surface area as types are exported
bterlson Mar 14, 2019
156dbc3
Move some shims to rollup config
bterlson Mar 14, 2019
f3cb8a4
Add a normal process shim; nextTick is required
bterlson Mar 14, 2019
a986899
Check for window before checking for window.WebSocket
bterlson Mar 14, 2019
d07cedb
peerDeps are external in rollup config as well
bterlson Mar 15, 2019
7044f04
Remove some unused devdeps that crept in during rebase
bterlson Mar 15, 2019
c22d361
Update package-lock.json
bterlson Mar 15, 2019
62fd1d9
Implement offline check for browser, fix build
bterlson Mar 18, 2019
b781cea
Add json plugin and dns shim to rollup config
bterlson Mar 18, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,11 @@ obj/*
.env
typings/
dist/
dist-esm/
browser/
output/
client/examples/js/lib/
processor/examples/js/lib/
typedoc
out/
out/

54 changes: 28 additions & 26 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
{
"files.exclude": {
"**/.git": true,
"**/.svn": true,
"**/.DS_Store": true
},
"[typescript]": {
"editor.formatOnSave": true,
"editor.formatOnPaste": true,
"editor.tabSize": 2,
"editor.detectIndentation": false
},
"[json]": {
"editor.formatOnSave": true,
"editor.formatOnPaste": true,
"editor.tabSize": 2,
"editor.detectIndentation": false
},
"[yaml]": {
"editor.formatOnSave": true,
"editor.formatOnPaste": true,
"editor.tabSize": 2,
"editor.detectIndentation": false
},
"editor.rulers": [100],
"typescript.tsdk": "./client/node_modules/typescript/lib"
}
"files.exclude": {
"**/.git": true,
"**/.svn": true,
"**/.DS_Store": true
},
"[typescript]": {
"editor.formatOnSave": true,
"editor.formatOnPaste": true,
"editor.tabSize": 2,
"editor.detectIndentation": false
},
"[json]": {
"editor.formatOnSave": true,
"editor.formatOnPaste": true,
"editor.tabSize": 2,
"editor.detectIndentation": false
},
"[yaml]": {
"editor.formatOnSave": true,
"editor.formatOnPaste": true,
"editor.tabSize": 2,
"editor.detectIndentation": false
},
"editor.rulers": [
100
],
"typescript.tsdk": "./node_modules/typescript/lib"
}
75 changes: 75 additions & 0 deletions karma.conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Karma configuration
// Generated on Fri Mar 08 2019 11:00:13 GMT-0800 (Pacific Standard Time)

module.exports = function (config) {
config.set({

// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',


// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['mocha'],


// list of files / patterns to load in the browser
files: [
'./test-browser/index.js'
],


// list of files / patterns to exclude
exclude: [
],


// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
},


// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],


// web server port
port: 9876,


// enable / disable colors in the output (reporters and logs)
colors: true,


// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,


// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,


// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Chrome'],


// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: true,

// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity,

client: {
mocha: {
timeout: 50000
}
}
})
}
36 changes: 29 additions & 7 deletions lib/ConnectionContextBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { DataTransformer, DefaultDataTransformer } from "./dataTransformer";
import { TokenProvider } from "./auth/token";
import { ConnectionConfig } from "./connectionConfig";
import { SasTokenProvider } from "./auth/sas";
import rhea from "rhea";

import * as Constants from "./util/constants";
import * as os from "os";

Expand Down Expand Up @@ -132,12 +134,15 @@ export module ConnectionContextBase {
if (!parameters || typeof parameters !== "object") {
throw new Error("'parameters' is a required parameter and must be of type 'object'.");
}
ConnectionConfig.validate(parameters.config,
{ isEntityPathRequired: parameters.isEntityPathRequired || false });
ConnectionConfig.validate(parameters.config, {
isEntityPathRequired: parameters.isEntityPathRequired || false
});
const userAgent = parameters.connectionProperties.userAgent;
if (userAgent.length > Constants.maxUserAgentLength) {
throw new Error(`The user-agent string cannot be more than 128 characters in length.` +
`The given user-agent string is: ${userAgent} with length: ${userAgent.length}`);
throw new Error(
`The user-agent string cannot be more than 128 characters in length.` +
`The given user-agent string is: ${userAgent} with length: ${userAgent.length}`
);
}

const connectionOptions: ConnectionOptions = {
Expand All @@ -157,6 +162,19 @@ export module ConnectionContextBase {
operationTimeoutInSeconds: parameters.operationTimeoutInSeconds
};

if (parameters.config.webSocket || (typeof window !== "undefined" && (window as any).WebSocket)) {
const socket = parameters.config.webSocket || (window as any).WebSocket;
// TODO: expose websocket_connect via rhea-promise
const ws = rhea.websocket_connect(socket);
const host = parameters.config.host;
const endpoint = parameters.config.webSocketEndpointPath || '';

// connectionOptions is cast to any to work around type errors.
// The errors seem spurious and so are ignored.
(connectionOptions.connection_details as any) =
ws(`wss://${host}:443/${endpoint}`, ["AMQPWSB10"], {});
}

const connection = new Connection(connectionOptions);
const connectionLock = `${Constants.establishConnection}-${generate_uuid()}`;
const connectionContextBase: ConnectionContextBase = {
Expand All @@ -167,9 +185,13 @@ export module ConnectionContextBase {
connectionId: connection.id,
cbsSession: new CbsClient(connection, connectionLock),
config: parameters.config,
tokenProvider: parameters.tokenProvider ||
new SasTokenProvider(parameters.config.endpoint, parameters.config.sharedAccessKeyName,
parameters.config.sharedAccessKey),
tokenProvider:
parameters.tokenProvider ||
new SasTokenProvider(
parameters.config.endpoint,
parameters.config.sharedAccessKeyName,
parameters.config.sharedAccessKey
),
dataTransformer: parameters.dataTransformer || new DefaultDataTransformer()
};

Expand Down
37 changes: 16 additions & 21 deletions lib/auth/aad.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import {
ApplicationTokenCredentials, DeviceTokenCredentials, UserTokenCredentials, MSITokenCredentials
} from "ms-rest-azure";
} from "@azure/ms-rest-nodeauth";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@bterlson When you tested Service Bus by pointing the amqp-common dependency to your git branch, were you able to run any of the examples like interactiveLogin, servicePrincipalLogin or the test on auth without making any changes?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@ramya-rao-a I didn't try the samples. I'll report here with my findings, though I may need your help getting the AD side set up properly.

import { TokenInfo, TokenType, TokenProvider } from "./token";
import * as Constants from "../util/constants";

Expand Down Expand Up @@ -50,26 +50,21 @@ export class AadTokenProvider implements TokenProvider {
* @param {string} [audience] - The audience for which the token is desired. If not
* provided then the Endpoint from the connection string will be applied.
*/
getToken(audience?: string): Promise<TokenInfo> {
async getToken(audience?: string): Promise<TokenInfo> {
const self = this;
return new Promise<TokenInfo>((resolve, reject) => {
self.credentials.getToken((err, result) => {
if (err) {
reject(err);
}
let expiresOn = Date.now();
if (result.expiresOn && result.expiresOn instanceof Date) {
expiresOn = result.expiresOn.getTime();
}
const expiry = Math.floor(expiresOn / 1000) +
self.tokenValidTimeInSeconds - Constants.aadTokenValidityMarginSeconds;
const tokenObj: TokenInfo = {
expiry: expiry,
tokenType: TokenType.CbsTokenTypeJwt,
token: result.accessToken
};
resolve(tokenObj);
});
});
const result = await self.credentials.getToken();
let expiresOn = Date.now();
if (result.expiresOn && result.expiresOn instanceof Date) {
expiresOn = result.expiresOn.getTime();
}
const expiry = Math.floor(expiresOn / 1000) +
self.tokenValidTimeInSeconds - Constants.aadTokenValidityMarginSeconds;
const tokenObj: TokenInfo = {
expiry: expiry,
tokenType: TokenType.CbsTokenTypeJwt,
token: result.accessToken
};

return tokenObj;
}
}
1 change: 1 addition & 0 deletions lib/auth/iotSas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import { SasTokenProvider } from "./sas";
import { TokenInfo } from "./token";
import { Buffer } from "buffer";

/**
* @class IotSasTokenProvider
Expand Down
7 changes: 4 additions & 3 deletions lib/auth/sas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@

import { parseConnectionString, ServiceBusConnectionStringModel } from "../util/utils";
import { TokenInfo, TokenProvider, TokenType } from "./token";
const isBuffer = require("is-buffer");
const jssha = require("jssha");
import { Buffer } from "buffer";
import isBuffer from "is-buffer";
import jssha from "jssha";

/**
* @class SasTokenProvider
Expand Down Expand Up @@ -37,7 +38,7 @@ export class SasTokenProvider implements TokenProvider {
tokenValidTimeInSeconds: number;

/**
* Initializes a new isntance of SasTokenProvider
* Initializes a new instance of SasTokenProvider
* @constructor
* @param {string} namespace - The namespace of the EventHub/ServiceBus instance.
* @param {string} keyName - The name of the EventHub/ServiceBus key.
Expand Down
35 changes: 35 additions & 0 deletions lib/connectionConfig/connectionConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,26 @@

import { parseConnectionString, ServiceBusConnectionStringModel } from "../util/utils";

/**
* Describes the required shape of WebSocket instances.
* @interface WebSocketInstance
*/
export interface WebSocketInstance {
send: Function;
onmessage: Function | null;
onopen: Function | null;
onclose: Function | null;
onerror: Function | null;
}

/**
* Describes the required shape of WebSocket constructors.
* @interface WebSocketImpl
*/
export interface WebSocketImpl {
new(url: string, protocols?: string | string[]): WebSocketInstance;
}

/**
* Describes the options that can be provided while creating a connection config.
* @interface ConnectionConfigOptions
Expand Down Expand Up @@ -47,6 +67,19 @@ export interface ConnectionConfig {
* @property {string} sharedAccessKey - The secret value of the access key.
*/
sharedAccessKey: string;

/**
* @property {WebSocketImpl} [webSocket] - The WebSocket constructor used to create an AMQP connection
* over a WebSocket. In browsers, the built-in WebSocket will be used by default. In Node, a
* TCP socket will be used if a WebSocket constructor is not provided.
*/
webSocket?: WebSocketImpl;

/**
* @property {string} [webSocketEndpointPath] - The path for the endpoint that accepts an AMQP
* connection over WebSockets.
*/
webSocketEndpointPath?: string;
}

/**
Expand All @@ -73,13 +106,15 @@ export namespace ConnectionConfig {
}

if (!parsedCS.Endpoint.endsWith("/")) parsedCS.Endpoint += "/";

const result: ConnectionConfig = {
connectionString: connectionString,
endpoint: parsedCS.Endpoint,
host: (parsedCS && parsedCS.Endpoint) ? (parsedCS.Endpoint.match('sb://([^/]*)') || [])[1] : "",
sharedAccessKeyName: parsedCS.SharedAccessKeyName,
sharedAccessKey: parsedCS.SharedAccessKey
};

if (path || parsedCS.EntityPath) result.entityPath = path || parsedCS.EntityPath;
return result;
}
Expand Down
4 changes: 2 additions & 2 deletions lib/dataTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

import { message } from "rhea-promise";
import * as log from "./log";

const isBuffer = require("is-buffer");
import isBuffer from "is-buffer";
import { Buffer } from "buffer";

/**
* Describes the transformations that can be performed to encode/decode the data before sending it
Expand Down
4 changes: 4 additions & 0 deletions lib/index.browser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/* tslint:disable */
// This file is a stub export filling in missing capabilities in the browser.
// The AadTokenProvider is only supported in Node.
export const AadTokenProvider = undefined;
1 change: 1 addition & 0 deletions lib/index.node.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { AadTokenProvider } from "./auth/aad";
5 changes: 4 additions & 1 deletion lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

/// <reference lib="es2015" />

export { RequestResponseLink, SendRequestOptions } from "./requestResponseLink";
export { retry, RetryConfig, RetryOperationType } from "./retry";
export { DataTransformer, DefaultDataTransformer } from "./dataTransformer";
export { TokenType, TokenProvider, TokenInfo } from "./auth/token";
export { SasTokenProvider } from "./auth/sas";
export { IotSasTokenProvider } from "./auth/iotSas";
export { AadTokenProvider } from "./auth/aad";
export * from './index.node';

export {
ConnectionConfig, ConnectionConfigOptions, EventHubConnectionConfig, IotHubConnectionConfig
} from "./connectionConfig";
Expand Down
Loading