react-doctor 0.9.9 → 0.9.10-dev.3bb84fb
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/{build-section-divider-rq_KQONI.js → build-section-divider-B8hqp04D.js} +22 -103
- package/dist/{ci-BwCh-hUD.js → ci-Dk3DstBG.js} +11 -11
- package/dist/cli.js +33 -30
- package/dist/{design-CTL1QpZB.js → design-Bq-3HXBZ.js} +4 -4
- package/dist/{exit-gracefully-C7wgCb-s.js → exit-gracefully-BDgtmBn-.js} +7 -6
- package/dist/index.d.ts +9 -1
- package/dist/index.js +159 -159
- package/dist/{inspect-CGCfCxoM.js → inspect-DME2yAzQ.js} +16 -16
- package/dist/{install-CdlRGSxJ.js → install-C_qBGcAr.js} +8 -8
- package/dist/{install-doctor-script-BEIl1lby.js → install-doctor-script-jDURjqWD.js} +4 -4
- package/dist/{install-github-workflow-Cun64Fxh.js → install-github-workflow-CVmKpHzY.js} +6 -6
- package/dist/{install-react-doctor-Bn-dP3rT.js → install-react-doctor-BVWAJ5wa.js} +8 -8
- package/dist/lsp.js +2122 -327
- package/dist/{print-branded-header-C9de_0PE.js → print-branded-header-BdWqKeOv.js} +4 -4
- package/dist/{read-object-file-ClOsQUSD.js → read-object-file-DDgbCE22.js} +4 -4
- package/dist/{record-metric-b5KUd2XK.js → record-metric-DYu6AVaU.js} +1654 -295
- package/dist/{report-error-DU6Bxy9R.js → report-error-CN1TnQFY.js} +18 -12
- package/dist/{report-workflow-result-CjrL22OD.js → report-workflow-result-B3mNTNry.js} +5 -5
- package/dist/{resolve-scope-pjSIB8ZY.js → resolve-scope-CFcIJ6wu.js} +6 -6
- package/dist/{rules-Ds2rHd-a.js → rules-C1Q8Eeih.js} +6 -6
- package/dist/{run-scan-app-D8wBLuwl.js → run-scan-app-BtiEbRGX.js} +10 -10
- package/dist/{scan-CHh6DGmw.js → scan-Dqlls0Ah.js} +8 -8
- package/dist/{should-fail-scan-gate-Bif6gnI9.js → should-fail-scan-gate-BwQnt3yQ.js} +114 -192
- package/dist/{should-skip-prompts-Q3cS356Z.js → should-skip-prompts-CQuGlo68.js} +4 -4
- package/dist/{unref-stdin-DTLx8HEf.js → unref-stdin-WVB8gYib.js} +112 -5
- package/dist/{version-BrAILQSv.js → version-BE2SrOFP.js} +4 -4
- package/dist/{why-DB_XpRpg.js → why-8fJcz5q1.js} +4 -4
- package/package.json +6 -6
package/dist/lsp.js
CHANGED
|
@@ -1199,7 +1199,7 @@ const random = (self) => {
|
|
|
1199
1199
|
* @category hashing
|
|
1200
1200
|
* @since 2.0.0
|
|
1201
1201
|
*/
|
|
1202
|
-
const combine = /* @__PURE__ */ dual(2, (self, b) => self * 53 ^ b);
|
|
1202
|
+
const combine$1 = /* @__PURE__ */ dual(2, (self, b) => self * 53 ^ b);
|
|
1203
1203
|
/**
|
|
1204
1204
|
* Applies bit manipulation techniques to optimize a hash value.
|
|
1205
1205
|
*
|
|
@@ -1374,7 +1374,7 @@ const string$2 = (str) => {
|
|
|
1374
1374
|
*/
|
|
1375
1375
|
const structureKeys = (o, keys) => {
|
|
1376
1376
|
let h = 12289;
|
|
1377
|
-
for (const key of keys) h ^= combine(hash(key), hash(o[key]));
|
|
1377
|
+
for (const key of keys) h ^= combine$1(hash(key), hash(o[key]));
|
|
1378
1378
|
return optimize(h);
|
|
1379
1379
|
};
|
|
1380
1380
|
/**
|
|
@@ -1455,7 +1455,7 @@ const iterableWith = (seed, f) => (iter) => {
|
|
|
1455
1455
|
* @since 2.0.0
|
|
1456
1456
|
*/
|
|
1457
1457
|
const array = /* @__PURE__ */ iterableWith(6151, hash);
|
|
1458
|
-
const hashMap = /* @__PURE__ */ iterableWith(/* @__PURE__ */ string$2("Map"), ([k, v]) => combine(hash(k), hash(v)));
|
|
1458
|
+
const hashMap = /* @__PURE__ */ iterableWith(/* @__PURE__ */ string$2("Map"), ([k, v]) => combine$1(hash(k), hash(v)));
|
|
1459
1459
|
const hashSet = /* @__PURE__ */ iterableWith(/* @__PURE__ */ string$2("Set"), hash);
|
|
1460
1460
|
const randomHashCache = /* @__PURE__ */ new WeakMap();
|
|
1461
1461
|
const hashCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -2681,7 +2681,7 @@ var Fail = class extends ReasonBase {
|
|
|
2681
2681
|
return isFailReason$1(that) && equals$2(this.error, that.error) && equals$2(this.annotations, that.annotations);
|
|
2682
2682
|
}
|
|
2683
2683
|
[symbol$1]() {
|
|
2684
|
-
return combine(string$2(this._tag))(combine(hash(this.error))(hash(this.annotations)));
|
|
2684
|
+
return combine$1(string$2(this._tag))(combine$1(hash(this.error))(hash(this.annotations)));
|
|
2685
2685
|
}
|
|
2686
2686
|
};
|
|
2687
2687
|
/** @internal */
|
|
@@ -2710,7 +2710,7 @@ var Die = class extends ReasonBase {
|
|
|
2710
2710
|
return isDieReason(that) && equals$2(this.defect, that.defect) && equals$2(this.annotations, that.annotations);
|
|
2711
2711
|
}
|
|
2712
2712
|
[symbol$1]() {
|
|
2713
|
-
return combine(string$2(this._tag))(combine(hash(this.defect))(hash(this.annotations)));
|
|
2713
|
+
return combine$1(string$2(this._tag))(combine$1(hash(this.defect))(hash(this.annotations)));
|
|
2714
2714
|
}
|
|
2715
2715
|
};
|
|
2716
2716
|
/** @internal */
|
|
@@ -2770,7 +2770,7 @@ const makeExit = (options) => {
|
|
|
2770
2770
|
return isExit(that) && that._tag === this._tag && equals$2(this[args], that[args]);
|
|
2771
2771
|
},
|
|
2772
2772
|
[symbol$1]() {
|
|
2773
|
-
return combine(string$2(options.op), hash(this[args]));
|
|
2773
|
+
return combine$1(string$2(options.op), hash(this[args]));
|
|
2774
2774
|
}
|
|
2775
2775
|
};
|
|
2776
2776
|
return function(value) {
|
|
@@ -2892,9 +2892,9 @@ const done$2 = (value) => {
|
|
|
2892
2892
|
/**
|
|
2893
2893
|
* @since 2.0.0
|
|
2894
2894
|
*/
|
|
2895
|
-
const TypeId$
|
|
2895
|
+
const TypeId$39 = "~effect/data/Option";
|
|
2896
2896
|
const CommonProto$1 = {
|
|
2897
|
-
[TypeId$
|
|
2897
|
+
[TypeId$39]: { _A: (_) => _ },
|
|
2898
2898
|
...PipeInspectableProto,
|
|
2899
2899
|
[Symbol.iterator]() {
|
|
2900
2900
|
return new SingleShotGen(this);
|
|
@@ -2907,7 +2907,7 @@ const SomeProto = /* @__PURE__ */ Object.defineProperty(/* @__PURE__ */ Object.a
|
|
|
2907
2907
|
return isOption(that) && isSome$1(that) && equals$2(this.value, that.value);
|
|
2908
2908
|
},
|
|
2909
2909
|
[symbol$1]() {
|
|
2910
|
-
return combine(hash(this._tag))(hash(this.value));
|
|
2910
|
+
return combine$1(hash(this._tag))(hash(this.value));
|
|
2911
2911
|
},
|
|
2912
2912
|
toString() {
|
|
2913
2913
|
return `some(${format$1(this.value)})`;
|
|
@@ -2944,7 +2944,7 @@ const NoneProto = /* @__PURE__ */ Object.assign(/* @__PURE__ */ Object.create(Co
|
|
|
2944
2944
|
}
|
|
2945
2945
|
});
|
|
2946
2946
|
/** @internal */
|
|
2947
|
-
const isOption = (input) => hasProperty(input, TypeId$
|
|
2947
|
+
const isOption = (input) => hasProperty(input, TypeId$39);
|
|
2948
2948
|
/** @internal */
|
|
2949
2949
|
const isNone$1 = (fa) => fa._tag === "None";
|
|
2950
2950
|
/** @internal */
|
|
@@ -2959,9 +2959,9 @@ const some$1 = (value) => {
|
|
|
2959
2959
|
};
|
|
2960
2960
|
//#endregion
|
|
2961
2961
|
//#region ../../node_modules/.pnpm/effect@4.0.0-beta.102/node_modules/effect/dist/internal/result.js
|
|
2962
|
-
const TypeId$
|
|
2962
|
+
const TypeId$38 = "~effect/data/Result";
|
|
2963
2963
|
const CommonProto = {
|
|
2964
|
-
[TypeId$
|
|
2964
|
+
[TypeId$38]: {
|
|
2965
2965
|
/* v8 ignore next 2 */
|
|
2966
2966
|
_A: (_) => _,
|
|
2967
2967
|
_E: (_) => _
|
|
@@ -2978,7 +2978,7 @@ const SuccessProto = /* @__PURE__ */ Object.assign(/* @__PURE__ */ Object.create
|
|
|
2978
2978
|
return isResult(that) && isSuccess$2(that) && equals$2(this.success, that.success);
|
|
2979
2979
|
},
|
|
2980
2980
|
[symbol$1]() {
|
|
2981
|
-
return combine(hash(this._tag))(hash(this.success));
|
|
2981
|
+
return combine$1(hash(this._tag))(hash(this.success));
|
|
2982
2982
|
},
|
|
2983
2983
|
toString() {
|
|
2984
2984
|
return `success(${format$1(this.success)})`;
|
|
@@ -2998,7 +2998,7 @@ const FailureProto = /* @__PURE__ */ Object.assign(/* @__PURE__ */ Object.create
|
|
|
2998
2998
|
return isResult(that) && isFailure$2(that) && equals$2(this.failure, that.failure);
|
|
2999
2999
|
},
|
|
3000
3000
|
[symbol$1]() {
|
|
3001
|
-
return combine(hash(this._tag))(hash(this.failure));
|
|
3001
|
+
return combine$1(hash(this._tag))(hash(this.failure));
|
|
3002
3002
|
},
|
|
3003
3003
|
toString() {
|
|
3004
3004
|
return `failure(${format$1(this.failure)})`;
|
|
@@ -3012,7 +3012,7 @@ const FailureProto = /* @__PURE__ */ Object.assign(/* @__PURE__ */ Object.create
|
|
|
3012
3012
|
}
|
|
3013
3013
|
});
|
|
3014
3014
|
/** @internal */
|
|
3015
|
-
const isResult = (input) => hasProperty(input, TypeId$
|
|
3015
|
+
const isResult = (input) => hasProperty(input, TypeId$38);
|
|
3016
3016
|
/** @internal */
|
|
3017
3017
|
const isFailure$2 = (result) => result._tag === "Failure";
|
|
3018
3018
|
/** @internal */
|
|
@@ -4247,6 +4247,37 @@ const isArrayNonEmpty = isArrayNonEmpty$1;
|
|
|
4247
4247
|
* @since 4.0.0
|
|
4248
4248
|
*/
|
|
4249
4249
|
const isReadonlyArrayNonEmpty = isArrayNonEmpty$1;
|
|
4250
|
+
/**
|
|
4251
|
+
* Sorts an array by the given `Order`, returning a new array.
|
|
4252
|
+
*
|
|
4253
|
+
* **When to use**
|
|
4254
|
+
*
|
|
4255
|
+
* Use to sort an array using a single `Order` comparator.
|
|
4256
|
+
*
|
|
4257
|
+
* **Details**
|
|
4258
|
+
*
|
|
4259
|
+
* Preserves `NonEmptyArray` in the return type. Use `sortWith` to sort by a
|
|
4260
|
+
* derived key, or `sortBy` for multi-key sorting.
|
|
4261
|
+
*
|
|
4262
|
+
* **Example** (Sorting numbers)
|
|
4263
|
+
*
|
|
4264
|
+
* ```ts
|
|
4265
|
+
* import { Array, Order } from "effect"
|
|
4266
|
+
*
|
|
4267
|
+
* console.log(Array.sort([3, 1, 4, 1, 5], Order.Number)) // [1, 1, 3, 4, 5]
|
|
4268
|
+
* ```
|
|
4269
|
+
*
|
|
4270
|
+
* @see {@link sortWith} — sort by a mapping function
|
|
4271
|
+
* @see {@link sortBy} — sort by multiple orders
|
|
4272
|
+
*
|
|
4273
|
+
* @category sorting
|
|
4274
|
+
* @since 2.0.0
|
|
4275
|
+
*/
|
|
4276
|
+
const sort$1 = /* @__PURE__ */ dual(2, (self, O) => {
|
|
4277
|
+
const out = Array$1.from(self);
|
|
4278
|
+
out.sort(O);
|
|
4279
|
+
return out;
|
|
4280
|
+
});
|
|
4250
4281
|
const hashBucketsAdd = (buckets, value) => {
|
|
4251
4282
|
const hash$5 = hash(value);
|
|
4252
4283
|
const bucket = buckets.get(hash$5);
|
|
@@ -4412,12 +4443,12 @@ const dedupe = (self) => {
|
|
|
4412
4443
|
*
|
|
4413
4444
|
* @since 2.0.0
|
|
4414
4445
|
*/
|
|
4415
|
-
const TypeId$
|
|
4446
|
+
const TypeId$37 = "~effect/BigDecimal";
|
|
4416
4447
|
const BigDecimalProto = {
|
|
4417
|
-
[TypeId$
|
|
4448
|
+
[TypeId$37]: TypeId$37,
|
|
4418
4449
|
[symbol$1]() {
|
|
4419
4450
|
const normalized = normalize(this);
|
|
4420
|
-
return combine(hash(normalized.value), number$1(normalized.scale));
|
|
4451
|
+
return combine$1(hash(normalized.value), number$1(normalized.scale));
|
|
4421
4452
|
},
|
|
4422
4453
|
[symbol](that) {
|
|
4423
4454
|
return isBigDecimal(that) && equals$1(this, that);
|
|
@@ -4460,7 +4491,7 @@ const BigDecimalProto = {
|
|
|
4460
4491
|
* @category guards
|
|
4461
4492
|
* @since 2.0.0
|
|
4462
4493
|
*/
|
|
4463
|
-
const isBigDecimal = (u) => hasProperty(u, TypeId$
|
|
4494
|
+
const isBigDecimal = (u) => hasProperty(u, TypeId$37);
|
|
4464
4495
|
/**
|
|
4465
4496
|
* Creates a `BigDecimal` from a `bigint` value and a scale.
|
|
4466
4497
|
*
|
|
@@ -4500,14 +4531,14 @@ const make$36 = (value, scale) => {
|
|
|
4500
4531
|
* @internal
|
|
4501
4532
|
*/
|
|
4502
4533
|
const makeNormalizedUnsafe = (value, scale) => {
|
|
4503
|
-
if (value !== bigint0$
|
|
4534
|
+
if (value !== bigint0$3 && value % bigint10 === bigint0$3) throw new RangeError("Value must be normalized");
|
|
4504
4535
|
const o = make$36(value, scale);
|
|
4505
4536
|
o.normalized = o;
|
|
4506
4537
|
return o;
|
|
4507
4538
|
};
|
|
4508
|
-
const bigint0$
|
|
4539
|
+
const bigint0$3 = /* @__PURE__ */ BigInt(0);
|
|
4509
4540
|
const bigint10 = /* @__PURE__ */ BigInt(10);
|
|
4510
|
-
const zero$1 = /* @__PURE__ */ makeNormalizedUnsafe(bigint0$
|
|
4541
|
+
const zero$1 = /* @__PURE__ */ makeNormalizedUnsafe(bigint0$3, 0);
|
|
4511
4542
|
/**
|
|
4512
4543
|
* Normalizes a given `BigDecimal` by removing trailing zeros.
|
|
4513
4544
|
*
|
|
@@ -4538,7 +4569,7 @@ const zero$1 = /* @__PURE__ */ makeNormalizedUnsafe(bigint0$2, 0);
|
|
|
4538
4569
|
* @since 2.0.0
|
|
4539
4570
|
*/
|
|
4540
4571
|
const normalize = (self) => {
|
|
4541
|
-
if (self.normalized === void 0) if (self.value === bigint0$
|
|
4572
|
+
if (self.normalized === void 0) if (self.value === bigint0$3) self.normalized = zero$1;
|
|
4542
4573
|
else {
|
|
4543
4574
|
const digits = `${self.value}`;
|
|
4544
4575
|
let trail = 0;
|
|
@@ -4609,7 +4640,7 @@ const scale = /* @__PURE__ */ dual(2, (self, scale) => {
|
|
|
4609
4640
|
* @category math
|
|
4610
4641
|
* @since 2.0.0
|
|
4611
4642
|
*/
|
|
4612
|
-
const abs = (n) => n.value < bigint0$
|
|
4643
|
+
const abs = (n) => n.value < bigint0$3 ? make$36(-n.value, n.scale) : n;
|
|
4613
4644
|
/**
|
|
4614
4645
|
* Provides an `Equivalence` instance for `BigDecimal` that determines equality between BigDecimal values.
|
|
4615
4646
|
*
|
|
@@ -4697,7 +4728,7 @@ const equals$1 = /* @__PURE__ */ dual(2, (self, that) => Equivalence$5(self, tha
|
|
|
4697
4728
|
const format = (n) => {
|
|
4698
4729
|
const normalized = normalize(n);
|
|
4699
4730
|
if (Math.abs(normalized.scale) >= 16) return toExponential(normalized);
|
|
4700
|
-
const negative = normalized.value < bigint0$
|
|
4731
|
+
const negative = normalized.value < bigint0$3;
|
|
4701
4732
|
const absolute = negative ? `${normalized.value}`.substring(1) : `${normalized.value}`;
|
|
4702
4733
|
let before;
|
|
4703
4734
|
let after;
|
|
@@ -4770,7 +4801,7 @@ const toExponential = (n) => {
|
|
|
4770
4801
|
* @category predicates
|
|
4771
4802
|
* @since 2.0.0
|
|
4772
4803
|
*/
|
|
4773
|
-
const isZero$1 = (n) => n.value === bigint0$
|
|
4804
|
+
const isZero$1 = (n) => n.value === bigint0$3;
|
|
4774
4805
|
/**
|
|
4775
4806
|
* Checks whether a given `BigDecimal` is negative.
|
|
4776
4807
|
*
|
|
@@ -4792,7 +4823,7 @@ const isZero$1 = (n) => n.value === bigint0$2;
|
|
|
4792
4823
|
* @category predicates
|
|
4793
4824
|
* @since 2.0.0
|
|
4794
4825
|
*/
|
|
4795
|
-
const isNegative = (n) => n.value < bigint0$
|
|
4826
|
+
const isNegative = (n) => n.value < bigint0$3;
|
|
4796
4827
|
//#endregion
|
|
4797
4828
|
//#region ../../node_modules/.pnpm/effect@4.0.0-beta.102/node_modules/effect/dist/Effectable.js
|
|
4798
4829
|
/**
|
|
@@ -4961,7 +4992,7 @@ const ServiceProto = {
|
|
|
4961
4992
|
}
|
|
4962
4993
|
};
|
|
4963
4994
|
const ReferenceTypeId = "~effect/Context/Reference";
|
|
4964
|
-
const TypeId$
|
|
4995
|
+
const TypeId$36 = "~effect/Context";
|
|
4965
4996
|
/**
|
|
4966
4997
|
* Creates a `Context` from an existing service map.
|
|
4967
4998
|
*
|
|
@@ -5000,7 +5031,7 @@ const makeUnsafe$7 = (mapUnsafe) => {
|
|
|
5000
5031
|
};
|
|
5001
5032
|
const Proto$13 = {
|
|
5002
5033
|
...PipeInspectableProto,
|
|
5003
|
-
[TypeId$
|
|
5034
|
+
[TypeId$36]: { _Services: (_) => _ },
|
|
5004
5035
|
toJSON() {
|
|
5005
5036
|
return {
|
|
5006
5037
|
_id: "Context",
|
|
@@ -5052,7 +5083,7 @@ const Proto$13 = {
|
|
|
5052
5083
|
* @category guards
|
|
5053
5084
|
* @since 2.0.0
|
|
5054
5085
|
*/
|
|
5055
|
-
const isContext = (u) => hasProperty(u, TypeId$
|
|
5086
|
+
const isContext = (u) => hasProperty(u, TypeId$36);
|
|
5056
5087
|
/**
|
|
5057
5088
|
* Checks whether the provided argument is a `Reference`.
|
|
5058
5089
|
*
|
|
@@ -5388,7 +5419,7 @@ const getOption = /* @__PURE__ */ dual(2, (self, service) => {
|
|
|
5388
5419
|
* @category combining
|
|
5389
5420
|
* @since 2.0.0
|
|
5390
5421
|
*/
|
|
5391
|
-
const merge$
|
|
5422
|
+
const merge$4 = /* @__PURE__ */ dual(2, (self, that) => {
|
|
5392
5423
|
if (self.mapUnsafe.size === 0) return that;
|
|
5393
5424
|
if (that.mapUnsafe.size === 0) return self;
|
|
5394
5425
|
return withMapUnsafe(self, (map) => {
|
|
@@ -5498,8 +5529,8 @@ const withMapUnsafe = (self, f) => {
|
|
|
5498
5529
|
const Reference = Service;
|
|
5499
5530
|
//#endregion
|
|
5500
5531
|
//#region ../../node_modules/.pnpm/effect@4.0.0-beta.102/node_modules/effect/dist/Duration.js
|
|
5501
|
-
const TypeId$
|
|
5502
|
-
const bigint0$
|
|
5532
|
+
const TypeId$35 = "~effect/time/Duration";
|
|
5533
|
+
const bigint0$2 = /* @__PURE__ */ BigInt(0);
|
|
5503
5534
|
const bigint1 = /* @__PURE__ */ BigInt(1);
|
|
5504
5535
|
const bigint1e3 = /* @__PURE__ */ BigInt(1e3);
|
|
5505
5536
|
const roundTiesAwayFromZero = (input) => BigInt(input < 0 ? Math.ceil(input - .5) : Math.floor(input + .5));
|
|
@@ -5563,7 +5594,7 @@ const fromInputUnsafe = (input) => {
|
|
|
5563
5594
|
}
|
|
5564
5595
|
case "object": {
|
|
5565
5596
|
if (input === null) break;
|
|
5566
|
-
if (TypeId$
|
|
5597
|
+
if (TypeId$35 in input) return input;
|
|
5567
5598
|
if (Array.isArray(input)) {
|
|
5568
5599
|
if (input.length !== 2 || !input.every(isNumber)) return invalid(input);
|
|
5569
5600
|
if (Number.isNaN(input[0]) || Number.isNaN(input[1])) return zero;
|
|
@@ -5595,7 +5626,7 @@ const zeroDurationValue = {
|
|
|
5595
5626
|
const infinityDurationValue = { _tag: "Infinity" };
|
|
5596
5627
|
const negativeInfinityDurationValue = { _tag: "NegativeInfinity" };
|
|
5597
5628
|
const DurationProto = {
|
|
5598
|
-
[TypeId$
|
|
5629
|
+
[TypeId$35]: TypeId$35,
|
|
5599
5630
|
[symbol$1]() {
|
|
5600
5631
|
return structure(this.value);
|
|
5601
5632
|
},
|
|
@@ -5651,7 +5682,7 @@ const make$34 = (input) => {
|
|
|
5651
5682
|
_tag: "Millis",
|
|
5652
5683
|
millis: input
|
|
5653
5684
|
};
|
|
5654
|
-
else if (input === bigint0$
|
|
5685
|
+
else if (input === bigint0$2) duration.value = zeroDurationValue;
|
|
5655
5686
|
else duration.value = {
|
|
5656
5687
|
_tag: "Nanos",
|
|
5657
5688
|
nanos: input
|
|
@@ -5673,7 +5704,7 @@ const make$34 = (input) => {
|
|
|
5673
5704
|
* @category guards
|
|
5674
5705
|
* @since 2.0.0
|
|
5675
5706
|
*/
|
|
5676
|
-
const isDuration = (u) => hasProperty(u, TypeId$
|
|
5707
|
+
const isDuration = (u) => hasProperty(u, TypeId$35);
|
|
5677
5708
|
/**
|
|
5678
5709
|
* Checks whether a Duration is finite (not infinite).
|
|
5679
5710
|
*
|
|
@@ -5708,7 +5739,7 @@ const isFinite$1 = (self) => self.value._tag !== "Infinity" && self.value._tag !
|
|
|
5708
5739
|
const isZero = (self) => {
|
|
5709
5740
|
switch (self.value._tag) {
|
|
5710
5741
|
case "Millis": return self.value.millis === 0;
|
|
5711
|
-
case "Nanos": return self.value.nanos === bigint0$
|
|
5742
|
+
case "Nanos": return self.value.nanos === bigint0$2;
|
|
5712
5743
|
case "Infinity":
|
|
5713
5744
|
case "NegativeInfinity": return false;
|
|
5714
5745
|
}
|
|
@@ -6741,7 +6772,7 @@ var Interrupt = class extends ReasonBase {
|
|
|
6741
6772
|
return isInterruptReason(that) && this.fiberId === that.fiberId && this.annotations === that.annotations;
|
|
6742
6773
|
}
|
|
6743
6774
|
[symbol$1]() {
|
|
6744
|
-
return combine(string$2(`${this._tag}:${this.fiberId}`))(random(this.annotations));
|
|
6775
|
+
return combine$1(string$2(`${this._tag}:${this.fiberId}`))(random(this.annotations));
|
|
6745
6776
|
}
|
|
6746
6777
|
};
|
|
6747
6778
|
/** @internal */
|
|
@@ -7171,7 +7202,7 @@ const fiberInterrupt = (self) => withFiber$1((fiber) => fiberInterruptAs(self, f
|
|
|
7171
7202
|
/** @internal */
|
|
7172
7203
|
const fiberInterruptAs = /* @__PURE__ */ dual((args) => hasProperty(args[0], FiberTypeId), (self, fiberId, annotations) => withFiber$1((parent) => {
|
|
7173
7204
|
let ann = fiberStackAnnotations(parent);
|
|
7174
|
-
ann = ann && annotations ? merge$
|
|
7205
|
+
ann = ann && annotations ? merge$4(ann, annotations) : ann ?? annotations;
|
|
7175
7206
|
self.interruptUnsafe(fiberId, ann);
|
|
7176
7207
|
return asVoid$1(fiberAwait(self));
|
|
7177
7208
|
}));
|
|
@@ -7531,6 +7562,8 @@ const exitAsVoidAll = (exits) => {
|
|
|
7531
7562
|
return failures.length === 0 ? exitVoid : exitFailCause(causeFromReasons(failures));
|
|
7532
7563
|
};
|
|
7533
7564
|
/** @internal */
|
|
7565
|
+
const service$1 = (service) => service;
|
|
7566
|
+
/** @internal */
|
|
7534
7567
|
const serviceOption$1 = (service) => withFiber$1((fiber) => succeed$5(getOption(fiber.context, service)));
|
|
7535
7568
|
/** @internal */
|
|
7536
7569
|
const updateContext$1 = /* @__PURE__ */ dual(2, (self, f) => withFiber$1((fiber) => {
|
|
@@ -7550,14 +7583,14 @@ const updateService = /* @__PURE__ */ dual(3, (self, service, f) => updateContex
|
|
|
7550
7583
|
return add(s, service, next);
|
|
7551
7584
|
}));
|
|
7552
7585
|
/** @internal */
|
|
7553
|
-
const context$
|
|
7586
|
+
const context$2 = () => getContext;
|
|
7554
7587
|
const getContext = /* @__PURE__ */ withFiber$1((fiber) => succeed$5(fiber.context));
|
|
7555
7588
|
/** @internal */
|
|
7556
7589
|
const contextWith$1 = (f) => withFiber$1((fiber) => f(fiber.context));
|
|
7557
7590
|
/** @internal */
|
|
7558
7591
|
const provideContext$1 = /* @__PURE__ */ dual(2, (self, context) => {
|
|
7559
7592
|
if (effectIsExit(self)) return self;
|
|
7560
|
-
return updateContext$1(self, merge$
|
|
7593
|
+
return updateContext$1(self, merge$4(context));
|
|
7561
7594
|
});
|
|
7562
7595
|
/** @internal */
|
|
7563
7596
|
const provideService$3 = function() {
|
|
@@ -8285,7 +8318,7 @@ const makeLatchUnsafe = (open) => new Latch(open ?? false);
|
|
|
8285
8318
|
const makeLatch = (open) => sync$2(() => makeLatchUnsafe(open));
|
|
8286
8319
|
/** @internal */
|
|
8287
8320
|
const withTracerEnabled$1 = /* @__PURE__ */ provideService$3(TracerEnabled);
|
|
8288
|
-
const bigint0 = /* @__PURE__ */ BigInt(0);
|
|
8321
|
+
const bigint0$1 = /* @__PURE__ */ BigInt(0);
|
|
8289
8322
|
const NoopSpanProto = {
|
|
8290
8323
|
_tag: "Span",
|
|
8291
8324
|
spanId: "noop",
|
|
@@ -8293,8 +8326,8 @@ const NoopSpanProto = {
|
|
|
8293
8326
|
sampled: false,
|
|
8294
8327
|
status: {
|
|
8295
8328
|
_tag: "Ended",
|
|
8296
|
-
startTime: bigint0,
|
|
8297
|
-
endTime: bigint0,
|
|
8329
|
+
startTime: bigint0$1,
|
|
8330
|
+
endTime: bigint0$1,
|
|
8298
8331
|
exit: exitVoid
|
|
8299
8332
|
},
|
|
8300
8333
|
attributes: /* @__PURE__ */ new Map(),
|
|
@@ -8727,6 +8760,38 @@ const hasInterruptsOnly = hasInterruptsOnly$1;
|
|
|
8727
8760
|
*/
|
|
8728
8761
|
const map$4 = causeMap;
|
|
8729
8762
|
/**
|
|
8763
|
+
* Merges two causes into a single cause whose `reasons` array is the union
|
|
8764
|
+
* of both inputs (de-duplicated by value equality).
|
|
8765
|
+
*
|
|
8766
|
+
* **When to use**
|
|
8767
|
+
*
|
|
8768
|
+
* Use to merge independent causes into one structured failure value.
|
|
8769
|
+
*
|
|
8770
|
+
* **Details**
|
|
8771
|
+
*
|
|
8772
|
+
* - Combining with `empty` returns the other cause unchanged.
|
|
8773
|
+
* - If the result is structurally equal to `self`, `self` is returned
|
|
8774
|
+
* (referential shortcut).
|
|
8775
|
+
*
|
|
8776
|
+
* **Example** (Combining two causes)
|
|
8777
|
+
*
|
|
8778
|
+
* ```ts
|
|
8779
|
+
* import { Cause } from "effect"
|
|
8780
|
+
*
|
|
8781
|
+
* const cause1 = Cause.fail("error1")
|
|
8782
|
+
* const cause2 = Cause.fail("error2")
|
|
8783
|
+
* const combined = Cause.combine(cause1, cause2)
|
|
8784
|
+
* console.log(combined.reasons.length) // 2
|
|
8785
|
+
* ```
|
|
8786
|
+
*
|
|
8787
|
+
* @see {@link fromReasons} — build a cause from an array of reasons
|
|
8788
|
+
* @see {@link empty} for the identity cause used when combining
|
|
8789
|
+
*
|
|
8790
|
+
* @category combining
|
|
8791
|
+
* @since 4.0.0
|
|
8792
|
+
*/
|
|
8793
|
+
const combine = causeCombine;
|
|
8794
|
+
/**
|
|
8730
8795
|
* Collapses a `Cause` into a single `unknown` value, picking the "most
|
|
8731
8796
|
* important" failure in this order:
|
|
8732
8797
|
*
|
|
@@ -9898,14 +9963,14 @@ const forkUnsafe = scopeForkUnsafe;
|
|
|
9898
9963
|
const close = scopeClose;
|
|
9899
9964
|
//#endregion
|
|
9900
9965
|
//#region ../../node_modules/.pnpm/effect@4.0.0-beta.102/node_modules/effect/dist/Layer.js
|
|
9901
|
-
const TypeId$
|
|
9966
|
+
const TypeId$33 = "~effect/Layer";
|
|
9902
9967
|
const MemoMapTypeId = "~effect/Layer/MemoMap";
|
|
9903
9968
|
const memoMapReuse = (entry, scope) => {
|
|
9904
9969
|
entry.observers++;
|
|
9905
9970
|
return andThen$1(scopeAddFinalizerExit(scope, (exit) => entry.finalizer(exit)), entry.effect);
|
|
9906
9971
|
};
|
|
9907
9972
|
const LayerProto = {
|
|
9908
|
-
[TypeId$
|
|
9973
|
+
[TypeId$33]: {
|
|
9909
9974
|
_ROut: identity,
|
|
9910
9975
|
_E: identity,
|
|
9911
9976
|
_RIn: identity
|
|
@@ -10561,6 +10626,50 @@ const mergeAllEffect = (layers, memoMap, scope) => {
|
|
|
10561
10626
|
* @since 2.0.0
|
|
10562
10627
|
*/
|
|
10563
10628
|
const mergeAll$1 = (...layers) => fromBuild((memoMap, scope) => mergeAllEffect(layers, memoMap, scope));
|
|
10629
|
+
/**
|
|
10630
|
+
* Merges this layer with another layer concurrently, producing a new layer with
|
|
10631
|
+
* combined input, error, and output types.
|
|
10632
|
+
*
|
|
10633
|
+
* **When to use**
|
|
10634
|
+
*
|
|
10635
|
+
* Use to combine an existing `Layer` with another `Layer` or an array of
|
|
10636
|
+
* layers while preserving pipeline style.
|
|
10637
|
+
*
|
|
10638
|
+
* **Details**
|
|
10639
|
+
*
|
|
10640
|
+
* This is a binary version of `mergeAll` that merges exactly two layers or one
|
|
10641
|
+
* layer with an array of layers. The layers are built concurrently and their
|
|
10642
|
+
* outputs are combined.
|
|
10643
|
+
*
|
|
10644
|
+
* **Example** (Merging two layers)
|
|
10645
|
+
*
|
|
10646
|
+
* ```ts
|
|
10647
|
+
* import { Context, Effect, Layer } from "effect"
|
|
10648
|
+
*
|
|
10649
|
+
* class Database extends Context.Service<Database, {
|
|
10650
|
+
* readonly query: (sql: string) => Effect.Effect<string>
|
|
10651
|
+
* }>()("Database") {}
|
|
10652
|
+
*
|
|
10653
|
+
* class Logger extends Context.Service<Logger, {
|
|
10654
|
+
* readonly log: (msg: string) => Effect.Effect<void>
|
|
10655
|
+
* }>()("Logger") {}
|
|
10656
|
+
*
|
|
10657
|
+
* const dbLayer = Layer.succeed(Database, {
|
|
10658
|
+
* query: Effect.fn("Database.query")((sql: string) => Effect.succeed("result"))
|
|
10659
|
+
* })
|
|
10660
|
+
* const loggerLayer = Layer.succeed(Logger, {
|
|
10661
|
+
* log: Effect.fn("Logger.log")((msg: string) => Effect.sync(() => console.log(msg)))
|
|
10662
|
+
* })
|
|
10663
|
+
*
|
|
10664
|
+
* const mergedLayer = Layer.merge(dbLayer, loggerLayer)
|
|
10665
|
+
* ```
|
|
10666
|
+
*
|
|
10667
|
+
* @see {@link mergeAll} for merging several layers at once
|
|
10668
|
+
*
|
|
10669
|
+
* @category zipping
|
|
10670
|
+
* @since 2.0.0
|
|
10671
|
+
*/
|
|
10672
|
+
const merge$3 = /* @__PURE__ */ dual(2, (self, that) => mergeAll$1(self, ...Array.isArray(that) ? that : [that]));
|
|
10564
10673
|
const provideWith = (self, that, f) => fromBuild((memoMap, scope) => flatMap$4(Array.isArray(that) ? mergeAllEffect(that, memoMap, scope) : that.build(memoMap, scope), (context) => self.build(memoMap, scope).pipe(provideContext$1(context), map$5((merged) => f(merged, context)))));
|
|
10565
10674
|
/**
|
|
10566
10675
|
* Feeds the output services of the dependency layer into the requirements of
|
|
@@ -10723,7 +10832,7 @@ const provide$2 = /* @__PURE__ */ dual(2, (self, that) => provideWith(self, that
|
|
|
10723
10832
|
* @category providing services
|
|
10724
10833
|
* @since 2.0.0
|
|
10725
10834
|
*/
|
|
10726
|
-
const provideMerge = /* @__PURE__ */ dual(2, (self, that) => provideWith(self, that, (self, that) => merge$
|
|
10835
|
+
const provideMerge = /* @__PURE__ */ dual(2, (self, that) => provideWith(self, that, (self, that) => merge$4(that, self)));
|
|
10727
10836
|
/**
|
|
10728
10837
|
* Constructs a layer dynamically based on the output of this layer.
|
|
10729
10838
|
*
|
|
@@ -10828,11 +10937,11 @@ const Clock = ClockRef;
|
|
|
10828
10937
|
//#endregion
|
|
10829
10938
|
//#region ../../node_modules/.pnpm/effect@4.0.0-beta.102/node_modules/effect/dist/internal/dateTime.js
|
|
10830
10939
|
/** @internal */
|
|
10831
|
-
const TypeId$
|
|
10940
|
+
const TypeId$32 = "~effect/time/DateTime";
|
|
10832
10941
|
/** @internal */
|
|
10833
10942
|
const TimeZoneTypeId = "~effect/time/DateTime/TimeZone";
|
|
10834
10943
|
const Proto$12 = {
|
|
10835
|
-
[TypeId$
|
|
10944
|
+
[TypeId$32]: TypeId$32,
|
|
10836
10945
|
pipe() {
|
|
10837
10946
|
return pipeArguments(this, arguments);
|
|
10838
10947
|
},
|
|
@@ -11077,7 +11186,7 @@ const matchEffect$1 = /* @__PURE__ */ dual(2, (self, options) => matchCauseEffec
|
|
|
11077
11186
|
}));
|
|
11078
11187
|
//#endregion
|
|
11079
11188
|
//#region ../../node_modules/.pnpm/effect@4.0.0-beta.102/node_modules/effect/dist/Schedule.js
|
|
11080
|
-
const TypeId$
|
|
11189
|
+
const TypeId$31 = "~effect/Schedule";
|
|
11081
11190
|
/**
|
|
11082
11191
|
* Context reference containing metadata for the currently running schedule step.
|
|
11083
11192
|
*
|
|
@@ -11102,7 +11211,7 @@ const CurrentMetadata = /* @__PURE__ */ Reference("effect/Schedule/CurrentMetada
|
|
|
11102
11211
|
elapsedSincePrevious: 0
|
|
11103
11212
|
}) });
|
|
11104
11213
|
const ScheduleProto = {
|
|
11105
|
-
[TypeId$
|
|
11214
|
+
[TypeId$31]: {
|
|
11106
11215
|
_Out: identity,
|
|
11107
11216
|
_In: identity,
|
|
11108
11217
|
_Env: identity
|
|
@@ -11131,7 +11240,7 @@ const ScheduleProto = {
|
|
|
11131
11240
|
* @category guards
|
|
11132
11241
|
* @since 2.0.0
|
|
11133
11242
|
*/
|
|
11134
|
-
const isSchedule = (u) => hasProperty(u, TypeId$
|
|
11243
|
+
const isSchedule = (u) => hasProperty(u, TypeId$31);
|
|
11135
11244
|
/**
|
|
11136
11245
|
* Creates a Schedule from a step function that returns a Pull.
|
|
11137
11246
|
*
|
|
@@ -11596,6 +11705,54 @@ const buildFromOptions = (options) => {
|
|
|
11596
11705
|
return schedule;
|
|
11597
11706
|
};
|
|
11598
11707
|
/**
|
|
11708
|
+
* Context reference for metric attributes applied from the current Effect
|
|
11709
|
+
* context.
|
|
11710
|
+
*
|
|
11711
|
+
* **When to use**
|
|
11712
|
+
*
|
|
11713
|
+
* Use to provide default attributes that should be merged into metric updates
|
|
11714
|
+
* and reads in a scoped part of a program.
|
|
11715
|
+
*
|
|
11716
|
+
* **Details**
|
|
11717
|
+
*
|
|
11718
|
+
* The default value is an empty attribute set. Metric reads and updates merge
|
|
11719
|
+
* these contextual attributes with the metric's own attributes to select the
|
|
11720
|
+
* metric series being accessed.
|
|
11721
|
+
*
|
|
11722
|
+
* **Example** (Providing current metric attributes)
|
|
11723
|
+
*
|
|
11724
|
+
* ```ts
|
|
11725
|
+
* import { Data, Effect, Metric } from "effect"
|
|
11726
|
+
*
|
|
11727
|
+
* class AttributesError extends Data.TaggedError("AttributesError")<{
|
|
11728
|
+
* readonly operation: string
|
|
11729
|
+
* }> {}
|
|
11730
|
+
*
|
|
11731
|
+
* const program = Effect.gen(function*() {
|
|
11732
|
+
* // Access current metric attributes
|
|
11733
|
+
* const attributes = yield* Metric.CurrentMetricAttributes
|
|
11734
|
+
* console.log("Current attributes:", attributes)
|
|
11735
|
+
*
|
|
11736
|
+
* // Set new attributes context
|
|
11737
|
+
* const newAttributes = { service: "api", version: "1.0" }
|
|
11738
|
+
* const result = yield* Effect.provideService(
|
|
11739
|
+
* Effect.gen(function*() {
|
|
11740
|
+
* const updatedAttributes = yield* Metric.CurrentMetricAttributes
|
|
11741
|
+
* return updatedAttributes
|
|
11742
|
+
* }),
|
|
11743
|
+
* Metric.CurrentMetricAttributes,
|
|
11744
|
+
* newAttributes
|
|
11745
|
+
* )
|
|
11746
|
+
*
|
|
11747
|
+
* return result
|
|
11748
|
+
* })
|
|
11749
|
+
* ```
|
|
11750
|
+
*
|
|
11751
|
+
* @category references
|
|
11752
|
+
* @since 4.0.0
|
|
11753
|
+
*/
|
|
11754
|
+
const CurrentMetricAttributes = /* @__PURE__ */ Reference("effect/Metric/CurrentMetricAttributes", { defaultValue: () => ({}) });
|
|
11755
|
+
/**
|
|
11599
11756
|
* Context reference for the metric registry in the current context.
|
|
11600
11757
|
*
|
|
11601
11758
|
* **When to use**
|
|
@@ -11622,6 +11779,348 @@ const buildFromOptions = (options) => {
|
|
|
11622
11779
|
* @since 4.0.0
|
|
11623
11780
|
*/
|
|
11624
11781
|
const MetricRegistry = /* @__PURE__ */ Reference("~effect/observability/Metric/MetricRegistryKey", { defaultValue: () => /* @__PURE__ */ new Map() });
|
|
11782
|
+
const TypeId$30 = "~effect/observability/Metric";
|
|
11783
|
+
var Metric$ = class {
|
|
11784
|
+
[TypeId$30] = TypeId$30;
|
|
11785
|
+
#metadataCache = /* @__PURE__ */ new WeakMap();
|
|
11786
|
+
#metadata;
|
|
11787
|
+
id;
|
|
11788
|
+
description;
|
|
11789
|
+
attributes;
|
|
11790
|
+
constructor(id, description, attributes) {
|
|
11791
|
+
this.id = id;
|
|
11792
|
+
this.description = description;
|
|
11793
|
+
this.attributes = attributes;
|
|
11794
|
+
}
|
|
11795
|
+
valueUnsafe(context) {
|
|
11796
|
+
return this.hook(context).get(context);
|
|
11797
|
+
}
|
|
11798
|
+
modifyUnsafe(input, context) {
|
|
11799
|
+
return this.hook(context).modify(input, context);
|
|
11800
|
+
}
|
|
11801
|
+
updateUnsafe(input, context) {
|
|
11802
|
+
return this.hook(context).update(input, context);
|
|
11803
|
+
}
|
|
11804
|
+
hook(context) {
|
|
11805
|
+
const extraAttributes = get$4(context, CurrentMetricAttributes);
|
|
11806
|
+
if (Object.keys(extraAttributes).length === 0) {
|
|
11807
|
+
if (isNotUndefined(this.#metadata)) return this.#metadata.hooks;
|
|
11808
|
+
this.#metadata = this.getOrCreate(context, this.attributes);
|
|
11809
|
+
return this.#metadata.hooks;
|
|
11810
|
+
}
|
|
11811
|
+
const mergedAttributes = mergeAttributes(this.attributes, extraAttributes);
|
|
11812
|
+
let metadata = this.#metadataCache.get(mergedAttributes);
|
|
11813
|
+
if (isNotUndefined(metadata)) return metadata.hooks;
|
|
11814
|
+
metadata = this.getOrCreate(context, mergedAttributes);
|
|
11815
|
+
this.#metadataCache.set(mergedAttributes, metadata);
|
|
11816
|
+
return metadata.hooks;
|
|
11817
|
+
}
|
|
11818
|
+
getOrCreate(context, attributes) {
|
|
11819
|
+
const key = makeKey(this, attributes);
|
|
11820
|
+
const registry = get$4(context, MetricRegistry);
|
|
11821
|
+
if (registry.has(key)) return registry.get(key);
|
|
11822
|
+
const hooks = this.createHooks();
|
|
11823
|
+
const meta = {
|
|
11824
|
+
id: this.id,
|
|
11825
|
+
type: this.type,
|
|
11826
|
+
description: this.description,
|
|
11827
|
+
attributes: attributesToRecord(attributes),
|
|
11828
|
+
hooks
|
|
11829
|
+
};
|
|
11830
|
+
registry.set(key, meta);
|
|
11831
|
+
return meta;
|
|
11832
|
+
}
|
|
11833
|
+
pipe() {
|
|
11834
|
+
return pipeArguments(this, arguments);
|
|
11835
|
+
}
|
|
11836
|
+
};
|
|
11837
|
+
const bigint0 = /* @__PURE__ */ BigInt(0);
|
|
11838
|
+
var CounterMetric = class extends Metric$ {
|
|
11839
|
+
type = "Counter";
|
|
11840
|
+
#bigint;
|
|
11841
|
+
#incremental;
|
|
11842
|
+
constructor(id, options) {
|
|
11843
|
+
super(id, options?.description, attributesToRecord(options?.attributes));
|
|
11844
|
+
this.#bigint = options?.bigint ?? false;
|
|
11845
|
+
this.#incremental = options?.incremental ?? false;
|
|
11846
|
+
}
|
|
11847
|
+
createHooks() {
|
|
11848
|
+
let count = this.#bigint ? bigint0 : 0;
|
|
11849
|
+
const canUpdate = this.#incremental ? this.#bigint ? (value) => value >= bigint0 : (value) => value >= 0 : (_value) => true;
|
|
11850
|
+
const update = (value) => {
|
|
11851
|
+
if (canUpdate(value)) count = count + value;
|
|
11852
|
+
};
|
|
11853
|
+
return makeHooks(() => ({
|
|
11854
|
+
count,
|
|
11855
|
+
incremental: this.#incremental
|
|
11856
|
+
}), update);
|
|
11857
|
+
}
|
|
11858
|
+
};
|
|
11859
|
+
var HistogramMetric = class extends Metric$ {
|
|
11860
|
+
type = "Histogram";
|
|
11861
|
+
#boundaries;
|
|
11862
|
+
constructor(id, options) {
|
|
11863
|
+
super(id, options?.description, attributesToRecord(options?.attributes));
|
|
11864
|
+
this.#boundaries = options.boundaries;
|
|
11865
|
+
}
|
|
11866
|
+
createHooks() {
|
|
11867
|
+
const bounds = this.#boundaries;
|
|
11868
|
+
const size = bounds.length;
|
|
11869
|
+
const values = new Uint32Array(size + 1);
|
|
11870
|
+
const boundaries = new Float64Array(size);
|
|
11871
|
+
let count = 0;
|
|
11872
|
+
let sum = 0;
|
|
11873
|
+
let min = Number.MAX_VALUE;
|
|
11874
|
+
let max = -Number.MAX_VALUE;
|
|
11875
|
+
map$6(sort$1(bounds, Number$5), (n, i) => {
|
|
11876
|
+
boundaries[i] = n;
|
|
11877
|
+
});
|
|
11878
|
+
const update = (value) => {
|
|
11879
|
+
let from = 0;
|
|
11880
|
+
let to = size;
|
|
11881
|
+
while (from !== to) {
|
|
11882
|
+
const mid = Math.floor(from + (to - from) / 2);
|
|
11883
|
+
if (value <= boundaries[mid]) to = mid;
|
|
11884
|
+
else from = mid;
|
|
11885
|
+
if (to === from + 1) if (value <= boundaries[from]) to = from;
|
|
11886
|
+
else from = to;
|
|
11887
|
+
}
|
|
11888
|
+
values[from] = values[from] + 1;
|
|
11889
|
+
count = count + 1;
|
|
11890
|
+
sum = sum + value;
|
|
11891
|
+
if (value < min) min = value;
|
|
11892
|
+
if (value > max) max = value;
|
|
11893
|
+
};
|
|
11894
|
+
const getBuckets = () => {
|
|
11895
|
+
const builder = allocate(size);
|
|
11896
|
+
let cumulated = 0;
|
|
11897
|
+
for (let i = 0; i < size; i++) {
|
|
11898
|
+
const boundary = boundaries[i];
|
|
11899
|
+
const value = values[i];
|
|
11900
|
+
cumulated = cumulated + value;
|
|
11901
|
+
builder[i] = [boundary, cumulated];
|
|
11902
|
+
}
|
|
11903
|
+
return builder;
|
|
11904
|
+
};
|
|
11905
|
+
return makeHooks(() => ({
|
|
11906
|
+
buckets: getBuckets(),
|
|
11907
|
+
count,
|
|
11908
|
+
min,
|
|
11909
|
+
max,
|
|
11910
|
+
sum
|
|
11911
|
+
}), update);
|
|
11912
|
+
}
|
|
11913
|
+
};
|
|
11914
|
+
var MetricTransform = class extends Metric$ {
|
|
11915
|
+
type;
|
|
11916
|
+
metric;
|
|
11917
|
+
valueUnsafe;
|
|
11918
|
+
updateUnsafe;
|
|
11919
|
+
modifyUnsafe;
|
|
11920
|
+
constructor(metric, valueUnsafe, updateUnsafe, modifyUnsafe) {
|
|
11921
|
+
super(metric.id, metric.description, metric.attributes);
|
|
11922
|
+
this.metric = metric;
|
|
11923
|
+
this.valueUnsafe = valueUnsafe;
|
|
11924
|
+
this.updateUnsafe = updateUnsafe;
|
|
11925
|
+
this.modifyUnsafe = modifyUnsafe;
|
|
11926
|
+
this.type = metric.type;
|
|
11927
|
+
}
|
|
11928
|
+
createHooks() {
|
|
11929
|
+
return this.metric.createHooks();
|
|
11930
|
+
}
|
|
11931
|
+
};
|
|
11932
|
+
/**
|
|
11933
|
+
* Represents a Counter metric that tracks cumulative numerical values over
|
|
11934
|
+
* time. Counters can be incremented and decremented and provide a running total
|
|
11935
|
+
* of changes.
|
|
11936
|
+
*
|
|
11937
|
+
* **Details**
|
|
11938
|
+
*
|
|
11939
|
+
* The optional `description` describes the counter, and `attributes` attach
|
|
11940
|
+
* dimensions to it. Set `bigint` to create a counter that accepts `bigint`
|
|
11941
|
+
* inputs. Set `incremental` to `true` to create a counter that can only ever be
|
|
11942
|
+
* incremented.
|
|
11943
|
+
*
|
|
11944
|
+
* **Example** (Creating counter metrics)
|
|
11945
|
+
*
|
|
11946
|
+
* ```ts
|
|
11947
|
+
* import { Data, Effect, Metric } from "effect"
|
|
11948
|
+
*
|
|
11949
|
+
* class CounterError extends Data.TaggedError("CounterError")<{
|
|
11950
|
+
* readonly operation: string
|
|
11951
|
+
* }> {}
|
|
11952
|
+
*
|
|
11953
|
+
* const program = Effect.gen(function*() {
|
|
11954
|
+
* // Create a basic counter for tracking requests
|
|
11955
|
+
* const requestCounter = Metric.counter("http_requests_total", {
|
|
11956
|
+
* description: "Total number of HTTP requests processed"
|
|
11957
|
+
* })
|
|
11958
|
+
*
|
|
11959
|
+
* // Create an incremental-only counter for events
|
|
11960
|
+
* const eventCounter = Metric.counter("events_processed", {
|
|
11961
|
+
* description: "Events processed (increment only)",
|
|
11962
|
+
* incremental: true
|
|
11963
|
+
* })
|
|
11964
|
+
*
|
|
11965
|
+
* // Create a bigint counter for large values
|
|
11966
|
+
* const bytesCounter = Metric.counter("bytes_transferred", {
|
|
11967
|
+
* description: "Total bytes transferred",
|
|
11968
|
+
* bigint: true,
|
|
11969
|
+
* attributes: { service: "file-transfer" }
|
|
11970
|
+
* })
|
|
11971
|
+
*
|
|
11972
|
+
* // Update counters with values
|
|
11973
|
+
* yield* Metric.update(requestCounter, 1) // Increment by 1
|
|
11974
|
+
* yield* Metric.update(requestCounter, 5) // Increment by 5 (total: 6)
|
|
11975
|
+
* yield* Metric.update(eventCounter, 1) // Increment by 1
|
|
11976
|
+
* yield* Metric.update(bytesCounter, 1024n) // Add 1024 bytes
|
|
11977
|
+
*
|
|
11978
|
+
* // Get current counter values
|
|
11979
|
+
* const requestValue = yield* Metric.value(requestCounter)
|
|
11980
|
+
* const eventValue = yield* Metric.value(eventCounter)
|
|
11981
|
+
* const bytesValue = yield* Metric.value(bytesCounter)
|
|
11982
|
+
*
|
|
11983
|
+
* return { requestValue, eventValue, bytesValue }
|
|
11984
|
+
* })
|
|
11985
|
+
* ```
|
|
11986
|
+
*
|
|
11987
|
+
* @category constructors
|
|
11988
|
+
* @since 2.0.0
|
|
11989
|
+
*/
|
|
11990
|
+
const counter = (name, options) => new CounterMetric(name, options);
|
|
11991
|
+
/**
|
|
11992
|
+
* Represents a `Histogram` metric that records observations into buckets.
|
|
11993
|
+
*
|
|
11994
|
+
* **When to use**
|
|
11995
|
+
*
|
|
11996
|
+
* Use when you need a metric for measuring the distribution of values within a
|
|
11997
|
+
* range.
|
|
11998
|
+
*
|
|
11999
|
+
* **Details**
|
|
12000
|
+
*
|
|
12001
|
+
* The optional `description` describes the histogram, and `attributes` attach
|
|
12002
|
+
* dimensions to it. The required `boundaries` option defines the histogram
|
|
12003
|
+
* bucket boundaries.
|
|
12004
|
+
*
|
|
12005
|
+
* **Example** (Creating histogram metrics)
|
|
12006
|
+
*
|
|
12007
|
+
* ```ts
|
|
12008
|
+
* import { Data, Effect, Metric } from "effect"
|
|
12009
|
+
*
|
|
12010
|
+
* class HistogramError extends Data.TaggedError("HistogramError")<{
|
|
12011
|
+
* readonly operation: string
|
|
12012
|
+
* }> {}
|
|
12013
|
+
*
|
|
12014
|
+
* const program = Effect.gen(function*() {
|
|
12015
|
+
* // Create a histogram for API response times
|
|
12016
|
+
* const responseTimeHistogram = Metric.histogram("api_response_time", {
|
|
12017
|
+
* description: "Distribution of API response times in milliseconds",
|
|
12018
|
+
* boundaries: Metric.linearBoundaries({ start: 0, width: 50, count: 10 })
|
|
12019
|
+
* // Creates buckets: 0-50ms, 50-100ms, 100-150ms, ..., 400-450ms, 450ms+
|
|
12020
|
+
* })
|
|
12021
|
+
*
|
|
12022
|
+
* // Create a histogram for request payload sizes
|
|
12023
|
+
* const payloadSizeHistogram = Metric.histogram("payload_size", {
|
|
12024
|
+
* description: "Distribution of request payload sizes in KB",
|
|
12025
|
+
* boundaries: Metric.exponentialBoundaries({ start: 1, factor: 2, count: 8 }),
|
|
12026
|
+
* // Creates exponential buckets: 1KB, 2KB, 4KB, 8KB, 16KB, 32KB, 64KB, 128KB+
|
|
12027
|
+
* attributes: { service: "api-gateway" }
|
|
12028
|
+
* })
|
|
12029
|
+
*
|
|
12030
|
+
* // Create a histogram with custom boundaries
|
|
12031
|
+
* const customHistogram = Metric.histogram("custom_metric", {
|
|
12032
|
+
* description: "Custom distribution metric",
|
|
12033
|
+
* boundaries: [0.1, 0.5, 1, 2.5, 5, 10, 25, 50, 100]
|
|
12034
|
+
* })
|
|
12035
|
+
*
|
|
12036
|
+
* // Record various response times
|
|
12037
|
+
* yield* Metric.update(responseTimeHistogram, 25) // Goes in 0-50ms bucket
|
|
12038
|
+
* yield* Metric.update(responseTimeHistogram, 75) // Goes in 50-100ms bucket
|
|
12039
|
+
* yield* Metric.update(responseTimeHistogram, 125) // Goes in 100-150ms bucket
|
|
12040
|
+
* yield* Metric.update(responseTimeHistogram, 200) // Goes in 150-200ms bucket
|
|
12041
|
+
* yield* Metric.update(responseTimeHistogram, 75) // Another 50-100ms
|
|
12042
|
+
*
|
|
12043
|
+
* // Record payload sizes
|
|
12044
|
+
* yield* Metric.update(payloadSizeHistogram, 3) // Goes in 2-4KB bucket
|
|
12045
|
+
* yield* Metric.update(payloadSizeHistogram, 15) // Goes in 8-16KB bucket
|
|
12046
|
+
* yield* Metric.update(payloadSizeHistogram, 0.5) // Goes in 0-1KB bucket
|
|
12047
|
+
*
|
|
12048
|
+
* // Get histogram state with distribution data
|
|
12049
|
+
* const responseTimeState = yield* Metric.value(responseTimeHistogram)
|
|
12050
|
+
* const payloadSizeState = yield* Metric.value(payloadSizeHistogram)
|
|
12051
|
+
*
|
|
12052
|
+
* // responseTimeState will contain:
|
|
12053
|
+
* // - buckets: [[50, 1], [100, 3], [150, 4], [200, 5], ...]
|
|
12054
|
+
* // - count: 5, min: 25, max: 200, sum: 500
|
|
12055
|
+
* // - Useful for calculating percentiles, averages, etc.
|
|
12056
|
+
*
|
|
12057
|
+
* return { responseTimeState, payloadSizeState }
|
|
12058
|
+
* })
|
|
12059
|
+
* ```
|
|
12060
|
+
*
|
|
12061
|
+
* @category constructors
|
|
12062
|
+
* @since 2.0.0
|
|
12063
|
+
*/
|
|
12064
|
+
const histogram = (name, options) => new HistogramMetric(name, options);
|
|
12065
|
+
/**
|
|
12066
|
+
* Returns a new metric that applies the specified attributes to all operations.
|
|
12067
|
+
*
|
|
12068
|
+
* **Details**
|
|
12069
|
+
*
|
|
12070
|
+
* Attributes are key-value pairs that provide additional context for metrics,
|
|
12071
|
+
* enabling filtering, grouping, and more detailed analysis. Each combination
|
|
12072
|
+
* of attribute values creates a separate metric series.
|
|
12073
|
+
*
|
|
12074
|
+
* **Example** (Applying metric attributes)
|
|
12075
|
+
*
|
|
12076
|
+
* ```ts
|
|
12077
|
+
* import { Effect, Metric } from "effect"
|
|
12078
|
+
*
|
|
12079
|
+
* const requestCounter = Metric.counter("http_requests_total", {
|
|
12080
|
+
* description: "Total HTTP requests"
|
|
12081
|
+
* })
|
|
12082
|
+
*
|
|
12083
|
+
* // Create tagged versions of the metric
|
|
12084
|
+
* const getRequests = Metric.withAttributes(requestCounter, {
|
|
12085
|
+
* method: "GET",
|
|
12086
|
+
* endpoint: "/api/users"
|
|
12087
|
+
* })
|
|
12088
|
+
*
|
|
12089
|
+
* const postRequests = Metric.withAttributes(requestCounter, {
|
|
12090
|
+
* method: "POST",
|
|
12091
|
+
* endpoint: "/api/users"
|
|
12092
|
+
* })
|
|
12093
|
+
*
|
|
12094
|
+
* const program = Effect.gen(function*() {
|
|
12095
|
+
* // These will be tracked as separate metric series
|
|
12096
|
+
* yield* Metric.update(getRequests, 1) // http_requests_total{method="GET", endpoint="/api/users"}
|
|
12097
|
+
* yield* Metric.update(postRequests, 1) // http_requests_total{method="POST", endpoint="/api/users"}
|
|
12098
|
+
* yield* Metric.update(getRequests, 1) // Increments the GET counter
|
|
12099
|
+
*
|
|
12100
|
+
* // You can also chain attributes
|
|
12101
|
+
* const taggedMetric = requestCounter.pipe(
|
|
12102
|
+
* Metric.withAttributes({ service: "user-api" }),
|
|
12103
|
+
* Metric.withAttributes({ version: "v1" })
|
|
12104
|
+
* )
|
|
12105
|
+
*
|
|
12106
|
+
* yield* Metric.update(taggedMetric, 1) // http_requests_total{service="user-api", version="v1"}
|
|
12107
|
+
* })
|
|
12108
|
+
*
|
|
12109
|
+
* // When taking snapshots, each attribute combination appears as a separate metric
|
|
12110
|
+
* const viewMetrics = Effect.gen(function*() {
|
|
12111
|
+
* const snapshots = yield* Metric.snapshot
|
|
12112
|
+
* for (const metric of snapshots) {
|
|
12113
|
+
* if (metric.id === "http_requests_total") {
|
|
12114
|
+
* console.log(`${metric.id}`, metric.attributes, metric.state)
|
|
12115
|
+
* }
|
|
12116
|
+
* }
|
|
12117
|
+
* })
|
|
12118
|
+
* ```
|
|
12119
|
+
*
|
|
12120
|
+
* @category Attributes
|
|
12121
|
+
* @since 4.0.0
|
|
12122
|
+
*/
|
|
12123
|
+
const withAttributes = /* @__PURE__ */ dual(2, (self, attributes) => new MetricTransform(self, (context) => self.valueUnsafe(addAttributesToContext(context, attributes)), (input, context) => self.updateUnsafe(input, addAttributesToContext(context, attributes)), (input, context) => self.modifyUnsafe(input, addAttributesToContext(context, attributes))));
|
|
11625
12124
|
/**
|
|
11626
12125
|
* Captures a snapshot of all registered metrics synchronously using the provided
|
|
11627
12126
|
* service context.
|
|
@@ -11698,6 +12197,41 @@ const snapshotUnsafe = (context) => {
|
|
|
11698
12197
|
state: hooks.get(context)
|
|
11699
12198
|
}));
|
|
11700
12199
|
};
|
|
12200
|
+
function makeKey(metric, attributes) {
|
|
12201
|
+
let key = `${metric.type}:${metric.id}`;
|
|
12202
|
+
if (isNotUndefined(metric.description)) key += `:${metric.description}`;
|
|
12203
|
+
if (isNotUndefined(attributes)) key += `:${serializeAttributes(attributes)}`;
|
|
12204
|
+
return key;
|
|
12205
|
+
}
|
|
12206
|
+
function makeHooks(get, update, modify) {
|
|
12207
|
+
return {
|
|
12208
|
+
get,
|
|
12209
|
+
update,
|
|
12210
|
+
modify: modify ?? update
|
|
12211
|
+
};
|
|
12212
|
+
}
|
|
12213
|
+
function serializeAttributes(attributes) {
|
|
12214
|
+
return serializeEntries(Array.isArray(attributes) ? attributes : Object.entries(attributes));
|
|
12215
|
+
}
|
|
12216
|
+
function serializeEntries(entries) {
|
|
12217
|
+
return entries.map(([key, value]) => `${key}=${value}`).join(",");
|
|
12218
|
+
}
|
|
12219
|
+
function mergeAttributes(self, other) {
|
|
12220
|
+
return {
|
|
12221
|
+
...attributesToRecord(self),
|
|
12222
|
+
...attributesToRecord(other)
|
|
12223
|
+
};
|
|
12224
|
+
}
|
|
12225
|
+
function attributesToRecord(attributes) {
|
|
12226
|
+
if (isNotUndefined(attributes) && Array.isArray(attributes)) return attributes.reduce((acc, [key, value]) => {
|
|
12227
|
+
assignProperty(acc, key, value);
|
|
12228
|
+
return acc;
|
|
12229
|
+
}, {});
|
|
12230
|
+
return attributes;
|
|
12231
|
+
}
|
|
12232
|
+
function addAttributesToContext(context, attributes) {
|
|
12233
|
+
return add(context, CurrentMetricAttributes, mergeAttributes(get$4(context, CurrentMetricAttributes), attributes));
|
|
12234
|
+
}
|
|
11701
12235
|
//#endregion
|
|
11702
12236
|
//#region ../../node_modules/.pnpm/effect@4.0.0-beta.102/node_modules/effect/dist/Effect.js
|
|
11703
12237
|
/**
|
|
@@ -13589,7 +14123,7 @@ const matchEffect = matchEffect$2;
|
|
|
13589
14123
|
* @category environment
|
|
13590
14124
|
* @since 2.0.0
|
|
13591
14125
|
*/
|
|
13592
|
-
const context = context$
|
|
14126
|
+
const context$1 = context$2;
|
|
13593
14127
|
/**
|
|
13594
14128
|
* Transforms the current context using the provided function.
|
|
13595
14129
|
*
|
|
@@ -13722,6 +14256,30 @@ const provide = provide$1;
|
|
|
13722
14256
|
*/
|
|
13723
14257
|
const provideContext = provideContext$1;
|
|
13724
14258
|
/**
|
|
14259
|
+
* Accesses a service from the context.
|
|
14260
|
+
*
|
|
14261
|
+
* **Example** (Accessing a required service)
|
|
14262
|
+
*
|
|
14263
|
+
* ```ts
|
|
14264
|
+
* import { Context, Effect } from "effect"
|
|
14265
|
+
*
|
|
14266
|
+
* interface Database {
|
|
14267
|
+
* readonly query: (sql: string) => Effect.Effect<string>
|
|
14268
|
+
* }
|
|
14269
|
+
*
|
|
14270
|
+
* const Database = Context.Service<Database>("Database")
|
|
14271
|
+
*
|
|
14272
|
+
* const program = Effect.gen(function*() {
|
|
14273
|
+
* const db = yield* Effect.service(Database)
|
|
14274
|
+
* return yield* db.query("SELECT * FROM users")
|
|
14275
|
+
* })
|
|
14276
|
+
* ```
|
|
14277
|
+
*
|
|
14278
|
+
* @category context
|
|
14279
|
+
* @since 4.0.0
|
|
14280
|
+
*/
|
|
14281
|
+
const service = service$1;
|
|
14282
|
+
/**
|
|
13725
14283
|
* Optionally accesses a service from the environment.
|
|
13726
14284
|
*
|
|
13727
14285
|
* **When to use**
|
|
@@ -54752,7 +55310,7 @@ const mapEffectConcurrent = (self, f, options) => fromTransformBracket(fnUntrace
|
|
|
54752
55310
|
const concurrencyN = options.concurrency === "unbounded" ? Number.MAX_SAFE_INTEGER : options.concurrency;
|
|
54753
55311
|
const queue = yield* bounded(0);
|
|
54754
55312
|
yield* addFinalizer(forkedScope, shutdown(queue));
|
|
54755
|
-
const runFork = runForkWith(yield* context());
|
|
55313
|
+
const runFork = runForkWith(yield* context$1());
|
|
54756
55314
|
const trackFiber = runIn(forkedScope);
|
|
54757
55315
|
if (options.unordered) {
|
|
54758
55316
|
const semaphore = makeUnsafe$2(concurrencyN);
|
|
@@ -56623,7 +57181,7 @@ const flatten = /* @__PURE__ */ dual((args) => isStream(args[0]), (self, options
|
|
|
56623
57181
|
* @category sequencing
|
|
56624
57182
|
* @since 2.0.0
|
|
56625
57183
|
*/
|
|
56626
|
-
const concat = /* @__PURE__ */ dual(2, (self, that) => flatten(fromArray([self, that])));
|
|
57184
|
+
const concat$1 = /* @__PURE__ */ dual(2, (self, that) => flatten(fromArray([self, that])));
|
|
56627
57185
|
/**
|
|
56628
57186
|
* Merges two streams, emitting elements from both as they arrive.
|
|
56629
57187
|
*
|
|
@@ -57102,7 +57660,7 @@ const toReadableStreamWith = /* @__PURE__ */ dual((args) => isStream(args[0]), (
|
|
|
57102
57660
|
* @category destructors
|
|
57103
57661
|
* @since 2.0.0
|
|
57104
57662
|
*/
|
|
57105
|
-
const toReadableStreamEffect = /* @__PURE__ */ dual((args) => isStream(args[0]), (self, options) => map$3(context(), (context) => toReadableStreamWith(self, context, options)));
|
|
57663
|
+
const toReadableStreamEffect = /* @__PURE__ */ dual((args) => isStream(args[0]), (self, options) => map$3(context$1(), (context) => toReadableStreamWith(self, context, options)));
|
|
57106
57664
|
//#endregion
|
|
57107
57665
|
//#region ../../node_modules/.pnpm/effect@4.0.0-beta.102/node_modules/effect/dist/FileSystem.js
|
|
57108
57666
|
/**
|
|
@@ -59911,7 +60469,7 @@ const SpanNameGenerator = /* @__PURE__ */ Reference("effect/http/HttpClient/Span
|
|
|
59911
60469
|
* @category layers
|
|
59912
60470
|
* @since 4.0.0
|
|
59913
60471
|
*/
|
|
59914
|
-
const layerMergedContext = (effect$2) => effect(HttpClient)(contextWith((context) => map$3(effect$2, (client) => transformResponse(client, updateContext((input) => merge$
|
|
60472
|
+
const layerMergedContext = (effect$2) => effect(HttpClient)(contextWith((context) => map$3(effect$2, (client) => transformResponse(client, updateContext((input) => merge$4(context, input))))));
|
|
59915
60473
|
const responseRegistry = /* @__PURE__ */ (() => {
|
|
59916
60474
|
if ("FinalizationRegistry" in globalThis && globalThis.FinalizationRegistry) {
|
|
59917
60475
|
const registry = /* @__PURE__ */ new FinalizationRegistry((controller) => {
|
|
@@ -60452,7 +61010,7 @@ const runImpl = (self, effect, options) => withFiber((parent) => {
|
|
|
60452
61010
|
* @category combinators
|
|
60453
61011
|
* @since 2.0.0
|
|
60454
61012
|
*/
|
|
60455
|
-
const runtime = (self) => () => map$3(context(), (services) => {
|
|
61013
|
+
const runtime = (self) => () => map$3(context$1(), (services) => {
|
|
60456
61014
|
const runFork = runForkWith(services);
|
|
60457
61015
|
return (effect, options) => {
|
|
60458
61016
|
if (self.state._tag === "Closed") return constInterruptedFiber();
|
|
@@ -60574,7 +61132,7 @@ const layerFlusher = /* @__PURE__ */ sync$1(Flusher, () => {
|
|
|
60574
61132
|
* @since 4.0.0
|
|
60575
61133
|
*/
|
|
60576
61134
|
const make$8 = /* @__PURE__ */ fnUntraced(function* (options) {
|
|
60577
|
-
const services = yield* context();
|
|
61135
|
+
const services = yield* context$1();
|
|
60578
61136
|
const clock = get$4(services, Clock);
|
|
60579
61137
|
const scope = get$4(services, Scope);
|
|
60580
61138
|
const exportInterval = max(fromInputUnsafe(options.exportInterval), zero);
|
|
@@ -60743,6 +61301,537 @@ const unknownToAttributeValue = (value) => {
|
|
|
60743
61301
|
}
|
|
60744
61302
|
};
|
|
60745
61303
|
//#endregion
|
|
61304
|
+
//#region ../../node_modules/.pnpm/effect@4.0.0-beta.102/node_modules/effect/dist/unstable/observability/internal/protobuf.js
|
|
61305
|
+
/**
|
|
61306
|
+
* Low-level protobuf wire format encoding utilities.
|
|
61307
|
+
*
|
|
61308
|
+
* Protobuf wire types:
|
|
61309
|
+
* - 0: Varint (int32, int64, uint32, uint64, sint32, sint64, bool, enum)
|
|
61310
|
+
* - 1: 64-bit (fixed64, sfixed64, double)
|
|
61311
|
+
* - 2: Length-delimited (string, bytes, embedded messages, packed repeated fields)
|
|
61312
|
+
* - 5: 32-bit (fixed32, sfixed32, float)
|
|
61313
|
+
*/
|
|
61314
|
+
const WireType = {
|
|
61315
|
+
Varint: 0,
|
|
61316
|
+
Fixed64: 1,
|
|
61317
|
+
LengthDelimited: 2,
|
|
61318
|
+
Fixed32: 5
|
|
61319
|
+
};
|
|
61320
|
+
/**
|
|
61321
|
+
* Encodes a field tag (field number + wire type)
|
|
61322
|
+
*/
|
|
61323
|
+
const encodeTag = (fieldNumber, wireType) => fieldNumber << 3 | wireType;
|
|
61324
|
+
/**
|
|
61325
|
+
* Encodes a varint (variable-length integer)
|
|
61326
|
+
*
|
|
61327
|
+
* @internal
|
|
61328
|
+
*/
|
|
61329
|
+
const encodeVarint = (value) => {
|
|
61330
|
+
const bytes = [];
|
|
61331
|
+
let n = typeof value === "bigint" ? value : BigInt(value);
|
|
61332
|
+
while (n > BigInt(127)) {
|
|
61333
|
+
bytes.push(Number(n & BigInt(127)) | 128);
|
|
61334
|
+
n >>= BigInt(7);
|
|
61335
|
+
}
|
|
61336
|
+
bytes.push(Number(n));
|
|
61337
|
+
return new Uint8Array(bytes);
|
|
61338
|
+
};
|
|
61339
|
+
/**
|
|
61340
|
+
* Encodes a 64-bit fixed value (little-endian)
|
|
61341
|
+
*
|
|
61342
|
+
* @internal
|
|
61343
|
+
*/
|
|
61344
|
+
const encodeFixed64 = (value) => {
|
|
61345
|
+
const bytes = new Uint8Array(8);
|
|
61346
|
+
new DataView(bytes.buffer).setBigUint64(0, value, true);
|
|
61347
|
+
return bytes;
|
|
61348
|
+
};
|
|
61349
|
+
/**
|
|
61350
|
+
* Encodes a 32-bit fixed value (little-endian)
|
|
61351
|
+
*
|
|
61352
|
+
* @internal
|
|
61353
|
+
*/
|
|
61354
|
+
const encodeFixed32 = (value) => {
|
|
61355
|
+
const bytes = new Uint8Array(4);
|
|
61356
|
+
new DataView(bytes.buffer).setUint32(0, value, true);
|
|
61357
|
+
return bytes;
|
|
61358
|
+
};
|
|
61359
|
+
/**
|
|
61360
|
+
* Encodes a double (64-bit float, little-endian)
|
|
61361
|
+
*
|
|
61362
|
+
* @internal
|
|
61363
|
+
*/
|
|
61364
|
+
const encodeDouble = (value) => {
|
|
61365
|
+
const bytes = new Uint8Array(8);
|
|
61366
|
+
new DataView(bytes.buffer).setFloat64(0, value, true);
|
|
61367
|
+
return bytes;
|
|
61368
|
+
};
|
|
61369
|
+
/**
|
|
61370
|
+
* Encodes a string to UTF-8 bytes
|
|
61371
|
+
*
|
|
61372
|
+
* @internal
|
|
61373
|
+
*/
|
|
61374
|
+
const encodeString = (value) => new TextEncoder().encode(value);
|
|
61375
|
+
/**
|
|
61376
|
+
* Encodes bytes as a hex string to Uint8Array
|
|
61377
|
+
*
|
|
61378
|
+
* @internal
|
|
61379
|
+
*/
|
|
61380
|
+
const encodeHexBytes = (hex) => {
|
|
61381
|
+
const bytes = new Uint8Array(hex.length / 2);
|
|
61382
|
+
for (let i = 0; i < hex.length; i += 2) bytes[i / 2] = parseInt(hex.slice(i, i + 2), 16);
|
|
61383
|
+
return bytes;
|
|
61384
|
+
};
|
|
61385
|
+
/**
|
|
61386
|
+
* Concatenates multiple Uint8Arrays
|
|
61387
|
+
*
|
|
61388
|
+
* @internal
|
|
61389
|
+
*/
|
|
61390
|
+
const concat = (...arrays) => {
|
|
61391
|
+
const totalLength = arrays.reduce((sum, arr) => sum + arr.length, 0);
|
|
61392
|
+
const result = new Uint8Array(totalLength);
|
|
61393
|
+
let offset = 0;
|
|
61394
|
+
for (const arr of arrays) {
|
|
61395
|
+
result.set(arr, offset);
|
|
61396
|
+
offset += arr.length;
|
|
61397
|
+
}
|
|
61398
|
+
return result;
|
|
61399
|
+
};
|
|
61400
|
+
/**
|
|
61401
|
+
* Encodes a varint field
|
|
61402
|
+
*
|
|
61403
|
+
* @internal
|
|
61404
|
+
*/
|
|
61405
|
+
const varintField = (fieldNumber, value) => concat(encodeVarint(encodeTag(fieldNumber, WireType.Varint)), encodeVarint(value));
|
|
61406
|
+
/**
|
|
61407
|
+
* Encodes a bool field
|
|
61408
|
+
*
|
|
61409
|
+
* @internal
|
|
61410
|
+
*/
|
|
61411
|
+
const boolField = (fieldNumber, value) => varintField(fieldNumber, value ? 1 : 0);
|
|
61412
|
+
/**
|
|
61413
|
+
* Encodes a fixed64 field
|
|
61414
|
+
*
|
|
61415
|
+
* @internal
|
|
61416
|
+
*/
|
|
61417
|
+
const fixed64Field = (fieldNumber, value) => concat(encodeVarint(encodeTag(fieldNumber, WireType.Fixed64)), encodeFixed64(value));
|
|
61418
|
+
/**
|
|
61419
|
+
* Encodes a fixed32 field
|
|
61420
|
+
*
|
|
61421
|
+
* @internal
|
|
61422
|
+
*/
|
|
61423
|
+
const fixed32Field = (fieldNumber, value) => concat(encodeVarint(encodeTag(fieldNumber, WireType.Fixed32)), encodeFixed32(value));
|
|
61424
|
+
/**
|
|
61425
|
+
* Encodes a double field
|
|
61426
|
+
*
|
|
61427
|
+
* @internal
|
|
61428
|
+
*/
|
|
61429
|
+
const doubleField = (fieldNumber, value) => concat(encodeVarint(encodeTag(fieldNumber, WireType.Fixed64)), encodeDouble(value));
|
|
61430
|
+
/**
|
|
61431
|
+
* Encodes a length-delimited field (bytes, string, embedded message)
|
|
61432
|
+
*
|
|
61433
|
+
* @internal
|
|
61434
|
+
*/
|
|
61435
|
+
const lengthDelimitedField = (fieldNumber, value) => concat(encodeVarint(encodeTag(fieldNumber, WireType.LengthDelimited)), encodeVarint(value.length), value);
|
|
61436
|
+
/**
|
|
61437
|
+
* Encodes a string field
|
|
61438
|
+
*
|
|
61439
|
+
* @internal
|
|
61440
|
+
*/
|
|
61441
|
+
const stringField = (fieldNumber, value) => lengthDelimitedField(fieldNumber, encodeString(value));
|
|
61442
|
+
/**
|
|
61443
|
+
* Encodes a bytes field from hex string
|
|
61444
|
+
*
|
|
61445
|
+
* @internal
|
|
61446
|
+
*/
|
|
61447
|
+
const bytesFieldFromHex = (fieldNumber, hex) => lengthDelimitedField(fieldNumber, encodeHexBytes(hex));
|
|
61448
|
+
/**
|
|
61449
|
+
* Encodes an embedded message field
|
|
61450
|
+
*
|
|
61451
|
+
* @internal
|
|
61452
|
+
*/
|
|
61453
|
+
const messageField = (fieldNumber, message) => lengthDelimitedField(fieldNumber, message);
|
|
61454
|
+
/**
|
|
61455
|
+
* Encodes repeated fields
|
|
61456
|
+
*
|
|
61457
|
+
* @internal
|
|
61458
|
+
*/
|
|
61459
|
+
const repeatedField = (fieldNumber, values, encode) => concat(...values.map((v) => messageField(fieldNumber, encode(v))));
|
|
61460
|
+
/**
|
|
61461
|
+
* Helper to conditionally encode a string field if non-empty
|
|
61462
|
+
*
|
|
61463
|
+
* @internal
|
|
61464
|
+
*/
|
|
61465
|
+
const optionalStringField = (fieldNumber, value) => value !== void 0 && value !== "" ? stringField(fieldNumber, value) : new Uint8Array(0);
|
|
61466
|
+
//#endregion
|
|
61467
|
+
//#region ../../node_modules/.pnpm/effect@4.0.0-beta.102/node_modules/effect/dist/unstable/observability/internal/otlpProtobuf.js
|
|
61468
|
+
/**
|
|
61469
|
+
* OTLP Protobuf encoding for traces, metrics, and logs.
|
|
61470
|
+
*
|
|
61471
|
+
* Implements the protobuf wire format according to:
|
|
61472
|
+
* https://github.com/open-telemetry/opentelemetry-proto
|
|
61473
|
+
*/
|
|
61474
|
+
/**
|
|
61475
|
+
* Encodes an AnyValue message.
|
|
61476
|
+
*
|
|
61477
|
+
* message AnyValue {
|
|
61478
|
+
* oneof value {
|
|
61479
|
+
* string string_value = 1;
|
|
61480
|
+
* bool bool_value = 2;
|
|
61481
|
+
* int64 int_value = 3;
|
|
61482
|
+
* double double_value = 4;
|
|
61483
|
+
* ArrayValue array_value = 5;
|
|
61484
|
+
* KeyValueList kvlist_value = 6;
|
|
61485
|
+
* bytes bytes_value = 7;
|
|
61486
|
+
* }
|
|
61487
|
+
* }
|
|
61488
|
+
*
|
|
61489
|
+
* @internal
|
|
61490
|
+
*/
|
|
61491
|
+
const encodeAnyValue = (value) => {
|
|
61492
|
+
if (value.stringValue !== void 0 && value.stringValue !== null) return stringField(1, value.stringValue);
|
|
61493
|
+
if (value.boolValue !== void 0 && value.boolValue !== null) return boolField(2, value.boolValue);
|
|
61494
|
+
if (value.intValue !== void 0 && value.intValue !== null) return varintField(3, BigInt(value.intValue));
|
|
61495
|
+
if (value.doubleValue !== void 0 && value.doubleValue !== null) return doubleField(4, value.doubleValue);
|
|
61496
|
+
if (value.arrayValue !== void 0) return messageField(5, encodeArrayValue(value.arrayValue));
|
|
61497
|
+
if (value.kvlistValue !== void 0) return messageField(6, encodeKeyValueList(value.kvlistValue));
|
|
61498
|
+
if (value.bytesValue !== void 0) return lengthDelimitedField(7, value.bytesValue);
|
|
61499
|
+
return new Uint8Array(0);
|
|
61500
|
+
};
|
|
61501
|
+
/**
|
|
61502
|
+
* Encodes an ArrayValue message.
|
|
61503
|
+
*
|
|
61504
|
+
* message ArrayValue {
|
|
61505
|
+
* repeated AnyValue values = 1;
|
|
61506
|
+
* }
|
|
61507
|
+
*
|
|
61508
|
+
* @internal
|
|
61509
|
+
*/
|
|
61510
|
+
const encodeArrayValue = (value) => repeatedField(1, value.values, encodeAnyValue);
|
|
61511
|
+
/**
|
|
61512
|
+
* Encodes a KeyValueList message.
|
|
61513
|
+
*
|
|
61514
|
+
* message KeyValueList {
|
|
61515
|
+
* repeated KeyValue values = 1;
|
|
61516
|
+
* }
|
|
61517
|
+
*
|
|
61518
|
+
* @internal
|
|
61519
|
+
*/
|
|
61520
|
+
const encodeKeyValueList = (value) => repeatedField(1, value.values, encodeKeyValue);
|
|
61521
|
+
/**
|
|
61522
|
+
* Encodes a KeyValue message.
|
|
61523
|
+
*
|
|
61524
|
+
* message KeyValue {
|
|
61525
|
+
* string key = 1;
|
|
61526
|
+
* AnyValue value = 2;
|
|
61527
|
+
* }
|
|
61528
|
+
*
|
|
61529
|
+
* @internal
|
|
61530
|
+
*/
|
|
61531
|
+
const encodeKeyValue = (kv) => concat(stringField(1, kv.key), messageField(2, encodeAnyValue(kv.value)));
|
|
61532
|
+
/**
|
|
61533
|
+
* Encodes an InstrumentationScope message.
|
|
61534
|
+
*
|
|
61535
|
+
* message InstrumentationScope {
|
|
61536
|
+
* string name = 1;
|
|
61537
|
+
* string version = 2;
|
|
61538
|
+
* repeated KeyValue attributes = 3;
|
|
61539
|
+
* uint32 dropped_attributes_count = 4;
|
|
61540
|
+
* }
|
|
61541
|
+
*
|
|
61542
|
+
* @internal
|
|
61543
|
+
*/
|
|
61544
|
+
const encodeInstrumentationScope = (scope) => concat(stringField(1, scope.name), optionalStringField(2, scope.version), scope.attributes ? repeatedField(3, scope.attributes, encodeKeyValue) : new Uint8Array(0), scope.droppedAttributesCount ? varintField(4, scope.droppedAttributesCount) : new Uint8Array(0));
|
|
61545
|
+
/**
|
|
61546
|
+
* Encodes a Resource message.
|
|
61547
|
+
*
|
|
61548
|
+
* message Resource {
|
|
61549
|
+
* repeated KeyValue attributes = 1;
|
|
61550
|
+
* uint32 dropped_attributes_count = 2;
|
|
61551
|
+
* }
|
|
61552
|
+
*
|
|
61553
|
+
* @internal
|
|
61554
|
+
*/
|
|
61555
|
+
const encodeResource = (resource) => concat(repeatedField(1, resource.attributes, encodeKeyValue), resource.droppedAttributesCount > 0 ? varintField(2, resource.droppedAttributesCount) : new Uint8Array(0));
|
|
61556
|
+
/**
|
|
61557
|
+
* Encodes a Status message.
|
|
61558
|
+
*
|
|
61559
|
+
* message Status {
|
|
61560
|
+
* string message = 2;
|
|
61561
|
+
* StatusCode code = 3;
|
|
61562
|
+
* }
|
|
61563
|
+
*
|
|
61564
|
+
* @internal
|
|
61565
|
+
*/
|
|
61566
|
+
const encodeStatus = (status) => concat(optionalStringField(2, status.message), varintField(3, status.code));
|
|
61567
|
+
/**
|
|
61568
|
+
* Encodes an Event message.
|
|
61569
|
+
*
|
|
61570
|
+
* message Event {
|
|
61571
|
+
* fixed64 time_unix_nano = 1;
|
|
61572
|
+
* string name = 2;
|
|
61573
|
+
* repeated KeyValue attributes = 3;
|
|
61574
|
+
* uint32 dropped_attributes_count = 4;
|
|
61575
|
+
* }
|
|
61576
|
+
*
|
|
61577
|
+
* @internal
|
|
61578
|
+
*/
|
|
61579
|
+
const encodeEvent = (event) => concat(fixed64Field(1, BigInt(event.timeUnixNano)), stringField(2, event.name), repeatedField(3, event.attributes, encodeKeyValue), event.droppedAttributesCount > 0 ? varintField(4, event.droppedAttributesCount) : new Uint8Array(0));
|
|
61580
|
+
/**
|
|
61581
|
+
* Encodes a Link message.
|
|
61582
|
+
*
|
|
61583
|
+
* message Link {
|
|
61584
|
+
* bytes trace_id = 1;
|
|
61585
|
+
* bytes span_id = 2;
|
|
61586
|
+
* string trace_state = 3;
|
|
61587
|
+
* repeated KeyValue attributes = 4;
|
|
61588
|
+
* uint32 dropped_attributes_count = 5;
|
|
61589
|
+
* fixed32 flags = 6;
|
|
61590
|
+
* }
|
|
61591
|
+
*
|
|
61592
|
+
* @internal
|
|
61593
|
+
*/
|
|
61594
|
+
const encodeLink = (link) => concat(bytesFieldFromHex(1, link.traceId), bytesFieldFromHex(2, link.spanId), optionalStringField(3, link.traceState), repeatedField(4, link.attributes, encodeKeyValue), link.droppedAttributesCount > 0 ? varintField(5, link.droppedAttributesCount) : new Uint8Array(0), link.flags !== void 0 ? fixed32Field(6, link.flags) : new Uint8Array(0));
|
|
61595
|
+
/**
|
|
61596
|
+
* Encodes a Span message.
|
|
61597
|
+
*
|
|
61598
|
+
* message Span {
|
|
61599
|
+
* bytes trace_id = 1;
|
|
61600
|
+
* bytes span_id = 2;
|
|
61601
|
+
* string trace_state = 3;
|
|
61602
|
+
* bytes parent_span_id = 4;
|
|
61603
|
+
* string name = 5;
|
|
61604
|
+
* SpanKind kind = 6;
|
|
61605
|
+
* fixed64 start_time_unix_nano = 7;
|
|
61606
|
+
* fixed64 end_time_unix_nano = 8;
|
|
61607
|
+
* repeated KeyValue attributes = 9;
|
|
61608
|
+
* uint32 dropped_attributes_count = 10;
|
|
61609
|
+
* repeated Event events = 11;
|
|
61610
|
+
* uint32 dropped_events_count = 12;
|
|
61611
|
+
* repeated Link links = 13;
|
|
61612
|
+
* uint32 dropped_links_count = 14;
|
|
61613
|
+
* Status status = 15;
|
|
61614
|
+
* fixed32 flags = 16;
|
|
61615
|
+
* }
|
|
61616
|
+
*
|
|
61617
|
+
* @internal
|
|
61618
|
+
*/
|
|
61619
|
+
const encodeSpan = (span) => concat(bytesFieldFromHex(1, span.traceId), bytesFieldFromHex(2, span.spanId), optionalStringField(3, span.traceState), span.parentSpanId !== void 0 ? bytesFieldFromHex(4, span.parentSpanId) : new Uint8Array(0), stringField(5, span.name), varintField(6, span.kind), fixed64Field(7, BigInt(span.startTimeUnixNano)), fixed64Field(8, BigInt(span.endTimeUnixNano)), repeatedField(9, span.attributes, encodeKeyValue), span.droppedAttributesCount > 0 ? varintField(10, span.droppedAttributesCount) : new Uint8Array(0), repeatedField(11, span.events, encodeEvent), span.droppedEventsCount > 0 ? varintField(12, span.droppedEventsCount) : new Uint8Array(0), repeatedField(13, span.links, encodeLink), span.droppedLinksCount > 0 ? varintField(14, span.droppedLinksCount) : new Uint8Array(0), messageField(15, encodeStatus(span.status)), span.flags !== void 0 ? fixed32Field(16, span.flags) : new Uint8Array(0));
|
|
61620
|
+
/**
|
|
61621
|
+
* Encodes a ScopeSpans message.
|
|
61622
|
+
*
|
|
61623
|
+
* message ScopeSpans {
|
|
61624
|
+
* InstrumentationScope scope = 1;
|
|
61625
|
+
* repeated Span spans = 2;
|
|
61626
|
+
* string schema_url = 3;
|
|
61627
|
+
* }
|
|
61628
|
+
*
|
|
61629
|
+
* @internal
|
|
61630
|
+
*/
|
|
61631
|
+
const encodeScopeSpans = (scopeSpans) => concat(messageField(1, encodeInstrumentationScope(scopeSpans.scope)), repeatedField(2, scopeSpans.spans, encodeSpan), optionalStringField(3, scopeSpans.schemaUrl));
|
|
61632
|
+
/**
|
|
61633
|
+
* Encodes a ResourceSpans message.
|
|
61634
|
+
*
|
|
61635
|
+
* message ResourceSpans {
|
|
61636
|
+
* Resource resource = 1;
|
|
61637
|
+
* repeated ScopeSpans scope_spans = 2;
|
|
61638
|
+
* string schema_url = 3;
|
|
61639
|
+
* }
|
|
61640
|
+
*
|
|
61641
|
+
* @internal
|
|
61642
|
+
*/
|
|
61643
|
+
const encodeResourceSpans = (resourceSpans) => concat(messageField(1, encodeResource(resourceSpans.resource)), repeatedField(2, resourceSpans.scopeSpans, encodeScopeSpans), optionalStringField(3, resourceSpans.schemaUrl));
|
|
61644
|
+
/**
|
|
61645
|
+
* Encodes a TracesData message (top-level export request).
|
|
61646
|
+
*
|
|
61647
|
+
* message TracesData {
|
|
61648
|
+
* repeated ResourceSpans resource_spans = 1;
|
|
61649
|
+
* }
|
|
61650
|
+
*
|
|
61651
|
+
* @internal
|
|
61652
|
+
*/
|
|
61653
|
+
const encodeTracesData = (tracesData) => repeatedField(1, tracesData.resourceSpans, encodeResourceSpans);
|
|
61654
|
+
/**
|
|
61655
|
+
* Encodes a NumberDataPoint message.
|
|
61656
|
+
*
|
|
61657
|
+
* message NumberDataPoint {
|
|
61658
|
+
* repeated KeyValue attributes = 7;
|
|
61659
|
+
* fixed64 start_time_unix_nano = 2;
|
|
61660
|
+
* fixed64 time_unix_nano = 3;
|
|
61661
|
+
* oneof value {
|
|
61662
|
+
* double as_double = 4;
|
|
61663
|
+
* sfixed64 as_int = 6;
|
|
61664
|
+
* }
|
|
61665
|
+
* repeated Exemplar exemplars = 5;
|
|
61666
|
+
* uint32 flags = 8;
|
|
61667
|
+
* }
|
|
61668
|
+
*
|
|
61669
|
+
* @internal
|
|
61670
|
+
*/
|
|
61671
|
+
const encodeNumberDataPoint = (point) => concat(fixed64Field(2, BigInt(point.startTimeUnixNano)), fixed64Field(3, BigInt(point.timeUnixNano)), point.asDouble !== void 0 ? doubleField(4, point.asDouble) : new Uint8Array(0), point.asInt !== void 0 ? fixed64Field(6, BigInt(point.asInt)) : new Uint8Array(0), repeatedField(7, point.attributes, encodeKeyValue), point.flags !== void 0 ? varintField(8, point.flags) : new Uint8Array(0));
|
|
61672
|
+
/**
|
|
61673
|
+
* Encodes a HistogramDataPoint message.
|
|
61674
|
+
*
|
|
61675
|
+
* message HistogramDataPoint {
|
|
61676
|
+
* repeated KeyValue attributes = 9;
|
|
61677
|
+
* fixed64 start_time_unix_nano = 2;
|
|
61678
|
+
* fixed64 time_unix_nano = 3;
|
|
61679
|
+
* fixed64 count = 4;
|
|
61680
|
+
* optional double sum = 5;
|
|
61681
|
+
* repeated fixed64 bucket_counts = 6;
|
|
61682
|
+
* repeated double explicit_bounds = 7;
|
|
61683
|
+
* optional double min = 11;
|
|
61684
|
+
* optional double max = 12;
|
|
61685
|
+
* uint32 flags = 10;
|
|
61686
|
+
* }
|
|
61687
|
+
*
|
|
61688
|
+
* @internal
|
|
61689
|
+
*/
|
|
61690
|
+
const encodeHistogramDataPoint = (point) => {
|
|
61691
|
+
const bucketCountsEncoded = concat(...point.bucketCounts.map((count) => fixed64Field(6, BigInt(count))));
|
|
61692
|
+
const explicitBoundsEncoded = concat(...point.explicitBounds.map((bound) => doubleField(7, bound)));
|
|
61693
|
+
return concat(fixed64Field(2, BigInt(point.startTimeUnixNano)), fixed64Field(3, BigInt(point.timeUnixNano)), fixed64Field(4, BigInt(point.count)), point.sum !== void 0 ? doubleField(5, point.sum) : new Uint8Array(0), bucketCountsEncoded, explicitBoundsEncoded, repeatedField(9, point.attributes, encodeKeyValue), point.flags !== void 0 ? varintField(10, point.flags) : new Uint8Array(0), point.min !== void 0 ? doubleField(11, point.min) : new Uint8Array(0), point.max !== void 0 ? doubleField(12, point.max) : new Uint8Array(0));
|
|
61694
|
+
};
|
|
61695
|
+
/**
|
|
61696
|
+
* Encodes a Gauge message.
|
|
61697
|
+
*
|
|
61698
|
+
* message Gauge {
|
|
61699
|
+
* repeated NumberDataPoint data_points = 1;
|
|
61700
|
+
* }
|
|
61701
|
+
*
|
|
61702
|
+
* @internal
|
|
61703
|
+
*/
|
|
61704
|
+
const encodeGauge = (gauge) => repeatedField(1, gauge.dataPoints, encodeNumberDataPoint);
|
|
61705
|
+
/**
|
|
61706
|
+
* Encodes a Sum message.
|
|
61707
|
+
*
|
|
61708
|
+
* message Sum {
|
|
61709
|
+
* repeated NumberDataPoint data_points = 1;
|
|
61710
|
+
* AggregationTemporality aggregation_temporality = 2;
|
|
61711
|
+
* bool is_monotonic = 3;
|
|
61712
|
+
* }
|
|
61713
|
+
*
|
|
61714
|
+
* @internal
|
|
61715
|
+
*/
|
|
61716
|
+
const encodeSum = (sum) => concat(repeatedField(1, sum.dataPoints, encodeNumberDataPoint), varintField(2, sum.aggregationTemporality), boolField(3, sum.isMonotonic));
|
|
61717
|
+
/**
|
|
61718
|
+
* Encodes a Histogram message.
|
|
61719
|
+
*
|
|
61720
|
+
* message Histogram {
|
|
61721
|
+
* repeated HistogramDataPoint data_points = 1;
|
|
61722
|
+
* AggregationTemporality aggregation_temporality = 2;
|
|
61723
|
+
* }
|
|
61724
|
+
*
|
|
61725
|
+
* @internal
|
|
61726
|
+
*/
|
|
61727
|
+
const encodeHistogram = (histogram) => concat(repeatedField(1, histogram.dataPoints, encodeHistogramDataPoint), varintField(2, histogram.aggregationTemporality));
|
|
61728
|
+
/**
|
|
61729
|
+
* Encodes a Metric message.
|
|
61730
|
+
*
|
|
61731
|
+
* message Metric {
|
|
61732
|
+
* string name = 1;
|
|
61733
|
+
* string description = 2;
|
|
61734
|
+
* string unit = 3;
|
|
61735
|
+
* oneof data {
|
|
61736
|
+
* Gauge gauge = 5;
|
|
61737
|
+
* Sum sum = 7;
|
|
61738
|
+
* Histogram histogram = 9;
|
|
61739
|
+
* ExponentialHistogram exponential_histogram = 10;
|
|
61740
|
+
* Summary summary = 11;
|
|
61741
|
+
* }
|
|
61742
|
+
* }
|
|
61743
|
+
*
|
|
61744
|
+
* @internal
|
|
61745
|
+
*/
|
|
61746
|
+
const encodeMetric = (metric) => concat(stringField(1, metric.name), optionalStringField(2, metric.description), optionalStringField(3, metric.unit), metric.gauge !== void 0 ? messageField(5, encodeGauge(metric.gauge)) : new Uint8Array(0), metric.sum !== void 0 ? messageField(7, encodeSum(metric.sum)) : new Uint8Array(0), metric.histogram !== void 0 ? messageField(9, encodeHistogram(metric.histogram)) : new Uint8Array(0));
|
|
61747
|
+
/**
|
|
61748
|
+
* Encodes a ScopeMetrics message.
|
|
61749
|
+
*
|
|
61750
|
+
* message ScopeMetrics {
|
|
61751
|
+
* InstrumentationScope scope = 1;
|
|
61752
|
+
* repeated Metric metrics = 2;
|
|
61753
|
+
* string schema_url = 3;
|
|
61754
|
+
* }
|
|
61755
|
+
*
|
|
61756
|
+
* @internal
|
|
61757
|
+
*/
|
|
61758
|
+
const encodeScopeMetrics = (scopeMetrics) => concat(messageField(1, encodeInstrumentationScope(scopeMetrics.scope)), repeatedField(2, scopeMetrics.metrics, encodeMetric), optionalStringField(3, scopeMetrics.schemaUrl));
|
|
61759
|
+
/**
|
|
61760
|
+
* Encodes a ResourceMetrics message.
|
|
61761
|
+
*
|
|
61762
|
+
* message ResourceMetrics {
|
|
61763
|
+
* Resource resource = 1;
|
|
61764
|
+
* repeated ScopeMetrics scope_metrics = 2;
|
|
61765
|
+
* string schema_url = 3;
|
|
61766
|
+
* }
|
|
61767
|
+
*
|
|
61768
|
+
* @internal
|
|
61769
|
+
*/
|
|
61770
|
+
const encodeResourceMetrics = (resourceMetrics) => concat(messageField(1, encodeResource(resourceMetrics.resource)), repeatedField(2, resourceMetrics.scopeMetrics, encodeScopeMetrics), optionalStringField(3, resourceMetrics.schemaUrl));
|
|
61771
|
+
/**
|
|
61772
|
+
* Encodes a MetricsData message (top-level export request).
|
|
61773
|
+
*
|
|
61774
|
+
* message MetricsData {
|
|
61775
|
+
* repeated ResourceMetrics resource_metrics = 1;
|
|
61776
|
+
* }
|
|
61777
|
+
*
|
|
61778
|
+
* @internal
|
|
61779
|
+
*/
|
|
61780
|
+
const encodeMetricsData = (metricsData) => repeatedField(1, metricsData.resourceMetrics, encodeResourceMetrics);
|
|
61781
|
+
/**
|
|
61782
|
+
* Encodes a LogRecord message.
|
|
61783
|
+
*
|
|
61784
|
+
* message LogRecord {
|
|
61785
|
+
* fixed64 time_unix_nano = 1;
|
|
61786
|
+
* fixed64 observed_time_unix_nano = 11;
|
|
61787
|
+
* SeverityNumber severity_number = 2;
|
|
61788
|
+
* string severity_text = 3;
|
|
61789
|
+
* AnyValue body = 5;
|
|
61790
|
+
* repeated KeyValue attributes = 6;
|
|
61791
|
+
* uint32 dropped_attributes_count = 7;
|
|
61792
|
+
* fixed32 flags = 8;
|
|
61793
|
+
* bytes trace_id = 9;
|
|
61794
|
+
* bytes span_id = 10;
|
|
61795
|
+
* }
|
|
61796
|
+
*
|
|
61797
|
+
* @internal
|
|
61798
|
+
*/
|
|
61799
|
+
const encodeLogRecord = (record) => concat(fixed64Field(1, BigInt(record.timeUnixNano)), record.severityNumber !== void 0 ? varintField(2, record.severityNumber) : new Uint8Array(0), optionalStringField(3, record.severityText), record.body !== void 0 ? messageField(5, encodeAnyValue(record.body)) : new Uint8Array(0), repeatedField(6, record.attributes, encodeKeyValue), record.droppedAttributesCount !== void 0 && record.droppedAttributesCount > 0 ? varintField(7, record.droppedAttributesCount) : new Uint8Array(0), record.flags !== void 0 ? fixed32Field(8, record.flags) : new Uint8Array(0), record.traceId !== void 0 && record.traceId !== "" ? bytesFieldFromHex(9, record.traceId) : new Uint8Array(0), record.spanId !== void 0 && record.spanId !== "" ? bytesFieldFromHex(10, record.spanId) : new Uint8Array(0), record.observedTimeUnixNano !== void 0 ? fixed64Field(11, BigInt(record.observedTimeUnixNano)) : new Uint8Array(0));
|
|
61800
|
+
/**
|
|
61801
|
+
* Encodes a ScopeLogs message.
|
|
61802
|
+
*
|
|
61803
|
+
* message ScopeLogs {
|
|
61804
|
+
* InstrumentationScope scope = 1;
|
|
61805
|
+
* repeated LogRecord log_records = 2;
|
|
61806
|
+
* string schema_url = 3;
|
|
61807
|
+
* }
|
|
61808
|
+
*
|
|
61809
|
+
* @internal
|
|
61810
|
+
*/
|
|
61811
|
+
const encodeScopeLogs = (scopeLogs) => concat(messageField(1, encodeInstrumentationScope(scopeLogs.scope)), repeatedField(2, scopeLogs.logRecords, encodeLogRecord), optionalStringField(3, scopeLogs.schemaUrl));
|
|
61812
|
+
/**
|
|
61813
|
+
* Encodes a ResourceLogs message.
|
|
61814
|
+
*
|
|
61815
|
+
* message ResourceLogs {
|
|
61816
|
+
* Resource resource = 1;
|
|
61817
|
+
* repeated ScopeLogs scope_logs = 2;
|
|
61818
|
+
* string schema_url = 3;
|
|
61819
|
+
* }
|
|
61820
|
+
*
|
|
61821
|
+
* @internal
|
|
61822
|
+
*/
|
|
61823
|
+
const encodeResourceLogs = (resourceLogs) => concat(messageField(1, encodeResource(resourceLogs.resource)), repeatedField(2, resourceLogs.scopeLogs, encodeScopeLogs), optionalStringField(3, resourceLogs.schemaUrl));
|
|
61824
|
+
/**
|
|
61825
|
+
* Encodes a LogsData message (top-level export request).
|
|
61826
|
+
*
|
|
61827
|
+
* message LogsData {
|
|
61828
|
+
* repeated ResourceLogs resource_logs = 1;
|
|
61829
|
+
* }
|
|
61830
|
+
*
|
|
61831
|
+
* @internal
|
|
61832
|
+
*/
|
|
61833
|
+
const encodeLogsData = (logsData) => repeatedField(1, logsData.resourceLogs, encodeResourceLogs);
|
|
61834
|
+
//#endregion
|
|
60746
61835
|
//#region ../../node_modules/.pnpm/effect@4.0.0-beta.102/node_modules/effect/dist/unstable/observability/OtlpSerialization.js
|
|
60747
61836
|
/**
|
|
60748
61837
|
* Serializes OTLP payloads into HTTP request bodies.
|
|
@@ -60772,6 +61861,18 @@ const layerJson$1 = /* @__PURE__ */ succeed$3(OtlpSerialization, {
|
|
|
60772
61861
|
metrics: (metrics) => jsonUnsafe(metrics),
|
|
60773
61862
|
logs: (logs) => jsonUnsafe(logs)
|
|
60774
61863
|
});
|
|
61864
|
+
/**
|
|
61865
|
+
* Provides `OtlpSerialization` using protobuf-encoded OTLP bodies with the
|
|
61866
|
+
* `application/x-protobuf` content type.
|
|
61867
|
+
*
|
|
61868
|
+
* @category layers
|
|
61869
|
+
* @since 4.0.0
|
|
61870
|
+
*/
|
|
61871
|
+
const layerProtobuf = /* @__PURE__ */ succeed$3(OtlpSerialization, {
|
|
61872
|
+
traces: (spans) => uint8Array(encodeTracesData(spans), "application/x-protobuf"),
|
|
61873
|
+
metrics: (metrics) => uint8Array(encodeMetricsData(metrics), "application/x-protobuf"),
|
|
61874
|
+
logs: (logs) => uint8Array(encodeLogsData(logs), "application/x-protobuf")
|
|
61875
|
+
});
|
|
60775
61876
|
//#endregion
|
|
60776
61877
|
//#region ../../node_modules/.pnpm/effect@4.0.0-beta.102/node_modules/effect/dist/unstable/observability/OtlpLogger.js
|
|
60777
61878
|
/**
|
|
@@ -60944,7 +62045,7 @@ const make$5 = /* @__PURE__ */ fnUntraced(function* (options) {
|
|
|
60944
62045
|
const temporality = options.temporality ?? "cumulative";
|
|
60945
62046
|
const resource = yield* fromConfig(options.resource);
|
|
60946
62047
|
const metricsScope = { name: serviceNameUnsafe(resource) };
|
|
60947
|
-
const services = yield* context();
|
|
62048
|
+
const services = yield* context$1();
|
|
60948
62049
|
let previousExportTimeNanos = startTimeNanos;
|
|
60949
62050
|
const previousCounterState = /* @__PURE__ */ new Map();
|
|
60950
62051
|
const previousHistogramState = /* @__PURE__ */ new Map();
|
|
@@ -61662,7 +62763,7 @@ const TypeId$1 = "~effect/Cache";
|
|
|
61662
62763
|
*/
|
|
61663
62764
|
const makeWith = (lookup, options) => contextWith$1((context) => {
|
|
61664
62765
|
const self = Object.create(Proto$1);
|
|
61665
|
-
self.lookup = (key) => updateContext$1(lookup(key), (input) => merge$
|
|
62766
|
+
self.lookup = (key) => updateContext$1(lookup(key), (input) => merge$4(context, input));
|
|
61666
62767
|
self.map = make$20();
|
|
61667
62768
|
self.capacity = options.capacity;
|
|
61668
62769
|
self.timeToLive = options.timeToLive ? (exit, key) => fromInputUnsafe(options.timeToLive(exit, key)) : defaultTimeToLive;
|
|
@@ -63745,6 +64846,11 @@ const REACT_ROUTER_CAPABILITY_THRESHOLDS = [
|
|
|
63745
64846
|
}
|
|
63746
64847
|
];
|
|
63747
64848
|
const SCORE_API_URL = "https://www.react.doctor/api/score";
|
|
64849
|
+
const AXIOM_TRACES_PATH = "/v1/traces";
|
|
64850
|
+
const AXIOM_METRICS_PATH = "/v1/metrics";
|
|
64851
|
+
const AXIOM_DATASET_HEADER = "X-Axiom-Dataset";
|
|
64852
|
+
const AXIOM_METRICS_DATASET_HEADER = "x-axiom-metrics-dataset";
|
|
64853
|
+
const TELEMETRY_SHUTDOWN_TIMEOUT_MS = 1e3;
|
|
63748
64854
|
const FETCH_TIMEOUT_MS = 1e4;
|
|
63749
64855
|
const GITHUB_VIEWER_PERMISSION_TIMEOUT_MS = 2e3;
|
|
63750
64856
|
const SPAWN_ARGS_MAX_LENGTH_CHARS = 24e3;
|
|
@@ -64007,7 +65113,7 @@ const SOCKET_FREE_USER_AGENT = "react-doctor-supply-chain";
|
|
|
64007
65113
|
const FILE_LINT_CACHE_FILENAME = "file-lint-cache.json";
|
|
64008
65114
|
const FILE_LINT_CACHE_MAX_FILE_COUNT = 5e4;
|
|
64009
65115
|
const SIDECAR_LINT_CACHE_FILENAME = "sidecar-lint-cache.json";
|
|
64010
|
-
const CORE_PACKAGE_VERSION = "0.9.
|
|
65116
|
+
const CORE_PACKAGE_VERSION = "0.9.10";
|
|
64011
65117
|
const DEAD_CODE_CACHE_FILENAME = "dead-code-cache.json";
|
|
64012
65118
|
const DEAD_CODE_SUMMARY_CACHE_FILENAME = "dead-code-summaries.json";
|
|
64013
65119
|
const SUPPLY_CHAIN_PLUGIN = "socket";
|
|
@@ -68224,11 +69330,304 @@ var ReactDoctorError = class extends TaggedErrorClass()("ReactDoctorError", { re
|
|
|
68224
69330
|
};
|
|
68225
69331
|
const isSplittableReactDoctorError = (error) => error instanceof ReactDoctorError && error.reason._tag === "OxlintBatchExceeded";
|
|
68226
69332
|
const isReactDoctorError = (error) => error instanceof ReactDoctorError;
|
|
69333
|
+
const REDACTED_PLACEHOLDER = "<redacted>";
|
|
69334
|
+
const KEEP_PREFIX = `$1${REDACTED_PLACEHOLDER}`;
|
|
69335
|
+
const KNOWN_SECRET_RULES = [
|
|
69336
|
+
{
|
|
69337
|
+
pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g,
|
|
69338
|
+
replacement: REDACTED_PLACEHOLDER
|
|
69339
|
+
},
|
|
69340
|
+
{
|
|
69341
|
+
pattern: /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}/g,
|
|
69342
|
+
replacement: REDACTED_PLACEHOLDER
|
|
69343
|
+
},
|
|
69344
|
+
{
|
|
69345
|
+
pattern: /(?<=:\/\/)[^\s/:@]+:[^\s/@]+(?=@)/g,
|
|
69346
|
+
replacement: REDACTED_PLACEHOLDER
|
|
69347
|
+
},
|
|
69348
|
+
{
|
|
69349
|
+
pattern: /\b(AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA|A3T[A-Z0-9])[0-9A-Z]{16,}/g,
|
|
69350
|
+
replacement: KEEP_PREFIX
|
|
69351
|
+
},
|
|
69352
|
+
{
|
|
69353
|
+
pattern: /\b(gh[pousr]_)[A-Za-z0-9]{36,}/g,
|
|
69354
|
+
replacement: KEEP_PREFIX
|
|
69355
|
+
},
|
|
69356
|
+
{
|
|
69357
|
+
pattern: /\b(github_pat_)[A-Za-z0-9_]{22,}/g,
|
|
69358
|
+
replacement: KEEP_PREFIX
|
|
69359
|
+
},
|
|
69360
|
+
{
|
|
69361
|
+
pattern: /\b(glpat-)[A-Za-z0-9_-]{20,}/g,
|
|
69362
|
+
replacement: KEEP_PREFIX
|
|
69363
|
+
},
|
|
69364
|
+
{
|
|
69365
|
+
pattern: /\b(xox[baprs]-)[A-Za-z0-9-]{10,}/g,
|
|
69366
|
+
replacement: KEEP_PREFIX
|
|
69367
|
+
},
|
|
69368
|
+
{
|
|
69369
|
+
pattern: /(?<=hooks\.slack\.com\/services\/)[A-Za-z0-9/+_-]{20,}/g,
|
|
69370
|
+
replacement: REDACTED_PLACEHOLDER
|
|
69371
|
+
},
|
|
69372
|
+
{
|
|
69373
|
+
pattern: /\b((?:sk|rk)_(?:live|test)_)[0-9A-Za-z]{10,}/g,
|
|
69374
|
+
replacement: KEEP_PREFIX
|
|
69375
|
+
},
|
|
69376
|
+
{
|
|
69377
|
+
pattern: /\b(sk-(?:proj-|ant-)?)[A-Za-z0-9_-]{20,}/g,
|
|
69378
|
+
replacement: KEEP_PREFIX
|
|
69379
|
+
},
|
|
69380
|
+
{
|
|
69381
|
+
pattern: /\b(AIza)[0-9A-Za-z_-]{35,}/g,
|
|
69382
|
+
replacement: KEEP_PREFIX
|
|
69383
|
+
},
|
|
69384
|
+
{
|
|
69385
|
+
pattern: /\b(ya29\.)[0-9A-Za-z_-]{20,}/g,
|
|
69386
|
+
replacement: KEEP_PREFIX
|
|
69387
|
+
},
|
|
69388
|
+
{
|
|
69389
|
+
pattern: /\b(npm_)[A-Za-z0-9]{36,}/g,
|
|
69390
|
+
replacement: KEEP_PREFIX
|
|
69391
|
+
},
|
|
69392
|
+
{
|
|
69393
|
+
pattern: /\b(SG\.)[A-Za-z0-9_-]{22,}\.[A-Za-z0-9_-]{43,}/g,
|
|
69394
|
+
replacement: KEEP_PREFIX
|
|
69395
|
+
},
|
|
69396
|
+
{
|
|
69397
|
+
pattern: /\b(SK)[0-9a-fA-F]{32,}/g,
|
|
69398
|
+
replacement: KEEP_PREFIX
|
|
69399
|
+
},
|
|
69400
|
+
{
|
|
69401
|
+
pattern: /\b(dop_v1_)[a-f0-9]{64,}/g,
|
|
69402
|
+
replacement: KEEP_PREFIX
|
|
69403
|
+
},
|
|
69404
|
+
{
|
|
69405
|
+
pattern: /\b(shp(?:at|ca|pa|ss)_)[a-fA-F0-9]{32,}/g,
|
|
69406
|
+
replacement: KEEP_PREFIX
|
|
69407
|
+
},
|
|
69408
|
+
{
|
|
69409
|
+
pattern: /\b(sq0[a-z]{3}-)[0-9A-Za-z_-]{22,}/g,
|
|
69410
|
+
replacement: KEEP_PREFIX
|
|
69411
|
+
},
|
|
69412
|
+
{
|
|
69413
|
+
pattern: /\b([0-9]{8,10}:AA)[0-9A-Za-z_-]{32,}/g,
|
|
69414
|
+
replacement: KEEP_PREFIX
|
|
69415
|
+
},
|
|
69416
|
+
{
|
|
69417
|
+
pattern: /(?<=\bBearer\s)[A-Za-z0-9._~+/=-]{16,}/g,
|
|
69418
|
+
replacement: REDACTED_PLACEHOLDER
|
|
69419
|
+
},
|
|
69420
|
+
{
|
|
69421
|
+
pattern: /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g,
|
|
69422
|
+
replacement: REDACTED_PLACEHOLDER
|
|
69423
|
+
}
|
|
69424
|
+
];
|
|
69425
|
+
const CANDIDATE_TOKEN_PATTERN = /[A-Za-z0-9_][A-Za-z0-9_-]*/g;
|
|
69426
|
+
const HEX_DIGEST_PATTERN = /^(?:[0-9a-f]{32}|[0-9a-f]{40}|[0-9a-f]{64})$/;
|
|
69427
|
+
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
69428
|
+
const HAS_LETTER_PATTERN = /[A-Za-z]/;
|
|
69429
|
+
const HAS_DIGIT_PATTERN = /[0-9]/;
|
|
69430
|
+
const shannonEntropyBits = (value) => {
|
|
69431
|
+
const counts = /* @__PURE__ */ new Map();
|
|
69432
|
+
for (const char of value) counts.set(char, (counts.get(char) ?? 0) + 1);
|
|
69433
|
+
let bits = 0;
|
|
69434
|
+
for (const count of counts.values()) {
|
|
69435
|
+
const probability = count / value.length;
|
|
69436
|
+
bits -= probability * Math.log2(probability);
|
|
69437
|
+
}
|
|
69438
|
+
return bits;
|
|
69439
|
+
};
|
|
69440
|
+
const looksLikeHighEntropySecret = (token) => {
|
|
69441
|
+
if (token.length < 32) return false;
|
|
69442
|
+
if (!HAS_LETTER_PATTERN.test(token) || !HAS_DIGIT_PATTERN.test(token)) return false;
|
|
69443
|
+
if (HEX_DIGEST_PATTERN.test(token) || UUID_PATTERN.test(token)) return false;
|
|
69444
|
+
return shannonEntropyBits(token) >= 3;
|
|
69445
|
+
};
|
|
69446
|
+
const redactHighEntropyTokens = (text) => text.replace(CANDIDATE_TOKEN_PATTERN, (token) => looksLikeHighEntropySecret(token) ? REDACTED_PLACEHOLDER : token);
|
|
69447
|
+
/**
|
|
69448
|
+
* Masks API keys, tokens, private keys, credentialed URLs, and emails
|
|
69449
|
+
* found anywhere inside a free-text string, returning the scrubbed text.
|
|
69450
|
+
* Applied to every diagnostic's `message` / `help` at construction time
|
|
69451
|
+
* so secrets never reach the terminal, the JSON report, or the score
|
|
69452
|
+
* API — react-doctor must never echo or transmit a user's secrets.
|
|
69453
|
+
*
|
|
69454
|
+
* Provider tokens keep their non-secret, type-identifying prefix (e.g.
|
|
69455
|
+
* `sk_live_<redacted>`, `ghp_<redacted>`, `AKIA<redacted>`) so the leaked
|
|
69456
|
+
* credential's type stays visible; structural or unknown-format secrets
|
|
69457
|
+
* with no meaningful prefix are masked whole.
|
|
69458
|
+
*
|
|
69459
|
+
* Runs the high-precision known-shape detectors first, then a generic
|
|
69460
|
+
* entropy-gated sweep for unknown-format secrets. Idempotent: the inert
|
|
69461
|
+
* `<redacted>` placeholder matches none of the detectors and is too
|
|
69462
|
+
* short for the generic sweep, so re-running leaves the text unchanged.
|
|
69463
|
+
*
|
|
69464
|
+
* Accepts `unknown` on purpose: callers feed it diagnostic `message` /
|
|
69465
|
+
* `help` that originate from oxlint JSON, which is only shape-checked at
|
|
69466
|
+
* the top level (the per-field `string` types are assumed, not validated).
|
|
69467
|
+
* A malformed non-string value returns `""` instead of throwing on
|
|
69468
|
+
* `.replace`, so one bad diagnostic can't abort parsing the whole batch.
|
|
69469
|
+
*/
|
|
69470
|
+
const redactSensitiveText = (text) => {
|
|
69471
|
+
if (typeof text !== "string" || text === "") return "";
|
|
69472
|
+
let redacted = text;
|
|
69473
|
+
for (const rule of KNOWN_SECRET_RULES) redacted = redacted.replace(rule.pattern, rule.replacement);
|
|
69474
|
+
return redactHighEntropyTokens(redacted);
|
|
69475
|
+
};
|
|
69476
|
+
const HOME_DIRECTORY = os.homedir();
|
|
69477
|
+
const USER_HOME_PATTERNS = [/[A-Za-z]:[\\/]Users[\\/][^\\/]+/gi, /(?:\/Users\/|\/home\/)[^/\\]+/gi];
|
|
69478
|
+
const scrubSensitivePaths = (text) => {
|
|
69479
|
+
let scrubbed = text;
|
|
69480
|
+
if (HOME_DIRECTORY.length > 1) scrubbed = scrubbed.split(HOME_DIRECTORY).join("~");
|
|
69481
|
+
for (const pattern of USER_HOME_PATTERNS) scrubbed = scrubbed.replace(pattern, "~");
|
|
69482
|
+
return scrubbed;
|
|
69483
|
+
};
|
|
69484
|
+
/**
|
|
69485
|
+
* Free-text fields can carry both a home-directory path (the OS username) and a
|
|
69486
|
+
* secret/email echoed from user code, so run both scrubbers: strip the username
|
|
69487
|
+
* from paths, then mask any known credential/PII shape. Shared by the Sentry
|
|
69488
|
+
* event scrubber ({@link scrubSentryEvent}), the metric emitter, and the
|
|
69489
|
+
* scrubbing tracer that guards everything bound for OTLP.
|
|
69490
|
+
*/
|
|
69491
|
+
const anonymizeText = (text) => redactSensitiveText(scrubSensitivePaths(text));
|
|
69492
|
+
/**
|
|
69493
|
+
* Recursively rewrites every string within an arbitrary value (object / array /
|
|
69494
|
+
* primitive) through {@link anonymizeText}, mutating in place. Used to sweep the
|
|
69495
|
+
* unstructured corners of a Sentry payload (event contexts/extra/tags, breadcrumb
|
|
69496
|
+
* data, span attributes, metric attributes) where a path or secret could hide.
|
|
69497
|
+
*/
|
|
69498
|
+
const anonymizeInPlace = (value) => {
|
|
69499
|
+
if (Array.isArray(value)) {
|
|
69500
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
69501
|
+
const item = value[index];
|
|
69502
|
+
if (typeof item === "string") value[index] = anonymizeText(item);
|
|
69503
|
+
else anonymizeInPlace(item);
|
|
69504
|
+
}
|
|
69505
|
+
return;
|
|
69506
|
+
}
|
|
69507
|
+
if (!isPlainObject(value)) return;
|
|
69508
|
+
for (const key of Object.keys(value)) {
|
|
69509
|
+
const inner = value[key];
|
|
69510
|
+
if (typeof inner === "string") value[key] = anonymizeText(inner);
|
|
69511
|
+
else anonymizeInPlace(inner);
|
|
69512
|
+
}
|
|
69513
|
+
};
|
|
69514
|
+
const scrubValue = (value) => typeof value === "string" ? anonymizeText(value) : value;
|
|
69515
|
+
/**
|
|
69516
|
+
* Anonymizes the failure a span ended with.
|
|
69517
|
+
*
|
|
69518
|
+
* The OTLP tracer runs `Cause.prettyErrors` over the exit and exports each
|
|
69519
|
+
* result as `exception.type` / `exception.message` / `exception.stacktrace`.
|
|
69520
|
+
* Stack traces are full of absolute paths, so a failing scan would ship the
|
|
69521
|
+
* user's home directory even though every attribute and event is scrubbed —
|
|
69522
|
+
* this is the one route into the payload that doesn't go through
|
|
69523
|
+
* `span.attribute`.
|
|
69524
|
+
*
|
|
69525
|
+
* Interrupt-only causes are left alone: the exporter emits a fixed
|
|
69526
|
+
* "Interrupted" label for them and never touches the error text.
|
|
69527
|
+
*/
|
|
69528
|
+
const scrubExit = (exit) => {
|
|
69529
|
+
if (isSuccess(exit) || hasInterruptsOnly(exit.cause)) return exit;
|
|
69530
|
+
const errors = prettyErrors(exit.cause);
|
|
69531
|
+
if (errors.length === 0) return exit;
|
|
69532
|
+
return failCause$3(errors.map((error) => {
|
|
69533
|
+
const anonymized = new Error(anonymizeText(error.message));
|
|
69534
|
+
anonymized.name = anonymizeText(error.name);
|
|
69535
|
+
anonymized.stack = error.stack === void 0 ? void 0 : anonymizeText(error.stack);
|
|
69536
|
+
return fail$6(anonymized);
|
|
69537
|
+
}).reduce((left, right) => combine(left, right)));
|
|
69538
|
+
};
|
|
69539
|
+
const scrubAttributes = (attributes) => {
|
|
69540
|
+
if (!attributes) return attributes;
|
|
69541
|
+
const scrubbed = {};
|
|
69542
|
+
for (const [key, value] of Object.entries(attributes)) scrubbed[key] = scrubValue(value);
|
|
69543
|
+
return scrubbed;
|
|
69544
|
+
};
|
|
69545
|
+
/**
|
|
69546
|
+
* Wraps a {@link Tracer.Span} so every value that reaches the exporter has been
|
|
69547
|
+
* run through {@link anonymizeText} first.
|
|
69548
|
+
*
|
|
69549
|
+
* Delegation is explicit rather than prototype-based: the wrapper forwards each
|
|
69550
|
+
* method to the real span, so the exporter keeps tracking the span it created
|
|
69551
|
+
* and no call depends on `this` binding surviving the indirection.
|
|
69552
|
+
*/
|
|
69553
|
+
const wrapSpan = (span) => ({
|
|
69554
|
+
_tag: "Span",
|
|
69555
|
+
get name() {
|
|
69556
|
+
return span.name;
|
|
69557
|
+
},
|
|
69558
|
+
get spanId() {
|
|
69559
|
+
return span.spanId;
|
|
69560
|
+
},
|
|
69561
|
+
get traceId() {
|
|
69562
|
+
return span.traceId;
|
|
69563
|
+
},
|
|
69564
|
+
get parent() {
|
|
69565
|
+
return span.parent;
|
|
69566
|
+
},
|
|
69567
|
+
get annotations() {
|
|
69568
|
+
return span.annotations;
|
|
69569
|
+
},
|
|
69570
|
+
get status() {
|
|
69571
|
+
return span.status;
|
|
69572
|
+
},
|
|
69573
|
+
get attributes() {
|
|
69574
|
+
return span.attributes;
|
|
69575
|
+
},
|
|
69576
|
+
get links() {
|
|
69577
|
+
return span.links;
|
|
69578
|
+
},
|
|
69579
|
+
get sampled() {
|
|
69580
|
+
return span.sampled;
|
|
69581
|
+
},
|
|
69582
|
+
get kind() {
|
|
69583
|
+
return span.kind;
|
|
69584
|
+
},
|
|
69585
|
+
end: (endTime, exit) => {
|
|
69586
|
+
span.end(endTime, scrubExit(exit));
|
|
69587
|
+
},
|
|
69588
|
+
attribute: (key, value) => {
|
|
69589
|
+
span.attribute(key, scrubValue(value));
|
|
69590
|
+
},
|
|
69591
|
+
event: (name, startTime, attributes) => {
|
|
69592
|
+
span.event(anonymizeText(name), startTime, scrubAttributes(attributes));
|
|
69593
|
+
},
|
|
69594
|
+
addLinks: (links) => {
|
|
69595
|
+
span.addLinks(links);
|
|
69596
|
+
}
|
|
69597
|
+
});
|
|
69598
|
+
/**
|
|
69599
|
+
* Wraps a tracer so span names, attributes, and event payloads are anonymized
|
|
69600
|
+
* on the way to the exporter.
|
|
69601
|
+
*
|
|
69602
|
+
* This is the OTLP replacement for Sentry's `beforeSendTransaction` hook. OTLP
|
|
69603
|
+
* exporters have no equivalent interception point, so without this the only
|
|
69604
|
+
* thing standing between a raw filesystem path and the wire would be every
|
|
69605
|
+
* individual call site remembering to scrub — which is exactly the guarantee
|
|
69606
|
+
* the Sentry scrubber existed to stop relying on. Call sites should still scrub
|
|
69607
|
+
* at the source; this is the backstop for the ones that don't, including any
|
|
69608
|
+
* added later.
|
|
69609
|
+
*/
|
|
69610
|
+
const makeScrubbingTracer = (underlying) => make$33({
|
|
69611
|
+
span: (options) => wrapSpan(underlying.span({
|
|
69612
|
+
...options,
|
|
69613
|
+
name: anonymizeText(options.name)
|
|
69614
|
+
})),
|
|
69615
|
+
...underlying.context ? { context: underlying.context } : {}
|
|
69616
|
+
});
|
|
68227
69617
|
const TRACER_PROJECT_NAME = "react-doctor";
|
|
69618
|
+
/**
|
|
69619
|
+
* Replaces an exporter layer's `Tracer` with a scrubbing wrapper around it.
|
|
69620
|
+
*
|
|
69621
|
+
* OTLP has no `beforeSend`-style interception point, so this is the one place
|
|
69622
|
+
* every exported span is guaranteed to pass through. Applied to the telemetry
|
|
69623
|
+
* layers rather than to individual call sites so an attribute added later can't
|
|
69624
|
+
* quietly bypass it.
|
|
69625
|
+
*/
|
|
69626
|
+
const withScrubbedSpans = (exporter) => effect(Tracer, map$3(service(Tracer), makeScrubbingTracer)).pipe(provideMerge(exporter));
|
|
68228
69627
|
const OTEL_ENDPOINT = string("REACT_DOCTOR_OTLP_ENDPOINT").pipe(option);
|
|
68229
69628
|
const OTEL_AUTH_HEADER = redacted("REACT_DOCTOR_OTLP_AUTH_HEADER").pipe(option);
|
|
68230
69629
|
/**
|
|
68231
|
-
*
|
|
69630
|
+
* Bring-your-own OpenTelemetry layer. The default `Effect.fn(...)` spans
|
|
68232
69631
|
* already populate the in-process tracer; this layer plugs an OTLP
|
|
68233
69632
|
* HTTP exporter into the runtime when the user opts in via:
|
|
68234
69633
|
*
|
|
@@ -68244,7 +69643,7 @@ const OTEL_AUTH_HEADER = redacted("REACT_DOCTOR_OTLP_AUTH_HEADER").pipe(option);
|
|
|
68244
69643
|
* inspect / diagnose orchestrators always run, this layer just
|
|
68245
69644
|
* dictates whether the spans they emit get shipped to a backend.
|
|
68246
69645
|
*/
|
|
68247
|
-
const
|
|
69646
|
+
const layerUserOtlp = unwrap$3(gen(function* () {
|
|
68248
69647
|
const endpoint = yield* OTEL_ENDPOINT;
|
|
68249
69648
|
const authHeader = yield* OTEL_AUTH_HEADER;
|
|
68250
69649
|
if (endpoint._tag === "None" || authHeader._tag === "None") return empty$7;
|
|
@@ -68256,6 +69655,85 @@ const layerOtlp = unwrap$3(gen(function* () {
|
|
|
68256
69655
|
}).pipe(provide$2(layer$8));
|
|
68257
69656
|
}).pipe(orDie));
|
|
68258
69657
|
/**
|
|
69658
|
+
* First-party telemetry export to Axiom.
|
|
69659
|
+
*
|
|
69660
|
+
* Composes the tracer and metrics exporters by hand rather than using
|
|
69661
|
+
* `Otlp.layer`, because Axiom routes each signal to a different dataset via a
|
|
69662
|
+
* different header (see `AXIOM_DATASET_HEADER` / `AXIOM_METRICS_DATASET_HEADER`)
|
|
69663
|
+
* and `Otlp.layer` passes one `headers` object to every signal. Logs are
|
|
69664
|
+
* deliberately not wired up — nothing in the engine emits `Effect.log` as
|
|
69665
|
+
* telemetry today.
|
|
69666
|
+
*
|
|
69667
|
+
* Serialization is protobuf, not JSON: Axiom's `/v1/metrics` accepts
|
|
69668
|
+
* `application/x-protobuf` only. `layerProtobuf` ships with Effect and pulls in
|
|
69669
|
+
* no extra dependency.
|
|
69670
|
+
*
|
|
69671
|
+
* Traces and metrics are exposed as separate layers so each signal's exporter
|
|
69672
|
+
* can be reasoned about on its own, and `layerObservability` merges them for the
|
|
69673
|
+
* normal case. Whichever you use, build it **exactly once per process**:
|
|
69674
|
+
* Effect's delta-temporality bookkeeping lives on the metrics exporter
|
|
69675
|
+
* instance, so a second one starts with no previous state and re-reports every
|
|
69676
|
+
* counter's full value as its delta — double-counting everything.
|
|
69677
|
+
*/
|
|
69678
|
+
const buildResource = (options) => ({
|
|
69679
|
+
serviceName: TRACER_PROJECT_NAME,
|
|
69680
|
+
serviceVersion: options.serviceVersion
|
|
69681
|
+
});
|
|
69682
|
+
const buildAuthorization = (options) => `Bearer ${value(options.token)}`;
|
|
69683
|
+
const normalizeDomain = (domain) => {
|
|
69684
|
+
let end = domain.length;
|
|
69685
|
+
while (end > 0 && domain.charCodeAt(end - 1) === 47) end -= 1;
|
|
69686
|
+
return domain.slice(0, end);
|
|
69687
|
+
};
|
|
69688
|
+
const layerAxiomTraces = (options) => layer$4({
|
|
69689
|
+
url: `${normalizeDomain(options.domain)}${AXIOM_TRACES_PATH}`,
|
|
69690
|
+
resource: buildResource(options),
|
|
69691
|
+
headers: {
|
|
69692
|
+
Authorization: buildAuthorization(options),
|
|
69693
|
+
[AXIOM_DATASET_HEADER]: options.tracesDataset
|
|
69694
|
+
},
|
|
69695
|
+
exportInterval: options.exportIntervalMs ?? 6e5,
|
|
69696
|
+
shutdownTimeout: TELEMETRY_SHUTDOWN_TIMEOUT_MS
|
|
69697
|
+
}).pipe(provide$2(layerProtobuf), provide$2(layer$8), withScrubbedSpans);
|
|
69698
|
+
/**
|
|
69699
|
+
* Metrics exporter. Instantiate **once per process** — see the double-counting
|
|
69700
|
+
* note above. Delta temporality is still the right choice for a short-lived CLI:
|
|
69701
|
+
* cumulative reports totals since a fixed start time, which for a process that
|
|
69702
|
+
* lives a few seconds is just the run total reported against a meaningless
|
|
69703
|
+
* window.
|
|
69704
|
+
*/
|
|
69705
|
+
const layerAxiomMetrics = (options) => layer$5({
|
|
69706
|
+
url: `${normalizeDomain(options.domain)}${AXIOM_METRICS_PATH}`,
|
|
69707
|
+
resource: buildResource(options),
|
|
69708
|
+
headers: {
|
|
69709
|
+
Authorization: buildAuthorization(options),
|
|
69710
|
+
[AXIOM_METRICS_DATASET_HEADER]: options.metricsDataset
|
|
69711
|
+
},
|
|
69712
|
+
exportInterval: options.exportIntervalMs ?? 6e5,
|
|
69713
|
+
shutdownTimeout: TELEMETRY_SHUTDOWN_TIMEOUT_MS,
|
|
69714
|
+
temporality: "delta"
|
|
69715
|
+
}).pipe(provide$2(layerProtobuf), provide$2(layer$8));
|
|
69716
|
+
/**
|
|
69717
|
+
* The first-party telemetry layer: spans and metrics together.
|
|
69718
|
+
*
|
|
69719
|
+
* A user-configured OTLP endpoint wins over first-party Axiom: Effect has one
|
|
69720
|
+
* `Tracer` reference, so the two are mutually exclusive, and someone who went to
|
|
69721
|
+
* the trouble of pointing React Doctor at their own collector meant it.
|
|
69722
|
+
* Passing `null` (or omitting options) disables first-party export entirely,
|
|
69723
|
+
* which is how `--no-telemetry` and every library consumer stay silent.
|
|
69724
|
+
*
|
|
69725
|
+
* Build this **once per process** and share the resulting context — see
|
|
69726
|
+
* `telemetry-runtime.ts`. Effect keeps delta-temporality state on the metrics
|
|
69727
|
+
* exporter instance, so a second build starts with no previous snapshot and
|
|
69728
|
+
* re-reports every counter's full value, doubling every metric.
|
|
69729
|
+
*/
|
|
69730
|
+
const layerObservability = (options = null) => unwrap$3(gen(function* () {
|
|
69731
|
+
const endpoint = yield* OTEL_ENDPOINT;
|
|
69732
|
+
const authHeader = yield* OTEL_AUTH_HEADER;
|
|
69733
|
+
if (endpoint._tag !== "None" && authHeader._tag !== "None") return layerUserOtlp;
|
|
69734
|
+
return options === null ? empty$7 : merge$3(layerAxiomTraces(options), layerAxiomMetrics(options));
|
|
69735
|
+
}).pipe(orDie));
|
|
69736
|
+
/**
|
|
68259
69737
|
* Read a positive-millisecond timeout from an env var, falling back to
|
|
68260
69738
|
* `defaultMs` when the var is unset, non-finite, or not strictly positive.
|
|
68261
69739
|
*/
|
|
@@ -73606,149 +75084,6 @@ const mapPreparedSourceLabels = (labels, preparedSourceMap) => {
|
|
|
73606
75084
|
}
|
|
73607
75085
|
return mappedLabels;
|
|
73608
75086
|
};
|
|
73609
|
-
const REDACTED_PLACEHOLDER = "<redacted>";
|
|
73610
|
-
const KEEP_PREFIX = `$1${REDACTED_PLACEHOLDER}`;
|
|
73611
|
-
const KNOWN_SECRET_RULES = [
|
|
73612
|
-
{
|
|
73613
|
-
pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g,
|
|
73614
|
-
replacement: REDACTED_PLACEHOLDER
|
|
73615
|
-
},
|
|
73616
|
-
{
|
|
73617
|
-
pattern: /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}/g,
|
|
73618
|
-
replacement: REDACTED_PLACEHOLDER
|
|
73619
|
-
},
|
|
73620
|
-
{
|
|
73621
|
-
pattern: /(?<=:\/\/)[^\s/:@]+:[^\s/@]+(?=@)/g,
|
|
73622
|
-
replacement: REDACTED_PLACEHOLDER
|
|
73623
|
-
},
|
|
73624
|
-
{
|
|
73625
|
-
pattern: /\b(AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA|A3T[A-Z0-9])[0-9A-Z]{16,}/g,
|
|
73626
|
-
replacement: KEEP_PREFIX
|
|
73627
|
-
},
|
|
73628
|
-
{
|
|
73629
|
-
pattern: /\b(gh[pousr]_)[A-Za-z0-9]{36,}/g,
|
|
73630
|
-
replacement: KEEP_PREFIX
|
|
73631
|
-
},
|
|
73632
|
-
{
|
|
73633
|
-
pattern: /\b(github_pat_)[A-Za-z0-9_]{22,}/g,
|
|
73634
|
-
replacement: KEEP_PREFIX
|
|
73635
|
-
},
|
|
73636
|
-
{
|
|
73637
|
-
pattern: /\b(glpat-)[A-Za-z0-9_-]{20,}/g,
|
|
73638
|
-
replacement: KEEP_PREFIX
|
|
73639
|
-
},
|
|
73640
|
-
{
|
|
73641
|
-
pattern: /\b(xox[baprs]-)[A-Za-z0-9-]{10,}/g,
|
|
73642
|
-
replacement: KEEP_PREFIX
|
|
73643
|
-
},
|
|
73644
|
-
{
|
|
73645
|
-
pattern: /(?<=hooks\.slack\.com\/services\/)[A-Za-z0-9/+_-]{20,}/g,
|
|
73646
|
-
replacement: REDACTED_PLACEHOLDER
|
|
73647
|
-
},
|
|
73648
|
-
{
|
|
73649
|
-
pattern: /\b((?:sk|rk)_(?:live|test)_)[0-9A-Za-z]{10,}/g,
|
|
73650
|
-
replacement: KEEP_PREFIX
|
|
73651
|
-
},
|
|
73652
|
-
{
|
|
73653
|
-
pattern: /\b(sk-(?:proj-|ant-)?)[A-Za-z0-9_-]{20,}/g,
|
|
73654
|
-
replacement: KEEP_PREFIX
|
|
73655
|
-
},
|
|
73656
|
-
{
|
|
73657
|
-
pattern: /\b(AIza)[0-9A-Za-z_-]{35,}/g,
|
|
73658
|
-
replacement: KEEP_PREFIX
|
|
73659
|
-
},
|
|
73660
|
-
{
|
|
73661
|
-
pattern: /\b(ya29\.)[0-9A-Za-z_-]{20,}/g,
|
|
73662
|
-
replacement: KEEP_PREFIX
|
|
73663
|
-
},
|
|
73664
|
-
{
|
|
73665
|
-
pattern: /\b(npm_)[A-Za-z0-9]{36,}/g,
|
|
73666
|
-
replacement: KEEP_PREFIX
|
|
73667
|
-
},
|
|
73668
|
-
{
|
|
73669
|
-
pattern: /\b(SG\.)[A-Za-z0-9_-]{22,}\.[A-Za-z0-9_-]{43,}/g,
|
|
73670
|
-
replacement: KEEP_PREFIX
|
|
73671
|
-
},
|
|
73672
|
-
{
|
|
73673
|
-
pattern: /\b(SK)[0-9a-fA-F]{32,}/g,
|
|
73674
|
-
replacement: KEEP_PREFIX
|
|
73675
|
-
},
|
|
73676
|
-
{
|
|
73677
|
-
pattern: /\b(dop_v1_)[a-f0-9]{64,}/g,
|
|
73678
|
-
replacement: KEEP_PREFIX
|
|
73679
|
-
},
|
|
73680
|
-
{
|
|
73681
|
-
pattern: /\b(shp(?:at|ca|pa|ss)_)[a-fA-F0-9]{32,}/g,
|
|
73682
|
-
replacement: KEEP_PREFIX
|
|
73683
|
-
},
|
|
73684
|
-
{
|
|
73685
|
-
pattern: /\b(sq0[a-z]{3}-)[0-9A-Za-z_-]{22,}/g,
|
|
73686
|
-
replacement: KEEP_PREFIX
|
|
73687
|
-
},
|
|
73688
|
-
{
|
|
73689
|
-
pattern: /\b([0-9]{8,10}:AA)[0-9A-Za-z_-]{32,}/g,
|
|
73690
|
-
replacement: KEEP_PREFIX
|
|
73691
|
-
},
|
|
73692
|
-
{
|
|
73693
|
-
pattern: /(?<=\bBearer\s)[A-Za-z0-9._~+/=-]{16,}/g,
|
|
73694
|
-
replacement: REDACTED_PLACEHOLDER
|
|
73695
|
-
},
|
|
73696
|
-
{
|
|
73697
|
-
pattern: /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g,
|
|
73698
|
-
replacement: REDACTED_PLACEHOLDER
|
|
73699
|
-
}
|
|
73700
|
-
];
|
|
73701
|
-
const CANDIDATE_TOKEN_PATTERN = /[A-Za-z0-9_][A-Za-z0-9_-]*/g;
|
|
73702
|
-
const HEX_DIGEST_PATTERN = /^(?:[0-9a-f]{32}|[0-9a-f]{40}|[0-9a-f]{64})$/;
|
|
73703
|
-
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
73704
|
-
const HAS_LETTER_PATTERN = /[A-Za-z]/;
|
|
73705
|
-
const HAS_DIGIT_PATTERN = /[0-9]/;
|
|
73706
|
-
const shannonEntropyBits = (value) => {
|
|
73707
|
-
const counts = /* @__PURE__ */ new Map();
|
|
73708
|
-
for (const char of value) counts.set(char, (counts.get(char) ?? 0) + 1);
|
|
73709
|
-
let bits = 0;
|
|
73710
|
-
for (const count of counts.values()) {
|
|
73711
|
-
const probability = count / value.length;
|
|
73712
|
-
bits -= probability * Math.log2(probability);
|
|
73713
|
-
}
|
|
73714
|
-
return bits;
|
|
73715
|
-
};
|
|
73716
|
-
const looksLikeHighEntropySecret = (token) => {
|
|
73717
|
-
if (token.length < 32) return false;
|
|
73718
|
-
if (!HAS_LETTER_PATTERN.test(token) || !HAS_DIGIT_PATTERN.test(token)) return false;
|
|
73719
|
-
if (HEX_DIGEST_PATTERN.test(token) || UUID_PATTERN.test(token)) return false;
|
|
73720
|
-
return shannonEntropyBits(token) >= 3;
|
|
73721
|
-
};
|
|
73722
|
-
const redactHighEntropyTokens = (text) => text.replace(CANDIDATE_TOKEN_PATTERN, (token) => looksLikeHighEntropySecret(token) ? REDACTED_PLACEHOLDER : token);
|
|
73723
|
-
/**
|
|
73724
|
-
* Masks API keys, tokens, private keys, credentialed URLs, and emails
|
|
73725
|
-
* found anywhere inside a free-text string, returning the scrubbed text.
|
|
73726
|
-
* Applied to every diagnostic's `message` / `help` at construction time
|
|
73727
|
-
* so secrets never reach the terminal, the JSON report, or the score
|
|
73728
|
-
* API — react-doctor must never echo or transmit a user's secrets.
|
|
73729
|
-
*
|
|
73730
|
-
* Provider tokens keep their non-secret, type-identifying prefix (e.g.
|
|
73731
|
-
* `sk_live_<redacted>`, `ghp_<redacted>`, `AKIA<redacted>`) so the leaked
|
|
73732
|
-
* credential's type stays visible; structural or unknown-format secrets
|
|
73733
|
-
* with no meaningful prefix are masked whole.
|
|
73734
|
-
*
|
|
73735
|
-
* Runs the high-precision known-shape detectors first, then a generic
|
|
73736
|
-
* entropy-gated sweep for unknown-format secrets. Idempotent: the inert
|
|
73737
|
-
* `<redacted>` placeholder matches none of the detectors and is too
|
|
73738
|
-
* short for the generic sweep, so re-running leaves the text unchanged.
|
|
73739
|
-
*
|
|
73740
|
-
* Accepts `unknown` on purpose: callers feed it diagnostic `message` /
|
|
73741
|
-
* `help` that originate from oxlint JSON, which is only shape-checked at
|
|
73742
|
-
* the top level (the per-field `string` types are assumed, not validated).
|
|
73743
|
-
* A malformed non-string value returns `""` instead of throwing on
|
|
73744
|
-
* `.replace`, so one bad diagnostic can't abort parsing the whole batch.
|
|
73745
|
-
*/
|
|
73746
|
-
const redactSensitiveText = (text) => {
|
|
73747
|
-
if (typeof text !== "string" || text === "") return "";
|
|
73748
|
-
let redacted = text;
|
|
73749
|
-
for (const rule of KNOWN_SECRET_RULES) redacted = redacted.replace(rule.pattern, rule.replacement);
|
|
73750
|
-
return redactHighEntropyTokens(redacted);
|
|
73751
|
-
};
|
|
73752
75087
|
const REACT_MODULE_SOURCE = "react";
|
|
73753
75088
|
const REQUIRE_IDENTIFIER = "require";
|
|
73754
75089
|
const USE_IDENTIFIER = "use";
|
|
@@ -75828,7 +77163,7 @@ var Linter = class Linter extends Service()("react-doctor/Linter") {
|
|
|
75828
77163
|
static layerComposite = (backends) => succeed$3(Linter, Linter.of({ run: (input) => {
|
|
75829
77164
|
if (backends.length === 0) return empty$4;
|
|
75830
77165
|
let diagnostics = backends[0].run(input);
|
|
75831
|
-
for (let index = 1; index < backends.length; index++) diagnostics = diagnostics.pipe(concat(backends[index].run(input)));
|
|
77166
|
+
for (let index = 1; index < backends.length; index++) diagnostics = diagnostics.pipe(concat$1(backends[index].run(input)));
|
|
75832
77167
|
return diagnostics;
|
|
75833
77168
|
} }));
|
|
75834
77169
|
};
|
|
@@ -75942,14 +77277,6 @@ var Reporter = class Reporter extends Service()("react-doctor/Reporter") {
|
|
|
75942
77277
|
});
|
|
75943
77278
|
}));
|
|
75944
77279
|
};
|
|
75945
|
-
const HOME_DIRECTORY = os.homedir();
|
|
75946
|
-
const USER_HOME_PATTERNS = [/[A-Za-z]:[\\/]Users[\\/][^\\/]+/gi, /(?:\/Users\/|\/home\/)[^/\\]+/gi];
|
|
75947
|
-
const scrubSensitivePaths = (text) => {
|
|
75948
|
-
let scrubbed = text;
|
|
75949
|
-
if (HOME_DIRECTORY.length > 1) scrubbed = scrubbed.split(HOME_DIRECTORY).join("~");
|
|
75950
|
-
for (const pattern of USER_HOME_PATTERNS) scrubbed = scrubbed.replace(pattern, "~");
|
|
75951
|
-
return scrubbed;
|
|
75952
|
-
};
|
|
75953
77280
|
const ScoreApiResponseSchema = Struct({
|
|
75954
77281
|
score: Number$1,
|
|
75955
77282
|
label: String$1,
|
|
@@ -76911,7 +78238,7 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
76911
78238
|
suppressedRuleCounts: transform.summarizeSuppressions()
|
|
76912
78239
|
};
|
|
76913
78240
|
}).pipe(withSpan("runInspect", { attributes: {
|
|
76914
|
-
"inspect.directory": input.directory,
|
|
78241
|
+
"inspect.directory": scrubSensitivePaths(input.directory),
|
|
76915
78242
|
"inspect.includePathCount": input.includePaths.length,
|
|
76916
78243
|
"inspect.runDeadCode": input.runDeadCode,
|
|
76917
78244
|
"inspect.isCi": input.isCi,
|
|
@@ -77210,7 +78537,7 @@ const runEditorScanEffect = (input) => gen(function* () {
|
|
|
77210
78537
|
skipExplicitIncludePathFilter: true
|
|
77211
78538
|
}).pipe(provide(layers))));
|
|
77212
78539
|
}).pipe(withSpan("runEditorScan"));
|
|
77213
|
-
const runEditorScan = (input) => runPromise(runEditorScanEffect(input).pipe(provide(
|
|
78540
|
+
const runEditorScan = (input) => runPromise(runEditorScanEffect(input).pipe(provide(layerUserOtlp)));
|
|
77214
78541
|
const lookupOwnRule = (rule) => Object.hasOwn(REACT_DOCTOR_RULE_REGISTRY, rule) ? REACT_DOCTOR_RULE_REGISTRY[rule] : void 0;
|
|
77215
78542
|
/**
|
|
77216
78543
|
* Returns presentation metadata for `<plugin>/<rule>`, or `null` when the
|
|
@@ -77250,7 +78577,7 @@ const computeConfigFingerprint = (projectDirectory, version) => {
|
|
|
77250
78577
|
/** Display name used in client-facing messages and progress titles. */
|
|
77251
78578
|
const SERVER_DISPLAY_NAME = "React Doctor";
|
|
77252
78579
|
/** Server version reported in `serverInfo`; injected at build, `dev` from source. */
|
|
77253
|
-
const SERVER_VERSION = "0.9.
|
|
78580
|
+
const SERVER_VERSION = "0.9.10";
|
|
77254
78581
|
/** `Diagnostic.source` shown next to every published diagnostic. */
|
|
77255
78582
|
const DIAGNOSTIC_SOURCE = "react-doctor";
|
|
77256
78583
|
/**
|
|
@@ -78956,7 +80283,29 @@ const startLanguageServer$1 = (options = {}) => {
|
|
|
78956
80283
|
installProcessGuards(connection);
|
|
78957
80284
|
createServer(connection, options);
|
|
78958
80285
|
};
|
|
80286
|
+
const NANOSECONDS_PER_MILLISECOND = 1000000n;
|
|
80287
|
+
const LSP_TELEMETRY_EXPORT_INTERVAL_MS = 6e4;
|
|
78959
80288
|
const SENTRY_FLUSH_TIMEOUT_MS = 2e3;
|
|
80289
|
+
const METRIC_DISTRIBUTION_BOUNDARIES = [
|
|
80290
|
+
0,
|
|
80291
|
+
1,
|
|
80292
|
+
2,
|
|
80293
|
+
5,
|
|
80294
|
+
10,
|
|
80295
|
+
25,
|
|
80296
|
+
50,
|
|
80297
|
+
100,
|
|
80298
|
+
250,
|
|
80299
|
+
500,
|
|
80300
|
+
1e3,
|
|
80301
|
+
2500,
|
|
80302
|
+
5e3,
|
|
80303
|
+
1e4,
|
|
80304
|
+
3e4,
|
|
80305
|
+
6e4,
|
|
80306
|
+
3e5,
|
|
80307
|
+
6e5
|
|
80308
|
+
];
|
|
78960
80309
|
const METRIC = {
|
|
78961
80310
|
cliInvoked: "cli.invoked",
|
|
78962
80311
|
cliError: "cli.error",
|
|
@@ -79028,36 +80377,399 @@ const toCategoryKey = (category) => category.toLowerCase().replace(/[^a-z0-9]+/g
|
|
|
79028
80377
|
//#region src/cli/utils/is-env-flag-enabled.ts
|
|
79029
80378
|
const isEnvFlagEnabled = (value) => value === "1" || value?.toLowerCase() === "true";
|
|
79030
80379
|
//#endregion
|
|
79031
|
-
//#region src/cli/utils/
|
|
80380
|
+
//#region src/cli/utils/is-telemetry-enabled.ts
|
|
79032
80381
|
/**
|
|
79033
|
-
*
|
|
79034
|
-
*
|
|
79035
|
-
*
|
|
79036
|
-
*
|
|
79037
|
-
* (
|
|
80382
|
+
* Whether this process may emit telemetry of any kind — Sentry crash reports and
|
|
80383
|
+
* Axiom traces/metrics alike.
|
|
80384
|
+
*
|
|
80385
|
+
* Reads raw `process.argv` rather than parsed Commander options because the
|
|
80386
|
+
* decision is needed before the CLI parses its arguments (Sentry initializes as
|
|
80387
|
+
* the first statement of `cli/index.ts`).
|
|
80388
|
+
*
|
|
80389
|
+
* `REACT_DOCTOR_NO_TELEMETRY` was previously honored only by the language
|
|
80390
|
+
* server. It applies to the CLI too, which is what lets this repo's own tooling
|
|
80391
|
+
* — the benchmark harness and the delta-audit runner — keep their scans out of
|
|
80392
|
+
* production telemetry now that disabling Sentry alone no longer silences
|
|
80393
|
+
* everything.
|
|
79038
80394
|
*/
|
|
79039
|
-
const
|
|
80395
|
+
const isTelemetryEnabled = () => {
|
|
80396
|
+
if (process.argv.includes("--no-score") || process.argv.includes("--no-telemetry")) return false;
|
|
80397
|
+
if (isEnvFlagEnabled(process.env.REACT_DOCTOR_NO_TELEMETRY)) return false;
|
|
80398
|
+
if (process.env.VITEST || process.env.NODE_ENV === "test") return false;
|
|
80399
|
+
return true;
|
|
80400
|
+
};
|
|
80401
|
+
//#endregion
|
|
80402
|
+
//#region src/cli/utils/is-ci-environment.ts
|
|
80403
|
+
const CI_ENVIRONMENT_VARIABLES = [
|
|
80404
|
+
"GITHUB_ACTIONS",
|
|
80405
|
+
"GITLAB_CI",
|
|
80406
|
+
"CIRCLECI"
|
|
80407
|
+
];
|
|
80408
|
+
const CI_PROVIDER_BY_ENVIRONMENT_VARIABLE = [
|
|
80409
|
+
["GITHUB_ACTIONS", "github-actions"],
|
|
80410
|
+
["GITLAB_CI", "gitlab-ci"],
|
|
80411
|
+
["CIRCLECI", "circleci"],
|
|
80412
|
+
["BUILDKITE", "buildkite"],
|
|
80413
|
+
["JENKINS_URL", "jenkins"],
|
|
80414
|
+
["TF_BUILD", "azure-pipelines"],
|
|
80415
|
+
["CODEBUILD_BUILD_ID", "aws-codebuild"],
|
|
80416
|
+
["TEAMCITY_VERSION", "teamcity"],
|
|
80417
|
+
["BITBUCKET_BUILD_NUMBER", "bitbucket"],
|
|
80418
|
+
["TRAVIS", "travis"],
|
|
80419
|
+
["DRONE", "drone"],
|
|
80420
|
+
["SEMAPHORE", "semaphore"],
|
|
80421
|
+
["APPVEYOR", "appveyor"],
|
|
80422
|
+
["HARNESS_BUILD_ID", "harness"],
|
|
80423
|
+
["BUDDY", "buddy"],
|
|
80424
|
+
["CF_BUILD_ID", "codefresh"],
|
|
80425
|
+
["NETLIFY", "netlify"],
|
|
80426
|
+
["RAILWAY_SERVICE_ID", "railway"],
|
|
80427
|
+
["VERCEL", "vercel"],
|
|
80428
|
+
["CM_BUILD_ID", "codemagic"],
|
|
80429
|
+
["PROW_JOB_ID", "prow"],
|
|
80430
|
+
["AGOLA_GIT_REF", "agola"],
|
|
80431
|
+
["CIRRUS_CI", "cirrus-ci"],
|
|
80432
|
+
["BLACKSMITH_STICKYDISK_TOKEN", "blacksmith"],
|
|
80433
|
+
["WARPBUILD_RUNNER_VERIFICATION_TOKEN", "warpbuild"],
|
|
80434
|
+
["NSC_CACHE_PATH", "namespace"],
|
|
80435
|
+
["UBICLOUD_CACHE_URL", "ubicloud"],
|
|
80436
|
+
["RENDER", "render"],
|
|
80437
|
+
["FLY_APP_NAME", "fly-io"]
|
|
80438
|
+
];
|
|
80439
|
+
const GITHUB_ACTION_MARKER_ENVIRONMENT_VARIABLE = "REACT_DOCTOR_GITHUB_ACTION";
|
|
80440
|
+
const CODING_AGENT_BY_ENVIRONMENT_VARIABLE = [
|
|
80441
|
+
["CLAUDECODE", "claude-code"],
|
|
80442
|
+
["CLAUDE_CODE", "claude-code"],
|
|
80443
|
+
["CURSOR_AGENT", "cursor"],
|
|
80444
|
+
["CODEX_CI", "codex"],
|
|
80445
|
+
["CODEX_SANDBOX", "codex"],
|
|
80446
|
+
["CODEX_SANDBOX_NETWORK_DISABLED", "codex"],
|
|
80447
|
+
["OPENCODE", "opencode"],
|
|
80448
|
+
["GOOSE_TERMINAL", "goose"],
|
|
80449
|
+
["AMP_THREAD_ID", "amp"],
|
|
80450
|
+
["CLINE_ACTIVE", "cline"],
|
|
80451
|
+
["AUGMENT_AGENT", "augment"],
|
|
80452
|
+
["TRAE_AI_SHELL_ID", "trae-ai"]
|
|
80453
|
+
];
|
|
80454
|
+
const GENERIC_CODING_AGENT_ENVIRONMENT_VARIABLES = ["AGENT_SESSION_ID", "AGENT_THREAD_ID"];
|
|
80455
|
+
const CODING_AGENT_ENVIRONMENT_VALUE_VARIABLES = ["AGENT"];
|
|
80456
|
+
const CODING_AGENT_ENVIRONMENT_VALUES = { AGENT: ["amp", "goose"] };
|
|
80457
|
+
[...CODING_AGENT_BY_ENVIRONMENT_VARIABLE.map(([environmentVariable]) => environmentVariable), ...GENERIC_CODING_AGENT_ENVIRONMENT_VARIABLES];
|
|
80458
|
+
const FALSY_CI_FLAG_VALUES = new Set([
|
|
80459
|
+
"",
|
|
80460
|
+
"0",
|
|
80461
|
+
"false"
|
|
80462
|
+
]);
|
|
80463
|
+
const isCiFlagSet = (value) => value !== void 0 && !FALSY_CI_FLAG_VALUES.has(value.toLowerCase());
|
|
80464
|
+
const isCiEnvironment = (env = process.env) => CI_ENVIRONMENT_VARIABLES.some((environmentVariable) => Boolean(env[environmentVariable])) || isCiFlagSet(env.CI);
|
|
80465
|
+
const detectCiProvider = () => {
|
|
80466
|
+
for (const [environmentVariable, provider] of CI_PROVIDER_BY_ENVIRONMENT_VARIABLE) if (process.env[environmentVariable]) return provider;
|
|
80467
|
+
return isCiFlagSet(process.env.CI) ? "unknown" : null;
|
|
80468
|
+
};
|
|
80469
|
+
const isOfficialGithubAction = () => Boolean(process.env[GITHUB_ACTION_MARKER_ENVIRONMENT_VARIABLE]);
|
|
80470
|
+
const detectCiEventName = () => process.env.GITHUB_EVENT_NAME?.trim() || null;
|
|
80471
|
+
const detectCodingAgentFromValue = () => {
|
|
80472
|
+
for (const environmentVariable of CODING_AGENT_ENVIRONMENT_VALUE_VARIABLES) {
|
|
80473
|
+
const value = process.env[environmentVariable]?.toLowerCase();
|
|
80474
|
+
if (value && CODING_AGENT_ENVIRONMENT_VALUES[environmentVariable].includes(value)) return value;
|
|
80475
|
+
}
|
|
80476
|
+
return null;
|
|
80477
|
+
};
|
|
80478
|
+
const detectCodingAgent = () => {
|
|
80479
|
+
for (const [environmentVariable, agent] of CODING_AGENT_BY_ENVIRONMENT_VARIABLE) if (process.env[environmentVariable]) return agent;
|
|
80480
|
+
const agentFromValue = detectCodingAgentFromValue();
|
|
80481
|
+
if (agentFromValue) return agentFromValue;
|
|
80482
|
+
if (GENERIC_CODING_AGENT_ENVIRONMENT_VARIABLES.some((environmentVariable) => process.env[environmentVariable])) return "unknown";
|
|
80483
|
+
return null;
|
|
80484
|
+
};
|
|
80485
|
+
const isCodingAgentEnvironment = () => detectCodingAgent() !== null;
|
|
80486
|
+
//#endregion
|
|
80487
|
+
//#region src/cli/utils/detect-terminal-kind.ts
|
|
80488
|
+
const TERMINAL_BY_TERM_PROGRAM = [
|
|
80489
|
+
["vscode", "vscode"],
|
|
80490
|
+
["iTerm.app", "iterm"],
|
|
80491
|
+
["Apple_Terminal", "apple-terminal"],
|
|
80492
|
+
["WezTerm", "wezterm"],
|
|
80493
|
+
["ghostty", "ghostty"],
|
|
80494
|
+
["Hyper", "hyper"],
|
|
80495
|
+
["Tabby", "tabby"],
|
|
80496
|
+
["rio", "rio"]
|
|
80497
|
+
];
|
|
79040
80498
|
/**
|
|
79041
|
-
*
|
|
79042
|
-
*
|
|
79043
|
-
*
|
|
79044
|
-
*
|
|
80499
|
+
* Best-effort label for the terminal emulator / editor hosting the CLI,
|
|
80500
|
+
* derived from terminal-identity env vars. Recorded as the `terminalKind` run
|
|
80501
|
+
* tag so we can see where React Doctor is actually run (nvim, VS Code, iTerm,
|
|
80502
|
+
* …) — the split Sentry can't otherwise see. Low-cardinality and free of any
|
|
80503
|
+
* username/path/secret, so it's safe as a tag. Editor terminals (nvim/vim)
|
|
80504
|
+
* win over the outer emulator because that's the surface a user is reading in;
|
|
80505
|
+
* "ci" marks a run with no interactive terminal; "unknown" when nothing matches.
|
|
80506
|
+
*/
|
|
80507
|
+
const detectTerminalKind = (env = process.env) => {
|
|
80508
|
+
if (env.NVIM) return "neovim";
|
|
80509
|
+
if (env.VIM_TERMINAL) return "vim";
|
|
80510
|
+
const termProgram = env.TERM_PROGRAM;
|
|
80511
|
+
if (termProgram) {
|
|
80512
|
+
for (const [marker, label] of TERMINAL_BY_TERM_PROGRAM) if (termProgram === marker) return label;
|
|
80513
|
+
}
|
|
80514
|
+
if (env.KITTY_WINDOW_ID || env.TERM === "xterm-kitty") return "kitty";
|
|
80515
|
+
if (env.WT_SESSION) return "windows-terminal";
|
|
80516
|
+
if (env.ALACRITTY_WINDOW_ID || env.TERM === "alacritty") return "alacritty";
|
|
80517
|
+
if (env.VTE_VERSION) return "vte";
|
|
80518
|
+
if (env.TMUX) return "tmux";
|
|
80519
|
+
if (isCiEnvironment(env)) return "ci";
|
|
80520
|
+
return "unknown";
|
|
80521
|
+
};
|
|
80522
|
+
//#endregion
|
|
80523
|
+
//#region src/cli/utils/is-debug-flag.ts
|
|
80524
|
+
/**
|
|
80525
|
+
* Whether the user passed `--debug` (surface the run's Sentry trace id, and
|
|
80526
|
+
* force performance tracing on so there's a trace to surface). Read straight
|
|
80527
|
+
* from argv rather than Commander's parsed flags because `initializeSentry()`
|
|
80528
|
+
* runs before Commander parses — the same reason `shouldEnableSentry()` reads
|
|
80529
|
+
* `--no-score` from argv. Sharing this one reader keeps the init-time sampling
|
|
80530
|
+
* override and the end-of-run print in agreement.
|
|
79045
80531
|
*/
|
|
79046
|
-
const
|
|
79047
|
-
|
|
79048
|
-
|
|
79049
|
-
|
|
79050
|
-
|
|
79051
|
-
|
|
79052
|
-
|
|
79053
|
-
|
|
80532
|
+
const isDebugFlagEnabled = (argv = process.argv) => argv.includes("--debug");
|
|
80533
|
+
//#endregion
|
|
80534
|
+
//#region src/cli/utils/is-git-hook-environment.ts
|
|
80535
|
+
const isGitHookEnvironment = () => Boolean(process.env.GIT_DIR);
|
|
80536
|
+
//#endregion
|
|
80537
|
+
//#region src/cli/utils/is-non-interactive-environment.ts
|
|
80538
|
+
const NON_INTERACTIVE_ENVIRONMENT_VARIABLES = [
|
|
80539
|
+
"CI",
|
|
80540
|
+
"GITHUB_ACTIONS",
|
|
80541
|
+
"GITLAB_CI",
|
|
80542
|
+
"BUILDKITE",
|
|
80543
|
+
"JENKINS_URL",
|
|
80544
|
+
"TF_BUILD",
|
|
80545
|
+
"CODEBUILD_BUILD_ID",
|
|
80546
|
+
"TEAMCITY_VERSION",
|
|
80547
|
+
"BITBUCKET_BUILD_NUMBER",
|
|
80548
|
+
"CIRCLECI",
|
|
80549
|
+
"TRAVIS",
|
|
80550
|
+
"DRONE",
|
|
80551
|
+
"GIT_DIR"
|
|
80552
|
+
];
|
|
80553
|
+
const isNonInteractiveEnvironment = () => NON_INTERACTIVE_ENVIRONMENT_VARIABLES.some((envVariable) => Boolean(process.env[envVariable])) || isCodingAgentEnvironment();
|
|
80554
|
+
//#endregion
|
|
80555
|
+
//#region src/cli/utils/version.ts
|
|
80556
|
+
const VERSION = process.env.VERSION ?? "0.0.0";
|
|
80557
|
+
//#endregion
|
|
80558
|
+
//#region src/cli/utils/json-mode.ts
|
|
80559
|
+
let context = null;
|
|
80560
|
+
const isJsonModeActive = () => context !== null;
|
|
80561
|
+
//#endregion
|
|
80562
|
+
//#region src/cli/utils/run-id.ts
|
|
80563
|
+
let cachedRunId;
|
|
80564
|
+
const getRunId = () => {
|
|
80565
|
+
cachedRunId ??= randomUUID();
|
|
80566
|
+
return cachedRunId;
|
|
80567
|
+
};
|
|
80568
|
+
//#endregion
|
|
80569
|
+
//#region src/cli/utils/build-run-context.ts
|
|
80570
|
+
const LSP_COMMAND = "experimental-lsp";
|
|
80571
|
+
const ROOT_SUBCOMMANDS = new Set([
|
|
80572
|
+
"design",
|
|
80573
|
+
"install",
|
|
80574
|
+
"setup",
|
|
80575
|
+
LSP_COMMAND
|
|
80576
|
+
]);
|
|
80577
|
+
const detectInvokedVia = () => {
|
|
80578
|
+
const userAgent = process.env.npm_config_user_agent;
|
|
80579
|
+
if (!userAgent) return "unknown";
|
|
80580
|
+
return userAgent.split("/", 1)[0]?.trim() || "unknown";
|
|
80581
|
+
};
|
|
80582
|
+
const detectNodeMajor = () => {
|
|
80583
|
+
const major = Number.parseInt(process.versions.node.split(".", 1)[0] ?? "", 10);
|
|
80584
|
+
return Number.isNaN(major) ? 0 : major;
|
|
80585
|
+
};
|
|
80586
|
+
const detectOrigin = (userArguments) => {
|
|
80587
|
+
if (detectCommand(userArguments) === LSP_COMMAND) return "lsp";
|
|
80588
|
+
if (isGitHookEnvironment()) return "git-hook";
|
|
80589
|
+
if (isCodingAgentEnvironment()) return "agent";
|
|
80590
|
+
if (isCiEnvironment()) return "ci";
|
|
80591
|
+
return "cli";
|
|
80592
|
+
};
|
|
80593
|
+
const detectCommand = (userArguments) => {
|
|
80594
|
+
for (const argument of userArguments) {
|
|
80595
|
+
if (argument === "--") break;
|
|
80596
|
+
if (argument.startsWith("-")) continue;
|
|
80597
|
+
return ROOT_SUBCOMMANDS.has(argument) ? argument : "inspect";
|
|
80598
|
+
}
|
|
80599
|
+
return "inspect";
|
|
80600
|
+
};
|
|
80601
|
+
/**
|
|
80602
|
+
* Snapshot of the current invocation, attached to Sentry events as the
|
|
80603
|
+
* `run` context to make crashes triage-able (which version, platform,
|
|
80604
|
+
* CI/agent, how it was invoked). Every field is cheap, synchronous, and
|
|
80605
|
+
* safe to read at any point — cwd reads fall back, env reads are
|
|
80606
|
+
* booleans — so it's rebuilt lazily at capture time when runtime-only
|
|
80607
|
+
* signals like `jsonMode` are finally known.
|
|
80608
|
+
*/
|
|
80609
|
+
const buildRunContext = () => {
|
|
80610
|
+
const userArguments = process.argv.slice(2);
|
|
80611
|
+
return {
|
|
80612
|
+
version: VERSION,
|
|
80613
|
+
runId: getRunId(),
|
|
80614
|
+
origin: detectOrigin(userArguments),
|
|
80615
|
+
command: detectCommand(userArguments),
|
|
80616
|
+
argv: scrubSensitivePaths(userArguments.join(" ")),
|
|
80617
|
+
cwd: scrubSensitivePaths(process.cwd()),
|
|
80618
|
+
node: process.version,
|
|
80619
|
+
nodeMajor: detectNodeMajor(),
|
|
80620
|
+
platform: process.platform,
|
|
80621
|
+
arch: process.arch,
|
|
80622
|
+
ci: isCiEnvironment(),
|
|
80623
|
+
ciProvider: detectCiProvider(),
|
|
80624
|
+
eventName: detectCiEventName(),
|
|
80625
|
+
viaAction: isOfficialGithubAction(),
|
|
80626
|
+
codingAgent: detectCodingAgent(),
|
|
80627
|
+
interactive: !isNonInteractiveEnvironment(),
|
|
80628
|
+
terminalKind: detectTerminalKind(),
|
|
80629
|
+
jsonMode: isJsonModeActive(),
|
|
80630
|
+
debug: isDebugFlagEnabled(),
|
|
80631
|
+
invokedVia: detectInvokedVia(),
|
|
80632
|
+
lintBatchOrdering: resolveLintBatchOrdering()
|
|
80633
|
+
};
|
|
80634
|
+
};
|
|
80635
|
+
//#endregion
|
|
80636
|
+
//#region src/cli/utils/build-sentry-project-context.ts
|
|
80637
|
+
/**
|
|
80638
|
+
* Projects the {@link ProjectInfo} we already detect during a scan into the
|
|
80639
|
+
* Sentry scope shape: a handful of searchable `project.*` tags plus the
|
|
80640
|
+
* anonymous project *shape* as a `project` context block. Lets crash/transaction
|
|
80641
|
+
* triage answer "which kind of project hit this?" (framework, React/Expo
|
|
80642
|
+
* version, TypeScript, size) without sending source code — and deliberately
|
|
80643
|
+
* omits `projectName` and `rootDirectory`, the two identifying fields, so the
|
|
80644
|
+
* project can't be tied back to a specific company/repo.
|
|
80645
|
+
*/
|
|
80646
|
+
const buildSentryProjectContext = (projectInfo) => ({
|
|
80647
|
+
tags: {
|
|
80648
|
+
"project.framework": projectInfo.framework,
|
|
80649
|
+
"project.reactMajor": projectInfo.reactMajorVersion,
|
|
80650
|
+
"project.typescript": projectInfo.hasTypeScript,
|
|
80651
|
+
"project.reactCompiler": projectInfo.hasReactCompiler,
|
|
80652
|
+
"project.expo": projectInfo.expoVersion !== null,
|
|
80653
|
+
"project.reactNative": projectInfo.hasReactNativeWorkspace
|
|
80654
|
+
},
|
|
80655
|
+
context: {
|
|
80656
|
+
framework: projectInfo.framework,
|
|
80657
|
+
reactVersion: projectInfo.reactVersion,
|
|
80658
|
+
reactMajorVersion: projectInfo.reactMajorVersion,
|
|
80659
|
+
hasTypeScript: projectInfo.hasTypeScript,
|
|
80660
|
+
hasReactCompiler: projectInfo.hasReactCompiler,
|
|
80661
|
+
tanstackQueryVersion: projectInfo.tanstackQueryVersion,
|
|
80662
|
+
mobxVersion: projectInfo.mobxVersion,
|
|
80663
|
+
styledComponentsVersion: projectInfo.styledComponentsVersion,
|
|
80664
|
+
tailwindVersion: projectInfo.tailwindVersion,
|
|
80665
|
+
zodVersion: projectInfo.zodVersion,
|
|
80666
|
+
preactVersion: projectInfo.preactVersion,
|
|
80667
|
+
hasReactNativeWorkspace: projectInfo.hasReactNativeWorkspace,
|
|
80668
|
+
expoVersion: projectInfo.expoVersion,
|
|
80669
|
+
hasReanimated: projectInfo.hasReanimated,
|
|
80670
|
+
sourceFileCount: projectInfo.sourceFileCount
|
|
79054
80671
|
}
|
|
79055
|
-
|
|
79056
|
-
|
|
79057
|
-
|
|
79058
|
-
|
|
79059
|
-
|
|
80672
|
+
});
|
|
80673
|
+
let currentProjectInfo = null;
|
|
80674
|
+
const getSentryProjectInfo = () => currentProjectInfo;
|
|
80675
|
+
//#endregion
|
|
80676
|
+
//#region src/cli/utils/build-sentry-scope.ts
|
|
80677
|
+
/**
|
|
80678
|
+
* Projects a {@link RunContext} snapshot (plus the current run's
|
|
80679
|
+
* {@link getSentryProjectInfo project info}, when a scan has discovered it) into
|
|
80680
|
+
* the Sentry scope shape — the searchable `tags` that make crashes/transactions
|
|
80681
|
+
* filterable (which command, origin, CI provider, coding agent, Node major,
|
|
80682
|
+
* package manager, project framework/React major) plus the full `run` and
|
|
80683
|
+
* `project` context blocks for deep triage.
|
|
80684
|
+
*
|
|
80685
|
+
* Shared by `instrument.ts` (seeded as `initialScope` so *every* event,
|
|
80686
|
+
* including performance transactions, carries it) and `report-error.ts` (a
|
|
80687
|
+
* capture-time refresh, since runtime-only signals like `jsonMode` and the
|
|
80688
|
+
* scanned project are only known once a command has begun).
|
|
80689
|
+
*/
|
|
80690
|
+
const buildSentryScope = (runContext = buildRunContext()) => {
|
|
80691
|
+
const tags = {
|
|
80692
|
+
origin: runContext.origin,
|
|
80693
|
+
command: runContext.command,
|
|
80694
|
+
ci: runContext.ci,
|
|
80695
|
+
ciProvider: runContext.ciProvider,
|
|
80696
|
+
eventName: runContext.eventName,
|
|
80697
|
+
viaAction: runContext.viaAction,
|
|
80698
|
+
codingAgent: runContext.codingAgent,
|
|
80699
|
+
interactive: runContext.interactive,
|
|
80700
|
+
terminalKind: runContext.terminalKind,
|
|
80701
|
+
jsonMode: runContext.jsonMode,
|
|
80702
|
+
debug: runContext.debug,
|
|
80703
|
+
invokedVia: runContext.invokedVia,
|
|
80704
|
+
nodeMajor: runContext.nodeMajor,
|
|
80705
|
+
lintBatchOrdering: runContext.lintBatchOrdering
|
|
80706
|
+
};
|
|
80707
|
+
const contexts = { run: { ...runContext } };
|
|
80708
|
+
const projectInfo = getSentryProjectInfo();
|
|
80709
|
+
if (projectInfo) {
|
|
80710
|
+
const project = buildSentryProjectContext(projectInfo);
|
|
80711
|
+
Object.assign(tags, project.tags);
|
|
80712
|
+
contexts.project = project.context;
|
|
79060
80713
|
}
|
|
80714
|
+
return {
|
|
80715
|
+
tags,
|
|
80716
|
+
contexts
|
|
80717
|
+
};
|
|
80718
|
+
};
|
|
80719
|
+
//#endregion
|
|
80720
|
+
//#region src/cli/utils/to-span-attributes.ts
|
|
80721
|
+
/**
|
|
80722
|
+
* Converts a Sentry tag map (which permits `null`/`undefined` to denote an
|
|
80723
|
+
* absent signal) into Sentry/OTel span attributes, which only accept primitives.
|
|
80724
|
+
* Missing values are dropped rather than coerced, so an absent signal doesn't
|
|
80725
|
+
* become a misleading `"null"` or `"undefined"` attribute.
|
|
80726
|
+
*/
|
|
80727
|
+
const toSpanAttributes = (tags) => {
|
|
80728
|
+
const attributes = {};
|
|
80729
|
+
for (const [key, value] of Object.entries(tags)) if (value != null) attributes[key] = value;
|
|
80730
|
+
return attributes;
|
|
80731
|
+
};
|
|
80732
|
+
//#endregion
|
|
80733
|
+
//#region src/cli/utils/record-metric.ts
|
|
80734
|
+
const withRunAttributes = (attributes) => {
|
|
80735
|
+
const merged = {
|
|
80736
|
+
...toSpanAttributes(buildSentryScope().tags),
|
|
80737
|
+
...toSpanAttributes(attributes ?? {})
|
|
80738
|
+
};
|
|
80739
|
+
const stringified = {};
|
|
80740
|
+
for (const [key, value] of Object.entries(merged)) stringified[key] = typeof value === "string" ? anonymizeText(value) : String(value);
|
|
80741
|
+
return stringified;
|
|
80742
|
+
};
|
|
80743
|
+
/**
|
|
80744
|
+
* Emits a counter into Effect's metric registry, where the OTLP exporter picks
|
|
80745
|
+
* it up at flush time.
|
|
80746
|
+
*
|
|
80747
|
+
* A guarded, swallow-on-throw no-op unless telemetry is enabled, so it's inert
|
|
80748
|
+
* under `--no-score` / `--no-telemetry`, in tests, and for the programmatic
|
|
80749
|
+
* `@react-doctor/api` library. Counters are independent of trace sampling, so
|
|
80750
|
+
* they are still recorded when tracing is off.
|
|
80751
|
+
*/
|
|
80752
|
+
const recordCount = (name, value = 1, attributes) => {
|
|
80753
|
+
if (!isTelemetryEnabled()) return;
|
|
80754
|
+
try {
|
|
80755
|
+
counter(name).pipe(withAttributes(withRunAttributes(attributes))).updateUnsafe(value, empty$8());
|
|
80756
|
+
} catch {}
|
|
80757
|
+
};
|
|
80758
|
+
/**
|
|
80759
|
+
* Emits a distribution (value ranges — durations, sizes, scores). Same gating
|
|
80760
|
+
* and run-attribute handling as {@link recordCount}.
|
|
80761
|
+
*
|
|
80762
|
+
* `unit` is recorded as an attribute rather than as OTLP metric metadata:
|
|
80763
|
+
* Effect's histogram carries no unit field, and keeping the millisecond/count
|
|
80764
|
+
* distinction queryable matters more than where it is stored.
|
|
80765
|
+
*/
|
|
80766
|
+
const recordDistribution = (name, value, options = {}) => {
|
|
80767
|
+
if (!isTelemetryEnabled()) return;
|
|
80768
|
+
try {
|
|
80769
|
+
const attributes = withRunAttributes(options.attributes);
|
|
80770
|
+
if (options.unit) attributes.unit = options.unit;
|
|
80771
|
+
histogram(name, { boundaries: METRIC_DISTRIBUTION_BOUNDARIES }).pipe(withAttributes(attributes)).updateUnsafe(value, empty$8());
|
|
80772
|
+
} catch {}
|
|
79061
80773
|
};
|
|
79062
80774
|
//#endregion
|
|
79063
80775
|
//#region src/cli/utils/scrub-sentry-event.ts
|
|
@@ -79108,29 +80820,112 @@ const scrubSentryEvent = (event) => {
|
|
|
79108
80820
|
}
|
|
79109
80821
|
};
|
|
79110
80822
|
//#endregion
|
|
79111
|
-
//#region src/cli/utils/
|
|
79112
|
-
/**
|
|
79113
|
-
*
|
|
79114
|
-
*
|
|
79115
|
-
*
|
|
79116
|
-
*
|
|
79117
|
-
*
|
|
79118
|
-
*
|
|
79119
|
-
|
|
79120
|
-
|
|
80823
|
+
//#region src/cli/utils/resolve-axiom-telemetry-options.ts
|
|
80824
|
+
/**
|
|
80825
|
+
* Resolves the credentials for first-party Axiom export, or `null` when this
|
|
80826
|
+
* process must not emit telemetry.
|
|
80827
|
+
*
|
|
80828
|
+
* Core deliberately does not read these itself — keeping the token on the CLI
|
|
80829
|
+
* side is what makes `@react-doctor/api` silent by construction rather than by a
|
|
80830
|
+
* runtime guard.
|
|
80831
|
+
*
|
|
80832
|
+
* Returning `null` for an empty token means an unconfigured build (or a
|
|
80833
|
+
* contributor's checkout without the token baked in) simply doesn't export,
|
|
80834
|
+
* instead of sending unauthenticated requests to Axiom on every run.
|
|
80835
|
+
*
|
|
80836
|
+
* The overrides are `REACT_DOCTOR_`-prefixed rather than the bare `AXIOM_TOKEN`
|
|
80837
|
+
* / `AXIOM_DATASET` names Axiom's own tooling uses. Those are common in the
|
|
80838
|
+
* environment of anyone who already runs Axiom, and reading them here would
|
|
80839
|
+
* silently redirect React Doctor's telemetry into an unrelated account — or
|
|
80840
|
+
* fail against a dataset that isn't shaped for it — without the user ever
|
|
80841
|
+
* asking for that.
|
|
80842
|
+
*/
|
|
80843
|
+
const resolveAxiomTelemetryOptions = () => {
|
|
80844
|
+
if (!isTelemetryEnabled()) return null;
|
|
80845
|
+
const token = process.env.REACT_DOCTOR_AXIOM_TOKEN || "xaat-31b59107-855d-4917-8fab-6dc29fb459ce";
|
|
80846
|
+
if (!token) return null;
|
|
80847
|
+
return {
|
|
80848
|
+
token: make$30(token),
|
|
80849
|
+
domain: process.env.REACT_DOCTOR_AXIOM_DOMAIN || "https://api.axiom.co",
|
|
80850
|
+
tracesDataset: process.env.REACT_DOCTOR_AXIOM_DATASET || "react-doctor",
|
|
80851
|
+
metricsDataset: process.env.REACT_DOCTOR_AXIOM_METRICS_DATASET || "react-doctor-metrics",
|
|
80852
|
+
serviceVersion: VERSION
|
|
80853
|
+
};
|
|
80854
|
+
};
|
|
80855
|
+
//#endregion
|
|
80856
|
+
//#region src/cli/utils/telemetry-runtime.ts
|
|
80857
|
+
const isUserOtlpConfigured = () => Boolean(process.env.REACT_DOCTOR_OTLP_ENDPOINT) && Boolean(process.env.REACT_DOCTOR_OTLP_AUTH_HEADER);
|
|
80858
|
+
let telemetryScope = null;
|
|
80859
|
+
let telemetryContext = null;
|
|
80860
|
+
let isBuilt = false;
|
|
80861
|
+
let pendingShutdown = null;
|
|
80862
|
+
/**
|
|
80863
|
+
* Builds the telemetry layer once and hands back its context.
|
|
80864
|
+
*
|
|
80865
|
+
* The CLI is an imperative shell around several separate `Effect.runPromise`
|
|
80866
|
+
* calls — the scan program, the renderer, and the run root span all run
|
|
80867
|
+
* independently. Providing a fresh layer to each would create a separate set of
|
|
80868
|
+
* OTLP exporters per program: each holds its own span buffer and its own
|
|
80869
|
+
* shutdown flush, so exit latency would multiply, the root span would land in a
|
|
80870
|
+
* different export than its children, and — because Effect tracks
|
|
80871
|
+
* delta-temporality state per exporter instance — every counter would be
|
|
80872
|
+
* re-reported in full by each new metrics exporter.
|
|
80873
|
+
*
|
|
80874
|
+
* Building into a long-lived scope instead means one tracer and one metrics
|
|
80875
|
+
* exporter shared by all of them: child spans nest under the run span natively,
|
|
80876
|
+
* with no `ExternalSpan` stitching, and one flush at exit ships both signals.
|
|
80877
|
+
*
|
|
80878
|
+
* Returns `null` when telemetry is disabled or unconfigured, which is what keeps
|
|
80879
|
+
* `--no-telemetry` and unconfigured builds from opening a scope at all.
|
|
80880
|
+
*
|
|
80881
|
+
* `exportIntervalMs` lets a long-running process (the language server) ship
|
|
80882
|
+
* telemetry periodically instead of only at shutdown.
|
|
80883
|
+
*/
|
|
80884
|
+
const getTelemetryContext = (overrides = {}) => {
|
|
80885
|
+
if (isBuilt) return telemetryContext;
|
|
80886
|
+
isBuilt = true;
|
|
80887
|
+
if (!isTelemetryEnabled()) return null;
|
|
80888
|
+
const options = resolveAxiomTelemetryOptions();
|
|
80889
|
+
if (options === null && !isUserOtlpConfigured()) return null;
|
|
79121
80890
|
try {
|
|
79122
|
-
|
|
79123
|
-
|
|
79124
|
-
|
|
79125
|
-
|
|
79126
|
-
|
|
80891
|
+
const scope = makeUnsafe$5();
|
|
80892
|
+
telemetryContext = runSync(buildWithScope(layerObservability(options === null ? null : {
|
|
80893
|
+
...options,
|
|
80894
|
+
...overrides
|
|
80895
|
+
}), scope));
|
|
80896
|
+
telemetryScope = scope;
|
|
79127
80897
|
} catch {
|
|
79128
|
-
|
|
80898
|
+
telemetryContext = null;
|
|
80899
|
+
telemetryScope = null;
|
|
79129
80900
|
}
|
|
80901
|
+
return telemetryContext;
|
|
80902
|
+
};
|
|
80903
|
+
/**
|
|
80904
|
+
* Closes the telemetry scope, which is what ships buffered spans and metrics.
|
|
80905
|
+
*
|
|
80906
|
+
* Both exporters flush during scope finalization, bounded by
|
|
80907
|
+
* `TELEMETRY_SHUTDOWN_TIMEOUT_MS`. Because the scope is built once and shared,
|
|
80908
|
+
* there is exactly one of each exporter per process — which is what keeps
|
|
80909
|
+
* metrics honest: Effect tracks delta-temporality state on the exporter
|
|
80910
|
+
* instance, so a second one would start with no previous snapshot and re-report
|
|
80911
|
+
* every counter's full value, doubling every metric.
|
|
80912
|
+
*
|
|
80913
|
+
* Memoized for the same reason: several exit paths can fire (a `--debug` user
|
|
80914
|
+
* error flushes, then the top-level catch flushes again), and repeat callers
|
|
80915
|
+
* must await the original shutdown rather than start a second one.
|
|
80916
|
+
*
|
|
80917
|
+
* Swallows failures so telemetry can never mask the user's result.
|
|
80918
|
+
*/
|
|
80919
|
+
const shutdownTelemetry = async () => {
|
|
80920
|
+
if (pendingShutdown !== null) return pendingShutdown;
|
|
80921
|
+
getTelemetryContext();
|
|
80922
|
+
const scope = telemetryScope;
|
|
80923
|
+
if (scope === null) return;
|
|
80924
|
+
telemetryScope = null;
|
|
80925
|
+
telemetryContext = null;
|
|
80926
|
+
pendingShutdown = runPromise(close(scope, void_$1)).catch(() => {});
|
|
80927
|
+
return pendingShutdown;
|
|
79130
80928
|
};
|
|
79131
|
-
//#endregion
|
|
79132
|
-
//#region src/cli/utils/version.ts
|
|
79133
|
-
const VERSION = process.env.VERSION ?? "0.0.0";
|
|
79134
80929
|
//#endregion
|
|
79135
80930
|
//#region src/cli/utils/sentry-config.ts
|
|
79136
80931
|
/**
|
|
@@ -79159,57 +80954,49 @@ const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@$
|
|
|
79159
80954
|
* overridable via the standard `SENTRY_ENVIRONMENT` env var.
|
|
79160
80955
|
*/
|
|
79161
80956
|
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion(VERSION) ? "development" : "production");
|
|
79162
|
-
/**
|
|
79163
|
-
* Performance-tracing sample rate in `[0, 1]`. Reads `SENTRY_TRACES_SAMPLE_RATE`
|
|
79164
|
-
* (set to `0` to disable tracing) and falls back to
|
|
79165
|
-
* {@link SENTRY_DEFAULT_TRACES_SAMPLE_RATE}. Invalid / out-of-range values fall
|
|
79166
|
-
* back to the default rather than silently disabling tracing.
|
|
79167
|
-
*/
|
|
79168
|
-
const resolveTracesSampleRate = () => {
|
|
79169
|
-
const raw = process.env.SENTRY_TRACES_SAMPLE_RATE;
|
|
79170
|
-
if (raw === void 0 || raw.trim() === "") return 1;
|
|
79171
|
-
const parsed = Number(raw);
|
|
79172
|
-
if (Number.isNaN(parsed) || parsed < 0 || parsed > 1) return 1;
|
|
79173
|
-
return parsed;
|
|
79174
|
-
};
|
|
79175
80957
|
//#endregion
|
|
79176
80958
|
//#region src/lsp-telemetry.ts
|
|
79177
80959
|
/**
|
|
79178
|
-
*
|
|
79179
|
-
*
|
|
79180
|
-
*
|
|
79181
|
-
*
|
|
79182
|
-
*
|
|
79183
|
-
*
|
|
79184
|
-
* contract (no IP, no paths/secrets).
|
|
80960
|
+
* Telemetry for the editor language server (`react-doctor experimental-lsp`).
|
|
80961
|
+
* Mirrors the CLI's model — a per-scan wide-event span plus counters and
|
|
80962
|
+
* distributions to Axiom, with crashes to Sentry — but with an LSP-appropriate
|
|
80963
|
+
* scope instead of the CLI run context, since the daemon isn't a one-shot
|
|
80964
|
+
* command. Shares the CLI's DSN, release, and the anonymization scrubbers, so
|
|
80965
|
+
* editor telemetry honors the same privacy contract (no IP, no paths/secrets).
|
|
79185
80966
|
*
|
|
79186
|
-
* Every emit is a guarded, swallow-on-throw no-op unless
|
|
80967
|
+
* Every emit is a guarded, swallow-on-throw no-op unless telemetry is live, so a
|
|
79187
80968
|
* telemetry failure (or an opted-out / test run) can never disrupt the editor
|
|
79188
80969
|
* session.
|
|
80970
|
+
*
|
|
80971
|
+
* Unlike the one-shot CLI, this process can run for hours, so its exporters use
|
|
80972
|
+
* a short periodic interval — telemetry ships while the editor session is alive
|
|
80973
|
+
* rather than only when the server shuts down (which it may never cleanly do).
|
|
79189
80974
|
*/
|
|
79190
|
-
let lspTracesSampleRate = 0;
|
|
79191
80975
|
const nodeMajorVersion = () => Number.parseInt(process.versions.node.split(".", 1)[0] ?? "", 10) || 0;
|
|
79192
|
-
|
|
79193
|
-
|
|
79194
|
-
|
|
79195
|
-
|
|
79196
|
-
|
|
79197
|
-
|
|
79198
|
-
|
|
79199
|
-
const
|
|
80976
|
+
/**
|
|
80977
|
+
* Opens the shared telemetry runtime with the daemon's periodic export
|
|
80978
|
+
* interval. Called at startup rather than lazily from the first scan: session
|
|
80979
|
+
* metrics are recorded before any scan completes, and if the editor kills the
|
|
80980
|
+
* server before one does, a runtime that was never built means those counters
|
|
80981
|
+
* are never exported.
|
|
80982
|
+
*/
|
|
80983
|
+
const getLspTelemetryContext = () => getTelemetryContext({ exportIntervalMs: LSP_TELEMETRY_EXPORT_INTERVAL_MS });
|
|
79200
80984
|
/**
|
|
79201
80985
|
* Initializes Sentry for the language server. Safe to call once at startup; a
|
|
79202
80986
|
* no-op when already initialized or when telemetry is opted out / disabled.
|
|
80987
|
+
*
|
|
80988
|
+
* Performance tracing is off — the `lsp.scan` wide event is an Effect span
|
|
80989
|
+
* exported to Axiom, and Effect has a single `Tracer` reference.
|
|
79203
80990
|
*/
|
|
79204
80991
|
const initializeLspSentry = (serverVersion) => {
|
|
79205
|
-
if (Sentry.isInitialized() || !
|
|
79206
|
-
|
|
80992
|
+
if (Sentry.isInitialized() || !isTelemetryEnabled()) return;
|
|
80993
|
+
getLspTelemetryContext();
|
|
79207
80994
|
Sentry.init({
|
|
79208
80995
|
dsn: process.env.SENTRY_DSN || "https://f253d570240a59b8dbd77b7a548ef133@o4510226365743104.ingest.us.sentry.io/4511487817809920",
|
|
79209
80996
|
release: resolveSentryRelease(),
|
|
79210
80997
|
environment: resolveSentryEnvironment(),
|
|
79211
80998
|
sendDefaultPii: false,
|
|
79212
|
-
tracesSampleRate:
|
|
80999
|
+
tracesSampleRate: 0,
|
|
79213
81000
|
debug: isEnvFlagEnabled(process.env.SENTRY_DEBUG),
|
|
79214
81001
|
initialScope: {
|
|
79215
81002
|
tags: {
|
|
@@ -79226,9 +81013,7 @@ const initializeLspSentry = (serverVersion) => {
|
|
|
79226
81013
|
arch: process.arch
|
|
79227
81014
|
} }
|
|
79228
81015
|
},
|
|
79229
|
-
beforeSend: (event) => scrubSentryEvent(event)
|
|
79230
|
-
beforeSendTransaction: (event) => scrubSentryEvent(event),
|
|
79231
|
-
beforeSendMetric: (metric) => scrubSentryMetric(metric)
|
|
81016
|
+
beforeSend: (event) => scrubSentryEvent(event)
|
|
79232
81017
|
});
|
|
79233
81018
|
};
|
|
79234
81019
|
/**
|
|
@@ -79254,36 +81039,45 @@ const buildLspScanEventAttributes = (scan) => {
|
|
|
79254
81039
|
return attributes;
|
|
79255
81040
|
};
|
|
79256
81041
|
const emitSessionStart = (session) => {
|
|
79257
|
-
|
|
79258
|
-
|
|
79259
|
-
|
|
79260
|
-
|
|
79261
|
-
|
|
79262
|
-
|
|
79263
|
-
|
|
79264
|
-
lintAvailable: session.lintAvailable
|
|
79265
|
-
} });
|
|
79266
|
-
} catch {}
|
|
81042
|
+
recordCount(METRIC.lspSessionStarted, 1, {
|
|
81043
|
+
nodeMajor: session.nodeMajor,
|
|
81044
|
+
projectCount: session.projectCount,
|
|
81045
|
+
workspaceFolderCount: session.workspaceFolderCount,
|
|
81046
|
+
scanOnType: session.scanOnType,
|
|
81047
|
+
lintAvailable: session.lintAvailable
|
|
81048
|
+
});
|
|
79267
81049
|
};
|
|
79268
81050
|
const emitWorkspaceScan = (scan) => {
|
|
79269
|
-
|
|
81051
|
+
recordCount(METRIC.lspScanCompleted, 1, {
|
|
81052
|
+
trigger: scan.trigger,
|
|
81053
|
+
lintDegraded: scan.lintDegraded
|
|
81054
|
+
});
|
|
81055
|
+
recordDistribution(METRIC.lspScanDuration, scan.durationMs, {
|
|
81056
|
+
unit: "millisecond",
|
|
81057
|
+
attributes: { trigger: scan.trigger }
|
|
81058
|
+
});
|
|
81059
|
+
recordDistribution(METRIC.lspScanDiagnostics, scan.totalDiagnostics, { attributes: { trigger: scan.trigger } });
|
|
81060
|
+
const telemetryContext = getLspTelemetryContext();
|
|
81061
|
+
if (telemetryContext === null) return;
|
|
79270
81062
|
try {
|
|
79271
|
-
|
|
79272
|
-
|
|
79273
|
-
|
|
79274
|
-
} });
|
|
79275
|
-
Sentry.metrics.distribution(METRIC.lspScanDuration, scan.durationMs, {
|
|
79276
|
-
unit: "millisecond",
|
|
79277
|
-
attributes: { trigger: scan.trigger }
|
|
79278
|
-
});
|
|
79279
|
-
Sentry.metrics.distribution(METRIC.lspScanDiagnostics, scan.totalDiagnostics, { attributes: { trigger: scan.trigger } });
|
|
79280
|
-
if (isLspTracingEnabled()) Sentry.startInactiveSpan({
|
|
81063
|
+
const tracer = get$4(telemetryContext, Tracer);
|
|
81064
|
+
const startTime = BigInt(scan.startedAtEpochMs) * NANOSECONDS_PER_MILLISECOND;
|
|
81065
|
+
const span = tracer.span({
|
|
79281
81066
|
name: "react-doctor experimental-lsp scan",
|
|
79282
|
-
|
|
79283
|
-
|
|
79284
|
-
|
|
79285
|
-
|
|
79286
|
-
|
|
81067
|
+
parent: none(),
|
|
81068
|
+
annotations: empty$8(),
|
|
81069
|
+
links: [],
|
|
81070
|
+
startTime,
|
|
81071
|
+
kind: "internal",
|
|
81072
|
+
root: true,
|
|
81073
|
+
sampled: true
|
|
81074
|
+
});
|
|
81075
|
+
const attributes = {
|
|
81076
|
+
...toSpanAttributes(buildSentryScope().tags),
|
|
81077
|
+
...buildLspScanEventAttributes(scan)
|
|
81078
|
+
};
|
|
81079
|
+
for (const [key, value] of Object.entries(attributes)) span.attribute(key, value);
|
|
81080
|
+
span.end(startTime + BigInt(scan.durationMs) * NANOSECONDS_PER_MILLISECOND, void_$1);
|
|
79287
81081
|
} catch {}
|
|
79288
81082
|
};
|
|
79289
81083
|
/** Builds the {@link Telemetry} sink the server drives. */
|
|
@@ -79291,6 +81085,7 @@ const createLspTelemetry = () => ({
|
|
|
79291
81085
|
recordSessionStart: emitSessionStart,
|
|
79292
81086
|
recordWorkspaceScan: emitWorkspaceScan,
|
|
79293
81087
|
flush: async () => {
|
|
81088
|
+
await shutdownTelemetry();
|
|
79294
81089
|
if (!Sentry.isInitialized()) return;
|
|
79295
81090
|
try {
|
|
79296
81091
|
await Sentry.flush(SENTRY_FLUSH_TIMEOUT_MS);
|
|
@@ -79315,5 +81110,5 @@ const startLanguageServer = () => {
|
|
|
79315
81110
|
};
|
|
79316
81111
|
//#endregion
|
|
79317
81112
|
export { startLanguageServer };
|
|
79318
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
79319
|
-
//# debugId=
|
|
81113
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="ff73316d-2f43-5645-89f2-a0eb447f3e2e")}catch(e){}}();
|
|
81114
|
+
//# debugId=ff73316d-2f43-5645-89f2-a0eb447f3e2e
|