@metamask-previews/tooling-insight 1.0.1-preview-898fae5

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 (108) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/LICENSE +21 -0
  3. package/README.md +134 -0
  4. package/dist/daily-anonymizer.cjs +8 -0
  5. package/dist/daily-anonymizer.cjs.map +1 -0
  6. package/dist/daily-anonymizer.d.cts +3 -0
  7. package/dist/daily-anonymizer.d.cts.map +1 -0
  8. package/dist/daily-anonymizer.d.mts +3 -0
  9. package/dist/daily-anonymizer.d.mts.map +1 -0
  10. package/dist/daily-anonymizer.mjs +6 -0
  11. package/dist/daily-anonymizer.mjs.map +1 -0
  12. package/dist/index.cjs +6 -0
  13. package/dist/index.cjs.map +1 -0
  14. package/dist/index.d.cts +4 -0
  15. package/dist/index.d.cts.map +1 -0
  16. package/dist/index.d.mts +4 -0
  17. package/dist/index.d.mts.map +1 -0
  18. package/dist/index.mjs +2 -0
  19. package/dist/index.mjs.map +1 -0
  20. package/dist/lib/allowlist.cjs +159 -0
  21. package/dist/lib/allowlist.cjs.map +1 -0
  22. package/dist/lib/allowlist.d.cts +31 -0
  23. package/dist/lib/allowlist.d.cts.map +1 -0
  24. package/dist/lib/allowlist.d.mts +31 -0
  25. package/dist/lib/allowlist.d.mts.map +1 -0
  26. package/dist/lib/allowlist.mjs +155 -0
  27. package/dist/lib/allowlist.mjs.map +1 -0
  28. package/dist/lib/csv.cjs +152 -0
  29. package/dist/lib/csv.cjs.map +1 -0
  30. package/dist/lib/csv.d.cts +16 -0
  31. package/dist/lib/csv.d.cts.map +1 -0
  32. package/dist/lib/csv.d.mts +16 -0
  33. package/dist/lib/csv.d.mts.map +1 -0
  34. package/dist/lib/csv.mjs +149 -0
  35. package/dist/lib/csv.mjs.map +1 -0
  36. package/dist/lib/exposition.cjs +102 -0
  37. package/dist/lib/exposition.cjs.map +1 -0
  38. package/dist/lib/exposition.d.cts +9 -0
  39. package/dist/lib/exposition.d.cts.map +1 -0
  40. package/dist/lib/exposition.d.mts +9 -0
  41. package/dist/lib/exposition.d.mts.map +1 -0
  42. package/dist/lib/exposition.mjs +99 -0
  43. package/dist/lib/exposition.mjs.map +1 -0
  44. package/dist/lib/fold.cjs +294 -0
  45. package/dist/lib/fold.cjs.map +1 -0
  46. package/dist/lib/fold.d.cts +32 -0
  47. package/dist/lib/fold.d.cts.map +1 -0
  48. package/dist/lib/fold.d.mts +32 -0
  49. package/dist/lib/fold.d.mts.map +1 -0
  50. package/dist/lib/fold.mjs +288 -0
  51. package/dist/lib/fold.mjs.map +1 -0
  52. package/dist/lib/log.cjs +116 -0
  53. package/dist/lib/log.cjs.map +1 -0
  54. package/dist/lib/log.d.cts +32 -0
  55. package/dist/lib/log.d.cts.map +1 -0
  56. package/dist/lib/log.d.mts +32 -0
  57. package/dist/lib/log.d.mts.map +1 -0
  58. package/dist/lib/log.mjs +113 -0
  59. package/dist/lib/log.mjs.map +1 -0
  60. package/dist/lib/paths.cjs +91 -0
  61. package/dist/lib/paths.cjs.map +1 -0
  62. package/dist/lib/paths.d.cts +45 -0
  63. package/dist/lib/paths.d.cts.map +1 -0
  64. package/dist/lib/paths.d.mts +45 -0
  65. package/dist/lib/paths.d.mts.map +1 -0
  66. package/dist/lib/paths.mjs +82 -0
  67. package/dist/lib/paths.mjs.map +1 -0
  68. package/dist/lib/push.cjs +122 -0
  69. package/dist/lib/push.cjs.map +1 -0
  70. package/dist/lib/push.d.cts +58 -0
  71. package/dist/lib/push.d.cts.map +1 -0
  72. package/dist/lib/push.d.mts +58 -0
  73. package/dist/lib/push.d.mts.map +1 -0
  74. package/dist/lib/push.mjs +116 -0
  75. package/dist/lib/push.mjs.map +1 -0
  76. package/dist/lib/remoteWrite.cjs +177 -0
  77. package/dist/lib/remoteWrite.cjs.map +1 -0
  78. package/dist/lib/remoteWrite.d.cts +24 -0
  79. package/dist/lib/remoteWrite.d.cts.map +1 -0
  80. package/dist/lib/remoteWrite.d.mts +24 -0
  81. package/dist/lib/remoteWrite.d.mts.map +1 -0
  82. package/dist/lib/remoteWrite.mjs +172 -0
  83. package/dist/lib/remoteWrite.mjs.map +1 -0
  84. package/dist/lib/state.cjs +100 -0
  85. package/dist/lib/state.cjs.map +1 -0
  86. package/dist/lib/state.d.cts +28 -0
  87. package/dist/lib/state.d.cts.map +1 -0
  88. package/dist/lib/state.d.mts +28 -0
  89. package/dist/lib/state.d.mts.map +1 -0
  90. package/dist/lib/state.mjs +95 -0
  91. package/dist/lib/state.mjs.map +1 -0
  92. package/dist/lib/types.cjs +3 -0
  93. package/dist/lib/types.cjs.map +1 -0
  94. package/dist/lib/types.d.cts +82 -0
  95. package/dist/lib/types.d.cts.map +1 -0
  96. package/dist/lib/types.d.mts +82 -0
  97. package/dist/lib/types.d.mts.map +1 -0
  98. package/dist/lib/types.mjs +2 -0
  99. package/dist/lib/types.mjs.map +1 -0
  100. package/dist/run.cjs +137 -0
  101. package/dist/run.cjs.map +1 -0
  102. package/dist/run.d.cts +20 -0
  103. package/dist/run.d.cts.map +1 -0
  104. package/dist/run.d.mts +20 -0
  105. package/dist/run.d.mts.map +1 -0
  106. package/dist/run.mjs +134 -0
  107. package/dist/run.mjs.map +1 -0
  108. package/package.json +100 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,38 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [1.0.1]
