@donativo/roux 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/README.md +335 -0
  2. package/dist/analysis/age.d.ts +3 -0
  3. package/dist/analysis/age.js +32 -0
  4. package/dist/analysis/age.js.map +1 -0
  5. package/dist/analysis/authors.d.ts +3 -0
  6. package/dist/analysis/authors.js +18 -0
  7. package/dist/analysis/authors.js.map +1 -0
  8. package/dist/analysis/churn.d.ts +5 -0
  9. package/dist/analysis/churn.js +39 -0
  10. package/dist/analysis/churn.js.map +1 -0
  11. package/dist/analysis/communication.d.ts +3 -0
  12. package/dist/analysis/communication.js +44 -0
  13. package/dist/analysis/communication.js.map +1 -0
  14. package/dist/analysis/coupling.d.ts +4 -0
  15. package/dist/analysis/coupling.js +84 -0
  16. package/dist/analysis/coupling.js.map +1 -0
  17. package/dist/analysis/entity-effort.d.ts +3 -0
  18. package/dist/analysis/entity-effort.js +36 -0
  19. package/dist/analysis/entity-effort.js.map +1 -0
  20. package/dist/analysis/entity-ownership.d.ts +3 -0
  21. package/dist/analysis/entity-ownership.js +35 -0
  22. package/dist/analysis/entity-ownership.js.map +1 -0
  23. package/dist/analysis/fragmentation.d.ts +3 -0
  24. package/dist/analysis/fragmentation.js +53 -0
  25. package/dist/analysis/fragmentation.js.map +1 -0
  26. package/dist/analysis/identity.d.ts +3 -0
  27. package/dist/analysis/identity.js +12 -0
  28. package/dist/analysis/identity.js.map +1 -0
  29. package/dist/analysis/index.d.ts +4 -0
  30. package/dist/analysis/index.js +59 -0
  31. package/dist/analysis/index.js.map +1 -0
  32. package/dist/analysis/main-dev-by-revs.d.ts +3 -0
  33. package/dist/analysis/main-dev-by-revs.js +36 -0
  34. package/dist/analysis/main-dev-by-revs.js.map +1 -0
  35. package/dist/analysis/main-dev.d.ts +3 -0
  36. package/dist/analysis/main-dev.js +38 -0
  37. package/dist/analysis/main-dev.js.map +1 -0
  38. package/dist/analysis/messages.d.ts +3 -0
  39. package/dist/analysis/messages.js +27 -0
  40. package/dist/analysis/messages.js.map +1 -0
  41. package/dist/analysis/refactoring-main-dev.d.ts +3 -0
  42. package/dist/analysis/refactoring-main-dev.js +37 -0
  43. package/dist/analysis/refactoring-main-dev.js.map +1 -0
  44. package/dist/analysis/revisions.d.ts +3 -0
  45. package/dist/analysis/revisions.js +16 -0
  46. package/dist/analysis/revisions.js.map +1 -0
  47. package/dist/analysis/summary.d.ts +3 -0
  48. package/dist/analysis/summary.js +12 -0
  49. package/dist/analysis/summary.js.map +1 -0
  50. package/dist/analysis/types.d.ts +18 -0
  51. package/dist/analysis/types.js +8 -0
  52. package/dist/analysis/types.js.map +1 -0
  53. package/dist/app.d.ts +12 -0
  54. package/dist/app.js +54 -0
  55. package/dist/app.js.map +1 -0
  56. package/dist/cli.d.ts +1 -0
  57. package/dist/cli.js +79 -0
  58. package/dist/cli.js.map +1 -0
  59. package/dist/git.d.ts +7 -0
  60. package/dist/git.js +24 -0
  61. package/dist/git.js.map +1 -0
  62. package/dist/index.d.ts +8 -0
  63. package/dist/index.js +6 -0
  64. package/dist/index.js.map +1 -0
  65. package/dist/output/csv.d.ts +1 -0
  66. package/dist/output/csv.js +19 -0
  67. package/dist/output/csv.js.map +1 -0
  68. package/dist/output/json.d.ts +1 -0
  69. package/dist/output/json.js +4 -0
  70. package/dist/output/json.js.map +1 -0
  71. package/dist/parsers/git.d.ts +2 -0
  72. package/dist/parsers/git.js +41 -0
  73. package/dist/parsers/git.js.map +1 -0
  74. package/dist/parsers/git2.d.ts +2 -0
  75. package/dist/parsers/git2.js +72 -0
  76. package/dist/parsers/git2.js.map +1 -0
  77. package/dist/parsers/index.d.ts +7 -0
  78. package/dist/parsers/index.js +7 -0
  79. package/dist/parsers/index.js.map +1 -0
  80. package/dist/parsers/types.d.ts +9 -0
  81. package/dist/parsers/types.js +2 -0
  82. package/dist/parsers/types.js.map +1 -0
  83. package/dist/transforms/grouper.d.ts +11 -0
  84. package/dist/transforms/grouper.js +57 -0
  85. package/dist/transforms/grouper.js.map +1 -0
  86. package/dist/transforms/team-mapper.d.ts +7 -0
  87. package/dist/transforms/team-mapper.js +51 -0
  88. package/dist/transforms/team-mapper.js.map +1 -0
  89. package/dist/transforms/temporal-grouper.d.ts +2 -0
  90. package/dist/transforms/temporal-grouper.js +42 -0
  91. package/dist/transforms/temporal-grouper.js.map +1 -0
  92. package/dist/utils/dataset.d.ts +2 -0
  93. package/dist/utils/dataset.js +34 -0
  94. package/dist/utils/dataset.js.map +1 -0
  95. package/package.json +53 -0
