@codometer/measurement 0.0.0-stage → 0.0.4

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.
@@ -0,0 +1,1150 @@
1
+ import { ConsoleLogger as e, Global as t, Injectable as n, Module as r, Scope as i } from "@nestjs/common";
2
+ import a from "node:path";
3
+ import { existsSync as o, mkdirSync as s, readFileSync as c, readdirSync as l, statSync as u } from "node:fs";
4
+ import d from "pino";
5
+ import f from "ignore";
6
+ import { ConfigurationModule as p, DEFAULT_INPUT_NAME as m, REPOSITORY_ROOT_MARKERS as ee } from "@codometer/configuration";
7
+ import { LanguagesModule as te, LanguagesService as h } from "@codometer/languages";
8
+ import { brotliCompressSync as g, constants as _, gzipSync as v } from "node:zlib";
9
+ //#region \0@oxc-project+runtime@0.151.0/helpers/esm/decorateMetadata.js
10
+ function y(e, t) {
11
+ if (typeof Reflect == "object" && typeof Reflect.metadata == "function") return Reflect.metadata(e, t);
12
+ }
13
+ //#endregion
14
+ //#region \0@oxc-project+runtime@0.151.0/helpers/esm/decorate.js
15
+ function b(e, t, n, r) {
16
+ var i = arguments.length, a = i < 3 ? t : r === null ? r = Object.getOwnPropertyDescriptor(t, n) : r, o;
17
+ if (typeof Reflect == "object" && typeof Reflect.decorate == "function") a = Reflect.decorate(e, t, n, r);
18
+ else for (var s = e.length - 1; s >= 0; s--) (o = e[s]) && (a = (i < 3 ? o(a) : i > 3 ? o(t, n, a) : o(t, n)) || a);
19
+ return i > 3 && a && Object.defineProperty(t, n, a), a;
20
+ }
21
+ //#endregion
22
+ //#region packages/ic-suite/codometer/codometer-measurement/src/modules/customization/customization.service.ts
23
+ var x = class {
24
+ constructor() {}
25
+ buildCommentResult(e, t) {
26
+ let n = (t[e.label] ?? []).filter((e) => e.breached);
27
+ return {
28
+ color: e.color,
29
+ count: n.length,
30
+ group: e.group,
31
+ instances: n.map((e) => ({
32
+ file: e.file,
33
+ line: e.line,
34
+ measured: e.measured
35
+ })),
36
+ label: e.label
37
+ };
38
+ }
39
+ countMatches(e, t) {
40
+ return e.filter((e) => t.some((t) => a.matchesGlob(e, t))).length;
41
+ }
42
+ analyze({ commentCounts: e, files: t, statistics: n, symbolCounts: r }) {
43
+ return n.map((n) => n.comment === void 0 ? {
44
+ color: n.color,
45
+ count: n.symbols === void 0 ? this.countMatches(t, n.patterns) : r[n.label] ?? 0,
46
+ group: n.group,
47
+ label: n.label
48
+ } : this.buildCommentResult(n, e));
49
+ }
50
+ buildCommentCounters(e) {
51
+ let t = [];
52
+ for (let n of e) {
53
+ let { comment: e, label: r } = n;
54
+ e !== void 0 && t.push({
55
+ budget: {
56
+ maximumCharacters: e.maximumCharacters,
57
+ maximumLines: e.maximumLines,
58
+ maximumWords: e.maximumWords,
59
+ severity: e.severity
60
+ },
61
+ kind: e.kind,
62
+ label: r,
63
+ language: e.language
64
+ });
65
+ }
66
+ return t;
67
+ }
68
+ buildSymbolCounters(e) {
69
+ return e.flatMap((e) => e.symbols === void 0 ? [] : [{
70
+ kinds: e.symbols.kinds,
71
+ label: e.label,
72
+ modifiers: e.symbols.modifiers ?? [],
73
+ patterns: e.patterns
74
+ }]);
75
+ }
76
+ };
77
+ x = b([n(), y("design:paramtypes", [])], x);
78
+ //#endregion
79
+ //#region packages/ic-suite/codometer/codometer-measurement/src/modules/customization/customization.module.ts
80
+ var S = class {};
81
+ S = b([r({
82
+ controllers: [],
83
+ exports: [x],
84
+ imports: [],
85
+ providers: [x]
86
+ })], S);
87
+ //#endregion
88
+ //#region packages/logger/src/modules/logger/logger.constants.ts
89
+ var ne = /^(\p{Extended_Pictographic}️?(?:‍\p{Extended_Pictographic}️?)*)\s+/u, re = /^([A-Za-z]+)/, ie = /* @__PURE__ */ new Set([
90
+ "built",
91
+ "cut",
92
+ "found",
93
+ "got",
94
+ "kept",
95
+ "left",
96
+ "lost",
97
+ "made",
98
+ "put",
99
+ "ran",
100
+ "read",
101
+ "rebuilt",
102
+ "sent",
103
+ "set",
104
+ "split",
105
+ "took",
106
+ "wrote"
107
+ ]), ae = /* @__PURE__ */ new Set([
108
+ "CommandFactory",
109
+ "ExceptionHandler",
110
+ "GraphQLModule",
111
+ "InstanceLoader",
112
+ "NestApplication",
113
+ "NestFactory",
114
+ "RouterExplorer",
115
+ "RoutesResolver",
116
+ "TypeOrmModule"
117
+ ]), C, w = class extends e {
118
+ static {
119
+ C = this;
120
+ }
121
+ constructor() {
122
+ super();
123
+ }
124
+ static isProduction = process.env.NODE_ENV === "production";
125
+ static rootLogger;
126
+ static writesToStandardError = !1;
127
+ child = C.root;
128
+ static createRootLogger() {
129
+ let e = process.env.LOG_LEVEL ?? "info";
130
+ return C.isProduction ? C.writesToStandardError ? d({ level: e }, d.destination(2)) : d({ level: e }) : d({
131
+ level: e,
132
+ transport: {
133
+ options: {
134
+ colorize: !0,
135
+ destination: C.writesToStandardError ? 2 : 1,
136
+ ignore: "pid,hostname,emoji",
137
+ messageFormat: "{emoji} {msg}",
138
+ singleLine: !0
139
+ },
140
+ target: "pino-pretty"
141
+ }
142
+ });
143
+ }
144
+ static logToStandardError() {
145
+ if (C.rootLogger !== void 0) {
146
+ process.emitWarning("LoggerService.logToStandardError() was called after the first log line, so log lines still go to standard output and anything piping that stream will read them as data. Call it as the first statement of the application's bootstrap.");
147
+ return;
148
+ }
149
+ C.writesToStandardError = !0;
150
+ }
151
+ assertConventionalMessage(e) {
152
+ if (C.isProduction || this.shouldSkipConventionalMessageValidation(e.context)) return;
153
+ let t = this.getConventionalMessageViolation(e.parsed);
154
+ if (t !== void 0) throw Error(t);
155
+ }
156
+ buildBindings(e) {
157
+ return this.assertConventionalMessage({
158
+ context: e.context,
159
+ parsed: e.parsed
160
+ }), {
161
+ ...e.data,
162
+ context: e.context,
163
+ ...C.isProduction ? {} : { emoji: e.parsed.emoji }
164
+ };
165
+ }
166
+ getConventionalMessageViolation(e) {
167
+ let t = e.emoji, n = e.text;
168
+ if (t === void 0) return `Log message must start with an emoji naming its subject, then a verb: "${n}"`;
169
+ let r = re.exec(n)?.[1];
170
+ if (r === void 0 || !this.isConventionalVerb(r)) return `Log message must begin with a verb in present progressive or past tense, got "${r ?? ""}": "${t} ${n}"`;
171
+ }
172
+ isConventionalVerb(e) {
173
+ let t = e.toLowerCase();
174
+ return t.endsWith("ing") || t.endsWith("ed") || ie.has(t);
175
+ }
176
+ parseMessage(e) {
177
+ let t = String(e), n = ne.exec(t), r = n?.[1];
178
+ return r === void 0 ? {
179
+ emoji: void 0,
180
+ text: t
181
+ } : {
182
+ emoji: r,
183
+ text: t.slice(n?.[0].length)
184
+ };
185
+ }
186
+ shouldSkipConventionalMessageValidation(e) {
187
+ return e !== void 0 && ae.has(e);
188
+ }
189
+ static get root() {
190
+ return C.rootLogger ??= C.createRootLogger(), C.rootLogger;
191
+ }
192
+ buildErrorLogEntry(e, t) {
193
+ let n = t instanceof Error ? t.stack || t.message : String(t);
194
+ return {
195
+ errorMessage: n,
196
+ logLine: `[${(/* @__PURE__ */ new Date()).toISOString()}] ${e}: ${n}\n`
197
+ };
198
+ }
199
+ createTimestampedOutputLogFilePath(e) {
200
+ let t = a.join(process.cwd(), "output");
201
+ return o(t) || s(t, { recursive: !0 }), a.join(t, `${e}-${(/* @__PURE__ */ new Date()).toISOString().replaceAll(/[:.]/g, "-")}.log`);
202
+ }
203
+ debug(e, t, n) {
204
+ let r = this.parseMessage(e);
205
+ this.child.debug(this.buildBindings({
206
+ context: t ?? this.context,
207
+ data: n,
208
+ parsed: r
209
+ }), r.text);
210
+ }
211
+ error(e, t, n) {
212
+ let r = this.parseMessage(e), i = typeof n == "object" ? n : void 0, a = typeof n == "string" ? n : this.context;
213
+ this.child.error({
214
+ ...this.buildBindings({
215
+ context: a,
216
+ data: i,
217
+ parsed: r
218
+ }),
219
+ stack: t
220
+ }, r.text);
221
+ }
222
+ info(e, t, n) {
223
+ let r = this.parseMessage(e);
224
+ this.child.info(this.buildBindings({
225
+ context: t ?? this.context,
226
+ data: n,
227
+ parsed: r
228
+ }), r.text);
229
+ }
230
+ log(e, t, n) {
231
+ this.info(e, t, n);
232
+ }
233
+ setContext(e) {
234
+ super.setContext(e), this.child = C.root.child({ context: e });
235
+ }
236
+ verbose(e, t, n) {
237
+ let r = this.parseMessage(e);
238
+ this.child.trace(this.buildBindings({
239
+ context: t ?? this.context,
240
+ data: n,
241
+ parsed: r
242
+ }), r.text);
243
+ }
244
+ warn(e, t, n) {
245
+ let r = this.parseMessage(e);
246
+ this.child.warn(this.buildBindings({
247
+ context: t ?? this.context,
248
+ data: n,
249
+ parsed: r
250
+ }), r.text);
251
+ }
252
+ };
253
+ w = C = b([n({ scope: i.TRANSIENT }), y("design:paramtypes", [])], w);
254
+ //#endregion
255
+ //#region packages/logger/src/modules/logger/logger.module.ts
256
+ var T = class {};
257
+ T = b([t(), r({
258
+ controllers: [],
259
+ exports: [w],
260
+ imports: [],
261
+ providers: [w]
262
+ })], T);
263
+ var oe = ".gitignore", E = /* @__PURE__ */ new Set([
264
+ ".cts",
265
+ ".mts",
266
+ ".ts",
267
+ ".tsx"
268
+ ]), D = /* @__PURE__ */ new Set([
269
+ ".cjs",
270
+ ".js",
271
+ ".jsx",
272
+ ".mjs"
273
+ ]), O = /* @__PURE__ */ new Set([
274
+ ".markdown",
275
+ ".md",
276
+ ".mdx"
277
+ ]), k = /* @__PURE__ */ new Set([
278
+ ".json",
279
+ ".jsonc",
280
+ ".jsonl"
281
+ ]), A = /* @__PURE__ */ new Set([".css"]), se = /* @__PURE__ */ new Set([
282
+ ".hcl",
283
+ ".tf",
284
+ ".tfvars"
285
+ ]), ce = /* @__PURE__ */ new Set([
286
+ ".bash",
287
+ ".sh",
288
+ ".zsh"
289
+ ]), le = /* @__PURE__ */ new Set([".sql"]), ue = /* @__PURE__ */ new Set([".toml"]), j = /* @__PURE__ */ new Set([".yaml", ".yml"]), M = /* @__PURE__ */ new Set([".ipynb"]), N = /\.(test|spec|unit\.test|integration\.test|end-to-end\.test)\.[cm]?[jt]sx?$/, P = class {
290
+ constructor() {}
291
+ toScopedPath(e, t) {
292
+ if (e.directory === "") return t;
293
+ let n = `${e.directory}/`;
294
+ if (t.startsWith(n)) return t.slice(n.length);
295
+ }
296
+ createScope(e) {
297
+ return {
298
+ directory: e.directory,
299
+ matcher: f({ ignorecase: !1 }).add(e.patterns)
300
+ };
301
+ }
302
+ isIgnored(e, t) {
303
+ let n = !1;
304
+ for (let r of e) {
305
+ let e = this.toScopedPath(r, t);
306
+ if (e === void 0 || e === "") continue;
307
+ let i = r.matcher.test(e);
308
+ i.ignored ? n = !0 : i.unignored && (n = !1);
309
+ }
310
+ return n;
311
+ }
312
+ readScope(e) {
313
+ if (o(e.filePath)) return this.createScope({
314
+ directory: e.directory,
315
+ patterns: c(e.filePath, "utf8").split("\n")
316
+ });
317
+ }
318
+ };
319
+ P = b([n(), y("design:paramtypes", [])], P);
320
+ //#endregion
321
+ //#region packages/ic-suite/codometer/codometer-measurement/src/modules/discovery/discovery.service.ts
322
+ var F, I = F = class {
323
+ ignoreRulesService;
324
+ logger;
325
+ constructor(e, t) {
326
+ this.ignoreRulesService = e, this.logger = t, this.logger.setContext(F.name);
327
+ }
328
+ applyDirectoryIgnoreFile(e) {
329
+ let t = this.ignoreRulesService.readScope({
330
+ directory: e.relativeDirectory,
331
+ filePath: a.join(e.absoluteDirectory, oe)
332
+ });
333
+ return t === void 0 ? e : {
334
+ ...e,
335
+ ignoreScopes: [...e.ignoreScopes, t]
336
+ };
337
+ }
338
+ filterByExtension(e, t) {
339
+ return e.filter((e) => t.has(a.extname(e).toLowerCase()));
340
+ }
341
+ isExcluded(e, t) {
342
+ return t.some((t) => a.matchesGlob(e, t));
343
+ }
344
+ isExhaustivelyExcluded(e, t) {
345
+ return t.some((t) => t.endsWith("/**") && a.matchesGlob(e, t.slice(0, -3)));
346
+ }
347
+ isIgnoredPath(e, t) {
348
+ return this.ignoreRulesService.isIgnored(e.ignoreScopes, t) || this.ignoreRulesService.isIgnored(e.excludeFromScopes, t);
349
+ }
350
+ listDiscoveredFiles(e) {
351
+ return this.walkDirectory({
352
+ absoluteDirectory: e.workingDirectory,
353
+ exclude: e.exclude,
354
+ excludeFromScopes: this.readExcludeFromScopes(e),
355
+ ignoreScopes: [],
356
+ relativeDirectory: ""
357
+ }).filter((t) => !this.isExcluded(t, e.exclude)).toSorted();
358
+ }
359
+ readDirectoryEntries(e) {
360
+ try {
361
+ return l(e.absoluteDirectory, { withFileTypes: !0 });
362
+ } catch (t) {
363
+ return this.logger.warn("📂 Skipped unreadable directory", void 0, {
364
+ path: e.absoluteDirectory,
365
+ reason: String(t)
366
+ }), [];
367
+ }
368
+ }
369
+ readExcludeFromScopes(e) {
370
+ let t = [];
371
+ for (let n of e.excludeFrom) {
372
+ let r = this.ignoreRulesService.readScope({
373
+ directory: "",
374
+ filePath: a.resolve(e.workingDirectory, n)
375
+ });
376
+ if (r === void 0) {
377
+ this.logger.warn("🙈 Skipped missing ignore file", void 0, { path: n });
378
+ continue;
379
+ }
380
+ t.push(r);
381
+ }
382
+ return t;
383
+ }
384
+ walkDirectory(e) {
385
+ let t = this.readDirectoryEntries(e), n = this.applyDirectoryIgnoreFile(e), r = [];
386
+ for (let i of t) {
387
+ if (i.isSymbolicLink() || i.name === ".git") continue;
388
+ let t = a.join(e.absoluteDirectory, i.name), o = e.relativeDirectory === "" ? i.name : `${e.relativeDirectory}/${i.name}`;
389
+ i.isDirectory() ? r.push(...this.walkSubdirectory({
390
+ ...n,
391
+ absolutePath: t,
392
+ relativePath: o
393
+ })) : i.isFile() && !this.isIgnoredPath(n, o) && r.push(o);
394
+ }
395
+ return r;
396
+ }
397
+ walkSubdirectory(e) {
398
+ return this.isExhaustivelyExcluded(e.relativePath, e.exclude) || this.isIgnoredPath(e, `${e.relativePath}/`) ? [] : this.walkDirectory({
399
+ ...e,
400
+ absoluteDirectory: e.absolutePath,
401
+ relativeDirectory: e.relativePath
402
+ });
403
+ }
404
+ categorize(e) {
405
+ let t = /* @__PURE__ */ new Set([...E, ...D]), n = e.filter((e) => t.has(a.extname(e)));
406
+ return {
407
+ cssFiles: this.filterByExtension(e, A),
408
+ files: e,
409
+ hclFiles: this.filterByExtension(e, se),
410
+ jsFiles: n.filter((e) => D.has(a.extname(e))),
411
+ jsonFiles: this.filterByExtension(e, k),
412
+ markdownFiles: this.filterByExtension(e, O),
413
+ notebookFiles: this.filterByExtension(e, M),
414
+ pyFiles: e.filter((e) => a.extname(e) === ".py"),
415
+ shellFiles: this.filterByExtension(e, ce),
416
+ sourceFiles: n,
417
+ sqlFiles: this.filterByExtension(e, le),
418
+ testFiles: n.filter((e) => N.test(e)),
419
+ tomlFiles: this.filterByExtension(e, ue),
420
+ tsFiles: n.filter((e) => E.has(a.extname(e))),
421
+ yamlFiles: this.filterByExtension(e, j)
422
+ };
423
+ }
424
+ discoverFiles(e) {
425
+ return this.categorize(this.listDiscoveredFiles(e));
426
+ }
427
+ };
428
+ I = F = b([n(), y("design:paramtypes", [P === void 0 ? Object : P, w === void 0 ? Object : w])], I);
429
+ //#endregion
430
+ //#region packages/ic-suite/codometer/codometer-measurement/src/modules/discovery/discovery.module.ts
431
+ var L = class {};
432
+ L = b([r({
433
+ controllers: [],
434
+ exports: [I],
435
+ imports: [T],
436
+ providers: [I, P]
437
+ })], L);
438
+ //#endregion
439
+ //#region packages/ic-suite/codometer/codometer-measurement/src/modules/inputs/inputs.constants.ts
440
+ var R = /[!*+?@[\]{}()]/, z = class extends Error {
441
+ constructor(e, t, n) {
442
+ super(`Input "${e}" starts at ${t}, which is outside ${n}. An input may reach out of the measured folder but not out of the repository holding it — write its directory relative to something inside.`), this.name = "InputOutsideRepositoryError";
443
+ }
444
+ }, B, V = B = class {
445
+ logger;
446
+ constructor(e) {
447
+ this.logger = e, this.logger.setContext(B.name);
448
+ }
449
+ canDescend(e, t) {
450
+ let n = this.isHidden(t);
451
+ return e.includeBases.some((e) => n ? this.leadsToBase(e, t) : this.leadsToBase(e, t) || this.sitsInsideBase(e, t));
452
+ }
453
+ findBoundary(e) {
454
+ let t = a.resolve(e);
455
+ for (;;) {
456
+ let n = t;
457
+ if (ee.some((e) => o(a.join(n, e)))) return n;
458
+ let r = a.dirname(t);
459
+ if (r === t) return a.resolve(e);
460
+ t = r;
461
+ }
462
+ }
463
+ isHidden(e) {
464
+ return e.split("/").at(-1)?.startsWith(".") === !0;
465
+ }
466
+ isLinkedFile(e) {
467
+ try {
468
+ return u(e).isFile();
469
+ } catch (t) {
470
+ return this.logger.warn("🔗 Skipped unreadable link", void 0, {
471
+ path: e,
472
+ reason: String(t)
473
+ }), !1;
474
+ }
475
+ }
476
+ isMatched(e, t) {
477
+ return e.include.some((e) => a.matchesGlob(t, e)) && !e.exclude.some((e) => a.matchesGlob(t, e));
478
+ }
479
+ leadsToBase(e, t) {
480
+ return e === t || e.startsWith(`${t}/`);
481
+ }
482
+ readEntries(e) {
483
+ try {
484
+ return l(e, { withFileTypes: !0 });
485
+ } catch (t) {
486
+ return this.logger.warn("🎯 Skipped unreadable input directory", void 0, {
487
+ path: e,
488
+ reason: String(t)
489
+ }), [];
490
+ }
491
+ }
492
+ readInputPrefix(e, t) {
493
+ return a.relative(t, e).split(a.sep).join("/");
494
+ }
495
+ resolveEntryKind(e, t) {
496
+ return t.isDirectory() ? "directory" : t.isFile() || t.isSymbolicLink() && this.isLinkedFile(e) ? "file" : "other";
497
+ }
498
+ sitsInsideBase(e, t) {
499
+ return e === "" || t.startsWith(`${e}/`);
500
+ }
501
+ sitsInsideBoundary(e, t) {
502
+ return t === e || t.startsWith(`${e}${a.sep}`);
503
+ }
504
+ toIncludeBase(e) {
505
+ let t = [];
506
+ for (let n of e.split("/")) {
507
+ if (R.test(n)) break;
508
+ t.push(n);
509
+ }
510
+ return t.join("/");
511
+ }
512
+ walk(e) {
513
+ let t = [];
514
+ for (let n of this.readEntries(e.absoluteDirectory)) {
515
+ let r = a.join(e.absoluteDirectory, n.name), i = e.relativeDirectory === "" ? n.name : `${e.relativeDirectory}/${n.name}`, o = this.resolveEntryKind(r, n);
516
+ o === "directory" && this.canDescend(e, i) ? t.push(...this.walk({
517
+ ...e,
518
+ absoluteDirectory: r,
519
+ relativeDirectory: i
520
+ })) : o === "file" && this.isMatched(e.input, i) && t.push(i);
521
+ }
522
+ return t;
523
+ }
524
+ matchFiles(e) {
525
+ let t = a.resolve(e.workingDirectory, e.input.directory), n = this.findBoundary(e.workingDirectory);
526
+ if (!this.sitsInsideBoundary(n, t)) throw new z(e.input.name, t, n);
527
+ let r = this.readInputPrefix(t, e.workingDirectory), i = this.walk({
528
+ absoluteDirectory: t,
529
+ includeBases: e.input.include.map((e) => this.toIncludeBase(e)),
530
+ input: e.input,
531
+ relativeDirectory: ""
532
+ }).toSorted();
533
+ return r === "" ? i : i.map((e) => `${r}/${e}`);
534
+ }
535
+ };
536
+ V = B = b([n(), y("design:paramtypes", [w === void 0 ? Object : w])], V);
537
+ //#endregion
538
+ //#region packages/ic-suite/codometer/codometer-measurement/src/modules/inputs/inputs.module.ts
539
+ var H = class {};
540
+ H = b([r({
541
+ controllers: [],
542
+ exports: [V],
543
+ imports: [T],
544
+ providers: [V]
545
+ })], H);
546
+ //#endregion
547
+ //#region packages/ic-suite/codometer/codometer-measurement/src/modules/limits/limits.constants.ts
548
+ var de = "files", fe = "custom", pe = "size", U = class extends Error {
549
+ constructor(e, t) {
550
+ super(`Input "${e}" matched no files, and a limit is written against its "${t}" metric. A limit says the files are there, so an empty match is a glob that stopped matching or a build that never ran — not a measurement of zero.`), this.name = "EmptyTargetError";
551
+ }
552
+ }, W = class extends Error {
553
+ constructor(e, t) {
554
+ super(`Cannot bind the limit written against "${e}": ${t}`), this.name = "UnboundMetricError";
555
+ }
556
+ }, G = class {
557
+ constructor() {}
558
+ bind(e) {
559
+ if (e.index.ambiguous.has(e.metricPath)) throw new W(e.path, `the "${e.target}" target measured more than one metric called "${e.metricPath}". Two configured statistics sharing a label is how that happens — rename one of them.`);
560
+ let t = e.index.metrics.get(e.metricPath);
561
+ return t === void 0 ? void 0 : {
562
+ files: e.index.files,
563
+ measured: t,
564
+ metric: e.metricPath,
565
+ target: e.target
566
+ };
567
+ }
568
+ describeBinding(e) {
569
+ return `the "${e.target}" target's "${e.metric}" metric`;
570
+ }
571
+ describeFailure(e) {
572
+ return e instanceof Error ? e.message : String(e);
573
+ }
574
+ describeTargets(e) {
575
+ return [...e.keys()].map((e) => `"${e}"`).join(", ");
576
+ }
577
+ findCandidates(e) {
578
+ let t = [];
579
+ for (let [n, r] of e.indexes) {
580
+ let i = `${n}.`;
581
+ if (!e.path.startsWith(i)) continue;
582
+ let a = this.bind({
583
+ index: r,
584
+ metricPath: e.path.slice(i.length),
585
+ path: e.path,
586
+ target: n
587
+ });
588
+ a !== void 0 && t.push(a);
589
+ }
590
+ let n = this.findDefaultCandidate(e);
591
+ return n !== void 0 && t.push(n), t;
592
+ }
593
+ findDefaultCandidate(e) {
594
+ if (e.defaultInput === void 0) return;
595
+ let t = e.indexes.get(e.defaultInput);
596
+ if (t === void 0) throw new W(e.path, `the configured default input "${e.defaultInput}" was never measured. Measured targets: ${this.describeTargets(e.indexes)}.`);
597
+ return this.bind({
598
+ index: t,
599
+ metricPath: e.path,
600
+ path: e.path,
601
+ target: e.defaultInput
602
+ });
603
+ }
604
+ resolve(e) {
605
+ let t = this.findCandidates(e), [n] = t;
606
+ if (n === void 0) throw new W(e.path, `nothing measured answers to it. Measured targets: ${this.describeTargets(e.indexes)}. Write the target's name in front of the metric path, or configure a default input.`);
607
+ if (t.length > 1) {
608
+ let n = t.map((e) => this.describeBinding(e)).join(", or ");
609
+ throw new W(e.path, `it could be ${n}. Write the target's name in front of the one it means.`);
610
+ }
611
+ if (n.files === 0) throw new U(n.target, n.metric);
612
+ return n;
613
+ }
614
+ evaluate(e) {
615
+ let t = [], n = [];
616
+ for (let r of e.configuration.limits) try {
617
+ let t = this.resolve({
618
+ defaultInput: e.configuration.defaultInput,
619
+ indexes: e.indexes,
620
+ path: r.metric
621
+ });
622
+ n.push({
623
+ breached: t.measured > r.value,
624
+ label: r.label,
625
+ limit: r.value,
626
+ measured: t.measured,
627
+ metric: t.metric,
628
+ severity: r.severity,
629
+ target: t.target
630
+ });
631
+ } catch (e) {
632
+ t.push({
633
+ metric: r.metric,
634
+ reason: this.describeFailure(e)
635
+ });
636
+ }
637
+ return {
638
+ failures: t,
639
+ limits: n
640
+ };
641
+ }
642
+ };
643
+ G = b([n(), y("design:paramtypes", [])], G);
644
+ //#endregion
645
+ //#region packages/ic-suite/codometer/codometer-measurement/src/modules/limits/metric-index.service.ts
646
+ var K = class {
647
+ constructor() {}
648
+ addMetric(e) {
649
+ if (e.index.metrics.has(e.metricPath)) {
650
+ e.index.ambiguous.add(e.metricPath);
651
+ return;
652
+ }
653
+ e.index.metrics.set(e.metricPath, e.value), e.instances !== void 0 && e.index.instances.set(e.metricPath, e.instances);
654
+ }
655
+ buildTargetIndex(e) {
656
+ let t = {
657
+ ambiguous: /* @__PURE__ */ new Set(),
658
+ files: e.files,
659
+ instances: /* @__PURE__ */ new Map(),
660
+ metrics: /* @__PURE__ */ new Map()
661
+ };
662
+ return this.addMetric({
663
+ index: t,
664
+ metricPath: de,
665
+ value: e.files
666
+ }), e.size !== void 0 && this.addMetric({
667
+ index: t,
668
+ metricPath: pe,
669
+ value: e.size.bytes
670
+ }), e.language !== void 0 && this.indexLanguage(t, e.language), t;
671
+ }
672
+ describeDuplicate(e) {
673
+ return {
674
+ reason: `Two measured targets are called "${e}". A limit addresses its metric by target name, so the name has to belong to one of them; the second was dropped.`,
675
+ target: e
676
+ };
677
+ }
678
+ indexCounters(e, t, n) {
679
+ for (let [r, i] of Object.entries(t)) {
680
+ let t = n === "" ? r : `${n}.${r}`;
681
+ typeof i == "number" ? this.addMetric({
682
+ index: e,
683
+ metricPath: t,
684
+ value: i
685
+ }) : this.isCounterGroup(i) && this.indexCounters(e, i, t);
686
+ }
687
+ }
688
+ indexLanguage(e, t) {
689
+ let { custom: n, ...r } = t;
690
+ this.indexCounters(e, r, "");
691
+ for (let t of n) this.addMetric({
692
+ index: e,
693
+ instances: t.instances,
694
+ metricPath: `${fe}.${t.label}`,
695
+ value: t.count
696
+ });
697
+ }
698
+ isCounterGroup(e) {
699
+ return typeof e == "object" && !!e && !Array.isArray(e);
700
+ }
701
+ index(e) {
702
+ let t = [], n = /* @__PURE__ */ new Map();
703
+ for (let r of e) {
704
+ if (n.has(r.name)) {
705
+ t.push(this.describeDuplicate(r.name));
706
+ continue;
707
+ }
708
+ n.set(r.name, this.buildTargetIndex(r));
709
+ }
710
+ return {
711
+ duplicates: t,
712
+ indexes: n
713
+ };
714
+ }
715
+ };
716
+ K = b([n(), y("design:paramtypes", [])], K);
717
+ //#endregion
718
+ //#region packages/ic-suite/codometer/codometer-measurement/src/modules/limits/limits.module.ts
719
+ var q = class {};
720
+ q = b([r({
721
+ controllers: [],
722
+ exports: [G, K],
723
+ imports: [],
724
+ providers: [G, K]
725
+ })], q);
726
+ var me = { params: { [_.BROTLI_PARAM_QUALITY]: 11 } }, J = class extends Error {
727
+ constructor(e, t) {
728
+ super(`Cannot measure ${e}: ${t}`), this.name = "UnreadableTargetFileError";
729
+ }
730
+ }, Y, X = Y = class {
731
+ logger;
732
+ constructor(e) {
733
+ this.logger = e, this.logger.setContext(Y.name);
734
+ }
735
+ compress(e, t) {
736
+ return {
737
+ brotli: () => g(e, me).length,
738
+ gzip: () => v(e, { level: 9 }).length,
739
+ none: () => e.length
740
+ }[t]();
741
+ }
742
+ measureFile(e, t) {
743
+ try {
744
+ return this.compress(c(e), t);
745
+ } catch (t) {
746
+ throw this.logger.error("🗜️ Failed to measure a target file", void 0, {
747
+ path: e,
748
+ reason: t instanceof Error ? t.message : String(t)
749
+ }), new J(e, String(t));
750
+ }
751
+ }
752
+ analyze(e) {
753
+ let t = 0;
754
+ for (let n of e.files) t += this.measureFile(a.resolve(e.workingDirectory, n), e.compression);
755
+ return {
756
+ bytes: t,
757
+ compression: e.compression,
758
+ files: e.files.length
759
+ };
760
+ }
761
+ };
762
+ X = Y = b([n(), y("design:paramtypes", [w === void 0 ? Object : w])], X);
763
+ //#endregion
764
+ //#region packages/ic-suite/codometer/codometer-measurement/src/modules/size/size.module.ts
765
+ var Z = class {};
766
+ Z = b([r({
767
+ controllers: [],
768
+ exports: [X],
769
+ imports: [T],
770
+ providers: [X]
771
+ })], Z);
772
+ //#endregion
773
+ //#region packages/ic-suite/codometer/codometer-measurement/src/modules/measure/measure.constants.ts
774
+ var he = {
775
+ css: {
776
+ atRules: 0,
777
+ comments: 0,
778
+ customProperties: 0,
779
+ declarations: 0,
780
+ files: 0,
781
+ lines: 0,
782
+ mediaQueries: 0,
783
+ rules: 0,
784
+ selectors: 0
785
+ },
786
+ custom: [],
787
+ folders: 0,
788
+ hcl: {
789
+ attributes: 0,
790
+ blocks: 0,
791
+ comments: 0,
792
+ files: 0,
793
+ interpolations: 0,
794
+ lines: 0,
795
+ outputs: 0,
796
+ resources: 0,
797
+ variables: 0
798
+ },
799
+ javascript: {
800
+ asyncFunctions: 0,
801
+ classes: 0,
802
+ commentLines: 0,
803
+ comments: 0,
804
+ constants: 0,
805
+ exported: 0,
806
+ externalPackages: 0,
807
+ files: 0,
808
+ functions: 0,
809
+ imports: 0,
810
+ methods: 0,
811
+ syncFunctions: 0,
812
+ testFiles: 0,
813
+ todos: 0
814
+ },
815
+ json: {
816
+ arrays: 0,
817
+ booleans: 0,
818
+ files: 0,
819
+ items: 0,
820
+ lines: 0,
821
+ maxDepth: 0,
822
+ nulls: 0,
823
+ numbers: 0,
824
+ objects: 0,
825
+ properties: 0,
826
+ strings: 0,
827
+ totalNodes: 0
828
+ },
829
+ jupyter: {
830
+ cells: 0,
831
+ classes: 0,
832
+ codeBlocks: 0,
833
+ codeCells: 0,
834
+ codeLines: 0,
835
+ decorators: 0,
836
+ executedCells: 0,
837
+ files: 0,
838
+ functions: 0,
839
+ headings: 0,
840
+ images: 0,
841
+ imports: 0,
842
+ links: 0,
843
+ markdownCells: 0,
844
+ markdownLines: 0,
845
+ maxDepth: 0,
846
+ outputs: 0,
847
+ properties: 0,
848
+ rawCells: 0,
849
+ totalNodes: 0
850
+ },
851
+ linesOfCode: 0,
852
+ markdown: {
853
+ blockQuotes: 0,
854
+ codeBlocks: 0,
855
+ files: 0,
856
+ headingLevel1: 0,
857
+ headingLevel2: 0,
858
+ headingLevel3: 0,
859
+ headingLevel4: 0,
860
+ headingLevel5: 0,
861
+ headingLevel6: 0,
862
+ images: 0,
863
+ inlineCode: 0,
864
+ lines: 0,
865
+ links: 0,
866
+ listItems: 0,
867
+ lists: 0,
868
+ paragraphs: 0,
869
+ tableRows: 0,
870
+ tables: 0,
871
+ taskListItems: 0,
872
+ thematicBreaks: 0
873
+ },
874
+ python: {
875
+ classes: 0,
876
+ commentLines: 0,
877
+ comments: 0,
878
+ constants: 0,
879
+ decorators: 0,
880
+ docstringLines: 0,
881
+ docstrings: 0,
882
+ files: 0,
883
+ functions: 0,
884
+ imports: 0,
885
+ lines: 0,
886
+ protocols: 0
887
+ },
888
+ repositoryBytes: 0,
889
+ shell: {
890
+ commentLines: 0,
891
+ comments: 0,
892
+ conditionals: 0,
893
+ exports: 0,
894
+ files: 0,
895
+ functions: 0,
896
+ lines: 0,
897
+ loops: 0,
898
+ pipelines: 0,
899
+ shebangs: 0,
900
+ variables: 0
901
+ },
902
+ sourceFiles: 0,
903
+ sql: {
904
+ comments: 0,
905
+ commonTableExpressions: 0,
906
+ creates: 0,
907
+ deletes: 0,
908
+ files: 0,
909
+ inserts: 0,
910
+ joins: 0,
911
+ lines: 0,
912
+ selects: 0,
913
+ statements: 0,
914
+ updates: 0
915
+ },
916
+ toml: {
917
+ arrays: 0,
918
+ arrayTables: 0,
919
+ comments: 0,
920
+ files: 0,
921
+ keys: 0,
922
+ lines: 0,
923
+ tables: 0
924
+ },
925
+ typescript: {
926
+ decorators: 0,
927
+ docComments: 0,
928
+ enums: 0,
929
+ files: 0,
930
+ genericDeclarations: 0,
931
+ interfaces: 0
932
+ },
933
+ yaml: {
934
+ aliases: 0,
935
+ anchors: 0,
936
+ comments: 0,
937
+ documents: 0,
938
+ files: 0,
939
+ keys: 0,
940
+ lines: 0,
941
+ mappings: 0,
942
+ maxDepth: 0,
943
+ scalars: 0,
944
+ sequences: 0
945
+ }
946
+ }, Q = class {
947
+ discoveryService;
948
+ languagesService;
949
+ customizationService;
950
+ inputsService;
951
+ sizeService;
952
+ limitsService;
953
+ metricIndexService;
954
+ constructor(e, t, n, r, i, a, o) {
955
+ this.discoveryService = e, this.languagesService = t, this.customizationService = n, this.inputsService = r, this.sizeService = i, this.limitsService = a, this.metricIndexService = o;
956
+ }
957
+ analyzeFiles(e) {
958
+ let t = e.workingDirectory, { discoveredFiles: n } = e, r = this.languagesService.analyze({
959
+ commentCounters: e.commentCounters,
960
+ configuration: e.configuration,
961
+ discoveredFiles: n,
962
+ symbolCounters: e.symbolCounters,
963
+ workingDirectory: t
964
+ }), i = this.sizeService.analyze({
965
+ compression: "none",
966
+ files: n.files,
967
+ workingDirectory: t
968
+ }), a = {
969
+ ...r.commentCounts,
970
+ ...r.typescript.declarationCommentCounts
971
+ };
972
+ return {
973
+ css: { ...r.css },
974
+ custom: this.customizationService.analyze({
975
+ commentCounts: a,
976
+ files: n.files,
977
+ statistics: e.statistics,
978
+ symbolCounts: r.typescript.symbolCounts
979
+ }),
980
+ folders: this.getFolderCount(n.files),
981
+ hcl: { ...r.hcl },
982
+ javascript: this.buildJavascriptStatistics(r.typescript),
983
+ json: { ...r.json },
984
+ jupyter: { ...r.jupyter },
985
+ linesOfCode: r.typescript.lines + r.python.lines + r.jupyter.codeLines,
986
+ markdown: { ...r.markdown },
987
+ python: { ...r.python },
988
+ repositoryBytes: i.bytes,
989
+ shell: { ...r.shell },
990
+ sourceFiles: r.typescript.tsFiles + r.typescript.jsFiles + r.python.files,
991
+ sql: { ...r.sql },
992
+ toml: { ...r.toml },
993
+ typescript: this.buildTypescriptStatistics(r.typescript),
994
+ yaml: { ...r.yaml }
995
+ };
996
+ }
997
+ buildJavascriptStatistics(e) {
998
+ return {
999
+ asyncFunctions: e.asyncFunctions,
1000
+ classes: e.classes,
1001
+ commentLines: e.commentLines,
1002
+ comments: e.comments,
1003
+ constants: e.constants,
1004
+ exported: e.exported,
1005
+ externalPackages: e.externalPackages.size,
1006
+ files: e.jsFiles,
1007
+ functions: e.functions,
1008
+ imports: e.imports,
1009
+ methods: e.methods,
1010
+ syncFunctions: e.syncFunctions,
1011
+ testFiles: e.testFiles,
1012
+ todos: e.todos
1013
+ };
1014
+ }
1015
+ buildTypescriptStatistics(e) {
1016
+ return {
1017
+ decorators: e.decorators,
1018
+ docComments: e.docComments,
1019
+ enums: e.enums,
1020
+ files: e.tsFiles,
1021
+ genericDeclarations: e.genericDeclarations,
1022
+ interfaces: e.interfaces
1023
+ };
1024
+ }
1025
+ describeFailure(e) {
1026
+ return e instanceof Error ? e.message : String(e);
1027
+ }
1028
+ discoverInputFiles(e, t) {
1029
+ let n = e.name === m ? this.discoveryService.discoverFiles({
1030
+ exclude: t.configuration.exclude,
1031
+ excludeFrom: t.configuration.excludeFrom,
1032
+ workingDirectory: t.workingDirectory
1033
+ }).files : this.inputsService.matchFiles({
1034
+ input: e,
1035
+ workingDirectory: t.workingDirectory
1036
+ });
1037
+ return this.excludeOutputPaths(n, t.outputPaths);
1038
+ }
1039
+ excludeOutputPaths(e, t) {
1040
+ if (t.length === 0) return e;
1041
+ let n = new Set(t);
1042
+ return e.filter((e) => !n.has(e));
1043
+ }
1044
+ getFolderCount(e) {
1045
+ let t = /* @__PURE__ */ new Set();
1046
+ for (let n of e) {
1047
+ let e = n.split("/");
1048
+ for (let n = 1; n < e.length; n++) t.add(e.slice(0, n).join("/"));
1049
+ }
1050
+ return t.size;
1051
+ }
1052
+ measureInput(e) {
1053
+ let { input: t } = e, n = this.discoverInputFiles(t, e), r = this.runsAnalysis(t, "language") ? this.analyzeFiles({
1054
+ commentCounters: e.commentCounters,
1055
+ configuration: e.configuration,
1056
+ discoveredFiles: this.discoveryService.categorize(n),
1057
+ statistics: e.statistics,
1058
+ symbolCounters: e.symbolCounters,
1059
+ workingDirectory: e.workingDirectory
1060
+ }) : void 0;
1061
+ return {
1062
+ files: n.length,
1063
+ language: r,
1064
+ name: t.name,
1065
+ size: this.runsAnalysis(t, "size") ? this.sizeService.analyze({
1066
+ compression: t.compression,
1067
+ files: n,
1068
+ workingDirectory: e.workingDirectory
1069
+ }) : void 0
1070
+ };
1071
+ }
1072
+ readLimitFailures(e) {
1073
+ return e.map((e) => ({
1074
+ kind: "limit",
1075
+ reason: e.reason,
1076
+ subject: e.metric
1077
+ }));
1078
+ }
1079
+ runsAnalysis(e, t) {
1080
+ return e.analyses.includes(t);
1081
+ }
1082
+ measure(e) {
1083
+ let t = e.configuration.custom, n = this.customizationService.buildCommentCounters(t), r = this.customizationService.buildSymbolCounters(t), i = [], a = [];
1084
+ for (let o of e.configuration.inputs) try {
1085
+ a.push(this.measureInput({
1086
+ commentCounters: n,
1087
+ configuration: e.configuration,
1088
+ input: o,
1089
+ outputPaths: e.outputPaths,
1090
+ statistics: t,
1091
+ symbolCounters: r,
1092
+ workingDirectory: e.workingDirectory
1093
+ }));
1094
+ } catch (e) {
1095
+ i.push({
1096
+ kind: "input",
1097
+ reason: this.describeFailure(e),
1098
+ subject: o.name
1099
+ });
1100
+ }
1101
+ let { duplicates: o, indexes: s } = this.metricIndexService.index(a), c = this.limitsService.evaluate({
1102
+ configuration: e.configuration,
1103
+ indexes: s
1104
+ }), l = a.find((e) => e.language !== void 0);
1105
+ return {
1106
+ failures: [
1107
+ ...i,
1108
+ ...o.map((e) => ({
1109
+ kind: "input",
1110
+ reason: e.reason,
1111
+ subject: e.target
1112
+ })),
1113
+ ...this.readLimitFailures(c.failures)
1114
+ ],
1115
+ indexes: s,
1116
+ inputs: a,
1117
+ limits: c.limits,
1118
+ statistics: l?.language ?? he
1119
+ };
1120
+ }
1121
+ };
1122
+ Q = b([n(), y("design:paramtypes", [
1123
+ I === void 0 ? Object : I,
1124
+ h === void 0 ? Object : h,
1125
+ x === void 0 ? Object : x,
1126
+ V === void 0 ? Object : V,
1127
+ X === void 0 ? Object : X,
1128
+ G === void 0 ? Object : G,
1129
+ K === void 0 ? Object : K
1130
+ ])], Q);
1131
+ //#endregion
1132
+ //#region packages/ic-suite/codometer/codometer-measurement/src/modules/measure/measure.module.ts
1133
+ var $ = class {};
1134
+ $ = b([r({
1135
+ controllers: [],
1136
+ exports: [Q],
1137
+ imports: [
1138
+ p,
1139
+ S,
1140
+ L,
1141
+ H,
1142
+ te,
1143
+ q,
1144
+ T,
1145
+ Z
1146
+ ],
1147
+ providers: [Q]
1148
+ })], $);
1149
+ //#endregion
1150
+ export { S as CustomizationModule, x as CustomizationService, L as DiscoveryModule, I as DiscoveryService, U as EmptyTargetError, z as InputOutsideRepositoryError, H as InputsModule, V as InputsService, q as LimitsModule, G as LimitsService, $ as MeasureModule, Q as MeasureService, K as MetricIndexService, Z as SizeModule, X as SizeService, W as UnboundMetricError, J as UnreadableTargetFileError };