@cedarjs/cli-helpers 8.0.0-canary.3599 → 8.0.0-canary.3601

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.
@@ -1,24 +1,3 @@
1
- import type { AttributeValue, Span } from '@opentelemetry/api';
2
- export { redactError, redactErrorMessage } from './redact.js';
3
- type TelemetryAttributes = {
4
- [key: string]: AttributeValue | undefined;
5
- };
6
- /**
7
- * Safely records attributes to the opentelemetry span
8
- *
9
- * @param attributes An object of key-value pairs to be individually recorded as attributes
10
- * @param span An optional span to record the attributes to. If not provided, the current active span will be used
11
- */
12
- export declare function recordTelemetryAttributes(attributes: TelemetryAttributes, span?: Span): void;
13
- /**
14
- * Safely records an error to the opentelemetry span
15
- *
16
- * Only a redacted version of the error is recorded: the first line of the
17
- * message, with URLs and file paths replaced by placeholders, and no stack
18
- * trace. See `redactErrorMessage`.
19
- *
20
- * @param error An error to record to the span
21
- * @param span An optional span to record the error to. If not provided, the current active span will be used
22
- */
23
- export declare function recordTelemetryError(error: unknown, span?: Span): void;
1
+ export { recordTelemetryAttributes, recordTelemetryError, } from '@cedarjs/telemetry/record';
2
+ export type { TelemetryAttributes, TelemetryAttributeValue, } from '@cedarjs/telemetry/record';
24
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/telemetry/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAA;AAK9D,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAE7D,KAAK,mBAAmB,GAAG;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAAA;CAC1C,CAAA;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,mBAAmB,EAC/B,IAAI,CAAC,EAAE,IAAI,QAaZ;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,QAa/D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/telemetry/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,2BAA2B,CAAA;AAClC,YAAY,EACV,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,2BAA2B,CAAA"}
@@ -1,32 +1,8 @@
1
- import opentelemetry, { SpanStatusCode } from "@opentelemetry/api";
2
- import { redactError } from "./redact.js";
3
- import { redactError as redactError2, redactErrorMessage } from "./redact.js";
4
- function recordTelemetryAttributes(attributes, span) {
5
- const spanToRecord = span ?? opentelemetry.trace.getActiveSpan();
6
- if (spanToRecord === void 0) {
7
- return;
8
- }
9
- for (const [key, value] of Object.entries(attributes)) {
10
- if (value !== void 0) {
11
- spanToRecord.setAttribute(key, value);
12
- }
13
- }
14
- }
15
- function recordTelemetryError(error, span) {
16
- const spanToRecord = span ?? opentelemetry.trace.getActiveSpan();
17
- if (spanToRecord === void 0) {
18
- return;
19
- }
20
- const redacted = redactError(error ?? "Unknown error");
21
- spanToRecord.setStatus({
22
- code: SpanStatusCode.ERROR,
23
- message: redacted.message
24
- });
25
- spanToRecord.recordException(redacted);
26
- }
1
+ import {
2
+ recordTelemetryAttributes,
3
+ recordTelemetryError
4
+ } from "@cedarjs/telemetry/record";
27
5
  export {
28
6
  recordTelemetryAttributes,
29
- recordTelemetryError,
30
- redactError2 as redactError,
31
- redactErrorMessage
7
+ recordTelemetryError
32
8
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cedarjs/cli-helpers",
3
- "version": "8.0.0-canary.3599",
3
+ "version": "8.0.0-canary.3601",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/cedarjs/cedar.git",
@@ -125,10 +125,9 @@
125
125
  "test:watch": "vitest watch"
126
126
  },
127
127
  "dependencies": {
128
- "@cedarjs/project-config": "8.0.0-canary.3599",
129
- "@cedarjs/telemetry": "8.0.0-canary.3599",
128
+ "@cedarjs/project-config": "8.0.0-canary.3601",
129
+ "@cedarjs/telemetry": "8.0.0-canary.3601",
130
130
  "@listr2/prompt-adapter-enquirer": "4.4.3",
131
- "@opentelemetry/api": "1.9.1",
132
131
  "ansis": "4.4.0",
133
132
  "dotenv": "16.6.1",
134
133
  "dotenv-defaults": "5.0.2",
@@ -146,7 +145,7 @@
146
145
  "yargs-parser": "21.1.1"
147
146
  },
