@fraym/streams 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # streams-go
1
+ # streams-nodejs
2
2
 
3
3
  Client implementation in javascript for the event streaming service [streams](https://github.com/fraym-work/streams).
4
4
 
@@ -22,9 +22,10 @@ const client = await newClient({
22
22
  ### Publish events
23
23
 
24
24
  Events are published in a transactional manner:
25
- * you can publish a set of events in a transaction
26
- * if one event in your set cannot be published no event will be published
27
- * as soon as all events are published they appear in their streams
25
+
26
+ - you can publish a set of events in a transaction
27
+ - if one event in your set cannot be published no event will be published
28
+ - as soon as all events are published they appear in their streams
28
29
 
29
30
  You can only publish events of one topic per transaction.
30
31
  Most of the fields of an event are optional. You do not have to use or specify them, but you can use them if you want to.
@@ -39,7 +40,7 @@ await client.publish("topic", [
39
40
  },
40
41
  // set `broadcast` to true if you want all subscribers of a group to process the event.
41
42
  // set to false (or remove) if you want this event to be handled only once by a group of subscribers.
42
- broadcast: false,
43
+ broadcast: false,
43
44
  type: "event-type",
44
45
  stream: "stream-name",
45
46
  correlationId: uuid(),
@@ -95,11 +96,11 @@ One client instance is only able to subscribe once. If you try to subscribe twic
95
96
 
96
97
  ### Get all events for a given topic filter
97
98
 
98
- The `getAllEvents` function uses the same filter logic as described for the [subscribe](#subscribe-to-events) function
99
+ The `getAllEvents` function uses the same topic filter parameters as described for the [subscribe](#subscribe-to-events) function
99
100
 
100
101
  ```typescript
101
102
  await client.getAllEvents(async (event: SubscriptionEvent) => {
102
- // @todo: handle the event in this callback
103
+ // @todo: handle the event in this callback
103
104
  });
104
105
  ```
105
106
 
@@ -108,7 +109,7 @@ await client.getAllEvents(async (event: SubscriptionEvent) => {
108
109
  You will not need to use this if you use our GDPR service.
109
110
 
110
111
  ```typescript
111
- await client.invalidateGdprData("tenantId", "topic-1", "grprId")
112
+ await client.invalidateGdprData("tenantId", "topic-1", "grprId");
112
113
  ```
113
114
 
114
115
  ### Create a snapshot of a topic
@@ -134,3 +135,38 @@ You won't lose any data if you don't. Use it for your peace of mind.
134
135
  ```typescript
135
136
  client.close();
136
137
  ```
138
+
139
+ ## Development
140
+
141
+ You'll need the following apps for a smooth development experience:
142
+
143
+ - minikube
144
+ - lens
145
+ - okteto
146
+ - helm
147
+
148
+ ### Running the dev environment
149
+
150
+ - Start minikube if not already done:
151
+
152
+ ```shell
153
+ minikube start
154
+ ```
155
+
156
+ - add mongodb and minio to your lokal kubernetes
157
+ - use Makefiles in `./.dev/*`
158
+ - copy `.env.build` to `.env.build.local`
159
+ - add your personal access token (needs read access for private fraym org repositories)
160
+ - deploy the app to your cluster
161
+
162
+ ```
163
+ make init
164
+ ```
165
+
166
+ - start okteto
167
+
168
+ ```
169
+ make dev
170
+ ```
171
+
172
+ - connect your IDE to that okteto instance
@@ -0,0 +1,3 @@
1
+ import { ServiceClient } from "@fraym/streams-proto";
2
+ import { HandlerFunc } from "./event";
3
+ export declare const getAllEvents: (includedTopics: string[], excludedTopics: string[], handler: HandlerFunc, serviceClient: ServiceClient) => Promise<void>;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getAllEvents = void 0;
4
+ const event_1 = require("./event");
5
+ const getAllEvents = async (includedTopics, excludedTopics, handler, serviceClient) => {
6
+ const stream = serviceClient.getEventsFromStart({
7
+ excludedTopics,
8
+ includedTopics,
9
+ });
10
+ return new Promise((resolve, reject) => {
11
+ stream.on("data", (data) => {
12
+ const event = (0, event_1.getSubscriptionEvent)(data);
13
+ if (event) {
14
+ handler(event);
15
+ }
16
+ });
17
+ stream.on("end", () => {
18
+ resolve();
19
+ });
20
+ stream.on("error", e => {
21
+ reject(e);
22
+ });
23
+ });
24
+ };
25
+ exports.getAllEvents = getAllEvents;
@@ -0,0 +1,14 @@
1
+ import { ClientConfig } from "./config";
2
+ import { HandlerFunc, PublishEvent, SubscriptionEvent } from "./event";
3
+ export interface Client {
4
+ getAllEvents: (handler: HandlerFunc, includedTopics?: string[], excludedTopics?: string[]) => Promise<void>;
5
+ getStream: (tenantId: string, stream: string) => Promise<SubscriptionEvent[]>;
6
+ useEventHandler: (type: string, handler: HandlerFunc) => void;
7
+ useEventHandlerForAllEventTypes: (handler: HandlerFunc) => void;
8
+ subscribe: (includedTopics?: string[], excludedTopics?: string[]) => Promise<void>;
9
+ publish: (topic: string, events: PublishEvent[]) => Promise<void>;
10
+ invalidateGdprData: (tenantId: string, topic: string, gdprId: string) => Promise<void>;
11
+ createSnapshot: (topic: string, toTime: Date) => Promise<void>;
12
+ close: () => void;
13
+ }
14
+ export declare const newClient: (config: ClientConfig) => Promise<Client>;
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.newClient = void 0;
4
+ const streams_proto_1 = require("@fraym/streams-proto");
5
+ const grpc_js_1 = require("@grpc/grpc-js");
6
+ const allEvents_1 = require("./allEvents");
7
+ const config_1 = require("./config");
8
+ const alreadySubscribed_1 = require("./errors/alreadySubscribed");
9
+ const handler_1 = require("./handler");
10
+ const init_1 = require("./init");
11
+ const invalidateGdpr_1 = require("./invalidateGdpr");
12
+ const publish_1 = require("./publish");
13
+ const snapshot_1 = require("./snapshot");
14
+ const stream_1 = require("./stream");
15
+ const subscribe_1 = require("./subscribe");
16
+ const newClient = async (config) => {
17
+ config = (0, config_1.useConfigDefaults)(config);
18
+ const serviceClient = new streams_proto_1.ServiceClient(config.serverAddress, grpc_js_1.credentials.createInsecure(), {
19
+ "grpc.keepalive_time_ms": config.keepaliveInterval,
20
+ "grpc.keepalive_timeout_ms": config.keepaliveTimeout,
21
+ "grpc.keepalive_permit_without_calls": 1,
22
+ });
23
+ const stream = await (0, init_1.initStream)(config, serviceClient);
24
+ const eventHandler = (0, handler_1.initEventHandler)(stream);
25
+ let hasSubscribed = false;
26
+ return {
27
+ getAllEvents: async (handler, includedTopics = [], excludedTopics = []) => {
28
+ await (0, allEvents_1.getAllEvents)(includedTopics, excludedTopics, handler, serviceClient);
29
+ },
30
+ getStream: async (tenantId, stream) => {
31
+ return await (0, stream_1.getStream)(tenantId, stream, serviceClient);
32
+ },
33
+ useEventHandler: (type, handler) => {
34
+ eventHandler.addHandler(type, handler);
35
+ },
36
+ useEventHandlerForAllEventTypes: handler => {
37
+ eventHandler.addHandlerForAllTypes(handler);
38
+ },
39
+ subscribe: async (includedTopics = [], excludedTopics = []) => {
40
+ if (hasSubscribed) {
41
+ throw new alreadySubscribed_1.AlreadySubscribedError();
42
+ }
43
+ return await (0, subscribe_1.sendSubscribe)(includedTopics, excludedTopics, config, stream);
44
+ },
45
+ publish: async (topic, events) => {
46
+ return (0, publish_1.sendPublish)(topic, events, config, stream);
47
+ },
48
+ invalidateGdprData: async (tenantId, topic, gdprId) => {
49
+ return await (0, invalidateGdpr_1.sendInvalidateGdpr)(tenantId, topic, gdprId, config, stream);
50
+ },
51
+ createSnapshot: async (topic, toTime) => {
52
+ return await (0, snapshot_1.sendSnapshot)(topic, toTime, config, stream);
53
+ },
54
+ close: () => {
55
+ stream.end();
56
+ },
57
+ };
58
+ };
59
+ exports.newClient = newClient;
@@ -0,0 +1,8 @@
1
+ export interface ClientConfig {
2
+ serverAddress: string;
3
+ groupId: string;
4
+ ackTimeout?: number;
5
+ keepaliveInterval?: number;
6
+ keepaliveTimeout?: number;
7
+ }
8
+ export declare const useConfigDefaults: (config: ClientConfig) => Required<ClientConfig>;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useConfigDefaults = void 0;
4
+ const useConfigDefaults = (config) => {
5
+ var _a, _b, _c;
6
+ return {
7
+ serverAddress: config.serverAddress,
8
+ groupId: config.groupId,
9
+ ackTimeout: (_a = config.ackTimeout) !== null && _a !== void 0 ? _a : 1000,
10
+ keepaliveTimeout: (_b = config.keepaliveTimeout) !== null && _b !== void 0 ? _b : 3 * 1000,
11
+ keepaliveInterval: (_c = config.keepaliveInterval) !== null && _c !== void 0 ? _c : 40 * 1000,
12
+ };
13
+ };
14
+ exports.useConfigDefaults = useConfigDefaults;
@@ -0,0 +1,3 @@
1
+ export declare class AlreadySubscribedError extends Error {
2
+ constructor();
3
+ }
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AlreadySubscribedError = void 0;
4
+ class AlreadySubscribedError extends Error {
5
+ constructor() {
6
+ super("streams client is already subscribed to a set of topics");
7
+ }
8
+ }
9
+ exports.AlreadySubscribedError = AlreadySubscribedError;
@@ -0,0 +1,25 @@
1
+ import { PublishEventEnvelope } from "@fraym/streams-proto";
2
+ export interface SubscriptionEvent extends BaseEvent {
3
+ topic: string;
4
+ raisedAt: Date;
5
+ }
6
+ export interface PublishEvent extends BaseEvent {
7
+ broadcast?: boolean;
8
+ }
9
+ export interface BaseEvent {
10
+ id: string;
11
+ payload: Record<string, EventData>;
12
+ tenantId: string;
13
+ type?: string;
14
+ stream?: string;
15
+ correlationId?: string;
16
+ causationId?: string;
17
+ reason?: string;
18
+ }
19
+ export declare type EventData = string | GdprEventData;
20
+ export interface GdprEventData {
21
+ value: string;
22
+ gdprDefault: string;
23
+ }
24
+ export declare type HandlerFunc = (event: SubscriptionEvent) => Promise<void>;
25
+ export declare const getSubscriptionEvent: (eventEnvelope: PublishEventEnvelope) => SubscriptionEvent | null;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getSubscriptionEvent = void 0;
4
+ const getSubscriptionEvent = (eventEnvelope) => {
5
+ var _a;
6
+ const event = eventEnvelope.event;
7
+ if (!event) {
8
+ return null;
9
+ }
10
+ const payload = {};
11
+ for (const key in event.payload) {
12
+ if (Object.prototype.hasOwnProperty.call(event.payload, key)) {
13
+ const data = event.payload[key];
14
+ if (data.metadata && data.metadata.gdpr) {
15
+ payload[key] = {
16
+ value: data.value,
17
+ gdprDefault: (_a = data.metadata.gdpr.default) !== null && _a !== void 0 ? _a : "",
18
+ };
19
+ }
20
+ else {
21
+ payload[key] = data.value;
22
+ }
23
+ }
24
+ }
25
+ return {
26
+ id: event.id,
27
+ topic: eventEnvelope.topic,
28
+ tenantId: eventEnvelope.tenantId,
29
+ payload,
30
+ raisedAt: new Date(event.raisedAt),
31
+ stream: event.stream || undefined,
32
+ type: event.type || undefined,
33
+ causationId: event.causationId || undefined,
34
+ correlationId: event.correlationId || undefined,
35
+ reason: event.reason || undefined,
36
+ };
37
+ };
38
+ exports.getSubscriptionEvent = getSubscriptionEvent;
@@ -0,0 +1,8 @@
1
+ import { Stream } from "./init";
2
+ import { HandlerFunc } from "./event";
3
+ interface EventHandler {
4
+ addHandler: (type: string, handler: HandlerFunc) => void;
5
+ addHandlerForAllTypes: (handler: HandlerFunc) => void;
6
+ }
7
+ export declare const initEventHandler: (stream: Stream) => EventHandler;
8
+ export {};
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.initEventHandler = void 0;
4
+ const event_1 = require("./event");
5
+ const initEventHandler = (stream) => {
6
+ const typeHandlerMap = {};
7
+ const globalHandlers = [];
8
+ stream.on("data", (data) => {
9
+ var _a, _b, _c;
10
+ if (((_a = data.data) === null || _a === void 0 ? void 0 : _a.$case) !== "event") {
11
+ return;
12
+ }
13
+ const event = (0, event_1.getSubscriptionEvent)(data.data.event);
14
+ if (!event) {
15
+ return;
16
+ }
17
+ const typeHandlers = (_c = typeHandlerMap[(_b = event.type) !== null && _b !== void 0 ? _b : ""]) !== null && _c !== void 0 ? _c : [];
18
+ typeHandlers.forEach(handler => handleEvent(event, handler, stream));
19
+ globalHandlers.forEach(handler => handleEvent(event, handler, stream));
20
+ });
21
+ return {
22
+ addHandler: (type, handler) => {
23
+ if (!typeHandlerMap[type]) {
24
+ typeHandlerMap[type] = [handler];
25
+ }
26
+ else {
27
+ typeHandlerMap[type].push(handler);
28
+ }
29
+ },
30
+ addHandlerForAllTypes: handler => {
31
+ globalHandlers.push(handler);
32
+ },
33
+ };
34
+ };
35
+ exports.initEventHandler = initEventHandler;
36
+ const handleEvent = (event, handler, stream) => {
37
+ handler(event)
38
+ .then(() => {
39
+ stream.write(newEventAckRequest(event.tenantId, event.topic, event.id));
40
+ })
41
+ .catch(e => {
42
+ stream.write(newEventNotAckRequest(event.tenantId, event.topic, event.id, e));
43
+ });
44
+ };
45
+ const newEventAckRequest = (tenantId, topic, eventId) => {
46
+ return {
47
+ payload: {
48
+ $case: "eventAck",
49
+ eventAck: {
50
+ eventId,
51
+ tenantId,
52
+ topic,
53
+ },
54
+ },
55
+ };
56
+ };
57
+ const newEventNotAckRequest = (tenantId, topic, eventId, reason) => {
58
+ return {
59
+ payload: {
60
+ $case: "eventNotAck",
61
+ eventNotAck: {
62
+ eventId,
63
+ tenantId,
64
+ topic,
65
+ reason,
66
+ },
67
+ },
68
+ };
69
+ };
@@ -0,0 +1,5 @@
1
+ import { ClientConfig } from "./config";
2
+ import { ClientDuplexStream } from "@grpc/grpc-js";
3
+ import { Request, ServiceClient, Response } from "@fraym/streams-proto";
4
+ export declare type Stream = ClientDuplexStream<Request, Response>;
5
+ export declare const initStream: (config: ClientConfig, serviceClient: ServiceClient) => Promise<Stream>;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.initStream = void 0;
4
+ const uuid_1 = require("uuid");
5
+ const initStream = async (config, serviceClient) => {
6
+ const stream = serviceClient.connect();
7
+ stream.on("end", stream.end);
8
+ return new Promise((resolve, reject) => {
9
+ stream.once("data", (data) => {
10
+ var _a;
11
+ if (((_a = data.data) === null || _a === void 0 ? void 0 : _a.$case) !== "initAck") {
12
+ reject("connection to streams service was not initialized correctly");
13
+ return;
14
+ }
15
+ resolve(stream);
16
+ });
17
+ stream.write(newInitRequest(config));
18
+ });
19
+ };
20
+ exports.initStream = initStream;
21
+ const newInitAction = (config) => {
22
+ return {
23
+ groupId: config.groupId,
24
+ subscriberId: (0, uuid_1.v4)(),
25
+ };
26
+ };
27
+ const newInitRequest = (config) => {
28
+ return {
29
+ payload: {
30
+ $case: "init",
31
+ init: newInitAction(config),
32
+ },
33
+ };
34
+ };
@@ -0,0 +1,3 @@
1
+ import { ClientConfig } from "./config";
2
+ import { Stream } from "./init";
3
+ export declare const sendInvalidateGdpr: (tenantId: string, topic: string, gdprId: string, config: ClientConfig, stream: Stream) => Promise<void>;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sendInvalidateGdpr = void 0;
4
+ const sendInvalidateGdpr = async (tenantId, topic, gdprId, config, stream) => {
5
+ stream.write(newInvalidateGdprRequest(tenantId, topic, gdprId));
6
+ return new Promise((resolve, reject) => {
7
+ const timeout = setTimeout(() => {
8
+ stream.off("data", fn);
9
+ reject("did not receive invalidate gdpr ack in configured timeout range");
10
+ }, config.ackTimeout);
11
+ const fn = (data) => {
12
+ var _a, _b;
13
+ if (((_a = data.data) === null || _a === void 0 ? void 0 : _a.$case) === "invalidateGdprNotAck") {
14
+ const notAck = data.data.invalidateGdprNotAck;
15
+ if (notAck.tenantId === tenantId &&
16
+ notAck.topic === topic &&
17
+ notAck.gdprId === gdprId) {
18
+ clearTimeout(timeout);
19
+ stream.off("data", fn);
20
+ reject(`did receive invalidate gdpr not ack message, reason: ${notAck.reason}`);
21
+ return;
22
+ }
23
+ }
24
+ if (((_b = data.data) === null || _b === void 0 ? void 0 : _b.$case) === "invalidateGdprAck") {
25
+ const ack = data.data.invalidateGdprAck;
26
+ if (ack.tenantId === tenantId && ack.topic === topic && ack.gdprId === gdprId) {
27
+ clearTimeout(timeout);
28
+ stream.off("data", fn);
29
+ resolve();
30
+ return;
31
+ }
32
+ }
33
+ };
34
+ stream.on("data", fn);
35
+ });
36
+ };
37
+ exports.sendInvalidateGdpr = sendInvalidateGdpr;
38
+ const newInvalidateGdprRequest = (tenantId, topic, gdprId) => {
39
+ return {
40
+ payload: {
41
+ $case: "invalidateGdpr",
42
+ invalidateGdpr: {
43
+ tenantId,
44
+ topic,
45
+ gdprId,
46
+ },
47
+ },
48
+ };
49
+ };
@@ -0,0 +1,4 @@
1
+ import { Stream } from "./init";
2
+ import { ClientConfig } from "./config";
3
+ import { PublishEvent } from "./event";
4
+ export declare const sendPublish: (topic: string, events: PublishEvent[], config: ClientConfig, stream: Stream) => Promise<void>;
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sendPublish = void 0;
4
+ const uuid_1 = require("uuid");
5
+ const sendPublish = async (topic, events, config, stream) => {
6
+ const publishActionId = (0, uuid_1.v4)();
7
+ stream.write(newPublishRequest(publishActionId, topic, events));
8
+ return new Promise((resolve, reject) => {
9
+ const timeout = setTimeout(() => {
10
+ stream.off("data", fn);
11
+ reject("did not receive publish ack in configured timeout range");
12
+ }, config.ackTimeout);
13
+ const fn = (data) => {
14
+ var _a, _b;
15
+ if (((_a = data.data) === null || _a === void 0 ? void 0 : _a.$case) === "publishAck" &&
16
+ data.data.publishAck.publishActionId === publishActionId) {
17
+ clearTimeout(timeout);
18
+ stream.off("data", fn);
19
+ resolve();
20
+ return;
21
+ }
22
+ if (((_b = data.data) === null || _b === void 0 ? void 0 : _b.$case) === "publishNotAck" &&
23
+ data.data.publishNotAck.publishActionId === publishActionId) {
24
+ clearTimeout(timeout);
25
+ stream.off("data", fn);
26
+ reject(`did receive publish not ack message: ${data.data.publishNotAck.reason}`);
27
+ return;
28
+ }
29
+ };
30
+ stream.on("data", fn);
31
+ });
32
+ };
33
+ exports.sendPublish = sendPublish;
34
+ const newPublishRequest = (publishActionId, topic, events) => {
35
+ return {
36
+ payload: {
37
+ $case: "publish",
38
+ publish: {
39
+ topic,
40
+ publishActionId,
41
+ events: events.map(getEventEnvelopeFromPublishedEvent),
42
+ },
43
+ },
44
+ };
45
+ };
46
+ const getEventEnvelopeFromPublishedEvent = (event) => {
47
+ var _a, _b, _c, _d, _e, _f;
48
+ const payload = {};
49
+ for (const key in event.payload) {
50
+ const currentData = event.payload[key];
51
+ payload[key] =
52
+ typeof currentData === "string"
53
+ ? {
54
+ value: currentData,
55
+ }
56
+ : {
57
+ value: currentData.value,
58
+ metadata: {
59
+ $case: "gdpr",
60
+ gdpr: {
61
+ default: currentData.gdprDefault,
62
+ id: "",
63
+ },
64
+ },
65
+ };
66
+ }
67
+ return {
68
+ broadcast: (_a = event.broadcast) !== null && _a !== void 0 ? _a : false,
69
+ tenantId: event.tenantId,
70
+ event: {
71
+ id: event.id,
72
+ type: (_b = event.type) !== null && _b !== void 0 ? _b : "",
73
+ reason: (_c = event.reason) !== null && _c !== void 0 ? _c : "",
74
+ stream: (_d = event.stream) !== null && _d !== void 0 ? _d : "",
75
+ correlationId: (_e = event.correlationId) !== null && _e !== void 0 ? _e : "",
76
+ causationId: (_f = event.causationId) !== null && _f !== void 0 ? _f : "",
77
+ payload,
78
+ raisedAt: "",
79
+ },
80
+ };
81
+ };
@@ -0,0 +1,3 @@
1
+ import { ClientConfig } from "./config";
2
+ import { Stream } from "./init";
3
+ export declare const sendSnapshot: (topic: string, toTime: Date, config: ClientConfig, stream: Stream) => Promise<void>;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sendSnapshot = void 0;
4
+ const sendSnapshot = async (topic, toTime, config, stream) => {
5
+ stream.write(newSnapshotRequest(topic, toTime));
6
+ return new Promise((resolve, reject) => {
7
+ const timeout = setTimeout(() => {
8
+ stream.off("data", fn);
9
+ reject("did not receive snapshot ack in configured timeout range");
10
+ }, config.ackTimeout);
11
+ const fn = (data) => {
12
+ var _a, _b;
13
+ if (((_a = data.data) === null || _a === void 0 ? void 0 : _a.$case) === "snapshotNotAck" && data.data.snapshotNotAck.topic === topic) {
14
+ clearTimeout(timeout);
15
+ stream.off("data", fn);
16
+ reject(`did receive snapshot not ack message, reason: ${data.data.snapshotNotAck.reason}`);
17
+ return;
18
+ }
19
+ if (((_b = data.data) === null || _b === void 0 ? void 0 : _b.$case) === "snapshotAck" && data.data.snapshotAck.topic === topic) {
20
+ clearTimeout(timeout);
21
+ stream.off("data", fn);
22
+ resolve();
23
+ return;
24
+ }
25
+ };
26
+ stream.on("data", fn);
27
+ });
28
+ };
29
+ exports.sendSnapshot = sendSnapshot;
30
+ const newSnapshotRequest = (topic, toTime) => {
31
+ return {
32
+ payload: {
33
+ $case: "snapshot",
34
+ snapshot: {
35
+ topic,
36
+ toTime: toTime.toISOString(),
37
+ },
38
+ },
39
+ };
40
+ };
@@ -0,0 +1,3 @@
1
+ import { SubscriptionEvent } from "./event";
2
+ import { ServiceClient } from "@fraym/streams-proto";
3
+ export declare const getStream: (tenantId: string, stream: string, serviceClient: ServiceClient) => Promise<SubscriptionEvent[]>;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getStream = void 0;
4
+ const event_1 = require("./event");
5
+ const getStream = async (tenantId, stream, serviceClient) => {
6
+ return new Promise((resolve, reject) => {
7
+ serviceClient.getStream({
8
+ stream,
9
+ tenantId,
10
+ }, (error, response) => {
11
+ if (error) {
12
+ reject(error.message);
13
+ return;
14
+ }
15
+ resolve(response.events
16
+ .map(event_1.getSubscriptionEvent)
17
+ .filter(event => event !== null));
18
+ });
19
+ });
20
+ };
21
+ exports.getStream = getStream;
@@ -0,0 +1,3 @@
1
+ import { ClientConfig } from "./config";
2
+ import { Stream } from "./init";
3
+ export declare const sendSubscribe: (includedTopics: string[], excludedTopics: string[], config: ClientConfig, stream: Stream) => Promise<void>;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sendSubscribe = void 0;
4
+ const sendSubscribe = async (includedTopics, excludedTopics, config, stream) => {
5
+ stream.write(newSubscribeRequest(includedTopics, excludedTopics));
6
+ return new Promise((resolve, reject) => {
7
+ const timeout = setTimeout(() => {
8
+ stream.off("data", fn);
9
+ reject("did not receive subscribe ack in configured timeout range");
10
+ }, config.ackTimeout);
11
+ const fn = (data) => {
12
+ var _a, _b;
13
+ if (((_a = data.data) === null || _a === void 0 ? void 0 : _a.$case) === "subscribeNotAck") {
14
+ clearTimeout(timeout);
15
+ stream.off("data", fn);
16
+ reject(`did receive subscribe not ack message: ${data.data.subscribeNotAck.reason}`);
17
+ return;
18
+ }
19
+ if (((_b = data.data) === null || _b === void 0 ? void 0 : _b.$case) === "subscribeAck") {
20
+ clearTimeout(timeout);
21
+ stream.off("data", fn);
22
+ resolve();
23
+ return;
24
+ }
25
+ };
26
+ stream.on("data", fn);
27
+ });
28
+ };
29
+ exports.sendSubscribe = sendSubscribe;
30
+ const newSubscribeRequest = (includedTopics, excludedTopics) => {
31
+ return {
32
+ payload: {
33
+ $case: "subscribe",
34
+ subscribe: {
35
+ excludedTopics,
36
+ includedTopics,
37
+ },
38
+ },
39
+ };
40
+ };
@@ -0,0 +1,3 @@
1
+ export * from "./client/client";
2
+ export { HandlerFunc, PublishEvent, SubscriptionEvent } from "./client/event";
3
+ export { ClientConfig } from "./client/config";
package/dist/index.js ADDED
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./client/client"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fraym/streams",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "license": "UNLICENSED",
5
5
  "homepage": "https://github.com/fraym-work/streams-nodejs",
6
6
  "repository": {
@@ -23,20 +23,16 @@
23
23
  ],
24
24
  "main": "dist/index.js",
25
25
  "types": "dist/index.d.ts",
26
+ "dependencies": {
27
+ "@fraym/streams-proto": "^5.3.1",
28
+ "@grpc/grpc-js": "^1.7.2",
29
+ "uuid": "^9.0.0"
30
+ },
26
31
  "devDependencies": {
27
32
  "@becklyn/prettier": "^1.0.2",
28
- "@types/google-protobuf": "^3.15.6",
29
33
  "@types/uuid": "^8.3.4",
30
- "grpc_tools_node_protoc_ts": "^5.3.2",
31
- "grpc-tools": "^1.11.2",
32
34
  "prettier": "^2.7.1",
33
35
  "typescript": "^4.8.4"
34
36
  },
35
- "prettier": "@becklyn/prettier",
36
- "dependencies": {
37
- "@grpc/grpc-js": "^1.7.1",
38
- "grpc": "^1.24.11",
39
- "np": "^7.6.2",
40
- "uuid": "^9.0.0"
41
- }
37
+ "prettier": "@becklyn/prettier"
42
38
  }