package/dist/cli.js ADDED
@@ -0,0 +1,79 @@
1
+ import { Command } from "commander";
2
+ import { run } from "./app";
3
+ import { analyses } from "./analysis";
4
+ const program = new Command();
5
+ program
6
+ .name("roux")
7
+ .description("Mine and analyze version control data")
8
+ .version("0.1.0");
9
+ // Shared options for all analysis subcommands
10
+ function addSharedOptions(cmd) {
11
+ return cmd
12
+ .option("-l, --log <file>", "Input git log file (otherwise reads current repo)")
13
+ .option("--repo <path>", "Git repo path to analyze")
14
+ .option("-r, --rows <n>", "Max output rows", parseInt)
15
+ .option("-n, --min-revs <n>", "Min revisions threshold", parseInt)
16
+ .option("-m, --min-shared-revs <n>", "Min shared revisions", parseInt)
17
+ .option("-i, --min-coupling <n>", "Min coupling %", parseInt)
18
+ .option("-x, --max-coupling <n>", "Max coupling %", parseInt)
19
+ .option("-s, --max-changeset-size <n>", "Max changeset size", parseInt)
20
+ .option("-o, --output-format <format>", "Output format: csv or json", "csv")
21
+ .option("-g, --group <file>", "Architectural group specification file")
22
+ .option("-p, --team-map <file>", "Team/person mapping CSV file")
23
+ .option("-t, --temporal-period <days>", "Temporal period in days", parseInt)
24
+ .option("-d, --age-time-now <date>", "Reference date for age analysis (YYYY-MM-DD)")
25
+ .option("-e, --expression-to-match <regex>", "Regex for message matching")
26
+ .option("-c, --format <format>", "Input log format: git2 or git", "git2")
27
+ .option("--after <date>", "Only commits after date (YYYY-MM-DD)")
28
+ .option("--before <date>", "Only commits before date (YYYY-MM-DD)")
29
+ .option("--rev <range>", "Git revision range (e.g. v1.0..v2.0)");
30
+ }
31
+ // Check if stdin has data (pipe mode)
32
+ async function readStdin() {
33
+ if (process.stdin.isTTY)
34
+ return undefined;
35
+ const chunks = [];
36
+ for await (const chunk of process.stdin) {
37
+ chunks.push(chunk);
38
+ }
39
+ return Buffer.concat(chunks).toString("utf-8");
40
+ }
41
+ // Register a subcommand for each analysis
42
+ for (const name of Object.keys(analyses)) {
43
+ const cmd = program.command(name).description(`Run ${name} analysis`);
44
+ addSharedOptions(cmd);
45
+ cmd.action(async (opts) => {
46
+ try {
47
+ const input = await readStdin();
48
+ const output = run({
49
+ analysis: name,
50
+ input,
51
+ log: opts.log,
52
+ repo: opts.repo,
53
+ rows: opts.rows,
54
+ minRevs: opts.minRevs,
55
+ minSharedRevs: opts.minSharedRevs,
56
+ minCoupling: opts.minCoupling,
57
+ maxCoupling: opts.maxCoupling,
58
+ maxChangesetSize: opts.maxChangesetSize,
59
+ outputFormat: opts.outputFormat,
60
+ groupFile: opts.group,
61
+ teamMapFile: opts.teamMap,
62
+ temporalPeriod: opts.temporalPeriod,
63
+ ageTimeNow: opts.ageTimeNow,
64
+ expressionToMatch: opts.expressionToMatch,
65
+ logFormat: opts.format,
66
+ after: opts.after,
67
+ before: opts.before,
68
+ rev: opts.rev,
69
+ });
70
+ process.stdout.write(output);
71
+ }
72
+ catch (e) {
73
+ console.error(e.message);
74
+ process.exit(1);
75
+ }
76
+ });
77
+ }
78
+ program.parse();
79
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,MAAM,CAAC;KACZ,WAAW,CAAC,uCAAuC,CAAC;KACpD,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,8CAA8C;AAC9C,SAAS,gBAAgB,CAAC,GAAY;IACpC,OAAO,GAAG;SACP,MAAM,CAAC,kBAAkB,EAAE,mDAAmD,CAAC;SAC/E,MAAM,CAAC,eAAe,EAAE,0BAA0B,CAAC;SACnD,MAAM,CAAC,gBAAgB,EAAE,iBAAiB,EAAE,QAAQ,CAAC;SACrD,MAAM,CAAC,oBAAoB,EAAE,yBAAyB,EAAE,QAAQ,CAAC;SACjE,MAAM,CAAC,2BAA2B,EAAE,sBAAsB,EAAE,QAAQ,CAAC;SACrE,MAAM,CAAC,wBAAwB,EAAE,gBAAgB,EAAE,QAAQ,CAAC;SAC5D,MAAM,CAAC,wBAAwB,EAAE,gBAAgB,EAAE,QAAQ,CAAC;SAC5D,MAAM,CAAC,8BAA8B,EAAE,oBAAoB,EAAE,QAAQ,CAAC;SACtE,MAAM,CAAC,8BAA8B,EAAE,4BAA4B,EAAE,KAAK,CAAC;SAC3E,MAAM,CAAC,oBAAoB,EAAE,wCAAwC,CAAC;SACtE,MAAM,CAAC,uBAAuB,EAAE,8BAA8B,CAAC;SAC/D,MAAM,CAAC,8BAA8B,EAAE,yBAAyB,EAAE,QAAQ,CAAC;SAC3E,MAAM,CAAC,2BAA2B,EAAE,8CAA8C,CAAC;SACnF,MAAM,CAAC,mCAAmC,EAAE,4BAA4B,CAAC;SACzE,MAAM,CAAC,uBAAuB,EAAE,+BAA+B,EAAE,MAAM,CAAC;SACxE,MAAM,CAAC,gBAAgB,EAAE,sCAAsC,CAAC;SAChE,MAAM,CAAC,iBAAiB,EAAE,uCAAuC,CAAC;SAClE,MAAM,CAAC,eAAe,EAAE,sCAAsC,CAAC,CAAC;AACrE,CAAC;AAED,sCAAsC;AACtC,KAAK,UAAU,SAAS;IACtB,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC1C,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QACxC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AACjD,CAAC;AAED,0CAA0C;AAC1C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;IACzC,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,OAAO,IAAI,WAAW,CAAC,CAAC;IACtE,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACtB,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACxB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,SAAS,EAAE,CAAC;YAChC,MAAM,MAAM,GAAG,GAAG,CAAC;gBACjB,QAAQ,EAAE,IAAI;gBACd,KAAK;gBACL,GAAG,EAAE,IAAI,CAAC,GAAG;gBACb,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,aAAa,EAAE,IAAI,CAAC,aAAa;gBACjC,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;gBACvC,YAAY,EAAE,IAAI,CAAC,YAAY;gBAC/B,SAAS,EAAE,IAAI,CAAC,KAAK;gBACrB,WAAW,EAAE,IAAI,CAAC,OAAO;gBACzB,cAAc,EAAE,IAAI,CAAC,cAAc;gBACnC,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;gBACzC,SAAS,EAAE,IAAI,CAAC,MAAM;gBACtB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,GAAG,EAAE,IAAI,CAAC,GAAG;aACd,CAAC,CAAC;YACH,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,CAAU,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CAAE,CAAW,CAAC,OAAO,CAAC,CAAC;YACpC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,OAAO,CAAC,KAAK,EAAE,CAAC"}
package/dist/git.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ export interface GitLogOptions {
2
+ repo?: string;
3
+ after?: string;
4
+ before?: string;
5
+ rev?: string;
6
+ }
7
+ export declare function generateGitLog(opts?: GitLogOptions): string;
package/dist/git.js ADDED
@@ -0,0 +1,24 @@
1
+ import { execSync } from "child_process";
2
+ export function generateGitLog(opts = {}) {
3
+ const cwd = opts.repo ?? process.cwd();
4
+ const args = [
5
+ "--all", "--numstat", "--date=short",
6
+ "--pretty=format:'--%h--%ad--%aN--%s'", "--no-renames",
7
+ ];
8
+ if (opts.after)
9
+ args.push(`--after=${opts.after}`);
10
+ if (opts.before)
11
+ args.push(`--before=${opts.before}`);
12
+ if (opts.rev) {
13
+ const idx = args.indexOf("--all");
14
+ if (idx !== -1)
15
+ args.splice(idx, 1);
16
+ args.push(opts.rev);
17
+ }
18
+ return execSync(`git log ${args.join(" ")}`, {
19
+ cwd,
20
+ encoding: "utf-8",
21
+ maxBuffer: 100 * 1024 * 1024,
22
+ });
23
+ }
24
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AASzC,MAAM,UAAU,cAAc,CAAC,OAAsB,EAAE;IACrD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACvC,MAAM,IAAI,GAAG;QACX,OAAO,EAAE,WAAW,EAAE,cAAc;QACpC,sCAAsC,EAAE,cAAc;KACvD,CAAC;IACF,IAAI,IAAI,CAAC,KAAK;QAAG,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IACpD,IAAI,IAAI,CAAC,MAAM;QAAE,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACtD,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAClC,IAAI,GAAG,KAAK,CAAC,CAAC;YAAE,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACtB,CAAC;IACD,OAAO,QAAQ,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE;QAC3C,GAAG;QACH,QAAQ,EAAE,OAAO;QACjB,SAAS,EAAE,GAAG,GAAG,IAAI,GAAG,IAAI;KAC7B,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,8 @@
1
+ export { run as analyze } from "./app";
2
+ export type { AppOptions } from "./app";
3
+ export { parseGit2Log as parseGitLog } from "./parsers/git2";
4
+ export { generateGitLog } from "./git";
5
+ export type { GitLogOptions } from "./git";
6
+ export { analyses } from "./analysis";
7
+ export type { Modification } from "./parsers/types";
8
+ export type { AnalysisFn, AnalysisOptions } from "./analysis/types";
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ // Public API — import { analyze, parseGitLog } from "roux"
2
+ export { run as analyze } from "./app";
3
+ export { parseGit2Log as parseGitLog } from "./parsers/git2";
4
+ export { generateGitLog } from "./git";
5
+ export { analyses } from "./analysis";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,OAAO,EAAE,GAAG,IAAI,OAAO,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAE,YAAY,IAAI,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function toCSV(data: Record<string, unknown>[], emptyHeaders?: string[]): string;
@@ -0,0 +1,19 @@
1
+ function csvField(value) {
2
+ const s = String(value ?? "");
3
+ // Quote if contains comma, double-quote, or newline
4
+ if (s.includes(",") || s.includes('"') || s.includes("\n")) {
5
+ return '"' + s.replace(/"/g, '""') + '"';
6
+ }
7
+ return s;
8
+ }
9
+ export function toCSV(data, emptyHeaders) {
10
+ const cols = data.length > 0 ? Object.keys(data[0]) : emptyHeaders;
11
+ if (!cols)
12
+ return "";
13
+ const lines = [cols.join(",")];
14
+ for (const row of data) {
15
+ lines.push(cols.map((h) => csvField(row[h])).join(","));
16
+ }
17
+ return lines.join("\n") + "\n";
18
+ }
19
+ //# sourceMappingURL=csv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"csv.js","sourceRoot":"","sources":["../../src/output/csv.ts"],"names":[],"mappings":"AAAA,SAAS,QAAQ,CAAC,KAAc;IAC9B,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;IAC9B,oDAAoD;IACpD,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3D,OAAO,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC;IAC3C,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,UAAU,KAAK,CACnB,IAA+B,EAC/B,YAAuB;IAEvB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;IACnE,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AACjC,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function toJSON(data: Record<string, unknown>[]): string;
@@ -0,0 +1,4 @@
1
+ export function toJSON(data) {
2
+ return JSON.stringify(data, null, 2) + "\n";
3
+ }
4
+ //# sourceMappingURL=json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/output/json.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,MAAM,CAAC,IAA+B;IACpD,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { Modification } from "./types";
2
+ export declare function parseGitLog(text: string): Modification[];
@@ -0,0 +1,41 @@
1
+ // [hash] author YYYY-MM-DD message
2
+ // The date is the FIRST occurrence of YYYY-MM-DD pattern after the "]"
3
+ const HEADER_RE = /^\[([a-f0-9]+)\]\s+(.+?)\s+(\d{4}-\d{2}-\d{2})\s+(.*)$/;
4
+ const NUMSTAT_RE = /^(\d+|-)\t(\d+|-)\t(.+)$/;
5
+ export function parseGitLog(text) {
6
+ const result = [];
7
+ const lines = text.split("\n");
8
+ let currentRev = "";
9
+ let currentDate = "";
10
+ let currentAuthor = "";
11
+ let currentMessage = "";
12
+ for (const line of lines) {
13
+ const trimmed = line.trim();
14
+ if (!trimmed)
15
+ continue;
16
+ const headerMatch = trimmed.match(HEADER_RE);
17
+ if (headerMatch) {
18
+ currentRev = headerMatch[1];
19
+ currentAuthor = headerMatch[2];
20
+ currentDate = headerMatch[3];
21
+ currentMessage = headerMatch[4];
22
+ continue;
23
+ }
24
+ const numstatMatch = trimmed.match(NUMSTAT_RE);
25
+ if (numstatMatch && currentRev) {
26
+ const added = numstatMatch[1];
27
+ const deleted = numstatMatch[2];
28
+ result.push({
29
+ entity: numstatMatch[3],
30
+ author: currentAuthor,
31
+ rev: currentRev,
32
+ date: currentDate,
33
+ locAdded: added === "-" ? -1 : parseInt(added, 10),
34
+ locDeleted: deleted === "-" ? -1 : parseInt(deleted, 10),
35
+ message: currentMessage,
36
+ });
37
+ }
38
+ }
39
+ return result;
40
+ }
41
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/parsers/git.ts"],"names":[],"mappings":"AAEA,mCAAmC;AACnC,uEAAuE;AACvE,MAAM,SAAS,GAAG,wDAAwD,CAAC;AAC3E,MAAM,UAAU,GAAG,0BAA0B,CAAC;AAE9C,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,MAAM,MAAM,GAAmB,EAAE,CAAC;IAClC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAE/B,IAAI,UAAU,GAAG,EAAE,CAAC;IACpB,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,IAAI,aAAa,GAAG,EAAE,CAAC;IACvB,IAAI,cAAc,GAAG,EAAE,CAAC;IAExB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO;YAAE,SAAS;QAEvB,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAC7C,IAAI,WAAW,EAAE,CAAC;YAChB,UAAU,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;YAC5B,aAAa,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;YAC/B,WAAW,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;YAC7B,cAAc,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;YAChC,SAAS;QACX,CAAC;QAED,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAC/C,IAAI,YAAY,IAAI,UAAU,EAAE,CAAC;YAC/B,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;YAC9B,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;YAChC,MAAM,CAAC,IAAI,CAAC;gBACV,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;gBACvB,MAAM,EAAE,aAAa;gBACrB,GAAG,EAAE,UAAU;gBACf,IAAI,EAAE,WAAW;gBACjB,QAAQ,EAAE,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC;gBAClD,UAAU,EAAE,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC;gBACxD,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { Modification } from "./types";
2
+ export declare function parseGit2Log(text: string): Modification[];
@@ -0,0 +1,72 @@
1
+ const DELIM = "--";
2
+ const NUMSTAT_RE = /^(\d+|-)\t(\d+|-)\t(.+)$/;
3
+ function parseHeader(line) {
4
+ // Format: --<rev>--<date>--<author>[--<message>]
5
+ // We strip the leading "--" then split on "--" with a limit of 4 segments
6
+ if (!line.startsWith(DELIM))
7
+ return null;
8
+ const rest = line.slice(2); // strip leading "--"
9
+ // Split into at most 4 parts: rev, date, author, message(optional)
10
+ // But message may contain "--", so we split carefully
11
+ const i1 = rest.indexOf(DELIM);
12
+ if (i1 === -1)
13
+ return null;
14
+ const rev = rest.slice(0, i1);
15
+ if (!/^[a-f0-9]+$/.test(rev))
16
+ return null;
17
+ const i2 = rest.indexOf(DELIM, i1 + 2);
18
+ if (i2 === -1)
19
+ return null;
20
+ const date = rest.slice(i1 + 2, i2);
21
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(date))
22
+ return null;
23
+ const afterDate = rest.slice(i2 + 2);
24
+ // Check if there's a message (next "--" after author)
25
+ const i3 = afterDate.indexOf(DELIM);
26
+ if (i3 === -1) {
27
+ return { rev, date, author: afterDate };
28
+ }
29
+ const author = afterDate.slice(0, i3);
30
+ const message = afterDate.slice(i3 + 2);
31
+ return { rev, date, author, message: message || undefined };
32
+ }
33
+ export function parseGit2Log(text) {
34
+ const result = [];
35
+ const lines = text.split("\n");
36
+ let currentRev = "";
37
+ let currentDate = "";
38
+ let currentAuthor = "";
39
+ let currentMessage;
40
+ for (const line of lines) {
41
+ const trimmed = line.trim();
42
+ if (!trimmed)
43
+ continue;
44
+ const header = parseHeader(trimmed);
45
+ if (header) {
46
+ currentRev = header.rev;
47
+ currentDate = header.date;
48
+ currentAuthor = header.author;
49
+ currentMessage = header.message;
50
+ continue;
51
+ }
52
+ const numstatMatch = trimmed.match(NUMSTAT_RE);
53
+ if (numstatMatch && currentRev) {
54
+ const added = numstatMatch[1];
55
+ const deleted = numstatMatch[2];
56
+ const mod = {
57
+ entity: numstatMatch[3],
58
+ author: currentAuthor,
59
+ rev: currentRev,
60
+ date: currentDate,
61
+ locAdded: added === "-" ? -1 : parseInt(added, 10),
62
+ locDeleted: deleted === "-" ? -1 : parseInt(deleted, 10),
63
+ };
64
+ if (currentMessage !== undefined) {
65
+ mod.message = currentMessage;
66
+ }
67
+ result.push(mod);
68
+ }
69
+ }
70
+ return result;
71
+ }
72
+ //# sourceMappingURL=git2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git2.js","sourceRoot":"","sources":["../../src/parsers/git2.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { parseGit2Log } from "./git2";
2
+ import { parseGitLog } from "./git";
3
+ export declare const parsers: {
4
+ readonly git2: typeof parseGit2Log;
5
+ readonly git: typeof parseGitLog;
6
+ };
7
+ export type VcsType = keyof typeof parsers;
@@ -0,0 +1,7 @@
1
+ import { parseGit2Log } from "./git2";
2
+ import { parseGitLog } from "./git";
3
+ export const parsers = {
4
+ git2: parseGit2Log,
5
+ git: parseGitLog,
6
+ };
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/parsers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAEpC,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,IAAI,EAAE,YAAY;IAClB,GAAG,EAAE,WAAW;CACR,CAAC"}
@@ -0,0 +1,9 @@
1
+ export interface Modification {
2
+ entity: string;
3
+ author: string;
4
+ rev: string;
5
+ date: string;
6
+ locAdded: number;
7
+ locDeleted: number;
8
+ message?: string;
9
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/parsers/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ import type { Modification } from "../parsers/types";
2
+ export interface GroupSpec {
3
+ pattern: RegExp;
4
+ name: string;
5
+ }
6
+ export declare function parseGroupText(text: string): GroupSpec[];
7
+ export declare const parseGroupFile: typeof parseGroupText;
8
+ export declare function parseGroupJSON(text: string): GroupSpec[];
9
+ export declare function parseGroupMarkdown(text: string): GroupSpec[];
10
+ export declare function parseGroupConfig(filePath: string): GroupSpec[];
11
+ export declare function applyGrouping(data: Modification[], specs: GroupSpec[]): Modification[];
@@ -0,0 +1,57 @@
1
+ import { readFileSync } from "fs";
2
+ import { extname } from "path";
3
+ function toGroupSpec(path, name) {
4
+ if (path.startsWith("^") && path.endsWith("$")) {
5
+ return { pattern: new RegExp(path), name };
6
+ }
7
+ const normalized = path.replace(/^\/|\/$/g, "");
8
+ return { pattern: new RegExp(`^${normalized}/`), name };
9
+ }
10
+ export function parseGroupText(text) {
11
+ return text
12
+ .split("\n")
13
+ .map((line) => line.trim())
14
+ .filter((line) => line && !line.startsWith("#"))
15
+ .map((line) => {
16
+ const [path, name] = line.split("=>").map((s) => s.trim());
17
+ return toGroupSpec(path, name);
18
+ });
19
+ }
20
+ export const parseGroupFile = parseGroupText;
21
+ export function parseGroupJSON(text) {
22
+ const obj = JSON.parse(text);
23
+ return Object.entries(obj).map(([path, name]) => toGroupSpec(path, name));
24
+ }
25
+ export function parseGroupMarkdown(text) {
26
+ return text
27
+ .split("\n")
28
+ .map((line) => line.trim())
29
+ .filter((line) => line.startsWith("|") && !line.includes("---"))
30
+ .slice(1) // skip header row
31
+ .map((line) => {
32
+ const cols = line.split("|").map((c) => c.trim()).filter(Boolean);
33
+ return toGroupSpec(cols[0], cols[1]);
34
+ });
35
+ }
36
+ export function parseGroupConfig(filePath) {
37
+ const text = readFileSync(filePath, "utf-8");
38
+ const ext = extname(filePath).toLowerCase();
39
+ switch (ext) {
40
+ case ".json": return parseGroupJSON(text);
41
+ case ".md": return parseGroupMarkdown(text);
42
+ default: return parseGroupText(text);
43
+ }
44
+ }
45
+ export function applyGrouping(data, specs) {
46
+ const result = [];
47
+ for (const mod of data) {
48
+ for (const spec of specs) {
49
+ if (spec.pattern.test(mod.entity)) {
50
+ result.push({ ...mod, entity: spec.name });
51
+ break;
52
+ }
53
+ }
54
+ }
55
+ return result;
56
+ }
57
+ //# sourceMappingURL=grouper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grouper.js","sourceRoot":"","sources":["../../src/transforms/grouper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { Modification } from "../parsers/types";
2
+ export declare function parseTeamCSV(csvText: string): Map<string, string>;
3
+ export declare const parseTeamMap: typeof parseTeamCSV;
4
+ export declare function parseTeamJSON(text: string): Map<string, string>;
5
+ export declare function parseTeamMarkdown(text: string): Map<string, string>;
6
+ export declare function parseTeamConfig(filePath: string): Map<string, string>;
7
+ export declare function applyTeamMapping(data: Modification[], teamMap: Map<string, string>): Modification[];
@@ -0,0 +1,51 @@
1
+ import { readFileSync } from "fs";
2
+ import { extname } from "path";
3
+ export function parseTeamCSV(csvText) {
4
+ const map = new Map();
5
+ for (const line of csvText.split("\n")) {
6
+ const trimmed = line.trim();
7
+ if (!trimmed || trimmed.startsWith("author"))
8
+ continue;
9
+ const commaIdx = trimmed.indexOf(",");
10
+ if (commaIdx > 0) {
11
+ map.set(trimmed.slice(0, commaIdx).trim(), trimmed.slice(commaIdx + 1).trim());
12
+ }
13
+ }
14
+ return map;
15
+ }
16
+ export const parseTeamMap = parseTeamCSV;
17
+ export function parseTeamJSON(text) {
18
+ const obj = JSON.parse(text);
19
+ return new Map(Object.entries(obj));
20
+ }
21
+ export function parseTeamMarkdown(text) {
22
+ const map = new Map();
23
+ const dataRows = text
24
+ .split("\n")
25
+ .map((line) => line.trim())
26
+ .filter((line) => line.startsWith("|") && !line.includes("---"))
27
+ .slice(1); // skip header row
28
+ for (const row of dataRows) {
29
+ const cols = row.split("|").map((c) => c.trim()).filter(Boolean);
30
+ if (cols.length >= 2) {
31
+ map.set(cols[0], cols[1]);
32
+ }
33
+ }
34
+ return map;
35
+ }
36
+ export function parseTeamConfig(filePath) {
37
+ const text = readFileSync(filePath, "utf-8");
38
+ const ext = extname(filePath).toLowerCase();
39
+ switch (ext) {
40
+ case ".json": return parseTeamJSON(text);
41
+ case ".md": return parseTeamMarkdown(text);
42
+ default: return parseTeamCSV(text);
43
+ }
44
+ }
45
+ export function applyTeamMapping(data, teamMap) {
46
+ return data.map((mod) => {
47
+ const team = teamMap.get(mod.author);
48
+ return team ? { ...mod, author: team } : mod;
49
+ });
50
+ }
51
+ //# sourceMappingURL=team-mapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"team-mapper.js","sourceRoot":"","sources":["../../src/transforms/team-mapper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { Modification } from "../parsers/types";
2
+ export declare function applyTemporalGrouping(data: Modification[], periodDays: number): Modification[];
@@ -0,0 +1,42 @@
1
+ export function applyTemporalGrouping(data, periodDays) {
2
+ if (data.length === 0)
3
+ return [];
4
+ const sorted = [...data].sort((a, b) => a.date.localeCompare(b.date));
5
+ const startDate = new Date(sorted[0].date);
6
+ const endDate = new Date(sorted[sorted.length - 1].date);
7
+ const byDate = new Map();
8
+ for (const mod of sorted) {
9
+ const existing = byDate.get(mod.date) ?? [];
10
+ existing.push(mod);
11
+ byDate.set(mod.date, existing);
12
+ }
13
+ const result = [];
14
+ const current = new Date(startDate);
15
+ while (current <= endDate) {
16
+ const windowEnd = new Date(current);
17
+ windowEnd.setDate(windowEnd.getDate() + periodDays - 1);
18
+ const latestDate = windowEnd > endDate ? endDate : windowEnd;
19
+ const entities = new Set();
20
+ const windowMods = [];
21
+ const d = new Date(current);
22
+ while (d <= latestDate && d <= endDate) {
23
+ const dateStr = d.toISOString().slice(0, 10);
24
+ const mods = byDate.get(dateStr) ?? [];
25
+ for (const mod of mods) {
26
+ if (!entities.has(mod.entity)) {
27
+ entities.add(mod.entity);
28
+ windowMods.push({
29
+ ...mod,
30
+ rev: latestDate.toISOString().slice(0, 10),
31
+ });
32
+ }
33
+ }
34
+ d.setDate(d.getDate() + 1);
35
+ }
36
+ if (windowMods.length > 0)
37
+ result.push(...windowMods);
38
+ current.setDate(current.getDate() + 1);
39
+ }
40
+ return result;
41
+ }
42
+ //# sourceMappingURL=temporal-grouper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"temporal-grouper.js","sourceRoot":"","sources":["../../src/transforms/temporal-grouper.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,qBAAqB,CACnC,IAAoB,EACpB,UAAkB;IAElB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEjC,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACtE,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAEzD,MAAM,MAAM,GAAG,IAAI,GAAG,EAA0B,CAAC;IACjD,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5C,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACjC,CAAC;IAED,MAAM,MAAM,GAAmB,EAAE,CAAC;IAClC,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC;IAEpC,OAAO,OAAO,IAAI,OAAO,EAAE,CAAC;QAC1B,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC;QACpC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC;QACxD,MAAM,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;QAE7D,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;QACnC,MAAM,UAAU,GAAmB,EAAE,CAAC;QACtC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC;QAC5B,OAAO,CAAC,IAAI,UAAU,IAAI,CAAC,IAAI,OAAO,EAAE,CAAC;YACvC,MAAM,OAAO,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC7C,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YACvC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC9B,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;oBACzB,UAAU,CAAC,IAAI,CAAC;wBACd,GAAG,GAAG;wBACN,GAAG,EAAE,UAAU,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;qBAC3C,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YACD,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;QAC7B,CAAC;QACD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,CAAC;QACtD,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function groupBy<T>(data: T[], key: keyof T & string): Map<T[keyof T], T[]>;
2
+ export declare function orderBy<T>(data: T[], key: keyof T & string, direction?: "asc" | "desc"): T[];
@@ -0,0 +1,34 @@
1
+ export function groupBy(data, key) {
2
+ const map = new Map();
3
+ for (const item of data) {
4
+ const k = item[key];
5
+ const group = map.get(k);
6
+ if (group) {
7
+ group.push(item);
8
+ }
9
+ else {
10
+ map.set(k, [item]);
11
+ }
12
+ }
13
+ return map;
14
+ }
15
+ export function orderBy(data, key, direction = "desc") {
16
+ const sorted = [...data];
17
+ sorted.sort((a, b) => {
18
+ const va = a[key];
19
+ const vb = b[key];
20
+ const cmp = direction === "desc" ? vb - va : va - vb;
21
+ if (cmp !== 0)
22
+ return cmp;
23
+ // Stable tie-break: sort alphabetically by first string field
24
+ const strKey = Object.keys(a).find((k) => typeof a[k] === "string");
25
+ if (strKey) {
26
+ const sa = a[strKey];
27
+ const sb = b[strKey];
28
+ return sa.localeCompare(sb);
29
+ }
30
+ return 0;
31
+ });
32
+ return sorted;
33
+ }
34
+ //# sourceMappingURL=dataset.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dataset.js","sourceRoot":"","sources":["../../src/utils/dataset.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,OAAO,CACrB,IAAS,EACT,GAAqB;IAErB,MAAM,GAAG,GAAG,IAAI,GAAG,EAAmB,CAAC;IACvC,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QACpB,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,OAAO,CACrB,IAAS,EACT,GAAqB,EACrB,YAA4B,MAAM;IAElC,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IACzB,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACnB,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAW,CAAC;QAC5B,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAW,CAAC;QAC5B,MAAM,GAAG,GAAG,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC;QACrD,IAAI,GAAG,KAAK,CAAC;YAAE,OAAO,GAAG,CAAC;QAC1B,8DAA8D;QAC9D,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAA4B,CAAC,CAAC,IAAI,CAC3D,CAAC,CAAC,EAAE,EAAE,CAAC,OAAQ,CAA6B,CAAC,CAAC,CAAC,KAAK,QAAQ,CAC7D,CAAC;QACF,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,EAAE,GAAI,CAA6B,CAAC,MAAM,CAAW,CAAC;YAC5D,MAAM,EAAE,GAAI,CAA6B,CAAC,MAAM,CAAW,CAAC;YAC5D,OAAO,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC"}