@kids-reporter/logger 0.0.1 → 0.0.2

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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["export * from './types.js'\nexport * from './utils.js'\n"],"mappings":"AAAA,cAAc,YAAY;AAC1B,cAAc,YAAY","ignoreList":[]}
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"types.js","names":[],"sources":["../src/types.ts"],"sourcesContent":["export type LogSeverity =\n | 'DEBUG'\n | 'INFO'\n | 'NOTICE'\n | 'WARNING'\n | 'ERROR'\n | 'ALERT'\n | 'CRITICAL'\n\nexport type StructuredLogPayload = {\n severity: LogSeverity\n message?: string\n} & Record<string, unknown>\n\n/** Supports Express req.headers where values can be string | string[]. */\nexport type TraceHeaderInput =\n | Headers\n | Record<string, string | string[] | undefined | unknown>\n | undefined\n\n/** Trace context for GCP Cloud Logging correlation. Only traceId is propagated. */\nexport type NormalizedTraceContext = {\n traceId: string\n traceHeaders: {\n 'X-Cloud-Trace-Context': string\n }\n}\n"],"mappings":"","ignoreList":[]}
package/dist/utils.js CHANGED
@@ -1,129 +1,129 @@
1
1
  const XCLOUD_TRACE_HEADER = 'x-cloud-trace-context';
2
2
  const TRACE_ID_REGEX = /^[a-f0-9]{32}$/i;
3
3
  const CONSOLE_BY_SEVERITY = {
4
- ALERT: 'error',
5
- CRITICAL: 'error',
6
- ERROR: 'error',
7
- WARNING: 'warn',
8
- NOTICE: 'log',
9
- INFO: 'log',
10
- DEBUG: 'log',
4
+ ALERT: 'error',
5
+ CRITICAL: 'error',
6
+ ERROR: 'error',
7
+ WARNING: 'warn',
8
+ NOTICE: 'log',
9
+ INFO: 'log',
10
+ DEBUG: 'log'
11
11
  };
12
12
  function normalizeHeaderValue(value) {
13
- if (value === undefined || value === null) {
14
- return undefined;
15
- }
16
- if (typeof value === 'string') {
17
- return value;
18
- }
19
- if (Array.isArray(value) &&
20
- value.length > 0 &&
21
- typeof value[0] === 'string') {
22
- return value[0];
23
- }
13
+ if (value === undefined || value === null) {
24
14
  return undefined;
15
+ }
16
+ if (typeof value === 'string') {
17
+ return value;
18
+ }
19
+ if (Array.isArray(value) && value.length > 0 && typeof value[0] === 'string') {
20
+ return value[0];
21
+ }
22
+ return undefined;
25
23
  }
26
24
  function getHeaderValue(input, headerName) {
27
- if (!input) {
28
- return undefined;
29
- }
30
- if (typeof Headers !== 'undefined' && input instanceof Headers) {
31
- return input.get(headerName) || undefined;
32
- }
33
- const lowered = headerName.toLowerCase();
34
- for (const [key, value] of Object.entries(input)) {
35
- if (key.toLowerCase() === lowered) {
36
- return normalizeHeaderValue(value);
37
- }
38
- }
25
+ if (!input) {
39
26
  return undefined;
27
+ }
28
+ if (typeof Headers !== 'undefined' && input instanceof Headers) {
29
+ return input.get(headerName) || undefined;
30
+ }
31
+ const lowered = headerName.toLowerCase();
32
+ for (const [key, value] of Object.entries(input)) {
33
+ if (key.toLowerCase() === lowered) {
34
+ return normalizeHeaderValue(value);
35
+ }
36
+ }
37
+ return undefined;
40
38
  }
