@azure/web-pubsub 1.1.0-alpha.20221107.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. package/README.md +31 -0
  2. package/dist/index.js +443 -294
  3. package/dist/index.js.map +1 -1
  4. package/dist-esm/src/generated/generatedClient.js +51 -3
  5. package/dist-esm/src/generated/generatedClient.js.map +1 -1
  6. package/dist-esm/src/generated/index.js +0 -1
  7. package/dist-esm/src/generated/index.js.map +1 -1
  8. package/dist-esm/src/generated/models/index.js +2 -0
  9. package/dist-esm/src/generated/models/index.js.map +1 -1
  10. package/dist-esm/src/generated/models/mappers.js +58 -44
  11. package/dist-esm/src/generated/models/mappers.js.map +1 -1
  12. package/dist-esm/src/generated/models/parameters.js +70 -31
  13. package/dist-esm/src/generated/models/parameters.js.map +1 -1
  14. package/dist-esm/src/generated/operations/healthApi.js.map +1 -1
  15. package/dist-esm/src/generated/operations/webPubSub.js +217 -185
  16. package/dist-esm/src/generated/operations/webPubSub.js.map +1 -1
  17. package/dist-esm/src/generated/operationsInterfaces/webPubSub.js.map +1 -1
  18. package/dist-esm/src/groupClient.js.map +1 -1
  19. package/dist-esm/src/hubClient.js +12 -2
  20. package/dist-esm/src/hubClient.js.map +1 -1
  21. package/dist-esm/src/index.js +1 -0
  22. package/dist-esm/src/index.js.map +1 -1
  23. package/dist-esm/src/utils.js +44 -0
  24. package/dist-esm/src/utils.js.map +1 -1
  25. package/dist-esm/test/groups.spec.js +23 -0
  26. package/dist-esm/test/groups.spec.js.map +1 -1
  27. package/dist-esm/test/hubs.spec.js +59 -7
  28. package/dist-esm/test/hubs.spec.js.map +1 -1
  29. package/dist-esm/test/integration.spec.js +99 -7
  30. package/dist-esm/test/integration.spec.js.map +1 -1
  31. package/dist-esm/test/odata.spec.js +15 -0
  32. package/dist-esm/test/odata.spec.js.map +1 -0
  33. package/package.json +7 -6
  34. package/types/web-pubsub.d.ts +56 -3
@@ -1,7 +1,7 @@
1
1
  // Copyright (c) Microsoft Corporation.
2
2
  // Licensed under the MIT license.
3
3
  /* eslint-disable no-invalid-this */
4
- import { WebPubSubServiceClient } from "../src/index";
4
+ import { WebPubSubServiceClient, odata } from "../src/index";
5
5
  import { isLiveMode, assertEnvironmentVariable } from "@azure-tools/test-recorder";
6
6
  import { assert } from "chai";
7
7
  import ws from "ws";
@@ -26,12 +26,13 @@ class SimpleWebSocketFrame {
26
26
  this.dataAsString = data.toString();
27
27
  }
28
28
  }
29
- isEndSignal() {
29
+ isEndSignal(id = undefined) {
30
30
  return (this.isBinary &&
31
31
  this.data instanceof Buffer &&
32
32
  this.data[0] === 5 &&
33
33
  this.data[1] === 1 &&
34
- this.data[2] === 1);
34
+ this.data[2] === 1 &&
35
+ (id === undefined || this.data[3] === id));
35
36
  }
