@fulmenhq/tsfulmen 0.3.3 → 0.4.1
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/CHANGELOG.md +76 -1
- package/README.md +30 -1
- package/config/crucible-ts/taxonomy/metrics.yaml +1 -1
- package/dist/appidentity/index.js +9 -2209
- package/dist/appidentity/index.js.map +1 -1
- package/dist/assets/index.d.ts +184 -0
- package/dist/assets/index.js +4 -0
- package/dist/assets/index.js.map +1 -0
- package/dist/bin/prometheus-cli.js +15 -9139
- package/dist/bin/prometheus-cli.js.map +1 -1
- package/dist/bin/schema-cli.js +4 -6098
- package/dist/bin/schema-cli.js.map +1 -1
- package/dist/bin/signals-cli.js +15 -1910
- package/dist/bin/signals-cli.js.map +1 -1
- package/dist/chunk-24BAF63H.js +194 -0
- package/dist/chunk-24BAF63H.js.map +1 -0
- package/dist/chunk-3HISR2XI.js +36 -0
- package/dist/chunk-3HISR2XI.js.map +1 -0
- package/dist/chunk-56F2EEAG.js +328 -0
- package/dist/chunk-56F2EEAG.js.map +1 -0
- package/dist/chunk-5HZEJGZ5.js +725 -0
- package/dist/chunk-5HZEJGZ5.js.map +1 -0
- package/dist/chunk-7YWACZEJ.js +837 -0
- package/dist/chunk-7YWACZEJ.js.map +1 -0
- package/dist/chunk-BCO3FUUO.js +682 -0
- package/dist/chunk-BCO3FUUO.js.map +1 -0
- package/dist/chunk-GOTEQYAD.js +410 -0
- package/dist/chunk-GOTEQYAD.js.map +1 -0
- package/dist/chunk-HY6JQOFN.js +32 -0
- package/dist/chunk-HY6JQOFN.js.map +1 -0
- package/dist/chunk-LMNAUTW7.js +43 -0
- package/dist/chunk-LMNAUTW7.js.map +1 -0
- package/dist/chunk-LWAH2UG7.js +103 -0
- package/dist/chunk-LWAH2UG7.js.map +1 -0
- package/dist/chunk-OHE2AOH4.js +273 -0
- package/dist/chunk-OHE2AOH4.js.map +1 -0
- package/dist/chunk-P3DNOZOG.js +1488 -0
- package/dist/chunk-P3DNOZOG.js.map +1 -0
- package/dist/chunk-PQ6TKPUN.js +27 -0
- package/dist/chunk-PQ6TKPUN.js.map +1 -0
- package/dist/chunk-QCCN6POA.js +211 -0
- package/dist/chunk-QCCN6POA.js.map +1 -0
- package/dist/chunk-QGTNV4U2.js +985 -0
- package/dist/chunk-QGTNV4U2.js.map +1 -0
- package/dist/chunk-RSLFR4TO.js +631 -0
- package/dist/chunk-RSLFR4TO.js.map +1 -0
- package/dist/chunk-SNV5WG5V.js +9412 -0
- package/dist/chunk-SNV5WG5V.js.map +1 -0
- package/dist/chunk-UP2VWCW5.js +33 -0
- package/dist/chunk-UP2VWCW5.js.map +1 -0
- package/dist/chunk-VJIGX7MH.js +208 -0
- package/dist/chunk-VJIGX7MH.js.map +1 -0
- package/dist/chunk-WCCMRVZF.js +130 -0
- package/dist/chunk-WCCMRVZF.js.map +1 -0
- package/dist/chunk-WSMVLWLB.js +269 -0
- package/dist/chunk-WSMVLWLB.js.map +1 -0
- package/dist/config/index.js +6 -1220
- package/dist/config/index.js.map +1 -1
- package/dist/crucible/fulpack/index.js +2 -25
- package/dist/crucible/fulpack/index.js.map +1 -1
- package/dist/crucible/index.js +13 -1129
- package/dist/crucible/index.js.map +1 -1
- package/dist/docscribe/index.js +2 -680
- package/dist/docscribe/index.js.map +1 -1
- package/dist/errors/index.js +5 -1831
- package/dist/errors/index.js.map +1 -1
- package/dist/errors-D7KXV3QW.js +4 -0
- package/dist/errors-D7KXV3QW.js.map +1 -0
- package/dist/errors-R7ZODJXS.js +8 -0
- package/dist/errors-R7ZODJXS.js.map +1 -0
- package/dist/export-EA3RNQNS.js +6 -0
- package/dist/export-EA3RNQNS.js.map +1 -0
- package/dist/foundry/index.js +340 -3949
- package/dist/foundry/index.js.map +1 -1
- package/dist/foundry/similarity/index.js +3 -134
- package/dist/foundry/similarity/index.js.map +1 -1
- package/dist/fulencode/index.js +3 -319
- package/dist/fulencode/index.js.map +1 -1
- package/dist/fulhash/index.js +3 -611
- package/dist/fulhash/index.js.map +1 -1
- package/dist/fulpack/index.js +3 -1515
- package/dist/fulpack/index.js.map +1 -1
- package/dist/hash-YOJYVOWH.js +4 -0
- package/dist/hash-YOJYVOWH.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +14 -4395
- package/dist/index.js.map +1 -1
- package/dist/loader-VP2ZIC4O.js +9 -0
- package/dist/loader-VP2ZIC4O.js.map +1 -0
- package/dist/logging/index.js +2 -723
- package/dist/logging/index.js.map +1 -1
- package/dist/pathfinder/index.js +18 -2341
- package/dist/pathfinder/index.js.map +1 -1
- package/dist/prom-client-PNEBGD3G.js +4801 -0
- package/dist/prom-client-PNEBGD3G.js.map +1 -0
- package/dist/reports/license-inventory.csv +1 -1
- package/dist/schema/index.d.ts +19 -6
- package/dist/schema/index.js +4 -6148
- package/dist/schema/index.js.map +1 -1
- package/dist/signals/index.js +8 -2767
- package/dist/signals/index.js.map +1 -1
- package/dist/similarity/index.js +3 -134
- package/dist/similarity/index.js.map +1 -1
- package/dist/telemetry/http/index.js +9 -930
- package/dist/telemetry/http/index.js.map +1 -1
- package/dist/telemetry/index.js +4 -1561
- package/dist/telemetry/index.js.map +1 -1
- package/dist/telemetry/prometheus/index.js +7 -8422
- package/dist/telemetry/prometheus/index.js.map +1 -1
- package/dist/validator-I3ASDVDB.js +6 -0
- package/dist/validator-I3ASDVDB.js.map +1 -0
- package/package.json +5 -1
- package/schemas/crucible-ts/library/module-manifest/v1.0.0/module-manifest.schema.json +1 -1
- package/schemas/crucible-ts/observability/logging/v1.0.0/definitions.schema.json +1 -1
- package/schemas/crucible-ts/observability/logging/v1.0.0/log-event.schema.json +13 -13
- package/schemas/crucible-ts/observability/logging/v1.0.0/logger-config.schema.json +2 -2
- package/schemas/crucible-ts/observability/logging/v1.0.0/logging-policy.schema.json +1 -1
- package/schemas/crucible-ts/observability/logging/v1.0.0/middleware-config.schema.json +2 -2
- package/schemas/crucible-ts/observability/logging/v1.0.0/severity-filter.schema.json +3 -3
- package/schemas/crucible-ts/upstream/3leaps/crucible/PROVENANCE.md +3 -3
- package/schemas/crucible-ts/upstream/3leaps/crucible/docs/catalog/classifiers/README.md +1 -1
- package/schemas/crucible-ts/upstream/3leaps/crucible/docs/standards/classifiers-framework.md +1 -1
- package/schemas/crucible-ts/upstream/3leaps/crucible/docs/standards/data-sensitivity-classification.md +1 -1
package/dist/pathfinder/index.js
CHANGED
|
@@ -1,2334 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import '
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import { fileURLToPath } from 'url';
|
|
9
|
-
import glob from 'fast-glob';
|
|
10
|
-
import Ajv from 'ajv';
|
|
11
|
-
import Ajv2019 from 'ajv/dist/2019.js';
|
|
12
|
-
import Ajv2020 from 'ajv/dist/2020.js';
|
|
13
|
-
import AjvDraft04 from 'ajv-draft-04';
|
|
14
|
-
import 'commander';
|
|
1
|
+
import { createStreamHasher } from '../chunk-WSMVLWLB.js';
|
|
2
|
+
import '../chunk-OHE2AOH4.js';
|
|
3
|
+
import { FulmenError, generateCorrelationId } from '../chunk-GOTEQYAD.js';
|
|
4
|
+
import { metrics, compileSchemaById, validateDataBySchemaId } from '../chunk-SNV5WG5V.js';
|
|
5
|
+
import '../chunk-QCCN6POA.js';
|
|
6
|
+
import '../chunk-56F2EEAG.js';
|
|
7
|
+
import '../chunk-UP2VWCW5.js';
|
|
15
8
|
import { createReadStream, promises } from 'fs';
|
|
9
|
+
import path3, { resolve, dirname, join } from 'path';
|
|
10
|
+
import fs2, { access, lstat, realpath } from 'fs/promises';
|
|
11
|
+
import fg from 'fast-glob';
|
|
16
12
|
import picomatch from 'picomatch';
|
|
17
13
|
import { homedir } from 'os';
|
|
18
14
|
|
|
19
|
-
var __defProp = Object.defineProperty;
|
|
20
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
21
|
-
var __esm = (fn, res) => function __init() {
|
|
22
|
-
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
23
|
-
};
|
|
24
|
-
var __export = (target, all) => {
|
|
25
|
-
for (var name in all)
|
|
26
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
// src/crucible/fulhash/types.ts
|
|
30
|
-
var Algorithm;
|
|
31
|
-
var init_types = __esm({
|
|
32
|
-
"src/crucible/fulhash/types.ts"() {
|
|
33
|
-
Algorithm = /* @__PURE__ */ ((Algorithm2) => {
|
|
34
|
-
Algorithm2["XXH3_128"] = "xxh3-128";
|
|
35
|
-
Algorithm2["SHA256"] = "sha256";
|
|
36
|
-
Algorithm2["CRC32"] = "crc32";
|
|
37
|
-
Algorithm2["CRC32C"] = "crc32c";
|
|
38
|
-
return Algorithm2;
|
|
39
|
-
})(Algorithm || {});
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
// src/fulhash/errors.ts
|
|
44
|
-
var FulHashError, UnsupportedAlgorithmError, InvalidChecksumError, InvalidChecksumFormatError, DigestStateError;
|
|
45
|
-
var init_errors = __esm({
|
|
46
|
-
"src/fulhash/errors.ts"() {
|
|
47
|
-
FulHashError = class _FulHashError extends Error {
|
|
48
|
-
constructor(message) {
|
|
49
|
-
super(message);
|
|
50
|
-
this.name = "FulHashError";
|
|
51
|
-
Object.setPrototypeOf(this, _FulHashError.prototype);
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
UnsupportedAlgorithmError = class _UnsupportedAlgorithmError extends FulHashError {
|
|
55
|
-
constructor(algorithm, supportedAlgorithms) {
|
|
56
|
-
super(
|
|
57
|
-
`Unsupported algorithm "${algorithm}". Supported algorithms: ${supportedAlgorithms.join(", ")}`
|
|
58
|
-
);
|
|
59
|
-
this.name = "UnsupportedAlgorithmError";
|
|
60
|
-
Object.setPrototypeOf(this, _UnsupportedAlgorithmError.prototype);
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
InvalidChecksumError = class _InvalidChecksumError extends FulHashError {
|
|
64
|
-
constructor(checksum, reason) {
|
|
65
|
-
super(`Invalid checksum "${checksum}": ${reason}. Expected format: algorithm:hex`);
|
|
66
|
-
this.name = "InvalidChecksumError";
|
|
67
|
-
Object.setPrototypeOf(this, _InvalidChecksumError.prototype);
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
InvalidChecksumFormatError = class _InvalidChecksumFormatError extends InvalidChecksumError {
|
|
71
|
-
constructor(checksum, reason) {
|
|
72
|
-
super(checksum, reason);
|
|
73
|
-
this.name = "InvalidChecksumFormatError";
|
|
74
|
-
Object.setPrototypeOf(this, _InvalidChecksumFormatError.prototype);
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
DigestStateError = class _DigestStateError extends FulHashError {
|
|
78
|
-
constructor(operation) {
|
|
79
|
-
super(`Cannot ${operation}: digest already finalized. Call reset() to reuse hasher.`);
|
|
80
|
-
this.name = "DigestStateError";
|
|
81
|
-
Object.setPrototypeOf(this, _DigestStateError.prototype);
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
function hexToBytes(hex) {
|
|
87
|
-
const bytes = new Uint8Array(4);
|
|
88
|
-
for (let i = 0; i < 4; i++) {
|
|
89
|
-
bytes[i] = Number.parseInt(hex.substr(i * 2, 2), 16);
|
|
90
|
-
}
|
|
91
|
-
return bytes;
|
|
92
|
-
}
|
|
93
|
-
async function hashBytes(data) {
|
|
94
|
-
const hex = await crc32(data);
|
|
95
|
-
return hexToBytes(hex);
|
|
96
|
-
}
|
|
97
|
-
async function hashString(str, encoding = "utf8") {
|
|
98
|
-
if (encoding !== "utf8") {
|
|
99
|
-
const buf = Buffer.from(str, encoding);
|
|
100
|
-
const hex2 = await crc32(buf);
|
|
101
|
-
return hexToBytes(hex2);
|
|
102
|
-
}
|
|
103
|
-
const hex = await crc32(str);
|
|
104
|
-
return hexToBytes(hex);
|
|
105
|
-
}
|
|
106
|
-
async function createHasher() {
|
|
107
|
-
const hasher = await createCRC32();
|
|
108
|
-
return hasher;
|
|
109
|
-
}
|
|
110
|
-
var init_crc32 = __esm({
|
|
111
|
-
"src/fulhash/algorithms/crc32.ts"() {
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
function hexToBytes2(hex) {
|
|
115
|
-
const bytes = new Uint8Array(4);
|
|
116
|
-
for (let i = 0; i < 4; i++) {
|
|
117
|
-
bytes[i] = Number.parseInt(hex.substr(i * 2, 2), 16);
|
|
118
|
-
}
|
|
119
|
-
return bytes;
|
|
120
|
-
}
|
|
121
|
-
async function hashBytes2(data) {
|
|
122
|
-
const hex = await crc32(data, CRC32C_POLYNOMIAL);
|
|
123
|
-
return hexToBytes2(hex);
|
|
124
|
-
}
|
|
125
|
-
async function hashString2(str, encoding = "utf8") {
|
|
126
|
-
if (encoding !== "utf8") {
|
|
127
|
-
const buf = Buffer.from(str, encoding);
|
|
128
|
-
const hex2 = await crc32(buf, CRC32C_POLYNOMIAL);
|
|
129
|
-
return hexToBytes2(hex2);
|
|
130
|
-
}
|
|
131
|
-
const hex = await crc32(str, CRC32C_POLYNOMIAL);
|
|
132
|
-
return hexToBytes2(hex);
|
|
133
|
-
}
|
|
134
|
-
async function createHasher2() {
|
|
135
|
-
const hasher = await createCRC32(CRC32C_POLYNOMIAL);
|
|
136
|
-
return hasher;
|
|
137
|
-
}
|
|
138
|
-
var CRC32C_POLYNOMIAL;
|
|
139
|
-
var init_crc32c = __esm({
|
|
140
|
-
"src/fulhash/algorithms/crc32c.ts"() {
|
|
141
|
-
CRC32C_POLYNOMIAL = 2197175160;
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
function hashBytes3(data) {
|
|
145
|
-
const hash2 = createHash("sha256");
|
|
146
|
-
hash2.update(data);
|
|
147
|
-
return new Uint8Array(hash2.digest());
|
|
148
|
-
}
|
|
149
|
-
function hashString3(str, encoding = "utf8") {
|
|
150
|
-
const hash2 = createHash("sha256");
|
|
151
|
-
hash2.update(str, encoding);
|
|
152
|
-
return new Uint8Array(hash2.digest());
|
|
153
|
-
}
|
|
154
|
-
var init_sha256 = __esm({
|
|
155
|
-
"src/fulhash/algorithms/sha256.ts"() {
|
|
156
|
-
}
|
|
157
|
-
});
|
|
158
|
-
function hexToBytes3(hex) {
|
|
159
|
-
const bytes = new Uint8Array(16);
|
|
160
|
-
for (let i = 0; i < 16; i++) {
|
|
161
|
-
bytes[i] = Number.parseInt(hex.substr(i * 2, 2), 16);
|
|
162
|
-
}
|
|
163
|
-
return bytes;
|
|
164
|
-
}
|
|
165
|
-
async function hashBytes4(data) {
|
|
166
|
-
const hex = await xxhash128(data);
|
|
167
|
-
return hexToBytes3(hex);
|
|
168
|
-
}
|
|
169
|
-
async function hashString4(str, encoding = "utf8") {
|
|
170
|
-
if (encoding !== "utf8") {
|
|
171
|
-
throw new FulHashError(
|
|
172
|
-
"XXH3-128 only supports UTF-8 encoding. Use utf8 encoding or convert data to Uint8Array."
|
|
173
|
-
);
|
|
174
|
-
}
|
|
175
|
-
const hex = await xxhash128(str);
|
|
176
|
-
return hexToBytes3(hex);
|
|
177
|
-
}
|
|
178
|
-
var init_xxh3 = __esm({
|
|
179
|
-
"src/fulhash/algorithms/xxh3.ts"() {
|
|
180
|
-
init_errors();
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
// src/fulhash/hash.ts
|
|
185
|
-
var hash_exports = {};
|
|
186
|
-
__export(hash_exports, {
|
|
187
|
-
hash: () => hash,
|
|
188
|
-
hashBytes: () => hashBytes5,
|
|
189
|
-
hashString: () => hashString5
|
|
190
|
-
});
|
|
191
|
-
async function hash(input, options) {
|
|
192
|
-
const algorithm = options?.algorithm ?? "xxh3-128" /* XXH3_128 */;
|
|
193
|
-
const encoding = options?.encoding ?? "utf8";
|
|
194
|
-
let bytes;
|
|
195
|
-
switch (algorithm) {
|
|
196
|
-
case "sha256" /* SHA256 */:
|
|
197
|
-
if (typeof input === "string") {
|
|
198
|
-
bytes = hashString3(input, encoding);
|
|
199
|
-
} else {
|
|
200
|
-
bytes = hashBytes3(input);
|
|
201
|
-
}
|
|
202
|
-
break;
|
|
203
|
-
case "xxh3-128" /* XXH3_128 */:
|
|
204
|
-
if (typeof input === "string") {
|
|
205
|
-
if (encoding !== "utf8") {
|
|
206
|
-
bytes = await hashBytes4(Buffer.from(input, encoding));
|
|
207
|
-
} else {
|
|
208
|
-
bytes = await hashString4(input, "utf8");
|
|
209
|
-
}
|
|
210
|
-
} else {
|
|
211
|
-
bytes = await hashBytes4(input);
|
|
212
|
-
}
|
|
213
|
-
break;
|
|
214
|
-
case "crc32" /* CRC32 */:
|
|
215
|
-
if (typeof input === "string") {
|
|
216
|
-
bytes = await hashString(input, encoding);
|
|
217
|
-
} else {
|
|
218
|
-
bytes = await hashBytes(input);
|
|
219
|
-
}
|
|
220
|
-
break;
|
|
221
|
-
case "crc32c" /* CRC32C */:
|
|
222
|
-
if (typeof input === "string") {
|
|
223
|
-
bytes = await hashString2(input, encoding);
|
|
224
|
-
} else {
|
|
225
|
-
bytes = await hashBytes2(input);
|
|
226
|
-
}
|
|
227
|
-
break;
|
|
228
|
-
default:
|
|
229
|
-
throw new UnsupportedAlgorithmError(algorithm, Object.values(Algorithm));
|
|
230
|
-
}
|
|
231
|
-
return new Digest(algorithm, bytes);
|
|
232
|
-
}
|
|
233
|
-
async function hashString5(str, options) {
|
|
234
|
-
return hash(str, options);
|
|
235
|
-
}
|
|
236
|
-
async function hashBytes5(data, options) {
|
|
237
|
-
return hash(data, options);
|
|
238
|
-
}
|
|
239
|
-
var init_hash = __esm({
|
|
240
|
-
"src/fulhash/hash.ts"() {
|
|
241
|
-
init_types();
|
|
242
|
-
init_crc32();
|
|
243
|
-
init_crc32c();
|
|
244
|
-
init_sha256();
|
|
245
|
-
init_xxh3();
|
|
246
|
-
init_digest();
|
|
247
|
-
init_errors();
|
|
248
|
-
}
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
// src/fulhash/digest.ts
|
|
252
|
-
var Digest;
|
|
253
|
-
var init_digest = __esm({
|
|
254
|
-
"src/fulhash/digest.ts"() {
|
|
255
|
-
init_types();
|
|
256
|
-
init_errors();
|
|
257
|
-
Digest = class _Digest {
|
|
258
|
-
algorithm;
|
|
259
|
-
_bytes;
|
|
260
|
-
hex;
|
|
261
|
-
formatted;
|
|
262
|
-
constructor(algorithm, bytes) {
|
|
263
|
-
this.algorithm = algorithm;
|
|
264
|
-
this._bytes = new Uint8Array(bytes);
|
|
265
|
-
this.hex = Array.from(this._bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
266
|
-
this.formatted = `${this.algorithm}:${this.hex}`;
|
|
267
|
-
Object.freeze(this);
|
|
268
|
-
}
|
|
269
|
-
get bytes() {
|
|
270
|
-
return Array.from(this._bytes);
|
|
271
|
-
}
|
|
272
|
-
toJSON() {
|
|
273
|
-
return {
|
|
274
|
-
algorithm: this.algorithm,
|
|
275
|
-
hex: this.hex,
|
|
276
|
-
formatted: this.formatted
|
|
277
|
-
};
|
|
278
|
-
}
|
|
279
|
-
toString() {
|
|
280
|
-
return this.formatted;
|
|
281
|
-
}
|
|
282
|
-
static parse(formatted) {
|
|
283
|
-
if (!formatted.includes(":")) {
|
|
284
|
-
throw new InvalidChecksumFormatError(formatted, "missing separator");
|
|
285
|
-
}
|
|
286
|
-
const [algorithmStr, hex] = formatted.split(":", 2);
|
|
287
|
-
if (!algorithmStr || !hex) {
|
|
288
|
-
throw new InvalidChecksumFormatError(formatted, "invalid format");
|
|
289
|
-
}
|
|
290
|
-
const algorithm = algorithmStr;
|
|
291
|
-
if (!Object.values(Algorithm).includes(algorithm)) {
|
|
292
|
-
throw new UnsupportedAlgorithmError(algorithm, Object.values(Algorithm));
|
|
293
|
-
}
|
|
294
|
-
if (!/^[0-9a-f]+$/.test(hex)) {
|
|
295
|
-
throw new InvalidChecksumError(
|
|
296
|
-
formatted,
|
|
297
|
-
"hex must contain only lowercase hexadecimal characters"
|
|
298
|
-
);
|
|
299
|
-
}
|
|
300
|
-
let expectedLength;
|
|
301
|
-
switch (algorithm) {
|
|
302
|
-
case "xxh3-128" /* XXH3_128 */:
|
|
303
|
-
expectedLength = 32;
|
|
304
|
-
break;
|
|
305
|
-
case "sha256" /* SHA256 */:
|
|
306
|
-
expectedLength = 64;
|
|
307
|
-
break;
|
|
308
|
-
case "crc32" /* CRC32 */:
|
|
309
|
-
case "crc32c" /* CRC32C */:
|
|
310
|
-
expectedLength = 8;
|
|
311
|
-
break;
|
|
312
|
-
default:
|
|
313
|
-
throw new UnsupportedAlgorithmError(algorithm, Object.values(Algorithm));
|
|
314
|
-
}
|
|
315
|
-
if (hex.length !== expectedLength) {
|
|
316
|
-
throw new InvalidChecksumError(
|
|
317
|
-
formatted,
|
|
318
|
-
`invalid hex length for ${algorithm}: expected ${expectedLength}, got ${hex.length}`
|
|
319
|
-
);
|
|
320
|
-
}
|
|
321
|
-
const bytes = new Uint8Array(hex.length / 2);
|
|
322
|
-
for (let i = 0; i < hex.length; i += 2) {
|
|
323
|
-
bytes[i / 2] = Number.parseInt(hex.slice(i, i + 2), 16);
|
|
324
|
-
}
|
|
325
|
-
return new _Digest(algorithm, bytes);
|
|
326
|
-
}
|
|
327
|
-
equals(other) {
|
|
328
|
-
if (this.algorithm !== other.algorithm) {
|
|
329
|
-
return false;
|
|
330
|
-
}
|
|
331
|
-
if (this.hex !== other.hex) {
|
|
332
|
-
return false;
|
|
333
|
-
}
|
|
334
|
-
return true;
|
|
335
|
-
}
|
|
336
|
-
static async verify(data, checksum) {
|
|
337
|
-
const expected = _Digest.parse(checksum);
|
|
338
|
-
const { hash: hash2 } = await Promise.resolve().then(() => (init_hash(), hash_exports));
|
|
339
|
-
const actual = await hash2(data, { algorithm: expected.algorithm });
|
|
340
|
-
return actual.equals(expected);
|
|
341
|
-
}
|
|
342
|
-
};
|
|
343
|
-
}
|
|
344
|
-
});
|
|
345
|
-
function generateCorrelationId() {
|
|
346
|
-
return randomUUID();
|
|
347
|
-
}
|
|
348
|
-
var init_correlation = __esm({
|
|
349
|
-
"src/errors/correlation.ts"() {
|
|
350
|
-
}
|
|
351
|
-
});
|
|
352
|
-
|
|
353
|
-
// src/errors/severity.ts
|
|
354
|
-
function getDefaultSeverity() {
|
|
355
|
-
return {
|
|
356
|
-
name: Severity.MEDIUM,
|
|
357
|
-
level: 2
|
|
358
|
-
};
|
|
359
|
-
}
|
|
360
|
-
var Severity, SEVERITY_LEVELS;
|
|
361
|
-
var init_severity = __esm({
|
|
362
|
-
"src/errors/severity.ts"() {
|
|
363
|
-
Severity = {
|
|
364
|
-
INFO: "info",
|
|
365
|
-
LOW: "low",
|
|
366
|
-
MEDIUM: "medium",
|
|
367
|
-
HIGH: "high",
|
|
368
|
-
CRITICAL: "critical"
|
|
369
|
-
};
|
|
370
|
-
SEVERITY_LEVELS = {
|
|
371
|
-
info: 0,
|
|
372
|
-
low: 1,
|
|
373
|
-
medium: 2,
|
|
374
|
-
high: 3,
|
|
375
|
-
critical: 4
|
|
376
|
-
};
|
|
377
|
-
}
|
|
378
|
-
});
|
|
379
|
-
|
|
380
|
-
// src/errors/serialization.ts
|
|
381
|
-
function extractErrorMessage(error) {
|
|
382
|
-
if (error instanceof Error) {
|
|
383
|
-
return error.message;
|
|
384
|
-
}
|
|
385
|
-
if (isErrorLike(error)) {
|
|
386
|
-
return error.message;
|
|
387
|
-
}
|
|
388
|
-
if (typeof error === "string") {
|
|
389
|
-
return error;
|
|
390
|
-
}
|
|
391
|
-
return String(error);
|
|
392
|
-
}
|
|
393
|
-
function extractStackTrace(error) {
|
|
394
|
-
if (error instanceof Error) {
|
|
395
|
-
return error.stack;
|
|
396
|
-
}
|
|
397
|
-
if (isErrorLike(error) && typeof error.stack === "string") {
|
|
398
|
-
return error.stack;
|
|
399
|
-
}
|
|
400
|
-
return void 0;
|
|
401
|
-
}
|
|
402
|
-
function isErrorLike(value) {
|
|
403
|
-
return typeof value === "object" && value !== null && "message" in value && typeof value.message === "string";
|
|
404
|
-
}
|
|
405
|
-
var init_serialization = __esm({
|
|
406
|
-
"src/errors/serialization.ts"() {
|
|
407
|
-
init_severity();
|
|
408
|
-
}
|
|
409
|
-
});
|
|
410
|
-
function applyFulmenAjvFormats(ajv, options = {}) {
|
|
411
|
-
const mode = options.mode ?? "fast";
|
|
412
|
-
const formats = options.formats ?? DEFAULT_FORMATS;
|
|
413
|
-
addFormats(ajv, { mode, formats });
|
|
414
|
-
return ajv;
|
|
415
|
-
}
|
|
416
|
-
var DEFAULT_FORMATS;
|
|
417
|
-
var init_ajv_formats = __esm({
|
|
418
|
-
"src/schema/ajv-formats.ts"() {
|
|
419
|
-
DEFAULT_FORMATS = [
|
|
420
|
-
"date-time",
|
|
421
|
-
"email",
|
|
422
|
-
"hostname",
|
|
423
|
-
"ipv4",
|
|
424
|
-
"ipv6",
|
|
425
|
-
"uri",
|
|
426
|
-
"uri-reference",
|
|
427
|
-
"uuid"
|
|
428
|
-
];
|
|
429
|
-
}
|
|
430
|
-
});
|
|
431
|
-
|
|
432
|
-
// src/schema/errors.ts
|
|
433
|
-
var SchemaValidationError;
|
|
434
|
-
var init_errors2 = __esm({
|
|
435
|
-
"src/schema/errors.ts"() {
|
|
436
|
-
SchemaValidationError = class _SchemaValidationError extends Error {
|
|
437
|
-
constructor(message, schemaId, diagnostics = [], source, cause) {
|
|
438
|
-
super(message);
|
|
439
|
-
this.schemaId = schemaId;
|
|
440
|
-
this.diagnostics = diagnostics;
|
|
441
|
-
this.source = source;
|
|
442
|
-
this.cause = cause;
|
|
443
|
-
this.name = "SchemaValidationError";
|
|
444
|
-
if (Error.captureStackTrace) {
|
|
445
|
-
Error.captureStackTrace(this, _SchemaValidationError);
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
/**
|
|
449
|
-
* Create error for schema not found
|
|
450
|
-
*/
|
|
451
|
-
static schemaNotFound(schemaId) {
|
|
452
|
-
return new _SchemaValidationError(`Schema not found: ${schemaId}`, schemaId);
|
|
453
|
-
}
|
|
454
|
-
/**
|
|
455
|
-
* Create error for invalid schema input
|
|
456
|
-
*/
|
|
457
|
-
static invalidSchemaInput(source, details) {
|
|
458
|
-
return new _SchemaValidationError(`Invalid schema input: ${details}`, void 0, [], source);
|
|
459
|
-
}
|
|
460
|
-
/**
|
|
461
|
-
* Create error for validation failure
|
|
462
|
-
*/
|
|
463
|
-
static validationFailed(schemaId, diagnostics, source) {
|
|
464
|
-
const errorCount = diagnostics.filter((d) => d.severity === "ERROR").length;
|
|
465
|
-
const warningCount = diagnostics.filter((d) => d.severity === "WARN").length;
|
|
466
|
-
const message = `Schema validation failed: ${errorCount} error(s), ${warningCount} warning(s)`;
|
|
467
|
-
return new _SchemaValidationError(message, schemaId, diagnostics, source);
|
|
468
|
-
}
|
|
469
|
-
/**
|
|
470
|
-
* Create error for goneat binary not found
|
|
471
|
-
*/
|
|
472
|
-
static goneatNotFound(goneatPath) {
|
|
473
|
-
const pathInfo = goneatPath ? ` at ${goneatPath}` : "";
|
|
474
|
-
return new _SchemaValidationError(
|
|
475
|
-
`Goneat binary not found${pathInfo}. Falling back to AJV validation.`
|
|
476
|
-
);
|
|
477
|
-
}
|
|
478
|
-
/**
|
|
479
|
-
* Create error for goneat execution failure
|
|
480
|
-
*/
|
|
481
|
-
static goneatExecutionFailed(error) {
|
|
482
|
-
return new _SchemaValidationError(
|
|
483
|
-
"Goneat execution failed. Falling back to AJV validation.",
|
|
484
|
-
void 0,
|
|
485
|
-
[],
|
|
486
|
-
void 0,
|
|
487
|
-
error
|
|
488
|
-
);
|
|
489
|
-
}
|
|
490
|
-
/**
|
|
491
|
-
* Create error for empty schema input
|
|
492
|
-
*/
|
|
493
|
-
static emptySchemaInput(source) {
|
|
494
|
-
return new _SchemaValidationError("Schema content is empty", void 0, [], source);
|
|
495
|
-
}
|
|
496
|
-
/**
|
|
497
|
-
* Create error for parse failure
|
|
498
|
-
*/
|
|
499
|
-
static parseFailed(source, error) {
|
|
500
|
-
return new _SchemaValidationError(
|
|
501
|
-
`Failed to parse schema: ${error.message}`,
|
|
502
|
-
void 0,
|
|
503
|
-
[],
|
|
504
|
-
source,
|
|
505
|
-
error
|
|
506
|
-
);
|
|
507
|
-
}
|
|
508
|
-
/**
|
|
509
|
-
* Create error for encoding failure
|
|
510
|
-
*/
|
|
511
|
-
static encodingFailed(source, error) {
|
|
512
|
-
return new _SchemaValidationError(
|
|
513
|
-
`Failed to encode schema: ${error.message}`,
|
|
514
|
-
void 0,
|
|
515
|
-
[],
|
|
516
|
-
source,
|
|
517
|
-
error
|
|
518
|
-
);
|
|
519
|
-
}
|
|
520
|
-
/**
|
|
521
|
-
* Create error for registry operation failure
|
|
522
|
-
*/
|
|
523
|
-
static registryError(operation, details) {
|
|
524
|
-
return new _SchemaValidationError(`Schema registry ${operation} failed: ${details}`);
|
|
525
|
-
}
|
|
526
|
-
/**
|
|
527
|
-
* Format error for display
|
|
528
|
-
*/
|
|
529
|
-
format() {
|
|
530
|
-
let output = this.message;
|
|
531
|
-
if (this.schemaId) {
|
|
532
|
-
output += `
|
|
533
|
-
Schema ID: ${this.schemaId}`;
|
|
534
|
-
}
|
|
535
|
-
if (this.diagnostics.length > 0) {
|
|
536
|
-
output += "\n\nValidation Issues:";
|
|
537
|
-
this.diagnostics.forEach((diag, index) => {
|
|
538
|
-
output += `
|
|
539
|
-
${index + 1}. [${diag.severity}] ${diag.message}`;
|
|
540
|
-
if (diag.pointer) {
|
|
541
|
-
output += ` at ${diag.pointer}`;
|
|
542
|
-
}
|
|
543
|
-
if (diag.keyword) {
|
|
544
|
-
output += ` (keyword: ${diag.keyword})`;
|
|
545
|
-
}
|
|
546
|
-
if (diag.source) {
|
|
547
|
-
output += ` [${diag.source}]`;
|
|
548
|
-
}
|
|
549
|
-
});
|
|
550
|
-
}
|
|
551
|
-
if (this.source) {
|
|
552
|
-
output += `
|
|
553
|
-
|
|
554
|
-
Source: ${this.source.type}`;
|
|
555
|
-
if (this.source.id) {
|
|
556
|
-
output += ` (${this.source.id})`;
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
return output;
|
|
560
|
-
}
|
|
561
|
-
/**
|
|
562
|
-
* Convert to JSON representation
|
|
563
|
-
*/
|
|
564
|
-
toJSON() {
|
|
565
|
-
return {
|
|
566
|
-
name: this.name,
|
|
567
|
-
message: this.message,
|
|
568
|
-
schemaId: this.schemaId,
|
|
569
|
-
diagnostics: this.diagnostics,
|
|
570
|
-
source: this.source,
|
|
571
|
-
cause: this.cause?.message
|
|
572
|
-
};
|
|
573
|
-
}
|
|
574
|
-
};
|
|
575
|
-
}
|
|
576
|
-
});
|
|
577
|
-
|
|
578
|
-
// src/schema/utils.ts
|
|
579
|
-
function createDiagnostic(pointer, message, keyword, severity = "ERROR", source = "ajv", data) {
|
|
580
|
-
return {
|
|
581
|
-
pointer,
|
|
582
|
-
message,
|
|
583
|
-
keyword,
|
|
584
|
-
severity,
|
|
585
|
-
source,
|
|
586
|
-
data
|
|
587
|
-
};
|
|
588
|
-
}
|
|
589
|
-
var init_utils = __esm({
|
|
590
|
-
"src/schema/utils.ts"() {
|
|
591
|
-
init_errors2();
|
|
592
|
-
}
|
|
593
|
-
});
|
|
594
|
-
var init_goneat_bridge = __esm({
|
|
595
|
-
"src/schema/goneat-bridge.ts"() {
|
|
596
|
-
init_utils();
|
|
597
|
-
}
|
|
598
|
-
});
|
|
599
|
-
var init_normalizer = __esm({
|
|
600
|
-
"src/schema/normalizer.ts"() {
|
|
601
|
-
init_errors2();
|
|
602
|
-
}
|
|
603
|
-
});
|
|
604
|
-
function optionsChanged(newOptions) {
|
|
605
|
-
if (!globalRegistryOptions) return false;
|
|
606
|
-
return true;
|
|
607
|
-
}
|
|
608
|
-
function getSchemaRegistry(options) {
|
|
609
|
-
if (!globalRegistry || optionsChanged()) {
|
|
610
|
-
globalRegistry = new SchemaRegistry(options);
|
|
611
|
-
globalRegistryOptions = options;
|
|
612
|
-
}
|
|
613
|
-
return globalRegistry;
|
|
614
|
-
}
|
|
615
|
-
var DEFAULT_PATTERNS, SchemaRegistry, globalRegistry, globalRegistryOptions;
|
|
616
|
-
var init_registry = __esm({
|
|
617
|
-
"src/schema/registry.ts"() {
|
|
618
|
-
init_errors2();
|
|
619
|
-
DEFAULT_PATTERNS = ["**/*.schema.json", "**/*.schema.yaml", "**/*.schema.yml"];
|
|
620
|
-
SchemaRegistry = class {
|
|
621
|
-
schemas = /* @__PURE__ */ new Map();
|
|
622
|
-
options;
|
|
623
|
-
constructor(options = {}) {
|
|
624
|
-
this.options = {
|
|
625
|
-
baseDir: options.baseDir || this.getDefaultSchemaDir(),
|
|
626
|
-
patterns: options.patterns || DEFAULT_PATTERNS,
|
|
627
|
-
followSymlinks: options.followSymlinks ?? false,
|
|
628
|
-
maxDepth: options.maxDepth ?? 10
|
|
629
|
-
};
|
|
630
|
-
}
|
|
631
|
-
/**
|
|
632
|
-
* Get default schema directory using import.meta.url
|
|
633
|
-
*/
|
|
634
|
-
getDefaultSchemaDir() {
|
|
635
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
636
|
-
const __dirname2 = dirname(__filename);
|
|
637
|
-
return join(__dirname2, "..", "..", "schemas", "crucible-ts");
|
|
638
|
-
}
|
|
639
|
-
/**
|
|
640
|
-
* Build logical schema ID from file path
|
|
641
|
-
*/
|
|
642
|
-
buildSchemaId(filePath, baseDir) {
|
|
643
|
-
const relativePath = relative(baseDir, filePath);
|
|
644
|
-
const withoutExt = relativePath.replace(/\.(schema\.(json|yaml|yml))$/, "");
|
|
645
|
-
return withoutExt.replace(/\\/g, "/");
|
|
646
|
-
}
|
|
647
|
-
/**
|
|
648
|
-
* Extract schema format from file extension
|
|
649
|
-
*/
|
|
650
|
-
getSchemaFormat(filePath) {
|
|
651
|
-
const ext = extname(filePath).toLowerCase();
|
|
652
|
-
switch (ext) {
|
|
653
|
-
case ".json":
|
|
654
|
-
return "json";
|
|
655
|
-
case ".yaml":
|
|
656
|
-
case ".yml":
|
|
657
|
-
return "yaml";
|
|
658
|
-
default:
|
|
659
|
-
return "json";
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
/**
|
|
663
|
-
* Extract metadata from schema file
|
|
664
|
-
*/
|
|
665
|
-
async extractMetadata(filePath) {
|
|
666
|
-
try {
|
|
667
|
-
const content = await readFile(filePath, "utf-8");
|
|
668
|
-
const format = this.getSchemaFormat(filePath);
|
|
669
|
-
let parsed;
|
|
670
|
-
if (format === "yaml") {
|
|
671
|
-
parsed = parse(content);
|
|
672
|
-
} else {
|
|
673
|
-
parsed = JSON.parse(content);
|
|
674
|
-
}
|
|
675
|
-
const baseDir = this.options.baseDir ?? "";
|
|
676
|
-
const relativePath = relative(baseDir, filePath);
|
|
677
|
-
return {
|
|
678
|
-
id: this.buildSchemaId(filePath, baseDir),
|
|
679
|
-
path: filePath,
|
|
680
|
-
relativePath,
|
|
681
|
-
format,
|
|
682
|
-
version: parsed.$schema || parsed.version,
|
|
683
|
-
description: parsed.title || parsed.description,
|
|
684
|
-
schemaDraft: parsed.$schema
|
|
685
|
-
};
|
|
686
|
-
} catch (error) {
|
|
687
|
-
throw SchemaValidationError.registryError(
|
|
688
|
-
"metadata extraction",
|
|
689
|
-
`Failed to process ${filePath}: ${error.message}`
|
|
690
|
-
);
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
/**
|
|
694
|
-
* Discover and index all available schemas
|
|
695
|
-
*/
|
|
696
|
-
async discoverSchemas() {
|
|
697
|
-
try {
|
|
698
|
-
const baseDir = this.options.baseDir ?? "";
|
|
699
|
-
const patterns = this.options.patterns ?? [];
|
|
700
|
-
if (patterns.length === 0) {
|
|
701
|
-
this.schemas.clear();
|
|
702
|
-
return;
|
|
703
|
-
}
|
|
704
|
-
const pattern = patterns.map((p) => join(baseDir, p));
|
|
705
|
-
try {
|
|
706
|
-
await access(baseDir);
|
|
707
|
-
} catch {
|
|
708
|
-
this.schemas.clear();
|
|
709
|
-
return;
|
|
710
|
-
}
|
|
711
|
-
const files = await glob(pattern, {
|
|
712
|
-
absolute: true,
|
|
713
|
-
followSymbolicLinks: this.options.followSymlinks,
|
|
714
|
-
deep: this.options.maxDepth,
|
|
715
|
-
onlyFiles: true,
|
|
716
|
-
suppressErrors: true
|
|
717
|
-
// Don't throw on permission errors
|
|
718
|
-
});
|
|
719
|
-
this.schemas.clear();
|
|
720
|
-
for (const filePath of files) {
|
|
721
|
-
try {
|
|
722
|
-
const metadata = await this.extractMetadata(filePath);
|
|
723
|
-
this.schemas.set(metadata.id, metadata);
|
|
724
|
-
} catch (error) {
|
|
725
|
-
console.warn(`Warning: Failed to process schema ${filePath}:`, error);
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
} catch (error) {
|
|
729
|
-
throw SchemaValidationError.registryError("discovery", error.message);
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
/**
|
|
733
|
-
* List available schemas with optional prefix filtering
|
|
734
|
-
*/
|
|
735
|
-
async listSchemas(prefix) {
|
|
736
|
-
if (this.schemas.size === 0) {
|
|
737
|
-
await this.discoverSchemas();
|
|
738
|
-
}
|
|
739
|
-
const schemas = Array.from(this.schemas.values());
|
|
740
|
-
if (prefix) {
|
|
741
|
-
return schemas.filter((schema) => schema.id.startsWith(prefix));
|
|
742
|
-
}
|
|
743
|
-
return schemas;
|
|
744
|
-
}
|
|
745
|
-
/**
|
|
746
|
-
* Get schema by logical ID
|
|
747
|
-
*/
|
|
748
|
-
async getSchema(id) {
|
|
749
|
-
if (this.schemas.size === 0) {
|
|
750
|
-
await this.discoverSchemas();
|
|
751
|
-
}
|
|
752
|
-
const schema = this.schemas.get(id);
|
|
753
|
-
if (!schema) {
|
|
754
|
-
throw SchemaValidationError.schemaNotFound(id);
|
|
755
|
-
}
|
|
756
|
-
return schema;
|
|
757
|
-
}
|
|
758
|
-
/**
|
|
759
|
-
* Get schema by file path
|
|
760
|
-
*/
|
|
761
|
-
async getSchemaByPath(filePath) {
|
|
762
|
-
if (this.schemas.size === 0) {
|
|
763
|
-
await this.discoverSchemas();
|
|
764
|
-
}
|
|
765
|
-
const absolutePath = filePath.startsWith("/") ? filePath : join(process.cwd(), filePath);
|
|
766
|
-
for (const schema of this.schemas.values()) {
|
|
767
|
-
if (schema.path === absolutePath) {
|
|
768
|
-
return schema;
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
throw SchemaValidationError.schemaNotFound(filePath);
|
|
772
|
-
}
|
|
773
|
-
/**
|
|
774
|
-
* Check if schema exists
|
|
775
|
-
*/
|
|
776
|
-
async hasSchema(id) {
|
|
777
|
-
if (this.schemas.size === 0) {
|
|
778
|
-
await this.discoverSchemas();
|
|
779
|
-
}
|
|
780
|
-
return this.schemas.has(id);
|
|
781
|
-
}
|
|
782
|
-
/**
|
|
783
|
-
* Get registry size
|
|
784
|
-
*/
|
|
785
|
-
get size() {
|
|
786
|
-
return this.schemas.size;
|
|
787
|
-
}
|
|
788
|
-
/**
|
|
789
|
-
* Clear registry cache
|
|
790
|
-
*/
|
|
791
|
-
clear() {
|
|
792
|
-
this.schemas.clear();
|
|
793
|
-
}
|
|
794
|
-
};
|
|
795
|
-
}
|
|
796
|
-
});
|
|
797
|
-
|
|
798
|
-
// src/telemetry/counter.ts
|
|
799
|
-
var Counter;
|
|
800
|
-
var init_counter = __esm({
|
|
801
|
-
"src/telemetry/counter.ts"() {
|
|
802
|
-
Counter = class {
|
|
803
|
-
constructor(name) {
|
|
804
|
-
this.name = name;
|
|
805
|
-
}
|
|
806
|
-
value = 0;
|
|
807
|
-
labeledValues = /* @__PURE__ */ new Map();
|
|
808
|
-
/**
|
|
809
|
-
* Increment counter by delta (default: 1)
|
|
810
|
-
*
|
|
811
|
-
* @param delta - Amount to increment (must be non-negative)
|
|
812
|
-
* @param labels - Optional label dimensions for this observation
|
|
813
|
-
* @throws {Error} If delta is negative
|
|
814
|
-
*
|
|
815
|
-
* @example
|
|
816
|
-
* ```typescript
|
|
817
|
-
* counter.inc(); // Increment unlabeled by 1
|
|
818
|
-
* counter.inc(5); // Increment unlabeled by 5
|
|
819
|
-
* counter.inc(1, { status: '200' }); // Increment labeled instance
|
|
820
|
-
* counter.inc(1, { result: 'success' }); // Different label set
|
|
821
|
-
* ```
|
|
822
|
-
*/
|
|
823
|
-
inc(delta = 1, labels) {
|
|
824
|
-
if (delta < 0) {
|
|
825
|
-
throw new Error(`Counter delta must be non-negative, got: ${delta}`);
|
|
826
|
-
}
|
|
827
|
-
if (labels && Object.keys(labels).length > 0) {
|
|
828
|
-
const labelKey = this.serializeLabels(labels);
|
|
829
|
-
const current = this.labeledValues.get(labelKey) || 0;
|
|
830
|
-
this.labeledValues.set(labelKey, current + delta);
|
|
831
|
-
} else {
|
|
832
|
-
this.value += delta;
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
/**
|
|
836
|
-
* Get current counter value (unlabeled)
|
|
837
|
-
*/
|
|
838
|
-
getValue() {
|
|
839
|
-
return this.value;
|
|
840
|
-
}
|
|
841
|
-
/**
|
|
842
|
-
* Get all labeled values
|
|
843
|
-
* @returns Map of serialized label keys to values
|
|
844
|
-
*/
|
|
845
|
-
getLabeledValues() {
|
|
846
|
-
return new Map(this.labeledValues);
|
|
847
|
-
}
|
|
848
|
-
/**
|
|
849
|
-
* Get value for specific label combination
|
|
850
|
-
*/
|
|
851
|
-
getValueForLabels(labels) {
|
|
852
|
-
const labelKey = this.serializeLabels(labels);
|
|
853
|
-
return this.labeledValues.get(labelKey) || 0;
|
|
854
|
-
}
|
|
855
|
-
/**
|
|
856
|
-
* Reset counter to zero (all label combinations)
|
|
857
|
-
*/
|
|
858
|
-
reset() {
|
|
859
|
-
this.value = 0;
|
|
860
|
-
this.labeledValues.clear();
|
|
861
|
-
}
|
|
862
|
-
/**
|
|
863
|
-
* Serialize labels to deterministic string key
|
|
864
|
-
* Format: key1=value1,key2=value2 (sorted by key)
|
|
865
|
-
*/
|
|
866
|
-
serializeLabels(labels) {
|
|
867
|
-
return Object.entries(labels).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}=${v}`).join(",");
|
|
868
|
-
}
|
|
869
|
-
};
|
|
870
|
-
}
|
|
871
|
-
});
|
|
872
|
-
|
|
873
|
-
// src/telemetry/gauge.ts
|
|
874
|
-
var Gauge;
|
|
875
|
-
var init_gauge = __esm({
|
|
876
|
-
"src/telemetry/gauge.ts"() {
|
|
877
|
-
Gauge = class {
|
|
878
|
-
constructor(name) {
|
|
879
|
-
this.name = name;
|
|
880
|
-
}
|
|
881
|
-
value = 0;
|
|
882
|
-
labeledValues = /* @__PURE__ */ new Map();
|
|
883
|
-
/**
|
|
884
|
-
* Set gauge to specific value
|
|
885
|
-
*
|
|
886
|
-
* @param value - New gauge value (can be any number, including negative)
|
|
887
|
-
* @param labels - Optional label dimensions for this observation
|
|
888
|
-
*
|
|
889
|
-
* @example
|
|
890
|
-
* ```typescript
|
|
891
|
-
* gauge.set(42); // Set unlabeled to 42
|
|
892
|
-
* gauge.set(-10); // Negative values allowed
|
|
893
|
-
* gauge.set(1, { phase: 'collect' }); // Set labeled instance
|
|
894
|
-
* ```
|
|
895
|
-
*/
|
|
896
|
-
set(value, labels) {
|
|
897
|
-
if (labels && Object.keys(labels).length > 0) {
|
|
898
|
-
const labelKey = this.serializeLabels(labels);
|
|
899
|
-
this.labeledValues.set(labelKey, value);
|
|
900
|
-
} else {
|
|
901
|
-
this.value = value;
|
|
902
|
-
}
|
|
903
|
-
}
|
|
904
|
-
/**
|
|
905
|
-
* Increment gauge by delta (default: 1)
|
|
906
|
-
*
|
|
907
|
-
* @param delta - Amount to increment (can be negative)
|
|
908
|
-
* @param labels - Optional label dimensions for this observation
|
|
909
|
-
*/
|
|
910
|
-
inc(delta = 1, labels) {
|
|
911
|
-
if (labels && Object.keys(labels).length > 0) {
|
|
912
|
-
const labelKey = this.serializeLabels(labels);
|
|
913
|
-
const current = this.labeledValues.get(labelKey) || 0;
|
|
914
|
-
this.labeledValues.set(labelKey, current + delta);
|
|
915
|
-
} else {
|
|
916
|
-
this.value += delta;
|
|
917
|
-
}
|
|
918
|
-
}
|
|
919
|
-
/**
|
|
920
|
-
* Decrement gauge by delta (default: 1)
|
|
921
|
-
*
|
|
922
|
-
* @param delta - Amount to decrement (can be negative)
|
|
923
|
-
* @param labels - Optional label dimensions for this observation
|
|
924
|
-
*/
|
|
925
|
-
dec(delta = 1, labels) {
|
|
926
|
-
if (labels && Object.keys(labels).length > 0) {
|
|
927
|
-
const labelKey = this.serializeLabels(labels);
|
|
928
|
-
const current = this.labeledValues.get(labelKey) || 0;
|
|
929
|
-
this.labeledValues.set(labelKey, current - delta);
|
|
930
|
-
} else {
|
|
931
|
-
this.value -= delta;
|
|
932
|
-
}
|
|
933
|
-
}
|
|
934
|
-
/**
|
|
935
|
-
* Get current gauge value (unlabeled)
|
|
936
|
-
*/
|
|
937
|
-
getValue() {
|
|
938
|
-
return this.value;
|
|
939
|
-
}
|
|
940
|
-
/**
|
|
941
|
-
* Get all labeled values
|
|
942
|
-
* @returns Map of serialized label keys to values
|
|
943
|
-
*/
|
|
944
|
-
getLabeledValues() {
|
|
945
|
-
return new Map(this.labeledValues);
|
|
946
|
-
}
|
|
947
|
-
/**
|
|
948
|
-
* Get value for specific label combination
|
|
949
|
-
*/
|
|
950
|
-
getValueForLabels(labels) {
|
|
951
|
-
const labelKey = this.serializeLabels(labels);
|
|
952
|
-
return this.labeledValues.get(labelKey) || 0;
|
|
953
|
-
}
|
|
954
|
-
/**
|
|
955
|
-
* Reset gauge to zero (all label combinations)
|
|
956
|
-
*/
|
|
957
|
-
reset() {
|
|
958
|
-
this.value = 0;
|
|
959
|
-
this.labeledValues.clear();
|
|
960
|
-
}
|
|
961
|
-
/**
|
|
962
|
-
* Serialize labels to deterministic string key
|
|
963
|
-
* Format: key1=value1,key2=value2 (sorted by key)
|
|
964
|
-
*/
|
|
965
|
-
serializeLabels(labels) {
|
|
966
|
-
return Object.entries(labels).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}=${v}`).join(",");
|
|
967
|
-
}
|
|
968
|
-
};
|
|
969
|
-
}
|
|
970
|
-
});
|
|
971
|
-
async function getDefaultUnit(name) {
|
|
972
|
-
return TaxonomyLoader.getInstance().getDefaultUnit(name);
|
|
973
|
-
}
|
|
974
|
-
var DEFAULT_MS_BUCKETS, TaxonomyLoader;
|
|
975
|
-
var init_taxonomy = __esm({
|
|
976
|
-
"src/telemetry/taxonomy.ts"() {
|
|
977
|
-
DEFAULT_MS_BUCKETS = [1, 5, 10, 50, 100, 500, 1e3, 5e3, 1e4];
|
|
978
|
-
TaxonomyLoader = class _TaxonomyLoader {
|
|
979
|
-
static instance;
|
|
980
|
-
taxonomy = null;
|
|
981
|
-
loadPromise = null;
|
|
982
|
-
loadError = null;
|
|
983
|
-
constructor() {
|
|
984
|
-
}
|
|
985
|
-
/**
|
|
986
|
-
* Get singleton instance
|
|
987
|
-
*/
|
|
988
|
-
static getInstance() {
|
|
989
|
-
if (!_TaxonomyLoader.instance) {
|
|
990
|
-
_TaxonomyLoader.instance = new _TaxonomyLoader();
|
|
991
|
-
}
|
|
992
|
-
return _TaxonomyLoader.instance;
|
|
993
|
-
}
|
|
994
|
-
/**
|
|
995
|
-
* Load taxonomy from YAML file
|
|
996
|
-
*/
|
|
997
|
-
async load() {
|
|
998
|
-
if (this.taxonomy !== null) {
|
|
999
|
-
return this.taxonomy;
|
|
1000
|
-
}
|
|
1001
|
-
if (this.loadError !== null) {
|
|
1002
|
-
throw this.loadError;
|
|
1003
|
-
}
|
|
1004
|
-
if (this.loadPromise) {
|
|
1005
|
-
return this.loadPromise;
|
|
1006
|
-
}
|
|
1007
|
-
this.loadPromise = (async () => {
|
|
1008
|
-
try {
|
|
1009
|
-
const taxonomyPath = join(
|
|
1010
|
-
__dirname,
|
|
1011
|
-
"..",
|
|
1012
|
-
"..",
|
|
1013
|
-
"config",
|
|
1014
|
-
"crucible-ts",
|
|
1015
|
-
"taxonomy",
|
|
1016
|
-
"metrics.yaml"
|
|
1017
|
-
);
|
|
1018
|
-
const content = await readFile(taxonomyPath, "utf-8");
|
|
1019
|
-
this.taxonomy = parse(content);
|
|
1020
|
-
return this.taxonomy;
|
|
1021
|
-
} catch (err) {
|
|
1022
|
-
this.loadError = err instanceof Error ? err : new Error(String(err));
|
|
1023
|
-
throw new Error(`Failed to load metrics taxonomy: ${this.loadError.message}`);
|
|
1024
|
-
}
|
|
1025
|
-
})();
|
|
1026
|
-
return this.loadPromise;
|
|
1027
|
-
}
|
|
1028
|
-
/**
|
|
1029
|
-
* Get taxonomy (async)
|
|
1030
|
-
*/
|
|
1031
|
-
async getTaxonomy() {
|
|
1032
|
-
return this.load();
|
|
1033
|
-
}
|
|
1034
|
-
/**
|
|
1035
|
-
* Get metric definition by name
|
|
1036
|
-
*/
|
|
1037
|
-
async getMetric(name) {
|
|
1038
|
-
const taxonomy = await this.load();
|
|
1039
|
-
return taxonomy.metrics.find((m) => m.name === name);
|
|
1040
|
-
}
|
|
1041
|
-
/**
|
|
1042
|
-
* Get default unit for metric
|
|
1043
|
-
*/
|
|
1044
|
-
async getDefaultUnit(name) {
|
|
1045
|
-
const metric = await this.getMetric(name);
|
|
1046
|
-
return metric?.unit;
|
|
1047
|
-
}
|
|
1048
|
-
/**
|
|
1049
|
-
* Get default histogram buckets for metric
|
|
1050
|
-
* Returns ADR-0007 buckets for _ms metrics, undefined for others
|
|
1051
|
-
*/
|
|
1052
|
-
async getDefaultBuckets(name) {
|
|
1053
|
-
if (name.endsWith("_ms")) {
|
|
1054
|
-
const taxonomy = await this.load();
|
|
1055
|
-
return taxonomy.defaults.histogram_buckets.ms_metrics;
|
|
1056
|
-
}
|
|
1057
|
-
return void 0;
|
|
1058
|
-
}
|
|
1059
|
-
/**
|
|
1060
|
-
* Check if metric name is valid (exists in taxonomy)
|
|
1061
|
-
*/
|
|
1062
|
-
async isValidMetricName(name) {
|
|
1063
|
-
try {
|
|
1064
|
-
const taxonomy = await this.load();
|
|
1065
|
-
return taxonomy.metrics.some((m) => m.name === name);
|
|
1066
|
-
} catch {
|
|
1067
|
-
return false;
|
|
1068
|
-
}
|
|
1069
|
-
}
|
|
1070
|
-
/**
|
|
1071
|
-
* Reset loader state (for testing)
|
|
1072
|
-
* @internal
|
|
1073
|
-
*/
|
|
1074
|
-
static _reset() {
|
|
1075
|
-
_TaxonomyLoader.instance = new _TaxonomyLoader();
|
|
1076
|
-
}
|
|
1077
|
-
};
|
|
1078
|
-
}
|
|
1079
|
-
});
|
|
1080
|
-
|
|
1081
|
-
// src/telemetry/histogram.ts
|
|
1082
|
-
var Histogram;
|
|
1083
|
-
var init_histogram = __esm({
|
|
1084
|
-
"src/telemetry/histogram.ts"() {
|
|
1085
|
-
init_taxonomy();
|
|
1086
|
-
Histogram = class {
|
|
1087
|
-
constructor(name, options) {
|
|
1088
|
-
this.name = name;
|
|
1089
|
-
if (options?.buckets) {
|
|
1090
|
-
this.buckets = [...options.buckets].sort((a, b) => a - b);
|
|
1091
|
-
} else if (name.endsWith("_ms") || name.endsWith("_seconds")) {
|
|
1092
|
-
this.buckets = [...DEFAULT_MS_BUCKETS];
|
|
1093
|
-
} else {
|
|
1094
|
-
this.buckets = [];
|
|
1095
|
-
}
|
|
1096
|
-
for (const bucket of this.buckets) {
|
|
1097
|
-
this.bucketCounts.set(bucket, 0);
|
|
1098
|
-
}
|
|
1099
|
-
}
|
|
1100
|
-
count = 0;
|
|
1101
|
-
sum = 0;
|
|
1102
|
-
bucketCounts = /* @__PURE__ */ new Map();
|
|
1103
|
-
labeledStates = /* @__PURE__ */ new Map();
|
|
1104
|
-
buckets;
|
|
1105
|
-
/**
|
|
1106
|
-
* Record an observation
|
|
1107
|
-
*
|
|
1108
|
-
* @param value - Value to observe (typically a duration in ms or seconds)
|
|
1109
|
-
* @param labels - Optional label dimensions for this observation
|
|
1110
|
-
*
|
|
1111
|
-
* @example
|
|
1112
|
-
* ```typescript
|
|
1113
|
-
* const start = performance.now();
|
|
1114
|
-
* // ... operation ...
|
|
1115
|
-
* histogram.observe(performance.now() - start);
|
|
1116
|
-
* histogram.observe(duration, { phase: 'collect', result: 'success' });
|
|
1117
|
-
* ```
|
|
1118
|
-
*/
|
|
1119
|
-
observe(value, labels) {
|
|
1120
|
-
if (labels && Object.keys(labels).length > 0) {
|
|
1121
|
-
const labelKey = this.serializeLabels(labels);
|
|
1122
|
-
let state = this.labeledStates.get(labelKey);
|
|
1123
|
-
if (!state) {
|
|
1124
|
-
state = {
|
|
1125
|
-
count: 0,
|
|
1126
|
-
sum: 0,
|
|
1127
|
-
bucketCounts: /* @__PURE__ */ new Map()
|
|
1128
|
-
};
|
|
1129
|
-
for (const bucket of this.buckets) {
|
|
1130
|
-
state.bucketCounts.set(bucket, 0);
|
|
1131
|
-
}
|
|
1132
|
-
this.labeledStates.set(labelKey, state);
|
|
1133
|
-
}
|
|
1134
|
-
state.count++;
|
|
1135
|
-
state.sum += value;
|
|
1136
|
-
for (const bucket of this.buckets) {
|
|
1137
|
-
if (value <= bucket) {
|
|
1138
|
-
state.bucketCounts.set(bucket, (state.bucketCounts.get(bucket) || 0) + 1);
|
|
1139
|
-
}
|
|
1140
|
-
}
|
|
1141
|
-
} else {
|
|
1142
|
-
this.count++;
|
|
1143
|
-
this.sum += value;
|
|
1144
|
-
for (const bucket of this.buckets) {
|
|
1145
|
-
if (value <= bucket) {
|
|
1146
|
-
this.bucketCounts.set(bucket, (this.bucketCounts.get(bucket) || 0) + 1);
|
|
1147
|
-
}
|
|
1148
|
-
}
|
|
1149
|
-
}
|
|
1150
|
-
}
|
|
1151
|
-
/**
|
|
1152
|
-
* Get histogram summary
|
|
1153
|
-
*
|
|
1154
|
-
* Returns OTLP-compatible histogram summary with cumulative bucket counts.
|
|
1155
|
-
*/
|
|
1156
|
-
getSummary() {
|
|
1157
|
-
const buckets = this.buckets.map((le) => ({
|
|
1158
|
-
le,
|
|
1159
|
-
count: this.bucketCounts.get(le) || 0
|
|
1160
|
-
}));
|
|
1161
|
-
return {
|
|
1162
|
-
count: this.count,
|
|
1163
|
-
sum: this.sum,
|
|
1164
|
-
buckets
|
|
1165
|
-
};
|
|
1166
|
-
}
|
|
1167
|
-
/**
|
|
1168
|
-
* Get current observation count
|
|
1169
|
-
*/
|
|
1170
|
-
getCount() {
|
|
1171
|
-
return this.count;
|
|
1172
|
-
}
|
|
1173
|
-
/**
|
|
1174
|
-
* Get sum of all observed values
|
|
1175
|
-
*/
|
|
1176
|
-
getSum() {
|
|
1177
|
-
return this.sum;
|
|
1178
|
-
}
|
|
1179
|
-
/**
|
|
1180
|
-
* Get average of observed values
|
|
1181
|
-
*/
|
|
1182
|
-
getAverage() {
|
|
1183
|
-
return this.count > 0 ? this.sum / this.count : 0;
|
|
1184
|
-
}
|
|
1185
|
-
/**
|
|
1186
|
-
* Get all labeled summaries
|
|
1187
|
-
* @returns Map of serialized label keys to histogram summaries
|
|
1188
|
-
*/
|
|
1189
|
-
getLabeledSummaries() {
|
|
1190
|
-
const summaries = /* @__PURE__ */ new Map();
|
|
1191
|
-
for (const [labelKey, state] of this.labeledStates) {
|
|
1192
|
-
const buckets = this.buckets.map((le) => ({
|
|
1193
|
-
le,
|
|
1194
|
-
count: state.bucketCounts.get(le) || 0
|
|
1195
|
-
}));
|
|
1196
|
-
summaries.set(labelKey, {
|
|
1197
|
-
count: state.count,
|
|
1198
|
-
sum: state.sum,
|
|
1199
|
-
buckets
|
|
1200
|
-
});
|
|
1201
|
-
}
|
|
1202
|
-
return summaries;
|
|
1203
|
-
}
|
|
1204
|
-
/**
|
|
1205
|
-
* Get summary for specific label combination
|
|
1206
|
-
*/
|
|
1207
|
-
getSummaryForLabels(labels) {
|
|
1208
|
-
const labelKey = this.serializeLabels(labels);
|
|
1209
|
-
const state = this.labeledStates.get(labelKey);
|
|
1210
|
-
if (!state) {
|
|
1211
|
-
return null;
|
|
1212
|
-
}
|
|
1213
|
-
const buckets = this.buckets.map((le) => ({
|
|
1214
|
-
le,
|
|
1215
|
-
count: state.bucketCounts.get(le) || 0
|
|
1216
|
-
}));
|
|
1217
|
-
return {
|
|
1218
|
-
count: state.count,
|
|
1219
|
-
sum: state.sum,
|
|
1220
|
-
buckets
|
|
1221
|
-
};
|
|
1222
|
-
}
|
|
1223
|
-
/**
|
|
1224
|
-
* Reset histogram to initial state (all label combinations)
|
|
1225
|
-
*/
|
|
1226
|
-
reset() {
|
|
1227
|
-
this.count = 0;
|
|
1228
|
-
this.sum = 0;
|
|
1229
|
-
for (const bucket of this.buckets) {
|
|
1230
|
-
this.bucketCounts.set(bucket, 0);
|
|
1231
|
-
}
|
|
1232
|
-
this.labeledStates.clear();
|
|
1233
|
-
}
|
|
1234
|
-
/**
|
|
1235
|
-
* Serialize labels to deterministic string key
|
|
1236
|
-
* Format: key1=value1,key2=value2 (sorted by key)
|
|
1237
|
-
*/
|
|
1238
|
-
serializeLabels(labels) {
|
|
1239
|
-
return Object.entries(labels).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}=${v}`).join(",");
|
|
1240
|
-
}
|
|
1241
|
-
};
|
|
1242
|
-
}
|
|
1243
|
-
});
|
|
1244
|
-
|
|
1245
|
-
// src/telemetry/registry.ts
|
|
1246
|
-
var MetricsRegistry;
|
|
1247
|
-
var init_registry2 = __esm({
|
|
1248
|
-
"src/telemetry/registry.ts"() {
|
|
1249
|
-
init_counter();
|
|
1250
|
-
init_gauge();
|
|
1251
|
-
init_histogram();
|
|
1252
|
-
init_taxonomy();
|
|
1253
|
-
MetricsRegistry = class {
|
|
1254
|
-
counters = /* @__PURE__ */ new Map();
|
|
1255
|
-
gauges = /* @__PURE__ */ new Map();
|
|
1256
|
-
histograms = /* @__PURE__ */ new Map();
|
|
1257
|
-
/**
|
|
1258
|
-
* Get or create a counter
|
|
1259
|
-
*
|
|
1260
|
-
* @param name - Metric name from taxonomy
|
|
1261
|
-
* @returns Counter instance
|
|
1262
|
-
*
|
|
1263
|
-
* @example
|
|
1264
|
-
* ```typescript
|
|
1265
|
-
* const counter = registry.counter('schema_validations');
|
|
1266
|
-
* counter.inc();
|
|
1267
|
-
* ```
|
|
1268
|
-
*/
|
|
1269
|
-
counter(name) {
|
|
1270
|
-
let counter = this.counters.get(name);
|
|
1271
|
-
if (!counter) {
|
|
1272
|
-
counter = new Counter(name);
|
|
1273
|
-
this.counters.set(name, counter);
|
|
1274
|
-
}
|
|
1275
|
-
return counter;
|
|
1276
|
-
}
|
|
1277
|
-
/**
|
|
1278
|
-
* Get or create a gauge
|
|
1279
|
-
*
|
|
1280
|
-
* @param name - Metric name from taxonomy
|
|
1281
|
-
* @returns Gauge instance
|
|
1282
|
-
*
|
|
1283
|
-
* @example
|
|
1284
|
-
* ```typescript
|
|
1285
|
-
* const gauge = registry.gauge('foundry_lookup_count');
|
|
1286
|
-
* gauge.set(42);
|
|
1287
|
-
* ```
|
|
1288
|
-
*/
|
|
1289
|
-
gauge(name) {
|
|
1290
|
-
let gauge = this.gauges.get(name);
|
|
1291
|
-
if (!gauge) {
|
|
1292
|
-
gauge = new Gauge(name);
|
|
1293
|
-
this.gauges.set(name, gauge);
|
|
1294
|
-
}
|
|
1295
|
-
return gauge;
|
|
1296
|
-
}
|
|
1297
|
-
/**
|
|
1298
|
-
* Get or create a histogram
|
|
1299
|
-
*
|
|
1300
|
-
* @param name - Metric name from taxonomy
|
|
1301
|
-
* @param options - Optional histogram options
|
|
1302
|
-
* @returns Histogram instance
|
|
1303
|
-
*
|
|
1304
|
-
* @example
|
|
1305
|
-
* ```typescript
|
|
1306
|
-
* // Auto-applies ADR-0007 buckets for _ms metrics
|
|
1307
|
-
* const histogram = registry.histogram('config_load_ms');
|
|
1308
|
-
* histogram.observe(42.5);
|
|
1309
|
-
*
|
|
1310
|
-
* // Custom buckets
|
|
1311
|
-
* const custom = registry.histogram('custom_metric', {
|
|
1312
|
-
* buckets: [10, 50, 100, 500, 1000]
|
|
1313
|
-
* });
|
|
1314
|
-
* ```
|
|
1315
|
-
*/
|
|
1316
|
-
histogram(name, options) {
|
|
1317
|
-
let histogram = this.histograms.get(name);
|
|
1318
|
-
if (!histogram) {
|
|
1319
|
-
histogram = new Histogram(name, options);
|
|
1320
|
-
this.histograms.set(name, histogram);
|
|
1321
|
-
}
|
|
1322
|
-
return histogram;
|
|
1323
|
-
}
|
|
1324
|
-
/**
|
|
1325
|
-
* Export all metrics as events
|
|
1326
|
-
*
|
|
1327
|
-
* Returns array of schema-compliant MetricsEvent objects.
|
|
1328
|
-
* Does not clear metrics (use flush() to clear after export).
|
|
1329
|
-
*
|
|
1330
|
-
* @returns Promise resolving to array of metrics events
|
|
1331
|
-
*
|
|
1332
|
-
* @example
|
|
1333
|
-
* ```typescript
|
|
1334
|
-
* const events = await registry.export();
|
|
1335
|
-
* console.log(JSON.stringify(events, null, 2));
|
|
1336
|
-
* ```
|
|
1337
|
-
*/
|
|
1338
|
-
async export() {
|
|
1339
|
-
const events = [];
|
|
1340
|
-
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
1341
|
-
for (const [name, counter] of this.counters) {
|
|
1342
|
-
const unit = await getDefaultUnit(name);
|
|
1343
|
-
events.push({
|
|
1344
|
-
timestamp,
|
|
1345
|
-
name,
|
|
1346
|
-
value: counter.getValue(),
|
|
1347
|
-
unit
|
|
1348
|
-
});
|
|
1349
|
-
for (const [labelKey, value] of counter.getLabeledValues()) {
|
|
1350
|
-
if (value > 0) {
|
|
1351
|
-
const tags = this.deserializeLabels(labelKey);
|
|
1352
|
-
events.push({
|
|
1353
|
-
timestamp,
|
|
1354
|
-
name,
|
|
1355
|
-
value,
|
|
1356
|
-
tags,
|
|
1357
|
-
unit
|
|
1358
|
-
});
|
|
1359
|
-
}
|
|
1360
|
-
}
|
|
1361
|
-
}
|
|
1362
|
-
for (const [name, gauge] of this.gauges) {
|
|
1363
|
-
const unit = await getDefaultUnit(name);
|
|
1364
|
-
events.push({
|
|
1365
|
-
timestamp,
|
|
1366
|
-
name,
|
|
1367
|
-
value: gauge.getValue(),
|
|
1368
|
-
unit
|
|
1369
|
-
});
|
|
1370
|
-
for (const [labelKey, value] of gauge.getLabeledValues()) {
|
|
1371
|
-
const tags = this.deserializeLabels(labelKey);
|
|
1372
|
-
events.push({
|
|
1373
|
-
timestamp,
|
|
1374
|
-
name,
|
|
1375
|
-
value,
|
|
1376
|
-
tags,
|
|
1377
|
-
unit
|
|
1378
|
-
});
|
|
1379
|
-
}
|
|
1380
|
-
}
|
|
1381
|
-
for (const [name, histogram] of this.histograms) {
|
|
1382
|
-
const unit = await getDefaultUnit(name);
|
|
1383
|
-
events.push({
|
|
1384
|
-
timestamp,
|
|
1385
|
-
name,
|
|
1386
|
-
value: histogram.getSummary(),
|
|
1387
|
-
unit
|
|
1388
|
-
});
|
|
1389
|
-
for (const [labelKey, summary] of histogram.getLabeledSummaries()) {
|
|
1390
|
-
if (summary.count > 0) {
|
|
1391
|
-
const tags = this.deserializeLabels(labelKey);
|
|
1392
|
-
events.push({
|
|
1393
|
-
timestamp,
|
|
1394
|
-
name,
|
|
1395
|
-
value: summary,
|
|
1396
|
-
tags,
|
|
1397
|
-
unit
|
|
1398
|
-
});
|
|
1399
|
-
}
|
|
1400
|
-
}
|
|
1401
|
-
}
|
|
1402
|
-
return events;
|
|
1403
|
-
}
|
|
1404
|
-
/**
|
|
1405
|
-
* Deserialize label key back to tags object
|
|
1406
|
-
* Format: key1=value1,key2=value2 → {key1: "value1", key2: "value2"}
|
|
1407
|
-
*/
|
|
1408
|
-
deserializeLabels(labelKey) {
|
|
1409
|
-
if (!labelKey) {
|
|
1410
|
-
return {};
|
|
1411
|
-
}
|
|
1412
|
-
const tags = {};
|
|
1413
|
-
for (const pair of labelKey.split(",")) {
|
|
1414
|
-
const [key, value] = pair.split("=");
|
|
1415
|
-
if (key && value) {
|
|
1416
|
-
tags[key] = value;
|
|
1417
|
-
}
|
|
1418
|
-
}
|
|
1419
|
-
return tags;
|
|
1420
|
-
}
|
|
1421
|
-
/**
|
|
1422
|
-
* Export and clear all metrics
|
|
1423
|
-
*
|
|
1424
|
-
* Exports metrics as events, optionally emits them via logger,
|
|
1425
|
-
* then resets all metrics to zero.
|
|
1426
|
-
*
|
|
1427
|
-
* @param options - Flush options
|
|
1428
|
-
* @returns Promise resolving to array of exported events
|
|
1429
|
-
*
|
|
1430
|
-
* @example
|
|
1431
|
-
* ```typescript
|
|
1432
|
-
* // Export and clear
|
|
1433
|
-
* const events = await registry.flush();
|
|
1434
|
-
*
|
|
1435
|
-
* // Export, emit to logger, and clear
|
|
1436
|
-
* const events = await registry.flush({
|
|
1437
|
-
* emit: (events) => console.log(JSON.stringify(events))
|
|
1438
|
-
* });
|
|
1439
|
-
* ```
|
|
1440
|
-
*/
|
|
1441
|
-
async flush(options) {
|
|
1442
|
-
const events = await this.export();
|
|
1443
|
-
try {
|
|
1444
|
-
if (options?.emit) {
|
|
1445
|
-
options.emit(events);
|
|
1446
|
-
}
|
|
1447
|
-
} finally {
|
|
1448
|
-
this.clear();
|
|
1449
|
-
}
|
|
1450
|
-
return events;
|
|
1451
|
-
}
|
|
1452
|
-
/**
|
|
1453
|
-
* Clear all metrics (reset to zero)
|
|
1454
|
-
*
|
|
1455
|
-
* Resets all counters, gauges, and histograms to their initial state.
|
|
1456
|
-
*/
|
|
1457
|
-
clear() {
|
|
1458
|
-
for (const counter of this.counters.values()) {
|
|
1459
|
-
counter.reset();
|
|
1460
|
-
}
|
|
1461
|
-
for (const gauge of this.gauges.values()) {
|
|
1462
|
-
gauge.reset();
|
|
1463
|
-
}
|
|
1464
|
-
for (const histogram of this.histograms.values()) {
|
|
1465
|
-
histogram.reset();
|
|
1466
|
-
}
|
|
1467
|
-
}
|
|
1468
|
-
/**
|
|
1469
|
-
* Get all registered metric names
|
|
1470
|
-
*
|
|
1471
|
-
* Returns array of all metric names that have been accessed
|
|
1472
|
-
* (counters, gauges, or histograms).
|
|
1473
|
-
*/
|
|
1474
|
-
getMetricNames() {
|
|
1475
|
-
const names = /* @__PURE__ */ new Set();
|
|
1476
|
-
for (const name of this.counters.keys()) {
|
|
1477
|
-
names.add(name);
|
|
1478
|
-
}
|
|
1479
|
-
for (const name of this.gauges.keys()) {
|
|
1480
|
-
names.add(name);
|
|
1481
|
-
}
|
|
1482
|
-
for (const name of this.histograms.keys()) {
|
|
1483
|
-
names.add(name);
|
|
1484
|
-
}
|
|
1485
|
-
return Array.from(names);
|
|
1486
|
-
}
|
|
1487
|
-
/**
|
|
1488
|
-
* Get total count of registered metrics
|
|
1489
|
-
*/
|
|
1490
|
-
getMetricCount() {
|
|
1491
|
-
return this.counters.size + this.gauges.size + this.histograms.size;
|
|
1492
|
-
}
|
|
1493
|
-
};
|
|
1494
|
-
}
|
|
1495
|
-
});
|
|
1496
|
-
|
|
1497
|
-
// src/telemetry/types.ts
|
|
1498
|
-
var init_types2 = __esm({
|
|
1499
|
-
"src/telemetry/types.ts"() {
|
|
1500
|
-
}
|
|
1501
|
-
});
|
|
1502
|
-
|
|
1503
|
-
// src/telemetry/validators.ts
|
|
1504
|
-
var init_validators = __esm({
|
|
1505
|
-
"src/telemetry/validators.ts"() {
|
|
1506
|
-
init_schema();
|
|
1507
|
-
}
|
|
1508
|
-
});
|
|
1509
|
-
|
|
1510
|
-
// src/telemetry/index.ts
|
|
1511
|
-
var metrics;
|
|
1512
|
-
var init_telemetry = __esm({
|
|
1513
|
-
"src/telemetry/index.ts"() {
|
|
1514
|
-
init_registry2();
|
|
1515
|
-
init_registry2();
|
|
1516
|
-
init_counter();
|
|
1517
|
-
init_gauge();
|
|
1518
|
-
init_histogram();
|
|
1519
|
-
init_taxonomy();
|
|
1520
|
-
init_types2();
|
|
1521
|
-
init_validators();
|
|
1522
|
-
metrics = new MetricsRegistry();
|
|
1523
|
-
}
|
|
1524
|
-
});
|
|
1525
|
-
async function loadMetaSchema(draft) {
|
|
1526
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
1527
|
-
const __dirname2 = dirname(__filename);
|
|
1528
|
-
const metaSchemaPath = join(
|
|
1529
|
-
__dirname2,
|
|
1530
|
-
"..",
|
|
1531
|
-
"..",
|
|
1532
|
-
"schemas",
|
|
1533
|
-
"crucible-ts",
|
|
1534
|
-
"meta",
|
|
1535
|
-
draft,
|
|
1536
|
-
"schema.json"
|
|
1537
|
-
);
|
|
1538
|
-
const content = await readFile(metaSchemaPath, "utf-8");
|
|
1539
|
-
return JSON.parse(content);
|
|
1540
|
-
}
|
|
1541
|
-
async function loadVocabularySchemas(draft) {
|
|
1542
|
-
if (draft !== "draft-2019-09" && draft !== "draft-2020-12") {
|
|
1543
|
-
return [];
|
|
1544
|
-
}
|
|
1545
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
1546
|
-
const __dirname2 = dirname(__filename);
|
|
1547
|
-
const vocabDir = join(__dirname2, "..", "..", "schemas", "crucible-ts", "meta", draft, "meta");
|
|
1548
|
-
const vocabFiles = draft === "draft-2020-12" ? [
|
|
1549
|
-
"core.json",
|
|
1550
|
-
"applicator.json",
|
|
1551
|
-
"unevaluated.json",
|
|
1552
|
-
"validation.json",
|
|
1553
|
-
"meta-data.json",
|
|
1554
|
-
"format-annotation.json",
|
|
1555
|
-
"content.json"
|
|
1556
|
-
] : [
|
|
1557
|
-
"core.json",
|
|
1558
|
-
"applicator.json",
|
|
1559
|
-
"validation.json",
|
|
1560
|
-
"meta-data.json",
|
|
1561
|
-
"format.json",
|
|
1562
|
-
"content.json"
|
|
1563
|
-
];
|
|
1564
|
-
const schemas = [];
|
|
1565
|
-
for (const file of vocabFiles) {
|
|
1566
|
-
try {
|
|
1567
|
-
const content = await readFile(join(vocabDir, file), "utf-8");
|
|
1568
|
-
schemas.push(JSON.parse(content));
|
|
1569
|
-
} catch {
|
|
1570
|
-
}
|
|
1571
|
-
}
|
|
1572
|
-
return schemas;
|
|
1573
|
-
}
|
|
1574
|
-
async function loadReferencedSchema(uri) {
|
|
1575
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
1576
|
-
const __dirname2 = dirname(__filename);
|
|
1577
|
-
const repoRoot = join(__dirname2, "..", "..");
|
|
1578
|
-
let resolvedPath;
|
|
1579
|
-
if (uri.startsWith("https://schemas.fulmenhq.dev/")) {
|
|
1580
|
-
let relativePath = uri.replace("https://schemas.fulmenhq.dev/", "");
|
|
1581
|
-
if (relativePath.startsWith("crucible/")) {
|
|
1582
|
-
relativePath = relativePath.slice("crucible/".length);
|
|
1583
|
-
}
|
|
1584
|
-
if (relativePath.startsWith("config/taxonomy/")) {
|
|
1585
|
-
resolvedPath = join(
|
|
1586
|
-
repoRoot,
|
|
1587
|
-
"config",
|
|
1588
|
-
"crucible-ts",
|
|
1589
|
-
"taxonomy",
|
|
1590
|
-
relativePath.split("/").pop() || ""
|
|
1591
|
-
);
|
|
1592
|
-
} else {
|
|
1593
|
-
resolvedPath = join(repoRoot, "schemas", "crucible-ts", relativePath);
|
|
1594
|
-
}
|
|
1595
|
-
} else if (uri.startsWith("../../") || uri.startsWith("../")) {
|
|
1596
|
-
const schemaBase = join(
|
|
1597
|
-
repoRoot,
|
|
1598
|
-
"schemas",
|
|
1599
|
-
"crucible-ts",
|
|
1600
|
-
"observability",
|
|
1601
|
-
"metrics",
|
|
1602
|
-
"v1.0.0"
|
|
1603
|
-
);
|
|
1604
|
-
resolvedPath = join(schemaBase, uri);
|
|
1605
|
-
} else if (uri.startsWith("file://")) {
|
|
1606
|
-
resolvedPath = fileURLToPath(uri);
|
|
1607
|
-
} else {
|
|
1608
|
-
throw new Error(`Cannot load remote schema: ${uri}`);
|
|
1609
|
-
}
|
|
1610
|
-
const content = await readFile(resolvedPath, "utf-8");
|
|
1611
|
-
const ext = resolvedPath.split(".").pop()?.toLowerCase();
|
|
1612
|
-
if (ext === "yaml" || ext === "yml") {
|
|
1613
|
-
return parse(content);
|
|
1614
|
-
}
|
|
1615
|
-
return JSON.parse(content);
|
|
1616
|
-
}
|
|
1617
|
-
function detectDialect(schema) {
|
|
1618
|
-
if (schema && typeof schema === "object" && !Array.isArray(schema)) {
|
|
1619
|
-
const maybeSchema = schema;
|
|
1620
|
-
const declared = maybeSchema.$schema;
|
|
1621
|
-
if (typeof declared === "string") {
|
|
1622
|
-
if (declared.includes("draft-04")) return "draft-04";
|
|
1623
|
-
if (declared.includes("draft-06")) return "draft-06";
|
|
1624
|
-
if (declared.includes("draft-07")) return "draft-07";
|
|
1625
|
-
if (declared.includes("draft/2019-09")) return "draft-2019-09";
|
|
1626
|
-
if (declared.includes("draft/2020-12")) return "draft-2020-12";
|
|
1627
|
-
}
|
|
1628
|
-
}
|
|
1629
|
-
return "draft-2020-12";
|
|
1630
|
-
}
|
|
1631
|
-
function createAjv(dialect) {
|
|
1632
|
-
const AjvCtor = dialect === "draft-2020-12" ? Ajv2020 : dialect === "draft-2019-09" ? Ajv2019 : dialect === "draft-04" ? AjvDraft04 : Ajv;
|
|
1633
|
-
const ajv = new AjvCtor({
|
|
1634
|
-
strict: false,
|
|
1635
|
-
allErrors: true,
|
|
1636
|
-
verbose: true,
|
|
1637
|
-
// Allow schemas with $id to be added without replacing existing ones
|
|
1638
|
-
addUsedSchema: false,
|
|
1639
|
-
// draft-04 uses "id"; later drafts use "$id"
|
|
1640
|
-
schemaId: dialect === "draft-04" ? "id" : "$id",
|
|
1641
|
-
// Enable async schema loading for YAML references
|
|
1642
|
-
loadSchema: loadReferencedSchema
|
|
1643
|
-
});
|
|
1644
|
-
applyFulmenAjvFormats(ajv);
|
|
1645
|
-
return ajv;
|
|
1646
|
-
}
|
|
1647
|
-
async function getAjv(dialect) {
|
|
1648
|
-
const existing = ajvInstances.get(dialect);
|
|
1649
|
-
if (existing) {
|
|
1650
|
-
const ready = metaschemaReady.get(dialect);
|
|
1651
|
-
if (ready) await ready;
|
|
1652
|
-
return existing;
|
|
1653
|
-
}
|
|
1654
|
-
const ajv = createAjv(dialect);
|
|
1655
|
-
ajvInstances.set(dialect, ajv);
|
|
1656
|
-
const readyPromise = Promise.all([loadVocabularySchemas(dialect), loadMetaSchema(dialect)]).then(([vocabSchemas, metaSchema]) => {
|
|
1657
|
-
for (const vocabSchema of vocabSchemas) {
|
|
1658
|
-
try {
|
|
1659
|
-
ajv.addMetaSchema(vocabSchema);
|
|
1660
|
-
} catch {
|
|
1661
|
-
}
|
|
1662
|
-
}
|
|
1663
|
-
try {
|
|
1664
|
-
ajv.addMetaSchema(metaSchema);
|
|
1665
|
-
} catch {
|
|
1666
|
-
}
|
|
1667
|
-
}).catch((error) => {
|
|
1668
|
-
throw new Error(`Failed to load metaschemas (${dialect}): ${error}`);
|
|
1669
|
-
});
|
|
1670
|
-
metaschemaReady.set(dialect, readyPromise);
|
|
1671
|
-
await readyPromise;
|
|
1672
|
-
return ajv;
|
|
1673
|
-
}
|
|
1674
|
-
async function compileSchema(schema, options = {}) {
|
|
1675
|
-
const baseKey = typeof schema === "string" ? schema : JSON.stringify(schema);
|
|
1676
|
-
let parsedSchema;
|
|
1677
|
-
if (typeof schema === "string") {
|
|
1678
|
-
try {
|
|
1679
|
-
parsedSchema = JSON.parse(schema);
|
|
1680
|
-
} catch {
|
|
1681
|
-
parsedSchema = parse(schema);
|
|
1682
|
-
}
|
|
1683
|
-
} else if (Buffer.isBuffer(schema)) {
|
|
1684
|
-
const content = schema.toString("utf-8");
|
|
1685
|
-
try {
|
|
1686
|
-
parsedSchema = JSON.parse(content);
|
|
1687
|
-
} catch {
|
|
1688
|
-
parsedSchema = parse(content);
|
|
1689
|
-
}
|
|
1690
|
-
} else {
|
|
1691
|
-
parsedSchema = schema;
|
|
1692
|
-
}
|
|
1693
|
-
const dialect = detectDialect(parsedSchema);
|
|
1694
|
-
const ajv = await getAjv(dialect);
|
|
1695
|
-
const cacheKey = `${dialect}:${baseKey}`;
|
|
1696
|
-
const cached = schemaCache.get(cacheKey);
|
|
1697
|
-
if (cached !== void 0) {
|
|
1698
|
-
return cached;
|
|
1699
|
-
}
|
|
1700
|
-
try {
|
|
1701
|
-
if (options.aliases && options.aliases.length > 0) {
|
|
1702
|
-
for (const alias of options.aliases) {
|
|
1703
|
-
if (alias && ajv.getSchema(alias) === void 0) {
|
|
1704
|
-
try {
|
|
1705
|
-
if (typeof parsedSchema === "object" && parsedSchema !== null) {
|
|
1706
|
-
ajv.addSchema(parsedSchema, alias);
|
|
1707
|
-
}
|
|
1708
|
-
} catch {
|
|
1709
|
-
}
|
|
1710
|
-
}
|
|
1711
|
-
}
|
|
1712
|
-
}
|
|
1713
|
-
const validator = typeof parsedSchema === "boolean" ? ajv.compile(parsedSchema) : await ajv.compileAsync(parsedSchema);
|
|
1714
|
-
schemaCache.set(cacheKey, validator);
|
|
1715
|
-
return validator;
|
|
1716
|
-
} catch (error) {
|
|
1717
|
-
throw SchemaValidationError.parseFailed(
|
|
1718
|
-
{
|
|
1719
|
-
type: "string",
|
|
1720
|
-
content: typeof schema === "string" ? schema : JSON.stringify(schema)
|
|
1721
|
-
},
|
|
1722
|
-
error
|
|
1723
|
-
);
|
|
1724
|
-
}
|
|
1725
|
-
}
|
|
1726
|
-
function validateData(data, validator) {
|
|
1727
|
-
const valid = validator(data);
|
|
1728
|
-
const result = {
|
|
1729
|
-
valid,
|
|
1730
|
-
diagnostics: [],
|
|
1731
|
-
source: "ajv"
|
|
1732
|
-
};
|
|
1733
|
-
if (!valid && validator.errors) {
|
|
1734
|
-
const errors = validator.errors;
|
|
1735
|
-
if (Array.isArray(errors)) {
|
|
1736
|
-
result.diagnostics = errors.map(
|
|
1737
|
-
(error) => createDiagnostic(
|
|
1738
|
-
error.instancePath || "",
|
|
1739
|
-
error.message || "Validation failed",
|
|
1740
|
-
error.keyword || "unknown",
|
|
1741
|
-
"ERROR",
|
|
1742
|
-
"ajv"
|
|
1743
|
-
)
|
|
1744
|
-
);
|
|
1745
|
-
}
|
|
1746
|
-
metrics.counter("schema_validation_errors").inc();
|
|
1747
|
-
} else {
|
|
1748
|
-
metrics.counter("schema_validations").inc();
|
|
1749
|
-
}
|
|
1750
|
-
return result;
|
|
1751
|
-
}
|
|
1752
|
-
async function compileSchemaById(schemaId, registryOptions) {
|
|
1753
|
-
try {
|
|
1754
|
-
const registry = getSchemaRegistry(registryOptions);
|
|
1755
|
-
const metadata = await registry.getSchema(schemaId);
|
|
1756
|
-
const content = await readFile(metadata.path, "utf-8");
|
|
1757
|
-
const aliases = [];
|
|
1758
|
-
const normalizedRelativePath = metadata.relativePath.replace(/\\/g, "/");
|
|
1759
|
-
if (normalizedRelativePath) {
|
|
1760
|
-
aliases.push(
|
|
1761
|
-
new URL(`crucible/${normalizedRelativePath}`, "https://schemas.fulmenhq.dev/").toString()
|
|
1762
|
-
);
|
|
1763
|
-
}
|
|
1764
|
-
return compileSchema(content, { aliases });
|
|
1765
|
-
} catch (error) {
|
|
1766
|
-
metrics.counter("schema_validation_errors").inc();
|
|
1767
|
-
throw error;
|
|
1768
|
-
}
|
|
1769
|
-
}
|
|
1770
|
-
async function validateDataBySchemaId(data, schemaId, registryOptions) {
|
|
1771
|
-
try {
|
|
1772
|
-
const validator = await compileSchemaById(schemaId, registryOptions);
|
|
1773
|
-
return validateData(data, validator);
|
|
1774
|
-
} catch (error) {
|
|
1775
|
-
metrics.counter("schema_validation_errors").inc();
|
|
1776
|
-
throw error;
|
|
1777
|
-
}
|
|
1778
|
-
}
|
|
1779
|
-
var ajvInstances, metaschemaReady, schemaCache;
|
|
1780
|
-
var init_validator = __esm({
|
|
1781
|
-
"src/schema/validator.ts"() {
|
|
1782
|
-
init_telemetry();
|
|
1783
|
-
init_ajv_formats();
|
|
1784
|
-
init_errors2();
|
|
1785
|
-
init_registry();
|
|
1786
|
-
init_utils();
|
|
1787
|
-
ajvInstances = /* @__PURE__ */ new Map();
|
|
1788
|
-
metaschemaReady = /* @__PURE__ */ new Map();
|
|
1789
|
-
schemaCache = /* @__PURE__ */ new Map();
|
|
1790
|
-
}
|
|
1791
|
-
});
|
|
1792
|
-
var init_cli = __esm({
|
|
1793
|
-
"src/schema/cli.ts"() {
|
|
1794
|
-
init_goneat_bridge();
|
|
1795
|
-
init_normalizer();
|
|
1796
|
-
init_registry();
|
|
1797
|
-
init_utils();
|
|
1798
|
-
init_validator();
|
|
1799
|
-
}
|
|
1800
|
-
});
|
|
1801
|
-
var init_export = __esm({
|
|
1802
|
-
"src/schema/export.ts"() {
|
|
1803
|
-
init_errors2();
|
|
1804
|
-
init_registry();
|
|
1805
|
-
init_validator();
|
|
1806
|
-
}
|
|
1807
|
-
});
|
|
1808
|
-
|
|
1809
|
-
// src/schema/index.ts
|
|
1810
|
-
var init_schema = __esm({
|
|
1811
|
-
"src/schema/index.ts"() {
|
|
1812
|
-
init_ajv_formats();
|
|
1813
|
-
init_cli();
|
|
1814
|
-
init_errors2();
|
|
1815
|
-
init_export();
|
|
1816
|
-
init_goneat_bridge();
|
|
1817
|
-
init_normalizer();
|
|
1818
|
-
init_registry();
|
|
1819
|
-
init_utils();
|
|
1820
|
-
init_validator();
|
|
1821
|
-
}
|
|
1822
|
-
});
|
|
1823
|
-
|
|
1824
|
-
// src/errors/validators.ts
|
|
1825
|
-
async function validateErrorData(data) {
|
|
1826
|
-
return ErrorValidator.getInstance().validate(data);
|
|
1827
|
-
}
|
|
1828
|
-
var ErrorValidator;
|
|
1829
|
-
var init_validators2 = __esm({
|
|
1830
|
-
"src/errors/validators.ts"() {
|
|
1831
|
-
init_schema();
|
|
1832
|
-
ErrorValidator = class _ErrorValidator {
|
|
1833
|
-
static instance;
|
|
1834
|
-
validateFn = null;
|
|
1835
|
-
initPromise = null;
|
|
1836
|
-
initError = null;
|
|
1837
|
-
constructor() {
|
|
1838
|
-
}
|
|
1839
|
-
/**
|
|
1840
|
-
* Get singleton instance
|
|
1841
|
-
*/
|
|
1842
|
-
static getInstance() {
|
|
1843
|
-
if (!_ErrorValidator.instance) {
|
|
1844
|
-
_ErrorValidator.instance = new _ErrorValidator();
|
|
1845
|
-
}
|
|
1846
|
-
return _ErrorValidator.instance;
|
|
1847
|
-
}
|
|
1848
|
-
/**
|
|
1849
|
-
* Initialize validator (lazy load, async)
|
|
1850
|
-
*/
|
|
1851
|
-
async init() {
|
|
1852
|
-
if (this.validateFn !== null || this.initError !== null) {
|
|
1853
|
-
return;
|
|
1854
|
-
}
|
|
1855
|
-
if (this.initPromise) {
|
|
1856
|
-
return this.initPromise;
|
|
1857
|
-
}
|
|
1858
|
-
this.initPromise = (async () => {
|
|
1859
|
-
try {
|
|
1860
|
-
await compileSchemaById("pathfinder/v1.0.0/error-response");
|
|
1861
|
-
await compileSchemaById("assessment/v1.0.0/severity-definitions");
|
|
1862
|
-
this.validateFn = await compileSchemaById("error-handling/v1.0.0/error-response");
|
|
1863
|
-
} catch (err) {
|
|
1864
|
-
this.initError = err instanceof Error ? err : new Error(String(err));
|
|
1865
|
-
throw new Error(`Failed to initialize error validator: ${this.initError.message}`);
|
|
1866
|
-
}
|
|
1867
|
-
})();
|
|
1868
|
-
return this.initPromise;
|
|
1869
|
-
}
|
|
1870
|
-
/**
|
|
1871
|
-
* Validate error data against schema
|
|
1872
|
-
*
|
|
1873
|
-
* @param data - Data to validate
|
|
1874
|
-
* @returns Promise resolving to true if valid, false otherwise
|
|
1875
|
-
* @throws {Error} If validator failed to initialize
|
|
1876
|
-
*/
|
|
1877
|
-
async validate(data) {
|
|
1878
|
-
if (this.validateFn === null) {
|
|
1879
|
-
await this.init();
|
|
1880
|
-
}
|
|
1881
|
-
if (this.initError) {
|
|
1882
|
-
throw this.initError;
|
|
1883
|
-
}
|
|
1884
|
-
if (!this.validateFn) {
|
|
1885
|
-
throw new Error("Validator not initialized");
|
|
1886
|
-
}
|
|
1887
|
-
return this.validateFn(data);
|
|
1888
|
-
}
|
|
1889
|
-
/**
|
|
1890
|
-
* Get validation errors from last validation
|
|
1891
|
-
*
|
|
1892
|
-
* @returns Validation errors or null
|
|
1893
|
-
*/
|
|
1894
|
-
getErrors() {
|
|
1895
|
-
if (!this.validateFn) {
|
|
1896
|
-
return null;
|
|
1897
|
-
}
|
|
1898
|
-
return this.validateFn.errors;
|
|
1899
|
-
}
|
|
1900
|
-
/**
|
|
1901
|
-
* Reset validator state (for testing)
|
|
1902
|
-
* @internal
|
|
1903
|
-
*/
|
|
1904
|
-
static _reset() {
|
|
1905
|
-
_ErrorValidator.instance = new _ErrorValidator();
|
|
1906
|
-
}
|
|
1907
|
-
};
|
|
1908
|
-
}
|
|
1909
|
-
});
|
|
1910
|
-
|
|
1911
|
-
// src/errors/fulmen-error.ts
|
|
1912
|
-
function isFulmenErrorData(value) {
|
|
1913
|
-
return typeof value === "object" && value !== null && "code" in value && typeof value.code === "string" && "message" in value && typeof value.message === "string";
|
|
1914
|
-
}
|
|
1915
|
-
var FulmenError;
|
|
1916
|
-
var init_fulmen_error = __esm({
|
|
1917
|
-
"src/errors/fulmen-error.ts"() {
|
|
1918
|
-
init_serialization();
|
|
1919
|
-
init_severity();
|
|
1920
|
-
init_validators2();
|
|
1921
|
-
FulmenError = class _FulmenError extends Error {
|
|
1922
|
-
data;
|
|
1923
|
-
constructor(data) {
|
|
1924
|
-
super(data.message);
|
|
1925
|
-
this.name = "FulmenError";
|
|
1926
|
-
this.data = Object.freeze({ ...data });
|
|
1927
|
-
Error.captureStackTrace(this, _FulmenError);
|
|
1928
|
-
}
|
|
1929
|
-
/**
|
|
1930
|
-
* Serialize to JSON (schema-compliant)
|
|
1931
|
-
*/
|
|
1932
|
-
toJSON() {
|
|
1933
|
-
return this.data;
|
|
1934
|
-
}
|
|
1935
|
-
/**
|
|
1936
|
-
* Check equality with another FulmenError
|
|
1937
|
-
*/
|
|
1938
|
-
equals(other) {
|
|
1939
|
-
return JSON.stringify(this.data) === JSON.stringify(other.data);
|
|
1940
|
-
}
|
|
1941
|
-
/**
|
|
1942
|
-
* Get severity level for comparison
|
|
1943
|
-
*/
|
|
1944
|
-
getSeverityLevel() {
|
|
1945
|
-
return this.data.severity_level ?? SEVERITY_LEVELS[this.data.severity ?? "medium"];
|
|
1946
|
-
}
|
|
1947
|
-
/**
|
|
1948
|
-
* Wrap an existing error with FulmenError structure
|
|
1949
|
-
*
|
|
1950
|
-
* @param error - Error to wrap (Error instance or FulmenErrorData)
|
|
1951
|
-
* @param options - Additional error options
|
|
1952
|
-
* @returns New FulmenError instance
|
|
1953
|
-
*
|
|
1954
|
-
* @example
|
|
1955
|
-
* ```typescript
|
|
1956
|
-
* try {
|
|
1957
|
-
* throw new Error('Config invalid');
|
|
1958
|
-
* } catch (err) {
|
|
1959
|
-
* const fulmenErr = FulmenError.wrap(err, {
|
|
1960
|
-
* code: 'CONFIG_INVALID',
|
|
1961
|
-
* severity: 'high',
|
|
1962
|
-
* exit_code: 2
|
|
1963
|
-
* });
|
|
1964
|
-
* throw fulmenErr;
|
|
1965
|
-
* }
|
|
1966
|
-
* ```
|
|
1967
|
-
*/
|
|
1968
|
-
static wrap(error, options = {}) {
|
|
1969
|
-
if (error instanceof _FulmenError) {
|
|
1970
|
-
const effectiveSeverity = options.severity ?? error.data.severity ?? Severity.MEDIUM;
|
|
1971
|
-
const effectiveSeverityLevel = SEVERITY_LEVELS[effectiveSeverity];
|
|
1972
|
-
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
1973
|
-
return new _FulmenError({
|
|
1974
|
-
...error.data,
|
|
1975
|
-
...options,
|
|
1976
|
-
code: options.code ?? error.data.code,
|
|
1977
|
-
message: error.data.message,
|
|
1978
|
-
severity: effectiveSeverity,
|
|
1979
|
-
// Consistent severity
|
|
1980
|
-
severity_level: effectiveSeverityLevel,
|
|
1981
|
-
// Recomputed level
|
|
1982
|
-
timestamp
|
|
1983
|
-
// Updated timestamp
|
|
1984
|
-
});
|
|
1985
|
-
}
|
|
1986
|
-
if (isFulmenErrorData(error)) {
|
|
1987
|
-
const defaultSeverity = getDefaultSeverity();
|
|
1988
|
-
const effectiveSeverity = options.severity ?? error.severity ?? defaultSeverity.name;
|
|
1989
|
-
const effectiveSeverityLevel = SEVERITY_LEVELS[effectiveSeverity];
|
|
1990
|
-
return new _FulmenError({
|
|
1991
|
-
...error,
|
|
1992
|
-
...options,
|
|
1993
|
-
severity: effectiveSeverity,
|
|
1994
|
-
severity_level: effectiveSeverityLevel,
|
|
1995
|
-
// Recomputed, not from error.severity_level
|
|
1996
|
-
timestamp: error.timestamp ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
1997
|
-
});
|
|
1998
|
-
}
|
|
1999
|
-
return _FulmenError.fromError(error, options);
|
|
2000
|
-
}
|
|
2001
|
-
/**
|
|
2002
|
-
* Create FulmenError from native Error object
|
|
2003
|
-
*
|
|
2004
|
-
* @param err - Native Error instance
|
|
2005
|
-
* @param options - Error options
|
|
2006
|
-
* @returns New FulmenError instance
|
|
2007
|
-
*
|
|
2008
|
-
* @example
|
|
2009
|
-
* ```typescript
|
|
2010
|
-
* const err = new TypeError('Invalid type');
|
|
2011
|
-
* const fulmenErr = FulmenError.fromError(err, {
|
|
2012
|
-
* code: 'TYPE_ERROR',
|
|
2013
|
-
* severity: 'medium'
|
|
2014
|
-
* });
|
|
2015
|
-
* ```
|
|
2016
|
-
*/
|
|
2017
|
-
static fromError(err, options = {}) {
|
|
2018
|
-
const code = options.code ?? "UNKNOWN_ERROR";
|
|
2019
|
-
const severity = options.severity ?? Severity.MEDIUM;
|
|
2020
|
-
const severityLevel = SEVERITY_LEVELS[severity];
|
|
2021
|
-
const message = extractErrorMessage(err);
|
|
2022
|
-
const stack = extractStackTrace(err);
|
|
2023
|
-
const data = {
|
|
2024
|
-
code,
|
|
2025
|
-
message,
|
|
2026
|
-
severity,
|
|
2027
|
-
severity_level: severityLevel,
|
|
2028
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2029
|
-
...options,
|
|
2030
|
-
context: {
|
|
2031
|
-
...options.context,
|
|
2032
|
-
originalName: err instanceof Error ? err.name : typeof err,
|
|
2033
|
-
stack
|
|
2034
|
-
},
|
|
2035
|
-
original: stack || message
|
|
2036
|
-
};
|
|
2037
|
-
return new _FulmenError(data);
|
|
2038
|
-
}
|
|
2039
|
-
/**
|
|
2040
|
-
* Validate error data against schema
|
|
2041
|
-
*
|
|
2042
|
-
* @param data - Error data to validate
|
|
2043
|
-
* @returns Promise resolving to true if valid
|
|
2044
|
-
*
|
|
2045
|
-
* @example
|
|
2046
|
-
* ```typescript
|
|
2047
|
-
* const data = { code: 'TEST', message: 'Test error' };
|
|
2048
|
-
* if (await FulmenError.validate(data)) {
|
|
2049
|
-
* const err = new FulmenError(data);
|
|
2050
|
-
* }
|
|
2051
|
-
* ```
|
|
2052
|
-
*/
|
|
2053
|
-
static async validate(data) {
|
|
2054
|
-
return validateErrorData(data);
|
|
2055
|
-
}
|
|
2056
|
-
/**
|
|
2057
|
-
* Exit process with structured error
|
|
2058
|
-
*
|
|
2059
|
-
* Logs error as JSON and exits with specified exit code.
|
|
2060
|
-
* Mockable for testing (override process.exit).
|
|
2061
|
-
*
|
|
2062
|
-
* @param error - FulmenError instance
|
|
2063
|
-
* @param options - Exit options
|
|
2064
|
-
*
|
|
2065
|
-
* @example
|
|
2066
|
-
* ```typescript
|
|
2067
|
-
* const err = FulmenError.fromError(new Error('Fatal'), {
|
|
2068
|
-
* code: 'FATAL_ERROR',
|
|
2069
|
-
* exit_code: 1
|
|
2070
|
-
* });
|
|
2071
|
-
* FulmenError.exitWithError(err); // Exits with code 1
|
|
2072
|
-
* ```
|
|
2073
|
-
*/
|
|
2074
|
-
static exitWithError(error, options = {}) {
|
|
2075
|
-
const logger = options.logger ?? console.error;
|
|
2076
|
-
const exitCode = error.data.exit_code ?? 1;
|
|
2077
|
-
logger(JSON.stringify(error.toJSON(), null, 2));
|
|
2078
|
-
process.exit(exitCode);
|
|
2079
|
-
}
|
|
2080
|
-
};
|
|
2081
|
-
}
|
|
2082
|
-
});
|
|
2083
|
-
|
|
2084
|
-
// src/errors/index.ts
|
|
2085
|
-
var init_errors3 = __esm({
|
|
2086
|
-
"src/errors/index.ts"() {
|
|
2087
|
-
init_correlation();
|
|
2088
|
-
init_fulmen_error();
|
|
2089
|
-
init_serialization();
|
|
2090
|
-
init_severity();
|
|
2091
|
-
init_validators2();
|
|
2092
|
-
}
|
|
2093
|
-
});
|
|
2094
|
-
|
|
2095
|
-
// src/fulhash/index.ts
|
|
2096
|
-
init_types();
|
|
2097
|
-
|
|
2098
|
-
// src/fulhash/convenience.ts
|
|
2099
|
-
init_digest();
|
|
2100
|
-
|
|
2101
|
-
// src/fulhash/stream.ts
|
|
2102
|
-
init_types();
|
|
2103
|
-
init_crc32();
|
|
2104
|
-
init_crc32c();
|
|
2105
|
-
init_digest();
|
|
2106
|
-
init_errors();
|
|
2107
|
-
|
|
2108
|
-
// src/fulhash/wasm-loader.ts
|
|
2109
|
-
init_errors();
|
|
2110
|
-
var isWasmReady = false;
|
|
2111
|
-
var initPromise = null;
|
|
2112
|
-
async function initializeWasm() {
|
|
2113
|
-
if (isWasmReady) {
|
|
2114
|
-
return;
|
|
2115
|
-
}
|
|
2116
|
-
if (initPromise) {
|
|
2117
|
-
return initPromise;
|
|
2118
|
-
}
|
|
2119
|
-
initPromise = createXXHash128().then(() => {
|
|
2120
|
-
isWasmReady = true;
|
|
2121
|
-
}).catch((error) => {
|
|
2122
|
-
initPromise = null;
|
|
2123
|
-
throw new FulHashError(`Failed to initialize hash-wasm XXH3-128 module: ${error.message}`);
|
|
2124
|
-
});
|
|
2125
|
-
return initPromise;
|
|
2126
|
-
}
|
|
2127
|
-
async function createHasher3() {
|
|
2128
|
-
if (!isWasmReady) {
|
|
2129
|
-
throw new FulHashError("WASM not initialized. Call initializeWasm() first.");
|
|
2130
|
-
}
|
|
2131
|
-
return createXXHash128();
|
|
2132
|
-
}
|
|
2133
|
-
|
|
2134
|
-
// src/fulhash/stream.ts
|
|
2135
|
-
function intToBytes(crc) {
|
|
2136
|
-
const bytes = new Uint8Array(4);
|
|
2137
|
-
const unsigned = crc >>> 0;
|
|
2138
|
-
bytes[0] = unsigned >>> 24 & 255;
|
|
2139
|
-
bytes[1] = unsigned >>> 16 & 255;
|
|
2140
|
-
bytes[2] = unsigned >>> 8 & 255;
|
|
2141
|
-
bytes[3] = unsigned & 255;
|
|
2142
|
-
return bytes;
|
|
2143
|
-
}
|
|
2144
|
-
var BaseStreamHasher = class {
|
|
2145
|
-
state = "initial" /* INITIAL */;
|
|
2146
|
-
algorithm;
|
|
2147
|
-
constructor(algorithm) {
|
|
2148
|
-
this.algorithm = algorithm;
|
|
2149
|
-
}
|
|
2150
|
-
ensureNotFinalized() {
|
|
2151
|
-
if (this.state === "finalized" /* FINALIZED */) {
|
|
2152
|
-
throw new DigestStateError("Cannot update after digest(). Call reset() to reuse hasher.");
|
|
2153
|
-
}
|
|
2154
|
-
}
|
|
2155
|
-
ensureUpdating() {
|
|
2156
|
-
if (this.state !== "updating" /* UPDATING */ && this.state !== "initial" /* INITIAL */) {
|
|
2157
|
-
throw new DigestStateError("Invalid state for digest(). Hasher may have been finalized.");
|
|
2158
|
-
}
|
|
2159
|
-
}
|
|
2160
|
-
markUpdating() {
|
|
2161
|
-
this.state = "updating" /* UPDATING */;
|
|
2162
|
-
}
|
|
2163
|
-
markFinalized() {
|
|
2164
|
-
this.state = "finalized" /* FINALIZED */;
|
|
2165
|
-
}
|
|
2166
|
-
markInitial() {
|
|
2167
|
-
this.state = "initial" /* INITIAL */;
|
|
2168
|
-
}
|
|
2169
|
-
};
|
|
2170
|
-
var SHA256StreamHasher = class extends BaseStreamHasher {
|
|
2171
|
-
hasher;
|
|
2172
|
-
constructor() {
|
|
2173
|
-
super("sha256" /* SHA256 */);
|
|
2174
|
-
this.hasher = createHash("sha256");
|
|
2175
|
-
}
|
|
2176
|
-
update(data) {
|
|
2177
|
-
this.ensureNotFinalized();
|
|
2178
|
-
this.markUpdating();
|
|
2179
|
-
if (typeof data === "string") {
|
|
2180
|
-
this.hasher.update(data, "utf8");
|
|
2181
|
-
} else {
|
|
2182
|
-
this.hasher.update(data);
|
|
2183
|
-
}
|
|
2184
|
-
return this;
|
|
2185
|
-
}
|
|
2186
|
-
digest() {
|
|
2187
|
-
this.ensureUpdating();
|
|
2188
|
-
this.markFinalized();
|
|
2189
|
-
const bytes = new Uint8Array(this.hasher.digest());
|
|
2190
|
-
return new Digest(this.algorithm, bytes);
|
|
2191
|
-
}
|
|
2192
|
-
reset() {
|
|
2193
|
-
this.hasher = createHash("sha256");
|
|
2194
|
-
this.markInitial();
|
|
2195
|
-
return this;
|
|
2196
|
-
}
|
|
2197
|
-
};
|
|
2198
|
-
var XXH3StreamHasher = class extends BaseStreamHasher {
|
|
2199
|
-
hasher;
|
|
2200
|
-
constructor(hasher) {
|
|
2201
|
-
super("xxh3-128" /* XXH3_128 */);
|
|
2202
|
-
this.hasher = hasher;
|
|
2203
|
-
this.hasher.init();
|
|
2204
|
-
}
|
|
2205
|
-
update(data) {
|
|
2206
|
-
this.ensureNotFinalized();
|
|
2207
|
-
this.markUpdating();
|
|
2208
|
-
if (typeof data === "string") {
|
|
2209
|
-
const encoder = new TextEncoder();
|
|
2210
|
-
this.hasher.update(encoder.encode(data));
|
|
2211
|
-
} else {
|
|
2212
|
-
this.hasher.update(data);
|
|
2213
|
-
}
|
|
2214
|
-
return this;
|
|
2215
|
-
}
|
|
2216
|
-
digest() {
|
|
2217
|
-
this.ensureUpdating();
|
|
2218
|
-
this.markFinalized();
|
|
2219
|
-
const bytes = this.hasher.digest("binary");
|
|
2220
|
-
return new Digest(this.algorithm, bytes);
|
|
2221
|
-
}
|
|
2222
|
-
reset() {
|
|
2223
|
-
this.hasher.init();
|
|
2224
|
-
this.markInitial();
|
|
2225
|
-
return this;
|
|
2226
|
-
}
|
|
2227
|
-
};
|
|
2228
|
-
var CRC32StreamHasher = class extends BaseStreamHasher {
|
|
2229
|
-
hasher = null;
|
|
2230
|
-
constructor() {
|
|
2231
|
-
super("crc32" /* CRC32 */);
|
|
2232
|
-
}
|
|
2233
|
-
async init() {
|
|
2234
|
-
this.hasher = await createHasher();
|
|
2235
|
-
this.hasher.init();
|
|
2236
|
-
}
|
|
2237
|
-
update(data) {
|
|
2238
|
-
this.ensureNotFinalized();
|
|
2239
|
-
this.markUpdating();
|
|
2240
|
-
if (!this.hasher) {
|
|
2241
|
-
throw new Error("Hasher not initialized");
|
|
2242
|
-
}
|
|
2243
|
-
if (typeof data === "string") {
|
|
2244
|
-
const encoder = new TextEncoder();
|
|
2245
|
-
this.hasher.update(encoder.encode(data));
|
|
2246
|
-
} else {
|
|
2247
|
-
this.hasher.update(data);
|
|
2248
|
-
}
|
|
2249
|
-
return this;
|
|
2250
|
-
}
|
|
2251
|
-
digest() {
|
|
2252
|
-
this.ensureUpdating();
|
|
2253
|
-
this.markFinalized();
|
|
2254
|
-
if (!this.hasher) throw new Error("Hasher not initialized");
|
|
2255
|
-
const hex = this.hasher.digest();
|
|
2256
|
-
const bytes = intToBytes(parseInt(hex, 16));
|
|
2257
|
-
return new Digest(this.algorithm, bytes);
|
|
2258
|
-
}
|
|
2259
|
-
reset() {
|
|
2260
|
-
if (!this.hasher) throw new Error("Hasher not initialized");
|
|
2261
|
-
this.hasher.init();
|
|
2262
|
-
this.markInitial();
|
|
2263
|
-
return this;
|
|
2264
|
-
}
|
|
2265
|
-
};
|
|
2266
|
-
var CRC32CStreamHasher = class extends BaseStreamHasher {
|
|
2267
|
-
hasher = null;
|
|
2268
|
-
constructor() {
|
|
2269
|
-
super("crc32c" /* CRC32C */);
|
|
2270
|
-
}
|
|
2271
|
-
async init() {
|
|
2272
|
-
this.hasher = await createHasher2();
|
|
2273
|
-
this.hasher.init();
|
|
2274
|
-
}
|
|
2275
|
-
update(data) {
|
|
2276
|
-
this.ensureNotFinalized();
|
|
2277
|
-
this.markUpdating();
|
|
2278
|
-
if (!this.hasher) throw new Error("Hasher not initialized");
|
|
2279
|
-
if (typeof data === "string") {
|
|
2280
|
-
const encoder = new TextEncoder();
|
|
2281
|
-
this.hasher.update(encoder.encode(data));
|
|
2282
|
-
} else {
|
|
2283
|
-
this.hasher.update(data);
|
|
2284
|
-
}
|
|
2285
|
-
return this;
|
|
2286
|
-
}
|
|
2287
|
-
digest() {
|
|
2288
|
-
this.ensureUpdating();
|
|
2289
|
-
this.markFinalized();
|
|
2290
|
-
if (!this.hasher) throw new Error("Hasher not initialized");
|
|
2291
|
-
const hex = this.hasher.digest();
|
|
2292
|
-
const bytes = intToBytes(parseInt(hex, 16));
|
|
2293
|
-
return new Digest(this.algorithm, bytes);
|
|
2294
|
-
}
|
|
2295
|
-
reset() {
|
|
2296
|
-
if (!this.hasher) throw new Error("Hasher not initialized");
|
|
2297
|
-
this.hasher.init();
|
|
2298
|
-
this.markInitial();
|
|
2299
|
-
return this;
|
|
2300
|
-
}
|
|
2301
|
-
};
|
|
2302
|
-
async function createStreamHasher(options = {}) {
|
|
2303
|
-
const algorithm = options.algorithm ?? "xxh3-128" /* XXH3_128 */;
|
|
2304
|
-
switch (algorithm) {
|
|
2305
|
-
case "sha256" /* SHA256 */:
|
|
2306
|
-
return new SHA256StreamHasher();
|
|
2307
|
-
case "xxh3-128" /* XXH3_128 */: {
|
|
2308
|
-
await initializeWasm();
|
|
2309
|
-
const wasmHasher = await createHasher3();
|
|
2310
|
-
return new XXH3StreamHasher(wasmHasher);
|
|
2311
|
-
}
|
|
2312
|
-
case "crc32" /* CRC32 */: {
|
|
2313
|
-
const hasher = new CRC32StreamHasher();
|
|
2314
|
-
await hasher.init();
|
|
2315
|
-
return hasher;
|
|
2316
|
-
}
|
|
2317
|
-
case "crc32c" /* CRC32C */: {
|
|
2318
|
-
const hasher = new CRC32CStreamHasher();
|
|
2319
|
-
await hasher.init();
|
|
2320
|
-
return hasher;
|
|
2321
|
-
}
|
|
2322
|
-
default:
|
|
2323
|
-
throw new UnsupportedAlgorithmError(algorithm, Object.values(Algorithm));
|
|
2324
|
-
}
|
|
2325
|
-
}
|
|
2326
|
-
|
|
2327
|
-
// src/fulhash/index.ts
|
|
2328
|
-
init_digest();
|
|
2329
|
-
init_errors();
|
|
2330
|
-
init_hash();
|
|
2331
|
-
|
|
2332
15
|
// src/pathfinder/types.ts
|
|
2333
16
|
var EnforcementLevel = /* @__PURE__ */ ((EnforcementLevel2) => {
|
|
2334
17
|
EnforcementLevel2["STRICT"] = "strict";
|
|
@@ -2458,12 +141,7 @@ var MonorepoMarkers = [
|
|
|
2458
141
|
"rush.json"
|
|
2459
142
|
];
|
|
2460
143
|
|
|
2461
|
-
// src/pathfinder/finder.ts
|
|
2462
|
-
init_errors3();
|
|
2463
|
-
init_telemetry();
|
|
2464
|
-
|
|
2465
144
|
// src/pathfinder/errors.ts
|
|
2466
|
-
init_errors3();
|
|
2467
145
|
var PathfinderErrorCode = /* @__PURE__ */ ((PathfinderErrorCode2) => {
|
|
2468
146
|
PathfinderErrorCode2["INVALID_CONFIG"] = "pathfinder.invalid_config";
|
|
2469
147
|
PathfinderErrorCode2["INVALID_ROOT"] = "pathfinder.invalid_root";
|
|
@@ -2512,8 +190,8 @@ function toPosixPath(p) {
|
|
|
2512
190
|
function isPathWithinRoot(candidate, root) {
|
|
2513
191
|
const normalizedCandidate = normalizeAbsolute(candidate);
|
|
2514
192
|
const normalizedRoot = normalizeAbsolute(root);
|
|
2515
|
-
const
|
|
2516
|
-
return
|
|
193
|
+
const relative = path3.relative(normalizedRoot, normalizedCandidate);
|
|
194
|
+
return relative === "" || !relative.startsWith("..") && !path3.isAbsolute(relative);
|
|
2517
195
|
}
|
|
2518
196
|
function enforcePathConstraints(absolutePath, _relativePath, constraint) {
|
|
2519
197
|
if (!constraint) {
|
|
@@ -2665,15 +343,15 @@ var IgnoreMatcher = class {
|
|
|
2665
343
|
}
|
|
2666
344
|
};
|
|
2667
345
|
function isSubPath(candidate, root) {
|
|
2668
|
-
const
|
|
2669
|
-
return
|
|
346
|
+
const relative = path3.relative(root, candidate);
|
|
347
|
+
return relative === "" || !relative.startsWith("..") && !path3.isAbsolute(relative);
|
|
2670
348
|
}
|
|
2671
349
|
function toRelativePrefix(directory, root) {
|
|
2672
|
-
const
|
|
2673
|
-
if (!
|
|
350
|
+
const relative = path3.relative(root, directory);
|
|
351
|
+
if (!relative || relative === ".") {
|
|
2674
352
|
return "";
|
|
2675
353
|
}
|
|
2676
|
-
return toPosixPath(
|
|
354
|
+
return toPosixPath(relative);
|
|
2677
355
|
}
|
|
2678
356
|
function resolvePattern(pattern, relativePrefix) {
|
|
2679
357
|
let directory = false;
|
|
@@ -2833,7 +511,7 @@ var Pathfinder = class {
|
|
|
2833
511
|
}
|
|
2834
512
|
let matches;
|
|
2835
513
|
try {
|
|
2836
|
-
matches = await
|
|
514
|
+
matches = await fg(normalizedQuery.include, globOptions);
|
|
2837
515
|
} catch (error) {
|
|
2838
516
|
throw this.wrapAndLogError(error, "pathfinder.traversal_failed" /* TRAVERSAL_FAILED */, "medium", {
|
|
2839
517
|
root: normalizedQuery.root,
|
|
@@ -3368,7 +1046,6 @@ async function getRealPath(path5) {
|
|
|
3368
1046
|
}
|
|
3369
1047
|
|
|
3370
1048
|
// src/pathfinder/validators.ts
|
|
3371
|
-
init_schema();
|
|
3372
1049
|
async function compileConfigSchema() {
|
|
3373
1050
|
return compileSchemaById("pathfinder/v1.0.0/finder-config");
|
|
3374
1051
|
}
|