@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.
- package/CHANGELOG.md +38 -0
- package/LICENSE +21 -0
- package/README.md +134 -0
- package/dist/daily-anonymizer.cjs +8 -0
- package/dist/daily-anonymizer.cjs.map +1 -0
- package/dist/daily-anonymizer.d.cts +3 -0
- package/dist/daily-anonymizer.d.cts.map +1 -0
- package/dist/daily-anonymizer.d.mts +3 -0
- package/dist/daily-anonymizer.d.mts.map +1 -0
- package/dist/daily-anonymizer.mjs +6 -0
- package/dist/daily-anonymizer.mjs.map +1 -0
- package/dist/index.cjs +6 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +4 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +4 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -0
- package/dist/lib/allowlist.cjs +159 -0
- package/dist/lib/allowlist.cjs.map +1 -0
- package/dist/lib/allowlist.d.cts +31 -0
- package/dist/lib/allowlist.d.cts.map +1 -0
- package/dist/lib/allowlist.d.mts +31 -0
- package/dist/lib/allowlist.d.mts.map +1 -0
- package/dist/lib/allowlist.mjs +155 -0
- package/dist/lib/allowlist.mjs.map +1 -0
- package/dist/lib/csv.cjs +152 -0
- package/dist/lib/csv.cjs.map +1 -0
- package/dist/lib/csv.d.cts +16 -0
- package/dist/lib/csv.d.cts.map +1 -0
- package/dist/lib/csv.d.mts +16 -0
- package/dist/lib/csv.d.mts.map +1 -0
- package/dist/lib/csv.mjs +149 -0
- package/dist/lib/csv.mjs.map +1 -0
- package/dist/lib/exposition.cjs +102 -0
- package/dist/lib/exposition.cjs.map +1 -0
- package/dist/lib/exposition.d.cts +9 -0
- package/dist/lib/exposition.d.cts.map +1 -0
- package/dist/lib/exposition.d.mts +9 -0
- package/dist/lib/exposition.d.mts.map +1 -0
- package/dist/lib/exposition.mjs +99 -0
- package/dist/lib/exposition.mjs.map +1 -0
- package/dist/lib/fold.cjs +294 -0
- package/dist/lib/fold.cjs.map +1 -0
- package/dist/lib/fold.d.cts +32 -0
- package/dist/lib/fold.d.cts.map +1 -0
- package/dist/lib/fold.d.mts +32 -0
- package/dist/lib/fold.d.mts.map +1 -0
- package/dist/lib/fold.mjs +288 -0
- package/dist/lib/fold.mjs.map +1 -0
- package/dist/lib/log.cjs +116 -0
- package/dist/lib/log.cjs.map +1 -0
- package/dist/lib/log.d.cts +32 -0
- package/dist/lib/log.d.cts.map +1 -0
- package/dist/lib/log.d.mts +32 -0
- package/dist/lib/log.d.mts.map +1 -0
- package/dist/lib/log.mjs +113 -0
- package/dist/lib/log.mjs.map +1 -0
- package/dist/lib/paths.cjs +91 -0
- package/dist/lib/paths.cjs.map +1 -0
- package/dist/lib/paths.d.cts +45 -0
- package/dist/lib/paths.d.cts.map +1 -0
- package/dist/lib/paths.d.mts +45 -0
- package/dist/lib/paths.d.mts.map +1 -0
- package/dist/lib/paths.mjs +82 -0
- package/dist/lib/paths.mjs.map +1 -0
- package/dist/lib/push.cjs +122 -0
- package/dist/lib/push.cjs.map +1 -0
- package/dist/lib/push.d.cts +58 -0
- package/dist/lib/push.d.cts.map +1 -0
- package/dist/lib/push.d.mts +58 -0
- package/dist/lib/push.d.mts.map +1 -0
- package/dist/lib/push.mjs +116 -0
- package/dist/lib/push.mjs.map +1 -0
- package/dist/lib/remoteWrite.cjs +177 -0
- package/dist/lib/remoteWrite.cjs.map +1 -0
- package/dist/lib/remoteWrite.d.cts +24 -0
- package/dist/lib/remoteWrite.d.cts.map +1 -0
- package/dist/lib/remoteWrite.d.mts +24 -0
- package/dist/lib/remoteWrite.d.mts.map +1 -0
- package/dist/lib/remoteWrite.mjs +172 -0
- package/dist/lib/remoteWrite.mjs.map +1 -0
- package/dist/lib/state.cjs +100 -0
- package/dist/lib/state.cjs.map +1 -0
- package/dist/lib/state.d.cts +28 -0
- package/dist/lib/state.d.cts.map +1 -0
- package/dist/lib/state.d.mts +28 -0
- package/dist/lib/state.d.mts.map +1 -0
- package/dist/lib/state.mjs +95 -0
- package/dist/lib/state.mjs.map +1 -0
- package/dist/lib/types.cjs +3 -0
- package/dist/lib/types.cjs.map +1 -0
- package/dist/lib/types.d.cts +82 -0
- package/dist/lib/types.d.cts.map +1 -0
- package/dist/lib/types.d.mts +82 -0
- package/dist/lib/types.d.mts.map +1 -0
- package/dist/lib/types.mjs +2 -0
- package/dist/lib/types.mjs.map +1 -0
- package/dist/run.cjs +137 -0
- package/dist/run.cjs.map +1 -0
- package/dist/run.d.cts +20 -0
- package/dist/run.d.cts.map +1 -0
- package/dist/run.d.mts +20 -0
- package/dist/run.d.mts.map +1 -0
- package/dist/run.mjs +134 -0
- package/dist/run.mjs.map +1 -0
- package/package.json +100 -0
package/dist/lib/log.mjs
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
import { getAnonymizerLogPath } from "./paths.mjs";
|
|
4
|
+
const MAX_LOG_BYTES = 1024 * 1024;
|
|
5
|
+
const MAX_ROTATED = 3;
|
|
6
|
+
/**
|
|
7
|
+
* Create the log directory if it does not yet exist.
|
|
8
|
+
*
|
|
9
|
+
* @param path - Absolute path to the log file whose parent directory to create.
|
|
10
|
+
*/
|
|
11
|
+
function ensureLogDir(path) {
|
|
12
|
+
const dir = dirname(path);
|
|
13
|
+
if (!existsSync(dir)) {
|
|
14
|
+
mkdirSync(dir, { recursive: true });
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Rotate the log file when it exceeds 1 MiB.
|
|
19
|
+
*
|
|
20
|
+
* @param path - Absolute path to the log file to rotate.
|
|
21
|
+
*/
|
|
22
|
+
function rotateIfNeeded(path) {
|
|
23
|
+
if (!existsSync(path)) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const { size } = statSync(path);
|
|
27
|
+
if (size <= MAX_LOG_BYTES) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
for (let index = MAX_ROTATED; index >= 1; index -= 1) {
|
|
31
|
+
const from = index === 1 ? path : `${path}.${index - 1}`;
|
|
32
|
+
const to = `${path}.${index}`;
|
|
33
|
+
if (existsSync(from)) {
|
|
34
|
+
if (existsSync(to)) {
|
|
35
|
+
unlinkSync(to);
|
|
36
|
+
}
|
|
37
|
+
renameSync(from, to);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Create a structured logger that appends JSON lines to the anonymizer log file,
|
|
43
|
+
* rotating when the file exceeds 1 MiB.
|
|
44
|
+
*
|
|
45
|
+
* @param cli - The CLI name to embed in every log entry.
|
|
46
|
+
* @param logPath - Path to the log file; defaults to the configured anonymizer log path.
|
|
47
|
+
* @returns An object with `info`, `error`, and `readLog` methods.
|
|
48
|
+
*/
|
|
49
|
+
export function createLogger(cli, logPath = getAnonymizerLogPath()) {
|
|
50
|
+
/**
|
|
51
|
+
* Append an entry to the log file, rotating first when needed.
|
|
52
|
+
*
|
|
53
|
+
* @param entry - The log entry to serialise.
|
|
54
|
+
* @param verbose - When true, also writes to stdout.
|
|
55
|
+
*/
|
|
56
|
+
const write = (entry, verbose) => {
|
|
57
|
+
ensureLogDir(logPath);
|
|
58
|
+
rotateIfNeeded(logPath);
|
|
59
|
+
const line = `${JSON.stringify(entry)}\n`;
|
|
60
|
+
writeFileSync(logPath, line, { flag: 'a' });
|
|
61
|
+
if (verbose) {
|
|
62
|
+
process.stdout.write(line);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
return {
|
|
66
|
+
/**
|
|
67
|
+
* Log an informational message.
|
|
68
|
+
*
|
|
69
|
+
* @param message - The message to log.
|
|
70
|
+
* @param extra - Optional extra data to attach to the log entry.
|
|
71
|
+
* @param verbose - When true, also writes to stdout.
|
|
72
|
+
*/
|
|
73
|
+
info(message, extra, verbose = false) {
|
|
74
|
+
write({
|
|
75
|
+
ts: new Date().toISOString(),
|
|
76
|
+
cli,
|
|
77
|
+
level: 'info',
|
|
78
|
+
message,
|
|
79
|
+
// exactOptionalPropertyTypes: omit the key when undefined rather than
|
|
80
|
+
// assigning undefined to an optional property.
|
|
81
|
+
...(extra === undefined ? {} : { extra }),
|
|
82
|
+
}, verbose);
|
|
83
|
+
},
|
|
84
|
+
/**
|
|
85
|
+
* Log an error message.
|
|
86
|
+
*
|
|
87
|
+
* @param message - The message to log.
|
|
88
|
+
* @param extra - Optional extra data to attach to the log entry.
|
|
89
|
+
* @param verbose - When true, also writes to stdout.
|
|
90
|
+
*/
|
|
91
|
+
error(message, extra, verbose = false) {
|
|
92
|
+
write({
|
|
93
|
+
ts: new Date().toISOString(),
|
|
94
|
+
cli,
|
|
95
|
+
level: 'error',
|
|
96
|
+
message,
|
|
97
|
+
...(extra === undefined ? {} : { extra }),
|
|
98
|
+
}, verbose);
|
|
99
|
+
},
|
|
100
|
+
/**
|
|
101
|
+
* Read the full contents of the log file.
|
|
102
|
+
*
|
|
103
|
+
* @returns The log file contents, or an empty string if the file does not exist.
|
|
104
|
+
*/
|
|
105
|
+
readLog() {
|
|
106
|
+
if (!existsSync(logPath)) {
|
|
107
|
+
return '';
|
|
108
|
+
}
|
|
109
|
+
return readFileSync(logPath, 'utf8');
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=log.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log.mjs","sourceRoot":"","sources":["../../src/lib/log.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n existsSync,\n mkdirSync,\n readFileSync,\n renameSync,\n statSync,\n unlinkSync,\n writeFileSync,\n} from 'node:fs';\nimport { dirname } from 'node:path';\n\nimport { getAnonymizerLogPath } from './paths';\n\n/** One structured log entry written to the anonymizer log file. */\nexport type LogEntry = {\n /** ISO-8601 timestamp of when the entry was written. */\n ts: string;\n /** The CLI name that produced the entry. */\n cli: string;\n /** Severity level. */\n level: 'info' | 'error';\n /** Human-readable message. */\n message: string;\n /** Optional extra structured data to attach to the entry. */\n extra?: Record<string, unknown>;\n};\n\n/** The type returned by `createLogger`. */\nexport type LoggerInstance = {\n /** Log an informational message. */\n info: (\n message: string,\n extra?: Record<string, unknown>,\n verbose?: boolean,\n ) => void;\n /** Log an error message. */\n error: (\n message: string,\n extra?: Record<string, unknown>,\n verbose?: boolean,\n ) => void;\n /** Read the full contents of the log file. */\n readLog: () => string;\n};\n\nconst MAX_LOG_BYTES = 1024 * 1024;\nconst MAX_ROTATED = 3;\n\n/**\n * Create the log directory if it does not yet exist.\n *\n * @param path - Absolute path to the log file whose parent directory to create.\n */\nfunction ensureLogDir(path: string): void {\n const dir = dirname(path);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n}\n\n/**\n * Rotate the log file when it exceeds 1 MiB.\n *\n * @param path - Absolute path to the log file to rotate.\n */\nfunction rotateIfNeeded(path: string): void {\n if (!existsSync(path)) {\n return;\n }\n const { size } = statSync(path);\n if (size <= MAX_LOG_BYTES) {\n return;\n }\n for (let index = MAX_ROTATED; index >= 1; index -= 1) {\n const from = index === 1 ? path : `${path}.${index - 1}`;\n const to = `${path}.${index}`;\n if (existsSync(from)) {\n if (existsSync(to)) {\n unlinkSync(to);\n }\n renameSync(from, to);\n }\n }\n}\n\n/**\n * Create a structured logger that appends JSON lines to the anonymizer log file,\n * rotating when the file exceeds 1 MiB.\n *\n * @param cli - The CLI name to embed in every log entry.\n * @param logPath - Path to the log file; defaults to the configured anonymizer log path.\n * @returns An object with `info`, `error`, and `readLog` methods.\n */\nexport function createLogger(\n cli: string,\n logPath = getAnonymizerLogPath(),\n): LoggerInstance {\n /**\n * Append an entry to the log file, rotating first when needed.\n *\n * @param entry - The log entry to serialise.\n * @param verbose - When true, also writes to stdout.\n */\n const write = (entry: LogEntry, verbose: boolean): void => {\n ensureLogDir(logPath);\n rotateIfNeeded(logPath);\n const line = `${JSON.stringify(entry)}\\n`;\n writeFileSync(logPath, line, { flag: 'a' });\n if (verbose) {\n process.stdout.write(line);\n }\n };\n\n return {\n /**\n * Log an informational message.\n *\n * @param message - The message to log.\n * @param extra - Optional extra data to attach to the log entry.\n * @param verbose - When true, also writes to stdout.\n */\n info(\n message: string,\n extra?: Record<string, unknown>,\n verbose = false,\n ): void {\n write(\n {\n ts: new Date().toISOString(),\n cli,\n level: 'info',\n message,\n // exactOptionalPropertyTypes: omit the key when undefined rather than\n // assigning undefined to an optional property.\n ...(extra === undefined ? {} : { extra }),\n },\n verbose,\n );\n },\n /**\n * Log an error message.\n *\n * @param message - The message to log.\n * @param extra - Optional extra data to attach to the log entry.\n * @param verbose - When true, also writes to stdout.\n */\n error(\n message: string,\n extra?: Record<string, unknown>,\n verbose = false,\n ): void {\n write(\n {\n ts: new Date().toISOString(),\n cli,\n level: 'error',\n message,\n ...(extra === undefined ? {} : { extra }),\n },\n verbose,\n );\n },\n /**\n * Read the full contents of the log file.\n *\n * @returns The log file contents, or an empty string if the file does not exist.\n */\n readLog(): string {\n if (!existsSync(logPath)) {\n return '';\n }\n return readFileSync(logPath, 'utf8');\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ENV_TOOL_USAGE_COLLECTION_DIR = exports.ENV_MIMIR_PASSWORD = exports.ENV_MIMIR_USERNAME = exports.ENV_MIMIR_URL = exports.ENV_ANONYMIZER_LOG_PATH = exports.ENV_TOOL_USAGE_COLLECTION_LOG_PATH = void 0;
|
|
4
|
+
exports.isCollectionDisabled = isCollectionDisabled;
|
|
5
|
+
exports.expandHomePath = expandHomePath;
|
|
6
|
+
exports.getCollectionDir = getCollectionDir;
|
|
7
|
+
exports.getEventsLogDir = getEventsLogDir;
|
|
8
|
+
exports.getStatePath = getStatePath;
|
|
9
|
+
exports.getAnonymizerLogPath = getAnonymizerLogPath;
|
|
10
|
+
const node_os_1 = require("node:os");
|
|
11
|
+
const node_path_1 = require("node:path");
|
|
12
|
+
exports.ENV_TOOL_USAGE_COLLECTION_LOG_PATH = 'TOOL_USAGE_COLLECTION_LOG_PATH';
|
|
13
|
+
exports.ENV_ANONYMIZER_LOG_PATH = 'ANONYMIZER_LOG_PATH';
|
|
14
|
+
exports.ENV_MIMIR_URL = 'MIMIR_URL';
|
|
15
|
+
exports.ENV_MIMIR_USERNAME = 'MIMIR_USERNAME';
|
|
16
|
+
exports.ENV_MIMIR_PASSWORD = 'MIMIR_PASSWORD';
|
|
17
|
+
exports.ENV_TOOL_USAGE_COLLECTION_DIR = 'TOOL_USAGE_COLLECTION_DIR';
|
|
18
|
+
const DEFAULT_COLLECTION_DIR = (0, node_path_1.join)((0, node_os_1.homedir)(), '.tool-usage-collection');
|
|
19
|
+
const STATE_FILE_NAME = 'anonymizer-state.json';
|
|
20
|
+
const DEFAULT_LOG_FILE_NAME = 'anonymizer.log';
|
|
21
|
+
/**
|
|
22
|
+
* Returns true when telemetry collection is disabled (CI environment or explicit opt-out).
|
|
23
|
+
*
|
|
24
|
+
* @returns `true` when `CI` is set or `TOOL_USAGE_COLLECTION_OPT_IN` is `"false"`.
|
|
25
|
+
*/
|
|
26
|
+
function isCollectionDisabled() {
|
|
27
|
+
return (Boolean(process.env.CI) ||
|
|
28
|
+
process.env.TOOL_USAGE_COLLECTION_OPT_IN === 'false');
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Expands a leading `~` or `~/` to the current user's home directory.
|
|
32
|
+
*
|
|
33
|
+
* @param path - A path that may start with `~`.
|
|
34
|
+
* @returns The path with `~` expanded to the home directory.
|
|
35
|
+
*/
|
|
36
|
+
function expandHomePath(path) {
|
|
37
|
+
if (path === '~') {
|
|
38
|
+
return (0, node_os_1.homedir)();
|
|
39
|
+
}
|
|
40
|
+
if (path.startsWith('~/')) {
|
|
41
|
+
return (0, node_path_1.join)((0, node_os_1.homedir)(), path.slice(2));
|
|
42
|
+
}
|
|
43
|
+
return path;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Base directory for anonymizer state and the default log file.
|
|
47
|
+
*
|
|
48
|
+
* @returns Absolute path to the collection directory.
|
|
49
|
+
*/
|
|
50
|
+
function getCollectionDir() {
|
|
51
|
+
const configured = process.env[exports.ENV_TOOL_USAGE_COLLECTION_DIR];
|
|
52
|
+
if (configured) {
|
|
53
|
+
return expandHomePath(configured);
|
|
54
|
+
}
|
|
55
|
+
return DEFAULT_COLLECTION_DIR;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Directory scanned for `*-events.log` source files.
|
|
59
|
+
* When `TOOL_USAGE_COLLECTION_LOG_PATH` points at a `.log` file, its parent dir is used.
|
|
60
|
+
*
|
|
61
|
+
* @returns Absolute path to the directory containing event log files.
|
|
62
|
+
*/
|
|
63
|
+
function getEventsLogDir() {
|
|
64
|
+
const configured = process.env[exports.ENV_TOOL_USAGE_COLLECTION_LOG_PATH];
|
|
65
|
+
if (!configured) {
|
|
66
|
+
return getCollectionDir();
|
|
67
|
+
}
|
|
68
|
+
const expanded = expandHomePath(configured);
|
|
69
|
+
return expanded.endsWith('.log') ? (0, node_path_1.dirname)(expanded) : expanded;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Absolute path to the anonymizer state JSON file.
|
|
73
|
+
*
|
|
74
|
+
* @returns Absolute path to the anonymizer state JSON file.
|
|
75
|
+
*/
|
|
76
|
+
function getStatePath() {
|
|
77
|
+
return (0, node_path_1.join)(getCollectionDir(), STATE_FILE_NAME);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Absolute path to the anonymizer log file.
|
|
81
|
+
*
|
|
82
|
+
* @returns Absolute path to the anonymizer log file.
|
|
83
|
+
*/
|
|
84
|
+
function getAnonymizerLogPath() {
|
|
85
|
+
const configured = process.env[exports.ENV_ANONYMIZER_LOG_PATH];
|
|
86
|
+
if (configured) {
|
|
87
|
+
return expandHomePath(configured);
|
|
88
|
+
}
|
|
89
|
+
return (0, node_path_1.join)(getCollectionDir(), DEFAULT_LOG_FILE_NAME);
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=paths.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.cjs","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":";;;AAsBA,oDAKC;AAQD,wCAQC;AAOD,4CAMC;AAQD,0CAOC;AAOD,oCAEC;AAOD,oDAMC;AA7FD,qCAAkC;AAClC,yCAA0C;AAE7B,QAAA,kCAAkC,GAC7C,gCAAgC,CAAC;AACtB,QAAA,uBAAuB,GAAG,qBAAqB,CAAC;AAChD,QAAA,aAAa,GAAG,WAAW,CAAC;AAC5B,QAAA,kBAAkB,GAAG,gBAAgB,CAAC;AACtC,QAAA,kBAAkB,GAAG,gBAAgB,CAAC;AAEtC,QAAA,6BAA6B,GAAG,2BAA2B,CAAC;AAEzE,MAAM,sBAAsB,GAAG,IAAA,gBAAI,EAAC,IAAA,iBAAO,GAAE,EAAE,wBAAwB,CAAC,CAAC;AAEzE,MAAM,eAAe,GAAG,uBAAuB,CAAC;AAChD,MAAM,qBAAqB,GAAG,gBAAgB,CAAC;AAE/C;;;;GAIG;AACH,SAAgB,oBAAoB;IAClC,OAAO,CACL,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,4BAA4B,KAAK,OAAO,CACrD,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAgB,cAAc,CAAC,IAAY;IACzC,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;QACjB,OAAO,IAAA,iBAAO,GAAE,CAAC;IACnB,CAAC;IACD,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,OAAO,IAAA,gBAAI,EAAC,IAAA,iBAAO,GAAE,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,SAAgB,gBAAgB;IAC9B,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,qCAA6B,CAAC,CAAC;IAC9D,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,cAAc,CAAC,UAAU,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,sBAAsB,CAAC;AAChC,CAAC;AAED;;;;;GAKG;AACH,SAAgB,eAAe;IAC7B,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,0CAAkC,CAAC,CAAC;IACnE,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,gBAAgB,EAAE,CAAC;IAC5B,CAAC;IACD,MAAM,QAAQ,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAC5C,OAAO,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAA,mBAAO,EAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;AAClE,CAAC;AAED;;;;GAIG;AACH,SAAgB,YAAY;IAC1B,OAAO,IAAA,gBAAI,EAAC,gBAAgB,EAAE,EAAE,eAAe,CAAC,CAAC;AACnD,CAAC;AAED;;;;GAIG;AACH,SAAgB,oBAAoB;IAClC,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,+BAAuB,CAAC,CAAC;IACxD,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,cAAc,CAAC,UAAU,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,IAAA,gBAAI,EAAC,gBAAgB,EAAE,EAAE,qBAAqB,CAAC,CAAC;AACzD,CAAC","sourcesContent":["import { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\n\nexport const ENV_TOOL_USAGE_COLLECTION_LOG_PATH =\n 'TOOL_USAGE_COLLECTION_LOG_PATH';\nexport const ENV_ANONYMIZER_LOG_PATH = 'ANONYMIZER_LOG_PATH';\nexport const ENV_MIMIR_URL = 'MIMIR_URL';\nexport const ENV_MIMIR_USERNAME = 'MIMIR_USERNAME';\nexport const ENV_MIMIR_PASSWORD = 'MIMIR_PASSWORD';\n\nexport const ENV_TOOL_USAGE_COLLECTION_DIR = 'TOOL_USAGE_COLLECTION_DIR';\n\nconst DEFAULT_COLLECTION_DIR = join(homedir(), '.tool-usage-collection');\n\nconst STATE_FILE_NAME = 'anonymizer-state.json';\nconst DEFAULT_LOG_FILE_NAME = 'anonymizer.log';\n\n/**\n * Returns true when telemetry collection is disabled (CI environment or explicit opt-out).\n *\n * @returns `true` when `CI` is set or `TOOL_USAGE_COLLECTION_OPT_IN` is `\"false\"`.\n */\nexport function isCollectionDisabled(): boolean {\n return (\n Boolean(process.env.CI) ||\n process.env.TOOL_USAGE_COLLECTION_OPT_IN === 'false'\n );\n}\n\n/**\n * Expands a leading `~` or `~/` to the current user's home directory.\n *\n * @param path - A path that may start with `~`.\n * @returns The path with `~` expanded to the home directory.\n */\nexport function expandHomePath(path: string): string {\n if (path === '~') {\n return homedir();\n }\n if (path.startsWith('~/')) {\n return join(homedir(), path.slice(2));\n }\n return path;\n}\n\n/**\n * Base directory for anonymizer state and the default log file.\n *\n * @returns Absolute path to the collection directory.\n */\nexport function getCollectionDir(): string {\n const configured = process.env[ENV_TOOL_USAGE_COLLECTION_DIR];\n if (configured) {\n return expandHomePath(configured);\n }\n return DEFAULT_COLLECTION_DIR;\n}\n\n/**\n * Directory scanned for `*-events.log` source files.\n * When `TOOL_USAGE_COLLECTION_LOG_PATH` points at a `.log` file, its parent dir is used.\n *\n * @returns Absolute path to the directory containing event log files.\n */\nexport function getEventsLogDir(): string {\n const configured = process.env[ENV_TOOL_USAGE_COLLECTION_LOG_PATH];\n if (!configured) {\n return getCollectionDir();\n }\n const expanded = expandHomePath(configured);\n return expanded.endsWith('.log') ? dirname(expanded) : expanded;\n}\n\n/**\n * Absolute path to the anonymizer state JSON file.\n *\n * @returns Absolute path to the anonymizer state JSON file.\n */\nexport function getStatePath(): string {\n return join(getCollectionDir(), STATE_FILE_NAME);\n}\n\n/**\n * Absolute path to the anonymizer log file.\n *\n * @returns Absolute path to the anonymizer log file.\n */\nexport function getAnonymizerLogPath(): string {\n const configured = process.env[ENV_ANONYMIZER_LOG_PATH];\n if (configured) {\n return expandHomePath(configured);\n }\n return join(getCollectionDir(), DEFAULT_LOG_FILE_NAME);\n}\n"]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export declare const ENV_TOOL_USAGE_COLLECTION_LOG_PATH = "TOOL_USAGE_COLLECTION_LOG_PATH";
|
|
2
|
+
export declare const ENV_ANONYMIZER_LOG_PATH = "ANONYMIZER_LOG_PATH";
|
|
3
|
+
export declare const ENV_MIMIR_URL = "MIMIR_URL";
|
|
4
|
+
export declare const ENV_MIMIR_USERNAME = "MIMIR_USERNAME";
|
|
5
|
+
export declare const ENV_MIMIR_PASSWORD = "MIMIR_PASSWORD";
|
|
6
|
+
export declare const ENV_TOOL_USAGE_COLLECTION_DIR = "TOOL_USAGE_COLLECTION_DIR";
|
|
7
|
+
/**
|
|
8
|
+
* Returns true when telemetry collection is disabled (CI environment or explicit opt-out).
|
|
9
|
+
*
|
|
10
|
+
* @returns `true` when `CI` is set or `TOOL_USAGE_COLLECTION_OPT_IN` is `"false"`.
|
|
11
|
+
*/
|
|
12
|
+
export declare function isCollectionDisabled(): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Expands a leading `~` or `~/` to the current user's home directory.
|
|
15
|
+
*
|
|
16
|
+
* @param path - A path that may start with `~`.
|
|
17
|
+
* @returns The path with `~` expanded to the home directory.
|
|
18
|
+
*/
|
|
19
|
+
export declare function expandHomePath(path: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Base directory for anonymizer state and the default log file.
|
|
22
|
+
*
|
|
23
|
+
* @returns Absolute path to the collection directory.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getCollectionDir(): string;
|
|
26
|
+
/**
|
|
27
|
+
* Directory scanned for `*-events.log` source files.
|
|
28
|
+
* When `TOOL_USAGE_COLLECTION_LOG_PATH` points at a `.log` file, its parent dir is used.
|
|
29
|
+
*
|
|
30
|
+
* @returns Absolute path to the directory containing event log files.
|
|
31
|
+
*/
|
|
32
|
+
export declare function getEventsLogDir(): string;
|
|
33
|
+
/**
|
|
34
|
+
* Absolute path to the anonymizer state JSON file.
|
|
35
|
+
*
|
|
36
|
+
* @returns Absolute path to the anonymizer state JSON file.
|
|
37
|
+
*/
|
|
38
|
+
export declare function getStatePath(): string;
|
|
39
|
+
/**
|
|
40
|
+
* Absolute path to the anonymizer log file.
|
|
41
|
+
*
|
|
42
|
+
* @returns Absolute path to the anonymizer log file.
|
|
43
|
+
*/
|
|
44
|
+
export declare function getAnonymizerLogPath(): string;
|
|
45
|
+
//# sourceMappingURL=paths.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.cts","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,kCAAkC,mCACb,CAAC;AACnC,eAAO,MAAM,uBAAuB,wBAAwB,CAAC;AAC7D,eAAO,MAAM,aAAa,cAAc,CAAC;AACzC,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AACnD,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AAEnD,eAAO,MAAM,6BAA6B,8BAA8B,CAAC;AAOzE;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAK9C;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQnD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAMzC;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAOxC;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAM7C"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export declare const ENV_TOOL_USAGE_COLLECTION_LOG_PATH = "TOOL_USAGE_COLLECTION_LOG_PATH";
|
|
2
|
+
export declare const ENV_ANONYMIZER_LOG_PATH = "ANONYMIZER_LOG_PATH";
|
|
3
|
+
export declare const ENV_MIMIR_URL = "MIMIR_URL";
|
|
4
|
+
export declare const ENV_MIMIR_USERNAME = "MIMIR_USERNAME";
|
|
5
|
+
export declare const ENV_MIMIR_PASSWORD = "MIMIR_PASSWORD";
|
|
6
|
+
export declare const ENV_TOOL_USAGE_COLLECTION_DIR = "TOOL_USAGE_COLLECTION_DIR";
|
|
7
|
+
/**
|
|
8
|
+
* Returns true when telemetry collection is disabled (CI environment or explicit opt-out).
|
|
9
|
+
*
|
|
10
|
+
* @returns `true` when `CI` is set or `TOOL_USAGE_COLLECTION_OPT_IN` is `"false"`.
|
|
11
|
+
*/
|
|
12
|
+
export declare function isCollectionDisabled(): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Expands a leading `~` or `~/` to the current user's home directory.
|
|
15
|
+
*
|
|
16
|
+
* @param path - A path that may start with `~`.
|
|
17
|
+
* @returns The path with `~` expanded to the home directory.
|
|
18
|
+
*/
|
|
19
|
+
export declare function expandHomePath(path: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Base directory for anonymizer state and the default log file.
|
|
22
|
+
*
|
|
23
|
+
* @returns Absolute path to the collection directory.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getCollectionDir(): string;
|
|
26
|
+
/**
|
|
27
|
+
* Directory scanned for `*-events.log` source files.
|
|
28
|
+
* When `TOOL_USAGE_COLLECTION_LOG_PATH` points at a `.log` file, its parent dir is used.
|
|
29
|
+
*
|
|
30
|
+
* @returns Absolute path to the directory containing event log files.
|
|
31
|
+
*/
|
|
32
|
+
export declare function getEventsLogDir(): string;
|
|
33
|
+
/**
|
|
34
|
+
* Absolute path to the anonymizer state JSON file.
|
|
35
|
+
*
|
|
36
|
+
* @returns Absolute path to the anonymizer state JSON file.
|
|
37
|
+
*/
|
|
38
|
+
export declare function getStatePath(): string;
|
|
39
|
+
/**
|
|
40
|
+
* Absolute path to the anonymizer log file.
|
|
41
|
+
*
|
|
42
|
+
* @returns Absolute path to the anonymizer log file.
|
|
43
|
+
*/
|
|
44
|
+
export declare function getAnonymizerLogPath(): string;
|
|
45
|
+
//# sourceMappingURL=paths.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.mts","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,kCAAkC,mCACb,CAAC;AACnC,eAAO,MAAM,uBAAuB,wBAAwB,CAAC;AAC7D,eAAO,MAAM,aAAa,cAAc,CAAC;AACzC,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AACnD,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AAEnD,eAAO,MAAM,6BAA6B,8BAA8B,CAAC;AAOzE;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAK9C;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQnD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAMzC;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAOxC;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAM7C"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { homedir } from "node:os";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
export const ENV_TOOL_USAGE_COLLECTION_LOG_PATH = 'TOOL_USAGE_COLLECTION_LOG_PATH';
|
|
4
|
+
export const ENV_ANONYMIZER_LOG_PATH = 'ANONYMIZER_LOG_PATH';
|
|
5
|
+
export const ENV_MIMIR_URL = 'MIMIR_URL';
|
|
6
|
+
export const ENV_MIMIR_USERNAME = 'MIMIR_USERNAME';
|
|
7
|
+
export const ENV_MIMIR_PASSWORD = 'MIMIR_PASSWORD';
|
|
8
|
+
export const ENV_TOOL_USAGE_COLLECTION_DIR = 'TOOL_USAGE_COLLECTION_DIR';
|
|
9
|
+
const DEFAULT_COLLECTION_DIR = join(homedir(), '.tool-usage-collection');
|
|
10
|
+
const STATE_FILE_NAME = 'anonymizer-state.json';
|
|
11
|
+
const DEFAULT_LOG_FILE_NAME = 'anonymizer.log';
|
|
12
|
+
/**
|
|
13
|
+
* Returns true when telemetry collection is disabled (CI environment or explicit opt-out).
|
|
14
|
+
*
|
|
15
|
+
* @returns `true` when `CI` is set or `TOOL_USAGE_COLLECTION_OPT_IN` is `"false"`.
|
|
16
|
+
*/
|
|
17
|
+
export function isCollectionDisabled() {
|
|
18
|
+
return (Boolean(process.env.CI) ||
|
|
19
|
+
process.env.TOOL_USAGE_COLLECTION_OPT_IN === 'false');
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Expands a leading `~` or `~/` to the current user's home directory.
|
|
23
|
+
*
|
|
24
|
+
* @param path - A path that may start with `~`.
|
|
25
|
+
* @returns The path with `~` expanded to the home directory.
|
|
26
|
+
*/
|
|
27
|
+
export function expandHomePath(path) {
|
|
28
|
+
if (path === '~') {
|
|
29
|
+
return homedir();
|
|
30
|
+
}
|
|
31
|
+
if (path.startsWith('~/')) {
|
|
32
|
+
return join(homedir(), path.slice(2));
|
|
33
|
+
}
|
|
34
|
+
return path;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Base directory for anonymizer state and the default log file.
|
|
38
|
+
*
|
|
39
|
+
* @returns Absolute path to the collection directory.
|
|
40
|
+
*/
|
|
41
|
+
export function getCollectionDir() {
|
|
42
|
+
const configured = process.env[ENV_TOOL_USAGE_COLLECTION_DIR];
|
|
43
|
+
if (configured) {
|
|
44
|
+
return expandHomePath(configured);
|
|
45
|
+
}
|
|
46
|
+
return DEFAULT_COLLECTION_DIR;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Directory scanned for `*-events.log` source files.
|
|
50
|
+
* When `TOOL_USAGE_COLLECTION_LOG_PATH` points at a `.log` file, its parent dir is used.
|
|
51
|
+
*
|
|
52
|
+
* @returns Absolute path to the directory containing event log files.
|
|
53
|
+
*/
|
|
54
|
+
export function getEventsLogDir() {
|
|
55
|
+
const configured = process.env[ENV_TOOL_USAGE_COLLECTION_LOG_PATH];
|
|
56
|
+
if (!configured) {
|
|
57
|
+
return getCollectionDir();
|
|
58
|
+
}
|
|
59
|
+
const expanded = expandHomePath(configured);
|
|
60
|
+
return expanded.endsWith('.log') ? dirname(expanded) : expanded;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Absolute path to the anonymizer state JSON file.
|
|
64
|
+
*
|
|
65
|
+
* @returns Absolute path to the anonymizer state JSON file.
|
|
66
|
+
*/
|
|
67
|
+
export function getStatePath() {
|
|
68
|
+
return join(getCollectionDir(), STATE_FILE_NAME);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Absolute path to the anonymizer log file.
|
|
72
|
+
*
|
|
73
|
+
* @returns Absolute path to the anonymizer log file.
|
|
74
|
+
*/
|
|
75
|
+
export function getAnonymizerLogPath() {
|
|
76
|
+
const configured = process.env[ENV_ANONYMIZER_LOG_PATH];
|
|
77
|
+
if (configured) {
|
|
78
|
+
return expandHomePath(configured);
|
|
79
|
+
}
|
|
80
|
+
return join(getCollectionDir(), DEFAULT_LOG_FILE_NAME);
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=paths.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.mjs","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,gBAAgB;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,kBAAkB;AAE1C,MAAM,CAAC,MAAM,kCAAkC,GAC7C,gCAAgC,CAAC;AACnC,MAAM,CAAC,MAAM,uBAAuB,GAAG,qBAAqB,CAAC;AAC7D,MAAM,CAAC,MAAM,aAAa,GAAG,WAAW,CAAC;AACzC,MAAM,CAAC,MAAM,kBAAkB,GAAG,gBAAgB,CAAC;AACnD,MAAM,CAAC,MAAM,kBAAkB,GAAG,gBAAgB,CAAC;AAEnD,MAAM,CAAC,MAAM,6BAA6B,GAAG,2BAA2B,CAAC;AAEzE,MAAM,sBAAsB,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,wBAAwB,CAAC,CAAC;AAEzE,MAAM,eAAe,GAAG,uBAAuB,CAAC;AAChD,MAAM,qBAAqB,GAAG,gBAAgB,CAAC;AAE/C;;;;GAIG;AACH,MAAM,UAAU,oBAAoB;IAClC,OAAO,CACL,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,4BAA4B,KAAK,OAAO,CACrD,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;QACjB,OAAO,OAAO,EAAE,CAAC;IACnB,CAAC;IACD,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;IAC9D,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,cAAc,CAAC,UAAU,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,sBAAsB,CAAC;AAChC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IACnE,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,gBAAgB,EAAE,CAAC;IAC5B,CAAC;IACD,MAAM,QAAQ,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAC5C,OAAO,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;AAClE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,IAAI,CAAC,gBAAgB,EAAE,EAAE,eAAe,CAAC,CAAC;AACnD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB;IAClC,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;IACxD,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,cAAc,CAAC,UAAU,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,IAAI,CAAC,gBAAgB,EAAE,EAAE,qBAAqB,CAAC,CAAC;AACzD,CAAC","sourcesContent":["import { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\n\nexport const ENV_TOOL_USAGE_COLLECTION_LOG_PATH =\n 'TOOL_USAGE_COLLECTION_LOG_PATH';\nexport const ENV_ANONYMIZER_LOG_PATH = 'ANONYMIZER_LOG_PATH';\nexport const ENV_MIMIR_URL = 'MIMIR_URL';\nexport const ENV_MIMIR_USERNAME = 'MIMIR_USERNAME';\nexport const ENV_MIMIR_PASSWORD = 'MIMIR_PASSWORD';\n\nexport const ENV_TOOL_USAGE_COLLECTION_DIR = 'TOOL_USAGE_COLLECTION_DIR';\n\nconst DEFAULT_COLLECTION_DIR = join(homedir(), '.tool-usage-collection');\n\nconst STATE_FILE_NAME = 'anonymizer-state.json';\nconst DEFAULT_LOG_FILE_NAME = 'anonymizer.log';\n\n/**\n * Returns true when telemetry collection is disabled (CI environment or explicit opt-out).\n *\n * @returns `true` when `CI` is set or `TOOL_USAGE_COLLECTION_OPT_IN` is `\"false\"`.\n */\nexport function isCollectionDisabled(): boolean {\n return (\n Boolean(process.env.CI) ||\n process.env.TOOL_USAGE_COLLECTION_OPT_IN === 'false'\n );\n}\n\n/**\n * Expands a leading `~` or `~/` to the current user's home directory.\n *\n * @param path - A path that may start with `~`.\n * @returns The path with `~` expanded to the home directory.\n */\nexport function expandHomePath(path: string): string {\n if (path === '~') {\n return homedir();\n }\n if (path.startsWith('~/')) {\n return join(homedir(), path.slice(2));\n }\n return path;\n}\n\n/**\n * Base directory for anonymizer state and the default log file.\n *\n * @returns Absolute path to the collection directory.\n */\nexport function getCollectionDir(): string {\n const configured = process.env[ENV_TOOL_USAGE_COLLECTION_DIR];\n if (configured) {\n return expandHomePath(configured);\n }\n return DEFAULT_COLLECTION_DIR;\n}\n\n/**\n * Directory scanned for `*-events.log` source files.\n * When `TOOL_USAGE_COLLECTION_LOG_PATH` points at a `.log` file, its parent dir is used.\n *\n * @returns Absolute path to the directory containing event log files.\n */\nexport function getEventsLogDir(): string {\n const configured = process.env[ENV_TOOL_USAGE_COLLECTION_LOG_PATH];\n if (!configured) {\n return getCollectionDir();\n }\n const expanded = expandHomePath(configured);\n return expanded.endsWith('.log') ? dirname(expanded) : expanded;\n}\n\n/**\n * Absolute path to the anonymizer state JSON file.\n *\n * @returns Absolute path to the anonymizer state JSON file.\n */\nexport function getStatePath(): string {\n return join(getCollectionDir(), STATE_FILE_NAME);\n}\n\n/**\n * Absolute path to the anonymizer log file.\n *\n * @returns Absolute path to the anonymizer log file.\n */\nexport function getAnonymizerLogPath(): string {\n const configured = process.env[ENV_ANONYMIZER_LOG_PATH];\n if (configured) {\n return expandHomePath(configured);\n }\n return join(getCollectionDir(), DEFAULT_LOG_FILE_NAME);\n}\n"]}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PushError = void 0;
|
|
4
|
+
exports.loadPushConfig = loadPushConfig;
|
|
5
|
+
exports.pushBatch = pushBatch;
|
|
6
|
+
const node_fs_1 = require("node:fs");
|
|
7
|
+
const node_path_1 = require("node:path");
|
|
8
|
+
const paths_1 = require("./paths.cjs");
|
|
9
|
+
/** Thrown when the remote-write endpoint returns a non-2xx response. */
|
|
10
|
+
class PushError extends Error {
|
|
11
|
+
/**
|
|
12
|
+
* Create a `PushError`.
|
|
13
|
+
*
|
|
14
|
+
* @param status - HTTP status code returned by the endpoint.
|
|
15
|
+
* @param responseBody - Response body text returned by the endpoint.
|
|
16
|
+
*/
|
|
17
|
+
constructor(status, responseBody) {
|
|
18
|
+
super(`Push failed with status ${status}`);
|
|
19
|
+
this.name = 'PushError';
|
|
20
|
+
this.status = status;
|
|
21
|
+
this.responseBody = responseBody;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.PushError = PushError;
|
|
25
|
+
/**
|
|
26
|
+
* Parse the repo's `.js.env` (shell-sourceable: `export KEY="value"`, `#` comments).
|
|
27
|
+
* Handles the optional `export ` prefix and surrounding single/double quotes.
|
|
28
|
+
*
|
|
29
|
+
* @param contents - Shell-sourceable `.js.env` file contents.
|
|
30
|
+
* @returns A map of environment variable names to their string values.
|
|
31
|
+
*/
|
|
32
|
+
function parseEnvFile(contents) {
|
|
33
|
+
const entries = {};
|
|
34
|
+
for (const rawLine of contents.split('\n')) {
|
|
35
|
+
let line = rawLine.trim();
|
|
36
|
+
if (!line || line.startsWith('#')) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (line.startsWith('export ')) {
|
|
40
|
+
line = line.slice('export '.length).trim();
|
|
41
|
+
}
|
|
42
|
+
const eq = line.indexOf('=');
|
|
43
|
+
if (eq === -1) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
const key = line.slice(0, eq).trim();
|
|
47
|
+
let value = line.slice(eq + 1).trim();
|
|
48
|
+
if (value.length >= 2 &&
|
|
49
|
+
((value.startsWith('"') && value.endsWith('"')) ||
|
|
50
|
+
(value.startsWith("'") && value.endsWith("'")))) {
|
|
51
|
+
value = value.slice(1, -1);
|
|
52
|
+
}
|
|
53
|
+
entries[key] = value;
|
|
54
|
+
}
|
|
55
|
+
return entries;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Load push credentials from process env, falling back to the repo's `.js.env`.
|
|
59
|
+
*
|
|
60
|
+
* @param repoRoot - Absolute path to the repo root where `.js.env` may live.
|
|
61
|
+
* @returns The resolved push configuration.
|
|
62
|
+
*/
|
|
63
|
+
function loadPushConfig(repoRoot) {
|
|
64
|
+
// File values are the fallback; env takes precedence for every key.
|
|
65
|
+
const envPath = (0, node_path_1.join)(repoRoot, '.js.env');
|
|
66
|
+
const file = (0, node_fs_1.existsSync)(envPath)
|
|
67
|
+
? parseEnvFile((0, node_fs_1.readFileSync)(envPath, 'utf8'))
|
|
68
|
+
: {};
|
|
69
|
+
const url = process.env[paths_1.ENV_MIMIR_URL] ?? file[paths_1.ENV_MIMIR_URL] ?? '';
|
|
70
|
+
const username = process.env[paths_1.ENV_MIMIR_USERNAME] ?? file[paths_1.ENV_MIMIR_USERNAME];
|
|
71
|
+
const password = process.env[paths_1.ENV_MIMIR_PASSWORD] ?? file[paths_1.ENV_MIMIR_PASSWORD];
|
|
72
|
+
return {
|
|
73
|
+
url,
|
|
74
|
+
...(username !== undefined && { username }),
|
|
75
|
+
...(password !== undefined && { password }),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* POST a remote-write body to the configured Prometheus remote-write endpoint.
|
|
80
|
+
*
|
|
81
|
+
* @param body - Snappy-compressed protobuf `WriteRequest` bytes to push.
|
|
82
|
+
* @param options - Push configuration including URL, credentials, and optional fetch override.
|
|
83
|
+
*/
|
|
84
|
+
async function pushBatch(body, options) {
|
|
85
|
+
if (options.dryRun) {
|
|
86
|
+
options.logger.info('dry-run push body', { byteLength: body.byteLength });
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
if (!options.url) {
|
|
90
|
+
throw new Error('Prometheus push URL is required');
|
|
91
|
+
}
|
|
92
|
+
// Basic auth is only needed for authenticated endpoints (e.g. dev). Prod uses Cloudflare WARP.
|
|
93
|
+
const authHeader = options.username && options.password
|
|
94
|
+
? {
|
|
95
|
+
Authorization: `Basic ${Buffer.from(`${options.username}:${options.password}`).toString('base64')}`,
|
|
96
|
+
}
|
|
97
|
+
: {};
|
|
98
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
99
|
+
const response = await fetchImpl(options.url, {
|
|
100
|
+
method: 'POST',
|
|
101
|
+
headers: {
|
|
102
|
+
...authHeader,
|
|
103
|
+
'Content-Type': 'application/x-protobuf',
|
|
104
|
+
'X-Prometheus-Remote-Write-Version': '0.1.0',
|
|
105
|
+
},
|
|
106
|
+
body,
|
|
107
|
+
});
|
|
108
|
+
const responseBody = await response.text();
|
|
109
|
+
if (!response.ok) {
|
|
110
|
+
options.logger.error('push failed', {
|
|
111
|
+
status: response.status,
|
|
112
|
+
body: responseBody,
|
|
113
|
+
});
|
|
114
|
+
throw new PushError(response.status, responseBody);
|
|
115
|
+
}
|
|
116
|
+
// Mimir returns HTTP 200 even for partial rejections; warnings appear in the body.
|
|
117
|
+
options.logger.info('push complete', {
|
|
118
|
+
status: response.status,
|
|
119
|
+
...(responseBody.trim() && { mimirWarning: responseBody.trim() }),
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=push.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push.cjs","sourceRoot":"","sources":["../../src/lib/push.ts"],"names":[],"mappings":";;;AAoFA,wCAgBC;AAwBD,8BA6CC;AAzKD,qCAAmD;AACnD,yCAAiC;AAEjC,uCAAgF;AAoBhF,wEAAwE;AACxE,MAAa,SAAU,SAAQ,KAAK;IAKlC;;;;;OAKG;IACH,YAAY,MAAc,EAAE,YAAoB;QAC9C,KAAK,CAAC,2BAA2B,MAAM,EAAE,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;QACxB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IACnC,CAAC;CACF;AAjBD,8BAiBC;AAED;;;;;;GAMG;AACH,SAAS,YAAY,CAAC,QAAgB;IACpC,MAAM,OAAO,GAA2B,EAAE,CAAC;IAC3C,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3C,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAClC,SAAS;QACX,CAAC;QACD,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC/B,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QAC7C,CAAC;QACD,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC;YACd,SAAS;QACX,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACrC,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACtC,IACE,KAAK,CAAC,MAAM,IAAI,CAAC;YACjB,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;gBAC7C,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EACjD,CAAC;YACD,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACvB,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,SAAgB,cAAc,CAAC,QAAgB;IAC7C,oEAAoE;IACpE,MAAM,OAAO,GAAG,IAAA,gBAAI,EAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,IAAA,oBAAU,EAAC,OAAO,CAAC;QAC9B,CAAC,CAAC,YAAY,CAAC,IAAA,sBAAY,EAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC7C,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAa,CAAC,IAAI,IAAI,CAAC,qBAAa,CAAC,IAAI,EAAE,CAAC;IACpE,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,0BAAkB,CAAC,IAAI,IAAI,CAAC,0BAAkB,CAAC,CAAC;IAC7E,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,0BAAkB,CAAC,IAAI,IAAI,CAAC,0BAAkB,CAAC,CAAC;IAE7E,OAAO;QACL,GAAG;QACH,GAAG,CAAC,QAAQ,KAAK,SAAS,IAAI,EAAE,QAAQ,EAAE,CAAC;QAC3C,GAAG,CAAC,QAAQ,KAAK,SAAS,IAAI,EAAE,QAAQ,EAAE,CAAC;KAC5C,CAAC;AACJ,CAAC;AAkBD;;;;;GAKG;AACI,KAAK,UAAU,SAAS,CAC7B,IAAgB,EAChB,OAAyB;IAEzB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,mBAAmB,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;QAC1E,OAAO;IACT,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACrD,CAAC;IAED,+FAA+F;IAC/F,MAAM,UAAU,GACd,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ;QAClC,CAAC,CAAC;YACE,aAAa,EAAE,SAAS,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;SACpG;QACH,CAAC,CAAC,EAAE,CAAC;IAET,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC;IAC7C,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE;QAC5C,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,GAAG,UAAU;YACb,cAAc,EAAE,wBAAwB;YACxC,mCAAmC,EAAE,OAAO;SAC7C;QACD,IAAI;KACL,CAAC,CAAC;IAEH,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC3C,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,EAAE;YAClC,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,IAAI,EAAE,YAAY;SACnB,CAAC,CAAC;QACH,MAAM,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACrD,CAAC;IACD,mFAAmF;IACnF,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE;QACnC,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC;KAClE,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport { ENV_MIMIR_URL, ENV_MIMIR_PASSWORD, ENV_MIMIR_USERNAME } from './paths';\n\n/** Prometheus remote-write endpoint coordinates. */\nexport type PushConfig = {\n /** Full URL of the remote-write endpoint. */\n url: string;\n /** HTTP Basic auth username. Omit for unauthenticated endpoints (e.g. prod via Cloudflare WARP). */\n username?: string;\n /** HTTP Basic auth password. Omit for unauthenticated endpoints (e.g. prod via Cloudflare WARP). */\n password?: string;\n};\n\n/** Minimal logger interface used by `pushBatch`. */\nexport type Logger = {\n /** Log an informational message. */\n info: (message: string, extra?: Record<string, unknown>) => void;\n /** Log an error message. */\n error: (message: string, extra?: Record<string, unknown>) => void;\n};\n\n/** Thrown when the remote-write endpoint returns a non-2xx response. */\nexport class PushError extends Error {\n readonly status: number;\n\n readonly responseBody: string;\n\n /**\n * Create a `PushError`.\n *\n * @param status - HTTP status code returned by the endpoint.\n * @param responseBody - Response body text returned by the endpoint.\n */\n constructor(status: number, responseBody: string) {\n super(`Push failed with status ${status}`);\n this.name = 'PushError';\n this.status = status;\n this.responseBody = responseBody;\n }\n}\n\n/**\n * Parse the repo's `.js.env` (shell-sourceable: `export KEY=\"value\"`, `#` comments).\n * Handles the optional `export ` prefix and surrounding single/double quotes.\n *\n * @param contents - Shell-sourceable `.js.env` file contents.\n * @returns A map of environment variable names to their string values.\n */\nfunction parseEnvFile(contents: string): Record<string, string> {\n const entries: Record<string, string> = {};\n for (const rawLine of contents.split('\\n')) {\n let line = rawLine.trim();\n if (!line || line.startsWith('#')) {\n continue;\n }\n if (line.startsWith('export ')) {\n line = line.slice('export '.length).trim();\n }\n const eq = line.indexOf('=');\n if (eq === -1) {\n continue;\n }\n const key = line.slice(0, eq).trim();\n let value = line.slice(eq + 1).trim();\n if (\n value.length >= 2 &&\n ((value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\")))\n ) {\n value = value.slice(1, -1);\n }\n entries[key] = value;\n }\n return entries;\n}\n\n/**\n * Load push credentials from process env, falling back to the repo's `.js.env`.\n *\n * @param repoRoot - Absolute path to the repo root where `.js.env` may live.\n * @returns The resolved push configuration.\n */\nexport function loadPushConfig(repoRoot: string): PushConfig {\n // File values are the fallback; env takes precedence for every key.\n const envPath = join(repoRoot, '.js.env');\n const file = existsSync(envPath)\n ? parseEnvFile(readFileSync(envPath, 'utf8'))\n : {};\n\n const url = process.env[ENV_MIMIR_URL] ?? file[ENV_MIMIR_URL] ?? '';\n const username = process.env[ENV_MIMIR_USERNAME] ?? file[ENV_MIMIR_USERNAME];\n const password = process.env[ENV_MIMIR_PASSWORD] ?? file[ENV_MIMIR_PASSWORD];\n\n return {\n url,\n ...(username !== undefined && { username }),\n ...(password !== undefined && { password }),\n };\n}\n\n/** Options for `pushBatch`. */\nexport type PushBatchOptions = {\n /** Full URL of the remote-write endpoint. */\n url: string;\n /** HTTP Basic auth username. Omit for unauthenticated endpoints (e.g. prod via Cloudflare WARP). */\n username?: string;\n /** HTTP Basic auth password. Omit for unauthenticated endpoints (e.g. prod via Cloudflare WARP). */\n password?: string;\n /** When true, logs the body but does not POST. */\n dryRun: boolean;\n /** Logger instance for success and error messages. */\n logger: Logger;\n /** Fetch implementation; defaults to the global `fetch`. */\n fetchImpl?: typeof fetch;\n};\n\n/**\n * POST a remote-write body to the configured Prometheus remote-write endpoint.\n *\n * @param body - Snappy-compressed protobuf `WriteRequest` bytes to push.\n * @param options - Push configuration including URL, credentials, and optional fetch override.\n */\nexport async function pushBatch(\n body: Uint8Array,\n options: PushBatchOptions,\n): Promise<void> {\n if (options.dryRun) {\n options.logger.info('dry-run push body', { byteLength: body.byteLength });\n return;\n }\n\n if (!options.url) {\n throw new Error('Prometheus push URL is required');\n }\n\n // Basic auth is only needed for authenticated endpoints (e.g. dev). Prod uses Cloudflare WARP.\n const authHeader =\n options.username && options.password\n ? {\n Authorization: `Basic ${Buffer.from(`${options.username}:${options.password}`).toString('base64')}`,\n }\n : {};\n\n const fetchImpl = options.fetchImpl ?? fetch;\n const response = await fetchImpl(options.url, {\n method: 'POST',\n headers: {\n ...authHeader,\n 'Content-Type': 'application/x-protobuf',\n 'X-Prometheus-Remote-Write-Version': '0.1.0',\n },\n body,\n });\n\n const responseBody = await response.text();\n if (!response.ok) {\n options.logger.error('push failed', {\n status: response.status,\n body: responseBody,\n });\n throw new PushError(response.status, responseBody);\n }\n // Mimir returns HTTP 200 even for partial rejections; warnings appear in the body.\n options.logger.info('push complete', {\n status: response.status,\n ...(responseBody.trim() && { mimirWarning: responseBody.trim() }),\n });\n}\n"]}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/** Prometheus remote-write endpoint coordinates. */
|
|
2
|
+
export type PushConfig = {
|
|
3
|
+
/** Full URL of the remote-write endpoint. */
|
|
4
|
+
url: string;
|
|
5
|
+
/** HTTP Basic auth username. Omit for unauthenticated endpoints (e.g. prod via Cloudflare WARP). */
|
|
6
|
+
username?: string;
|
|
7
|
+
/** HTTP Basic auth password. Omit for unauthenticated endpoints (e.g. prod via Cloudflare WARP). */
|
|
8
|
+
password?: string;
|
|
9
|
+
};
|
|
10
|
+
/** Minimal logger interface used by `pushBatch`. */
|
|
11
|
+
export type Logger = {
|
|
12
|
+
/** Log an informational message. */
|
|
13
|
+
info: (message: string, extra?: Record<string, unknown>) => void;
|
|
14
|
+
/** Log an error message. */
|
|
15
|
+
error: (message: string, extra?: Record<string, unknown>) => void;
|
|
16
|
+
};
|
|
17
|
+
/** Thrown when the remote-write endpoint returns a non-2xx response. */
|
|
18
|
+
export declare class PushError extends Error {
|
|
19
|
+
readonly status: number;
|
|
20
|
+
readonly responseBody: string;
|
|
21
|
+
/**
|
|
22
|
+
* Create a `PushError`.
|
|
23
|
+
*
|
|
24
|
+
* @param status - HTTP status code returned by the endpoint.
|
|
25
|
+
* @param responseBody - Response body text returned by the endpoint.
|
|
26
|
+
*/
|
|
27
|
+
constructor(status: number, responseBody: string);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Load push credentials from process env, falling back to the repo's `.js.env`.
|
|
31
|
+
*
|
|
32
|
+
* @param repoRoot - Absolute path to the repo root where `.js.env` may live.
|
|
33
|
+
* @returns The resolved push configuration.
|
|
34
|
+
*/
|
|
35
|
+
export declare function loadPushConfig(repoRoot: string): PushConfig;
|
|
36
|
+
/** Options for `pushBatch`. */
|
|
37
|
+
export type PushBatchOptions = {
|
|
38
|
+
/** Full URL of the remote-write endpoint. */
|
|
39
|
+
url: string;
|
|
40
|
+
/** HTTP Basic auth username. Omit for unauthenticated endpoints (e.g. prod via Cloudflare WARP). */
|
|
41
|
+
username?: string;
|
|
42
|
+
/** HTTP Basic auth password. Omit for unauthenticated endpoints (e.g. prod via Cloudflare WARP). */
|
|
43
|
+
password?: string;
|
|
44
|
+
/** When true, logs the body but does not POST. */
|
|
45
|
+
dryRun: boolean;
|
|
46
|
+
/** Logger instance for success and error messages. */
|
|
47
|
+
logger: Logger;
|
|
48
|
+
/** Fetch implementation; defaults to the global `fetch`. */
|
|
49
|
+
fetchImpl?: typeof fetch;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* POST a remote-write body to the configured Prometheus remote-write endpoint.
|
|
53
|
+
*
|
|
54
|
+
* @param body - Snappy-compressed protobuf `WriteRequest` bytes to push.
|
|
55
|
+
* @param options - Push configuration including URL, credentials, and optional fetch override.
|
|
56
|
+
*/
|
|
57
|
+
export declare function pushBatch(body: Uint8Array, options: PushBatchOptions): Promise<void>;
|
|
58
|
+
//# sourceMappingURL=push.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push.d.cts","sourceRoot":"","sources":["../../src/lib/push.ts"],"names":[],"mappings":"AAKA,oDAAoD;AACpD,MAAM,MAAM,UAAU,GAAG;IACvB,6CAA6C;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,oGAAoG;IACpG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oGAAoG;IACpG,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,oDAAoD;AACpD,MAAM,MAAM,MAAM,GAAG;IACnB,oCAAoC;IACpC,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACjE,4BAA4B;IAC5B,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CACnE,CAAC;AAEF,wEAAwE;AACxE,qBAAa,SAAU,SAAQ,KAAK;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAE9B;;;;;OAKG;gBACS,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;CAMjD;AAqCD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAgB3D;AAED,+BAA+B;AAC/B,MAAM,MAAM,gBAAgB,GAAG;IAC7B,6CAA6C;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,oGAAoG;IACpG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oGAAoG;IACpG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,MAAM,EAAE,OAAO,CAAC;IAChB,sDAAsD;IACtD,MAAM,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,SAAS,CAC7B,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,IAAI,CAAC,CA0Cf"}
|