@atproto/tap 0.0.2

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.
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SimpleIndexer = void 0;
4
+ class SimpleIndexer {
5
+ constructor() {
6
+ Object.defineProperty(this, "identityHandler", {
7
+ enumerable: true,
8
+ configurable: true,
9
+ writable: true,
10
+ value: void 0
11
+ });
12
+ Object.defineProperty(this, "recordHandler", {
13
+ enumerable: true,
14
+ configurable: true,
15
+ writable: true,
16
+ value: void 0
17
+ });
18
+ Object.defineProperty(this, "errorHandler", {
19
+ enumerable: true,
20
+ configurable: true,
21
+ writable: true,
22
+ value: void 0
23
+ });
24
+ }
25
+ identity(fn) {
26
+ this.identityHandler = fn;
27
+ }
28
+ record(fn) {
29
+ this.recordHandler = fn;
30
+ }
31
+ error(fn) {
32
+ this.errorHandler = fn;
33
+ }
34
+ async onEvent(evt, opts) {
35
+ if (evt.type === 'record') {
36
+ await this.recordHandler?.(evt, opts);
37
+ }
38
+ else {
39
+ await this.identityHandler?.(evt, opts);
40
+ }
41
+ await opts.ack();
42
+ }
43
+ onError(err) {
44
+ if (this.errorHandler) {
45
+ this.errorHandler(err);
46
+ }
47
+ else {
48
+ throw err;
49
+ }
50
+ }
51
+ }
52
+ exports.SimpleIndexer = SimpleIndexer;
53
+ //# sourceMappingURL=simple-indexer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"simple-indexer.js","sourceRoot":"","sources":["../src/simple-indexer.ts"],"names":[],"mappings":";;;AAaA,MAAa,aAAa;IAA1B;QACU;;;;;WAAiD;QACjD;;;;;WAA6C;QAC7C;;;;;WAAsC;IA8BhD,CAAC;IA5BC,QAAQ,CAAC,EAAwB;QAC/B,IAAI,CAAC,eAAe,GAAG,EAAE,CAAA;IAC3B,CAAC;IAED,MAAM,CAAC,EAAsB;QAC3B,IAAI,CAAC,aAAa,GAAG,EAAE,CAAA;IACzB,CAAC;IAED,KAAK,CAAC,EAAgB;QACpB,IAAI,CAAC,YAAY,GAAG,EAAE,CAAA;IACxB,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAa,EAAE,IAAiB;QAC5C,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC1B,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;QACvC,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;QACzC,CAAC;QACD,MAAM,IAAI,CAAC,GAAG,EAAE,CAAA;IAClB,CAAC;IAED,OAAO,CAAC,GAAU;QAChB,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAA;QACxB,CAAC;aAAM,CAAC;YACN,MAAM,GAAG,CAAA;QACX,CAAC;IACH,CAAC;CACF;AAjCD,sCAiCC","sourcesContent":["import { HandlerOpts, TapHandler } from './channel'\nimport { IdentityEvent, RecordEvent, TapEvent } from './types'\n\ntype IdentityEventHandler = (\n evt: IdentityEvent,\n opts?: HandlerOpts,\n) => Promise<void>\ntype RecordEventHandler = (\n evt: RecordEvent,\n opts?: HandlerOpts,\n) => Promise<void>\ntype ErrorHandler = (err: Error) => void\n\nexport class SimpleIndexer implements TapHandler {\n private identityHandler: IdentityEventHandler | undefined\n private recordHandler: RecordEventHandler | undefined\n private errorHandler: ErrorHandler | undefined\n\n identity(fn: IdentityEventHandler) {\n this.identityHandler = fn\n }\n\n record(fn: RecordEventHandler) {\n this.recordHandler = fn\n }\n\n error(fn: ErrorHandler) {\n this.errorHandler = fn\n }\n\n async onEvent(evt: TapEvent, opts: HandlerOpts): Promise<void> {\n if (evt.type === 'record') {\n await this.recordHandler?.(evt, opts)\n } else {\n await this.identityHandler?.(evt, opts)\n }\n await opts.ack()\n }\n\n onError(err: Error) {\n if (this.errorHandler) {\n this.errorHandler(err)\n } else {\n throw err\n }\n }\n}\n"]}
@@ -0,0 +1,286 @@
1
+ import { z } from 'zod';
2
+ export declare const recordEventDataSchema: z.ZodObject<{
3
+ did: z.ZodString;
4
+ rev: z.ZodString;
5
+ collection: z.ZodString;
6
+ rkey: z.ZodString;
7
+ action: z.ZodEnum<["create", "update", "delete"]>;
8
+ record: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
9
+ cid: z.ZodOptional<z.ZodString>;
10
+ live: z.ZodBoolean;
11
+ }, "strip", z.ZodTypeAny, {
12
+ did: string;
13
+ rev: string;
14
+ collection: string;
15
+ rkey: string;
16
+ action: "create" | "update" | "delete";
17
+ live: boolean;
18
+ record?: Record<string, unknown> | undefined;
19
+ cid?: string | undefined;
20
+ }, {
21
+ did: string;
22
+ rev: string;
23
+ collection: string;
24
+ rkey: string;
25
+ action: "create" | "update" | "delete";
26
+ live: boolean;
27
+ record?: Record<string, unknown> | undefined;
28
+ cid?: string | undefined;
29
+ }>;
30
+ export declare const identityEventDataSchema: z.ZodObject<{
31
+ did: z.ZodString;
32
+ handle: z.ZodString;
33
+ is_active: z.ZodBoolean;
34
+ status: z.ZodEnum<["active", "takendown", "suspended", "deactivated", "deleted"]>;
35
+ }, "strip", z.ZodTypeAny, {
36
+ did: string;
37
+ status: "active" | "takendown" | "suspended" | "deactivated" | "deleted";
38
+ handle: string;
39
+ is_active: boolean;
40
+ }, {
41
+ did: string;
42
+ status: "active" | "takendown" | "suspended" | "deactivated" | "deleted";
43
+ handle: string;
44
+ is_active: boolean;
45
+ }>;
46
+ export declare const recordEventSchema: z.ZodObject<{
47
+ id: z.ZodNumber;
48
+ type: z.ZodLiteral<"record">;
49
+ record: z.ZodObject<{
50
+ did: z.ZodString;
51
+ rev: z.ZodString;
52
+ collection: z.ZodString;
53
+ rkey: z.ZodString;
54
+ action: z.ZodEnum<["create", "update", "delete"]>;
55
+ record: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
56
+ cid: z.ZodOptional<z.ZodString>;
57
+ live: z.ZodBoolean;
58
+ }, "strip", z.ZodTypeAny, {
59
+ did: string;
60
+ rev: string;
61
+ collection: string;
62
+ rkey: string;
63
+ action: "create" | "update" | "delete";
64
+ live: boolean;
65
+ record?: Record<string, unknown> | undefined;
66
+ cid?: string | undefined;
67
+ }, {
68
+ did: string;
69
+ rev: string;
70
+ collection: string;
71
+ rkey: string;
72
+ action: "create" | "update" | "delete";
73
+ live: boolean;
74
+ record?: Record<string, unknown> | undefined;
75
+ cid?: string | undefined;
76
+ }>;
77
+ }, "strip", z.ZodTypeAny, {
78
+ type: "record";
79
+ record: {
80
+ did: string;
81
+ rev: string;
82
+ collection: string;
83
+ rkey: string;
84
+ action: "create" | "update" | "delete";
85
+ live: boolean;
86
+ record?: Record<string, unknown> | undefined;
87
+ cid?: string | undefined;
88
+ };
89
+ id: number;
90
+ }, {
91
+ type: "record";
92
+ record: {
93
+ did: string;
94
+ rev: string;
95
+ collection: string;
96
+ rkey: string;
97
+ action: "create" | "update" | "delete";
98
+ live: boolean;
99
+ record?: Record<string, unknown> | undefined;
100
+ cid?: string | undefined;
101
+ };
102
+ id: number;
103
+ }>;
104
+ export declare const identityEventSchema: z.ZodObject<{
105
+ id: z.ZodNumber;
106
+ type: z.ZodLiteral<"identity">;
107
+ identity: z.ZodObject<{
108
+ did: z.ZodString;
109
+ handle: z.ZodString;
110
+ is_active: z.ZodBoolean;
111
+ status: z.ZodEnum<["active", "takendown", "suspended", "deactivated", "deleted"]>;
112
+ }, "strip", z.ZodTypeAny, {
113
+ did: string;
114
+ status: "active" | "takendown" | "suspended" | "deactivated" | "deleted";
115
+ handle: string;
116
+ is_active: boolean;
117
+ }, {
118
+ did: string;
119
+ status: "active" | "takendown" | "suspended" | "deactivated" | "deleted";
120
+ handle: string;
121
+ is_active: boolean;
122
+ }>;
123
+ }, "strip", z.ZodTypeAny, {
124
+ type: "identity";
125
+ id: number;
126
+ identity: {
127
+ did: string;
128
+ status: "active" | "takendown" | "suspended" | "deactivated" | "deleted";
129
+ handle: string;
130
+ is_active: boolean;
131
+ };
132
+ }, {
133
+ type: "identity";
134
+ id: number;
135
+ identity: {
136
+ did: string;
137
+ status: "active" | "takendown" | "suspended" | "deactivated" | "deleted";
138
+ handle: string;
139
+ is_active: boolean;
140
+ };
141
+ }>;
142
+ export declare const tapEventSchema: z.ZodUnion<[z.ZodObject<{
143
+ id: z.ZodNumber;
144
+ type: z.ZodLiteral<"record">;
145
+ record: z.ZodObject<{
146
+ did: z.ZodString;
147
+ rev: z.ZodString;
148
+ collection: z.ZodString;
149
+ rkey: z.ZodString;
150
+ action: z.ZodEnum<["create", "update", "delete"]>;
151
+ record: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
152
+ cid: z.ZodOptional<z.ZodString>;
153
+ live: z.ZodBoolean;
154
+ }, "strip", z.ZodTypeAny, {
155
+ did: string;
156
+ rev: string;
157
+ collection: string;
158
+ rkey: string;
159
+ action: "create" | "update" | "delete";
160
+ live: boolean;
161
+ record?: Record<string, unknown> | undefined;
162
+ cid?: string | undefined;
163
+ }, {
164
+ did: string;
165
+ rev: string;
166
+ collection: string;
167
+ rkey: string;
168
+ action: "create" | "update" | "delete";
169
+ live: boolean;
170
+ record?: Record<string, unknown> | undefined;
171
+ cid?: string | undefined;
172
+ }>;
173
+ }, "strip", z.ZodTypeAny, {
174
+ type: "record";
175
+ record: {
176
+ did: string;
177
+ rev: string;
178
+ collection: string;
179
+ rkey: string;
180
+ action: "create" | "update" | "delete";
181
+ live: boolean;
182
+ record?: Record<string, unknown> | undefined;
183
+ cid?: string | undefined;
184
+ };
185
+ id: number;
186
+ }, {
187
+ type: "record";
188
+ record: {
189
+ did: string;
190
+ rev: string;
191
+ collection: string;
192
+ rkey: string;
193
+ action: "create" | "update" | "delete";
194
+ live: boolean;
195
+ record?: Record<string, unknown> | undefined;
196
+ cid?: string | undefined;
197
+ };
198
+ id: number;
199
+ }>, z.ZodObject<{
200
+ id: z.ZodNumber;
201
+ type: z.ZodLiteral<"identity">;
202
+ identity: z.ZodObject<{
203
+ did: z.ZodString;
204
+ handle: z.ZodString;
205
+ is_active: z.ZodBoolean;
206
+ status: z.ZodEnum<["active", "takendown", "suspended", "deactivated", "deleted"]>;
207
+ }, "strip", z.ZodTypeAny, {
208
+ did: string;
209
+ status: "active" | "takendown" | "suspended" | "deactivated" | "deleted";
210
+ handle: string;
211
+ is_active: boolean;
212
+ }, {
213
+ did: string;
214
+ status: "active" | "takendown" | "suspended" | "deactivated" | "deleted";
215
+ handle: string;
216
+ is_active: boolean;
217
+ }>;
218
+ }, "strip", z.ZodTypeAny, {
219
+ type: "identity";
220
+ id: number;
221
+ identity: {
222
+ did: string;
223
+ status: "active" | "takendown" | "suspended" | "deactivated" | "deleted";
224
+ handle: string;
225
+ is_active: boolean;
226
+ };
227
+ }, {
228
+ type: "identity";
229
+ id: number;
230
+ identity: {
231
+ did: string;
232
+ status: "active" | "takendown" | "suspended" | "deactivated" | "deleted";
233
+ handle: string;
234
+ is_active: boolean;
235
+ };
236
+ }>]>;
237
+ export type RecordEvent = {
238
+ id: number;
239
+ type: 'record';
240
+ action: 'create' | 'update' | 'delete';
241
+ did: string;
242
+ rev: string;
243
+ collection: string;
244
+ rkey: string;
245
+ record?: Record<string, unknown>;
246
+ cid?: string;
247
+ live: boolean;
248
+ };
249
+ export type IdentityEvent = {
250
+ id: number;
251
+ type: 'identity';
252
+ did: string;
253
+ handle: string;
254
+ isActive: boolean;
255
+ status: RepoStatus;
256
+ };
257
+ export type RepoStatus = 'active' | 'takendown' | 'suspended' | 'deactivated' | 'deleted';
258
+ export type TapEvent = IdentityEvent | RecordEvent;
259
+ export declare const parseTapEvent: (data: unknown) => TapEvent;
260
+ export declare const repoInfoSchema: z.ZodObject<{
261
+ did: z.ZodString;
262
+ handle: z.ZodString;
263
+ state: z.ZodString;
264
+ rev: z.ZodString;
265
+ records: z.ZodNumber;
266
+ error: z.ZodOptional<z.ZodString>;
267
+ retries: z.ZodOptional<z.ZodNumber>;
268
+ }, "strip", z.ZodTypeAny, {
269
+ did: string;
270
+ rev: string;
271
+ handle: string;
272
+ state: string;
273
+ records: number;
274
+ error?: string | undefined;
275
+ retries?: number | undefined;
276
+ }, {
277
+ did: string;
278
+ rev: string;
279
+ handle: string;
280
+ state: string;
281
+ records: number;
282
+ error?: string | undefined;
283
+ retries?: number | undefined;
284
+ }>;
285
+ export type RepoInfo = z.infer<typeof repoInfoSchema>;
286
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;EAShC,CAAA;AAEF,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;EAWlC,CAAA;AAEF,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAI5B,CAAA;AAEF,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAI9B,CAAA;AAEF,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAAoD,CAAA;AAE/E,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,QAAQ,CAAA;IACd,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAA;IACtC,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAChC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,OAAO,CAAA;CACd,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,UAAU,CAAA;IAChB,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,OAAO,CAAA;IACjB,MAAM,EAAE,UAAU,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,UAAU,GAClB,QAAQ,GACR,WAAW,GACX,WAAW,GACX,aAAa,GACb,SAAS,CAAA;AAEb,MAAM,MAAM,QAAQ,GAAG,aAAa,GAAG,WAAW,CAAA;AAElD,eAAO,MAAM,aAAa,GAAI,MAAM,OAAO,KAAG,QAyB7C,CAAA;AAED,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;EAQzB,CAAA;AAEF,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAA"}
package/dist/types.js ADDED
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.repoInfoSchema = exports.parseTapEvent = exports.tapEventSchema = exports.identityEventSchema = exports.recordEventSchema = exports.identityEventDataSchema = exports.recordEventDataSchema = void 0;
4
+ const zod_1 = require("zod");
5
+ exports.recordEventDataSchema = zod_1.z.object({
6
+ did: zod_1.z.string(),
7
+ rev: zod_1.z.string(),
8
+ collection: zod_1.z.string(),
9
+ rkey: zod_1.z.string(),
10
+ action: zod_1.z.enum(['create', 'update', 'delete']),
11
+ record: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()).optional(),
12
+ cid: zod_1.z.string().optional(),
13
+ live: zod_1.z.boolean(),
14
+ });
15
+ exports.identityEventDataSchema = zod_1.z.object({
16
+ did: zod_1.z.string(),
17
+ handle: zod_1.z.string(),
18
+ is_active: zod_1.z.boolean(),
19
+ status: zod_1.z.enum([
20
+ 'active',
21
+ 'takendown',
22
+ 'suspended',
23
+ 'deactivated',
24
+ 'deleted',
25
+ ]),
26
+ });
27
+ exports.recordEventSchema = zod_1.z.object({
28
+ id: zod_1.z.number(),
29
+ type: zod_1.z.literal('record'),
30
+ record: exports.recordEventDataSchema,
31
+ });
32
+ exports.identityEventSchema = zod_1.z.object({
33
+ id: zod_1.z.number(),
34
+ type: zod_1.z.literal('identity'),
35
+ identity: exports.identityEventDataSchema,
36
+ });
37
+ exports.tapEventSchema = zod_1.z.union([exports.recordEventSchema, exports.identityEventSchema]);
38
+ const parseTapEvent = (data) => {
39
+ const parsed = exports.tapEventSchema.parse(data);
40
+ if (parsed.type === 'identity') {
41
+ return {
42
+ id: parsed.id,
43
+ type: parsed.type,
44
+ did: parsed.identity.did,
45
+ handle: parsed.identity.handle,
46
+ isActive: parsed.identity.is_active,
47
+ status: parsed.identity.status,
48
+ };
49
+ }
50
+ else {
51
+ return {
52
+ id: parsed.id,
53
+ type: parsed.type,
54
+ action: parsed.record.action,
55
+ did: parsed.record.did,
56
+ rev: parsed.record.rev,
57
+ collection: parsed.record.collection,
58
+ rkey: parsed.record.rkey,
59
+ record: parsed.record.record,
60
+ cid: parsed.record.cid,
61
+ live: parsed.record.live,
62
+ };
63
+ }
64
+ };
65
+ exports.parseTapEvent = parseTapEvent;
66
+ exports.repoInfoSchema = zod_1.z.object({
67
+ did: zod_1.z.string(),
68
+ handle: zod_1.z.string(),
69
+ state: zod_1.z.string(),
70
+ rev: zod_1.z.string(),
71
+ records: zod_1.z.number(),
72
+ error: zod_1.z.string().optional(),
73
+ retries: zod_1.z.number().optional(),
74
+ });
75
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod'\n\nexport const recordEventDataSchema = z.object({\n did: z.string(),\n rev: z.string(),\n collection: z.string(),\n rkey: z.string(),\n action: z.enum(['create', 'update', 'delete']),\n record: z.record(z.string(), z.unknown()).optional(),\n cid: z.string().optional(),\n live: z.boolean(),\n})\n\nexport const identityEventDataSchema = z.object({\n did: z.string(),\n handle: z.string(),\n is_active: z.boolean(),\n status: z.enum([\n 'active',\n 'takendown',\n 'suspended',\n 'deactivated',\n 'deleted',\n ]),\n})\n\nexport const recordEventSchema = z.object({\n id: z.number(),\n type: z.literal('record'),\n record: recordEventDataSchema,\n})\n\nexport const identityEventSchema = z.object({\n id: z.number(),\n type: z.literal('identity'),\n identity: identityEventDataSchema,\n})\n\nexport const tapEventSchema = z.union([recordEventSchema, identityEventSchema])\n\nexport type RecordEvent = {\n id: number\n type: 'record'\n action: 'create' | 'update' | 'delete'\n did: string\n rev: string\n collection: string\n rkey: string\n record?: Record<string, unknown>\n cid?: string\n live: boolean\n}\n\nexport type IdentityEvent = {\n id: number\n type: 'identity'\n did: string\n handle: string\n isActive: boolean\n status: RepoStatus\n}\n\nexport type RepoStatus =\n | 'active'\n | 'takendown'\n | 'suspended'\n | 'deactivated'\n | 'deleted'\n\nexport type TapEvent = IdentityEvent | RecordEvent\n\nexport const parseTapEvent = (data: unknown): TapEvent => {\n const parsed = tapEventSchema.parse(data)\n if (parsed.type === 'identity') {\n return {\n id: parsed.id,\n type: parsed.type,\n did: parsed.identity.did,\n handle: parsed.identity.handle,\n isActive: parsed.identity.is_active,\n status: parsed.identity.status,\n }\n } else {\n return {\n id: parsed.id,\n type: parsed.type,\n action: parsed.record.action,\n did: parsed.record.did,\n rev: parsed.record.rev,\n collection: parsed.record.collection,\n rkey: parsed.record.rkey,\n record: parsed.record.record,\n cid: parsed.record.cid,\n live: parsed.record.live,\n }\n }\n}\n\nexport const repoInfoSchema = z.object({\n did: z.string(),\n handle: z.string(),\n state: z.string(),\n rev: z.string(),\n records: z.number(),\n error: z.string().optional(),\n retries: z.number().optional(),\n})\n\nexport type RepoInfo = z.infer<typeof repoInfoSchema>\n"]}
package/dist/util.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export declare const formatAdminAuthHeader: (password: string) => string;
2
+ export declare const parseAdminAuthHeader: (header: string) => string;
3
+ export declare const assureAdminAuth: (expectedPassword: string, header: string) => void;
4
+ //# sourceMappingURL=util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,qBAAqB,GAAI,UAAU,MAAM,WAErD,CAAA;AAED,eAAO,MAAM,oBAAoB,GAAI,QAAQ,MAAM,WASlD,CAAA;AAED,eAAO,MAAM,eAAe,GAAI,kBAAkB,MAAM,EAAE,QAAQ,MAAM,SAMvE,CAAA"}
package/dist/util.js ADDED
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assureAdminAuth = exports.parseAdminAuthHeader = exports.formatAdminAuthHeader = void 0;
4
+ const formatAdminAuthHeader = (password) => {
5
+ return 'Basic ' + Buffer.from(`admin:${password}`).toString('base64');
6
+ };
7
+ exports.formatAdminAuthHeader = formatAdminAuthHeader;
8
+ const parseAdminAuthHeader = (header) => {
9
+ const noPrefix = header.startsWith('Basic ') ? header.slice(6) : header;
10
+ const [username, password] = Buffer.from(noPrefix, 'base64')
11
+ .toString()
12
+ .split(':');
13
+ if (username !== 'admin') {
14
+ throw new Error("Unexpected username in admin headers. Expected 'admin'");
15
+ }
16
+ return password;
17
+ };
18
+ exports.parseAdminAuthHeader = parseAdminAuthHeader;
19
+ const assureAdminAuth = (expectedPassword, header) => {
20
+ const headerPassword = (0, exports.parseAdminAuthHeader)(header);
21
+ const passEqual = timingSafeEqual(headerPassword, expectedPassword);
22
+ if (!passEqual) {
23
+ throw new Error('Invalid admin password');
24
+ }
25
+ };
26
+ exports.assureAdminAuth = assureAdminAuth;
27
+ const timingSafeEqual = (a, b) => {
28
+ const bufA = Buffer.from(a);
29
+ const bufB = Buffer.from(b);
30
+ if (bufA.length !== bufB.length) {
31
+ // Compare against self to maintain constant time even with length mismatch
32
+ Buffer.from(a).compare(Buffer.from(a));
33
+ return false;
34
+ }
35
+ return bufA.compare(bufB) === 0;
36
+ };
37
+ //# sourceMappingURL=util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":";;;AAAO,MAAM,qBAAqB,GAAG,CAAC,QAAgB,EAAE,EAAE;IACxD,OAAO,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;AACvE,CAAC,CAAA;AAFY,QAAA,qBAAqB,yBAEjC;AAEM,MAAM,oBAAoB,GAAG,CAAC,MAAc,EAAE,EAAE;IACrD,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAA;IACvE,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC;SACzD,QAAQ,EAAE;SACV,KAAK,CAAC,GAAG,CAAC,CAAA;IACb,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAA;IAC3E,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC,CAAA;AATY,QAAA,oBAAoB,wBAShC;AAEM,MAAM,eAAe,GAAG,CAAC,gBAAwB,EAAE,MAAc,EAAE,EAAE;IAC1E,MAAM,cAAc,GAAG,IAAA,4BAAoB,EAAC,MAAM,CAAC,CAAA;IACnD,MAAM,SAAS,GAAG,eAAe,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAA;IACnE,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAA;IAC3C,CAAC;AACH,CAAC,CAAA;AANY,QAAA,eAAe,mBAM3B;AAED,MAAM,eAAe,GAAG,CAAC,CAAS,EAAE,CAAS,EAAW,EAAE;IACxD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAC3B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAC3B,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;QAChC,2EAA2E;QAC3E,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;QACtC,OAAO,KAAK,CAAA;IACd,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;AACjC,CAAC,CAAA","sourcesContent":["export const formatAdminAuthHeader = (password: string) => {\n return 'Basic ' + Buffer.from(`admin:${password}`).toString('base64')\n}\n\nexport const parseAdminAuthHeader = (header: string) => {\n const noPrefix = header.startsWith('Basic ') ? header.slice(6) : header\n const [username, password] = Buffer.from(noPrefix, 'base64')\n .toString()\n .split(':')\n if (username !== 'admin') {\n throw new Error(\"Unexpected username in admin headers. Expected 'admin'\")\n }\n return password\n}\n\nexport const assureAdminAuth = (expectedPassword: string, header: string) => {\n const headerPassword = parseAdminAuthHeader(header)\n const passEqual = timingSafeEqual(headerPassword, expectedPassword)\n if (!passEqual) {\n throw new Error('Invalid admin password')\n }\n}\n\nconst timingSafeEqual = (a: string, b: string): boolean => {\n const bufA = Buffer.from(a)\n const bufB = Buffer.from(b)\n if (bufA.length !== bufB.length) {\n // Compare against self to maintain constant time even with length mismatch\n Buffer.from(a).compare(Buffer.from(a))\n return false\n }\n return bufA.compare(bufB) === 0\n}\n"]}
package/jest.config.js ADDED
@@ -0,0 +1,10 @@
1
+ /** @type {import('jest').Config} */
2
+ module.exports = {
3
+ displayName: 'Tap',
4
+ transform: { '^.+\\.(j|t)s$': '@swc/jest' },
5
+ transformIgnorePatterns: ['/node_modules/.pnpm/(?!(get-port)@)'],
6
+ testTimeout: 60000,
7
+ setupFiles: ['<rootDir>/../../jest.setup.ts'],
8
+ moduleNameMapper: { '^(\\.\\.?\\/.+)\\.js$': ['$1.ts', '$1.js'] },
9
+ testPathIgnorePatterns: ['/node_modules/', '/dist/'],
10
+ }
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@atproto/tap",
3
+ "version": "0.0.2",
4
+ "license": "MIT",
5
+ "description": "atproto tap client",
6
+ "keywords": [
7
+ "atproto",
8
+ "tap",
9
+ "sync",
10
+ "firehose",
11
+ "relay"
12
+ ],
13
+ "homepage": "https://atproto.com",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/bluesky-social/atproto",
17
+ "directory": "packages/tap"
18
+ },
19
+ "engines": {
20
+ "node": ">=18.7.0"
21
+ },
22
+ "main": "dist/index.js",
23
+ "types": "dist/index.d.ts",
24
+ "dependencies": {
25
+ "ws": "^8.12.0",
26
+ "zod": "^3.23.8",
27
+ "@atproto/common": "^0.5.3",
28
+ "@atproto/syntax": "^0.4.2",
29
+ "@atproto/ws-client": "^0.0.4"
30
+ },
31
+ "devDependencies": {
32
+ "@types/express": "^4.17.17",
33
+ "@types/ws": "^8.5.4",
34
+ "express": "^4.18.2",
35
+ "get-port": "^6.1.2",
36
+ "jest": "^28.1.2",
37
+ "typescript": "^5.6.3"
38
+ },
39
+ "scripts": {
40
+ "build": "tsc --build tsconfig.build.json",
41
+ "test": "jest"
42
+ }
43
+ }