@kiwa-test/edge 1.0.2 → 1.1.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/dist/index.cjs CHANGED
@@ -20,8 +20,45 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ AXIS_TO_EVENTS: () => AXIS_TO_EVENTS,
24
+ acceptWebSocket: () => acceptWebSocket,
25
+ closeStream: () => closeStream,
26
+ closeWebSocket: () => closeWebSocket,
27
+ collectFidelityCoverage: () => collectFidelityCoverage,
28
+ completeCpu: () => completeCpu,
29
+ completeCron: () => completeCron,
30
+ completeSubrequest: () => completeSubrequest,
31
+ countSubrequest: () => countSubrequest,
32
+ createDurableObject: () => createDurableObject,
33
+ createEdgeKvSession: () => createEdgeKvSession,
34
+ createGeoReplicatedSession: () => createGeoReplicatedSession,
23
35
  createKvNamespace: () => createKvNamespace,
24
- invokeEdgeHandler: () => invokeEdgeHandler
36
+ failCron: () => failCron,
37
+ fireAlarm: () => fireAlarm,
38
+ geoPrimaryWrite: () => geoPrimaryWrite,
39
+ invokeEdgeHandler: () => invokeEdgeHandler,
40
+ kvRangeQuery: () => kvRangeQuery,
41
+ kvRead: () => kvRead,
42
+ kvWrite: () => kvWrite,
43
+ markReplicaLagged: () => markReplicaLagged,
44
+ openStream: () => openStream,
45
+ platformEventName: () => platformEventName,
46
+ remainingBudget: () => remainingBudget,
47
+ requestDurableObject: () => requestDurableObject,
48
+ requestWebSocketUpgrade: () => requestWebSocketUpgrade,
49
+ resolveConflict: () => resolveConflict,
50
+ resumeStream: () => resumeStream,
51
+ scheduleCron: () => scheduleCron,
52
+ sendChunk: () => sendChunk,
53
+ sendMessage: () => sendMessage,
54
+ startCpu: () => startCpu,
55
+ startCpuBudget: () => startCpuBudget,
56
+ startCron: () => startCron,
57
+ startSubrequest: () => startSubrequest,
58
+ startSubrequestBudget: () => startSubrequestBudget,
59
+ syncReplica: () => syncReplica,
60
+ tickCpu: () => tickCpu,
61
+ writeStorage: () => writeStorage
25
62
  });
26
63
  module.exports = __toCommonJS(index_exports);
27
64
 
@@ -126,9 +163,836 @@ function createKvNamespace(initial = {}) {
126
163
  }
127
164
  };
128
165
  }
