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