41
39
  function getRandomHex(length) {
42
- const bytes = new Uint8Array(Math.ceil(length / 2));
43
- if (globalThis.crypto &&
44
- typeof globalThis.crypto.getRandomValues === 'function') {
45
- globalThis.crypto.getRandomValues(bytes);
40
+ const bytes = new Uint8Array(Math.ceil(length / 2));
41
+ if (globalThis.crypto && typeof globalThis.crypto.getRandomValues === 'function') {
42
+ globalThis.crypto.getRandomValues(bytes);
43
+ } else {
44
+ for (let i = 0; i < bytes.length; i += 1) {
45
+ bytes[i] = Math.floor(Math.random() * 256);
46
46
  }
47
- else {
48
- for (let i = 0; i < bytes.length; i += 1) {
49
- bytes[i] = Math.floor(Math.random() * 256);
50
- }
51
- }
52
- return Array.from(bytes, (value) => value.toString(16).padStart(2, '0'))
53
- .join('')
54
- .slice(0, length);
47
+ }
48
+ return Array.from(bytes, value => value.toString(16).padStart(2, '0')).join('').slice(0, length);
55
49
  }
50
+
56
51
  /**
57
52
  * Parses traceId from GCP X-Cloud-Trace-Context.
58
53
  * Accepts "traceId;o=1" or "traceId/spanId;o=1" (spanId is ignored).
59
54
  */
60
55
  function parseXCloudTraceContext(xCloudTraceContext) {
61
- if (!xCloudTraceContext) {
62
- return undefined;
63
- }
64
- const [traceAndSpan] = xCloudTraceContext.trim().split(';');
65
- const traceId = traceAndSpan.split('/')[0]?.trim();
66
- if (!traceId || !TRACE_ID_REGEX.test(traceId)) {
67
- return undefined;
68
- }
69
- return traceId.toLowerCase();
56
+ if (!xCloudTraceContext) {
57
+ return undefined;
58
+ }
59
+ const [traceAndSpan] = xCloudTraceContext.trim().split(';');
60
+ const traceId = traceAndSpan.split('/')[0]?.trim();
61
+ if (!traceId || !TRACE_ID_REGEX.test(traceId)) {
62
+ return undefined;
63
+ }
64
+ return traceId.toLowerCase();
70
65
  }
66
+
67
+ // Overloads: when generateIfMissing is true, return is always NormalizedTraceContext
68
+ /* eslint-disable no-redeclare -- overload signatures + implementation */
69
+
71
70
  export function normalizeTraceContext(headersInput, options = {}) {
72
- /* eslint-enable no-redeclare */
73
- const shouldGenerate = options.generateIfMissing !== false;
74
- const xCloudTraceContext = getHeaderValue(headersInput, XCLOUD_TRACE_HEADER);
75
- const traceId = parseXCloudTraceContext(xCloudTraceContext);
76
- if (!traceId && !shouldGenerate) {
77
- return undefined;
71
+ /* eslint-enable no-redeclare */
72
+ const shouldGenerate = options.generateIfMissing !== false;
73
+ const xCloudTraceContext = getHeaderValue(headersInput, XCLOUD_TRACE_HEADER);
74
+ const traceId = parseXCloudTraceContext(xCloudTraceContext);
75
+ if (!traceId && !shouldGenerate) {
76
+ return undefined;
77
+ }
78
+ const resolvedTraceId = traceId ?? getRandomHex(32);
79
+ const xCloudValue = `${resolvedTraceId};o=1`;
80
+ return {
81
+ traceId: resolvedTraceId,
82
+ traceHeaders: {
83
+ 'X-Cloud-Trace-Context': xCloudValue
78
84
  }
79
- const resolvedTraceId = traceId ?? getRandomHex(32);
80
- const xCloudValue = `${resolvedTraceId};o=1`;
81
- return {
82
- traceId: resolvedTraceId,
83
- traceHeaders: {
84
- 'X-Cloud-Trace-Context': xCloudValue,
85
- },
86
- };
85
+ };
87
86
  }
88
- export function getGcpTraceField({ projectId, traceId, }) {
89
- if (!projectId || !traceId) {
90
- return undefined;
91
- }
92
- return `projects/${projectId}/traces/${traceId}`;
87
+ export function getGcpTraceField({
88
+ projectId,
89
+ traceId
90
+ }) {
91
+ if (!projectId || !traceId) {
92
+ return undefined;
93
+ }
94
+ return `projects/${projectId}/traces/${traceId}`;
93
95
  }
94
96
  export function getTraceLogFields(headersInput, options = {}) {
95
- const traceContext = normalizeTraceContext(headersInput, {
96
- generateIfMissing: options.generateIfMissing ?? false,
97
- });
98
- if (!traceContext) {
99
- return {};
100
- }
101
- const projectId = options.projectId ||
102
- process.env.GOOGLE_CLOUD_PROJECT ||
103
- process.env.GCP_PROJECT;
104
- const traceField = getGcpTraceField({
105
- projectId,
106
- traceId: traceContext.traceId,
107
- });
108
- return {
109
- ...(traceField ? { 'logging.googleapis.com/trace': traceField } : {}),
110
- traceId: traceContext.traceId,
111
- };
97
+ const traceContext = normalizeTraceContext(headersInput, {
98
+ generateIfMissing: options.generateIfMissing ?? false
99
+ });
100
+ if (!traceContext) {
101
+ return {};
102
+ }
103
+ const projectId = options.projectId || process.env.GOOGLE_CLOUD_PROJECT || process.env.GCP_PROJECT;
104
+ const traceField = getGcpTraceField({
105
+ projectId,
106
+ traceId: traceContext.traceId
107
+ });
108
+ return {
109
+ ...(traceField ? {
110
+ 'logging.googleapis.com/trace': traceField
111
+ } : {}),
112
+ traceId: traceContext.traceId
113
+ };
112
114
  }
113
115
  export function emitStructured(payload) {
114
- const severity = typeof payload?.severity === 'string'
115
- ? payload.severity.toUpperCase()
116
- : 'INFO';
117
- const method = CONSOLE_BY_SEVERITY[severity] || 'log';
118
- const message = JSON.stringify(payload);
119
- if (method === 'error') {
120
- console.error(message);
121
- return;
122
- }
123
- if (method === 'warn') {
124
- console.warn(message);
125
- return;
126
- }
127
- console.log(message);
116
+ const severity = typeof payload?.severity === 'string' ? payload.severity.toUpperCase() : 'INFO';
117
+ const method = CONSOLE_BY_SEVERITY[severity] || 'log';
118
+ const message = JSON.stringify(payload);
119
+ if (method === 'error') {
120
+ console.error(message);
121
+ return;
122
+ }
123
+ if (method === 'warn') {
124
+ console.warn(message);
125
+ return;
126
+ }
127
+ console.log(message);
128
128
  }
129
129
  //# sourceMappingURL=utils.js.map
package/dist/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","names":["XCLOUD_TRACE_HEADER","TRACE_ID_REGEX","CONSOLE_BY_SEVERITY","ALERT","CRITICAL","ERROR","WARNING","NOTICE","INFO","DEBUG","normalizeHeaderValue","value","undefined","Array","isArray","length","getHeaderValue","input","headerName","Headers","get","lowered","toLowerCase","key","Object","entries","getRandomHex","bytes","Uint8Array","Math","ceil","globalThis","crypto","getRandomValues","i","floor","random","from","toString","padStart","join","slice","parseXCloudTraceContext","xCloudTraceContext","traceAndSpan","trim","split","traceId","test","normalizeTraceContext","headersInput","options","shouldGenerate","generateIfMissing","resolvedTraceId","xCloudValue","traceHeaders","getGcpTraceField","projectId","getTraceLogFields","traceContext","process","env","GOOGLE_CLOUD_PROJECT","GCP_PROJECT","traceField","emitStructured","payload","severity","toUpperCase","method","message","JSON","stringify","console","error","warn","log"],"sources":["../src/utils.ts"],"sourcesContent":["import {\n NormalizedTraceContext,\n StructuredLogPayload,\n TraceHeaderInput,\n} from './types.js'\n\nconst XCLOUD_TRACE_HEADER = 'x-cloud-trace-context'\nconst TRACE_ID_REGEX = /^[a-f0-9]{32}$/i\n\nconst CONSOLE_BY_SEVERITY: Record<string, 'log' | 'warn' | 'error'> = {\n ALERT: 'error',\n CRITICAL: 'error',\n ERROR: 'error',\n WARNING: 'warn',\n NOTICE: 'log',\n INFO: 'log',\n DEBUG: 'log',\n}\n\nfunction normalizeHeaderValue(\n value: string | string[] | undefined | unknown\n): string | undefined {\n if (value === undefined || value === null) {\n return undefined\n }\n if (typeof value === 'string') {\n return value\n }\n if (\n Array.isArray(value) &&\n value.length > 0 &&\n typeof value[0] === 'string'\n ) {\n return value[0]\n }\n return undefined\n}\n\nfunction getHeaderValue(input: TraceHeaderInput, headerName: string) {\n if (!input) {\n return undefined\n }\n if (typeof Headers !== 'undefined' && input instanceof Headers) {\n return input.get(headerName) || undefined\n }\n const lowered = headerName.toLowerCase()\n for (const [key, value] of Object.entries(input)) {\n if (key.toLowerCase() === lowered) {\n return normalizeHeaderValue(value)\n }\n }\n return undefined\n}\n\nfunction getRandomHex(length: number) {\n const bytes = new Uint8Array(Math.ceil(length / 2))\n if (\n globalThis.crypto &&\n typeof globalThis.crypto.getRandomValues === 'function'\n ) {\n globalThis.crypto.getRandomValues(bytes)\n } else {\n for (let i = 0; i < bytes.length; i += 1) {\n bytes[i] = Math.floor(Math.random() * 256)\n }\n }\n return Array.from(bytes, (value) => value.toString(16).padStart(2, '0'))\n .join('')\n .slice(0, length)\n}\n\n/**\n * Parses traceId from GCP X-Cloud-Trace-Context.\n * Accepts \"traceId;o=1\" or \"traceId/spanId;o=1\" (spanId is ignored).\n */\nfunction parseXCloudTraceContext(\n xCloudTraceContext?: string\n): string | undefined {\n if (!xCloudTraceContext) {\n return undefined\n }\n const [traceAndSpan] = xCloudTraceContext.trim().split(';')\n const traceId = traceAndSpan.split('/')[0]?.trim()\n if (!traceId || !TRACE_ID_REGEX.test(traceId)) {\n return undefined\n }\n return traceId.toLowerCase()\n}\n\n// Overloads: when generateIfMissing is true, return is always NormalizedTraceContext\n/* eslint-disable no-redeclare -- overload signatures + implementation */\nexport function normalizeTraceContext(\n headersInput: TraceHeaderInput | undefined,\n options: { generateIfMissing: true }\n): NormalizedTraceContext\nexport function normalizeTraceContext(\n headersInput?: TraceHeaderInput,\n options?: { generateIfMissing?: boolean }\n): NormalizedTraceContext | undefined\nexport function normalizeTraceContext(\n headersInput?: TraceHeaderInput,\n options: { generateIfMissing?: boolean } = {}\n) {\n /* eslint-enable no-redeclare */\n const shouldGenerate = options.generateIfMissing !== false\n const xCloudTraceContext = getHeaderValue(headersInput, XCLOUD_TRACE_HEADER)\n const traceId = parseXCloudTraceContext(xCloudTraceContext)\n\n if (!traceId && !shouldGenerate) {\n return undefined\n }\n\n const resolvedTraceId = traceId ?? getRandomHex(32)\n const xCloudValue = `${resolvedTraceId};o=1`\n\n return {\n traceId: resolvedTraceId,\n traceHeaders: {\n 'X-Cloud-Trace-Context': xCloudValue,\n },\n }\n}\n\nexport function getGcpTraceField({\n projectId,\n traceId,\n}: {\n projectId?: string\n traceId: string\n}) {\n if (!projectId || !traceId) {\n return undefined\n }\n return `projects/${projectId}/traces/${traceId}`\n}\n\nexport function getTraceLogFields(\n headersInput?: TraceHeaderInput,\n options: { projectId?: string; generateIfMissing?: boolean } = {}\n) {\n const traceContext = normalizeTraceContext(headersInput, {\n generateIfMissing: options.generateIfMissing ?? false,\n })\n if (!traceContext) {\n return {}\n }\n\n const projectId =\n options.projectId ||\n process.env.GOOGLE_CLOUD_PROJECT ||\n process.env.GCP_PROJECT\n const traceField = getGcpTraceField({\n projectId,\n traceId: traceContext.traceId,\n })\n\n return {\n ...(traceField ? { 'logging.googleapis.com/trace': traceField } : {}),\n traceId: traceContext.traceId,\n }\n}\n\nexport function emitStructured(payload: StructuredLogPayload) {\n const severity =\n typeof payload?.severity === 'string'\n ? payload.severity.toUpperCase()\n : 'INFO'\n const method = CONSOLE_BY_SEVERITY[severity] || 'log'\n const message = JSON.stringify(payload)\n\n if (method === 'error') {\n console.error(message)\n return\n }\n if (method === 'warn') {\n console.warn(message)\n return\n }\n console.log(message)\n}\n"],"mappings":"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","ignoreList":[]}
package/package.json CHANGED
@@ -1,9 +1,12 @@
1
1
  {
2
2
  "name": "@kids-reporter/logger",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Shared structured logger for Kids Reporter services",
7
+ "files": [
8
+ "dist"
9
+ ],
7
10
  "main": "./dist/index.js",
8
11
  "types": "./dist/index.d.ts",
9
12
  "exports": {
@@ -14,13 +17,19 @@
14
17
  }
15
18
  },
16
19
  "scripts": {
17
- "build": "tsc -p tsconfig.json",
18
- "postinstall": "yarn build",
20
+ "build": "./scripts/build.sh",
19
21
  "lint:check": "eslint src --config ./eslint.config.mjs --ext .ts",
20
22
  "type-check": "tsc --noEmit -p tsconfig.json"
21
23
  },
22
24
  "devDependencies": {
23
- "eslint": "^9.0.0",
25
+ "@babel/cli": "^7.18.5",
26
+ "@babel/core": "^7.18.5",
27
+ "@babel/plugin-transform-runtime": "^7.18.5",
28
+ "@babel/preset-env": "^7.18.2",
29
+ "@babel/preset-typescript": "^7.17.12",
24
30
  "typescript": "^5.9.2"
31
+ },
32
+ "dependencies": {
33
+ "@babel/runtime": "^7.18.5"
25
34
  }
26
35
  }
package/eslint.config.mjs DELETED
@@ -1,22 +0,0 @@
1
- import baseConfig, {
2
- nodeConfig,
3
- typescriptConfig,
4
- } from '../../eslint.base.config.mjs'
5
-
6
- export default [
7
- ...baseConfig,
8
- {
9
- ...typescriptConfig,
10
- files: ['src/**/*.ts'],
11
- rules: {
12
- ...typescriptConfig.rules,
13
- },
14
- },
15
- {
16
- ...nodeConfig,
17
- files: ['**/*.config.{js,mjs,cjs}'],
18
- },
19
- {
20
- ignores: ['node_modules/**', 'dist/**'],
21
- },
22
- ]
package/src/index.ts DELETED
@@ -1,2 +0,0 @@
1
- export * from './types.js'
2
- export * from './utils.js'
package/src/types.ts DELETED
@@ -1,27 +0,0 @@
1
- export type LogSeverity =
2
- | 'DEBUG'
3
- | 'INFO'
4
- | 'NOTICE'
5
- | 'WARNING'
6
- | 'ERROR'
7
- | 'ALERT'
8
- | 'CRITICAL'
9
-
10
- export type StructuredLogPayload = {
11
- severity: LogSeverity
12
- message?: string
13
- } & Record<string, unknown>
14
-
15
- /** Supports Express req.headers where values can be string | string[]. */
16
- export type TraceHeaderInput =
17
- | Headers
18
- | Record<string, string | string[] | undefined | unknown>
19
- | undefined
20
-
21
- /** Trace context for GCP Cloud Logging correlation. Only traceId is propagated. */
22
- export type NormalizedTraceContext = {
23
- traceId: string
24
- traceHeaders: {
25
- 'X-Cloud-Trace-Context': string
26
- }
27
- }
package/src/utils.ts DELETED
@@ -1,180 +0,0 @@
1
- import {
2
- NormalizedTraceContext,
3
- StructuredLogPayload,
4
- TraceHeaderInput,
5
- } from './types.js'
6
-
7
- const XCLOUD_TRACE_HEADER = 'x-cloud-trace-context'
8
- const TRACE_ID_REGEX = /^[a-f0-9]{32}$/i
9
-
10
- const CONSOLE_BY_SEVERITY: Record<string, 'log' | 'warn' | 'error'> = {
11
- ALERT: 'error',
12
- CRITICAL: 'error',
13
- ERROR: 'error',
14
- WARNING: 'warn',
15
- NOTICE: 'log',
16
- INFO: 'log',
17
- DEBUG: 'log',
18
- }
19
-
20
- function normalizeHeaderValue(
21
- value: string | string[] | undefined | unknown
22
- ): string | undefined {
23
- if (value === undefined || value === null) {
24
- return undefined
25
- }
26
- if (typeof value === 'string') {
27
- return value
28
- }
29
- if (
30
- Array.isArray(value) &&
31
- value.length > 0 &&
32
- typeof value[0] === 'string'
33
- ) {
34
- return value[0]
35
- }
36
- return undefined
37
- }
38
-
39
- function getHeaderValue(input: TraceHeaderInput, headerName: string) {
40
- if (!input) {
41
- return undefined
42
- }
43
- if (typeof Headers !== 'undefined' && input instanceof Headers) {
44
- return input.get(headerName) || undefined
45
- }
46
- const lowered = headerName.toLowerCase()
47
- for (const [key, value] of Object.entries(input)) {
48
- if (key.toLowerCase() === lowered) {
49
- return normalizeHeaderValue(value)
50
- }
51
- }
52
- return undefined
53
- }
54
-
55
- function getRandomHex(length: number) {
56
- const bytes = new Uint8Array(Math.ceil(length / 2))
57
- if (
58
- globalThis.crypto &&
59
- typeof globalThis.crypto.getRandomValues === 'function'
60
- ) {
61
- globalThis.crypto.getRandomValues(bytes)
62
- } else {
63
- for (let i = 0; i < bytes.length; i += 1) {
64
- bytes[i] = Math.floor(Math.random() * 256)
65
- }
66
- }
67
- return Array.from(bytes, (value) => value.toString(16).padStart(2, '0'))
68
- .join('')
69
- .slice(0, length)
70
- }
71
-
72
- /**
73
- * Parses traceId from GCP X-Cloud-Trace-Context.
74
- * Accepts "traceId;o=1" or "traceId/spanId;o=1" (spanId is ignored).
75
- */
76
- function parseXCloudTraceContext(
77
- xCloudTraceContext?: string
78
- ): string | undefined {
79
- if (!xCloudTraceContext) {
80
- return undefined
81
- }
82
- const [traceAndSpan] = xCloudTraceContext.trim().split(';')
83
- const traceId = traceAndSpan.split('/')[0]?.trim()
84
- if (!traceId || !TRACE_ID_REGEX.test(traceId)) {
85
- return undefined
86
- }
87
- return traceId.toLowerCase()
88
- }
89
-
90
- // Overloads: when generateIfMissing is true, return is always NormalizedTraceContext
91
- /* eslint-disable no-redeclare -- overload signatures + implementation */
92
- export function normalizeTraceContext(
93
- headersInput: TraceHeaderInput | undefined,
94
- options: { generateIfMissing: true }
95
- ): NormalizedTraceContext
96
- export function normalizeTraceContext(
97
- headersInput?: TraceHeaderInput,
98
- options?: { generateIfMissing?: boolean }
99
- ): NormalizedTraceContext | undefined
100
- export function normalizeTraceContext(
101
- headersInput?: TraceHeaderInput,
102
- options: { generateIfMissing?: boolean } = {}
103
- ) {
104
- /* eslint-enable no-redeclare */
105
- const shouldGenerate = options.generateIfMissing !== false
106
- const xCloudTraceContext = getHeaderValue(headersInput, XCLOUD_TRACE_HEADER)
107
- const traceId = parseXCloudTraceContext(xCloudTraceContext)
108
-
109
- if (!traceId && !shouldGenerate) {
110
- return undefined
111
- }
112
-
113
- const resolvedTraceId = traceId ?? getRandomHex(32)
114
- const xCloudValue = `${resolvedTraceId};o=1`
115
-
116
- return {
117
- traceId: resolvedTraceId,
118
- traceHeaders: {
119
- 'X-Cloud-Trace-Context': xCloudValue,
120
- },
121
- }
122
- }
123
-
124
- export function getGcpTraceField({
125
- projectId,
126
- traceId,
127
- }: {
128
- projectId?: string
129
- traceId: string
130
- }) {
131
- if (!projectId || !traceId) {
132
- return undefined
133
- }
134
- return `projects/${projectId}/traces/${traceId}`
135
- }
136
-
137
- export function getTraceLogFields(
138
- headersInput?: TraceHeaderInput,
139
- options: { projectId?: string; generateIfMissing?: boolean } = {}
140
- ) {
141
- const traceContext = normalizeTraceContext(headersInput, {
142
- generateIfMissing: options.generateIfMissing ?? false,
143
- })
144
- if (!traceContext) {
145
- return {}
146
- }
147
-
148
- const projectId =
149
- options.projectId ||
150
- process.env.GOOGLE_CLOUD_PROJECT ||
151
- process.env.GCP_PROJECT
152
- const traceField = getGcpTraceField({
153
- projectId,
154
- traceId: traceContext.traceId,
155
- })
156
-
157
- return {
158
- ...(traceField ? { 'logging.googleapis.com/trace': traceField } : {}),
159
- traceId: traceContext.traceId,
160
- }
161
- }
162
-
163
- export function emitStructured(payload: StructuredLogPayload) {
164
- const severity =
165
- typeof payload?.severity === 'string'
166
- ? payload.severity.toUpperCase()
167
- : 'INFO'
168
- const method = CONSOLE_BY_SEVERITY[severity] || 'log'
169
- const message = JSON.stringify(payload)
170
-
171
- if (method === 'error') {
172
- console.error(message)
173
- return
174
- }
175
- if (method === 'warn') {
176
- console.warn(message)
177
- return
178
- }
179
- console.log(message)
180
- }
package/tsconfig.json DELETED
@@ -1,17 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "ESNext",
5
- "moduleResolution": "bundler",
6
- "rootDir": "./src",
7
- "outDir": "./dist",
8
- "declaration": true,
9
- "declarationMap": true,
10
- "sourceMap": true,
11
- "noEmit": false,
12
- "strict": true,
13
- "skipLibCheck": true
14
- },
15
- "include": ["src/**/*.ts"],
16
- "exclude": ["node_modules", "dist"]
17
- }