effect-jetstream 1.0.0
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/LICENSE +21 -0
- package/README.md +182 -0
- package/dist/BlueskyRecord.d.ts +214 -0
- package/dist/BlueskyRecord.d.ts.map +1 -0
- package/dist/BlueskyRecord.js +88 -0
- package/dist/BlueskyRecord.js.map +1 -0
- package/dist/Jetstream.d.ts +47 -0
- package/dist/Jetstream.d.ts.map +1 -0
- package/dist/Jetstream.js +22 -0
- package/dist/Jetstream.js.map +1 -0
- package/dist/JetstreamClient.d.ts +51 -0
- package/dist/JetstreamClient.d.ts.map +1 -0
- package/dist/JetstreamClient.js +17 -0
- package/dist/JetstreamClient.js.map +1 -0
- package/dist/JetstreamConfig.d.ts +83 -0
- package/dist/JetstreamConfig.d.ts.map +1 -0
- package/dist/JetstreamConfig.js +23 -0
- package/dist/JetstreamConfig.js.map +1 -0
- package/dist/JetstreamError.d.ts +61 -0
- package/dist/JetstreamError.d.ts.map +1 -0
- package/dist/JetstreamError.js +45 -0
- package/dist/JetstreamError.js.map +1 -0
- package/dist/JetstreamMessage.d.ts +126 -0
- package/dist/JetstreamMessage.d.ts.map +1 -0
- package/dist/JetstreamMessage.js +96 -0
- package/dist/JetstreamMessage.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/client.d.ts +51 -0
- package/dist/internal/client.d.ts.map +1 -0
- package/dist/internal/client.js +122 -0
- package/dist/internal/client.js.map +1 -0
- package/dist/internal/decoder.d.ts +9 -0
- package/dist/internal/decoder.d.ts.map +1 -0
- package/dist/internal/decoder.js +152 -0
- package/dist/internal/decoder.js.map +1 -0
- package/dist/internal/jetstream.d.ts +47 -0
- package/dist/internal/jetstream.d.ts.map +1 -0
- package/dist/internal/jetstream.js +120 -0
- package/dist/internal/jetstream.js.map +1 -0
- package/dist/internal/websocket.d.ts +12 -0
- package/dist/internal/websocket.d.ts.map +1 -0
- package/dist/internal/websocket.js +36 -0
- package/dist/internal/websocket.js.map +1 -0
- package/package.json +50 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
import * as Context from "effect/Context";
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
import * as Layer from "effect/Layer";
|
|
7
|
+
import * as Ref from "effect/Ref";
|
|
8
|
+
import * as Schema from "effect/Schema";
|
|
9
|
+
import * as Stream from "effect/Stream";
|
|
10
|
+
import { Block, Follow, Like, Post, Profile, Repost } from "../BlueskyRecord.js";
|
|
11
|
+
import { ParseError } from "../JetstreamError.js";
|
|
12
|
+
import { tag as JetstreamTag } from "./jetstream.js";
|
|
13
|
+
/**
|
|
14
|
+
* @since 1.0.0
|
|
15
|
+
* @category symbols
|
|
16
|
+
*/
|
|
17
|
+
export const TypeId = Symbol.for("effect-jetstream/JetstreamClient");
|
|
18
|
+
/**
|
|
19
|
+
* @since 1.0.0
|
|
20
|
+
* @category tags
|
|
21
|
+
*/
|
|
22
|
+
export const tag = Context.GenericTag("effect-jetstream/JetstreamClient");
|
|
23
|
+
const recordSchemas = {
|
|
24
|
+
"app.bsky.feed.post": Post,
|
|
25
|
+
"app.bsky.feed.like": Like,
|
|
26
|
+
"app.bsky.feed.repost": Repost,
|
|
27
|
+
"app.bsky.graph.follow": Follow,
|
|
28
|
+
"app.bsky.graph.block": Block,
|
|
29
|
+
"app.bsky.actor.profile": Profile
|
|
30
|
+
};
|
|
31
|
+
const decodeRecord = (collection, record) => {
|
|
32
|
+
const schema = recordSchemas[collection];
|
|
33
|
+
return Schema.decodeUnknown(schema)(record).pipe(Effect.mapError((error) => new ParseError({
|
|
34
|
+
message: `Record schema validation failed for ${collection}: ${error.message}`
|
|
35
|
+
})));
|
|
36
|
+
};
|
|
37
|
+
const eventContext = (event) => {
|
|
38
|
+
if (event._tag === "CommitCreate" || event._tag === "CommitUpdate" || event._tag === "CommitDelete") {
|
|
39
|
+
return {
|
|
40
|
+
kind: event.kind,
|
|
41
|
+
did: event.did,
|
|
42
|
+
collection: event.commit.collection,
|
|
43
|
+
rkey: event.commit.rkey
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
kind: event.kind,
|
|
48
|
+
did: event.did
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
const logHandlerFailure = (label, event) => (cause) => Effect.logWarning("Jetstream handler failed", {
|
|
52
|
+
handler: label,
|
|
53
|
+
...eventContext(event),
|
|
54
|
+
cause
|
|
55
|
+
});
|
|
56
|
+
const logRecordFailure = (collection, error, event) => Effect.logWarning("Dropping malformed record", {
|
|
57
|
+
collection,
|
|
58
|
+
...eventContext(event),
|
|
59
|
+
message: error.message
|
|
60
|
+
});
|
|
61
|
+
/**
|
|
62
|
+
* @since 1.0.0
|
|
63
|
+
* @category layers
|
|
64
|
+
*/
|
|
65
|
+
export const layer = Layer.effect(tag, Effect.gen(function* () {
|
|
66
|
+
const jetstream = yield* JetstreamTag;
|
|
67
|
+
const handlers = yield* Ref.make([]);
|
|
68
|
+
const addHandler = (handler) => Ref.update(handlers, (current) => [...current, handler]);
|
|
69
|
+
const onCreate = Effect.fn("JetstreamClient.onCreate")((collection, handler) => addHandler((event) => {
|
|
70
|
+
if (event._tag !== "CommitCreate" || event.commit.collection !== collection) {
|
|
71
|
+
return Effect.void;
|
|
72
|
+
}
|
|
73
|
+
return decodeRecord(collection, event.commit.record).pipe(Effect.matchEffect({
|
|
74
|
+
onFailure: (error) => logRecordFailure(collection, error, event),
|
|
75
|
+
onSuccess: (record) => handler({
|
|
76
|
+
...event,
|
|
77
|
+
commit: {
|
|
78
|
+
...event.commit,
|
|
79
|
+
record
|
|
80
|
+
}
|
|
81
|
+
}).pipe(Effect.catchAllCause(logHandlerFailure("onCreate", event)))
|
|
82
|
+
}));
|
|
83
|
+
}));
|
|
84
|
+
const onUpdate = Effect.fn("JetstreamClient.onUpdate")((collection, handler) => addHandler((event) => {
|
|
85
|
+
if (event._tag !== "CommitUpdate" || event.commit.collection !== collection) {
|
|
86
|
+
return Effect.void;
|
|
87
|
+
}
|
|
88
|
+
return decodeRecord(collection, event.commit.record).pipe(Effect.matchEffect({
|
|
89
|
+
onFailure: (error) => logRecordFailure(collection, error, event),
|
|
90
|
+
onSuccess: (record) => handler({
|
|
91
|
+
...event,
|
|
92
|
+
commit: {
|
|
93
|
+
...event.commit,
|
|
94
|
+
record
|
|
95
|
+
}
|
|
96
|
+
}).pipe(Effect.catchAllCause(logHandlerFailure("onUpdate", event)))
|
|
97
|
+
}));
|
|
98
|
+
}));
|
|
99
|
+
const onDelete = Effect.fn("JetstreamClient.onDelete")((collection, handler) => addHandler((event) => {
|
|
100
|
+
if (event._tag !== "CommitDelete" || event.commit.collection !== collection) {
|
|
101
|
+
return Effect.void;
|
|
102
|
+
}
|
|
103
|
+
return handler(event).pipe(Effect.catchAllCause(logHandlerFailure("onDelete", event)));
|
|
104
|
+
}));
|
|
105
|
+
const on = Effect.fn("JetstreamClient.on")((kind, handler) => addHandler((event) => {
|
|
106
|
+
if (event.kind !== kind) {
|
|
107
|
+
return Effect.void;
|
|
108
|
+
}
|
|
109
|
+
return handler(event).pipe(Effect.catchAllCause(logHandlerFailure("on", event)));
|
|
110
|
+
}));
|
|
111
|
+
const dispatchEvent = Effect.fn("JetstreamClient.dispatchEvent")((event) => Ref.get(handlers).pipe(Effect.flatMap((current) => Effect.forEach(current, (handler) => handler(event), { discard: true }))));
|
|
112
|
+
const run = jetstream.stream.pipe(Stream.runForEach(dispatchEvent), Effect.zipRight(Effect.never));
|
|
113
|
+
return tag.of({
|
|
114
|
+
[TypeId]: TypeId,
|
|
115
|
+
onCreate,
|
|
116
|
+
onUpdate,
|
|
117
|
+
onDelete,
|
|
118
|
+
on,
|
|
119
|
+
run
|
|
120
|
+
});
|
|
121
|
+
}));
|
|
122
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/internal/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
5
|
+
import type { JetstreamDecoder } from "../JetstreamConfig.js";
|
|
6
|
+
import { ParseError } from "../JetstreamError.js";
|
|
7
|
+
import { type JetstreamMessage } from "../JetstreamMessage.js";
|
|
8
|
+
export declare const decodeMessage: (data: string | Uint8Array, decoder?: JetstreamDecoder) => Effect.Effect<JetstreamMessage, ParseError>;
|
|
9
|
+
//# sourceMappingURL=decoder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decoder.d.ts","sourceRoot":"","sources":["../../src/internal/decoder.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAGvC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACjD,OAAO,EAML,KAAK,gBAAgB,EACtB,MAAM,wBAAwB,CAAA;AAsD/B,eAAO,MAAM,aAAa,GACxB,MAAM,MAAM,GAAG,UAAU,EACzB,UAAU,gBAAgB,KACzB,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,UAAU,CA8G5C,CAAA"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
5
|
+
import * as Schema from "effect/Schema";
|
|
6
|
+
import { Did } from "../BlueskyRecord.js";
|
|
7
|
+
import { ParseError } from "../JetstreamError.js";
|
|
8
|
+
import { AccountEvent, CommitCreate, CommitDelete, CommitUpdate, IdentityEvent } from "../JetstreamMessage.js";
|
|
9
|
+
const textDecoder = new TextDecoder();
|
|
10
|
+
const Commit = Schema.Struct({
|
|
11
|
+
rev: Schema.String,
|
|
12
|
+
operation: Schema.Literal("create", "update", "delete"),
|
|
13
|
+
collection: Schema.String,
|
|
14
|
+
rkey: Schema.String,
|
|
15
|
+
record: Schema.optional(Schema.Unknown),
|
|
16
|
+
cid: Schema.optional(Schema.String)
|
|
17
|
+
});
|
|
18
|
+
const Identity = Schema.Struct({
|
|
19
|
+
did: Did,
|
|
20
|
+
handle: Schema.String,
|
|
21
|
+
seq: Schema.Number,
|
|
22
|
+
time: Schema.String
|
|
23
|
+
});
|
|
24
|
+
const Account = Schema.Struct({
|
|
25
|
+
active: Schema.Boolean,
|
|
26
|
+
did: Did,
|
|
27
|
+
seq: Schema.Number,
|
|
28
|
+
time: Schema.String,
|
|
29
|
+
status: Schema.optional(Schema.Literal("deactivated", "suspended", "deleted"))
|
|
30
|
+
});
|
|
31
|
+
const RawMessage = Schema.Struct({
|
|
32
|
+
did: Did,
|
|
33
|
+
time_us: Schema.Number,
|
|
34
|
+
kind: Schema.Literal("commit", "identity", "account"),
|
|
35
|
+
commit: Schema.optional(Commit),
|
|
36
|
+
identity: Schema.optional(Identity),
|
|
37
|
+
account: Schema.optional(Account)
|
|
38
|
+
});
|
|
39
|
+
const decodeRaw = Schema.decodeUnknown(Schema.parseJson(RawMessage));
|
|
40
|
+
const decodeText = (data, decoder) => {
|
|
41
|
+
if (typeof data === "string") {
|
|
42
|
+
return Effect.succeed(data);
|
|
43
|
+
}
|
|
44
|
+
if (!decoder) {
|
|
45
|
+
return Effect.succeed(textDecoder.decode(data));
|
|
46
|
+
}
|
|
47
|
+
return decoder(data).pipe(Effect.map((decoded) => textDecoder.decode(decoded)));
|
|
48
|
+
};
|
|
49
|
+
export const decodeMessage = (data, decoder) => {
|
|
50
|
+
return Effect.gen(function* () {
|
|
51
|
+
const text = yield* decodeText(data, decoder);
|
|
52
|
+
const raw = yield* decodeRaw(text).pipe(Effect.mapError((e) => new ParseError({
|
|
53
|
+
message: `Schema validation failed: ${e.message}`,
|
|
54
|
+
raw: text.slice(0, 200)
|
|
55
|
+
})));
|
|
56
|
+
if (raw.kind === "commit") {
|
|
57
|
+
if (!raw.commit) {
|
|
58
|
+
return yield* Effect.fail(new ParseError({
|
|
59
|
+
message: "Missing commit payload for commit event",
|
|
60
|
+
raw: text.slice(0, 200)
|
|
61
|
+
}));
|
|
62
|
+
}
|
|
63
|
+
const { commit } = raw;
|
|
64
|
+
const base = {
|
|
65
|
+
did: raw.did,
|
|
66
|
+
time_us: raw.time_us,
|
|
67
|
+
kind: "commit"
|
|
68
|
+
};
|
|
69
|
+
switch (commit.operation) {
|
|
70
|
+
case "create":
|
|
71
|
+
if (commit.record === undefined) {
|
|
72
|
+
return yield* Effect.fail(new ParseError({
|
|
73
|
+
message: "Missing record for commit create",
|
|
74
|
+
raw: text.slice(0, 200)
|
|
75
|
+
}));
|
|
76
|
+
}
|
|
77
|
+
return new CommitCreate({
|
|
78
|
+
...base,
|
|
79
|
+
commit: {
|
|
80
|
+
rev: commit.rev,
|
|
81
|
+
operation: "create",
|
|
82
|
+
collection: commit.collection,
|
|
83
|
+
rkey: commit.rkey,
|
|
84
|
+
record: commit.record,
|
|
85
|
+
cid: commit.cid
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
case "update":
|
|
89
|
+
if (commit.record === undefined) {
|
|
90
|
+
return yield* Effect.fail(new ParseError({
|
|
91
|
+
message: "Missing record for commit update",
|
|
92
|
+
raw: text.slice(0, 200)
|
|
93
|
+
}));
|
|
94
|
+
}
|
|
95
|
+
return new CommitUpdate({
|
|
96
|
+
...base,
|
|
97
|
+
commit: {
|
|
98
|
+
rev: commit.rev,
|
|
99
|
+
operation: "update",
|
|
100
|
+
collection: commit.collection,
|
|
101
|
+
rkey: commit.rkey,
|
|
102
|
+
record: commit.record,
|
|
103
|
+
cid: commit.cid
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
case "delete":
|
|
107
|
+
return new CommitDelete({
|
|
108
|
+
...base,
|
|
109
|
+
commit: {
|
|
110
|
+
rev: commit.rev,
|
|
111
|
+
operation: "delete",
|
|
112
|
+
collection: commit.collection,
|
|
113
|
+
rkey: commit.rkey
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (raw.kind === "identity") {
|
|
119
|
+
if (!raw.identity) {
|
|
120
|
+
return yield* Effect.fail(new ParseError({
|
|
121
|
+
message: "Missing identity payload for identity event",
|
|
122
|
+
raw: text.slice(0, 200)
|
|
123
|
+
}));
|
|
124
|
+
}
|
|
125
|
+
return new IdentityEvent({
|
|
126
|
+
did: raw.did,
|
|
127
|
+
time_us: raw.time_us,
|
|
128
|
+
kind: "identity",
|
|
129
|
+
identity: raw.identity
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
if (raw.kind === "account") {
|
|
133
|
+
if (!raw.account) {
|
|
134
|
+
return yield* Effect.fail(new ParseError({
|
|
135
|
+
message: "Missing account payload for account event",
|
|
136
|
+
raw: text.slice(0, 200)
|
|
137
|
+
}));
|
|
138
|
+
}
|
|
139
|
+
return new AccountEvent({
|
|
140
|
+
did: raw.did,
|
|
141
|
+
time_us: raw.time_us,
|
|
142
|
+
kind: "account",
|
|
143
|
+
account: raw.account
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
return yield* Effect.fail(new ParseError({
|
|
147
|
+
message: `Unknown event kind: ${raw.kind}`,
|
|
148
|
+
raw: text.slice(0, 200)
|
|
149
|
+
}));
|
|
150
|
+
});
|
|
151
|
+
};
|
|
152
|
+
//# sourceMappingURL=decoder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decoder.js","sourceRoot":"","sources":["../../src/internal/decoder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
import * as Socket from "@effect/platform/Socket";
|
|
5
|
+
import * as Context from "effect/Context";
|
|
6
|
+
import * as Effect from "effect/Effect";
|
|
7
|
+
import * as Layer from "effect/Layer";
|
|
8
|
+
import * as Stream from "effect/Stream";
|
|
9
|
+
import type { JetstreamConfig, OptionsUpdate, SubscriberSourcedMessage } from "../JetstreamConfig.js";
|
|
10
|
+
import { type JetstreamError } from "../JetstreamError.js";
|
|
11
|
+
import type { JetstreamMessage } from "../JetstreamMessage.js";
|
|
12
|
+
/**
|
|
13
|
+
* @since 1.0.0
|
|
14
|
+
* @category symbols
|
|
15
|
+
*/
|
|
16
|
+
export declare const TypeId: unique symbol;
|
|
17
|
+
/**
|
|
18
|
+
* @since 1.0.0
|
|
19
|
+
* @category symbols
|
|
20
|
+
*/
|
|
21
|
+
export type TypeId = typeof TypeId;
|
|
22
|
+
/**
|
|
23
|
+
* @since 1.0.0
|
|
24
|
+
* @category models
|
|
25
|
+
*/
|
|
26
|
+
export interface Jetstream {
|
|
27
|
+
readonly [TypeId]: TypeId;
|
|
28
|
+
readonly stream: Stream.Stream<JetstreamMessage, JetstreamError>;
|
|
29
|
+
readonly send: (message: SubscriberSourcedMessage) => Effect.Effect<void, JetstreamError>;
|
|
30
|
+
readonly updateOptions: (options: OptionsUpdate) => Effect.Effect<void, JetstreamError>;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* @since 1.0.0
|
|
34
|
+
* @category tags
|
|
35
|
+
*/
|
|
36
|
+
export declare const tag: Context.Tag<Jetstream, Jetstream>;
|
|
37
|
+
/**
|
|
38
|
+
* @since 1.0.0
|
|
39
|
+
* @category layers
|
|
40
|
+
*/
|
|
41
|
+
export declare const layer: (config: JetstreamConfig) => Layer.Layer<Jetstream, JetstreamError, Socket.WebSocketConstructor>;
|
|
42
|
+
/**
|
|
43
|
+
* @since 1.0.0
|
|
44
|
+
* @category layers
|
|
45
|
+
*/
|
|
46
|
+
export declare const live: (config: JetstreamConfig) => Layer.Layer<Jetstream, JetstreamError>;
|
|
47
|
+
//# sourceMappingURL=jetstream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jetstream.d.ts","sourceRoot":"","sources":["../../src/internal/jetstream.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,MAAM,MAAM,yBAAyB,CAAA;AACjD,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AAEzC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAOrC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,EAAE,eAAe,EAAoB,aAAa,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAA;AACvH,OAAO,EAA+B,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACvF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAI9D;;;GAGG;AACH,eAAO,MAAM,MAAM,EAAE,OAAO,MAAiD,CAAA;AAE7E;;;GAGG;AACH,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAA;AAElC;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAA;IAChE,QAAQ,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC,CAAA;IACzF,QAAQ,CAAC,aAAa,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC,CAAA;CACxF;AAED;;;GAGG;AACH,eAAO,MAAM,GAAG,mCAA8D,CAAA;AA6B9E;;;GAGG;AACH,eAAO,MAAM,KAAK,GAChB,QAAQ,eAAe,KACtB,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,cAAc,EAAE,MAAM,CAAC,oBAAoB,CA2HlE,CAAA;AAEH;;;GAGG;AACH,eAAO,MAAM,IAAI,GACf,QAAQ,eAAe,KACtB,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,cAAc,CAGrC,CAAA"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
import * as Socket from "@effect/platform/Socket";
|
|
5
|
+
import * as Context from "effect/Context";
|
|
6
|
+
import * as Deferred from "effect/Deferred";
|
|
7
|
+
import * as Effect from "effect/Effect";
|
|
8
|
+
import * as Layer from "effect/Layer";
|
|
9
|
+
import * as Mailbox from "effect/Mailbox";
|
|
10
|
+
import * as Option from "effect/Option";
|
|
11
|
+
import * as Queue from "effect/Queue";
|
|
12
|
+
import * as Ref from "effect/Ref";
|
|
13
|
+
import * as Schedule from "effect/Schedule";
|
|
14
|
+
import * as Scope from "effect/Scope";
|
|
15
|
+
import * as Stream from "effect/Stream";
|
|
16
|
+
import { ConnectionError, ParseError } from "../JetstreamError.js";
|
|
17
|
+
import { decodeMessage } from "./decoder.js";
|
|
18
|
+
import { buildUrl } from "./websocket.js";
|
|
19
|
+
/**
|
|
20
|
+
* @since 1.0.0
|
|
21
|
+
* @category symbols
|
|
22
|
+
*/
|
|
23
|
+
export const TypeId = Symbol.for("effect-jetstream/Jetstream");
|
|
24
|
+
/**
|
|
25
|
+
* @since 1.0.0
|
|
26
|
+
* @category tags
|
|
27
|
+
*/
|
|
28
|
+
export const tag = Context.GenericTag("effect-jetstream/Jetstream");
|
|
29
|
+
const reconnectSchedule = Schedule.exponential("1 second").pipe(Schedule.union(Schedule.spaced("30 seconds")));
|
|
30
|
+
const outboundBufferSize = 1024;
|
|
31
|
+
const defaultZstdDecoder = (data) => Effect.tryPromise({
|
|
32
|
+
try: () => Bun.zstdDecompress(data),
|
|
33
|
+
catch: (error) => new ParseError({
|
|
34
|
+
message: `Zstd decompression failed: ${String(error)}`
|
|
35
|
+
})
|
|
36
|
+
});
|
|
37
|
+
const resolveDecoder = (config) => {
|
|
38
|
+
if (!config.compress) {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
return config.decoder ?? defaultZstdDecoder;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* @since 1.0.0
|
|
45
|
+
* @category layers
|
|
46
|
+
*/
|
|
47
|
+
export const layer = (config) => Layer.scoped(tag, Effect.gen(function* () {
|
|
48
|
+
const url = buildUrl(config);
|
|
49
|
+
const scope = yield* Effect.scope;
|
|
50
|
+
const mailbox = yield* Mailbox.make();
|
|
51
|
+
const outbound = yield* Queue.bounded(outboundBufferSize);
|
|
52
|
+
const pending = yield* Ref.make(Option.none());
|
|
53
|
+
const decoder = resolveDecoder(config);
|
|
54
|
+
if (config.compress && config.decoder === undefined) {
|
|
55
|
+
yield* Effect.logWarning("Jetstream compression enabled without a custom decoder; using Bun.zstdDecompress without a dictionary.");
|
|
56
|
+
}
|
|
57
|
+
const shutdown = Effect.gen(function* () {
|
|
58
|
+
const closed = new ConnectionError({
|
|
59
|
+
reason: "Closed",
|
|
60
|
+
cause: "Jetstream shutdown"
|
|
61
|
+
});
|
|
62
|
+
const pendingValue = yield* Ref.get(pending);
|
|
63
|
+
if (Option.isSome(pendingValue)) {
|
|
64
|
+
yield* Deferred.fail(pendingValue.value.done, closed);
|
|
65
|
+
}
|
|
66
|
+
const remaining = yield* Queue.takeAll(outbound);
|
|
67
|
+
for (const item of remaining) {
|
|
68
|
+
yield* Deferred.fail(item.done, closed);
|
|
69
|
+
}
|
|
70
|
+
yield* Queue.shutdown(outbound);
|
|
71
|
+
yield* mailbox.end;
|
|
72
|
+
});
|
|
73
|
+
yield* Scope.addFinalizer(scope, shutdown);
|
|
74
|
+
const logDecodeError = (error) => Effect.logWarning("Dropping malformed Jetstream message", {
|
|
75
|
+
message: error.message,
|
|
76
|
+
raw: error.raw
|
|
77
|
+
});
|
|
78
|
+
const handleIncoming = Effect.fn("Jetstream.handleIncoming")((data) => decodeMessage(data, decoder).pipe(Effect.flatMap((message) => mailbox.offer(message)), Effect.asVoid, Effect.catchAll(logDecodeError)));
|
|
79
|
+
const takeNextOutbound = Effect.uninterruptibleMask((restore) => Ref.get(pending).pipe(Effect.flatMap((pendingValue) => {
|
|
80
|
+
if (Option.isSome(pendingValue)) {
|
|
81
|
+
return Effect.succeed(pendingValue.value);
|
|
82
|
+
}
|
|
83
|
+
return restore(Queue.take(outbound)).pipe(Effect.flatMap((next) => Effect.uninterruptible(Ref.set(pending, Option.some(next))).pipe(Effect.as(next))));
|
|
84
|
+
})));
|
|
85
|
+
const writeOne = (writer) => Effect.gen(function* () {
|
|
86
|
+
const next = yield* takeNextOutbound;
|
|
87
|
+
yield* writer(JSON.stringify(next.message)).pipe(Effect.mapError((cause) => new ConnectionError({ reason: "Closed", cause })));
|
|
88
|
+
yield* Ref.set(pending, Option.none());
|
|
89
|
+
yield* Deferred.succeed(next.done, undefined);
|
|
90
|
+
});
|
|
91
|
+
const writeLoop = (writer) => writeOne(writer).pipe(Effect.forever);
|
|
92
|
+
const readLoop = (socket) => socket.runRaw((data) => handleIncoming(data)).pipe(Effect.catchAll((cause) => Effect.fail(new ConnectionError({ reason: "Closed", cause }))), Effect.zipRight(Effect.fail(new ConnectionError({ reason: "Closed", cause: "Socket closed" }))));
|
|
93
|
+
const runConnection = Effect.scoped(Effect.gen(function* () {
|
|
94
|
+
const socket = yield* Socket.makeWebSocket(url);
|
|
95
|
+
const writer = yield* socket.writer;
|
|
96
|
+
yield* Effect.raceFirst(readLoop(socket), writeLoop(writer));
|
|
97
|
+
})).pipe(Effect.retry(reconnectSchedule));
|
|
98
|
+
yield* Effect.forkIn(runConnection, scope);
|
|
99
|
+
const send = Effect.fn("Jetstream.send")((message) => Effect.gen(function* () {
|
|
100
|
+
const done = yield* Deferred.make();
|
|
101
|
+
const accepted = yield* Queue.offer(outbound, { message, done });
|
|
102
|
+
if (!accepted) {
|
|
103
|
+
return yield* Effect.fail(new ConnectionError({ reason: "Closed", cause: "Send queue shutdown" }));
|
|
104
|
+
}
|
|
105
|
+
return yield* Deferred.await(done);
|
|
106
|
+
}));
|
|
107
|
+
const updateOptions = Effect.fn("Jetstream.updateOptions")((options) => send({ type: "options_update", payload: options }));
|
|
108
|
+
return tag.of({
|
|
109
|
+
[TypeId]: TypeId,
|
|
110
|
+
stream: Mailbox.toStream(mailbox),
|
|
111
|
+
send,
|
|
112
|
+
updateOptions
|
|
113
|
+
});
|
|
114
|
+
}));
|
|
115
|
+
/**
|
|
116
|
+
* @since 1.0.0
|
|
117
|
+
* @category layers
|
|
118
|
+
*/
|
|
119
|
+
export const live = (config) => layer(config).pipe(Layer.provide(Socket.layerWebSocketConstructorGlobal));
|
|
120
|
+
//# sourceMappingURL=jetstream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jetstream.js","sourceRoot":"","sources":["../../src/internal/jetstream.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
import * as Socket from "@effect/platform/Socket";
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
import * as Stream from "effect/Stream";
|
|
7
|
+
import { ConnectionError } from "../JetstreamError.js";
|
|
8
|
+
import type { JetstreamConfig } from "../JetstreamConfig.js";
|
|
9
|
+
export declare const buildUrl: (config: JetstreamConfig) => string;
|
|
10
|
+
export declare const createSocket: (url: string) => Effect.Effect<Socket.Socket, ConnectionError, Socket.WebSocketConstructor>;
|
|
11
|
+
export declare const messageStream: (socket: Socket.Socket) => Stream.Stream<string | Uint8Array, ConnectionError>;
|
|
12
|
+
//# sourceMappingURL=websocket.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../../src/internal/websocket.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,MAAM,MAAM,yBAAyB,CAAA;AACjD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAE5D,eAAO,MAAM,QAAQ,GAAI,QAAQ,eAAe,KAAG,MAwBlD,CAAA;AAED,eAAO,MAAM,YAAY,GACvB,KAAK,MAAM,KACV,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE,MAAM,CAAC,oBAAoB,CAGzE,CAAA;AAEH,eAAO,MAAM,aAAa,GACxB,QAAQ,MAAM,CAAC,MAAM,KACpB,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,UAAU,EAAE,eAAe,CAgBjD,CAAA"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
import * as Socket from "@effect/platform/Socket";
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
import * as Stream from "effect/Stream";
|
|
7
|
+
import { ConnectionError } from "../JetstreamError.js";
|
|
8
|
+
export const buildUrl = (config) => {
|
|
9
|
+
const url = new URL(config.endpoint);
|
|
10
|
+
for (const collection of config.wantedCollections) {
|
|
11
|
+
url.searchParams.append("wantedCollections", collection);
|
|
12
|
+
}
|
|
13
|
+
for (const did of config.wantedDids) {
|
|
14
|
+
url.searchParams.append("wantedDids", did);
|
|
15
|
+
}
|
|
16
|
+
if (config.cursor !== undefined) {
|
|
17
|
+
url.searchParams.set("cursor", config.cursor.toString());
|
|
18
|
+
}
|
|
19
|
+
if (config.maxMessageSizeBytes !== undefined) {
|
|
20
|
+
url.searchParams.set("maxMessageSizeBytes", config.maxMessageSizeBytes.toString());
|
|
21
|
+
}
|
|
22
|
+
if (config.compress) {
|
|
23
|
+
url.searchParams.set("compress", "true");
|
|
24
|
+
}
|
|
25
|
+
return url.toString();
|
|
26
|
+
};
|
|
27
|
+
export const createSocket = (url) => Socket.makeWebSocket(url).pipe(Effect.mapError((cause) => new ConnectionError({ reason: "Connect", cause })));
|
|
28
|
+
export const messageStream = (socket) => Stream.async((emit) => {
|
|
29
|
+
const run = socket.runRaw((data) => {
|
|
30
|
+
emit.single(data);
|
|
31
|
+
}).pipe(Effect.catchAll((error) => Effect.sync(() => {
|
|
32
|
+
emit.fail(new ConnectionError({ reason: "Closed", cause: error }));
|
|
33
|
+
})), Effect.ensuring(Effect.sync(() => emit.end())));
|
|
34
|
+
return run;
|
|
35
|
+
});
|
|
36
|
+
//# sourceMappingURL=websocket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"websocket.js","sourceRoot":"","sources":["../../src/internal/websocket.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,MAAM,MAAM,yBAAyB,CAAA;AACjD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAGtD,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,MAAuB,EAAU,EAAE;IAC1D,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IAEpC,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,iBAAiB,EAAE,CAAC;QAClD,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,mBAAmB,EAAE,UAAU,CAAC,CAAA;IAC1D,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACpC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,YAAY,EAAE,GAAG,CAAC,CAAA;IAC5C,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAChC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAA;IAC1D,CAAC;IAED,IAAI,MAAM,CAAC,mBAAmB,KAAK,SAAS,EAAE,CAAC;QAC7C,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,qBAAqB,EAAE,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,CAAC,CAAA;IACpF,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACpB,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,CAAA;IAC1C,CAAC;IAED,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAA;AACvB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,GAAW,EACiE,EAAE,CAC9E,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,CAC5B,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,eAAe,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,CAC9E,CAAA;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,MAAqB,EACgC,EAAE,CACvD,MAAM,CAAC,KAAK,CAAuC,CAAC,IAAI,EAAE,EAAE;IAC1D,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CACvB,CAAC,IAAI,EAAE,EAAE;QACP,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACnB,CAAC,CACF,CAAC,IAAI,CACJ,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CACxB,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;QACf,IAAI,CAAC,IAAI,CAAC,IAAI,eAAe,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;IACpE,CAAC,CAAC,CACH,EACD,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAC/C,CAAA;IAED,OAAO,GAAG,CAAA;AACZ,CAAC,CAAC,CAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "effect-jetstream",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Effect-based client for the Bluesky Jetstream API",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/mepuka/effect-jetstream.git"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"bluesky",
|
|
12
|
+
"jetstream",
|
|
13
|
+
"effect",
|
|
14
|
+
"atprotocol",
|
|
15
|
+
"websocket",
|
|
16
|
+
"streaming"
|
|
17
|
+
],
|
|
18
|
+
"type": "module",
|
|
19
|
+
"main": "dist/index.js",
|
|
20
|
+
"module": "dist/index.js",
|
|
21
|
+
"types": "dist/index.d.ts",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"import": "./dist/index.js",
|
|
25
|
+
"types": "./dist/index.d.ts"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"README.md",
|
|
31
|
+
"LICENSE"
|
|
32
|
+
],
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsc",
|
|
35
|
+
"prepare": "effect-language-service patch",
|
|
36
|
+
"typecheck": "tsc --noEmit",
|
|
37
|
+
"prepublishOnly": "bun run build"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@effect/language-service": "^0.71.0",
|
|
41
|
+
"@types/bun": "latest"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"typescript": "^5"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@effect/platform": "^0.94.1",
|
|
48
|
+
"effect": "^3.19.14"
|
|
49
|
+
}
|
|
50
|
+
}
|