166
+
167
+ // src/semantics/types.ts
168
+ var dialect = {
169
+ cloudflare: {
170
+ "durable-object.created": "durable_object.created",
171
+ "durable-object.requested": "durable_object.fetch",
172
+ "durable-object.alarm-fired": "durable_object.alarm",
173
+ "durable-object.storage-written": "durable_object.storage.put",
174
+ "websocket.upgrade-requested": "websocket_upgrade.requested",
175
+ "websocket.accepted": "websocket_upgrade.accepted",
176
+ "websocket.message": "websocket.message",
177
+ "websocket.closed": "websocket.close",
178
+ "kv.read": "kv_get",
179
+ "kv.write": "kv_put",
180
+ "kv.cache-hit": "kv_cache.hit",
181
+ "kv.cache-miss": "kv_cache.miss",
182
+ "geo.primary-write": "smart_placement.primary_write",
183
+ "geo.replica-lagged": "kv_replication.lagged",
184
+ "geo.replica-synced": "kv_replication.synced",
185
+ "geo.conflict-resolved": "durable_object.conflict_resolved",
186
+ "cron.scheduled": "scheduled_event.enqueued",
187
+ "cron.started": "scheduled_event.started",
188
+ "cron.completed": "scheduled_event.completed",
189
+ "cron.failed": "scheduled_event.failed",
190
+ "subrequest.started": "subrequest.fetch",
191
+ "subrequest.counted": "subrequest.counted",
192
+ "subrequest.limited": "subrequest.limit_exceeded",
193
+ "subrequest.completed": "subrequest.completed",
194
+ "cpu.started": "worker.cpu.started",
195
+ "cpu.budget-warning": "worker.cpu.warning",
196
+ "cpu.limited": "worker.cpu.limit_exceeded",
197
+ "cpu.completed": "worker.cpu.completed",
198
+ "stream.opened": "response_stream.opened",
199
+ "stream.chunk-sent": "response_stream.chunk",
200
+ "stream.backpressure": "response_stream.backpressure",
201
+ "stream.closed": "response_stream.closed"
202
+ },
203
+ vercel: {
204
+ "durable-object.created": "edge_function.session_affinity.created",
205
+ "durable-object.requested": "edge_function.session_affinity.request",
206
+ "durable-object.alarm-fired": "edge_function.background_timer",
207
+ "durable-object.storage-written": "edge_config.write",
208
+ "websocket.upgrade-requested": "edge_websocket_upgrade.requested",
209
+ "websocket.accepted": "edge_websocket_upgrade.accepted",
210
+ "websocket.message": "edge_websocket.message",
211
+ "websocket.closed": "edge_websocket.close",
212
+ "kv.read": "edge_config.get",
213
+ "kv.write": "edge_config.set",
214
+ "kv.cache-hit": "edge_config.cache_hit",
215
+ "kv.cache-miss": "edge_config.cache_miss",
216
+ "geo.primary-write": "edge_config.primary_write",
217
+ "geo.replica-lagged": "edge_config.replica_lagged",
218
+ "geo.replica-synced": "edge_config.replica_synced",
219
+ "geo.conflict-resolved": "edge_config.conflict_resolved",
220
+ "cron.scheduled": "vercel_cron.scheduled",
221
+ "cron.started": "vercel_cron.started",
222
+ "cron.completed": "vercel_cron.completed",
223
+ "cron.failed": "vercel_cron.failed",
224
+ "subrequest.started": "edge_function.fetch",
225
+ "subrequest.counted": "edge_function.subrequest_counted",
226
+ "subrequest.limited": "edge_function.subrequest_limited",
227
+ "subrequest.completed": "edge_function.fetch_completed",
228
+ "cpu.started": "edge_function.cpu_started",
229
+ "cpu.budget-warning": "edge_function.cpu_warning",
230
+ "cpu.limited": "edge_function.cpu_limited",
231
+ "cpu.completed": "edge_function.cpu_completed",
232
+ "stream.opened": "edge_function.stream_opened",
233
+ "stream.chunk-sent": "edge_function.stream_chunk",
234
+ "stream.backpressure": "edge_function.stream_backpressure",
235
+ "stream.closed": "edge_function.stream_closed"
236
+ },
237
+ deno: {
238
+ "durable-object.created": "deploy.stateful_object.created",
239
+ "durable-object.requested": "deploy.stateful_fetch",
240
+ "durable-object.alarm-fired": "deploy.cron.timer",
241
+ "durable-object.storage-written": "deno_kv.atomic_write",
242
+ "websocket.upgrade-requested": "deno_websocket_upgrade.requested",
243
+ "websocket.accepted": "deno_websocket_upgrade.accepted",
244
+ "websocket.message": "deno_websocket.message",
245
+ "websocket.closed": "deno_websocket.close",
246
+ "kv.read": "deno_kv.get",
247
+ "kv.write": "deno_kv.set",
248
+ "kv.cache-hit": "deno_kv.cache_hit",
249
+ "kv.cache-miss": "deno_kv.cache_miss",
250
+ "geo.primary-write": "deno_kv.primary_write",
251
+ "geo.replica-lagged": "deno_kv.replica_lagged",
252
+ "geo.replica-synced": "deno_kv.replica_synced",
253
+ "geo.conflict-resolved": "deno_kv.conflict_resolved",
254
+ "cron.scheduled": "deploy.cron.scheduled",
255
+ "cron.started": "deploy.cron.started",
256
+ "cron.completed": "deploy.cron.completed",
257
+ "cron.failed": "deploy.cron.failed",
258
+ "subrequest.started": "deploy.fetch.started",
259
+ "subrequest.counted": "deploy.fetch.counted",
260
+ "subrequest.limited": "deploy.fetch.limited",
261
+ "subrequest.completed": "deploy.fetch.completed",
262
+ "cpu.started": "deploy.cpu.started",
263
+ "cpu.budget-warning": "deploy.cpu.warning",
264
+ "cpu.limited": "deploy.cpu.limited",
265
+ "cpu.completed": "deploy.cpu.completed",
266
+ "stream.opened": "deploy.stream.opened",
267
+ "stream.chunk-sent": "deploy.stream.chunk",
268
+ "stream.backpressure": "deploy.stream.backpressure",
269
+ "stream.closed": "deploy.stream.closed"
270
+ }
271
+ };
272
+ function platformEventName(platform, neutral) {
273
+ return dialect[platform][neutral] ?? neutral;
274
+ }
275
+
276
+ // src/semantics/fidelity.ts
277
+ var AXIS_TO_EVENTS = {
278
+ "durable-object": [
279
+ "durable-object.created",
280
+ "durable-object.requested",
281
+ "durable-object.alarm-fired",
282
+ "durable-object.storage-written"
283
+ ],
284
+ "websocket-edge": [
285
+ "websocket.upgrade-requested",
286
+ "websocket.accepted",
287
+ "websocket.message",
288
+ "websocket.closed"
289
+ ],
290
+ "edge-kv": ["kv.read", "kv.write", "kv.cache-hit", "kv.cache-miss"],
291
+ "geo-replicated": [
292
+ "geo.primary-write",
293
+ "geo.replica-lagged",
294
+ "geo.replica-synced",
295
+ "geo.conflict-resolved"
296
+ ],
297
+ "cron-trigger": ["cron.scheduled", "cron.started", "cron.completed", "cron.failed"],
298
+ "subrequest-limit": [
299
+ "subrequest.started",
300
+ "subrequest.counted",
301
+ "subrequest.limited",
302
+ "subrequest.completed"
303
+ ],
304
+ "cpu-time-limit": ["cpu.started", "cpu.budget-warning", "cpu.limited", "cpu.completed"],
305
+ "streaming-response": [
306
+ "stream.opened",
307
+ "stream.chunk-sent",
308
+ "stream.backpressure",
309
+ "stream.closed"
310
+ ]
311
+ };
312
+ function collectFidelityCoverage(platforms) {
313
+ const axes = Object.keys(AXIS_TO_EVENTS);
314
+ const rows = [];
315
+ for (const platform of platforms) {
316
+ for (const axis of axes) {
317
+ const neutralEvents = AXIS_TO_EVENTS[axis];
318
+ const platformEvents = neutralEvents.map((n) => platformEventName(platform, n));
319
+ rows.push({
320
+ platform,
321
+ axis,
322
+ neutralEvents,
323
+ platformEvents
324
+ });
325
+ }
326
+ }
327
+ return { platforms, axes, rows };
328
+ }
329
+
330
+ // src/semantics/durable-object.ts
331
+ function record(session, step) {
332
+ session.history.push(step);
333
+ return step;
334
+ }
335
+ function createDurableObject(input) {
336
+ const session = {
337
+ id: input.id,
338
+ platform: input.platform,
339
+ state: "initialized",
340
+ requestCount: 0,
341
+ storageKeys: /* @__PURE__ */ new Map(),
342
+ scheduledAlarmAt: null,
343
+ history: []
344
+ };
345
+ record(session, {
346
+ neutralEvent: "durable-object.created",
347
+ platformEvent: platformEventName(input.platform, "durable-object.created"),
348
+ state: "initialized",
349
+ platform: input.platform,
350
+ metadata: { id: input.id }
351
+ });
352
+ return session;
353
+ }
354
+ function requestDurableObject(session, input) {
355
+ if (session.state === "terminated") {
356
+ throw new Error("requestDurableObject: object is terminated");
357
+ }
358
+ session.state = "active";
359
+ session.requestCount += 1;
360
+ return record(session, {
361
+ neutralEvent: "durable-object.requested",
362
+ platformEvent: platformEventName(session.platform, "durable-object.requested"),
363
+ state: session.state,
364
+ platform: session.platform,
365
+ metadata: { url: input.url, requestCount: session.requestCount }
366
+ });
367
+ }
368
+ function fireAlarm(session) {
369
+ if (session.state === "terminated") {
370
+ throw new Error("fireAlarm: object is terminated");
371
+ }
372
+ const firedAt = session.scheduledAlarmAt;
373
+ session.scheduledAlarmAt = null;
374
+ session.state = "active";
375
+ return record(session, {
376
+ neutralEvent: "durable-object.alarm-fired",
377
+ platformEvent: platformEventName(session.platform, "durable-object.alarm-fired"),
378
+ state: session.state,
379
+ platform: session.platform,
380
+ metadata: { firedAt: firedAt ?? 0, scheduled: firedAt !== null }
381
+ });
382
+ }
383
+ function writeStorage(session, input) {
384
+ if (session.state === "terminated") {
385
+ throw new Error("writeStorage: object is terminated");
386
+ }
387
+ session.storageKeys.set(input.key, input.value);
388
+ session.state = "active";
389
+ return record(session, {
390
+ neutralEvent: "durable-object.storage-written",
391
+ platformEvent: platformEventName(session.platform, "durable-object.storage-written"),
392
+ state: session.state,
393
+ platform: session.platform,
394
+ metadata: { key: input.key, size: input.value.length, keyCount: session.storageKeys.size }
395
+ });
396
+ }
397
+
398
+ // src/semantics/websocket-edge.ts
399
+ function record2(session, step) {
400
+ session.history.push(step);
401
+ return step;
402
+ }
403
+ function requestWebSocketUpgrade(input) {
404
+ const session = {
405
+ id: input.id,
406
+ platform: input.platform,
407
+ state: "pending",
408
+ messages: [],
409
+ history: []
410
+ };
411
+ record2(session, {
412
+ neutralEvent: "websocket.upgrade-requested",
413
+ platformEvent: platformEventName(input.platform, "websocket.upgrade-requested"),
414
+ state: "pending",
415
+ platform: input.platform,
416
+ metadata: { id: input.id }
417
+ });
418
+ return session;
419
+ }
420
+ function acceptWebSocket(session) {
421
+ if (session.state !== "pending") {
422
+ throw new Error(`acceptWebSocket: socket is ${session.state}, expected pending`);
423
+ }
424
+ session.state = "open";
425
+ return record2(session, {
426
+ neutralEvent: "websocket.accepted",
427
+ platformEvent: platformEventName(session.platform, "websocket.accepted"),
428
+ state: session.state,
429
+ platform: session.platform,
430
+ metadata: { id: session.id }
431
+ });
432
+ }
433
+ function sendMessage(session, input) {
434
+ if (session.state !== "open") {
435
+ throw new Error(`sendMessage: socket is ${session.state}, expected open`);
436
+ }
437
+ session.messages.push(input.data);
438
+ return record2(session, {
439
+ neutralEvent: "websocket.message",
440
+ platformEvent: platformEventName(session.platform, "websocket.message"),
441
+ state: session.state,
442
+ platform: session.platform,
443
+ metadata: { size: input.data.length, index: session.messages.length - 1 }
444
+ });
445
+ }
446
+ function closeWebSocket(session, input) {
447
+ if (session.state === "closed") {
448
+ throw new Error("closeWebSocket: socket already closed");
449
+ }
450
+ session.state = "closed";
451
+ return record2(session, {
452
+ neutralEvent: "websocket.closed",
453
+ platformEvent: platformEventName(session.platform, "websocket.closed"),
454
+ state: session.state,
455
+ platform: session.platform,
456
+ metadata: { code: input.code, totalMessages: session.messages.length }
457
+ });
458
+ }
459
+
460
+ // src/semantics/edge-kv.ts
461
+ function record3(session, step) {
462
+ session.history.push(step);
463
+ return step;
464
+ }
465
+ function createEdgeKvSession(input) {
466
+ return {
467
+ platform: input.platform,
468
+ store: /* @__PURE__ */ new Map(),
469
+ cache: /* @__PURE__ */ new Map(),
470
+ state: input.state ?? "eventually-consistent",
471
+ history: []
472
+ };
473
+ }
474
+ function kvRead(session, input) {
475
+ let neutral;
476
+ let hit;
477
+ if (session.cache.has(input.key)) {
478
+ neutral = "kv.cache-hit";
479
+ hit = true;
480
+ } else if (session.store.has(input.key)) {
481
+ session.cache.set(input.key, session.store.get(input.key));
482
+ neutral = "kv.read";
483
+ hit = false;
484
+ } else {
485
+ neutral = "kv.cache-miss";
486
+ hit = false;
487
+ }
488
+ return record3(session, {
489
+ neutralEvent: neutral,
490
+ platformEvent: platformEventName(session.platform, neutral),
491
+ state: session.state,
492
+ platform: session.platform,
493
+ metadata: { key: input.key, hit }
494
+ });
495
+ }
496
+ function kvWrite(session, input) {
497
+ session.store.set(input.key, input.value);
498
+ session.cache.delete(input.key);
499
+ return record3(session, {
500
+ neutralEvent: "kv.write",
501
+ platformEvent: platformEventName(session.platform, "kv.write"),
502
+ state: session.state,
503
+ platform: session.platform,
504
+ metadata: { key: input.key, size: input.value.length }
505
+ });
506
+ }
507
+ function kvRangeQuery(session, input) {
508
+ const limit = input.limit ?? Number.POSITIVE_INFINITY;
509
+ const matches = [...session.store.keys()].filter((k) => k.startsWith(input.prefix)).sort().slice(0, limit);
510
+ const step = record3(session, {
511
+ neutralEvent: "kv.read",
512
+ platformEvent: platformEventName(session.platform, "kv.read"),
513
+ state: session.state,
514
+ platform: session.platform,
515
+ metadata: {
516
+ prefix: input.prefix,
517
+ matched: matches.length,
518
+ limit: Number.isFinite(limit) ? limit : 0
519
+ }
520
+ });
521
+ return { matches, step };
522
+ }
523
+
524
+ // src/semantics/geo-replicated.ts
525
+ var POST_WRITE_LAG_MS = 100;
526
+ function record4(session, step) {
527
+ session.history.push(step);
528
+ return step;
529
+ }
530
+ function createGeoReplicatedSession(input) {
531
+ const lagMs = {};
532
+ for (const region of input.replicaRegions) lagMs[region] = 0;
533
+ return {
534
+ platform: input.platform,
535
+ primaryRegion: input.primaryRegion,
536
+ replicaRegions: [...input.replicaRegions],
537
+ state: "in-sync",
538
+ version: 0,
539
+ lagMs,
540
+ history: []
541
+ };
542
+ }
543
+ function geoPrimaryWrite(session, input) {
544
+ session.version += 1;
545
+ session.state = "lagging";
546
+ for (const region of session.replicaRegions) session.lagMs[region] = POST_WRITE_LAG_MS;
547
+ return record4(session, {
548
+ neutralEvent: "geo.primary-write",
549
+ platformEvent: platformEventName(session.platform, "geo.primary-write"),
550
+ state: session.state,
551
+ platform: session.platform,
552
+ metadata: { version: session.version, region: session.primaryRegion, size: input.data.length }
553
+ });
554
+ }
555
+ function markReplicaLagged(session, input) {
556
+ if (!session.replicaRegions.includes(input.region)) {
557
+ throw new Error(`markReplicaLagged: ${input.region} is not a replica region`);
558
+ }
559
+ session.lagMs[input.region] = input.lagMs;
560
+ session.state = "lagging";
561
+ return record4(session, {
562
+ neutralEvent: "geo.replica-lagged",
563
+ platformEvent: platformEventName(session.platform, "geo.replica-lagged"),
564
+ state: session.state,
565
+ platform: session.platform,
566
+ metadata: { region: input.region, lagMs: input.lagMs }
567
+ });
568
+ }
569
+ function syncReplica(session, input) {
570
+ if (!session.replicaRegions.includes(input.region)) {
571
+ throw new Error(`syncReplica: ${input.region} is not a replica region`);
572
+ }
573
+ session.lagMs[input.region] = 0;
574
+ const allSynced = session.replicaRegions.every((r) => session.lagMs[r] === 0);
575
+ if (allSynced) session.state = "in-sync";
576
+ return record4(session, {
577
+ neutralEvent: "geo.replica-synced",
578
+ platformEvent: platformEventName(session.platform, "geo.replica-synced"),
579
+ state: session.state,
580
+ platform: session.platform,
581
+ metadata: { region: input.region, allSynced }
582
+ });
583
+ }
584
+ function resolveConflict(session, input) {
585
+ if (!session.replicaRegions.includes(input.region)) {
586
+ throw new Error(`resolveConflict: ${input.region} is not a replica region`);
587
+ }
588
+ session.version = input.chosenVersion;
589
+ for (const region of session.replicaRegions) session.lagMs[region] = 0;
590
+ session.state = "in-sync";
591
+ return record4(session, {
592
+ neutralEvent: "geo.conflict-resolved",
593
+ platformEvent: platformEventName(session.platform, "geo.conflict-resolved"),
594
+ state: session.state,
595
+ platform: session.platform,
596
+ metadata: { region: input.region, chosenVersion: input.chosenVersion }
597
+ });
598
+ }
599
+
600
+ // src/semantics/cron-trigger.ts
601
+ function scheduleCron(input) {
602
+ const triggerType = input.triggerType ?? "scheduled";
603
+ const maxRetries = input.maxRetries ?? 3;
604
+ const session = {
605
+ id: input.id,
606
+ platform: input.platform,
607
+ triggerType,
608
+ cronSpec: input.cronSpec,
609
+ state: "scheduled",
610
+ startedAt: null,
611
+ retryCount: 0,
612
+ maxRetries,
613
+ history: []
614
+ };
615
+ const step = {
616
+ neutralEvent: "cron.scheduled",
617
+ platformEvent: platformEventName(input.platform, "cron.scheduled"),
618
+ state: "scheduled",
619
+ platform: input.platform,
620
+ metadata: { triggerType, cronSpec: input.cronSpec, maxRetries }
621
+ };
622
+ session.history.push(step);
623
+ return session;
624
+ }
625
+ function startCron(session) {
626
+ if (session.state !== "scheduled") {
627
+ throw new Error(`startCron: session is ${session.state}, expected scheduled`);
628
+ }
629
+ session.state = "running";
630
+ session.startedAt = Date.now();
631
+ const step = {
632
+ neutralEvent: "cron.started",
633
+ platformEvent: platformEventName(session.platform, "cron.started"),
634
+ state: "running",
635
+ platform: session.platform,
636
+ metadata: { startedAt: session.startedAt, triggerType: session.triggerType }
637
+ };
638
+ session.history.push(step);
639
+ return step;
640
+ }
641
+ function completeCron(session, input) {
642
+ if (session.state !== "running") {
643
+ throw new Error(`completeCron: session is ${session.state}, expected running`);
644
+ }
645
+ session.state = "completed";
646
+ const step = {
647
+ neutralEvent: "cron.completed",
648
+ platformEvent: platformEventName(session.platform, "cron.completed"),
649
+ state: "completed",
650
+ platform: session.platform,
651
+ metadata: { durationMs: input.durationMs, triggerType: session.triggerType }
652
+ };
653
+ session.history.push(step);
654
+ return step;
655
+ }
656
+ function failCron(session, input) {
657
+ if (session.state !== "running") {
658
+ throw new Error(`failCron: session is ${session.state}, expected running`);
659
+ }
660
+ session.retryCount += 1;
661
+ const willRetry = session.retryCount < session.maxRetries;
662
+ session.state = willRetry ? "scheduled" : "failed";
663
+ const step = {
664
+ neutralEvent: "cron.failed",
665
+ platformEvent: platformEventName(session.platform, "cron.failed"),
666
+ state: session.state,
667
+ platform: session.platform,
668
+ metadata: {
669
+ reason: input.reason,
670
+ retryCount: session.retryCount,
671
+ willRetry,
672
+ triggerType: session.triggerType
673
+ }
674
+ };
675
+ session.history.push(step);
676
+ return step;
677
+ }
678
+
679
+ // src/semantics/subrequest-limit.ts
680
+ function startSubrequestBudget(input) {
681
+ return {
682
+ platform: input.platform,
683
+ count: 0,
684
+ limit: input.limit ?? 50,
685
+ warningThreshold: input.warningThreshold ?? 40,
686
+ state: "ok",
687
+ history: []
688
+ };
689
+ }
690
+ function startSubrequest(session, input) {
691
+ if (session.state === "limited") {
692
+ throw new Error("startSubrequest: budget is limited, cannot start");
693
+ }
694
+ const step = {
695
+ neutralEvent: "subrequest.started",
696
+ platformEvent: platformEventName(session.platform, "subrequest.started"),
697
+ state: session.state,
698
+ platform: session.platform,
699
+ metadata: { url: input.url, currentCount: session.count }
700
+ };
701
+ session.history.push(step);
702
+ return step;
703
+ }
704
+ function countSubrequest(session) {
705
+ if (session.state === "limited") {
706
+ throw new Error("countSubrequest: budget is limited, cannot count further");
707
+ }
708
+ session.count += 1;
709
+ if (session.count >= session.limit) {
710
+ session.state = "limited";
711
+ const step2 = {
712
+ neutralEvent: "subrequest.limited",
713
+ platformEvent: platformEventName(session.platform, "subrequest.limited"),
714
+ state: "limited",
715
+ platform: session.platform,
716
+ metadata: { count: session.count, limit: session.limit }
717
+ };
718
+ session.history.push(step2);
719
+ return step2;
720
+ }
721
+ if (session.count >= session.warningThreshold) {
722
+ session.state = "approaching-limit";
723
+ }
724
+ const step = {
725
+ neutralEvent: "subrequest.counted",
726
+ platformEvent: platformEventName(session.platform, "subrequest.counted"),
727
+ state: session.state,
728
+ platform: session.platform,
729
+ metadata: {
730
+ count: session.count,
731
+ limit: session.limit,
732
+ remaining: session.limit - session.count
733
+ }
734
+ };
735
+ session.history.push(step);
736
+ return step;
737
+ }
738
+ function completeSubrequest(session, input) {
739
+ const step = {
740
+ neutralEvent: "subrequest.completed",
741
+ platformEvent: platformEventName(session.platform, "subrequest.completed"),
742
+ state: session.state,
743
+ platform: session.platform,
744
+ metadata: {
745
+ url: input.url,
746
+ durationMs: input.durationMs,
747
+ totalCount: session.count
748
+ }
749
+ };
750
+ session.history.push(step);
751
+ return step;
752
+ }
753
+ function remainingBudget(session) {
754
+ return Math.max(0, session.limit - session.count);
755
+ }
756
+
757
+ // src/semantics/cpu-time-limit.ts
758
+ function startCpuBudget(input) {
759
+ return {
760
+ platform: input.platform,
761
+ budgetMs: input.budgetMs ?? 50,
762
+ warningAtMs: input.warningAtMs ?? 40,
763
+ elapsedMs: 0,
764
+ state: "idle",
765
+ history: []
766
+ };
767
+ }
768
+ function startCpu(session) {
769
+ if (session.state !== "idle") {
770
+ throw new Error(`startCpu: session is ${session.state}, expected idle`);
771
+ }
772
+ session.state = "running";
773
+ const step = {
774
+ neutralEvent: "cpu.started",
775
+ platformEvent: platformEventName(session.platform, "cpu.started"),
776
+ state: "running",
777
+ platform: session.platform,
778
+ metadata: { budgetMs: session.budgetMs }
779
+ };
780
+ session.history.push(step);
781
+ return step;
782
+ }
783
+ function tickCpu(session, input) {
784
+ if (session.state === "idle") {
785
+ throw new Error("tickCpu: session is idle, call startCpu first");
786
+ }
787
+ if (session.state === "throttled" || session.state === "completed") {
788
+ throw new Error(`tickCpu: session is ${session.state}, cannot tick`);
789
+ }
790
+ session.elapsedMs += input.deltaMs;
791
+ if (session.elapsedMs >= session.budgetMs) {
792
+ session.state = "throttled";
793
+ const step2 = {
794
+ neutralEvent: "cpu.limited",
795
+ platformEvent: platformEventName(session.platform, "cpu.limited"),
796
+ state: "throttled",
797
+ platform: session.platform,
798
+ metadata: {
799
+ elapsedMs: session.elapsedMs,
800
+ budgetMs: session.budgetMs,
801
+ overshootMs: session.elapsedMs - session.budgetMs
802
+ }
803
+ };
804
+ session.history.push(step2);
805
+ return step2;
806
+ }
807
+ if (session.elapsedMs >= session.warningAtMs) {
808
+ session.state = "warning";
809
+ const step2 = {
810
+ neutralEvent: "cpu.budget-warning",
811
+ platformEvent: platformEventName(session.platform, "cpu.budget-warning"),
812
+ state: "warning",
813
+ platform: session.platform,
814
+ metadata: {
815
+ elapsedMs: session.elapsedMs,
816
+ warningAtMs: session.warningAtMs,
817
+ remaining: session.budgetMs - session.elapsedMs
818
+ }
819
+ };
820
+ session.history.push(step2);
821
+ return step2;
822
+ }
823
+ const step = {
824
+ neutralEvent: "cpu.started",
825
+ platformEvent: platformEventName(session.platform, "cpu.started"),
826
+ state: session.state,
827
+ platform: session.platform,
828
+ metadata: {
829
+ elapsedMs: session.elapsedMs,
830
+ budgetMs: session.budgetMs,
831
+ remaining: session.budgetMs - session.elapsedMs
832
+ }
833
+ };
834
+ session.history.push(step);
835
+ return step;
836
+ }
837
+ function completeCpu(session) {
838
+ if (session.state === "idle") {
839
+ throw new Error("completeCpu: session is idle, cannot complete");
840
+ }
841
+ session.state = "completed";
842
+ const step = {
843
+ neutralEvent: "cpu.completed",
844
+ platformEvent: platformEventName(session.platform, "cpu.completed"),
845
+ state: "completed",
846
+ platform: session.platform,
847
+ metadata: {
848
+ elapsedMs: session.elapsedMs,
849
+ budgetMs: session.budgetMs,
850
+ usedRatio: session.elapsedMs / session.budgetMs
851
+ }
852
+ };
853
+ session.history.push(step);
854
+ return step;
855
+ }
856
+
857
+ // src/semantics/streaming-response.ts
858
+ function openStream(input) {
859
+ const kind = input.kind ?? "chunked";
860
+ const highWaterMark = input.highWaterMark ?? 65536;
861
+ const session = {
862
+ id: input.id,
863
+ platform: input.platform,
864
+ kind,
865
+ state: "open",
866
+ chunksSent: 0,
867
+ bytesSent: 0,
868
+ highWaterMark,
869
+ history: []
870
+ };
871
+ const step = {
872
+ neutralEvent: "stream.opened",
873
+ platformEvent: platformEventName(input.platform, "stream.opened"),
874
+ state: "open",
875
+ platform: input.platform,
876
+ metadata: { id: input.id, kind, highWaterMark }
877
+ };
878
+ session.history.push(step);
879
+ return session;
880
+ }
881
+ function sendChunk(session, input) {
882
+ if (session.state === "closed") {
883
+ throw new Error("sendChunk: stream is closed");
884
+ }
885
+ session.chunksSent += 1;
886
+ session.bytesSent += input.data.length;
887
+ if (session.bytesSent > session.highWaterMark) {
888
+ session.state = "backpressure";
889
+ const step2 = {
890
+ neutralEvent: "stream.backpressure",
891
+ platformEvent: platformEventName(session.platform, "stream.backpressure"),
892
+ state: "backpressure",
893
+ platform: session.platform,
894
+ metadata: {
895
+ bytesSent: session.bytesSent,
896
+ highWaterMark: session.highWaterMark,
897
+ chunksSent: session.chunksSent
898
+ }
899
+ };
900
+ session.history.push(step2);
901
+ return step2;
902
+ }
903
+ const step = {
904
+ neutralEvent: "stream.chunk-sent",
905
+ platformEvent: platformEventName(session.platform, "stream.chunk-sent"),
906
+ state: session.state,
907
+ platform: session.platform,
908
+ metadata: {
909
+ bytesSent: session.bytesSent,
910
+ chunksSent: session.chunksSent,
911
+ size: input.data.length
912
+ }
913
+ };
914
+ session.history.push(step);
915
+ return step;
916
+ }
917
+ function resumeStream(session) {
918
+ if (session.state !== "backpressure") {
919
+ throw new Error(`resumeStream: stream is ${session.state}, expected backpressure`);
920
+ }
921
+ session.state = "open";
922
+ session.bytesSent = Math.max(0, session.bytesSent - session.highWaterMark);
923
+ const step = {
924
+ neutralEvent: "stream.chunk-sent",
925
+ platformEvent: platformEventName(session.platform, "stream.chunk-sent"),
926
+ state: "open",
927
+ platform: session.platform,
928
+ metadata: {
929
+ resumed: true,
930
+ chunksSent: session.chunksSent,
931
+ bytesSent: session.bytesSent
932
+ }
933
+ };
934
+ session.history.push(step);
935
+ return step;
936
+ }
937
+ function closeStream(session, input) {
938
+ if (session.state === "closed") {
939
+ throw new Error("closeStream: stream already closed");
940
+ }
941
+ session.state = "closed";
942
+ const step = {
943
+ neutralEvent: "stream.closed",
944
+ platformEvent: platformEventName(session.platform, "stream.closed"),
945
+ state: "closed",
946
+ platform: session.platform,
947
+ metadata: {
948
+ reason: input.reason,
949
+ totalChunks: session.chunksSent,
950
+ totalBytes: session.bytesSent
951
+ }
952
+ };
953
+ session.history.push(step);
954
+ return step;
955
+ }
129
956
  // Annotate the CommonJS export names for ESM import in node:
