@deslop/scope 0.1.1237 → 0.1.1239

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/server.js CHANGED
@@ -4007,7 +4007,7 @@ const min$1 = (O) => dual(2, (self, that) => self === that || O(self, that) < 1
4007
4007
  * @category comparisons
4008
4008
  * @since 2.0.0
4009
4009
  */
4010
- const max$2 = (O) => dual(2, (self, that) => self === that || O(self, that) > -1 ? self : that);
4010
+ const max$3 = (O) => dual(2, (self, that) => self === that || O(self, that) > -1 ? self : that);
4011
4011
  // ../../node_modules/.pnpm/effect@4.1.2/node_modules/effect/dist/Option.js
4012
4012
  /**
4013
4013
  * Creates an `Option` representing the absence of a value.
@@ -4525,6 +4525,63 @@ const map$11 = /*#__PURE__*/ dual(2, (self, f) => isNone(self) ? none() : some$1
4525
4525
  */
4526
4526
  const flatMap$7 = /*#__PURE__*/ dual(2, (self, f) => isNone(self) ? none() : f(self.value));
4527
4527
  /**
4528
+ * Combines a structure of `Option`s (tuple, struct, or iterable) into a single
4529
+ * `Option` containing the unwrapped structure.
4530
+ *
4531
+ * **When to use**
4532
+ *
4533
+ * Use when you need to combine multiple `Option` values into one while
4534
+ * preserving the input shape, with any `None` making the result `None`.
4535
+ *
4536
+ * **Details**
4537
+ *
4538
+ * - Tuple input → `Option` of a tuple with the same length
4539
+ * - Struct input → `Option` of a struct with the same keys
4540
+ * - Iterable input → `Option` of an `Array`
4541
+ * - Any `None` in the input → entire result is `None`
4542
+ *
4543
+ * **Example** (Combining a tuple and a struct)
4544
+ *
4545
+ * ```ts import.meta.vitest
4546
+ * import { Option } from "effect"
4547
+ *
4548
+ * const maybeName: Option.Option<string> = Option.some("John")
4549
+ * const maybeAge: Option.Option<number> = Option.some(25)
4550
+ *
4551
+ * // ┌─── Option<[string, number]>
4552
+ * // ▼
4553
+ * const tuple = Option.all([maybeName, maybeAge]) // => Option.some(["John", 25])
4554
+ *
4555
+ * // ┌─── Option<{ name: string; age: number; }>
4556
+ * // ▼
4557
+ * const struct = Option.all({ name: maybeName, age: maybeAge }) // => Option.some({ name: "John", age: 25 })
4558
+ * ```
4559
+ *
4560
+ * @see {@link product} for combining exactly two
4561
+ * @see {@link productMany} for a homogeneous collection
4562
+ *
4563
+ * @stability stable
4564
+ * @category combining
4565
+ * @since 2.0.0
4566
+ */
4567
+ const all$4 = (input) => {
4568
+ if (Symbol.iterator in input) {
4569
+ const out = [];
4570
+ for (const o of input) {
4571
+ if (isNone(o)) return none();
4572
+ out.push(o.value);
4573
+ }
4574
+ return some$1(out);
4575
+ }
4576
+ const out = {};
4577
+ for (const key of Object.keys(input)) {
4578
+ const o = input[key];
4579
+ if (isNone(o)) return none();
4580
+ assignProperty(out, key, o.value);
4581
+ }
4582
+ return some$1(out);
4583
+ };
4584
+ /**
4528
4585
  * Converts an `Option` into an `Array`.
4529
4586
  *
4530
4587
  * **When to use**
@@ -6169,7 +6226,7 @@ const values$2 = (self) => collect$1(self, (_, a) => a);
6169
6226
  * @category mutations
6170
6227
  * @since 2.0.0
6171
6228
  */
6172
- const set$6 = /*#__PURE__*/ dual(3, (self, key, value) => {
6229
+ const set$7 = /*#__PURE__*/ dual(3, (self, key, value) => {
6173
6230
  return {
6174
6231
  ...self,
6175
6232
  [key]: value
@@ -6208,6 +6265,31 @@ const isSubrecordBy = (equivalence) => dual(2, (self, that) => {
6208
6265
  return true;
6209
6266
  });
6210
6267
  /**
6268
+ * Merges two records, preserving entries that exist in either of the records.
6269
+ * For keys that exist in both records, the provided combine function is used to merge the values.
6270
+ *
6271
+ * **Example** (Merging records with union)
6272
+ *
6273
+ * ```ts import.meta.vitest
6274
+ * import { Record } from "effect"
6275
+ *
6276
+ * Record.union({ a: 1, b: 2 }, { b: 3, c: 4 }, (a, b) => a + b) // => { a: 1, b: 5, c: 4 }
6277
+ * ```
6278
+ *
6279
+ * @stability stable
6280
+ * @category combining
6281
+ * @since 2.0.0
6282
+ */
6283
+ const union$2 = /*#__PURE__*/ dual(3, (self, that, combine) => {
6284
+ if (isEmptyRecord(self)) return { ...that };
6285
+ if (isEmptyRecord(that)) return { ...self };
6286
+ const out = empty$12();
6287
+ for (const key of keys$1(self)) if (has$4(that, key)) assignProperty(out, key, combine(self[key], that[key]));
6288
+ else assignProperty(out, key, self[key]);
6289
+ for (const key of keys$1(that)) if (!has$4(out, key)) assignProperty(out, key, that[key]);
6290
+ return out;
6291
+ });
6292
+ /**
6211
6293
  * Create an `Equivalence` for records using the provided `Equivalence` for values.
6212
6294
  * Two records are considered equivalent if they have the same keys and their corresponding values are equivalent.
6213
6295
  *
@@ -7259,6 +7341,26 @@ const some = /*#__PURE__*/ dual(2, (self, predicate) => self.some(predicate));
7259
7341
  */
7260
7342
  const min = /*#__PURE__*/ dual(2, (self, O) => self.reduce(min$1(O)));
7261
7343
  /**
7344
+ * Returns the maximum element of a non-empty array according to the given
7345
+ * `Order`.
7346
+ *
7347
+ * **Example** (Finding the maximum)
7348
+ *
7349
+ * ```ts import.meta.vitest
7350
+ * import { Array, Order } from "effect"
7351
+ *
7352
+ * Array.max([3, 1, 2], Order.Number) // => 3
7353
+ * ```
7354
+ *
7355
+ * @see {@link min} — find the minimum
7356
+ * @see {@link sort} — sort the entire array
7357
+ *
7358
+ * @stability stable
7359
+ * @category getters
7360
+ * @since 2.0.0
7361
+ */
7362
+ const max$2 = /*#__PURE__*/ dual(2, (self, O) => self.reduce(max$3(O)));
7363
+ /**
7262
7364
  * Builds an array by repeatedly applying a function to a seed value. The
7263
7365
  * function returns `Option.some([element, nextSeed])` to continue, or
7264
7366
  * `Option.none()` to stop.
@@ -7505,15 +7607,15 @@ const DURATION_REGEXP = /^(-?\d+(?:\.\d+)?)\s+(nanos?|micros?|millis?|seconds?|m
7505
7607
  const fromInputUnsafe$1 = (input) => {
7506
7608
  switch (typeof input) {
7507
7609
  case "number": return millis(input);
7508
- case "bigint": return nanos(input);
7610
+ case "bigint": return nanos$1(input);
7509
7611
  case "string": {
7510
7612
  if (input === "Infinity") return infinity;
7511
7613
  if (input === "-Infinity") return negativeInfinity;
7512
7614
  const match = DURATION_REGEXP.exec(input);
7513
7615
  if (!match) break;
7514
7616
  const [_, valueStr, unit] = match;
7515
- if (unit === "nano" || unit === "nanos") return nanos(parseNanos(valueStr, bigint1$2));
7516
- if (unit === "micro" || unit === "micros") return nanos(parseNanos(valueStr, bigint1e3));
7617
+ if (unit === "nano" || unit === "nanos") return nanos$1(parseNanos(valueStr, bigint1$2));
7618
+ if (unit === "micro" || unit === "micros") return nanos$1(parseNanos(valueStr, bigint1e3));
7517
7619
  switch (unit) {
7518
7620
  case "milli":
7519
7621
  case "millis": return fromMillisString(valueStr, 1);
@@ -7841,7 +7943,7 @@ const negativeInfinity = /*#__PURE__*/ make$80(-Infinity);
7841
7943
  * @category constructors
7842
7944
  * @since 2.0.0
7843
7945
  */
7844
- const nanos = (nanos) => make$80(nanos);
7946
+ const nanos$1 = (nanos) => make$80(nanos);
7845
7947
  /**
7846
7948
  * Creates a Duration from milliseconds.
7847
7949
  *
@@ -8118,7 +8220,7 @@ const Equivalence$3 = (self, that) => matchPair(self, that, {
8118
8220
  * @category ordering
8119
8221
  * @since 2.0.0
8120
8222
  */
8121
- const max$1 = /*#__PURE__*/ max$2(Order$4);
8223
+ const max$1 = /*#__PURE__*/ max$3(Order$4);
8122
8224
  /**
8123
8225
  * Adds two Durations together.
8124
8226
  *
@@ -8842,6 +8944,38 @@ var EncodingError = class extends (/*#__PURE__*/ TaggedError$1("EncodingError"))
8842
8944
  */
8843
8945
  [EncodingErrorTypeId] = EncodingErrorTypeId;
8844
8946
  };
8947
+ // ../../node_modules/.pnpm/effect@4.1.2/node_modules/effect/dist/encoding/Hex.js
8948
+ /**
8949
+ * Hexadecimal encoding, decoding, and random value helpers.
8950
+ *
8951
+ * @stability stable
8952
+ * @since 4.0.0
8953
+ */
8954
+ /**
8955
+ * Encodes the given value into a hex `string`.
8956
+ *
8957
+ * **When to use**
8958
+ *
8959
+ * Use to encode text or bytes as lowercase hexadecimal text.
8960
+ *
8961
+ * **Example** (Encoding hex strings and bytes)
8962
+ *
8963
+ * ```ts import.meta.vitest
8964
+ * import { Hex } from "effect/encoding"
8965
+ *
8966
+ * // Encode a string to hex
8967
+ * Hex.encode("hello") // => "68656c6c6f"
8968
+ *
8969
+ * // Encode binary data to hex
8970
+ * const bytes = new Uint8Array([72, 101, 108, 108, 111])
8971
+ * Hex.encode(bytes) // => "48656c6c6f"
8972
+ * ```
8973
+ *
8974
+ * @stability stable
8975
+ * @category encoding
8976
+ * @since 4.0.0
8977
+ */
8978
+ const encode$1 = (input) => typeof input === "string" ? hexEncodeUint8Array(encoder$5.encode(input)) : hexEncodeUint8Array(input);
8845
8979
  /**
8846
8980
  * Generates a random lowercase hexadecimal string, optimized for lengths that
8847
8981
  * are multiples of 8.
@@ -8891,6 +9025,71 @@ const random32 = () => {
8891
9025
  const d = randomWord();
8892
9026
  return String.fromCharCode(hexCharCodes[a >>> 28], hexCharCodes[a >>> 24 & 15], hexCharCodes[a >>> 20 & 15], hexCharCodes[a >>> 16 & 15], hexCharCodes[a >>> 12 & 15], hexCharCodes[a >>> 8 & 15], hexCharCodes[a >>> 4 & 15], hexCharCodes[a & 15], hexCharCodes[b >>> 28], hexCharCodes[b >>> 24 & 15], hexCharCodes[b >>> 20 & 15], hexCharCodes[b >>> 16 & 15], hexCharCodes[b >>> 12 & 15], hexCharCodes[b >>> 8 & 15], hexCharCodes[b >>> 4 & 15], hexCharCodes[b & 15], hexCharCodes[c >>> 28], hexCharCodes[c >>> 24 & 15], hexCharCodes[c >>> 20 & 15], hexCharCodes[c >>> 16 & 15], hexCharCodes[c >>> 12 & 15], hexCharCodes[c >>> 8 & 15], hexCharCodes[c >>> 4 & 15], hexCharCodes[c & 15], hexCharCodes[d >>> 28], hexCharCodes[d >>> 24 & 15], hexCharCodes[d >>> 20 & 15], hexCharCodes[d >>> 16 & 15], hexCharCodes[d >>> 12 & 15], hexCharCodes[d >>> 8 & 15], hexCharCodes[d >>> 4 & 15], hexCharCodes[d & 15]);
8893
9027
  };
9028
+ /**
9029
+ * Decodes a hexadecimal string into bytes safely.
9030
+ *
9031
+ * **When to use**
9032
+ *
9033
+ * Use to decode hexadecimal text into bytes without throwing on invalid input.
9034
+ *
9035
+ * **Details**
9036
+ *
9037
+ * Returns `Result.succeed` with a `Uint8Array` when decoding succeeds, or
9038
+ * `Result.fail` with an `EncodingError` when the input has an odd length or
9039
+ * contains invalid hex characters.
9040
+ *
9041
+ * **Example** (Decoding hex bytes)
9042
+ *
9043
+ * ```ts import.meta.vitest
9044
+ * import { Result } from "effect"
9045
+ * import { Hex } from "effect/encoding"
9046
+ *
9047
+ * Hex.decode("48656c6c6f") // => Result.succeed(new Uint8Array([72, 101, 108, 108, 111]))
9048
+ * ```
9049
+ *
9050
+ * @stability stable
9051
+ * @category decoding
9052
+ * @since 4.0.0
9053
+ */
9054
+ const decode$2 = (str) => {
9055
+ const bytes = new TextEncoder().encode(str);
9056
+ if (bytes.length % 2 !== 0) return fail$11(new EncodingError({
9057
+ module: "Hex",
9058
+ kind: "Decode",
9059
+ input: str,
9060
+ message: `Length must be a multiple of 2, but is ${bytes.length}`
9061
+ }));
9062
+ try {
9063
+ const length = bytes.length / 2;
9064
+ const result = new Uint8Array(length);
9065
+ for (let i = 0; i < length; i++) {
9066
+ const a = fromHexChar(bytes[i * 2]);
9067
+ const b = fromHexChar(bytes[i * 2 + 1]);
9068
+ result[i] = a << 4 | b;
9069
+ }
9070
+ return succeed$10(result);
9071
+ } catch (e) {
9072
+ return fail$11(new EncodingError({
9073
+ module: "Hex",
9074
+ kind: "Decode",
9075
+ input: str,
9076
+ message: e instanceof Error ? e.message : "Invalid input"
9077
+ }));
9078
+ }
9079
+ };
9080
+ const encoder$5 = /*#__PURE__*/ new TextEncoder();
9081
+ const byteToHex = /*#__PURE__*/ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
9082
+ const hexEncodeUint8Array = (bytes) => {
9083
+ let result = "";
9084
+ for (let i = 0; i < bytes.length; i++) result += byteToHex[bytes[i]];
9085
+ return result;
9086
+ };
9087
+ const fromHexChar = (byte) => {
9088
+ if (48 <= byte && byte <= 57) return byte - 48;
9089
+ if (97 <= byte && byte <= 102) return byte - 97 + 10;
9090
+ if (65 <= byte && byte <= 70) return byte - 65 + 10;
9091
+ throw new TypeError("Invalid input");
9092
+ };
8894
9093
  // ../../node_modules/.pnpm/effect@4.1.2/node_modules/effect/dist/Tracer.js
8895
9094
  /**
8896
9095
  * Defines the low-level tracing model used by Effect.
@@ -15375,7 +15574,7 @@ const increment$1 = (n) => n + 1;
15375
15574
  * @category math
15376
15575
  * @since 2.0.0
15377
15576
  */
15378
- const max = /*#__PURE__*/ max$2(Number$6);
15577
+ const max = /*#__PURE__*/ max$3(Number$6);
15379
15578
  /**
15380
15579
  * Parses a `number` from a `string` safely using the `Number()` function.
15381
15580
  * The following special string values are supported: "NaN", "Infinity", "-Infinity".
@@ -15531,6 +15730,23 @@ const capitalize = (self) => {
15531
15730
  */
15532
15731
  const replace = (searchValue, replaceValue) => (self) => self.replace(searchValue, replaceValue);
15533
15732
  /**
15733
+ * Extracts a section of a string and returns it as a new string.
15734
+ *
15735
+ * **Example** (Slicing strings)
15736
+ *
15737
+ * ```ts import.meta.vitest
15738
+ * import { pipe, String } from "effect"
15739
+ *
15740
+ * pipe("abcd", String.slice(1, 3)) // => "bc"
15741
+ * pipe("hello world", String.slice(0, 5)) // => "hello"
15742
+ * ```
15743
+ *
15744
+ * @stability stable
15745
+ * @category transforming
15746
+ * @since 2.0.0
15747
+ */
15748
+ const slice = (start, end) => (self) => self.slice(start, end);
15749
+ /**
15534
15750
  * Checks whether a `string` is non-empty.
15535
15751
  *
15536
15752
  * **Example** (Checking for non-empty strings)
@@ -15643,6 +15859,23 @@ const endsWith = (searchString, position) => (self) => self.endsWith(searchStrin
15643
15859
  */
15644
15860
  const match$3 = (regExp) => (self) => fromNullOr(self.match(regExp));
15645
15861
  /**
15862
+ * Pads the string from the start with a given fill string to a specified length.
15863
+ *
15864
+ * **Example** (Padding strings at the start)
15865
+ *
15866
+ * ```ts import.meta.vitest
15867
+ * import { pipe, String } from "effect"
15868
+ *
15869
+ * pipe("a", String.padStart(5)) // => " a"
15870
+ * pipe("a", String.padStart(5, "_")) // => "____a"
15871
+ * ```
15872
+ *
15873
+ * @stability stable
15874
+ * @category transforming
15875
+ * @since 2.0.0
15876
+ */
15877
+ const padStart = (maxLength, fillString) => (self) => self.padStart(maxLength, fillString);
15878
+ /**
15646
15879
  * Replaces all occurrences of a substring or pattern in a string.
15647
15880
  *
15648
15881
  * **Example** (Replacing all matches)
@@ -16414,7 +16647,7 @@ const getFromBucket = (self, bucket, key) => {
16414
16647
  * @category mutations
16415
16648
  * @since 2.0.0
16416
16649
  */
16417
- const set$5 = /*#__PURE__*/ dual(3, (self, key, value) => {
16650
+ const set$6 = /*#__PURE__*/ dual(3, (self, key, value) => {
16418
16651
  if (self.backing.has(key) || isSimpleKey(key)) {
16419
16652
  self.backing.set(key, value);
16420
16653
  return self;
@@ -23224,7 +23457,7 @@ const increment = (bytes) => {
23224
23457
  return false;
23225
23458
  };
23226
23459
  // ../../node_modules/.pnpm/effect@4.1.2/node_modules/effect/dist/internal/uuid.js
23227
- const hex = /*#__PURE__*/ Array.from({ length: 256 }, (_, byte) => byte.toString(16).padStart(2, "0"));
23460
+ const hex$1 = /*#__PURE__*/ Array.from({ length: 256 }, (_, byte) => byte.toString(16).padStart(2, "0"));
23228
23461
  /** @internal */
23229
23462
  const stringify = (bytes) => {
23230
23463
  if (bytes.length < 16) return [
@@ -23233,8 +23466,8 @@ const stringify = (bytes) => {
23233
23466
  bytes.subarray(6, 8),
23234
23467
  bytes.subarray(8, 10),
23235
23468
  bytes.subarray(10, 16)
23236
- ].map((segment) => Array.from(segment, (byte) => hex[byte]).join("")).join("-");
23237
- return hex[bytes[0]] + hex[bytes[1]] + hex[bytes[2]] + hex[bytes[3]] + "-" + hex[bytes[4]] + hex[bytes[5]] + "-" + hex[bytes[6]] + hex[bytes[7]] + "-" + hex[bytes[8]] + hex[bytes[9]] + "-" + hex[bytes[10]] + hex[bytes[11]] + hex[bytes[12]] + hex[bytes[13]] + hex[bytes[14]] + hex[bytes[15]];
23469
+ ].map((segment) => Array.from(segment, (byte) => hex$1[byte]).join("")).join("-");
23470
+ return hex$1[bytes[0]] + hex$1[bytes[1]] + hex$1[bytes[2]] + hex$1[bytes[3]] + "-" + hex$1[bytes[4]] + hex$1[bytes[5]] + "-" + hex$1[bytes[6]] + hex$1[bytes[7]] + "-" + hex$1[bytes[8]] + hex$1[bytes[9]] + "-" + hex$1[bytes[10]] + hex$1[bytes[11]] + hex$1[bytes[12]] + hex$1[bytes[13]] + hex$1[bytes[14]] + hex$1[bytes[15]];
23238
23471
  };
23239
23472
  /** @internal */
23240
23473
  const v4Bytes = (bytes) => {
@@ -27403,7 +27636,7 @@ const checkSaltLength = (algorithm, cryptoKey) => {
27403
27636
  * @category services
27404
27637
  * @since 4.0.0
27405
27638
  */
27406
- var Signature = class extends (/*#__PURE__*/ Service$2()("effect/crypto/Signature")) {};
27639
+ var Signature$1 = class extends (/*#__PURE__*/ Service$2()("effect/crypto/Signature")) {};
27407
27640
  /**
27408
27641
  * Layer that provides `Signature` on the `WebCrypto` reference.
27409
27642
  *
@@ -27417,11 +27650,11 @@ var Signature = class extends (/*#__PURE__*/ Service$2()("effect/crypto/Signatur
27417
27650
  * @category layers
27418
27651
  * @since 4.0.0
27419
27652
  */
27420
- const layerWebCrypto$1 = /*#__PURE__*/ effect(Signature, /*#__PURE__*/ gen(function* () {
27653
+ const layerWebCrypto$1 = /*#__PURE__*/ effect(Signature$1, /*#__PURE__*/ gen(function* () {
27421
27654
  const random = yield* SecureRandom;
27422
27655
  const crypto = yield* WebCrypto;
27423
27656
  const caches = makeCaches(family);
27424
- return Signature.of({
27657
+ return Signature$1.of({
27425
27658
  generateKeyPair: (algorithm) => generateKeyPair(family, crypto, random, algorithm, generateParams(algorithm)),
27426
27659
  sign: (privateKey, data) => run$6("Signature", "sign", privateKey.algorithm.name, crypto, async (subtle) => {
27427
27660
  const cryptoKey = await caches.privateKey(subtle, privateKey);
@@ -28213,7 +28446,7 @@ const setHash$1 = (self, key, hash, value) => {
28213
28446
  return new HashMapImpl(false, impl._edit, newRoot, impl._size + (added.value ? 1 : 0));
28214
28447
  };
28215
28448
  /** @internal */
28216
- const set$4 = /*#__PURE__*/ dual(3, (self, key, value) => {
28449
+ const set$5 = /*#__PURE__*/ dual(3, (self, key, value) => {
28217
28450
  return setHash$1(self, key, hash(key), value);
28218
28451
  });
28219
28452
  /** @internal */
@@ -28311,7 +28544,7 @@ const fromIterable$4 = fromIterable$5;
28311
28544
  * @category transforming
28312
28545
  * @since 2.0.0
28313
28546
  */
28314
- const set$3 = set$4;
28547
+ const set$4 = set$5;
28315
28548
  /**
28316
28549
  * Returns an `IterableIterator` of the values within the `HashMap`.
28317
28550
  *
@@ -28397,7 +28630,7 @@ const make$67 = (...values) => fromIterable$3(values);
28397
28630
  /** @internal */
28398
28631
  const fromIterable$3 = (values) => {
28399
28632
  let map = empty$8();
28400
- for (const value of values) map = set$4(map, value, true);
28633
+ for (const value of values) map = set$5(map, value, true);
28401
28634
  return makeImpl(map);
28402
28635
  };
28403
28636
  /** @internal */
@@ -28405,7 +28638,7 @@ const has$1 = (self, value) => has$2(keyMap(self), value);
28405
28638
  /** @internal */
28406
28639
  const add$2 = (self, value) => {
28407
28640
  const map = keyMap(self);
28408
- return has$2(map, value) ? self : makeImpl(set$4(map, value, true));
28641
+ return has$2(map, value) ? self : makeImpl(set$5(map, value, true));
28409
28642
  };
28410
28643
  /** @internal */
28411
28644
  const size = (self) => size$1(keyMap(self));
@@ -29165,7 +29398,7 @@ const get$6 = /*#__PURE__*/ dual(2, (self, key) => fromUndefinedOr(self[key.toLo
29165
29398
  * @category combinators
29166
29399
  * @since 4.0.0
29167
29400
  */
29168
- const set$2 = /*#__PURE__*/ dual(3, (self, key, value) => {
29401
+ const set$3 = /*#__PURE__*/ dual(3, (self, key, value) => {
29169
29402
  const out = make$64(self);
29170
29403
  out[key.toLowerCase()] = value;
29171
29404
  return out;
@@ -29432,7 +29665,7 @@ const parseRetryAfter$1 = (input) => {
29432
29665
  const trimmed = input.trim();
29433
29666
  if (wholeSeconds.test(trimmed)) {
29434
29667
  const seconds$1 = Number(trimmed);
29435
- const duration = Number.isSafeInteger(seconds$1 * 1e3) ? seconds(seconds$1) : nanos(BigInt(trimmed) * nanosPerSecond);
29668
+ const duration = Number.isSafeInteger(seconds$1 * 1e3) ? seconds(seconds$1) : nanos$1(BigInt(trimmed) * nanosPerSecond);
29436
29669
  return succeed$10({
29437
29670
  _tag: "Duration",
29438
29671
  duration
@@ -30994,6 +31227,33 @@ function encodeBase64() {
30994
31227
  return transform$2(encode);
30995
31228
  }
30996
31229
  /**
31230
+ * Encodes a `Uint8Array` or string to a hexadecimal string.
31231
+ *
31232
+ * **Details**
31233
+ *
31234
+ * The getter is pure and never fails.
31235
+ *
31236
+ * **Example** (Encoding to hex)
31237
+ *
31238
+ * ```ts import.meta.vitest
31239
+ * import { Effect, Option, SchemaGetter } from "effect"
31240
+ *
31241
+ * const encode = SchemaGetter.encodeHex<Uint8Array>()
31242
+ * const result = Effect.runSync(SchemaGetter.run(encode, Option.some(new Uint8Array([1, 2, 3])), {}))
31243
+ * result // => Option.some("010203")
31244
+ * ```
31245
+ *
31246
+ * @see {@link decodeHex} for the inverse operation to `Uint8Array`
31247
+ * @see {@link decodeHexString} for the inverse operation to `string`
31248
+ *
31249
+ * @stability stable
31250
+ * @category encoding
31251
+ * @since 4.0.0
31252
+ */
31253
+ function encodeHex() {
31254
+ return transform$2(encode$1);
31255
+ }
31256
+ /**
30997
31257
  * Decodes a Base64 string to a `Uint8Array`.
30998
31258
  *
30999
31259
  * **Details**
@@ -31021,6 +31281,36 @@ function decodeBase64() {
31021
31281
  return transformEffect$1((input, options) => mapErrorEager(fromResult(decode$1(input)), () => new InvalidValue$1({ expected: "a valid Base64 string" }, input, options)));
31022
31282
  }
31023
31283
  /**
31284
+ * Decodes a hexadecimal string to a `Uint8Array`.
31285
+ *
31286
+ * **Details**
31287
+ *
31288
+ * - Fails with `SchemaIssue.InvalidValue` if the input is not valid hex.
31289
+ *
31290
+ * **Example** (Decoding hex to bytes)
31291
+ *
31292
+ * ```ts import.meta.vitest
31293
+ * import { Effect, Option, SchemaGetter } from "effect"
31294
+ *
31295
+ * const decode = SchemaGetter.decodeHex<string>()
31296
+ * const result = await Effect.runPromise(SchemaGetter.run(decode, Option.some("010203"), {}))
31297
+ * Option.map(result, Array.from) // => Option.some([1, 2, 3])
31298
+ * ```
31299
+ *
31300
+ * @see {@link decodeHexString} to decode to `string` instead
31301
+ * @see {@link encodeHex} for the inverse operation
31302
+ *
31303
+ * @stability stable
31304
+ * @category decoding
31305
+ * @since 4.0.0
31306
+ */
31307
+ function decodeHex() {
31308
+ return transformEffect$1((input, options) => match$7(decode$2(input), {
31309
+ onFailure: () => fail$6(new InvalidValue$1({ expected: "a valid hexadecimal string" }, input, options)),
31310
+ onSuccess: succeed$5
31311
+ }));
31312
+ }
31313
+ /**
31024
31314
  * Encodes a present string using `encodeURIComponent`.
31025
31315
  *
31026
31316
  * **Details**
@@ -34205,6 +34495,12 @@ function decodeUnknownEffect$1(schema, options) {
34205
34495
  const parser = run$5(schema.ast);
34206
34496
  return options === void 0 ? parser : (input, overrideOptions) => parser(input, mergeParseOptions(options, overrideOptions));
34207
34497
  }
34498
+ /** @internal */
34499
+ function decodeUnknownOption$1(schema, options) {
34500
+ return asOption(decodeUnknownEffect$1(schema, options));
34501
+ }
34502
+ /** @internal */
34503
+ const decodeOption$1 = decodeUnknownOption$1;
34208
34504
  /**
34209
34505
  * Creates a decoder for `unknown` input that reports failure safely as a
34210
34506
  * `Result`.
@@ -34290,6 +34586,16 @@ function runWithCompiler(compiler, ast) {
34290
34586
  function asExit(parser) {
34291
34587
  return (input, options) => runSyncExit(parser(input, options));
34292
34588
  }
34589
+ /** @internal */
34590
+ function asOption(parser) {
34591
+ const parserExit = asExit(parser);
34592
+ return (input, options) => {
34593
+ const exit = parserExit(input, options);
34594
+ if (isSuccess(exit)) return some$1(exit.value);
34595
+ getSchemaIssueOrThrow(exit.cause, "Option adapter can only return none for schema issues");
34596
+ return none();
34597
+ };
34598
+ }
34293
34599
  function asResult(parser) {
34294
34600
  const parserExit = asExit(parser);
34295
34601
  return (input, options) => {
@@ -36748,6 +37054,61 @@ function decodeUnknownEffect(schema, options) {
36748
37054
  */
36749
37055
  const decodeEffect = decodeUnknownEffect;
36750
37056
  /**
37057
+ * Decodes an `unknown` input against a schema, returning an `Option` that is
37058
+ * `Some` with the decoded value on success or `None` for schema mismatches.
37059
+ *
37060
+ * **When to use**
37061
+ *
37062
+ * Use when you do not know the input type statically and only need to know
37063
+ * whether decoding succeeded.
37064
+ *
37065
+ * **Details**
37066
+ *
37067
+ * Prefer this over {@link decodeUnknownExit} or {@link decodeUnknownEffect}
37068
+ * when you don't need error details. For input already typed as the schema's
37069
+ * `Encoded` type use {@link decodeOption}.
37070
+ * Options may be provided either when creating the decoder or when applying it;
37071
+ * application options override creation options.
37072
+ *
37073
+ * **Gotchas**
37074
+ *
37075
+ * Only causes made entirely of schema issues are converted to `None`. Causes
37076
+ * that contain defects, interruptions, or other non-schema reasons throw
37077
+ * instead.
37078
+ *
37079
+ * @stability stable
37080
+ * @category decoding
37081
+ * @since 3.10.0
37082
+ */
37083
+ const decodeUnknownOption = decodeUnknownOption$1;
37084
+ /**
37085
+ * Decodes a typed input (the schema's `Encoded` type) against a schema,
37086
+ * returning an `Option` that is `Some` with the decoded value on success or
37087
+ * `None` for schema mismatches.
37088
+ *
37089
+ * **When to use**
37090
+ *
37091
+ * Use when you already have input typed as the schema's `Encoded` type and
37092
+ * only need to know whether decoding succeeded.
37093
+ *
37094
+ * **Details**
37095
+ *
37096
+ * For `unknown` input use {@link decodeUnknownOption}.
37097
+ * Options may be provided either when creating the decoder or when applying it;
37098
+ * application options override creation options.
37099
+ *
37100
+ * **Gotchas**
37101
+ *
37102
+ * Only causes made entirely of schema issues are converted to `None`. Causes
37103
+ * that contain defects, interruptions, or other non-schema reasons throw
37104
+ * instead.
37105
+ *
37106
+ * @stability stable
37107
+ * @category decoding
37108
+ * @since 3.10.0
37109
+ */
37110
+ const decodeOption = decodeOption$1;
37111
+ /**
36751
37112
  * Decodes an `unknown` input against a schema, returning a `Result` that
36752
37113
  * succeeds with the decoded value or fails with a {@link SchemaError} for schema
36753
37114
  * mismatches.
@@ -38547,6 +38908,26 @@ const Uint8Array$2 = /*#__PURE__*/ instanceOf(globalThis.Uint8Array, {
38547
38908
  */
38548
38909
  const Uint8ArrayFromBase64 = /*#__PURE__*/ Base64String.pipe(/*#__PURE__*/ decodeTo(Uint8Array$2, uint8ArrayFromBase64String));
38549
38910
  /**
38911
+ * Schema that decodes a hex encoded string into a
38912
+ * `Uint8Array`.
38913
+ *
38914
+ * **Details**
38915
+ *
38916
+ * Decoding:
38917
+ * - A **valid** hex encoded string is decoded as a `Uint8Array`.
38918
+ *
38919
+ * Encoding:
38920
+ * - A `Uint8Array` is encoded as a hex encoded string.
38921
+ *
38922
+ * @stability stable
38923
+ * @category schemas
38924
+ * @since 3.10.0
38925
+ */
38926
+ const Uint8ArrayFromHex = /*#__PURE__*/ String$6.annotate({ expected: "a hex encoded string that will be decoded as a Uint8Array" }).pipe(/*#__PURE__*/ decodeTo(Uint8Array$2, {
38927
+ decode: /*#__PURE__*/ decodeHex(),
38928
+ encode: /*#__PURE__*/ encodeHex()
38929
+ }));
38930
+ /**
38550
38931
  * Creates a schema for `Cause.Reason` values using separate schemas for typed
38551
38932
  * failures and unexpected defects.
38552
38933
  *
@@ -38806,7 +39187,7 @@ const Duration = /*#__PURE__*/ declare(isDuration, {
38806
39187
  switch (e._tag) {
38807
39188
  case "Infinity": return infinity;
38808
39189
  case "NegativeInfinity": return negativeInfinity;
38809
- case "Nanos": return nanos(e.value);
39190
+ case "Nanos": return nanos$1(e.value);
38810
39191
  case "Millis": return millis(e.value);
38811
39192
  }
38812
39193
  },
@@ -38931,7 +39312,7 @@ function Exit(value, error, defect) {
38931
39312
  * @category schemas
38932
39313
  * @since 3.10.0
38933
39314
  */
38934
- function Redacted(value, options) {
39315
+ function Redacted$1(value, options) {
38935
39316
  const label = typeof options?.label === "string" ? options.label : void 0;
38936
39317
  const disallowJsonEncode = options?.disallowJsonEncode === true;
38937
39318
  const normalizedOptions = label !== void 0 ? disallowJsonEncode ? {
@@ -39631,7 +40012,7 @@ const make$58 = (value) => {
39631
40012
  * @category mutations
39632
40013
  * @since 2.0.0
39633
40014
  */
39634
- const set$1 = /*#__PURE__*/ dual(2, (self, value) => {
40015
+ const set$2 = /*#__PURE__*/ dual(2, (self, value) => {
39635
40016
  self.current = value;
39636
40017
  return self;
39637
40018
  });
@@ -39893,7 +40274,7 @@ const subscribe = (self) => uninterruptible(contextWith((services) => {
39893
40274
  return addFinalizer$1(scope, unsubscribe(subscription)).pipe(andThen(addFinalizerExit(localScope, (exit) => close(scope, exit))), as(subscription));
39894
40275
  }));
39895
40276
  const unsubscribe = (self) => uninterruptible(withFiber((state) => {
39896
- set$1(self.shutdownFlag, true);
40277
+ set$2(self.shutdownFlag, true);
39897
40278
  return forEach$1(takeAll$2(self.pollers), (d) => interruptWith(d, state.id), {
39898
40279
  discard: true,
39899
40280
  concurrency: "unbounded"
@@ -43303,7 +43684,7 @@ const get$4 = /*#__PURE__*/ dual(2, (self, key) => uninterruptibleMask((restore)
43303
43684
  refCount: 1
43304
43685
  };
43305
43686
  entry.finalizer = release$1(self, key, entry);
43306
- set$5(state.map, key, entry);
43687
+ set$6(state.map, key, entry);
43307
43688
  const context = new Map(self.context.mapUnsafe);
43308
43689
  parent.context.mapUnsafe.forEach((value, key) => {
43309
43690
  context.set(key, value);
@@ -46426,6 +46807,46 @@ function Record(key, value, pathOrOptions, options) {
46426
46807
  function Port$1(name) {
46427
46808
  return schema$1(PortSchema, name);
46428
46809
  }
46810
+ /**
46811
+ * Creates a config for a redacted string value. The parsed result is wrapped
46812
+ * in a `Redacted` container that hides the value from logs and `toString`.
46813
+ *
46814
+ * **When to use**
46815
+ *
46816
+ * Use to read secret string settings that should not be exposed in logs or
46817
+ * string output.
46818
+ *
46819
+ * **Details**
46820
+ *
46821
+ * Shortcut for `Config.schema(Schema.Redacted(Schema.String), name)`.
46822
+ *
46823
+ * **Example** (Reading a secret)
46824
+ *
46825
+ * ```ts import.meta.vitest
46826
+ * import { Config, ConfigProvider, Effect } from "effect"
46827
+ *
46828
+ * const program = Config.Redacted("API_KEY").pipe(Effect.map(String))
46829
+ *
46830
+ * const provider = ConfigProvider.fromEnv({
46831
+ * env: {
46832
+ * API_KEY: "sk-1234567890abcdef"
46833
+ * }
46834
+ * })
46835
+ *
46836
+ * Effect.runSync(
46837
+ * program.pipe(Effect.provideService(ConfigProvider.ConfigProvider, provider))
46838
+ * ) // => "<redacted>"
46839
+ * ```
46840
+ *
46841
+ * @see {@link String} for non-secret string settings
46842
+ *
46843
+ * @stability stable
46844
+ * @category constructors
46845
+ * @since 2.0.0
46846
+ */
46847
+ function Redacted(name) {
46848
+ return schema$1(Redacted$1(String$6), name);
46849
+ }
46429
46850
  // ../../node_modules/.pnpm/effect@4.1.2/node_modules/effect/dist/Console.js
46430
46851
  /**
46431
46852
  * Context reference for the current console service in the Effect system, allowing access to the active console implementation from within the Effect context.
@@ -47788,6 +48209,42 @@ const make$45 = (value) => sync(() => makeUnsafe$1(value));
47788
48209
  */
47789
48210
  const get$1 = (self) => sync(() => self.ref.current);
47790
48211
  /**
48212
+ * Sets the value of the Ref to the specified value.
48213
+ *
48214
+ * **When to use**
48215
+ *
48216
+ * Use to replace the current `Ref` value with a known value.
48217
+ *
48218
+ * **Example** (Setting a value)
48219
+ *
48220
+ * ```ts import.meta.vitest
48221
+ * import { Effect, Ref } from "effect"
48222
+ *
48223
+ * const program = Effect.gen(function*() {
48224
+ * const ref = yield* Ref.make(0)
48225
+ * yield* Ref.set(ref, 42)
48226
+ * return yield* Ref.get(ref)
48227
+ * })
48228
+ *
48229
+ * const program2 = Effect.gen(function*() {
48230
+ * const ref = yield* Ref.make(0)
48231
+ * yield* Ref.set(ref, 100)
48232
+ * return yield* Ref.get(ref)
48233
+ * })
48234
+ *
48235
+ * await Effect.runPromise(program) // => 42
48236
+ * await Effect.runPromise(program2) // => 100
48237
+ * ```
48238
+ *
48239
+ * @see {@link getAndSet} for setting while returning the previous value
48240
+ * @see {@link setAndGet} for setting while returning the new value
48241
+ *
48242
+ * @stability stable
48243
+ * @category mutations
48244
+ * @since 2.0.0
48245
+ */
48246
+ const set$1 = /*#__PURE__*/ dual(2, (self, value) => sync(() => set$2(self.ref, value)));
48247
+ /**
47791
48248
  * Updates the value of the Ref atomically using the given function.
47792
48249
  *
47793
48250
  * **When to use**
@@ -48821,7 +49278,7 @@ const getCurrentVersion = () => currentVersion;
48821
49278
  */
48822
49279
  const HttpResponseDetails = /*#__PURE__*/ Struct({
48823
49280
  status: Int$1,
48824
- headers: Record$1(String$6, Union([String$6, Redacted(String$6)]))
49281
+ headers: Record$1(String$6, Union([String$6, Redacted$1(String$6)]))
48825
49282
  }).annotate({ identifier: "HttpResponseDetails" });
48826
49283
  const ReasonTypeId = "~effect/ai/AiError/Reason";
48827
49284
  const providerMetadataWithDefaults = () => ProviderMetadata.pipe(withConstructorDefault(succeed$5({})), withDecodingDefault(succeed$5({})));
@@ -51090,7 +51547,7 @@ const encodeText = buffer !== void 0 ? (body) => buffer.from(body, "utf8") : (bo
51090
51547
  * @category constructors
51091
51548
  * @since 4.0.0
51092
51549
  */
51093
- const text$1 = (body, contentType) => {
51550
+ const text$2 = (body, contentType) => {
51094
51551
  if (typeof body !== "string") body = body === void 0 ? "" : String(body);
51095
51552
  if (buffer !== void 0) return new Uint8Array$1(void 0, contentType ?? "text/plain", buffer.byteLength(body, "utf8"), body);
51096
51553
  const bytes = encoder$2.encode(body);
@@ -51107,7 +51564,7 @@ const text$1 = (body, contentType) => {
51107
51564
  * @category constructors
51108
51565
  * @since 4.0.0
51109
51566
  */
51110
- const jsonUnsafe$1 = (body, contentType) => text$1(JSON.stringify(body), contentType ?? "application/json");
51567
+ const jsonUnsafe$1 = (body, contentType) => text$2(JSON.stringify(body), contentType ?? "application/json");
51111
51568
  /**
51112
51569
  * Creates a JSON HTTP body in an `Effect`.
51113
51570
  *
@@ -51120,7 +51577,7 @@ const jsonUnsafe$1 = (body, contentType) => text$1(JSON.stringify(body), content
51120
51577
  * @since 4.0.0
51121
51578
  */
51122
51579
  const json$1 = (body, contentType) => try_({
51123
- try: () => text$1(JSON.stringify(body), contentType ?? "application/json"),
51580
+ try: () => text$2(JSON.stringify(body), contentType ?? "application/json"),
51124
51581
  catch: (cause) => new HttpBodyError({
51125
51582
  reason: { _tag: "JsonError" },
51126
51583
  cause
@@ -51506,7 +51963,7 @@ const compressBody$1 = (body, algorithm, options) => {
51506
51963
  */
51507
51964
  const updateHeaders = (headers, body) => {
51508
51965
  if (body._tag === "Empty" || body._tag === "FormData") return remove$1(remove$1(headers, "content-type"), "content-length");
51509
- headers = body.contentType === void 0 ? remove$1(headers, "content-type") : set$2(headers, "content-type", body.contentType);
51966
+ headers = body.contentType === void 0 ? remove$1(headers, "content-type") : set$3(headers, "content-type", body.contentType);
51510
51967
  return updateContentLength(headers, body);
51511
51968
  };
51512
51969
  /**
@@ -51514,7 +51971,7 @@ const updateHeaders = (headers, body) => {
51514
51971
  */
51515
51972
  const updateContentLength = (headers, body) => {
51516
51973
  const contentLength = body._tag === "Empty" || body._tag === "FormData" ? void 0 : body.contentLength;
51517
- return contentLength === void 0 ? remove$1(headers, "content-length") : set$2(headers, "content-length", contentLength.toString());
51974
+ return contentLength === void 0 ? remove$1(headers, "content-length") : set$3(headers, "content-length", contentLength.toString());
51518
51975
  };
51519
51976
  // ../../node_modules/.pnpm/effect@4.1.2/node_modules/effect/dist/http/Url.js
51520
51977
  /**
@@ -51665,7 +52122,7 @@ const setMethod = /*#__PURE__*/ dual(2, (self, method) => makeWith$1(method, sel
51665
52122
  * @category combinators
51666
52123
  * @since 4.0.0
51667
52124
  */
51668
- const setHeader$1 = /*#__PURE__*/ dual(3, (self, key, value) => makeWith$1(self.method, self.url, self.urlParams, self.hash, set$2(self.headers, key, value), self.body));
52125
+ const setHeader$1 = /*#__PURE__*/ dual(3, (self, key, value) => makeWith$1(self.method, self.url, self.urlParams, self.hash, set$3(self.headers, key, value), self.body));
51669
52126
  /**
51670
52127
  * Sets multiple request headers from an input collection, replacing existing values with matching names.
51671
52128
  *
@@ -51765,7 +52222,7 @@ const setBody$1 = /*#__PURE__*/ dual(2, (self, body) => {
51765
52222
  */
51766
52223
  const compressBody = /*#__PURE__*/ dual((args) => isHttpClientRequest(args[0]), (self, algorithm, options) => {
51767
52224
  if (self.headers["content-encoding"] !== void 0) return succeed$5(self);
51768
- return map$5(compressBody$1(self.body, algorithm, options), (body) => body === self.body ? self : makeWith$1(self.method, self.url, self.urlParams, self.hash, set$2(updateContentLength(self.headers, body), "content-encoding", algorithm), body));
52225
+ return map$5(compressBody$1(self.body, algorithm, options), (body) => body === self.body ? self : makeWith$1(self.method, self.url, self.urlParams, self.hash, set$3(updateContentLength(self.headers, body), "content-encoding", algorithm), body));
51769
52226
  });
51770
52227
  /**
51771
52228
  * Sets a JSON request body using unsafe JSON encoding.
@@ -53183,7 +53640,7 @@ const makeCollectorUnsafe = () => {
53183
53640
  *
53184
53641
  * @internal
53185
53642
  */
53186
- const spanName = (spanPrefix, tag) => spanPrefix === void 0 ? tag : `${spanPrefix}.${tag}`;
53643
+ const spanName$1 = (spanPrefix, tag) => spanPrefix === void 0 ? tag : `${spanPrefix}.${tag}`;
53187
53644
  /**
53188
53645
  * Default RPC span attributes, overridden by user `spanAttributes`.
53189
53646
  *
@@ -57210,7 +57667,7 @@ function decodeValueUnchecked(layout, r) {
57210
57667
  }
57211
57668
  }
57212
57669
  case "duration": switch (r.byte()) {
57213
- case 0: return nanos(r.zigzag());
57670
+ case 0: return nanos$1(r.zigzag());
57214
57671
  case 1: return infinity;
57215
57672
  case 2: return negativeInfinity;
57216
57673
  default: return invalid("duration", void 0, r.options);
@@ -57798,7 +58255,7 @@ const makeNoSerialization$1 = /*#__PURE__*/ fnUntraced(function* (group, options
57798
58255
  const context = opts?.context ?? empty$14();
57799
58256
  if (!isStream) {
57800
58257
  const onRequest = (span) => onEffectRequest(rpc, middleware, span, rpc.payloadSchema.make(payload), headers, context, opts?.discard ?? false);
57801
- return disableTracing ? onRequest(void 0) : useSpan(spanName(spanPrefix, rpc._tag), {
58258
+ return disableTracing ? onRequest(void 0) : useSpan(spanName$1(spanPrefix, rpc._tag), {
57802
58259
  kind: "client",
57803
58260
  attributes: spanAttributes(rpc._tag, options.spanAttributes)
57804
58261
  }, onRequest);
@@ -57861,7 +58318,7 @@ const makeNoSerialization$1 = /*#__PURE__*/ fnUntraced(function* (group, options
57861
58318
  });
57862
58319
  const onStreamRequest = fnUntraced(function* (rpc, middleware, payload, headers, streamBufferSize, context) {
57863
58320
  if (isShutdown) return yield* interrupt$1;
57864
- const span = disableTracing ? void 0 : yield* makeSpanScoped(spanName(spanPrefix, rpc._tag), {
58321
+ const span = disableTracing ? void 0 : yield* makeSpanScoped(spanName$1(spanPrefix, rpc._tag), {
57865
58322
  kind: "client",
57866
58323
  attributes: spanAttributes(rpc._tag, options.spanAttributes)
57867
58324
  });
@@ -63817,14 +64274,14 @@ const getContentType = (options, headers) => {
63817
64274
  * @category constructors
63818
64275
  * @since 4.0.0
63819
64276
  */
63820
- const text = (body, options) => {
64277
+ const text$1 = (body, options) => {
63821
64278
  const headers = options?.headers ? fromInput$1(options.headers) : empty$6;
63822
64279
  return makeResponse({
63823
64280
  status: options?.status ?? 200,
63824
64281
  statusText: options?.statusText,
63825
64282
  headers,
63826
64283
  cookies: options?.cookies ?? empty$7,
63827
- body: text$1(body, getContentType(options, headers))
64284
+ body: text$2(body, getContentType(options, headers))
63828
64285
  });
63829
64286
  };
63830
64287
  /**
@@ -63932,7 +64389,7 @@ const stream$1 = (body, options) => {
63932
64389
  * @category combinators
63933
64390
  * @since 4.0.0
63934
64391
  */
63935
- const setHeader = /*#__PURE__*/ dual(3, (self, key, value) => makeResponse(self, set$2(self.headers, key, value)));
64392
+ const setHeader = /*#__PURE__*/ dual(3, (self, key, value) => makeResponse(self, set$3(self.headers, key, value)));
63936
64393
  /**
63937
64394
  * Returns a response with the specified header removed.
63938
64395
  *
@@ -64096,7 +64553,7 @@ const make$26 = /*#__PURE__*/ fnUntraced(function* (impl) {
64096
64553
  const limit = bytesToRead === void 0 ? void 0 : offset + contentLength;
64097
64554
  const start = yield* fileResponseNumber(offset, "offset");
64098
64555
  const end = limit === void 0 ? void 0 : yield* fileResponseNumber(limit, "end");
64099
- const headers = set$2(optionHeaders(options), "etag", toString(etag));
64556
+ const headers = set$3(optionHeaders(options), "etag", toString(etag));
64100
64557
  if (isSome(info.mtime)) headers["last-modified"] = info.mtime.value.toUTCString();
64101
64558
  return impl.fileResponse(path, options?.status ?? 200, options?.statusText, headers, start, end, contentLength);
64102
64559
  }),
@@ -64113,7 +64570,7 @@ const make$26 = /*#__PURE__*/ fnUntraced(function* (impl) {
64113
64570
  });
64114
64571
  const optionHeaders = (options) => {
64115
64572
  const headers = options?.headers ? fromInput$1(options.headers) : empty$6;
64116
- return options?.contentType ? set$2(headers, "content-type", options.contentType) : headers;
64573
+ return options?.contentType ? set$3(headers, "content-type", options.contentType) : headers;
64117
64574
  };
64118
64575
  const fileResponseSize = (input, field) => {
64119
64576
  const size = fromInput$2(input);
@@ -65728,7 +66185,7 @@ const cors$1 = (options) => {
65728
66185
  };
65729
66186
  const preResponseHandler = (request, response) => {
65730
66187
  const headers = headersFromRequest(request);
65731
- return succeed$5(setHeaders(response, headers["vary"] === void 0 ? headers : set$2(headers, "vary", varyWith(response.headers, "Origin"))));
66188
+ return succeed$5(setHeaders(response, headers["vary"] === void 0 ? headers : set$3(headers, "vary", varyWith(response.headers, "Origin"))));
65732
66189
  };
65733
66190
  return (httpApp) => withFiber((fiber) => {
65734
66191
  const request = getUnsafe$2(fiber.context, HttpServerRequest);
@@ -68768,7 +69225,7 @@ const makeNoSerialization = /*#__PURE__*/ fnUntraced(function* (group, options)
68768
69225
  if (opts?.onRequest) effect = opts.onRequest(effect);
68769
69226
  if (enableTracing) {
68770
69227
  const parentSpan = getOrUndefined(requestFiber.context, ParentSpan);
68771
- effect = withSpan(effect, spanName(spanPrefix, request.tag), {
69228
+ effect = withSpan(effect, spanName$1(spanPrefix, request.tag), {
68772
69229
  captureStackTrace: false,
68773
69230
  kind: "server",
68774
69231
  attributes: spanAttributes(request.tag, options.spanAttributes),
@@ -69263,7 +69720,7 @@ const makeProtocolWithHttpEffect = /*#__PURE__*/ fnUntraced(function* (options =
69263
69720
  if (!includesFraming) {
69264
69721
  const responses = yield* interruptible(collect(queue));
69265
69722
  const encoded = parser.encode(responses);
69266
- return text(encoded === void 0 ? "" : encoded, { contentType: serialization.contentType });
69723
+ return text$1(encoded === void 0 ? "" : encoded, { contentType: serialization.contentType });
69267
69724
  }
69268
69725
  const initialChunk = yield* interruptible(catchDone(takeAll$1(queue), () => succeed$5([])));
69269
69726
  if (queue.state._tag === "Done") return uint8Array(initialChunk.length === 1 ? initialChunk[0] : concat$2(initialChunk), { contentType: serialization.contentType });
@@ -70686,6 +71143,79 @@ const makeUriMatcher = () => {
70686
71143
  };
70687
71144
  };
70688
71145
  const isProtocolVersion = (version) => version === "2024-11-05" || version === "2025-03-26" || version === "2025-06-18" || version === "2025-11-25" || version === "2026-07-28";
71146
+ /**
71147
+ * Service that derives bytes from a secret.
71148
+ *
71149
+ * **Example** (Deriving a key with HKDF)
71150
+ *
71151
+ * ```ts import.meta.vitest
71152
+ * import { Effect } from "effect"
71153
+ * import { Kdf } from "effect/crypto"
71154
+ *
71155
+ * const program = Effect.gen(function*() {
71156
+ * const kdf = yield* Kdf.Kdf
71157
+ * return yield* kdf.derive(Kdf.hkdfSha256, new Uint8Array(32), {
71158
+ * salt: new Uint8Array(16),
71159
+ * info: new TextEncoder().encode("encryption"),
71160
+ * length: 32
71161
+ * })
71162
+ * })
71163
+ *
71164
+ * const bytes = await Effect.runPromise(program.pipe(Effect.provide(Kdf.layerWebCrypto)))
71165
+ * bytes.length // => 32
71166
+ * ```
71167
+ *
71168
+ * @stability unstable
71169
+ * @category services
71170
+ * @since 4.0.0
71171
+ */
71172
+ var Kdf = class extends (/*#__PURE__*/ Service$2()("effect/crypto/Kdf")) {};
71173
+ const invalidArgument = (description) => fail$5("Kdf", "derive", new InvalidArgument({ description }));
71174
+ const isIntegerIn$1 = (n, min, max) => Number.isSafeInteger(n) && n >= min && n <= max;
71175
+ const checkArguments = (algorithm, options) => {
71176
+ if (algorithm._tag !== "Hkdf" && options.info !== void 0) return invalidArgument("info only applies to HKDF");
71177
+ if (algorithm._tag === "Argon2id") return void 0;
71178
+ if (algorithm.hash.name === "MD5") return invalidArgument(`${algorithm._tag} needs a SHA hash, not MD5`);
71179
+ if (algorithm._tag === "Hkdf") {
71180
+ const maxLength = 255 * algorithm.hash.outputLength;
71181
+ return isIntegerIn$1(options.length, 1, maxLength) ? void 0 : invalidArgument(`length must be between 1 and ${maxLength} bytes for ${algorithm.name}`);
71182
+ }
71183
+ if (!isIntegerIn$1(algorithm.iterations, 1, 2147483647)) return invalidArgument("iterations must be between 1 and 2^31 - 1");
71184
+ return isIntegerIn$1(options.length, 1, 536870911) ? void 0 : invalidArgument("length must be between 1 and 2^29 - 1 bytes");
71185
+ };
71186
+ const webCryptoParams = (algorithm, options) => algorithm._tag === "Hkdf" ? {
71187
+ name: "HKDF",
71188
+ hash: algorithm.hash.name,
71189
+ salt: options.salt,
71190
+ info: options.info ?? /* @__PURE__ */ new Uint8Array()
71191
+ } : {
71192
+ name: "PBKDF2",
71193
+ hash: algorithm.hash.name,
71194
+ salt: options.salt,
71195
+ iterations: algorithm.iterations
71196
+ };
71197
+ /**
71198
+ * Layer that provides `Kdf` on the `WebCrypto` reference.
71199
+ *
71200
+ * **Details**
71201
+ *
71202
+ * HKDF and PBKDF2 run on `crypto.subtle`, off the event loop where the runtime
71203
+ * supports it. Argon2id fails with an `Unsupported` reason.
71204
+ *
71205
+ * @stability unstable
71206
+ * @category layers
71207
+ * @since 4.0.0
71208
+ */
71209
+ const layerWebCrypto = /*#__PURE__*/ effect(Kdf, /*#__PURE__*/ WebCrypto.use((crypto) => succeed$5(Kdf.of({ derive: (algorithm, secret, options) => suspend$2(() => {
71210
+ const failure = checkArguments(algorithm, options);
71211
+ if (failure !== void 0) return failure;
71212
+ if (algorithm._tag === "Argon2id") return fail$5("Kdf", "derive", new Unsupported({ description: "Kdf.layerWebCrypto does not provide argon2id" }));
71213
+ const name = algorithm._tag === "Hkdf" ? "HKDF" : "PBKDF2";
71214
+ return run$6("Kdf", "derive", algorithm.name, crypto, async (subtle) => {
71215
+ const handle = await subtle.importKey("raw", secret, name, false, ["deriveBits"]);
71216
+ return new Uint8Array(await subtle.deriveBits(webCryptoParams(algorithm, options), handle, options.length * 8));
71217
+ });
71218
+ }) }))));
70689
71219
  // ../../node_modules/.pnpm/effect@4.1.2/node_modules/effect/dist/http/FetchHttpClient.js
70690
71220
  /**
70691
71221
  * Fetch-based implementation of the Effect HTTP client service.
@@ -76489,79 +77019,6 @@ require_sender();
76489
77019
  require_subprotocol();
76490
77020
  require_websocket();
76491
77021
  var import_websocket_server = /* @__PURE__ */ __toESM(require_websocket_server(), 1);
76492
- /**
76493
- * Service that derives bytes from a secret.
76494
- *
76495
- * **Example** (Deriving a key with HKDF)
76496
- *
76497
- * ```ts import.meta.vitest
76498
- * import { Effect } from "effect"
76499
- * import { Kdf } from "effect/crypto"
76500
- *
76501
- * const program = Effect.gen(function*() {
76502
- * const kdf = yield* Kdf.Kdf
76503
- * return yield* kdf.derive(Kdf.hkdfSha256, new Uint8Array(32), {
76504
- * salt: new Uint8Array(16),
76505
- * info: new TextEncoder().encode("encryption"),
76506
- * length: 32
76507
- * })
76508
- * })
76509
- *
76510
- * const bytes = await Effect.runPromise(program.pipe(Effect.provide(Kdf.layerWebCrypto)))
76511
- * bytes.length // => 32
76512
- * ```
76513
- *
76514
- * @stability unstable
76515
- * @category services
76516
- * @since 4.0.0
76517
- */
76518
- var Kdf = class extends (/*#__PURE__*/ Service$2()("effect/crypto/Kdf")) {};
76519
- const invalidArgument = (description) => fail$5("Kdf", "derive", new InvalidArgument({ description }));
76520
- const isIntegerIn$1 = (n, min, max) => Number.isSafeInteger(n) && n >= min && n <= max;
76521
- const checkArguments = (algorithm, options) => {
76522
- if (algorithm._tag !== "Hkdf" && options.info !== void 0) return invalidArgument("info only applies to HKDF");
76523
- if (algorithm._tag === "Argon2id") return void 0;
76524
- if (algorithm.hash.name === "MD5") return invalidArgument(`${algorithm._tag} needs a SHA hash, not MD5`);
76525
- if (algorithm._tag === "Hkdf") {
76526
- const maxLength = 255 * algorithm.hash.outputLength;
76527
- return isIntegerIn$1(options.length, 1, maxLength) ? void 0 : invalidArgument(`length must be between 1 and ${maxLength} bytes for ${algorithm.name}`);
76528
- }
76529
- if (!isIntegerIn$1(algorithm.iterations, 1, 2147483647)) return invalidArgument("iterations must be between 1 and 2^31 - 1");
76530
- return isIntegerIn$1(options.length, 1, 536870911) ? void 0 : invalidArgument("length must be between 1 and 2^29 - 1 bytes");
76531
- };
76532
- const webCryptoParams = (algorithm, options) => algorithm._tag === "Hkdf" ? {
76533
- name: "HKDF",
76534
- hash: algorithm.hash.name,
76535
- salt: options.salt,
76536
- info: options.info ?? /* @__PURE__ */ new Uint8Array()
76537
- } : {
76538
- name: "PBKDF2",
76539
- hash: algorithm.hash.name,
76540
- salt: options.salt,
76541
- iterations: algorithm.iterations
76542
- };
76543
- /**
76544
- * Layer that provides `Kdf` on the `WebCrypto` reference.
76545
- *
76546
- * **Details**
76547
- *
76548
- * HKDF and PBKDF2 run on `crypto.subtle`, off the event loop where the runtime
76549
- * supports it. Argon2id fails with an `Unsupported` reason.
76550
- *
76551
- * @stability unstable
76552
- * @category layers
76553
- * @since 4.0.0
76554
- */
76555
- const layerWebCrypto = /*#__PURE__*/ effect(Kdf, /*#__PURE__*/ WebCrypto.use((crypto) => succeed$5(Kdf.of({ derive: (algorithm, secret, options) => suspend$2(() => {
76556
- const failure = checkArguments(algorithm, options);
76557
- if (failure !== void 0) return failure;
76558
- if (algorithm._tag === "Argon2id") return fail$5("Kdf", "derive", new Unsupported({ description: "Kdf.layerWebCrypto does not provide argon2id" }));
76559
- const name = algorithm._tag === "Hkdf" ? "HKDF" : "PBKDF2";
76560
- return run$6("Kdf", "derive", algorithm.name, crypto, async (subtle) => {
76561
- const handle = await subtle.importKey("raw", secret, name, false, ["deriveBits"]);
76562
- return new Uint8Array(await subtle.deriveBits(webCryptoParams(algorithm, options), handle, options.length * 8));
76563
- });
76564
- }) }))));
76565
77022
  // ../../node_modules/.pnpm/@effect+platform-node-shared@4.1.2_effect@4.1.2/node_modules/@effect/platform-node-shared/dist/NodeCrypto.js
76566
77023
  /**
76567
77024
  * Node.js layers for the `effect/crypto` modules, also used by Bun.
@@ -86257,7 +86714,7 @@ const make$3 = /*#__PURE__*/ fnUntraced(function* (options) {
86257
86714
  const exporterUserAgent = `OTel-OTLP-Exporter-JavaScript-Effect-${options.label}/${getCurrentVersion()}`;
86258
86715
  const userHeaders = fromInput$1(options.headers);
86259
86716
  const userAgent = userHeaders["user-agent"];
86260
- const headers = set$2(userHeaders, "user-agent", userAgent ? `${userAgent} ${exporterUserAgent}` : exporterUserAgent);
86717
+ const headers = set$3(userHeaders, "user-agent", userAgent ? `${userAgent} ${exporterUserAgent}` : exporterUserAgent);
86261
86718
  const request = post(options.url, { headers });
86262
86719
  const exportsEmpty = options.maxBatchSize === "disabled" && options.exportEmpty === true;
86263
86720
  let buffer = [];
@@ -86468,7 +86925,7 @@ function jsonReplacer(key, value) {
86468
86925
  }
86469
86926
  const jsonBody = (data) => {
86470
86927
  const json = JSON.stringify(data);
86471
- return text$1(json.includes("null") || json.includes("\"bytesValue\":") ? JSON.stringify(data, jsonReplacer) : json, "application/json");
86928
+ return text$2(json.includes("null") || json.includes("\"bytesValue\":") ? JSON.stringify(data, jsonReplacer) : json, "application/json");
86472
86929
  };
86473
86930
  /**
86474
86931
  * Provides `OtlpSerialization` using OTLP/HTTP JSON bodies.
@@ -86828,7 +87285,7 @@ const SpanKind = {
86828
87285
  consumer: 5
86829
87286
  };
86830
87287
  // ../../packages/runtime/src/telemetry.ts
86831
- function layerOtlp(serviceName, url, runtime) {
87288
+ function layerOtlp(serviceName, url, runtime, version) {
86832
87289
  return unwrap$7(gen(function* () {
86833
87290
  const start = `${yield* currentTimeNanos}`;
86834
87291
  const resource = {
@@ -86837,7 +87294,8 @@ function layerOtlp(serviceName, url, runtime) {
86837
87294
  "scope.runtime": runtime,
86838
87295
  "service.instance.id": start
86839
87296
  },
86840
- serviceName
87297
+ serviceName,
87298
+ serviceVersion: getOrUndefined$1(liftPredicate(version, (current) => current !== "0.1.0"))
86841
87299
  };
86842
87300
  return pipe(mergeAll$1(layer({
86843
87301
  exportInterval: "250 millis",
@@ -86861,7 +87319,7 @@ var RpcAuth = class RpcAuth extends Service$1()("@deslop/runtime/auth/lib/utils/
86861
87319
  static layerClient = (token) => layerClient(RpcAuth, (options) => gen(function* () {
86862
87320
  return yield* options.next({
86863
87321
  ...options.request,
86864
- headers: set$2(options.request.headers, "authorization", `Bearer ${yield* token}`)
87322
+ headers: set$3(options.request.headers, "authorization", `Bearer ${yield* token}`)
86865
87323
  });
86866
87324
  }));
86867
87325
  };
@@ -86883,7 +87341,7 @@ function rejected(message) {
86883
87341
  function developer() {
86884
87342
  return succeed$5(DEVELOPER);
86885
87343
  }
86886
- const unavailable = text("The authorization service is temporarily unavailable; retry later", {
87344
+ const unavailable = text$1("The authorization service is temporarily unavailable; retry later", {
86887
87345
  headers: { "retry-after": "5" },
86888
87346
  status: 503
86889
87347
  });
@@ -86918,7 +87376,7 @@ middleware()(gen(function* () {
86918
87376
  const user = yield* result$1(auth.user((yield* HttpServerRequest).headers));
86919
87377
  if (isFailure$1(user)) {
86920
87378
  if (user.failure.error === "temporarily_unavailable") return unavailable;
86921
- return text("Sign in first", { status: 401 });
87379
+ return text$1("Sign in first", { status: 401 });
86922
87380
  }
86923
87381
  return yield* provideService(app, CurrentUser, user.success);
86924
87382
  });
@@ -86930,14 +87388,14 @@ function layerMcpAuth(resource) {
86930
87388
  return (app) => gen(function* () {
86931
87389
  const headers = (yield* HttpServerRequest).headers;
86932
87390
  const challenge = `Bearer resource_metadata="${new URL("/.well-known/oauth-protected-resource/mcp", resource).href}", scope="deslop"`;
86933
- if (isNone(get$6(headers, "authorization"))) return text("OAuth authorization required; sign in with your MCP client", {
87391
+ if (isNone(get$6(headers, "authorization"))) return text$1("OAuth authorization required; sign in with your MCP client", {
86934
87392
  headers: { "www-authenticate": challenge },
86935
87393
  status: 401
86936
87394
  });
86937
87395
  const user = yield* result$1(auth.access(headers, resource));
86938
87396
  if (isFailure$1(user)) {
86939
87397
  if (user.failure.error === "temporarily_unavailable") return unavailable;
86940
- return text("The access token is invalid or expired; your MCP client refreshes it, and asks you to sign in again only if refreshing fails", {
87398
+ return text$1("The access token is invalid or expired; your MCP client refreshes it, and asks you to sign in again only if refreshing fails", {
86941
87399
  headers: { "www-authenticate": `${challenge}, error="invalid_token"` },
86942
87400
  status: 401
86943
87401
  });
@@ -86957,7 +87415,7 @@ const packageMetadata = gen(function* () {
86957
87415
  const file = (yield* Path$1).join(packageRoot, "package.json");
86958
87416
  return yield* decodeEffect(fromJsonString(PackageMetadata))(yield* (yield* FileSystem).readFileString(file));
86959
87417
  });
86960
- const appName = map$5(packageMetadata, (metadata) => replace("@deslop/", "")(metadata.name));
87418
+ const appName$1 = map$5(packageMetadata, (metadata) => replace("@deslop/", "")(metadata.name));
86961
87419
  const checkoutRoot = fnUntraced(function* (directory) {
86962
87420
  const path = yield* Path$1;
86963
87421
  if (yield* orElseSucceed((yield* FileSystem).exists(path.join(directory, "pnpm-workspace.yaml")), () => false)) return some$1(directory);
@@ -86966,7 +87424,7 @@ const checkoutRoot = fnUntraced(function* (directory) {
86966
87424
  });
86967
87425
  const dataDirectory = gen(function* () {
86968
87426
  const path = yield* Path$1;
86969
- const name = yield* appName;
87427
+ const name = yield* appName$1;
86970
87428
  const directory = yield* match$8(yield* checkoutRoot(packageRoot), {
86971
87429
  onNone: () => map$5(String$5("HOME"), (home) => path.join(home, ".deslop", name)),
86972
87430
  onSome: (root) => succeed$5(path.join(root, ".deslop", name))
@@ -87040,10 +87498,10 @@ function layerKeyValueStore(directory) {
87040
87498
  unwrap$7(map$5(dataDirectory, layerKeyValueStore));
87041
87499
  const layerProtocol = mergeAll$1(layerSchemaBinary(), succeed$6(MaxBodySize)(mebibytes(10)));
87042
87500
  const layerTelemetry = unwrap$7(gen(function* () {
87043
- const name = (yield* packageMetadata).name;
87501
+ const metadata = yield* packageMetadata;
87044
87502
  return match$8(yield* option(String$5("OTEL_URL")), {
87045
87503
  onNone: () => empty$10,
87046
- onSome: (url) => layerOtlp(`${name}-server`, url, "server")
87504
+ onSome: (url) => layerOtlp(`${metadata.name}-server`, url, "server", metadata.version)
87047
87505
  });
87048
87506
  }));
87049
87507
  const layerRoutes = use((router) => gen(function* () {
@@ -87055,7 +87513,7 @@ const layerRoutes = use((router) => gen(function* () {
87055
87513
  const request = yield* HttpServerRequest;
87056
87514
  const next = filter$5(liftThrowable(() => new URL(new URL(request.url, canonical).searchParams.get("next") ?? canonical, canonical))(), (url) => url.origin === canonical);
87057
87515
  return match$8(issuer, {
87058
- onNone: () => text("Sign-in is not configured for this app", { status: 503 }),
87516
+ onNone: () => text$1("Sign-in is not configured for this app", { status: 503 }),
87059
87517
  onSome: (origin) => match$8(next, {
87060
87518
  onNone: () => empty({ status: 400 }),
87061
87519
  onSome: (url) => redirect(`${new URL("/", origin).href}?${new URLSearchParams({
@@ -87071,7 +87529,7 @@ const layerRoutes = use((router) => gen(function* () {
87071
87529
  onNone: () => ({}),
87072
87530
  onSome: (origin) => ({ auth: origin })
87073
87531
  }),
87074
- name: yield* appName,
87532
+ name: yield* appName$1,
87075
87533
  traces,
87076
87534
  version: (yield* packageMetadata).version
87077
87535
  });
@@ -87104,7 +87562,7 @@ const layerAnnounce = effectDiscard(gen(function* () {
87104
87562
  });
87105
87563
  }));
87106
87564
  function layerIcon(icon) {
87107
- const response = succeed$5(text(icon, {
87565
+ const response = succeed$5(text$1(icon, {
87108
87566
  contentType: "image/svg+xml",
87109
87567
  headers: { "cache-control": "public, max-age=86400" }
87110
87568
  }));
@@ -87113,7 +87571,7 @@ function layerIcon(icon) {
87113
87571
  const layerWeb = unwrap$7(gen(function* () {
87114
87572
  const client = fileURLToPath(new URL("./client", import.meta.url));
87115
87573
  if (!(yield* (yield* FileSystem).exists((yield* Path$1).join(client, "index.html")))) return empty$10;
87116
- const name = capitalize(yield* appName);
87574
+ const name = capitalize(yield* appName$1);
87117
87575
  return mergeAll$1(add("GET", "/manifest.webmanifest", succeed$5(jsonUnsafe({
87118
87576
  background_color: "#0a0a0a",
87119
87577
  display: "standalone",
@@ -87153,7 +87611,7 @@ function layerMcp(options) {
87153
87611
  ...options,
87154
87612
  allowSessionTermination: true,
87155
87613
  icons: [{ src: new URL("/icon", canonical).href }],
87156
- name: yield* appName,
87614
+ name: yield* appName$1,
87157
87615
  path: "/mcp",
87158
87616
  protocols: [
87159
87617
  v2026_07_28,
@@ -87360,7 +87818,7 @@ function runApp(app) {
87360
87818
  };
87361
87819
  const program = gen(function* () {
87362
87820
  const metadata = yield* packageMetadata;
87363
- const name = yield* appName;
87821
+ const name = yield* appName$1;
87364
87822
  const root = pipe(make$4(name), withSharedFlags(flagsOf(settings)));
87365
87823
  const given = map$5(root, (input) => getSomes$1(input));
87366
87824
  return yield* pipe(root, withHandler((input) => flatMap$2(provider(getSomes$1(input)), (values) => provideService(server(app), ConfigProvider, values))), withSubcommands([pipe(make$4("service"), withSubcommands([
@@ -87504,6 +87962,7 @@ const Runtime = Literals([
87504
87962
  "web",
87505
87963
  "mobile",
87506
87964
  "server",
87965
+ "ci",
87507
87966
  "unknown"
87508
87967
  ]);
87509
87968
  const Service = Struct({
@@ -87514,7 +87973,8 @@ const ServiceStatus = Struct({
87514
87973
  ...Service.fields,
87515
87974
  entries: Natural,
87516
87975
  lastEventAt: Nano,
87517
- runStartedAt: Nano
87976
+ runStartedAt: Nano,
87977
+ version: String$6
87518
87978
  });
87519
87979
  const IngestionStatus = Struct({
87520
87980
  rejections: ArraySchema(Struct({
@@ -87545,14 +88005,14 @@ const TracesPage = Struct({
87545
88005
  })),
87546
88006
  total: Int$1
87547
88007
  });
87548
- const Overview = Struct({ services: ArraySchema(Struct({
88008
+ const Overview = Struct({ apps: ArraySchema(Struct({
87549
88009
  name: String$6,
87550
88010
  operations: ArraySchema(Struct({
87551
88011
  count: Int$1,
87552
88012
  failures: Int$1,
87553
88013
  name: String$6,
87554
88014
  p50Ms: Finite,
87555
- p95Ms: Finite,
88015
+ runtime: Runtime,
87556
88016
  traces: ArraySchema(Struct({
87557
88017
  durationMs: Finite,
87558
88018
  failure: optional$8(Struct({
@@ -87562,6 +88022,10 @@ const Overview = Struct({ services: ArraySchema(Struct({
87562
88022
  id: TraceId,
87563
88023
  time: Nano
87564
88024
  }))
88025
+ })),
88026
+ versions: ArraySchema(Struct({
88027
+ runtimes: ArraySchema(Runtime),
88028
+ version: String$6
87565
88029
  }))
87566
88030
  })) });
87567
88031
  const Stats = Struct({
@@ -87616,6 +88080,7 @@ var RpcContracts = class extends make$29(make$31("scope.overview", {
87616
88080
  success: Trace
87617
88081
  })).middleware(RpcAuth) {};
87618
88082
  // src/services/telemetry/lib/utils.ts
88083
+ const byRelease = mapInput(Array_(Number$6), (version) => map$8(split(version, "."), (part) => getOrElse(parse$2(part), () => 0)));
87619
88084
  function queryOf(filters, now) {
87620
88085
  return {
87621
88086
  limit: 1e3,
@@ -87632,6 +88097,38 @@ function logTime(log, now) {
87632
88097
  function resourceString(resource, key) {
87633
88098
  return pipe(resource.attributes ?? [], findFirst((attribute) => attribute.key === key), flatMap$7((attribute) => liftPredicate(attribute.value["stringValue"], isString$1)), getOrElse(() => ""));
87634
88099
  }
88100
+ function spanName(span) {
88101
+ const name = getOrElse(liftPredicate(span["name"], isString$1), () => "");
88102
+ const attributes = { attributes: getOrElse(decodeUnknownOption(ArraySchema(Attribute))(span["attributes"]), () => []) };
88103
+ if (name === "" || name !== resourceString(attributes, "http.request.method")) return name;
88104
+ const route = resourceString(attributes, "http.route");
88105
+ if (isNonEmpty$1(route)) return `${name} ${route}`;
88106
+ if (span["kind"] === 2) return `${name} (no route)`;
88107
+ return pipe(liftPredicate(resourceString(attributes, "url.path"), isNonEmpty$1), match$8({
88108
+ onNone: () => name,
88109
+ onSome: (path) => `${name} ${path}`
88110
+ }));
88111
+ }
88112
+ function versionOf(entry) {
88113
+ return resourceString(entry.resource, "service.version");
88114
+ }
88115
+ function releaseOf(entry) {
88116
+ return getOrElse(liftPredicate(versionOf(entry), (version) => isSome(match$3(/^\d+(?:\.\d+)*$/u)(version))), () => "");
88117
+ }
88118
+ function newestVersions(entries, known) {
88119
+ const versioned = filter$3(map$8(entries, (entry) => ({
88120
+ service: entry.service,
88121
+ version: releaseOf(entry)
88122
+ })), (item) => item.version !== "");
88123
+ return union$2(known, map$9(groupBy(versioned, (item) => item.service), (group) => max$2(map$8(group, (item) => item.version), byRelease)), max$3(byRelease));
88124
+ }
88125
+ function superseded(entry, newest) {
88126
+ const version = releaseOf(entry);
88127
+ return version !== "" && exists(get$10(newest, entry.service), (latest) => isLessThan$1(byRelease)(version, latest));
88128
+ }
88129
+ function appName(service) {
88130
+ return pipe(service, replace(/^@deslop\//u, ""), replace(/-(?:server|client|ios)$/u, ""));
88131
+ }
87635
88132
  function runtime(resource) {
87636
88133
  const value = resourceString(resource, "scope.runtime");
87637
88134
  if (is$2(Runtime)(value)) return value;
@@ -87727,7 +88224,8 @@ function serviceStatuses(entries) {
87727
88224
  }),
87728
88225
  name,
87729
88226
  runStartedAt: `${run}`,
87730
- runtime: runtime(latest.resource)
88227
+ runtime: runtime(latest.resource),
88228
+ version: versionOf(latest)
87731
88229
  };
87732
88230
  });
87733
88231
  }
@@ -87814,8 +88312,9 @@ function traced(records, now) {
87814
88312
  if (!(some(spans, (span) => parentId(span) === "") || now - pipe(parse$2(`${BigInt(timing.time) / 1000000n}`), getOrElse(() => now)) > 6e4)) return none();
87815
88313
  const root = rootOf(spans);
87816
88314
  return some$1({
88315
+ app: appName(root.service),
87817
88316
  name: root.name,
87818
- service: root.service,
88317
+ runtime: runtime(root.resource),
87819
88318
  trace: {
87820
88319
  durationMs: timing.durationMs,
87821
88320
  ...match$8(brokeAt(spans), {
@@ -87827,30 +88326,32 @@ function traced(records, now) {
87827
88326
  }),
87828
88327
  id: root.traceId,
87829
88328
  time: timing.time
87830
- }
88329
+ },
88330
+ version: versionOf(root)
87831
88331
  });
87832
88332
  });
87833
88333
  }
87834
88334
  function operationsOf(group, keep) {
87835
- return sort(map$8(toEntries(groupBy(group, (item) => item.name)), (entry) => {
88335
+ return sort(map$8(toEntries(groupBy(group, (item) => `${item.runtime} ${item.name}`)), (entry) => {
87836
88336
  const times = sort(map$8(entry[1], (item) => item.trace.durationMs), Number$6);
87837
- function percentile(ratio) {
87838
- return getOrElse(get$9(times, max(0, Math.ceil(times.length * ratio) - 1)), () => 0);
87839
- }
87840
88337
  return {
87841
88338
  count: entry[1].length,
87842
88339
  failures: failureCount(entry[1]),
87843
- name: entry[0],
87844
- p50Ms: percentile(.5),
87845
- p95Ms: percentile(.95),
88340
+ name: headNonEmpty(entry[1]).name,
88341
+ p50Ms: getOrElse(get$9(times, max(0, Math.ceil(times.length / 2) - 1)), () => 0),
88342
+ runtime: headNonEmpty(entry[1]).runtime,
87846
88343
  traces: map$8(sort(take$3(dedupeWith([...take$3(sort(filter$3(entry[1], (item) => item.trace.failure !== void 0), mapInput(flip$2(BigInt$5), (item) => BigInt(item.trace.time))), keep / 2), ...sort(entry[1], mapInput(flip$2(Number$6), (item) => item.trace.durationMs))], (first, second) => first.trace.id === second.trace.id), keep), mapInput(flip$2(Number$6), (item) => item.trace.durationMs)), (item) => item.trace)
87847
88344
  };
87848
88345
  }), combine$2(mapInput(flip$2(Number$6), (operation) => operation.failures), mapInput(flip$2(Number$6), (operation) => operation.count)));
87849
88346
  }
87850
88347
  function overview(entries, keep, now) {
87851
- return { services: map$8(sort(toEntries(groupBy(getSomes(map$8(values$2(groupBy(filter$3(entries, (entry) => entry.traceId !== ""), (entry) => entry.traceId)), (records) => traced(records, now))), (item) => item.service)), combine$2(mapInput(flip$2(Number$6), (entry) => failureCount(entry[1])), mapInput(flip$2(Number$6), (entry) => entry[1].length))), (entry) => ({
87852
- name: entry[0],
87853
- operations: operationsOf(entry[1], keep)
88348
+ return { apps: map$8(sort(values$2(groupBy(getSomes(map$8(values$2(groupBy(filter$3(entries, (entry) => entry.traceId !== ""), (entry) => entry.traceId)), (records) => traced(records, now))), (item) => item.app)), combine$2(mapInput(flip$2(Number$6), (group) => failureCount(group)), mapInput(flip$2(Number$6), (group) => group.length))), (group) => ({
88349
+ name: headNonEmpty(group).app,
88350
+ operations: operationsOf(group, keep),
88351
+ versions: sort(map$8(toEntries(groupBy(filter$3(group, (item) => item.version !== ""), (item) => item.version)), (entry) => ({
88352
+ runtimes: dedupe(map$8(entry[1], (item) => item.runtime)),
88353
+ version: entry[0]
88354
+ })), mapInput(flip$2(byRelease), (release) => release.version))
87854
88355
  })) };
87855
88356
  }
87856
88357
  // src/services/telemetry/service.ts
@@ -87874,11 +88375,19 @@ var Telemetry = class extends Service$2()("@deslop/scope/services/telemetry/serv
87874
88375
  try: () => decodeURIComponent(file)
87875
88376
  }), filterOrFail((key) => !endsWith(".tmp")(key)), flatMap$2((key) => store.get(key)), catch_$2(() => as(fs.remove(path.join(directory, file), { force: true }), none()))), { concurrency: 8 });
87876
88377
  const version = yield* make$41(0);
87877
- const state = yield* make$43(fromIterable$4(map$8(getSomes(saved), (entry) => [entry.id, entry])));
88378
+ const releases = yield* make$45(newestVersions(getSomes(saved), empty$12()));
88379
+ const state = yield* make$43(fromIterable$4(map$8(getSomes(saved), (entry) => {
88380
+ if (entry.signal === "log") return [entry.id, entry];
88381
+ return [entry.id, {
88382
+ ...entry,
88383
+ name: spanName(entry.payload)
88384
+ }];
88385
+ })));
87878
88386
  const prune = gen(function* () {
87879
88387
  const cutoff = BigInt((yield* currentTimeMillis) - toMillis(RETENTION)) * 1000000n;
88388
+ const newest = yield* get$1(releases);
87880
88389
  yield* updateEffect(state, (current) => {
87881
- const expired = filter$3(fromIterable$6(values(current)), (entry) => BigInt(entry.time) < cutoff);
88390
+ const expired = filter$3(fromIterable$6(values(current)), (entry) => BigInt(entry.time) < cutoff || superseded(entry, newest));
87882
88391
  return as(forEach$1(expired, (entry) => store.remove(entry.id), {
87883
88392
  concurrency: 1,
87884
88393
  discard: true
@@ -87898,10 +88407,25 @@ var Telemetry = class extends Service$2()("@deslop/scope/services/telemetry/serv
87898
88407
  return currentEntries(entries);
87899
88408
  });
87900
88409
  const save = fnUntraced(function* (entries) {
87901
- yield* uninterruptible(updateEffect(state, (current) => as(forEach$1(entries, (entry) => store.set(entry.id, entry), {
87902
- concurrency: 1,
87903
- discard: true
87904
- }), reduce(entries, current, (all, entry) => set$3(all, entry.id, entry)))));
88410
+ yield* uninterruptible(updateEffect(state, fnUntraced(function* (current) {
88411
+ const known = yield* get$1(releases);
88412
+ const newest = newestVersions(entries, known);
88413
+ const kept = filter$3(entries, (entry) => !superseded(entry, newest));
88414
+ const replaced = filter$3(match$1(isEmptyRecord(filter$4(newest, (latest, name) => known[name] !== latest)), {
88415
+ onFalse: () => fromIterable$6(values(current)),
88416
+ onTrue: () => []
88417
+ }), (entry) => superseded(entry, newest));
88418
+ yield* forEach$1(replaced, (entry) => store.remove(entry.id), {
88419
+ concurrency: 1,
88420
+ discard: true
88421
+ });
88422
+ yield* forEach$1(kept, (entry) => store.set(entry.id, entry), {
88423
+ concurrency: 1,
88424
+ discard: true
88425
+ });
88426
+ yield* set$1(releases, newest);
88427
+ return reduce(kept, reduce(replaced, current, (all, entry) => remove$2(all, entry.id)), (all, entry) => set$4(all, entry.id, entry));
88428
+ })));
87905
88429
  }, failed);
87906
88430
  const live = yield* make$41(overview(yield* read, 20, yield* currentTimeMillis));
87907
88431
  yield* pipe(changes(version), buffer$1({
@@ -87949,7 +88473,7 @@ var Telemetry = class extends Service$2()("@deslop/scope/services/telemetry/serv
87949
88473
  yield* save(flatMap$5(payload.resourceSpans ?? [], (group) => flatMap$5(group.scopeSpans ?? [], (scope) => map$8(scope.spans ?? [], (span) => ({
87950
88474
  durationMs: durationMs(span.startTimeUnixNano, span.endTimeUnixNano ?? "0"),
87951
88475
  id: `${toLowerCase(span.traceId)}:${toLowerCase(span.spanId)}`,
87952
- name: span.name ?? "",
88476
+ name: spanName(span),
87953
88477
  payload: span,
87954
88478
  resource: group.resource ?? {},
87955
88479
  resourceSchemaUrl: group.schemaUrl ?? "",
@@ -87971,7 +88495,7 @@ var Telemetry = class extends Service$2()("@deslop/scope/services/telemetry/serv
87971
88495
  reject: fnUntraced(function* (input) {
87972
88496
  const now = yield* currentTimeMillis;
87973
88497
  const key = `${input.route}:${input.status}:${input.credential}`;
87974
- yield* update$2(rejections, (current) => set$6(current, key, {
88498
+ yield* update$2(rejections, (current) => set$7(current, key, {
87975
88499
  ...input,
87976
88500
  count: (current[key]?.count ?? 0) + 1,
87977
88501
  lastAt: now
@@ -88036,9 +88560,171 @@ const RpcHandlers = RpcContracts.toLayer(gen(function* () {
88036
88560
  "scope.trace": (input) => telemetry.trace(input.id)
88037
88561
  });
88038
88562
  }));
88563
+ // src/services/github/lib/utils.ts
88564
+ function nanos(time) {
88565
+ return `${BigInt(toEpochMillis(makeUnsafe$5(time))) * 1000000n}`;
88566
+ }
88567
+ function hex(value, width) {
88568
+ return padStart(width, "0")(value.toString(16));
88569
+ }
88570
+ function traceIdOf(run, attempt) {
88571
+ return `${hex(run, 24)}${hex(attempt, 8)}`;
88572
+ }
88573
+ function runSpanId(run) {
88574
+ return `1${hex(run, 15)}`;
88575
+ }
88576
+ function jobSpanId(job) {
88577
+ return `2${hex(job, 15)}`;
88578
+ }
88579
+ function statusOf(conclusion, message) {
88580
+ if (conclusion === "failure" || conclusion === "timed_out" || conclusion === "startup_failure") return {
88581
+ code: 2,
88582
+ message
88583
+ };
88584
+ if (conclusion === "success") return {
88585
+ code: 1,
88586
+ message: ""
88587
+ };
88588
+ return {
88589
+ code: 0,
88590
+ message: ""
88591
+ };
88592
+ }
88593
+ function text(key, value) {
88594
+ return {
88595
+ key,
88596
+ value: { stringValue: value }
88597
+ };
88598
+ }
88599
+ function request(repository, spans) {
88600
+ return TracesRequest.make({ resourceSpans: [{
88601
+ resource: { attributes: [text("service.name", repository), text("scope.runtime", "ci")] },
88602
+ scopeSpans: [{
88603
+ scope: { name: "github-actions" },
88604
+ spans
88605
+ }]
88606
+ }] });
88607
+ }
88608
+ function runIds(event) {
88609
+ return {
88610
+ spanId: runSpanId(event.workflow_run.id),
88611
+ traceId: traceIdOf(event.workflow_run.id, event.workflow_run.run_attempt)
88612
+ };
88613
+ }
88614
+ function runTrace(event) {
88615
+ const run = event.workflow_run;
88616
+ return request(event.repository.full_name, [{
88617
+ attributes: [
88618
+ text("github.title", run.display_title),
88619
+ text("github.event", run.event),
88620
+ text("git.branch", run.head_branch ?? ""),
88621
+ text("git.commit", run.head_sha),
88622
+ text("github.conclusion", run.conclusion ?? ""),
88623
+ text("url.full", run.html_url)
88624
+ ],
88625
+ kind: 1,
88626
+ name: run.name ?? run.display_title,
88627
+ parentSpanId: "",
88628
+ startTimeUnixNano: nanos(run.run_started_at),
88629
+ status: statusOf(run.conclusion, `${run.display_title} failed`),
88630
+ ...runIds(event),
88631
+ ...match$8(liftPredicate(event.action, (action) => action === "completed"), {
88632
+ onNone: () => ({}),
88633
+ onSome: () => ({ endTimeUnixNano: nanos(run.updated_at) })
88634
+ })
88635
+ }]);
88636
+ }
88637
+ function jobTrace(event) {
88638
+ const job = event.workflow_job;
88639
+ const traceId = traceIdOf(job.run_id, job.run_attempt);
88640
+ const steps = getSomes(map$8(job.steps, (step) => pipe(all$4({
88641
+ completed: fromNullishOr(step.completed_at),
88642
+ started: fromNullishOr(step.started_at)
88643
+ }), filter$5(() => step.conclusion !== "skipped"), map$11((times) => ({
88644
+ ...step,
88645
+ ...times
88646
+ })))));
88647
+ const failed = findFirst(steps, (step) => statusOf(step.conclusion, "").code === 2);
88648
+ return request(event.repository.full_name, [{
88649
+ attributes: [
88650
+ text("github.runner", job.runner_name ?? ""),
88651
+ text("github.conclusion", job.conclusion ?? ""),
88652
+ {
88653
+ key: "github.queued_ms",
88654
+ value: { intValue: `${toEpochMillis(makeUnsafe$5(job.started_at)) - toEpochMillis(makeUnsafe$5(job.created_at))}` }
88655
+ },
88656
+ text("url.full", job.html_url)
88657
+ ],
88658
+ endTimeUnixNano: nanos(job.completed_at ?? job.started_at),
88659
+ kind: 1,
88660
+ name: job.name,
88661
+ parentSpanId: runSpanId(job.run_id),
88662
+ spanId: jobSpanId(job.id),
88663
+ startTimeUnixNano: nanos(job.started_at),
88664
+ status: statusOf(job.conclusion, match$8(failed, {
88665
+ onNone: () => `${job.name} failed`,
88666
+ onSome: (step) => `${step.name} failed`
88667
+ })),
88668
+ traceId
88669
+ }, ...map$8(steps, (step) => ({
88670
+ attributes: [text("github.conclusion", step.conclusion ?? ""), text("url.full", `${job.html_url}#step:${step.number}:1`)],
88671
+ endTimeUnixNano: nanos(step.completed),
88672
+ kind: 1,
88673
+ name: step.name,
88674
+ parentSpanId: jobSpanId(job.id),
88675
+ spanId: `3${hex(job.id, 12)}${hex(step.number, 3)}`,
88676
+ startTimeUnixNano: nanos(step.started),
88677
+ status: statusOf(step.conclusion, `${step.name} failed`),
88678
+ traceId
88679
+ }))]);
88680
+ }
88681
+ // src/services/github/schema.ts
88682
+ const Repository = Struct({ full_name: String$6 });
88683
+ const Step = Struct({
88684
+ completed_at: NullOr(String$6),
88685
+ conclusion: NullOr(String$6),
88686
+ name: String$6,
88687
+ number: Int$1,
88688
+ started_at: NullOr(String$6)
88689
+ });
88690
+ const WorkflowJob = Struct({
88691
+ action: String$6,
88692
+ repository: Repository,
88693
+ workflow_job: Struct({
88694
+ completed_at: NullOr(String$6),
88695
+ conclusion: NullOr(String$6),
88696
+ created_at: String$6,
88697
+ html_url: String$6,
88698
+ id: Int$1,
88699
+ name: String$6,
88700
+ run_attempt: Int$1,
88701
+ run_id: Int$1,
88702
+ runner_name: NullOr(String$6),
88703
+ started_at: String$6,
88704
+ steps: ArraySchema(Step)
88705
+ })
88706
+ });
88707
+ const WorkflowRun = Struct({
88708
+ action: String$6,
88709
+ repository: Repository,
88710
+ workflow_run: Struct({
88711
+ conclusion: NullOr(String$6),
88712
+ display_title: String$6,
88713
+ event: String$6,
88714
+ head_branch: NullOr(String$6),
88715
+ head_sha: String$6,
88716
+ html_url: String$6,
88717
+ id: Int$1,
88718
+ name: NullOr(String$6),
88719
+ run_attempt: Int$1,
88720
+ run_number: Int$1,
88721
+ run_started_at: String$6,
88722
+ updated_at: String$6
88723
+ })
88724
+ });
88039
88725
  // src/tools/contracts.ts
88040
88726
  const Tools = make$37(make$38("list_services", {
88041
- description: "Start here: each service with its latest run, last event and entry count, plus rejected exports. A service missing here sent nothing in the last three days.",
88727
+ description: "Start here: each service with its latest run, release, last event and entry count, plus rejected exports. Only each service's newest release is kept, so nothing here predates it. A service missing here sent nothing in the last three days.",
88042
88728
  failure: TelemetryError,
88043
88729
  success: IngestionStatus
88044
88730
  }).annotate(Readonly, true), make$38("find", {
@@ -88082,7 +88768,7 @@ const cors = cors$1({
88082
88768
  function answer(schema, save) {
88083
88769
  return flatMap$2(HttpServerRequest, (request) => {
88084
88770
  if (!startsWith("application/json")(request.headers["content-type"] ?? "")) return succeed$5(empty({ status: 415 }));
88085
- return pipe(schemaBodyJson(schema), flatMap$2(save), as(text("{}", { contentType: "application/json" })), catchTags({
88771
+ return pipe(schemaBodyJson(schema), flatMap$2(save), as(text$1("{}", { contentType: "application/json" })), catchTags({
88086
88772
  HttpServerError: () => succeed$5(jsonUnsafe({
88087
88773
  code: 3,
88088
88774
  message: "Invalid OTLP JSON body"
@@ -88098,31 +88784,70 @@ function answer(schema, save) {
88098
88784
  }));
88099
88785
  });
88100
88786
  }
88787
+ const receiver = use((router) => gen(function* () {
88788
+ const telemetry = yield* Telemetry;
88789
+ const ingest = fnUntraced(function* (route, schema, save) {
88790
+ const request = yield* HttpServerRequest;
88791
+ const response = yield* answer(schema, save);
88792
+ if (response.status >= 400) {
88793
+ function credential() {
88794
+ if (request.headers["authorization"] !== void 0) return "authorization";
88795
+ if (request.headers["cookie"] !== void 0) return "cookie";
88796
+ return "none";
88797
+ }
88798
+ yield* telemetry.reject({
88799
+ credential: credential(),
88800
+ route,
88801
+ status: response.status
88802
+ });
88803
+ }
88804
+ return response;
88805
+ });
88806
+ yield* router.add("POST", "/v1/traces", cors(ingest("/v1/traces", TracesRequest, telemetry.ingestTraces)));
88807
+ yield* router.add("POST", "/v1/logs", cors(ingest("/v1/logs", LogsRequest, telemetry.ingestLogs)));
88808
+ yield* router.add("OPTIONS", "/v1/*", cors(succeed$5(empty())));
88809
+ yield* router.add("GET", "/health", text$1("ready"));
88810
+ }));
88811
+ const Signature = pipe(String$6, check(isPattern(/^sha256=[0-9a-f]{64}$/u)), decodeTo(Uint8ArrayFromHex, {
88812
+ decode: transform$2(slice(7)),
88813
+ encode: transform$2((tag) => `sha256=${tag}`)
88814
+ }));
88101
88815
  runApp({
88102
88816
  icon: icon_default,
88103
- routes: pipe(mergeAll$1(use((router) => gen(function* () {
88817
+ routes: pipe(mergeAll$1(receiver, use((router) => gen(function* () {
88104
88818
  const telemetry = yield* Telemetry;
88105
- const ingest = fnUntraced(function* (route, schema, save) {
88106
- const request = yield* HttpServerRequest;
88107
- const response = yield* answer(schema, save);
88108
- if (response.status >= 400) {
88109
- function credential() {
88110
- if (request.headers["authorization"] !== void 0) return "authorization";
88111
- if (request.headers["cookie"] !== void 0) return "cookie";
88112
- return "none";
88113
- }
88114
- yield* telemetry.reject({
88115
- credential: credential(),
88116
- route,
88117
- status: response.status
88118
- });
88119
- }
88120
- return response;
88819
+ const mac = yield* Mac;
88820
+ yield* match$8(yield* option(Redacted("GITHUB_WEBHOOK_SECRET")), {
88821
+ onNone: () => void_$1,
88822
+ onSome: fnUntraced(function* (secret) {
88823
+ const key = yield* key$1(hmacSha256, new TextEncoder().encode(value$2(secret)));
88824
+ yield* router.add("POST", "/v1/github", catchTags(gen(function* () {
88825
+ const request = yield* HttpServerRequest;
88826
+ const body = new Uint8Array(yield* request.arrayBuffer);
88827
+ if (!(yield* match$8(decodeOption(Signature)(request.headers["x-hub-signature-256"] ?? ""), {
88828
+ onNone: () => succeed$5(false),
88829
+ onSome: (tag) => mac.verify(key, tag, body)
88830
+ }))) return empty({ status: 401 });
88831
+ const text = new TextDecoder().decode(body);
88832
+ if (request.headers["x-github-event"] === "workflow_run") {
88833
+ const event = yield* decodeEffect(fromJsonString(WorkflowRun))(text);
88834
+ const ids = runIds(event);
88835
+ const finished = yield* map$5(option$1(telemetry.trace(ids.traceId)), exists((trace) => some(trace.spans, (span) => span.spanId === ids.spanId && isString$2(span.payload["endTimeUnixNano"]))));
88836
+ if (event.action === "completed" || event.action === "in_progress" && !finished) yield* telemetry.ingestTraces(runTrace(event));
88837
+ }
88838
+ if (request.headers["x-github-event"] === "workflow_job") {
88839
+ const event = yield* decodeEffect(fromJsonString(WorkflowJob))(text);
88840
+ if (event.action === "completed" && event.workflow_job.conclusion !== "skipped") yield* telemetry.ingestTraces(jobTrace(event));
88841
+ }
88842
+ return empty({ status: 204 });
88843
+ }), {
88844
+ CryptoError: () => succeed$5(empty({ status: 401 })),
88845
+ HttpServerError: () => succeed$5(empty({ status: 400 })),
88846
+ SchemaError: (error) => succeed$5(text$1(error.message, { status: 400 })),
88847
+ TelemetryError: () => succeed$5(empty({ status: 503 }))
88848
+ }));
88849
+ })
88121
88850
  });
88122
- yield* router.add("POST", "/v1/traces", cors(ingest("/v1/traces", TracesRequest, telemetry.ingestTraces)));
88123
- yield* router.add("POST", "/v1/logs", cors(ingest("/v1/logs", LogsRequest, telemetry.ingestLogs)));
88124
- yield* router.add("OPTIONS", "/v1/*", cors(succeed$5(empty())));
88125
- yield* router.add("GET", "/health", text("ready"));
88126
88851
  })), pipe(layerHttp$1({
88127
88852
  group: RpcContracts,
88128
88853
  path: "/api/rpc",