@graphrefly/graphrefly 0.4.0 → 0.6.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.
@@ -34,6 +34,8 @@ __export(extra_exports, {
34
34
  cached: () => cached,
35
35
  catchError: () => catchError,
36
36
  checkpointNodeValue: () => checkpointNodeValue,
37
+ checkpointToRedis: () => checkpointToRedis,
38
+ checkpointToS3: () => checkpointToS3,
37
39
  circuitBreaker: () => circuitBreaker,
38
40
  combine: () => combine,
39
41
  combineLatest: () => combineLatest,
@@ -75,11 +77,15 @@ __export(extra_exports, {
75
77
  fromIter: () => fromIter,
76
78
  fromKafka: () => fromKafka,
77
79
  fromMCP: () => fromMCP,
80
+ fromNATS: () => fromNATS,
78
81
  fromNDJSON: () => fromNDJSON,
79
82
  fromOTel: () => fromOTel,
80
83
  fromPrometheus: () => fromPrometheus,
81
84
  fromPromise: () => fromPromise,
85
+ fromPulsar: () => fromPulsar,
86
+ fromRabbitMQ: () => fromRabbitMQ,
82
87
  fromRedisStream: () => fromRedisStream,
88
+ fromSqlite: () => fromSqlite,
83
89
  fromStatsD: () => fromStatsD,
84
90
  fromSyslog: () => fromSyslog,
85
91
  fromTimer: () => fromTimer,
@@ -142,11 +148,23 @@ __export(extra_exports, {
142
148
  throwError: () => throwError,
143
149
  timeout: () => timeout,
144
150
  toArray: () => toArray,
151
+ toCSV: () => toCSV,
152
+ toClickHouse: () => toClickHouse,
153
+ toFile: () => toFile,
145
154
  toKafka: () => toKafka,
155
+ toLoki: () => toLoki,
146
156
  toMessages$: () => toMessages$,
157
+ toMongo: () => toMongo,
158
+ toNATS: () => toNATS,
147
159
  toObservable: () => toObservable,
160
+ toPostgres: () => toPostgres,
161
+ toPulsar: () => toPulsar,
162
+ toRabbitMQ: () => toRabbitMQ,
148
163
  toRedisStream: () => toRedisStream,
164
+ toS3: () => toS3,
149
165
  toSSE: () => toSSE,
166
+ toSqlite: () => toSqlite,
167
+ toTempo: () => toTempo,
150
168
  toWebSocket: () => toWebSocket,
151
169
  tokenBucket: () => tokenBucket,
152
170
  tokenTracker: () => tokenTracker,
@@ -2359,7 +2377,7 @@ function toWebSocket(source, socket, opts) {
2359
2377
  };
2360
2378
  const inner = node([source], () => void 0, {
2361
2379
  describeKind: "effect",
2362
- onMessage(msg) {
2380
+ onMessage(msg, _depIndex, _actions) {
2363
2381
  if (msg[0] === DATA) {
2364
2382
  let serialized;
2365
2383
  try {
@@ -2810,7 +2828,7 @@ function toKafka(source, kafkaProducer, topic, opts) {
2810
2828
  const inner = node([source], () => void 0, {
2811
2829
  describeKind: "effect",
2812
2830
  ...rest,
2813
- onMessage(msg) {
2831
+ onMessage(msg, _depIndex, _actions) {
2814
2832
  if (msg[0] === DATA) {
2815
2833
  const value = msg[1];
2816
2834
  const key = keyExtractor?.(value) ?? null;
@@ -2909,7 +2927,7 @@ function toRedisStream(source, client, key, opts) {
2909
2927
  const inner = node([source], () => void 0, {
2910
2928
  describeKind: "effect",
2911
2929
  ...rest,
2912
- onMessage(msg) {
2930
+ onMessage(msg, _depIndex, _actions) {
2913
2931
  if (msg[0] === DATA) {
2914
2932
  const value = msg[1];
2915
2933
  let fields;
@@ -3114,6 +3132,866 @@ function fromClickHouseWatch(client, query, opts) {
3114
3132
  };
3115
3133
  }, sourceOpts2(rest));
3116
3134
  }
3135
+ function fromPulsar(consumer, opts) {
3136
+ const {
3137
+ autoAck = true,
3138
+ deserialize = (buf) => {
3139
+ try {
3140
+ return JSON.parse(buf.toString());
3141
+ } catch {
3142
+ return buf.toString();
3143
+ }
3144
+ },
3145
+ ...rest
3146
+ } = opts ?? {};
3147
+ return producer((_d, a) => {
3148
+ let active = true;
3149
+ const loop = async () => {
3150
+ while (active) {
3151
+ try {
3152
+ const msg = await consumer.receive();
3153
+ if (!active) return;
3154
+ a.emit({
3155
+ topic: msg.getTopicName(),
3156
+ messageId: msg.getMessageId().toString(),
3157
+ key: msg.getPartitionKey(),
3158
+ value: deserialize(msg.getData()),
3159
+ properties: msg.getProperties(),
3160
+ publishTime: msg.getPublishTimestamp(),
3161
+ eventTime: msg.getEventTimestamp(),
3162
+ timestampNs: wallClockNs()
3163
+ });
3164
+ if (autoAck) await consumer.acknowledge(msg);
3165
+ } catch (err) {
3166
+ if (active) a.down([[ERROR, err]]);
3167
+ return;
3168
+ }
3169
+ }
3170
+ };
3171
+ void loop();
3172
+ return () => {
3173
+ active = false;
3174
+ };
3175
+ }, sourceOpts2(rest));
3176
+ }
3177
+ function toPulsar(source, pulsarProducer, opts) {
3178
+ const {
3179
+ serialize = (v) => Buffer.from(JSON.stringify(v)),
3180
+ keyExtractor,
3181
+ propertiesExtractor,
3182
+ onTransportError,
3183
+ ...rest
3184
+ } = opts ?? {};
3185
+ const inner = node([source], () => void 0, {
3186
+ describeKind: "effect",
3187
+ ...rest,
3188
+ onMessage(msg, _depIndex, _actions) {
3189
+ if (msg[0] === DATA) {
3190
+ const value = msg[1];
3191
+ let data;
3192
+ try {
3193
+ data = serialize(value);
3194
+ } catch (err) {
3195
+ onTransportError?.({
3196
+ stage: "serialize",
3197
+ error: err instanceof Error ? err : new Error(String(err)),
3198
+ value
3199
+ });
3200
+ return true;
3201
+ }
3202
+ void pulsarProducer.send({
3203
+ data,
3204
+ partitionKey: keyExtractor?.(value),
3205
+ properties: propertiesExtractor?.(value)
3206
+ }).catch((err) => {
3207
+ onTransportError?.({
3208
+ stage: "send",
3209
+ error: err instanceof Error ? err : new Error(String(err)),
3210
+ value
3211
+ });
3212
+ });
3213
+ return true;
3214
+ }
3215
+ return false;
3216
+ }
3217
+ });
3218
+ return inner.subscribe(() => {
3219
+ });
3220
+ }
3221
+ function fromNATS(client, subject, opts) {
3222
+ const decoder = new TextDecoder();
3223
+ const {
3224
+ queue,
3225
+ deserialize = (data) => {
3226
+ const text = decoder.decode(data);
3227
+ try {
3228
+ return JSON.parse(text);
3229
+ } catch {
3230
+ return text;
3231
+ }
3232
+ },
3233
+ ...rest
3234
+ } = opts ?? {};
3235
+ return producer((_d, a) => {
3236
+ let active = true;
3237
+ const sub = client.subscribe(subject, queue ? { queue } : void 0);
3238
+ const loop = async () => {
3239
+ try {
3240
+ for await (const msg of sub) {
3241
+ if (!active) return;
3242
+ const headers = {};
3243
+ if (msg.headers) {
3244
+ for (const k of msg.headers.keys()) {
3245
+ headers[k] = msg.headers.get(k);
3246
+ }
3247
+ }
3248
+ a.emit({
3249
+ subject: msg.subject,
3250
+ data: deserialize(msg.data),
3251
+ headers,
3252
+ reply: msg.reply,
3253
+ sid: msg.sid,
3254
+ timestampNs: wallClockNs()
3255
+ });
3256
+ }
3257
+ if (active) a.down([[COMPLETE]]);
3258
+ } catch (err) {
3259
+ if (active) a.down([[ERROR, err]]);
3260
+ }
3261
+ };
3262
+ void loop();
3263
+ return () => {
3264
+ active = false;
3265
+ };
3266
+ }, sourceOpts2(rest));
3267
+ }
3268
+ function toNATS(source, client, subject, opts) {
3269
+ const encoder = new TextEncoder();
3270
+ const {
3271
+ serialize = (v) => encoder.encode(JSON.stringify(v)),
3272
+ onTransportError,
3273
+ ...rest
3274
+ } = opts ?? {};
3275
+ const inner = node([source], () => void 0, {
3276
+ describeKind: "effect",
3277
+ ...rest,
3278
+ onMessage(msg, _depIndex, _actions) {
3279
+ if (msg[0] === DATA) {
3280
+ const value = msg[1];
3281
+ let data;
3282
+ try {
3283
+ data = serialize(value);
3284
+ } catch (err) {
3285
+ onTransportError?.({
3286
+ stage: "serialize",
3287
+ error: err instanceof Error ? err : new Error(String(err)),
3288
+ value
3289
+ });
3290
+ return true;
3291
+ }
3292
+ try {
3293
+ client.publish(subject, data);
3294
+ } catch (err) {
3295
+ onTransportError?.({
3296
+ stage: "send",
3297
+ error: err instanceof Error ? err : new Error(String(err)),
3298
+ value
3299
+ });
3300
+ }
3301
+ return true;
3302
+ }
3303
+ return false;
3304
+ }
3305
+ });
3306
+ return inner.subscribe(() => {
3307
+ });
3308
+ }
3309
+ function fromRabbitMQ(channel, queue, opts) {
3310
+ const {
3311
+ autoAck = true,
3312
+ deserialize = (buf) => {
3313
+ try {
3314
+ return JSON.parse(buf.toString());
3315
+ } catch {
3316
+ return buf.toString();
3317
+ }
3318
+ },
3319
+ ...rest
3320
+ } = opts ?? {};
3321
+ return producer((_d, a) => {
3322
+ let active = true;
3323
+ let consumerTag;
3324
+ const start = async () => {
3325
+ try {
3326
+ const result = await channel.consume(
3327
+ queue,
3328
+ (msg) => {
3329
+ if (!active) return;
3330
+ if (msg === null) {
3331
+ if (active) a.down([[ERROR, new Error("Consumer cancelled by broker")]]);
3332
+ return;
3333
+ }
3334
+ a.emit({
3335
+ queue,
3336
+ routingKey: msg.fields.routingKey,
3337
+ exchange: msg.fields.exchange,
3338
+ content: deserialize(msg.content),
3339
+ properties: msg.properties,
3340
+ deliveryTag: msg.fields.deliveryTag,
3341
+ redelivered: msg.fields.redelivered,
3342
+ timestampNs: wallClockNs()
3343
+ });
3344
+ if (autoAck) channel.ack(msg);
3345
+ },
3346
+ { noAck: false }
3347
+ );
3348
+ consumerTag = result.consumerTag;
3349
+ } catch (err) {
3350
+ if (active) a.down([[ERROR, err]]);
3351
+ }
3352
+ };
3353
+ void start();
3354
+ return () => {
3355
+ active = false;
3356
+ if (consumerTag !== void 0) {
3357
+ void channel.cancel(consumerTag);
3358
+ }
3359
+ };
3360
+ }, sourceOpts2(rest));
3361
+ }
3362
+ function toRabbitMQ(source, channel, exchange, opts) {
3363
+ const {
3364
+ serialize = (v) => Buffer.from(JSON.stringify(v)),
3365
+ routingKeyExtractor = () => "",
3366
+ onTransportError,
3367
+ ...rest
3368
+ } = opts ?? {};
3369
+ const inner = node([source], () => void 0, {
3370
+ describeKind: "effect",
3371
+ ...rest,
3372
+ onMessage(msg, _depIndex, _actions) {
3373
+ if (msg[0] === DATA) {
3374
+ const value = msg[1];
3375
+ let routingKey;
3376
+ try {
3377
+ routingKey = routingKeyExtractor(value);
3378
+ } catch (err) {
3379
+ onTransportError?.({
3380
+ stage: "routing_key",
3381
+ error: err instanceof Error ? err : new Error(String(err)),
3382
+ value
3383
+ });
3384
+ return true;
3385
+ }
3386
+ let content;
3387
+ try {
3388
+ content = serialize(value);
3389
+ } catch (err) {
3390
+ onTransportError?.({
3391
+ stage: "serialize",
3392
+ error: err instanceof Error ? err : new Error(String(err)),
3393
+ value
3394
+ });
3395
+ return true;
3396
+ }
3397
+ try {
3398
+ channel.publish(exchange, routingKey, content);
3399
+ } catch (err) {
3400
+ onTransportError?.({
3401
+ stage: "send",
3402
+ error: err instanceof Error ? err : new Error(String(err)),
3403
+ value
3404
+ });
3405
+ }
3406
+ return true;
3407
+ }
3408
+ return false;
3409
+ }
3410
+ });
3411
+ return inner.subscribe(() => {
3412
+ });
3413
+ }
3414
+ function toFile(source, writer, opts) {
3415
+ const {
3416
+ serialize = (v) => `${JSON.stringify(v)}
3417
+ `,
3418
+ flushIntervalMs = 0,
3419
+ batchSize = Number.POSITIVE_INFINITY,
3420
+ onTransportError,
3421
+ mode: _mode,
3422
+ ...rest
3423
+ } = opts ?? {};
3424
+ let buffer2 = [];
3425
+ let timer;
3426
+ const doFlush = () => {
3427
+ if (buffer2.length === 0) return;
3428
+ const chunk = buffer2.join("");
3429
+ buffer2 = [];
3430
+ try {
3431
+ writer.write(chunk);
3432
+ } catch (err) {
3433
+ onTransportError?.({
3434
+ stage: "send",
3435
+ error: err instanceof Error ? err : new Error(String(err)),
3436
+ value: chunk
3437
+ });
3438
+ }
3439
+ };
3440
+ const scheduleFlush = () => {
3441
+ if (flushIntervalMs > 0 && timer === void 0) {
3442
+ timer = setTimeout(() => {
3443
+ timer = void 0;
3444
+ doFlush();
3445
+ }, flushIntervalMs);
3446
+ }
3447
+ };
3448
+ const buffered = flushIntervalMs > 0 || batchSize < Number.POSITIVE_INFINITY;
3449
+ const inner = node([source], () => void 0, {
3450
+ describeKind: "effect",
3451
+ ...rest,
3452
+ onMessage(msg, _depIndex, _actions) {
3453
+ if (msg[0] === DATA) {
3454
+ const value = msg[1];
3455
+ let line;
3456
+ try {
3457
+ line = serialize(value);
3458
+ } catch (err) {
3459
+ onTransportError?.({
3460
+ stage: "serialize",
3461
+ error: err instanceof Error ? err : new Error(String(err)),
3462
+ value
3463
+ });
3464
+ return true;
3465
+ }
3466
+ if (buffered) {
3467
+ buffer2.push(line);
3468
+ if (buffer2.length >= batchSize) doFlush();
3469
+ else scheduleFlush();
3470
+ } else {
3471
+ try {
3472
+ writer.write(line);
3473
+ } catch (err) {
3474
+ onTransportError?.({
3475
+ stage: "send",
3476
+ error: err instanceof Error ? err : new Error(String(err)),
3477
+ value
3478
+ });
3479
+ }
3480
+ }
3481
+ return true;
3482
+ }
3483
+ if (msg[0] === COMPLETE || msg[0] === TEARDOWN) {
3484
+ doFlush();
3485
+ }
3486
+ return false;
3487
+ }
3488
+ });
3489
+ const unsub = inner.subscribe(() => {
3490
+ });
3491
+ const dispose = () => {
3492
+ if (timer !== void 0) {
3493
+ clearTimeout(timer);
3494
+ timer = void 0;
3495
+ }
3496
+ doFlush();
3497
+ writer.end();
3498
+ unsub();
3499
+ };
3500
+ return {
3501
+ dispose,
3502
+ flush: async () => {
3503
+ doFlush();
3504
+ }
3505
+ };
3506
+ }
3507
+ function escapeCSVField(value, delimiter) {
3508
+ if (value.includes(delimiter) || value.includes('"') || value.includes("\n")) {
3509
+ return `"${value.replace(/"/g, '""')}"`;
3510
+ }
3511
+ return value;
3512
+ }
3513
+ function toCSV(source, writer, opts) {
3514
+ const {
3515
+ columns,
3516
+ delimiter = ",",
3517
+ writeHeader = true,
3518
+ cellExtractor = (row, col) => String(row[col] ?? ""),
3519
+ flushIntervalMs = 0,
3520
+ batchSize = Number.POSITIVE_INFINITY,
3521
+ onTransportError,
3522
+ ...rest
3523
+ } = opts;
3524
+ let headerWritten = false;
3525
+ const serializeRow = (row) => {
3526
+ if (!headerWritten && writeHeader) {
3527
+ headerWritten = true;
3528
+ const header = columns.map((c) => escapeCSVField(c, delimiter)).join(delimiter);
3529
+ const data = columns.map((c) => escapeCSVField(cellExtractor(row, c), delimiter)).join(delimiter);
3530
+ return `${header}
3531
+ ${data}
3532
+ `;
3533
+ }
3534
+ return `${columns.map((c) => escapeCSVField(cellExtractor(row, c), delimiter)).join(delimiter)}
3535
+ `;
3536
+ };
3537
+ return toFile(source, writer, {
3538
+ serialize: serializeRow,
3539
+ flushIntervalMs,
3540
+ batchSize,
3541
+ onTransportError,
3542
+ ...rest
3543
+ });
3544
+ }
3545
+ function toClickHouse(source, client, table, opts) {
3546
+ const {
3547
+ batchSize = 1e3,
3548
+ flushIntervalMs = 5e3,
3549
+ format = "JSONEachRow",
3550
+ transform = (v) => v,
3551
+ onTransportError,
3552
+ ...rest
3553
+ } = opts ?? {};
3554
+ let buffer2 = [];
3555
+ let timer;
3556
+ let lastFlush = Promise.resolve();
3557
+ const doFlush = () => {
3558
+ if (buffer2.length === 0) return Promise.resolve();
3559
+ const batch2 = buffer2;
3560
+ buffer2 = [];
3561
+ try {
3562
+ const p = client.insert({ table, values: batch2, format }).catch((err) => {
3563
+ onTransportError?.({
3564
+ stage: "send",
3565
+ error: err instanceof Error ? err : new Error(String(err)),
3566
+ value: batch2
3567
+ });
3568
+ });
3569
+ lastFlush = p;
3570
+ return p;
3571
+ } catch (err) {
3572
+ onTransportError?.({
3573
+ stage: "send",
3574
+ error: err instanceof Error ? err : new Error(String(err)),
3575
+ value: batch2
3576
+ });
3577
+ return Promise.resolve();
3578
+ }
3579
+ };
3580
+ const scheduleFlush = () => {
3581
+ if (timer === void 0) {
3582
+ timer = setTimeout(() => {
3583
+ timer = void 0;
3584
+ doFlush();
3585
+ }, flushIntervalMs);
3586
+ }
3587
+ };
3588
+ const inner = node([source], () => void 0, {
3589
+ describeKind: "effect",
3590
+ ...rest,
3591
+ onMessage(msg, _depIndex, _actions) {
3592
+ if (msg[0] === DATA) {
3593
+ const value = msg[1];
3594
+ try {
3595
+ buffer2.push(transform(value));
3596
+ } catch (err) {
3597
+ onTransportError?.({
3598
+ stage: "serialize",
3599
+ error: err instanceof Error ? err : new Error(String(err)),
3600
+ value
3601
+ });
3602
+ return true;
3603
+ }
3604
+ if (buffer2.length >= batchSize) doFlush();
3605
+ else scheduleFlush();
3606
+ return true;
3607
+ }
3608
+ if (msg[0] === COMPLETE || msg[0] === TEARDOWN) {
3609
+ doFlush();
3610
+ }
3611
+ return false;
3612
+ }
3613
+ });
3614
+ const unsub = inner.subscribe(() => {
3615
+ });
3616
+ const dispose = () => {
3617
+ if (timer !== void 0) {
3618
+ clearTimeout(timer);
3619
+ timer = void 0;
3620
+ }
3621
+ doFlush();
3622
+ unsub();
3623
+ };
3624
+ return {
3625
+ dispose,
3626
+ flush: () => doFlush().then(() => lastFlush)
3627
+ };
3628
+ }
3629
+ function toS3(source, client, bucket, opts) {
3630
+ const {
3631
+ format = "ndjson",
3632
+ keyGenerator = (seq2, timestampNs) => {
3633
+ const ms = Math.floor(timestampNs / 1e6);
3634
+ const ts = new Date(ms).toISOString().replace(/[:.]/g, "-");
3635
+ return `data/${ts}-${seq2}.${format === "ndjson" ? "ndjson" : "json"}`;
3636
+ },
3637
+ batchSize = 1e3,
3638
+ flushIntervalMs = 1e4,
3639
+ transform = (v) => v,
3640
+ onTransportError,
3641
+ ...rest
3642
+ } = opts ?? {};
3643
+ let buffer2 = [];
3644
+ let timer;
3645
+ let seq = 0;
3646
+ let lastFlush = Promise.resolve();
3647
+ const doFlush = () => {
3648
+ if (buffer2.length === 0) return Promise.resolve();
3649
+ const batch2 = buffer2;
3650
+ buffer2 = [];
3651
+ seq += 1;
3652
+ const body = format === "ndjson" ? `${batch2.map((v) => JSON.stringify(v)).join("\n")}
3653
+ ` : JSON.stringify(batch2);
3654
+ const contentType = format === "ndjson" ? "application/x-ndjson" : "application/json";
3655
+ const key = keyGenerator(seq, wallClockNs());
3656
+ try {
3657
+ const p = client.putObject({ Bucket: bucket, Key: key, Body: body, ContentType: contentType }).then(() => {
3658
+ }).catch((err) => {
3659
+ onTransportError?.({
3660
+ stage: "send",
3661
+ error: err instanceof Error ? err : new Error(String(err)),
3662
+ value: batch2
3663
+ });
3664
+ });
3665
+ lastFlush = p;
3666
+ return p;
3667
+ } catch (err) {
3668
+ onTransportError?.({
3669
+ stage: "send",
3670
+ error: err instanceof Error ? err : new Error(String(err)),
3671
+ value: batch2
3672
+ });
3673
+ return Promise.resolve();
3674
+ }
3675
+ };
3676
+ const scheduleFlush = () => {
3677
+ if (timer === void 0) {
3678
+ timer = setTimeout(() => {
3679
+ timer = void 0;
3680
+ doFlush();
3681
+ }, flushIntervalMs);
3682
+ }
3683
+ };
3684
+ const inner = node([source], () => void 0, {
3685
+ describeKind: "effect",
3686
+ ...rest,
3687
+ onMessage(msg, _depIndex, _actions) {
3688
+ if (msg[0] === DATA) {
3689
+ const value = msg[1];
3690
+ try {
3691
+ buffer2.push(transform(value));
3692
+ } catch (err) {
3693
+ onTransportError?.({
3694
+ stage: "serialize",
3695
+ error: err instanceof Error ? err : new Error(String(err)),
3696
+ value
3697
+ });
3698
+ return true;
3699
+ }
3700
+ if (buffer2.length >= batchSize) doFlush();
3701
+ else scheduleFlush();
3702
+ return true;
3703
+ }
3704
+ if (msg[0] === COMPLETE || msg[0] === TEARDOWN) {
3705
+ doFlush();
3706
+ }
3707
+ return false;
3708
+ }
3709
+ });
3710
+ const unsub = inner.subscribe(() => {
3711
+ });
3712
+ const dispose = () => {
3713
+ if (timer !== void 0) {
3714
+ clearTimeout(timer);
3715
+ timer = void 0;
3716
+ }
3717
+ doFlush();
3718
+ unsub();
3719
+ };
3720
+ return {
3721
+ dispose,
3722
+ flush: () => doFlush().then(() => lastFlush)
3723
+ };
3724
+ }
3725
+ function toPostgres(source, client, table, opts) {
3726
+ const {
3727
+ toSQL = (v, t) => ({
3728
+ sql: `INSERT INTO "${t.replace(/"/g, '""')}" (data) VALUES ($1)`,
3729
+ params: [JSON.stringify(v)]
3730
+ }),
3731
+ onTransportError,
3732
+ ...rest
3733
+ } = opts ?? {};
3734
+ const inner = node([source], () => void 0, {
3735
+ describeKind: "effect",
3736
+ ...rest,
3737
+ onMessage(msg, _depIndex, _actions) {
3738
+ if (msg[0] === DATA) {
3739
+ const value = msg[1];
3740
+ let query;
3741
+ try {
3742
+ query = toSQL(value, table);
3743
+ } catch (err) {
3744
+ onTransportError?.({
3745
+ stage: "serialize",
3746
+ error: err instanceof Error ? err : new Error(String(err)),
3747
+ value
3748
+ });
3749
+ return true;
3750
+ }
3751
+ void client.query(query.sql, query.params).catch((err) => {
3752
+ onTransportError?.({
3753
+ stage: "send",
3754
+ error: err instanceof Error ? err : new Error(String(err)),
3755
+ value
3756
+ });
3757
+ });
3758
+ return true;
3759
+ }
3760
+ return false;
3761
+ }
3762
+ });
3763
+ return inner.subscribe(() => {
3764
+ });
3765
+ }
3766
+ function toMongo(source, collection, opts) {
3767
+ const { toDocument = (v) => v, onTransportError, ...rest } = opts ?? {};
3768
+ const inner = node([source], () => void 0, {
3769
+ describeKind: "effect",
3770
+ ...rest,
3771
+ onMessage(msg, _depIndex, _actions) {
3772
+ if (msg[0] === DATA) {
3773
+ const value = msg[1];
3774
+ let doc;
3775
+ try {
3776
+ doc = toDocument(value);
3777
+ } catch (err) {
3778
+ onTransportError?.({
3779
+ stage: "serialize",
3780
+ error: err instanceof Error ? err : new Error(String(err)),
3781
+ value
3782
+ });
3783
+ return true;
3784
+ }
3785
+ void collection.insertOne(doc).catch((err) => {
3786
+ onTransportError?.({
3787
+ stage: "send",
3788
+ error: err instanceof Error ? err : new Error(String(err)),
3789
+ value
3790
+ });
3791
+ });
3792
+ return true;
3793
+ }
3794
+ return false;
3795
+ }
3796
+ });
3797
+ return inner.subscribe(() => {
3798
+ });
3799
+ }
3800
+ function toLoki(source, client, opts) {
3801
+ const {
3802
+ labels = {},
3803
+ toLine = (v) => JSON.stringify(v),
3804
+ toLabels,
3805
+ onTransportError,
3806
+ ...rest
3807
+ } = opts ?? {};
3808
+ const inner = node([source], () => void 0, {
3809
+ describeKind: "effect",
3810
+ ...rest,
3811
+ onMessage(msg, _depIndex, _actions) {
3812
+ if (msg[0] === DATA) {
3813
+ const value = msg[1];
3814
+ let line;
3815
+ try {
3816
+ line = toLine(value);
3817
+ } catch (err) {
3818
+ onTransportError?.({
3819
+ stage: "serialize",
3820
+ error: err instanceof Error ? err : new Error(String(err)),
3821
+ value
3822
+ });
3823
+ return true;
3824
+ }
3825
+ let streamLabels;
3826
+ try {
3827
+ streamLabels = toLabels ? { ...labels, ...toLabels(value) } : labels;
3828
+ } catch (err) {
3829
+ onTransportError?.({
3830
+ stage: "serialize",
3831
+ error: err instanceof Error ? err : new Error(String(err)),
3832
+ value
3833
+ });
3834
+ return true;
3835
+ }
3836
+ const ts = `${wallClockNs()}`;
3837
+ void client.push({ streams: [{ stream: streamLabels, values: [[ts, line]] }] }).catch((err) => {
3838
+ onTransportError?.({
3839
+ stage: "send",
3840
+ error: err instanceof Error ? err : new Error(String(err)),
3841
+ value
3842
+ });
3843
+ });
3844
+ return true;
3845
+ }
3846
+ return false;
3847
+ }
3848
+ });
3849
+ return inner.subscribe(() => {
3850
+ });
3851
+ }
3852
+ function toTempo(source, client, opts) {
3853
+ const { toResourceSpans = (v) => [v], onTransportError, ...rest } = opts ?? {};
3854
+ const inner = node([source], () => void 0, {
3855
+ describeKind: "effect",
3856
+ ...rest,
3857
+ onMessage(msg, _depIndex, _actions) {
3858
+ if (msg[0] === DATA) {
3859
+ const value = msg[1];
3860
+ let spans;
3861
+ try {
3862
+ spans = toResourceSpans(value);
3863
+ } catch (err) {
3864
+ onTransportError?.({
3865
+ stage: "serialize",
3866
+ error: err instanceof Error ? err : new Error(String(err)),
3867
+ value
3868
+ });
3869
+ return true;
3870
+ }
3871
+ void client.push({ resourceSpans: spans }).catch((err) => {
3872
+ onTransportError?.({
3873
+ stage: "send",
3874
+ error: err instanceof Error ? err : new Error(String(err)),
3875
+ value
3876
+ });
3877
+ });
3878
+ return true;
3879
+ }
3880
+ return false;
3881
+ }
3882
+ });
3883
+ return inner.subscribe(() => {
3884
+ });
3885
+ }
3886
+ function checkpointToS3(graph, client, bucket, opts) {
3887
+ const { prefix = "checkpoints/", debounceMs, compactEvery, onError } = opts ?? {};
3888
+ const adapter = {
3889
+ save(data) {
3890
+ const ms = Math.floor(wallClockNs() / 1e6);
3891
+ const key = `${prefix}${graph.name}/checkpoint-${ms}.json`;
3892
+ let body;
3893
+ try {
3894
+ body = JSON.stringify(data);
3895
+ } catch (err) {
3896
+ onError?.(err);
3897
+ return;
3898
+ }
3899
+ void client.putObject({
3900
+ Bucket: bucket,
3901
+ Key: key,
3902
+ Body: body,
3903
+ ContentType: "application/json"
3904
+ }).catch((err) => onError?.(err));
3905
+ }
3906
+ };
3907
+ return graph.autoCheckpoint(adapter, { debounceMs, compactEvery, onError });
3908
+ }
3909
+ function checkpointToRedis(graph, client, opts) {
3910
+ const { prefix = "graphrefly:checkpoint:", debounceMs, compactEvery, onError } = opts ?? {};
3911
+ const key = `${prefix}${graph.name}`;
3912
+ const adapter = {
3913
+ save(data) {
3914
+ let body;
3915
+ try {
3916
+ body = JSON.stringify(data);
3917
+ } catch (err) {
3918
+ onError?.(err);
3919
+ return;
3920
+ }
3921
+ void client.set(key, body).catch((err) => onError?.(err));
3922
+ }
3923
+ };
3924
+ return graph.autoCheckpoint(adapter, { debounceMs, compactEvery, onError });
3925
+ }
3926
+ function fromSqlite(db, query, opts) {
3927
+ const { mapRow = (r) => r, params, ...rest } = opts ?? {};
3928
+ return producer(
3929
+ (_d, a) => {
3930
+ let mapped;
3931
+ try {
3932
+ const rows = db.query(query, params);
3933
+ mapped = rows.map(mapRow);
3934
+ } catch (err) {
3935
+ a.down([[ERROR, err instanceof Error ? err : new Error(String(err))]]);
3936
+ return void 0;
3937
+ }
3938
+ batch(() => {
3939
+ for (const item of mapped) {
3940
+ a.down([[DATA, item]]);
3941
+ }
3942
+ a.down([[COMPLETE]]);
3943
+ });
3944
+ return void 0;
3945
+ },
3946
+ { describeKind: "producer", completeWhenDepsComplete: false, ...rest }
3947
+ );
3948
+ }
3949
+ function toSqlite(source, db, table, opts) {
3950
+ if (table.includes("\0") || table.length === 0) {
3951
+ throw new Error(`toSqlite: invalid table name: ${JSON.stringify(table)}`);
3952
+ }
3953
+ const {
3954
+ toSQL = (v, t) => ({
3955
+ sql: `INSERT INTO "${t.replace(/"/g, '""')}" (data) VALUES (?)`,
3956
+ params: [JSON.stringify(v)]
3957
+ }),
3958
+ onTransportError,
3959
+ ...rest
3960
+ } = opts ?? {};
3961
+ const inner = node([source], () => void 0, {
3962
+ describeKind: "effect",
3963
+ ...rest,
3964
+ onMessage(msg, _depIndex, _actions) {
3965
+ if (msg[0] === DATA) {
3966
+ const value = msg[1];
3967
+ let query;
3968
+ try {
3969
+ query = toSQL(value, table);
3970
+ } catch (err) {
3971
+ onTransportError?.({
3972
+ stage: "serialize",
3973
+ error: err instanceof Error ? err : new Error(String(err)),
3974
+ value
3975
+ });
3976
+ return true;
3977
+ }
3978
+ try {
3979
+ db.query(query.sql, query.params);
3980
+ } catch (err) {
3981
+ onTransportError?.({
3982
+ stage: "send",
3983
+ error: err instanceof Error ? err : new Error(String(err)),
3984
+ value
3985
+ });
3986
+ }
3987
+ return true;
3988
+ }
3989
+ return false;
3990
+ }
3991
+ });
3992
+ return inner.subscribe(() => {
3993
+ });
3994
+ }
3117
3995
 
3118
3996
  // src/extra/backpressure.ts
3119
3997
  var nextLockId = 0;
@@ -6754,6 +7632,8 @@ function workerSelf(target, opts) {
6754
7632
  cached,
6755
7633
  catchError,
6756
7634
  checkpointNodeValue,
7635
+ checkpointToRedis,
7636
+ checkpointToS3,
6757
7637
  circuitBreaker,
6758
7638
  combine,
6759
7639
  combineLatest,
@@ -6795,11 +7675,15 @@ function workerSelf(target, opts) {
6795
7675
  fromIter,
6796
7676
  fromKafka,
6797
7677
  fromMCP,
7678
+ fromNATS,
6798
7679
  fromNDJSON,
6799
7680
  fromOTel,
6800
7681
  fromPrometheus,
6801
7682
  fromPromise,
7683
+ fromPulsar,
7684
+ fromRabbitMQ,
6802
7685
  fromRedisStream,
7686
+ fromSqlite,
6803
7687
  fromStatsD,
6804
7688
  fromSyslog,
6805
7689
  fromTimer,
@@ -6862,11 +7746,23 @@ function workerSelf(target, opts) {
6862
7746
  throwError,
6863
7747
  timeout,
6864
7748
  toArray,
7749
+ toCSV,
7750
+ toClickHouse,
7751
+ toFile,
6865
7752
  toKafka,
7753
+ toLoki,
6866
7754
  toMessages$,
7755
+ toMongo,
7756
+ toNATS,
6867
7757
  toObservable,
7758
+ toPostgres,
7759
+ toPulsar,
7760
+ toRabbitMQ,
6868
7761
  toRedisStream,
7762
+ toS3,
6869
7763
  toSSE,
7764
+ toSqlite,
7765
+ toTempo,
6870
7766
  toWebSocket,
6871
7767
  tokenBucket,
6872
7768
  tokenTracker,