36
37
  toString() {
37
38
  if (this.isEndSignal()) {
@@ -61,17 +62,19 @@ class PubSubWebSocketFrame {
61
62
  return this.dataAsString;
62
63
  }
63
64
  }
64
- function getEndSignal() {
65
+ function getEndSignal(id = undefined) {
65
66
  // magic number 511
66
- const payload = new Uint8Array(3);
67
+ const payload = new Uint8Array(id === undefined ? 3 : 4);
67
68
  payload[0] = 5;
68
69
  payload[1] = 1;
69
70
  payload[2] = 1;
71
+ if (id !== undefined) {
72
+ payload[3] = id;
73
+ }
70
74
  return payload;
71
75
  }
72
76
  describe("ServiceClient to manage the connected WebSocket connections", function () {
73
- // Issue - https://github.com/Azure/azure-sdk-for-js/issues/20571 waiting for service fix
74
- it.skip("Simple clients can receive expected messages with different content types", async function () {
77
+ it("Simple clients can receive expected messages with different content types", async function () {
75
78
  if (!isLiveMode())
76
79
  this.skip();
77
80
  const hub = "SimpleClientCanReceiveMessage";
@@ -107,6 +110,53 @@ describe("ServiceClient to manage the connected WebSocket connections", function
107
110
  assert.equal(messages[0].dataAsString, '{"message":"Hello world!"}');
108
111
  assert.equal(messages[1].dataAsString, "Hi there!");
109
112
  });
113
+ it("Simple clients can can join group and receive group messages", async function () {
114
+ if (!isLiveMode())
115
+ this.skip();
116
+ const hub = "SimpleClientCanReceiveGroupMessage";
117
+ const messages = [];
118
+ // Get token
119
+ const serviceClient = new WebPubSubServiceClient(assertEnvironmentVariable("WPS_CONNECTION_STRING"), hub);
120
+ const token = await serviceClient.getClientAccessToken({
121
+ groups: ["group1", "group2"],
122
+ });
123
+ const end1Signal = defer();
124
+ const end2Signal = defer();
125
+ // Start simple WebSocket connections
126
+ const client = new ws.WebSocket(token.url);
127
+ client.on("message", (data, isBinary) => {
128
+ const frame = new SimpleWebSocketFrame(data, isBinary);
129
+ console.log(frame.toString());
130
+ if (frame.isEndSignal(1)) {
131
+ end1Signal.resolve();
132
+ }
133
+ else if (frame.isEndSignal(2)) {
134
+ end2Signal.resolve();
135
+ }
136
+ else {
137
+ messages.push(frame);
138
+ }
139
+ });
140
+ client.on("open", async () => {
141
+ const group1Client = serviceClient.group("group1");
142
+ const group2Client = serviceClient.group("group2");
143
+ // send to all
144
+ // Send a JSON message
145
+ await group1Client.sendToAll({ message: "Hello world from group1!" });
146
+ await group2Client.sendToAll(getEndSignal(1));
147
+ // Send a plain text message
148
+ await group2Client.sendToAll("Hi there from group2!", { contentType: "text/plain" });
149
+ // Send the binary end signal message
150
+ await group2Client.sendToAll(getEndSignal(2));
151
+ });
152
+ await end1Signal.promise;
153
+ await end2Signal.promise;
154
+ client.close();
155
+ assert.equal(messages.length, 2);
156
+ // order from different groups is not guaranteed
157
+ assert.isTrue(messages.findIndex((s) => s.dataAsString === '{"message":"Hello world from group1!"}') > -1);
158
+ assert.isTrue(messages.findIndex((s) => s.dataAsString === "Hi there from group2!") > -1);
159
+ });
110
160
  it("Subprotocol clients can receive expected messages with different content types", async function () {
111
161
  if (!isLiveMode())
112
162
  this.skip();
@@ -149,5 +199,47 @@ describe("ServiceClient to manage the connected WebSocket connections", function
149
199
  assert.equal(messages[1].dataAsString, '{"type":"message","from":"server","dataType":"json","data":{"message":"Hello world!"}}');
150
200
  assert.equal(messages[2].dataAsString, '{"type":"message","from":"server","dataType":"text","data":"Hi there!"}');
151
201
  });
202
+ it("Clients can receive messages with filters", async function () {
203
+ if (!isLiveMode())
204
+ this.skip();
205
+ const hub = "ClientCanReceiveMessageWithFilters";
206
+ const messages = [];
207
+ // Get token
208
+ const serviceClient = new WebPubSubServiceClient(assertEnvironmentVariable("WPS_CONNECTION_STRING"), hub);
209
+ const token = await serviceClient.getClientAccessToken({ groups: ["groupA"] });
210
+ const endSignal = defer();
211
+ // Start simple WebSocket connections
212
+ const client = new ws.WebSocket(token.url);
213
+ client.on("message", (data, isBinary) => {
214
+ const frame = new SimpleWebSocketFrame(data, isBinary);
215
+ console.log(frame.toString());
216
+ if (frame.isEndSignal()) {
217
+ endSignal.resolve();
218
+ client.close();
219
+ }
220
+ else {
221
+ messages.push(frame);
222
+ }
223
+ });
224
+ client.on("open", async () => {
225
+ // Send a JSON message to anonymous connections
226
+ await serviceClient.sendToAll({ message: "Hello world!" }, { filter: "userId eq null" });
227
+ // Send a text message to connections in groupA but not in groupB
228
+ const groupA = "groupA";
229
+ const groupB = "groupB";
230
+ await serviceClient.sendToAll("Hello world!", {
231
+ contentType: "text/plain",
232
+ // use plain text "'groupA' in groups and not('groupB' in groups)"
233
+ // or use the odata helper method
234
+ filter: odata `${groupA} in groups and not(${groupB} in groups)`,
235
+ });
236
+ // Send the binary end signal message
237
+ await serviceClient.sendToAll(getEndSignal());
238
+ });
239
+ await endSignal.promise;
240
+ assert.equal(messages.length, 2);
241
+ assert.equal(messages[0].dataAsString, '{"message":"Hello world!"}');
242
+ assert.equal(messages[1].dataAsString, "Hello world!");
243
+ });
152
244
  });
153
245
  //# sourceMappingURL=integration.spec.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"integration.spec.js","sourceRoot":"","sources":["../../test/integration.spec.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAClC,oCAAoC;AACpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAEnF,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAC9B,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,SAAS,KAAK;IAKZ,IAAI,aAA6B,CAAC;IAClC,IAAI,YAAkC,CAAC;IAEvC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACjD,aAAa,GAAG,OAAO,CAAC;QACxB,YAAY,GAAG,MAAM,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,OAAO;QACP,OAAO,EAAE,aAAc;QACvB,MAAM,EAAE,YAAa;KACtB,CAAC;AACJ,CAAC;AAED,MAAM,oBAAoB;IAExB,YAAmB,IAAqC,EAAS,QAAiB;QAA/D,SAAI,GAAJ,IAAI,CAAiC;QAAS,aAAQ,GAAR,QAAQ,CAAS;QAChF,IAAI,CAAC,QAAQ,EAAE;YACb,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;SACrC;IACH,CAAC;IAED,WAAW;QACT,OAAO,CACL,IAAI,CAAC,QAAQ;YACb,IAAI,CAAC,IAAI,YAAY,MAAM;YAC3B,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;YAClB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;YAClB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CACnB,CAAC;IACJ,CAAC;IAED,QAAQ;QACN,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE;YACtB,OAAO,aAAa,CAAC;SACtB;QACD,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YAClB,OAAO,IAAI,CAAC,YAAY,CAAC;SAC1B;aAAM;YACL,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;SAC7B;IACH,CAAC;CACF;AAED,MAAM,oBAAoB;IAGxB,YAAY,IAAqC,EAAE,QAAiB;QAClE,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACzB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QACpC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC/C,CAAC;IAED,WAAW;QACT,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,KAAK,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC;IAC5E,CAAC;IAED,QAAQ;QACN,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE;YACtB,OAAO,aAAa,CAAC;SACtB;QAED,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;CACF;AAED,SAAS,YAAY;IACnB,mBAAmB;IACnB,MAAM,OAAO,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;IAClC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACf,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACf,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACf,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,QAAQ,CAAC,6DAA6D,EAAE;IACtE,yFAAyF;IACzF,EAAE,CAAC,IAAI,CAAC,2EAA2E,EAAE,KAAK;QACxF,IAAI,CAAC,UAAU,EAAE;YAAE,IAAI,CAAC,IAAI,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,+BAA+B,CAAC;QAE5C,MAAM,QAAQ,GAA2B,EAAE,CAAC;QAE5C,YAAY;QACZ,MAAM,aAAa,GAAG,IAAI,sBAAsB,CAC9C,yBAAyB,CAAC,uBAAuB,CAAC,EAClD,GAAG,CACJ,CAAC;QACF,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,oBAAoB,EAAE,CAAC;QACzD,MAAM,SAAS,GAAG,KAAK,EAAQ,CAAC;QAChC,qCAAqC;QACrC,MAAM,MAAM,GAAG,IAAI,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC3C,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE;YACtC,MAAM,KAAK,GAAG,IAAI,oBAAoB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YACvD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC9B,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE;gBACvB,SAAS,CAAC,OAAO,EAAE,CAAC;gBACpB,MAAM,CAAC,KAAK,EAAE,CAAC;aAChB;iBAAM;gBACL,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;aACtB;QACH,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE;YAC3B,cAAc;YACd,sBAAsB;YACtB,MAAM,aAAa,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC;YAE3D,4BAA4B;YAC5B,MAAM,aAAa,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC,CAAC;YAE1E,qCAAqC;YACrC,MAAM,aAAa,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;QAEH,MAAM,SAAS,CAAC,OAAO,CAAC;QAExB,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACjC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,4BAA4B,CAAC,CAAC;QACrE,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gFAAgF,EAAE,KAAK;QACxF,IAAI,CAAC,UAAU,EAAE;YAAE,IAAI,CAAC,IAAI,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,+BAA+B,CAAC;QAC5C,MAAM,QAAQ,GAA2B,EAAE,CAAC;QAE5C,YAAY;QACZ,MAAM,aAAa,GAAG,IAAI,sBAAsB,CAC9C,yBAAyB,CAAC,uBAAuB,CAAC,EAClD,GAAG,CACJ,CAAC;QACF,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,oBAAoB,EAAE,CAAC;QACzD,MAAM,SAAS,GAAG,KAAK,EAAQ,CAAC;QAChC,MAAM,eAAe,GAAG,KAAK,EAAQ,CAAC;QACtC,qCAAqC;QACrC,MAAM,MAAM,GAAG,IAAI,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,yBAAyB,CAAC,CAAC;QACtE,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE;YACtC,MAAM,KAAK,GAAG,IAAI,oBAAoB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YACvD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC9B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,KAAK,WAAW,EAAE;gBACvC,eAAe,CAAC,OAAO,EAAE,CAAC;aAC3B;YACD,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE;gBACvB,SAAS,CAAC,OAAO,EAAE,CAAC;gBACpB,MAAM,CAAC,KAAK,EAAE,CAAC;aAChB;iBAAM;gBACL,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;aACtB;QACH,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE;YAC3B,MAAM,eAAe,CAAC,OAAO,CAAC;YAE9B,cAAc;YACd,sBAAsB;YACtB,MAAM,aAAa,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC;YAE3D,4BAA4B;YAC5B,MAAM,aAAa,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC,CAAC;YAE1E,qCAAqC;YACrC,MAAM,aAAa,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;QAEH,MAAM,SAAS,CAAC,OAAO,CAAC;QAExB,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACjC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QACrD,MAAM,CAAC,KAAK,CACV,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,EACxB,wFAAwF,CACzF,CAAC;QACF,MAAM,CAAC,KAAK,CACV,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,EACxB,yEAAyE,CAC1E,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n/* eslint-disable no-invalid-this */\nimport { WebPubSubServiceClient } from \"../src/index\";\nimport { isLiveMode, assertEnvironmentVariable } from \"@azure-tools/test-recorder\";\nimport { Context } from \"mocha\";\nimport { assert } from \"chai\";\nimport ws from \"ws\";\n\nfunction defer<T>(): {\n promise: Promise<T>;\n resolve: (t: T) => void;\n reject: (err: Error) => void;\n} {\n let actualResolve: (t: T) => void;\n let actualReject: (err: Error) => void;\n\n const promise = new Promise<T>((resolve, reject) => {\n actualResolve = resolve;\n actualReject = reject;\n });\n\n return {\n promise,\n resolve: actualResolve!,\n reject: actualReject!,\n };\n}\n\nclass SimpleWebSocketFrame {\n public dataAsString: string | undefined;\n constructor(public data: Buffer | ArrayBuffer | Buffer[], public isBinary: boolean) {\n if (!isBinary) {\n this.dataAsString = data.toString();\n }\n }\n\n isEndSignal(): boolean {\n return (\n this.isBinary &&\n this.data instanceof Buffer &&\n this.data[0] === 5 &&\n this.data[1] === 1 &&\n this.data[2] === 1\n );\n }\n\n toString(): string | undefined {\n if (this.isEndSignal()) {\n return \"|EndSignal|\";\n }\n if (!this.isBinary) {\n return this.dataAsString;\n } else {\n return this.data.toString();\n }\n }\n}\n\nclass PubSubWebSocketFrame {\n public message: any;\n public dataAsString: string;\n constructor(data: Buffer | ArrayBuffer | Buffer[], isBinary: boolean) {\n assert.isFalse(isBinary);\n this.dataAsString = data.toString();\n this.message = JSON.parse(this.dataAsString);\n }\n\n isEndSignal(): boolean {\n return this.message.dataType === \"binary\" && this.message.data === \"BQEB\";\n }\n\n toString(): string | undefined {\n if (this.isEndSignal()) {\n return \"|EndSignal|\";\n }\n\n return this.dataAsString;\n }\n}\n\nfunction getEndSignal(): Uint8Array {\n // magic number 511\n const payload = new Uint8Array(3);\n payload[0] = 5;\n payload[1] = 1;\n payload[2] = 1;\n return payload;\n}\n\ndescribe(\"ServiceClient to manage the connected WebSocket connections\", function () {\n // Issue - https://github.com/Azure/azure-sdk-for-js/issues/20571 waiting for service fix\n it.skip(\"Simple clients can receive expected messages with different content types\", async function (this: Context) {\n if (!isLiveMode()) this.skip();\n const hub = \"SimpleClientCanReceiveMessage\";\n\n const messages: SimpleWebSocketFrame[] = [];\n\n // Get token\n const serviceClient = new WebPubSubServiceClient(\n assertEnvironmentVariable(\"WPS_CONNECTION_STRING\"),\n hub\n );\n const token = await serviceClient.getClientAccessToken();\n const endSignal = defer<void>();\n // Start simple WebSocket connections\n const client = new ws.WebSocket(token.url);\n client.on(\"message\", (data, isBinary) => {\n const frame = new SimpleWebSocketFrame(data, isBinary);\n console.log(frame.toString());\n if (frame.isEndSignal()) {\n endSignal.resolve();\n client.close();\n } else {\n messages.push(frame);\n }\n });\n client.on(\"open\", async () => {\n // send to all\n // Send a JSON message\n await serviceClient.sendToAll({ message: \"Hello world!\" });\n\n // Send a plain text message\n await serviceClient.sendToAll(\"Hi there!\", { contentType: \"text/plain\" });\n\n // Send the binary end signal message\n await serviceClient.sendToAll(getEndSignal());\n });\n\n await endSignal.promise;\n\n assert.equal(messages.length, 2);\n assert.equal(messages[0].dataAsString, '{\"message\":\"Hello world!\"}');\n assert.equal(messages[1].dataAsString, \"Hi there!\");\n });\n\n it(\"Subprotocol clients can receive expected messages with different content types\", async function (this: Context) {\n if (!isLiveMode()) this.skip();\n const hub = \"PubSubClientCanReceiveMessage\";\n const messages: PubSubWebSocketFrame[] = [];\n\n // Get token\n const serviceClient = new WebPubSubServiceClient(\n assertEnvironmentVariable(\"WPS_CONNECTION_STRING\"),\n hub\n );\n const token = await serviceClient.getClientAccessToken();\n const endSignal = defer<void>();\n const connectedSignal = defer<void>();\n // Start simple WebSocket connections\n const client = new ws.WebSocket(token.url, \"json.webpubsub.azure.v1\");\n client.on(\"message\", (data, isBinary) => {\n const frame = new PubSubWebSocketFrame(data, isBinary);\n console.log(frame.toString());\n if (frame.message.event === \"connected\") {\n connectedSignal.resolve();\n }\n if (frame.isEndSignal()) {\n endSignal.resolve();\n client.close();\n } else {\n messages.push(frame);\n }\n });\n client.on(\"open\", async () => {\n await connectedSignal.promise;\n\n // send to all\n // Send a JSON message\n await serviceClient.sendToAll({ message: \"Hello world!\" });\n\n // Send a plain text message\n await serviceClient.sendToAll(\"Hi there!\", { contentType: \"text/plain\" });\n\n // Send the binary end signal message\n await serviceClient.sendToAll(getEndSignal());\n });\n\n await endSignal.promise;\n\n assert.equal(messages.length, 3);\n assert.equal(messages[0].message.event, \"connected\");\n assert.equal(\n messages[1].dataAsString,\n '{\"type\":\"message\",\"from\":\"server\",\"dataType\":\"json\",\"data\":{\"message\":\"Hello world!\"}}'\n );\n assert.equal(\n messages[2].dataAsString,\n '{\"type\":\"message\",\"from\":\"server\",\"dataType\":\"text\",\"data\":\"Hi there!\"}'\n );\n });\n});\n"]}
1
+ {"version":3,"file":"integration.spec.js","sourceRoot":"","sources":["../../test/integration.spec.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n/* eslint-disable no-invalid-this */\nimport { WebPubSubServiceClient, odata } from \"../src/index\";\nimport { isLiveMode, assertEnvironmentVariable } from \"@azure-tools/test-recorder\";\nimport { Context } from \"mocha\";\nimport { assert } from \"chai\";\nimport ws from \"ws\";\n\nfunction defer<T>(): {\n promise: Promise<T>;\n resolve: (t: T) => void;\n reject: (err: Error) => void;\n} {\n let actualResolve: (t: T) => void;\n let actualReject: (err: Error) => void;\n\n const promise = new Promise<T>((resolve, reject) => {\n actualResolve = resolve;\n actualReject = reject;\n });\n\n return {\n promise,\n resolve: actualResolve!,\n reject: actualReject!,\n };\n}\n\nclass SimpleWebSocketFrame {\n public dataAsString: string | undefined;\n constructor(public data: Buffer | ArrayBuffer | Buffer[], public isBinary: boolean) {\n if (!isBinary) {\n this.dataAsString = data.toString();\n }\n }\n\n isEndSignal(id: number | undefined = undefined): boolean {\n return (\n this.isBinary &&\n this.data instanceof Buffer &&\n this.data[0] === 5 &&\n this.data[1] === 1 &&\n this.data[2] === 1 &&\n (id === undefined || this.data[3] === id)\n );\n }\n\n toString(): string | undefined {\n if (this.isEndSignal()) {\n return \"|EndSignal|\";\n }\n if (!this.isBinary) {\n return this.dataAsString;\n } else {\n return this.data.toString();\n }\n }\n}\n\nclass PubSubWebSocketFrame {\n public message: any;\n public dataAsString: string;\n constructor(data: Buffer | ArrayBuffer | Buffer[], isBinary: boolean) {\n assert.isFalse(isBinary);\n this.dataAsString = data.toString();\n this.message = JSON.parse(this.dataAsString);\n }\n\n isEndSignal(): boolean {\n return this.message.dataType === \"binary\" && this.message.data === \"BQEB\";\n }\n\n toString(): string | undefined {\n if (this.isEndSignal()) {\n return \"|EndSignal|\";\n }\n\n return this.dataAsString;\n }\n}\n\nfunction getEndSignal(id: number | undefined = undefined): Uint8Array {\n // magic number 511\n const payload = new Uint8Array(id === undefined ? 3 : 4);\n payload[0] = 5;\n payload[1] = 1;\n payload[2] = 1;\n if (id !== undefined) {\n payload[3] = id;\n }\n return payload;\n}\n\ndescribe(\"ServiceClient to manage the connected WebSocket connections\", function () {\n it(\"Simple clients can receive expected messages with different content types\", async function (this: Context) {\n if (!isLiveMode()) this.skip();\n const hub = \"SimpleClientCanReceiveMessage\";\n\n const messages: SimpleWebSocketFrame[] = [];\n\n // Get token\n const serviceClient = new WebPubSubServiceClient(\n assertEnvironmentVariable(\"WPS_CONNECTION_STRING\"),\n hub\n );\n const token = await serviceClient.getClientAccessToken();\n const endSignal = defer<void>();\n // Start simple WebSocket connections\n const client = new ws.WebSocket(token.url);\n client.on(\"message\", (data, isBinary) => {\n const frame = new SimpleWebSocketFrame(data, isBinary);\n console.log(frame.toString());\n if (frame.isEndSignal()) {\n endSignal.resolve();\n client.close();\n } else {\n messages.push(frame);\n }\n });\n client.on(\"open\", async () => {\n // send to all\n // Send a JSON message\n await serviceClient.sendToAll({ message: \"Hello world!\" });\n\n // Send a plain text message\n await serviceClient.sendToAll(\"Hi there!\", { contentType: \"text/plain\" });\n\n // Send the binary end signal message\n await serviceClient.sendToAll(getEndSignal());\n });\n\n await endSignal.promise;\n\n assert.equal(messages.length, 2);\n assert.equal(messages[0].dataAsString, '{\"message\":\"Hello world!\"}');\n assert.equal(messages[1].dataAsString, \"Hi there!\");\n });\n\n it(\"Simple clients can can join group and receive group messages\", async function (this: Context) {\n if (!isLiveMode()) this.skip();\n const hub = \"SimpleClientCanReceiveGroupMessage\";\n\n const messages: SimpleWebSocketFrame[] = [];\n\n // Get token\n const serviceClient = new WebPubSubServiceClient(\n assertEnvironmentVariable(\"WPS_CONNECTION_STRING\"),\n hub\n );\n const token = await serviceClient.getClientAccessToken({\n groups: [\"group1\", \"group2\"],\n });\n const end1Signal = defer<void>();\n const end2Signal = defer<void>();\n // Start simple WebSocket connections\n const client = new ws.WebSocket(token.url);\n client.on(\"message\", (data, isBinary) => {\n const frame = new SimpleWebSocketFrame(data, isBinary);\n console.log(frame.toString());\n if (frame.isEndSignal(1)) {\n end1Signal.resolve();\n } else if (frame.isEndSignal(2)) {\n end2Signal.resolve();\n } else {\n messages.push(frame);\n }\n });\n client.on(\"open\", async () => {\n const group1Client = serviceClient.group(\"group1\");\n const group2Client = serviceClient.group(\"group2\");\n // send to all\n // Send a JSON message\n await group1Client.sendToAll({ message: \"Hello world from group1!\" });\n await group2Client.sendToAll(getEndSignal(1));\n // Send a plain text message\n await group2Client.sendToAll(\"Hi there from group2!\", { contentType: \"text/plain\" });\n\n // Send the binary end signal message\n await group2Client.sendToAll(getEndSignal(2));\n });\n\n await end1Signal.promise;\n await end2Signal.promise;\n client.close();\n assert.equal(messages.length, 2);\n\n // order from different groups is not guaranteed\n assert.isTrue(\n messages.findIndex((s) => s.dataAsString === '{\"message\":\"Hello world from group1!\"}') > -1\n );\n assert.isTrue(messages.findIndex((s) => s.dataAsString === \"Hi there from group2!\") > -1);\n });\n\n it(\"Subprotocol clients can receive expected messages with different content types\", async function (this: Context) {\n if (!isLiveMode()) this.skip();\n const hub = \"PubSubClientCanReceiveMessage\";\n const messages: PubSubWebSocketFrame[] = [];\n\n // Get token\n const serviceClient = new WebPubSubServiceClient(\n assertEnvironmentVariable(\"WPS_CONNECTION_STRING\"),\n hub\n );\n const token = await serviceClient.getClientAccessToken();\n const endSignal = defer<void>();\n const connectedSignal = defer<void>();\n // Start simple WebSocket connections\n const client = new ws.WebSocket(token.url, \"json.webpubsub.azure.v1\");\n client.on(\"message\", (data, isBinary) => {\n const frame = new PubSubWebSocketFrame(data, isBinary);\n console.log(frame.toString());\n if (frame.message.event === \"connected\") {\n connectedSignal.resolve();\n }\n if (frame.isEndSignal()) {\n endSignal.resolve();\n client.close();\n } else {\n messages.push(frame);\n }\n });\n client.on(\"open\", async () => {\n await connectedSignal.promise;\n\n // send to all\n // Send a JSON message\n await serviceClient.sendToAll({ message: \"Hello world!\" });\n\n // Send a plain text message\n await serviceClient.sendToAll(\"Hi there!\", { contentType: \"text/plain\" });\n\n // Send the binary end signal message\n await serviceClient.sendToAll(getEndSignal());\n });\n\n await endSignal.promise;\n\n assert.equal(messages.length, 3);\n assert.equal(messages[0].message.event, \"connected\");\n assert.equal(\n messages[1].dataAsString,\n '{\"type\":\"message\",\"from\":\"server\",\"dataType\":\"json\",\"data\":{\"message\":\"Hello world!\"}}'\n );\n assert.equal(\n messages[2].dataAsString,\n '{\"type\":\"message\",\"from\":\"server\",\"dataType\":\"text\",\"data\":\"Hi there!\"}'\n );\n });\n\n it(\"Clients can receive messages with filters\", async function (this: Context) {\n if (!isLiveMode()) this.skip();\n const hub = \"ClientCanReceiveMessageWithFilters\";\n\n const messages: SimpleWebSocketFrame[] = [];\n\n // Get token\n const serviceClient = new WebPubSubServiceClient(\n assertEnvironmentVariable(\"WPS_CONNECTION_STRING\"),\n hub\n );\n const token = await serviceClient.getClientAccessToken({ groups: [\"groupA\"] });\n const endSignal = defer<void>();\n // Start simple WebSocket connections\n const client = new ws.WebSocket(token.url);\n client.on(\"message\", (data, isBinary) => {\n const frame = new SimpleWebSocketFrame(data, isBinary);\n console.log(frame.toString());\n if (frame.isEndSignal()) {\n endSignal.resolve();\n client.close();\n } else {\n messages.push(frame);\n }\n });\n client.on(\"open\", async () => {\n // Send a JSON message to anonymous connections\n await serviceClient.sendToAll({ message: \"Hello world!\" }, { filter: \"userId eq null\" });\n // Send a text message to connections in groupA but not in groupB\n const groupA = \"groupA\";\n const groupB = \"groupB\";\n await serviceClient.sendToAll(\"Hello world!\", {\n contentType: \"text/plain\",\n // use plain text \"'groupA' in groups and not('groupB' in groups)\"\n // or use the odata helper method\n filter: odata`${groupA} in groups and not(${groupB} in groups)`,\n });\n // Send the binary end signal message\n await serviceClient.sendToAll(getEndSignal());\n });\n\n await endSignal.promise;\n\n assert.equal(messages.length, 2);\n assert.equal(messages[0].dataAsString, '{\"message\":\"Hello world!\"}');\n assert.equal(messages[1].dataAsString, \"Hello world!\");\n });\n});\n"]}
@@ -0,0 +1,15 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT license.
3
+ /* eslint-disable no-invalid-this */
4
+ import { odata } from "../src/utils";
5
+ import { assert } from "chai";
6
+ describe("Can parse odata to string", function () {
7
+ it("can wrap different types as expected", async () => {
8
+ const userId = "vic's";
9
+ const anonymous = null;
10
+ const length = 3;
11
+ const filter = odata `userId eq ${anonymous} or userId eq ${userId} or length(userId) gt ${length}`;
12
+ assert.equal("userId eq null or userId eq 'vic''s' or length(userId) gt 3", filter);
13
+ });
14
+ });
15
+ //# sourceMappingURL=odata.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"odata.spec.js","sourceRoot":"","sources":["../../test/odata.spec.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAClC,oCAAoC;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAE9B,QAAQ,CAAC,2BAA2B,EAAE;IACpC,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;QACpD,MAAM,MAAM,GAAG,OAAO,CAAC;QACvB,MAAM,SAAS,GAAG,IAAI,CAAC;QACvB,MAAM,MAAM,GAAG,CAAC,CAAC;QACjB,MAAM,MAAM,GAAG,KAAK,CAAA,aAAa,SAAS,iBAAiB,MAAM,yBAAyB,MAAM,EAAE,CAAC;QACnG,MAAM,CAAC,KAAK,CAAC,6DAA6D,EAAE,MAAM,CAAC,CAAC;IACtF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n/* eslint-disable no-invalid-this */\nimport { odata } from \"../src/utils\";\nimport { assert } from \"chai\";\n\ndescribe(\"Can parse odata to string\", function () {\n it(\"can wrap different types as expected\", async () => {\n const userId = \"vic's\";\n const anonymous = null;\n const length = 3;\n const filter = odata`userId eq ${anonymous} or userId eq ${userId} or length(userId) gt ${length}`;\n assert.equal(\"userId eq null or userId eq 'vic''s' or length(userId) gt 3\", filter);\n });\n});\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@azure/web-pubsub",
3
- "version": "1.1.0-alpha.20221107.1",
3
+ "version": "1.1.0",
4
4
  "description": "Azure client library for Azure Web PubSub",
5
5
  "sdk-type": "client",
6
6
  "main": "dist/index.js",
@@ -30,7 +30,8 @@
30
30
  "test": "npm run build:test && npm run unit-test && npm run integration-test",
31
31
  "unit-test:browser": "echo \"Browser is not supported.\" && exit 0",
32
32
  "unit-test:node": "dev-tool run test:node-ts-input -- --timeout 1200000 --exclude 'test/**/browser/*.spec.ts' 'test/**/*.spec.ts'",
33
- "unit-test": "npm run unit-test:node && npm run unit-test:browser"
33
+ "unit-test": "npm run unit-test:node && npm run unit-test:browser",
34
+ "generate:client": "autorest --typescript ./swagger/README.md"
34
35
  },
35
36
  "files": [
36
37
  "dist/",
@@ -77,10 +78,10 @@
77
78
  "jsonwebtoken": "^8.5.1"
78
79
  },
79
80
  "devDependencies": {
80
- "@azure/dev-tool": ">=1.0.0-alpha <1.0.0-alphb",
81
- "@azure/eslint-plugin-azure-sdk": ">=3.0.0-alpha <3.0.0-alphb",
82
- "@azure/test-utils": ">=1.0.0-alpha <1.0.0-alphb",
83
- "@azure-tools/test-credential": ">=1.0.0-alpha <1.0.0-alphb",
81
+ "@azure/dev-tool": "^1.0.0",
82
+ "@azure/eslint-plugin-azure-sdk": "^3.0.0",
83
+ "@azure/test-utils": "^1.0.0",
84
+ "@azure-tools/test-credential": "^1.0.0",
84
85
  "@azure-tools/test-recorder": "^2.0.0",
85
86
  "@microsoft/api-extractor": "^7.31.1",
86
87
  "@types/chai": "^4.1.6",
@@ -47,6 +47,10 @@ export declare interface GenerateClientTokenOptions extends OperationOptions {
47
47
  * Minutes until the token expires.
48
48
  */
49
49
  expirationTimeInMinutes?: number;
50
+ /**
51
+ * The groups to join when the client connects
52
+ */
53
+ groups?: string[];
50
54
  }
51
55
 
52
56
  /**
@@ -98,11 +102,10 @@ export declare interface GroupRemoveUserOptions extends OperationOptions {
98
102
  /**
99
103
  * Options for sending text messages to a group..
100
104
  */
101
- export declare interface GroupSendTextToAllOptions extends OperationOptions {
105
+ export declare interface GroupSendTextToAllOptions extends GroupSendToAllOptions {
102
106
  /**
103
- * Connection ids to exclude from receiving this message.
107
+ * The content will be sent to the clients in plain text.
104
108
  */
105
- excludedConnections?: string[];
106
109
  contentType: "text/plain";
107
110
  }
108
111
 
@@ -114,6 +117,14 @@ export declare interface GroupSendToAllOptions extends OperationOptions {
114
117
  * Connection ids to exclude from receiving this message.
115
118
  */
116
119
  excludedConnections?: string[];
120
+ /**
121
+ * The filter syntax to filter out the connections to send the messages to following OData filter syntax.
122
+ * Examples:
123
+ * * Exclude connections from `user1` and `user2`: `userId ne 'user1' and userId ne 'user2'`
124
+ * * Exclude connections in `group1`: `not('group1' in groups)`
125
+ * Details about `filter` syntax please see [OData filter syntax for Azure Web PubSub](https://aka.ms/awps/filter-syntax).
126
+ */
127
+ filter?: string;
117
128
  }
118
129
 
119
130
  /**
@@ -207,6 +218,9 @@ export declare interface HubRevokePermissionOptions extends OperationOptions {
207
218
  * Options for sending text messages to hubs.
208
219
  */
209
220
  export declare interface HubSendTextToAllOptions extends HubSendToAllOptions {
221
+ /**
222
+ * The content will be sent to the clients in plain text.
223
+ */
210
224
  contentType: "text/plain";
211
225
  }
212
226
 
@@ -221,6 +235,9 @@ export declare interface HubSendTextToConnectionOptions extends HubSendToConnect
221
235
  * Options for sending a text message to a user.
222
236
  */
223
237
  export declare interface HubSendTextToUserOptions extends HubSendToUserOptions {
238
+ /**
239
+ * The content will be sent to the clients in plain text.
240
+ */
224
241
  contentType: "text/plain";
225
242
  }
226
243
 
@@ -232,6 +249,14 @@ export declare interface HubSendToAllOptions extends OperationOptions {
232
249
  * Connection ids to exclude from receiving this message.
233
250
  */
234
251
  excludedConnections?: string[];
252
+ /**
253
+ * The filter syntax to filter out the connections to send the messages to following OData filter syntax.
254
+ * Examples:
255
+ * * Exclude connections from `user1` and `user2`: `userId ne 'user1' and userId ne 'user2'`
256
+ * * Exclude connections in `group1`: `not('group1' in groups)`
257
+ * Details about `filter` syntax please see [OData filter syntax for Azure Web PubSub](https://aka.ms/awps/filter-syntax).
258
+ */
259
+ filter?: string;
235
260
  }
236
261
 
237
262
  /**
@@ -244,6 +269,14 @@ export declare interface HubSendToConnectionOptions extends OperationOptions {
244
269
  * Options for sending a message to a user.
245
270
  */
246
271
  export declare interface HubSendToUserOptions extends OperationOptions {
272
+ /**
273
+ * The filter syntax to filter out the connections to send the messages to following OData filter syntax.
274
+ * Examples:
275
+ * * Exclude connections in `group1`: `not('group1' in groups)`
276
+ * * Send to connections in `group1` or `group2`: `'group1' in groups or `group2` in groups`
277
+ * Details about `filter` syntax please see [OData filter syntax for Azure Web PubSub](https://aka.ms/awps/filter-syntax).
278
+ */
279
+ filter?: string;
247
280
  }
248
281
 
249
282
  /**
@@ -251,6 +284,20 @@ export declare interface HubSendToUserOptions extends OperationOptions {
251
284
  */
252
285
  export declare type JSONTypes = string | number | boolean | object;
253
286
 
287
+ /**
288
+ * Escapes an odata filter expression to avoid errors with quoting string literals.
289
+ * Example usage:
290
+ * ```ts
291
+ * const userId = "vic's";
292
+ * const anonymous = null;
293
+ * const length = 3
294
+ * const filter = odata`userId eq ${anonymous} or userId eq ${userId} or length(userId) > ${length}`;
295
+ * ```
296
+ * @param strings - Array of strings for the expression
297
+ * @param values - Array of values for the expression
298
+ */
299
+ export declare function odata(strings: TemplateStringsArray, ...values: unknown[]): string;
300
+
254
301
  export declare type Permission = "joinLeaveGroup" | "sendToGroup";
255
302
 
256
303
  export declare interface WebPubSubGroup {
@@ -485,6 +532,12 @@ export declare class WebPubSubServiceClient {
485
532
  * @param options - Additional options
486
533
  */
487
534
  removeUserFromAllGroups(userId: string, options?: HubCloseConnectionOptions): Promise<void>;
535
+ /**
536
+ * Remove a specific connection from all groups they are joined to
537
+ * @param connectionId - The connection id to remove from all groups
538
+ * @param options - Additional options
539
+ */
540
+ removeConnectionFromAllGroups(connectionId: string, options?: HubCloseConnectionOptions): Promise<void>;
488
541
  /**
489
542
  * Check if a particular group exists (i.e. has active connections).
490
543
  *