148
147
  "devDependencies": {
149
- "@cedarjs/framework-tools": "8.0.0-canary.3599",
148
+ "@cedarjs/framework-tools": "8.0.0-canary.3601",
150
149
  "@types/dotenv-defaults": "^5.0.0",
151
150
  "@types/lodash": "4.17.27",
152
151
  "@types/pascalcase": "1.0.3",
@@ -1,27 +0,0 @@
1
- /**
2
- * Turns an error (or any thrown value) into a message that is safe to send
3
- * with telemetry.
4
- *
5
- * Only the first line is kept, because some errors include the full stack
6
- * trace in the message. Then every word that could identify a user, their
7
- * project or their infrastructure is replaced: anything containing `/`, `\`,
8
- * `@` or `:`, and IPv4 addresses. Replacements are labelled `[url]`, `[host]`,
9
- * `[path]` or `[redacted]`. Quoted paths are replaced as a whole, since they
10
- * can contain spaces, and so are hostnames in DNS errors.
11
- *
12
- * Words that describe the failure without identifying anyone are kept:
13
- * scoped package names (`@cedarjs/vite`), known specifiers (`node:fs`),
14
- * version numbers, clock times and words that only end in a colon (`Error:`).
15
- * What is left is the shape of the error, e.g.
16
- * `ENOENT: no such file or directory, open '[path]'`.
17
- *
18
- * This module has no imports so it can be bundled into create-cedar-app
19
- * without pulling in anything else.
20
- */
21
- export declare function redactErrorMessage(error: unknown): string;
22
- /**
23
- * Returns a new Error that only carries the redacted message of `error`.
24
- * The original stack trace is left out, since it contains file paths.
25
- */
26
- export declare function redactError(error: unknown): Error;
27
- //# sourceMappingURL=redact.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../../src/telemetry/redact.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAwBzD;AA2FD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAYjD"}
@@ -1,78 +0,0 @@
1
- function redactErrorMessage(error) {
2
- const message = error instanceof Error ? error.message : typeof error === "string" ? error : String(error);
3
- return (message.split("\n")[0] || "Unknown error").replace(
4
- /(['"`])([^'"`\\/\n]*[\\/][^'"`\n]*)\1/g,
5
- (_match, quote, inner) => `${quote}${isSafeWord(inner) ? inner : placeholderFor(inner)}${quote}`
6
- ).replace(/\b(ENOTFOUND|EAI_AGAIN)\s+[^\s'"`]+/g, "$1 [host]").replace(/\S+/g, redactWord);
7
- }
8
- const SCOPED_PACKAGE = /^@[a-z0-9~-][\w.~-]*\/[a-z0-9~-][\w.~-]*(?:\/[\w.-]+)*(?:@[\w.^~*<>=-]+)?$/i;
9
- const KNOWN_SPECIFIER = /^(?:node|npm|workspace|catalog):[\w.^~*<>=-]*$/;
10
- const CLOCK_TIME = /^\d{1,2}:\d{2}(?::\d{2})?$/;
11
- const IPV4 = /(?:^|[^\d.])\d{1,3}(?:\.\d{1,3}){3}(?![.\d])/;
12
- const IPV6 = /^\[?[\da-f]*:[\da-f]*:[\da-f:]*\]?(?::\d+)?$/i;
13
- const HOST_AND_PORT = /^[\w.-]+:\d+$/;
14
- const LEADING_PUNCTUATION = /* @__PURE__ */ new Set(["(", "'", '"', "`", "<", "[", "{"]);
15
- const TRAILING_PUNCTUATION = /* @__PURE__ */ new Set([
16
- ")",
17
- "'",
18
- '"',
19
- "`",
20
- ">",
21
- "]",
22
- "}",
23
- ",",
24
- ";",
25
- ".",
26
- "!",
27
- "?"
28
- ]);
29
- function isSafeWord(word) {
30
- if (!/[/\\@:]/.test(word) && !IPV4.test(word)) {
31
- return true;
32
- }
33
- return SCOPED_PACKAGE.test(word) || KNOWN_SPECIFIER.test(word) || word.startsWith("npm:") && SCOPED_PACKAGE.test(word.slice(4)) || CLOCK_TIME.test(word);
34
- }
35
- function placeholderFor(word) {
36
- if (word.includes("://")) {
37
- return "[url]";
38
- }
39
- if (IPV4.test(word) || IPV6.test(word) || HOST_AND_PORT.test(word)) {
40
- return "[host]";
41
- }
42
- if (/[/\\]/.test(word)) {
43
- return "[path]";
44
- }
45
- return "[redacted]";
46
- }
47
- function redactWord(word) {
48
- let start = 0;
49
- let end = word.length;
50
- while (end > start && TRAILING_PUNCTUATION.has(word[end - 1])) {
51
- end--;
52
- }
53
- const withoutTrailing = word.slice(0, end);
54
- if (!CLOCK_TIME.test(withoutTrailing) && IPV6.test(withoutTrailing)) {
55
- return "[host]" + word.slice(end);
56
- }
57
- while (start < end && LEADING_PUNCTUATION.has(word[start])) {
58
- start++;
59
- }
60
- const core = word.slice(start, end);
61
- const checked = core.endsWith(":") ? core.slice(0, -1) : core;
62
- if (checked === "" || isSafeWord(checked)) {
63
- return word;
64
- }
65
- return word.slice(0, start) + placeholderFor(core) + word.slice(end);
66
- }
67
- function redactError(error) {
68
- const redacted = new Error(redactErrorMessage(error));
69
- if (error instanceof Error) {
70
- redacted.name = error.name;
71
- }
72
- redacted.stack = `${redacted.name}: ${redacted.message}`;
73
- return redacted;
74
- }
75
- export {
76
- redactError,
77
- redactErrorMessage
78
- };