130
957
  0 && (module.exports = {
958
+ AXIS_TO_EVENTS,
959
+ acceptWebSocket,
960
+ closeStream,
961
+ closeWebSocket,
962
+ collectFidelityCoverage,
963
+ completeCpu,
964
+ completeCron,
965
+ completeSubrequest,
966
+ countSubrequest,
967
+ createDurableObject,
968
+ createEdgeKvSession,
969
+ createGeoReplicatedSession,
131
970
  createKvNamespace,
132
- invokeEdgeHandler
971
+ failCron,
972
+ fireAlarm,
973
+ geoPrimaryWrite,
974
+ invokeEdgeHandler,
975
+ kvRangeQuery,
976
+ kvRead,
977
+ kvWrite,
978
+ markReplicaLagged,
979
+ openStream,
980
+ platformEventName,
981
+ remainingBudget,
982
+ requestDurableObject,
983
+ requestWebSocketUpgrade,
984
+ resolveConflict,
985
+ resumeStream,
986
+ scheduleCron,
987
+ sendChunk,
988
+ sendMessage,
989
+ startCpu,
990
+ startCpuBudget,
991
+ startCron,
992
+ startSubrequest,
993
+ startSubrequestBudget,
994
+ syncReplica,
995
+ tickCpu,
996
+ writeStorage
133
997
  });
134
998
  //# sourceMappingURL=index.cjs.map