Skip to content

Commit bb749d0

Browse files
committed
build: release 3.0.0
1 parent c2bf70f commit bb749d0

File tree

8 files changed

+176
-18
lines changed

8 files changed

+176
-18
lines changed

dist/client.cjs

Lines changed: 70 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ __export(client_exports, {
3333
});
3434
module.exports = __toCommonJS(client_exports);
3535
var import_crypto2 = __toESM(require("crypto"), 1);
36-
var import_events = require("events");
3736
var import_fs2 = __toESM(require("fs"), 1);
3837
var import_url = require("url");
3938
var import_avro_js2 = __toESM(require("avro-js"), 1);
@@ -166,11 +165,26 @@ function parseEvent(schema, event) {
166165
throw new Error("Failed to parse changedFields", { cause: error });
167166
}
168167
}
168+
flattenSinglePropertyObjects(payload);
169169
return {
170170
replayId,
171171
payload
172172
};
173173
}
174+
function flattenSinglePropertyObjects(theObject) {
175+
Object.entries(theObject).forEach(([key, value]) => {
176+
if (key !== "ChangeEventHeader" && value && typeof value === "object") {
177+
const subKeys = Object.keys(value);
178+
if (subKeys.length === 1) {
179+
const subValue = value[subKeys[0]];
180+
theObject[key] = subValue;
181+
if (subValue && typeof subValue === "object") {
182+
flattenSinglePropertyObjects(theObject[key]);
183+
}
184+
}
185+
}
186+
});
187+
}
174188
function parseFieldBitmaps(allFields, fieldBitmapsAsHex) {
175189
if (fieldBitmapsAsHex.length === 0) {
176190
return [];
@@ -366,6 +380,52 @@ function base64url(input) {
366380
return buf.toString("base64url");
367381
}
368382

383+
// src/pubSubEventEmitter.js
384+
var import_events = require("events");
385+
var PubSubEventEmitter = class extends import_events.EventEmitter {
386+
#topicName;
387+
#requestedEventCount;
388+
#receivedEventCount;
389+
/**
390+
* Create a new EventEmitter for Pub/Sub API events
391+
* @param {string} topicName
392+
* @param {number} requestedEventCount
393+
*/
394+
constructor(topicName, requestedEventCount) {
395+
super();
396+
this.#topicName = topicName;
397+
this.#requestedEventCount = requestedEventCount;
398+
this.#receivedEventCount = 0;
399+
}
400+
emit(eventName, args) {
401+
if (eventName === "data") {
402+
this.#receivedEventCount++;
403+
}
404+
return super.emit(eventName, args);
405+
}
406+
/**
407+
* Returns the number of events that were requested during the subscription
408+
* @returns {number} the number of events that were requested
409+
*/
410+
getRequestedEventCount() {
411+
return this.#requestedEventCount;
412+
}
413+
/**
414+
* Returns the number of events that were received since the subscription
415+
* @returns {number} the number of events that were received
416+
*/
417+
getReceivedEventCount() {
418+
return this.#receivedEventCount;
419+
}
420+
/**
421+
* Returns the topic name for this subscription
422+
* @returns {string} the topic name
423+
*/
424+
getTopicName() {
425+
return this.#topicName;
426+
}
427+
};
428+
369429
// src/client.js
370430
var PubSubApiClient = class {
371431
/**
@@ -492,7 +552,6 @@ var PubSubApiClient = class {
492552
* Subscribes to a topic and retrieves all past events in retention window
493553
* @param {string} topicName name of the topic that we're subscribing to
494554
* @param {number} numRequested number of events requested
495-
* @param {number} replayId replay ID
496555
* @returns {Promise<EventEmitter>} Promise that holds an emitter that allows you to listen to received events and stream lifecycle events
497556
*/
498557
async subscribeFromEarliestEvent(topicName, numRequested) {
@@ -531,9 +590,8 @@ var PubSubApiClient = class {
531590
}
532591
/**
533592
* Subscribes to a topic using the gRPC client and an event schema
534-
* @param {string} topicName name of the topic that we're subscribing to
535-
* @param {number} numRequested number of events requested
536-
* @return {EventEmitter} emitter that allows you to listen to received events and stream lifecycle events
593+
* @param {object} subscribeRequest subscription request
594+
* @return {PubSubEventEmitter} emitter that allows you to listen to received events and stream lifecycle events
537595
*/
538596
async #subscribe(subscribeRequest) {
539597
try {
@@ -548,7 +606,10 @@ var PubSubApiClient = class {
548606
this.#logger.info(
549607
`Subscribe request sent for ${subscribeRequest.numRequested} events from ${subscribeRequest.topicName}...`
550608
);
551-
const eventEmitter = new import_events.EventEmitter();
609+
const eventEmitter = new PubSubEventEmitter(
610+
subscribeRequest.topicName,
611+
subscribeRequest.numRequested
612+
);
552613
subscription.on("data", (data) => {
553614
if (data.events) {
554615
const latestReplayId = decodeReplayId(data.latestReplayId);
@@ -559,6 +620,9 @@ var PubSubApiClient = class {
559620
const parsedEvent = parseEvent(schema, event);
560621
this.#logger.debug(parsedEvent);
561622
eventEmitter.emit("data", parsedEvent);
623+
if (eventEmitter.getReceivedEventCount() === eventEmitter.getRequestedEventCount()) {
624+
eventEmitter.emit("lastevent");
625+
}
562626
});
563627
} else {
564628
}

dist/client.d.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ export default class PubSubApiClient {
4141
* Subscribes to a topic and retrieves all past events in retention window
4242
* @param {string} topicName name of the topic that we're subscribing to
4343
* @param {number} numRequested number of events requested
44-
* @param {number} replayId replay ID
4544
* @returns {Promise<EventEmitter>} Promise that holds an emitter that allows you to listen to received events and stream lifecycle events
4645
*/
4746
subscribeFromEarliestEvent(topicName: string, numRequested: number): Promise<EventEmitter>;
@@ -87,5 +86,4 @@ export type Logger = {
8786
info: Function;
8887
error: Function;
8988
};
90-
import { EventEmitter } from 'events';
9189
//# sourceMappingURL=client.d.ts.map

dist/client.d.ts.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/client.js

Lines changed: 70 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// src/client.js
22
import crypto2 from "crypto";
3-
import { EventEmitter } from "events";
43
import fs2 from "fs";
54
import { fileURLToPath } from "url";
65
import avro2 from "avro-js";
@@ -133,11 +132,26 @@ function parseEvent(schema, event) {
133132
throw new Error("Failed to parse changedFields", { cause: error });
134133
}
135134
}
135+
flattenSinglePropertyObjects(payload);
136136
return {
137137
replayId,
138138
payload
139139
};
140140
}
141+
function flattenSinglePropertyObjects(theObject) {
142+
Object.entries(theObject).forEach(([key, value]) => {
143+
if (key !== "ChangeEventHeader" && value && typeof value === "object") {
144+
const subKeys = Object.keys(value);
145+
if (subKeys.length === 1) {
146+
const subValue = value[subKeys[0]];
147+
theObject[key] = subValue;
148+
if (subValue && typeof subValue === "object") {
149+
flattenSinglePropertyObjects(theObject[key]);
150+
}
151+
}
152+
}
153+
});
154+
}
141155
function parseFieldBitmaps(allFields, fieldBitmapsAsHex) {
142156
if (fieldBitmapsAsHex.length === 0) {
143157
return [];
@@ -333,6 +347,52 @@ function base64url(input) {
333347
return buf.toString("base64url");
334348
}
335349

350+
// src/pubSubEventEmitter.js
351+
import { EventEmitter } from "events";
352+
var PubSubEventEmitter = class extends EventEmitter {
353+
#topicName;
354+
#requestedEventCount;
355+
#receivedEventCount;
356+
/**
357+
* Create a new EventEmitter for Pub/Sub API events
358+
* @param {string} topicName
359+
* @param {number} requestedEventCount
360+
*/
361+
constructor(topicName, requestedEventCount) {
362+
super();
363+
this.#topicName = topicName;
364+
this.#requestedEventCount = requestedEventCount;
365+
this.#receivedEventCount = 0;
366+
}
367+
emit(eventName, args) {
368+
if (eventName === "data") {
369+
this.#receivedEventCount++;
370+
}
371+
return super.emit(eventName, args);
372+
}
373+
/**
374+
* Returns the number of events that were requested during the subscription
375+
* @returns {number} the number of events that were requested
376+
*/
377+
getRequestedEventCount() {
378+
return this.#requestedEventCount;
379+
}
380+
/**
381+
* Returns the number of events that were received since the subscription
382+
* @returns {number} the number of events that were received
383+
*/
384+
getReceivedEventCount() {
385+
return this.#receivedEventCount;
386+
}
387+
/**
388+
* Returns the topic name for this subscription
389+
* @returns {string} the topic name
390+
*/
391+
getTopicName() {
392+
return this.#topicName;
393+
}
394+
};
395+
336396
// src/client.js
337397
var PubSubApiClient = class {
338398
/**
@@ -459,7 +519,6 @@ var PubSubApiClient = class {
459519
* Subscribes to a topic and retrieves all past events in retention window
460520
* @param {string} topicName name of the topic that we're subscribing to
461521
* @param {number} numRequested number of events requested
462-
* @param {number} replayId replay ID
463522
* @returns {Promise<EventEmitter>} Promise that holds an emitter that allows you to listen to received events and stream lifecycle events
464523
*/
465524
async subscribeFromEarliestEvent(topicName, numRequested) {
@@ -498,9 +557,8 @@ var PubSubApiClient = class {
498557
}
499558
/**
500559
* Subscribes to a topic using the gRPC client and an event schema
501-
* @param {string} topicName name of the topic that we're subscribing to
502-
* @param {number} numRequested number of events requested
503-
* @return {EventEmitter} emitter that allows you to listen to received events and stream lifecycle events
560+
* @param {object} subscribeRequest subscription request
561+
* @return {PubSubEventEmitter} emitter that allows you to listen to received events and stream lifecycle events
504562
*/
505563
async #subscribe(subscribeRequest) {
506564
try {
@@ -515,7 +573,10 @@ var PubSubApiClient = class {
515573
this.#logger.info(
516574
`Subscribe request sent for ${subscribeRequest.numRequested} events from ${subscribeRequest.topicName}...`
517575
);
518-
const eventEmitter = new EventEmitter();
576+
const eventEmitter = new PubSubEventEmitter(
577+
subscribeRequest.topicName,
578+
subscribeRequest.numRequested
579+
);
519580
subscription.on("data", (data) => {
520581
if (data.events) {
521582
const latestReplayId = decodeReplayId(data.latestReplayId);
@@ -526,6 +587,9 @@ var PubSubApiClient = class {
526587
const parsedEvent = parseEvent(schema, event);
527588
this.#logger.debug(parsedEvent);
528589
eventEmitter.emit("data", parsedEvent);
590+
if (eventEmitter.getReceivedEventCount() === eventEmitter.getRequestedEventCount()) {
591+
eventEmitter.emit("lastevent");
592+
}
529593
});
530594
} else {
531595
}

dist/eventParser.d.ts.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/pubSubEventEmitter.d.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* EventEmitter wrapper for processing Pub/Sub API events
3+
* while keeping track of the topic name and the volume of events requested/received.
4+
*/
5+
export default class PubSubEventEmitter extends EventEmitter {
6+
/**
7+
* Create a new EventEmitter for Pub/Sub API events
8+
* @param {string} topicName
9+
* @param {number} requestedEventCount
10+
*/
11+
constructor(topicName: string, requestedEventCount: number);
12+
emit(eventName: any, args: any): boolean;
13+
/**
14+
* Returns the number of events that were requested during the subscription
15+
* @returns {number} the number of events that were requested
16+
*/
17+
getRequestedEventCount(): number;
18+
/**
19+
* Returns the number of events that were received since the subscription
20+
* @returns {number} the number of events that were received
21+
*/
22+
getReceivedEventCount(): number;
23+
/**
24+
* Returns the topic name for this subscription
25+
* @returns {string} the topic name
26+
*/
27+
getTopicName(): string;
28+
#private;
29+
}
30+
import { EventEmitter } from 'events';
31+
//# sourceMappingURL=pubSubEventEmitter.d.ts.map

dist/pubSubEventEmitter.d.ts.map

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "salesforce-pubsub-api-client",
3-
"version": "2.4.4",
3+
"version": "3.0.0",
44
"type": "module",
55
"description": "A node client for the Salesforce Pub/Sub API",
66
"author": "pozil",
@@ -28,7 +28,7 @@
2828
"certifi": "^14.5.15",
2929
"dotenv": "^16.3.1",
3030
"jsforce": "^1.11.1",
31-
"undici": "^5.23.3"
31+
"undici": "^5.23.4"
3232
},
3333
"devDependencies": {
3434
"@chialab/esbuild-plugin-meta-url": "^0.17.7",

0 commit comments

Comments
 (0)