11
+
12
+ ### Added
13
+
14
+ - Add preview build functionality to README and implement GitHub Actions workflow
15
+
16
+ ### Changed
17
+
18
+ - Bump the npm_and_yarn group across 1 directory with 6 updates ([#4](https://github.com/MetaMask/experimental-tooling-insight/pull/4))
19
+
20
+ ### Fixed
21
+
22
+ - Clear environment variables for isolated test runs in `run.test.ts`
23
+
24
+ ## [1.0.0]
25
+
26
+ ### Added
27
+
28
+ - Initial implementation of the `metamask-daily-anonymizer` CLI binary ([#1](https://github.com/MetaMask/experimental-tooling-insight/pull/1))
29
+ - Reads local dev-tool event CSV logs from `~/.tool-usage-collection/`
30
+ - Folds raw events into per-day anonymized Prometheus counters
31
+ - Pushes to a Prometheus remote-write endpoint (Mimir) via a hand-rolled protobuf + snappy encoder with no runtime dependencies
32
+ - Supports `--dry-run`, `--force`, `--verbose`, and `--repo-root=<path>` CLI flags
33
+ - Maintains a state file to enforce a 24h push cadence and track the latest pushed day
34
+ - Published under the `alpha` npm dist-tag
35
+
36
+ [Unreleased]: https://github.com/MetaMask/experimental-tooling-insight/compare/v1.0.1...HEAD
37
+ [1.0.1]: https://github.com/MetaMask/experimental-tooling-insight/compare/v1.0.0...v1.0.1
38
+ [1.0.0]: https://github.com/MetaMask/experimental-tooling-insight/releases/tag/v1.0.0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 MetaMask
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,134 @@
1
+ # `@metamask/tooling-insight`
2
+
3
+ Daily anonymizer for MetaMask developer tooling usage metrics. Reads local dev-tool event logs, folds them into per-day anonymized counters, and pushes them to a Prometheus remote-write endpoint. Exposed as the `metamask-daily-anonymizer` CLI binary.
4
+
5
+ ## Installation
6
+
7
+ `yarn add @metamask/tooling-insight`
8
+
9
+ or
10
+
11
+ `npm install @metamask/tooling-insight`
12
+
13
+ ## Usage
14
+
15
+ Run the anonymizer directly:
16
+
17
+ ```bash
18
+ metamask-daily-anonymizer [--dry-run] [--force] [--verbose] [--repo-root=<path>]
19
+ ```
20
+
21
+ | Flag | Description |
22
+ | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
23
+ | `--dry-run` | Print the exposition body without pushing or advancing state. |
24
+ | `--force` | Skip the 24 h cadence check and push regardless. |
25
+ | `--verbose` | Write structured log output to stdout in addition to the log file. |
26
+ | `--repo-root=<path>` | Absolute path to the target repository. Used to resolve the skill/script allowlist and read `.js.env`. Defaults to the nearest `package.json` ancestor of the current directory. |
27
+
28
+ Or import the `run` function programmatically:
29
+
30
+ ```typescript
31
+ import { run } from '@metamask/tooling-insight';
32
+
33
+ await run({ args: ['--dry-run'] });
34
+ ```
35
+
36
+ ## Environment variables
37
+
38
+ The anonymizer reads push credentials from the environment, falling back to a `.js.env` file in the target repository root (shell-sourceable `export KEY="value"` format).
39
+
40
+ | Variable | Description |
41
+ | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
42
+ | `MIMIR_URL` | Full URL of the Mimir remote-write endpoint (e.g. `https://mimir-dev.example.com/api/v1/push`). |
43
+ | `MIMIR_USERNAME` | HTTP Basic auth username. Required for authenticated endpoints (e.g. dev). Omit when access is network-controlled (e.g. prod via Cloudflare WARP). |
44
+ | `MIMIR_PASSWORD` | HTTP Basic auth password. Required for authenticated endpoints (e.g. dev). Omit when access is network-controlled (e.g. prod via Cloudflare WARP). |
45
+ | `TOOL_USAGE_COLLECTION_DIR` | Override the directory where event logs and state are stored. Defaults to `~/.tool-usage-collection/`. |
46
+ | `METAMASK_SKILLS_DIR` | Path to a checked-out copy of the MetaMask public skills repository (used to build the allowlist). |
47
+
48
+ ## API
49
+
50
+ See our documentation:
51
+
52
+ - [Latest published API documentation](https://metamask.github.io/experimental-tooling-insight/latest/)
53
+ - [Latest development API documentation](https://metamask.github.io/experimental-tooling-insight/staging/)
54
+
55
+ ## Contributing
56
+
57
+ ### Setup
58
+
59
+ - Install the current LTS version of [Node.js](https://nodejs.org)
60
+ - If you are using [nvm](https://github.com/creationix/nvm#installation) (recommended) running `nvm install` will install the latest version and running `nvm use` will automatically choose the right node version for you.
61
+ - Install [Yarn](https://yarnpkg.com) v4 via [Corepack](https://github.com/nodejs/corepack?tab=readme-ov-file#how-to-install)
62
+ - Run `yarn install` to install dependencies and run any required post-install scripts
63
+
64
+ ### Testing and Linting
65
+
66
+ Run `yarn test` to run the tests once. To run tests on file changes, run `yarn test:watch`.
67
+
68
+ Run `yarn lint` to run the linter, or run `yarn lint:fix` to run the linter and fix any automatically fixable issues.
69
+
70
+ ### Release & Publishing
71
+
72
+ The project follows the same release process as the other libraries in the MetaMask organization. The GitHub Actions [`action-create-release-pr`](https://github.com/MetaMask/action-create-release-pr) and [`action-publish-release`](https://github.com/MetaMask/action-publish-release) are used to automate the release process; see those repositories for more information about how they work.
73
+
74
+ 1. Choose a release version.
75
+
76
+ 2. Trigger the [`workflow_dispatch`](https://docs.github.com/en/actions/reference/events-that-trigger-workflows#workflow_dispatch) event [manually](https://docs.github.com/en/actions/managing-workflow-runs/manually-running-a-workflow) for the `Create Release Pull Request` action to create the release PR.
77
+
78
+ 3. Update the changelog to move each change entry into the appropriate change category ([see here](https://keepachangelog.com/en/1.0.0/#types) for the full list of change categories), and edit them to be more easily understood by users of the package.
79
+
80
+ 4. Review and QA the release.
81
+
82
+ 5. Squash & Merge the release PR.
83
+
84
+ 6. Approve the `publish-npm` job (or ask somebody on the npm publishers team to approve it for you).
85
+
86
+ ### Testing changes in other projects using preview builds
87
+
88
+ If you are working on a pull request and want to test changes in another project before publishing, you can create a _preview build_ and configure your project to use it.
89
+
90
+ #### Creating a preview build
91
+
92
+ 1. Open the pull request you want to test.
93
+ 2. Post a comment with the exact text `@metamaskbot publish-preview`.
94
+ 3. The `publish-preview` workflow reacts to the comment with a +1, then runs and posts a follow-up comment containing the install identifier.
95
+
96
+ Two things to note about preview builds:
97
+
98
+ - The package name is scoped to `@metamask-previews` instead of `@metamask` (e.g. `@metamask-previews/tooling-insight`).
99
+ - The short SHA of the last commit is appended to the version (e.g. `1.0.0-preview-e2df9b4` instead of `1.0.0`).
100
+
101
+ Comments on PRs from forks are intentionally skipped — the token used to publish is never exposed to forked repositories.
102
+
103
+ #### Using a preview build
104
+
105
+ To use a preview build in a project, override the resolution logic so the production version is replaced by the preview version:
106
+
107
+ 1. Open `package.json` in the consuming project and find the entry for `@metamask/tooling-insight` in `dependencies`.
108
+ 2. Locate the resolution overrides section (create it if it doesn't exist). For Yarn this is `resolutions`; for npm it is `overrides`.
109
+ 3. Add an entry pointing to the preview version. Examples:
110
+
111
+ Yarn Modern (`resolutions`):
112
+
113
+ ```json
114
+ "@metamask/tooling-insight@^1.0.0": "npm:@metamask-previews/tooling-insight@1.0.0-preview-e2df9b4"
115
+ ```
116
+
117
+ Yarn Classic (`resolutions`):
118
+
119
+ ```json
120
+ "@metamask/tooling-insight": "npm:@metamask-previews/tooling-insight@1.0.0-preview-e2df9b4"
121
+ ```
122
+
123
+ npm (`overrides`):
124
+
125
+ ```json
126
+ "@metamask/tooling-insight": "npm:@metamask-previews/tooling-insight@1.0.0-preview-e2df9b4"
127
+ ```
128
+
129
+ 4. Run `yarn install`.
130
+
131
+ #### Updating a preview build
132
+
133
+ 1. Post another `@metamaskbot publish-preview` comment on the pull request and wait for the follow-up comment with the new identifier.
134
+ 2. Update the pinned version in the consuming project's `package.json` and re-run `yarn install`.
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const run_1 = require("./run.cjs");
5
+ (0, run_1.run)().catch(() => {
6
+ process.exitCode = 1;
7
+ });
8
+ //# sourceMappingURL=daily-anonymizer.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daily-anonymizer.cjs","sourceRoot":"","sources":["../src/daily-anonymizer.ts"],"names":[],"mappings":";;;AACA,mCAA4B;AAE5B,IAAA,SAAG,GAAE,CAAC,KAAK,CAAC,GAAG,EAAE;IACf,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\nimport { run } from './run';\n\nrun().catch(() => {\n process.exitCode = 1;\n});\n"]}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=daily-anonymizer.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daily-anonymizer.d.cts","sourceRoot":"","sources":["../src/daily-anonymizer.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=daily-anonymizer.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daily-anonymizer.d.mts","sourceRoot":"","sources":["../src/daily-anonymizer.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ import { run } from "./run.mjs";
3
+ run().catch(() => {
4
+ process.exitCode = 1;
5
+ });
6
+ //# sourceMappingURL=daily-anonymizer.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daily-anonymizer.mjs","sourceRoot":"","sources":["../src/daily-anonymizer.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,kBAAc;AAE5B,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;IACf,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\nimport { run } from './run';\n\nrun().catch(() => {\n process.exitCode = 1;\n});\n"]}
package/dist/index.cjs ADDED
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.run = void 0;
4
+ var run_1 = require("./run.cjs");
5
+ Object.defineProperty(exports, "run", { enumerable: true, get: function () { return run_1.run; } });
6
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,iCAA4B;AAAnB,0FAAA,GAAG,OAAA","sourcesContent":["export { run } from './run';\nexport type { RunOptions } from './run';\nexport type {\n AnonymizerState,\n Allowlist,\n CsvEventType,\n EventTypeLabel,\n MetricName,\n SampleLabels,\n SamplePoint,\n ToolEvent,\n ToolType,\n} from './lib/types';\n"]}
@@ -0,0 +1,4 @@
1
+ export { run } from "./run.cjs";
2
+ export type { RunOptions } from "./run.cjs";
3
+ export type { AnonymizerState, Allowlist, CsvEventType, EventTypeLabel, MetricName, SampleLabels, SamplePoint, ToolEvent, ToolType, } from "./lib/types.cjs";
4
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,kBAAc;AAC5B,YAAY,EAAE,UAAU,EAAE,kBAAc;AACxC,YAAY,EACV,eAAe,EACf,SAAS,EACT,YAAY,EACZ,cAAc,EACd,UAAU,EACV,YAAY,EACZ,WAAW,EACX,SAAS,EACT,QAAQ,GACT,wBAAoB"}
@@ -0,0 +1,4 @@
1
+ export { run } from "./run.mjs";
2
+ export type { RunOptions } from "./run.mjs";
3
+ export type { AnonymizerState, Allowlist, CsvEventType, EventTypeLabel, MetricName, SampleLabels, SamplePoint, ToolEvent, ToolType, } from "./lib/types.mjs";
4
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,kBAAc;AAC5B,YAAY,EAAE,UAAU,EAAE,kBAAc;AACxC,YAAY,EACV,eAAe,EACf,SAAS,EACT,YAAY,EACZ,cAAc,EACd,UAAU,EACV,YAAY,EACZ,WAAW,EACX,SAAS,EACT,QAAQ,GACT,wBAAoB"}
package/dist/index.mjs ADDED
@@ -0,0 +1,2 @@
1
+ export { run } from "./run.mjs";
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,kBAAc","sourcesContent":["export { run } from './run';\nexport type { RunOptions } from './run';\nexport type {\n AnonymizerState,\n Allowlist,\n CsvEventType,\n EventTypeLabel,\n MetricName,\n SampleLabels,\n SamplePoint,\n ToolEvent,\n ToolType,\n} from './lib/types';\n"]}
@@ -0,0 +1,159 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.findRepoRoot = findRepoRoot;
4
+ exports.readAllowlist = readAllowlist;
5
+ const node_child_process_1 = require("node:child_process");
6
+ const node_fs_1 = require("node:fs");
7
+ const node_path_1 = require("node:path");
8
+ const ENV_METAMASK_SKILLS_DIR = 'METAMASK_SKILLS_DIR';
9
+ const ENV_CONSENSYS_SKILLS_DIR = 'CONSENSYS_SKILLS_DIR';
10
+ /**
11
+ * Thin wrapper around `execFileSync` used as the default git executor.
12
+ *
13
+ * @param file - The git executable path.
14
+ * @param args - Arguments to pass to git.
15
+ * @param options - Execution options including cwd and encoding.
16
+ * @param options.cwd - Optional working directory for the git command.
17
+ * @param options.encoding - Output encoding; must be `'utf8'`.
18
+ * @returns The stdout of the git command as a UTF-8 string.
19
+ */
20
+ function defaultExecGit(file, args, options) {
21
+ return (0, node_child_process_1.execFileSync)(file, args, options);
22
+ }
23
+ /**
24
+ * Walk up from `startDir` until a directory containing `package.json` is found.
25
+ *
26
+ * @param startDir - Directory to start the search from.
27
+ * @returns The repo root directory, or `startDir` if no `package.json` is found.
28
+ */
29
+ function findRepoRoot(startDir) {
30
+ let current = startDir;
31
+ while (true) {
32
+ if ((0, node_fs_1.existsSync)((0, node_path_1.join)(current, 'package.json'))) {
33
+ return current;
34
+ }
35
+ const parent = (0, node_path_1.join)(current, '..');
36
+ if (parent === current) {
37
+ return startDir;
38
+ }
39
+ current = parent;
40
+ }
41
+ }
42
+ /**
43
+ * Parse the `.skills.local` key-value override file in the repo root.
44
+ *
45
+ * @param repoRoot - Absolute path to the repo root containing `.skills.local`.
46
+ * @returns A map of key-value pairs from the local skills override file.
47
+ */
48
+ function parseSkillsLocal(repoRoot) {
49
+ const path = (0, node_path_1.join)(repoRoot, '.skills.local');
50
+ if (!(0, node_fs_1.existsSync)(path)) {
51
+ return {};
52
+ }
53
+ const entries = {};
54
+ for (const line of (0, node_fs_1.readFileSync)(path, 'utf8').split('\n')) {
55
+ const trimmed = line.trim();
56
+ if (!trimmed || trimmed.startsWith('#')) {
57
+ continue;
58
+ }
59
+ const eq = trimmed.indexOf('=');
60
+ if (eq === -1) {
61
+ continue;
62
+ }
63
+ entries[trimmed.slice(0, eq).trim()] = trimmed.slice(eq + 1).trim();
64
+ }
65
+ return entries;
66
+ }
67
+ /**
68
+ * Resolve the absolute path for a skills directory from multiple sources in priority order:
69
+ * environment variable → `.skills.local` key → cached directory.
70
+ *
71
+ * @param envKey - Environment variable name to check first.
72
+ * @param skillsLocalKey - Key to look up in `.skills.local`.
73
+ * @param repoRoot - Repo root for `.skills.local` and fallback resolution.
74
+ * @param defaultRelative - Optional relative path to a cached skills directory under the repo root.
75
+ * @returns Absolute path to the skills directory, or `null` if unresolvable.
76
+ */
77
+ function resolveSkillsDir(envKey, skillsLocalKey, repoRoot, defaultRelative) {
78
+ if (process.env[envKey]) {
79
+ return process.env[envKey];
80
+ }
81
+ const local = parseSkillsLocal(repoRoot)[skillsLocalKey];
82
+ if (local) {
83
+ return local;
84
+ }
85
+ if (defaultRelative) {
86
+ const cached = (0, node_path_1.join)(repoRoot, defaultRelative);
87
+ if ((0, node_fs_1.existsSync)(cached)) {
88
+ return cached;
89
+ }
90
+ }
91
+ return null;
92
+ }
93
+ /**
94
+ * Extract skill names from `git ls-tree` output by matching the `skill.md` path pattern.
95
+ *
96
+ * @param gitOutput - Raw `ls-tree` output from git.
97
+ * @returns An array of skill names prefixed with `mms-`.
98
+ */
99
+ function extractSkillNames(gitOutput) {
100
+ const names = [];
101
+ for (const line of gitOutput.split('\n')) {
102
+ const match = line.match(/^domains\/[^/]+\/skills\/([^/]+)\/skill\.md$/u);
103
+ if (match) {
104
+ names.push(`mms-${match[1]}`);
105
+ }
106
+ }
107
+ return names;
108
+ }
109
+ /**
110
+ * List skill names by running `git ls-tree` against the skills git repository.
111
+ *
112
+ * @param dir - Absolute path to the skills git repository.
113
+ * @param execGit - Git executor function.
114
+ * @returns An array of skill names found in the skills repository.
115
+ */
116
+ function readSkillsFromDir(dir, execGit) {
117
+ const output = execGit('git', ['-C', dir, 'ls-tree', '-r', '--name-only', 'main', '--', 'domains'], { encoding: 'utf8' });
118
+ return extractSkillNames(output);
119
+ }
120
+ /**
121
+ * Read yarn script names from the consuming repo's `main` branch `package.json`.
122
+ *
123
+ * @param repoRoot - Absolute path to the consuming repo root.
124
+ * @param execGit - Git executor function.
125
+ * @returns An array of yarn script names from the consuming repo's main branch.
126
+ */
127
+ function readYarnScripts(repoRoot, execGit) {
128
+ const output = execGit('git', ['show', 'main:package.json'], {
129
+ cwd: repoRoot,
130
+ encoding: 'utf8',
131
+ });
132
+ const parsed = JSON.parse(output);
133
+ return Object.keys(parsed.scripts ?? {});
134
+ }
135
+ /**
136
+ * Read skill and yarn-script allowlists from local git refs.
137
+ * Private skills repo is optional; public skills + package.json scripts are required.
138
+ *
139
+ * @param options - Optional overrides for repo root and git executor.
140
+ * @returns The combined allowlist of skill names and yarn script names.
141
+ */
142
+ function readAllowlist(options = {}) {
143
+ const repoRoot = options.repoRoot ?? findRepoRoot(process.cwd());
144
+ const execGit = options.execGit ?? defaultExecGit;
145
+ const publicDir = resolveSkillsDir(ENV_METAMASK_SKILLS_DIR, 'METAMASK_SKILLS_DIR', repoRoot, '.skills-cache/metamask-skills');
146
+ if (!publicDir) {
147
+ throw new Error('MetaMask skills source directory could not be resolved');
148
+ }
149
+ const privateDir = resolveSkillsDir(ENV_CONSENSYS_SKILLS_DIR, 'CONSENSYS_SKILLS_DIR', repoRoot);
150
+ const skills = new Set(readSkillsFromDir(publicDir, execGit));
151
+ if (privateDir) {
152
+ for (const name of readSkillsFromDir(privateDir, execGit)) {
153
+ skills.add(name);
154
+ }
155
+ }
156
+ const scripts = new Set(readYarnScripts(repoRoot, execGit));
157
+ return { skills, scripts };
158
+ }
159
+ //# sourceMappingURL=allowlist.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"allowlist.cjs","sourceRoot":"","sources":["../../src/lib/allowlist.ts"],"names":[],"mappings":"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","sourcesContent":["import { execFileSync } from 'node:child_process';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport type { Allowlist } from './types';\n\nconst ENV_METAMASK_SKILLS_DIR = 'METAMASK_SKILLS_DIR';\nconst ENV_CONSENSYS_SKILLS_DIR = 'CONSENSYS_SKILLS_DIR';\n\n/** Signature of the git executor passed to allowlist readers, matching `execFileSync`. */\nexport type ExecGit = (\n file: string,\n args: readonly string[],\n options: {\n /** Optional working directory for the git command. */\n cwd?: string;\n /** Output encoding; must be `'utf8'`. */\n encoding: 'utf8';\n },\n) => string;\n\n/** Options for `readAllowlist`. */\nexport type AllowlistOptions = {\n /** Absolute path to the repo root; defaults to `findRepoRoot(process.cwd())`. */\n repoRoot?: string;\n /** Git executor; defaults to the real `execFileSync` wrapper. */\n execGit?: ExecGit;\n};\n\n/**\n * Thin wrapper around `execFileSync` used as the default git executor.\n *\n * @param file - The git executable path.\n * @param args - Arguments to pass to git.\n * @param options - Execution options including cwd and encoding.\n * @param options.cwd - Optional working directory for the git command.\n * @param options.encoding - Output encoding; must be `'utf8'`.\n * @returns The stdout of the git command as a UTF-8 string.\n */\nfunction defaultExecGit(\n file: string,\n args: readonly string[],\n options: {\n /** Optional working directory for the git command. */\n cwd?: string;\n /** Output encoding; must be `'utf8'`. */\n encoding: 'utf8';\n },\n): string {\n return execFileSync(file, args, options);\n}\n\n/**\n * Walk up from `startDir` until a directory containing `package.json` is found.\n *\n * @param startDir - Directory to start the search from.\n * @returns The repo root directory, or `startDir` if no `package.json` is found.\n */\nexport function findRepoRoot(startDir: string): string {\n let current = startDir;\n while (true) {\n if (existsSync(join(current, 'package.json'))) {\n return current;\n }\n const parent = join(current, '..');\n if (parent === current) {\n return startDir;\n }\n current = parent;\n }\n}\n\n/**\n * Parse the `.skills.local` key-value override file in the repo root.\n *\n * @param repoRoot - Absolute path to the repo root containing `.skills.local`.\n * @returns A map of key-value pairs from the local skills override file.\n */\nfunction parseSkillsLocal(repoRoot: string): Record<string, string> {\n const path = join(repoRoot, '.skills.local');\n if (!existsSync(path)) {\n return {};\n }\n const entries: Record<string, string> = {};\n for (const line of readFileSync(path, 'utf8').split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) {\n continue;\n }\n const eq = trimmed.indexOf('=');\n if (eq === -1) {\n continue;\n }\n entries[trimmed.slice(0, eq).trim()] = trimmed.slice(eq + 1).trim();\n }\n return entries;\n}\n\n/**\n * Resolve the absolute path for a skills directory from multiple sources in priority order:\n * environment variable → `.skills.local` key → cached directory.\n *\n * @param envKey - Environment variable name to check first.\n * @param skillsLocalKey - Key to look up in `.skills.local`.\n * @param repoRoot - Repo root for `.skills.local` and fallback resolution.\n * @param defaultRelative - Optional relative path to a cached skills directory under the repo root.\n * @returns Absolute path to the skills directory, or `null` if unresolvable.\n */\nfunction resolveSkillsDir(\n envKey: string,\n skillsLocalKey: string,\n repoRoot: string,\n defaultRelative?: string,\n): string | null {\n if (process.env[envKey]) {\n return process.env[envKey];\n }\n const local = parseSkillsLocal(repoRoot)[skillsLocalKey];\n if (local) {\n return local;\n }\n if (defaultRelative) {\n const cached = join(repoRoot, defaultRelative);\n if (existsSync(cached)) {\n return cached;\n }\n }\n return null;\n}\n\n/**\n * Extract skill names from `git ls-tree` output by matching the `skill.md` path pattern.\n *\n * @param gitOutput - Raw `ls-tree` output from git.\n * @returns An array of skill names prefixed with `mms-`.\n */\nfunction extractSkillNames(gitOutput: string): string[] {\n const names: string[] = [];\n for (const line of gitOutput.split('\\n')) {\n const match = line.match(/^domains\\/[^/]+\\/skills\\/([^/]+)\\/skill\\.md$/u);\n if (match) {\n names.push(`mms-${match[1]}`);\n }\n }\n return names;\n}\n\n/**\n * List skill names by running `git ls-tree` against the skills git repository.\n *\n * @param dir - Absolute path to the skills git repository.\n * @param execGit - Git executor function.\n * @returns An array of skill names found in the skills repository.\n */\nfunction readSkillsFromDir(dir: string, execGit: ExecGit): string[] {\n const output = execGit(\n 'git',\n ['-C', dir, 'ls-tree', '-r', '--name-only', 'main', '--', 'domains'],\n { encoding: 'utf8' },\n );\n return extractSkillNames(output);\n}\n\n/**\n * Read yarn script names from the consuming repo's `main` branch `package.json`.\n *\n * @param repoRoot - Absolute path to the consuming repo root.\n * @param execGit - Git executor function.\n * @returns An array of yarn script names from the consuming repo's main branch.\n */\nfunction readYarnScripts(repoRoot: string, execGit: ExecGit): string[] {\n const output = execGit('git', ['show', 'main:package.json'], {\n cwd: repoRoot,\n encoding: 'utf8',\n });\n const parsed = JSON.parse(output) as {\n /** Map of yarn script names to their shell commands. */\n scripts?: Record<string, string>;\n };\n return Object.keys(parsed.scripts ?? {});\n}\n\n/**\n * Read skill and yarn-script allowlists from local git refs.\n * Private skills repo is optional; public skills + package.json scripts are required.\n *\n * @param options - Optional overrides for repo root and git executor.\n * @returns The combined allowlist of skill names and yarn script names.\n */\nexport function readAllowlist(options: AllowlistOptions = {}): Allowlist {\n const repoRoot = options.repoRoot ?? findRepoRoot(process.cwd());\n const execGit = options.execGit ?? defaultExecGit;\n\n const publicDir = resolveSkillsDir(\n ENV_METAMASK_SKILLS_DIR,\n 'METAMASK_SKILLS_DIR',\n repoRoot,\n '.skills-cache/metamask-skills',\n );\n if (!publicDir) {\n throw new Error('MetaMask skills source directory could not be resolved');\n }\n\n const privateDir = resolveSkillsDir(\n ENV_CONSENSYS_SKILLS_DIR,\n 'CONSENSYS_SKILLS_DIR',\n repoRoot,\n );\n\n const skills = new Set<string>(readSkillsFromDir(publicDir, execGit));\n if (privateDir) {\n for (const name of readSkillsFromDir(privateDir, execGit)) {\n skills.add(name);\n }\n }\n\n const scripts = new Set<string>(readYarnScripts(repoRoot, execGit));\n\n return { skills, scripts };\n}\n"]}
@@ -0,0 +1,31 @@
1
+ import type { Allowlist } from "./types.cjs";
2
+ /** Signature of the git executor passed to allowlist readers, matching `execFileSync`. */
3
+ export type ExecGit = (file: string, args: readonly string[], options: {
4
+ /** Optional working directory for the git command. */
5
+ cwd?: string;
6
+ /** Output encoding; must be `'utf8'`. */
7
+ encoding: 'utf8';
8
+ }) => string;
9
+ /** Options for `readAllowlist`. */
10
+ export type AllowlistOptions = {
11
+ /** Absolute path to the repo root; defaults to `findRepoRoot(process.cwd())`. */
12
+ repoRoot?: string;
13
+ /** Git executor; defaults to the real `execFileSync` wrapper. */
14
+ execGit?: ExecGit;
15
+ };
16
+ /**
17
+ * Walk up from `startDir` until a directory containing `package.json` is found.
18
+ *
19
+ * @param startDir - Directory to start the search from.
20
+ * @returns The repo root directory, or `startDir` if no `package.json` is found.
21
+ */
22
+ export declare function findRepoRoot(startDir: string): string;
23
+ /**
24
+ * Read skill and yarn-script allowlists from local git refs.
25
+ * Private skills repo is optional; public skills + package.json scripts are required.
26
+ *
27
+ * @param options - Optional overrides for repo root and git executor.
28
+ * @returns The combined allowlist of skill names and yarn script names.
29
+ */
30
+ export declare function readAllowlist(options?: AllowlistOptions): Allowlist;
31
+ //# sourceMappingURL=allowlist.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"allowlist.d.cts","sourceRoot":"","sources":["../../src/lib/allowlist.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAgB;AAKzC,0FAA0F;AAC1F,MAAM,MAAM,OAAO,GAAG,CACpB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,EAAE;IACP,sDAAsD;IACtD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;CAClB,KACE,MAAM,CAAC;AAEZ,mCAAmC;AACnC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,iFAAiF;IACjF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAyBF;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAYrD;AAgHD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE,gBAAqB,GAAG,SAAS,CA8BvE"}
@@ -0,0 +1,31 @@
1
+ import type { Allowlist } from "./types.mjs";
2
+ /** Signature of the git executor passed to allowlist readers, matching `execFileSync`. */
3
+ export type ExecGit = (file: string, args: readonly string[], options: {
4
+ /** Optional working directory for the git command. */
5
+ cwd?: string;
6
+ /** Output encoding; must be `'utf8'`. */
7
+ encoding: 'utf8';
8
+ }) => string;
9
+ /** Options for `readAllowlist`. */
10
+ export type AllowlistOptions = {
11
+ /** Absolute path to the repo root; defaults to `findRepoRoot(process.cwd())`. */
12
+ repoRoot?: string;
13
+ /** Git executor; defaults to the real `execFileSync` wrapper. */
14
+ execGit?: ExecGit;
15
+ };
16
+ /**
17
+ * Walk up from `startDir` until a directory containing `package.json` is found.
18
+ *
19
+ * @param startDir - Directory to start the search from.
20
+ * @returns The repo root directory, or `startDir` if no `package.json` is found.
21
+ */
22
+ export declare function findRepoRoot(startDir: string): string;
23
+ /**
24
+ * Read skill and yarn-script allowlists from local git refs.
25
+ * Private skills repo is optional; public skills + package.json scripts are required.
26
+ *
27
+ * @param options - Optional overrides for repo root and git executor.
28
+ * @returns The combined allowlist of skill names and yarn script names.
29
+ */
30
+ export declare function readAllowlist(options?: AllowlistOptions): Allowlist;
31
+ //# sourceMappingURL=allowlist.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"allowlist.d.mts","sourceRoot":"","sources":["../../src/lib/allowlist.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAgB;AAKzC,0FAA0F;AAC1F,MAAM,MAAM,OAAO,GAAG,CACpB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,EAAE;IACP,sDAAsD;IACtD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;CAClB,KACE,MAAM,CAAC;AAEZ,mCAAmC;AACnC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,iFAAiF;IACjF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAyBF;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAYrD;AAgHD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE,gBAAqB,GAAG,SAAS,CA8BvE"}