securenow 4.0.9 → 4.0.12
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/nextjs-auto-capture.d.ts +33 -0
- package/nextjs-middleware.d.ts +57 -0
- package/nextjs-wrapper.d.ts +95 -0
- package/nextjs.d.ts +87 -0
- package/nextjs.js +78 -27
- package/package.json +37 -9
- package/register.d.ts +75 -0
- package/tracing.d.ts +89 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SecureNow Next.js Automatic Body Capture TypeScript Declarations
|
|
3
|
+
*
|
|
4
|
+
* This module automatically patches Request.prototype methods to capture
|
|
5
|
+
* request bodies when they are first read by the application.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* // instrumentation.ts
|
|
10
|
+
* import { registerSecureNow } from 'securenow/nextjs';
|
|
11
|
+
* import 'securenow/nextjs-auto-capture'; // Auto-patches Request methods
|
|
12
|
+
*
|
|
13
|
+
* export function register() {
|
|
14
|
+
* registerSecureNow();
|
|
15
|
+
* }
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* Environment Variables:
|
|
19
|
+
* - SECURENOW_CAPTURE_BODY=1 - Enable body capture (default: disabled)
|
|
20
|
+
* - SECURENOW_MAX_BODY_SIZE=10240 - Max body size in bytes (default: 10KB)
|
|
21
|
+
* - SECURENOW_SENSITIVE_FIELDS=field1,field2 - Additional sensitive fields to redact
|
|
22
|
+
*
|
|
23
|
+
* Features:
|
|
24
|
+
* - Zero code changes required in API routes
|
|
25
|
+
* - Automatically captures JSON, GraphQL, and form data
|
|
26
|
+
* - Redacts sensitive fields (passwords, tokens, etc.)
|
|
27
|
+
* - Handles request.clone() properly
|
|
28
|
+
* - No stream conflicts with Next.js
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
// This module has side effects (patches Request.prototype)
|
|
32
|
+
// No exports, just import it to enable automatic body capture
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SecureNow Next.js Middleware TypeScript Declarations
|
|
3
|
+
*
|
|
4
|
+
* Provides middleware for capturing request bodies in Next.js API routes.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { NextRequest, NextResponse } from 'next/server';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Next.js middleware function for request body capture
|
|
11
|
+
*
|
|
12
|
+
* @param request - Next.js request object
|
|
13
|
+
* @returns Promise<NextResponse> - Passes through to next handler
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* // middleware.ts
|
|
18
|
+
* import { NextRequest, NextResponse } from 'next/server';
|
|
19
|
+
* import { middleware as securenowMiddleware } from 'securenow/nextjs-middleware';
|
|
20
|
+
*
|
|
21
|
+
* export async function middleware(request: NextRequest) {
|
|
22
|
+
* // Capture body with SecureNow
|
|
23
|
+
* await securenowMiddleware(request);
|
|
24
|
+
*
|
|
25
|
+
* // Your custom middleware logic
|
|
26
|
+
* return NextResponse.next();
|
|
27
|
+
* }
|
|
28
|
+
*
|
|
29
|
+
* export const config = {
|
|
30
|
+
* matcher: '/api/:path*',
|
|
31
|
+
* };
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export function middleware(request: NextRequest): Promise<NextResponse>;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Configuration options for body capture middleware
|
|
38
|
+
*/
|
|
39
|
+
export interface BodyCaptureOptions {
|
|
40
|
+
/**
|
|
41
|
+
* Maximum body size to capture in bytes
|
|
42
|
+
* @default 10240 (10KB)
|
|
43
|
+
*/
|
|
44
|
+
maxBodySize?: number;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Additional sensitive field names to redact
|
|
48
|
+
* @default []
|
|
49
|
+
*/
|
|
50
|
+
sensitiveFields?: string[];
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Enable body capture
|
|
54
|
+
* @default true
|
|
55
|
+
*/
|
|
56
|
+
enabled?: boolean;
|
|
57
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SecureNow Next.js API Route Wrapper TypeScript Declarations
|
|
3
|
+
*
|
|
4
|
+
* Provides a higher-order function to wrap Next.js API routes for body capture.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { NextRequest } from 'next/server';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Next.js API route handler type
|
|
11
|
+
*/
|
|
12
|
+
export type NextApiHandler = (
|
|
13
|
+
request: NextRequest,
|
|
14
|
+
context?: any
|
|
15
|
+
) => Promise<Response> | Response;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Wrap a Next.js API route handler to enable body capture
|
|
19
|
+
*
|
|
20
|
+
* @param handler - Your API route handler function
|
|
21
|
+
* @returns Wrapped handler with body capture enabled
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* // app/api/users/route.ts
|
|
26
|
+
* import { NextRequest } from 'next/server';
|
|
27
|
+
* import { withSecureNow } from 'securenow/nextjs-wrapper';
|
|
28
|
+
*
|
|
29
|
+
* async function handler(request: NextRequest) {
|
|
30
|
+
* const body = await request.json();
|
|
31
|
+
* // Your logic here
|
|
32
|
+
* return Response.json({ success: true });
|
|
33
|
+
* }
|
|
34
|
+
*
|
|
35
|
+
* export const POST = withSecureNow(handler);
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* // With TypeScript types
|
|
41
|
+
* import { NextRequest } from 'next/server';
|
|
42
|
+
* import { withSecureNow } from 'securenow/nextjs-wrapper';
|
|
43
|
+
*
|
|
44
|
+
* interface CreateUserBody {
|
|
45
|
+
* email: string;
|
|
46
|
+
* name: string;
|
|
47
|
+
* }
|
|
48
|
+
*
|
|
49
|
+
* async function createUser(request: NextRequest) {
|
|
50
|
+
* const body: CreateUserBody = await request.json();
|
|
51
|
+
* // Body is automatically captured and redacted in traces
|
|
52
|
+
* return Response.json({ id: 123 });
|
|
53
|
+
* }
|
|
54
|
+
*
|
|
55
|
+
* export const POST = withSecureNow(createUser);
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export function withSecureNow<T extends NextApiHandler>(
|
|
59
|
+
handler: T
|
|
60
|
+
): T;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Configuration options for the wrapper
|
|
64
|
+
*/
|
|
65
|
+
export interface WrapperOptions {
|
|
66
|
+
/**
|
|
67
|
+
* Maximum body size to capture in bytes
|
|
68
|
+
* @default 10240 (10KB)
|
|
69
|
+
*/
|
|
70
|
+
maxBodySize?: number;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Additional sensitive field names to redact
|
|
74
|
+
* @default []
|
|
75
|
+
*/
|
|
76
|
+
sensitiveFields?: string[];
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Enable body capture
|
|
80
|
+
* @default true
|
|
81
|
+
*/
|
|
82
|
+
enabled?: boolean;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Wrap a Next.js API route handler with custom options
|
|
87
|
+
*
|
|
88
|
+
* @param handler - Your API route handler function
|
|
89
|
+
* @param options - Configuration options
|
|
90
|
+
* @returns Wrapped handler with body capture enabled
|
|
91
|
+
*/
|
|
92
|
+
export function withSecureNowOptions<T extends NextApiHandler>(
|
|
93
|
+
handler: T,
|
|
94
|
+
options: WrapperOptions
|
|
95
|
+
): T;
|
package/nextjs.d.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SecureNow Next.js Integration TypeScript Declarations
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface RegisterOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Service name for OpenTelemetry traces
|
|
8
|
+
* @default process.env.SECURENOW_APPID || process.env.OTEL_SERVICE_NAME
|
|
9
|
+
*/
|
|
10
|
+
serviceName?: string;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* OTLP endpoint for traces
|
|
14
|
+
* @default process.env.SECURENOW_INSTANCE || 'http://46.62.173.237:4318'
|
|
15
|
+
*/
|
|
16
|
+
endpoint?: string;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Don't append UUID to service name
|
|
20
|
+
* @default false
|
|
21
|
+
*/
|
|
22
|
+
noUuid?: boolean;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Enable request body capture (Next.js middleware required)
|
|
26
|
+
* @default false
|
|
27
|
+
*/
|
|
28
|
+
captureBody?: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Register SecureNow OpenTelemetry instrumentation for Next.js
|
|
33
|
+
*
|
|
34
|
+
* @param options - Optional configuration options
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* // instrumentation.ts
|
|
39
|
+
* import { registerSecureNow } from 'securenow/nextjs';
|
|
40
|
+
*
|
|
41
|
+
* export function register() {
|
|
42
|
+
* registerSecureNow();
|
|
43
|
+
* }
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* // With custom options
|
|
49
|
+
* import { registerSecureNow } from 'securenow/nextjs';
|
|
50
|
+
*
|
|
51
|
+
* export function register() {
|
|
52
|
+
* registerSecureNow({
|
|
53
|
+
* serviceName: 'my-nextjs-app',
|
|
54
|
+
* endpoint: 'http://signoz.company.com:4318',
|
|
55
|
+
* noUuid: true,
|
|
56
|
+
* });
|
|
57
|
+
* }
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export function registerSecureNow(options?: RegisterOptions): void;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Default sensitive fields that are automatically redacted from traces
|
|
64
|
+
*/
|
|
65
|
+
export const DEFAULT_SENSITIVE_FIELDS: readonly string[];
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Redact sensitive fields from an object
|
|
69
|
+
* @param obj - Object to redact
|
|
70
|
+
* @param sensitiveFields - Array of field names to redact (case-insensitive substring match)
|
|
71
|
+
* @returns Redacted copy of the object
|
|
72
|
+
*/
|
|
73
|
+
export function redactSensitiveData<T = any>(
|
|
74
|
+
obj: T,
|
|
75
|
+
sensitiveFields?: string[]
|
|
76
|
+
): T;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Redact sensitive data from GraphQL query strings
|
|
80
|
+
* @param query - GraphQL query string
|
|
81
|
+
* @param sensitiveFields - Array of field names to redact
|
|
82
|
+
* @returns Redacted query string
|
|
83
|
+
*/
|
|
84
|
+
export function redactGraphQLQuery(
|
|
85
|
+
query: string,
|
|
86
|
+
sensitiveFields?: string[]
|
|
87
|
+
): string;
|
package/nextjs.js
CHANGED
|
@@ -23,6 +23,16 @@ const { v4: uuidv4 } = require('uuid');
|
|
|
23
23
|
|
|
24
24
|
const env = k => process.env[k] ?? process.env[k.toUpperCase()] ?? process.env[k.toLowerCase()];
|
|
25
25
|
|
|
26
|
+
const parseHeaders = str => {
|
|
27
|
+
const out = {}; if (!str) return out;
|
|
28
|
+
for (const raw of String(str).split(',')) {
|
|
29
|
+
const s = raw.trim(); if (!s) continue;
|
|
30
|
+
const i = s.indexOf('='); if (i === -1) continue;
|
|
31
|
+
out[s.slice(0, i).trim().toLowerCase()] = s.slice(i + 1).trim();
|
|
32
|
+
}
|
|
33
|
+
return out;
|
|
34
|
+
};
|
|
35
|
+
|
|
26
36
|
let isRegistered = false;
|
|
27
37
|
|
|
28
38
|
// Default sensitive fields to redact from request bodies
|
|
@@ -215,6 +225,9 @@ function registerSecureNow(options = {}) {
|
|
|
215
225
|
return;
|
|
216
226
|
}
|
|
217
227
|
|
|
228
|
+
// Detect environment outside try block for error handling
|
|
229
|
+
const isVercel = !!(env('VERCEL') || env('VERCEL_ENV') || env('VERCEL_URL'));
|
|
230
|
+
|
|
218
231
|
try {
|
|
219
232
|
console.log('[securenow] Next.js integration loading (pid=%d)', process.pid);
|
|
220
233
|
|
|
@@ -264,8 +277,12 @@ function registerSecureNow(options = {}) {
|
|
|
264
277
|
const customSensitiveFields = (env('SECURENOW_SENSITIVE_FIELDS') || '').split(',').map(s => s.trim()).filter(Boolean);
|
|
265
278
|
const allSensitiveFields = [...DEFAULT_SENSITIVE_FIELDS, ...customSensitiveFields];
|
|
266
279
|
|
|
267
|
-
// --------
|
|
268
|
-
|
|
280
|
+
// -------- Log environment detection --------
|
|
281
|
+
if (!isVercel) {
|
|
282
|
+
console.log('[securenow] 🖥️ Self-hosted environment detected (EC2/PM2) - using vanilla SDK');
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// -------- Use different initialization based on environment --------
|
|
269
286
|
const { HttpInstrumentation } = require('@opentelemetry/instrumentation-http');
|
|
270
287
|
|
|
271
288
|
// Configure HTTP instrumentation with comprehensive header capture
|
|
@@ -433,31 +450,61 @@ function registerSecureNow(options = {}) {
|
|
|
433
450
|
},
|
|
434
451
|
});
|
|
435
452
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
// Propagate context to your backend APIs
|
|
447
|
-
propagateContextUrls: [
|
|
448
|
-
/^https?:\/\/localhost/,
|
|
449
|
-
/^https?:\/\/.*\.vercel\.app/,
|
|
450
|
-
// Add your backend domains here
|
|
451
|
-
],
|
|
452
|
-
// Optionally ignore certain URLs
|
|
453
|
-
ignoreUrls: [
|
|
454
|
-
/_next\/static/,
|
|
455
|
-
/_next\/image/,
|
|
456
|
-
/\.map$/,
|
|
457
|
-
],
|
|
453
|
+
if (isVercel) {
|
|
454
|
+
// -------- Vercel Environment: Use @vercel/otel --------
|
|
455
|
+
const { registerOTel } = require('@vercel/otel');
|
|
456
|
+
|
|
457
|
+
registerOTel({
|
|
458
|
+
serviceName: serviceName,
|
|
459
|
+
attributes: {
|
|
460
|
+
'deployment.environment': env('NODE_ENV') || env('VERCEL_ENV') || 'development',
|
|
461
|
+
'service.version': process.env.npm_package_version || process.env.VERCEL_GIT_COMMIT_SHA || undefined,
|
|
462
|
+
'vercel.region': process.env.VERCEL_REGION || undefined,
|
|
458
463
|
},
|
|
459
|
-
|
|
460
|
-
|
|
464
|
+
instrumentations: [httpInstrumentation],
|
|
465
|
+
instrumentationConfig: {
|
|
466
|
+
fetch: {
|
|
467
|
+
// Propagate context to your backend APIs
|
|
468
|
+
propagateContextUrls: [
|
|
469
|
+
/^https?:\/\/localhost/,
|
|
470
|
+
/^https?:\/\/.*\.vercel\.app/,
|
|
471
|
+
// Add your backend domains here
|
|
472
|
+
],
|
|
473
|
+
// Optionally ignore certain URLs
|
|
474
|
+
ignoreUrls: [
|
|
475
|
+
/_next\/static/,
|
|
476
|
+
/_next\/image/,
|
|
477
|
+
/\.map$/,
|
|
478
|
+
],
|
|
479
|
+
},
|
|
480
|
+
},
|
|
481
|
+
});
|
|
482
|
+
} else {
|
|
483
|
+
// -------- Self-Hosted (EC2/PM2): Use Vanilla OpenTelemetry SDK --------
|
|
484
|
+
const { NodeSDK } = require('@opentelemetry/sdk-node');
|
|
485
|
+
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');
|
|
486
|
+
const { Resource } = require('@opentelemetry/resources');
|
|
487
|
+
const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
|
|
488
|
+
|
|
489
|
+
const traceExporter = new OTLPTraceExporter({
|
|
490
|
+
url: tracesUrl,
|
|
491
|
+
headers: parseHeaders(env('OTEL_EXPORTER_OTLP_HEADERS'))
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
const sdk = new NodeSDK({
|
|
495
|
+
serviceName: serviceName,
|
|
496
|
+
traceExporter: traceExporter,
|
|
497
|
+
instrumentations: [httpInstrumentation],
|
|
498
|
+
resource: new Resource({
|
|
499
|
+
[SemanticResourceAttributes.SERVICE_NAME]: serviceName,
|
|
500
|
+
[SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: env('NODE_ENV') || env('VERCEL_ENV') || 'production',
|
|
501
|
+
[SemanticResourceAttributes.SERVICE_VERSION]: process.env.npm_package_version || undefined,
|
|
502
|
+
}),
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
sdk.start();
|
|
506
|
+
console.log('[securenow] 🎯 Vanilla SDK initialized for self-hosted environment');
|
|
507
|
+
}
|
|
461
508
|
|
|
462
509
|
isRegistered = true;
|
|
463
510
|
console.log('[securenow] ✅ OpenTelemetry started for Next.js → %s', tracesUrl);
|
|
@@ -485,7 +532,11 @@ function registerSecureNow(options = {}) {
|
|
|
485
532
|
|
|
486
533
|
} catch (error) {
|
|
487
534
|
console.error('[securenow] Failed to initialize OpenTelemetry:', error);
|
|
488
|
-
|
|
535
|
+
if (isVercel) {
|
|
536
|
+
console.error('[securenow] Make sure you have @vercel/otel installed: npm install @vercel/otel');
|
|
537
|
+
} else {
|
|
538
|
+
console.error('[securenow] Make sure OpenTelemetry dependencies are installed');
|
|
539
|
+
}
|
|
489
540
|
}
|
|
490
541
|
}
|
|
491
542
|
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "securenow",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.12",
|
|
4
4
|
"description": "OpenTelemetry instrumentation for Node.js and Next.js - Send traces to SigNoz or any OTLP backend",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "register.js",
|
|
7
|
+
"types": "register.d.ts",
|
|
7
8
|
"bin": {
|
|
8
|
-
"securenow": "
|
|
9
|
+
"securenow": "cli.js"
|
|
9
10
|
},
|
|
10
11
|
"scripts": {
|
|
11
12
|
"postinstall": "node postinstall.js || exit 0"
|
|
@@ -29,13 +30,34 @@
|
|
|
29
30
|
"nestjs"
|
|
30
31
|
],
|
|
31
32
|
"exports": {
|
|
32
|
-
".":
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"./
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
".": {
|
|
34
|
+
"types": "./register.d.ts",
|
|
35
|
+
"default": "./register.js"
|
|
36
|
+
},
|
|
37
|
+
"./register": {
|
|
38
|
+
"types": "./register.d.ts",
|
|
39
|
+
"default": "./register.js"
|
|
40
|
+
},
|
|
41
|
+
"./tracing": {
|
|
42
|
+
"types": "./tracing.d.ts",
|
|
43
|
+
"default": "./tracing.js"
|
|
44
|
+
},
|
|
45
|
+
"./nextjs": {
|
|
46
|
+
"types": "./nextjs.d.ts",
|
|
47
|
+
"default": "./nextjs.js"
|
|
48
|
+
},
|
|
49
|
+
"./nextjs-auto-capture": {
|
|
50
|
+
"types": "./nextjs-auto-capture.d.ts",
|
|
51
|
+
"default": "./nextjs-auto-capture.js"
|
|
52
|
+
},
|
|
53
|
+
"./nextjs-middleware": {
|
|
54
|
+
"types": "./nextjs-middleware.d.ts",
|
|
55
|
+
"default": "./nextjs-middleware.js"
|
|
56
|
+
},
|
|
57
|
+
"./nextjs-wrapper": {
|
|
58
|
+
"types": "./nextjs-wrapper.d.ts",
|
|
59
|
+
"default": "./nextjs-wrapper.js"
|
|
60
|
+
},
|
|
39
61
|
"./nextjs-webpack-config": "./nextjs-webpack-config.js",
|
|
40
62
|
"./register-vite": "./register-vite.js",
|
|
41
63
|
"./web-vite": {
|
|
@@ -45,11 +67,17 @@
|
|
|
45
67
|
},
|
|
46
68
|
"files": [
|
|
47
69
|
"register.js",
|
|
70
|
+
"register.d.ts",
|
|
48
71
|
"tracing.js",
|
|
72
|
+
"tracing.d.ts",
|
|
49
73
|
"nextjs.js",
|
|
74
|
+
"nextjs.d.ts",
|
|
50
75
|
"nextjs-auto-capture.js",
|
|
76
|
+
"nextjs-auto-capture.d.ts",
|
|
51
77
|
"nextjs-middleware.js",
|
|
78
|
+
"nextjs-middleware.d.ts",
|
|
52
79
|
"nextjs-wrapper.js",
|
|
80
|
+
"nextjs-wrapper.d.ts",
|
|
53
81
|
"cli.js",
|
|
54
82
|
"postinstall.js",
|
|
55
83
|
"register-vite.js",
|
package/register.d.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SecureNow Register Module TypeScript Declarations
|
|
3
|
+
*
|
|
4
|
+
* Main entry point for Node.js/Express/Fastify/NestJS applications.
|
|
5
|
+
* This module is automatically loaded when using NODE_OPTIONS="-r securenow/register"
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Environment Variables:
|
|
10
|
+
*
|
|
11
|
+
* Required:
|
|
12
|
+
* - SECURENOW_APPID=your-app-name - Logical service name
|
|
13
|
+
* - SECURENOW_INSTANCE=http://host:4318 - OTLP endpoint
|
|
14
|
+
*
|
|
15
|
+
* Optional:
|
|
16
|
+
* - SECURENOW_NO_UUID=1 - Use same service.name across all workers
|
|
17
|
+
* - SECURENOW_STRICT=1 - Exit if no appid/name provided in cluster
|
|
18
|
+
* - SECURENOW_CAPTURE_BODY=1 - Enable request body capture
|
|
19
|
+
* - SECURENOW_MAX_BODY_SIZE=10240 - Max body size in bytes (default: 10KB)
|
|
20
|
+
* - SECURENOW_SENSITIVE_FIELDS=field1,field2 - Additional sensitive fields
|
|
21
|
+
* - SECURENOW_DISABLE_INSTRUMENTATIONS=pkg1,pkg2 - Disable specific instrumentations
|
|
22
|
+
* - OTEL_LOG_LEVEL=info|debug - Logging level
|
|
23
|
+
* - SECURENOW_TEST_SPAN=1 - Create test span on startup
|
|
24
|
+
*
|
|
25
|
+
* Alternative Environment Variables:
|
|
26
|
+
* - OTEL_SERVICE_NAME - Alternative to SECURENOW_APPID
|
|
27
|
+
* - OTEL_EXPORTER_OTLP_ENDPOINT - Alternative to SECURENOW_INSTANCE
|
|
28
|
+
* - OTEL_EXPORTER_OTLP_TRACES_ENDPOINT - Full traces URL
|
|
29
|
+
* - OTEL_EXPORTER_OTLP_HEADERS - Headers for OTLP exporter (k=v,k2=v2)
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
// This module has side effects (initializes OpenTelemetry)
|
|
33
|
+
// It's typically used via NODE_OPTIONS, not imported directly
|
|
34
|
+
export {};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @example
|
|
38
|
+
* ```bash
|
|
39
|
+
* # Using with Node.js preload
|
|
40
|
+
* NODE_OPTIONS="-r securenow/register" node app.js
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```bash
|
|
45
|
+
* # Using with PM2
|
|
46
|
+
* pm2 start app.js --node-args="-r securenow/register"
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```javascript
|
|
51
|
+
* // ecosystem.config.js
|
|
52
|
+
* module.exports = {
|
|
53
|
+
* apps: [{
|
|
54
|
+
* name: 'my-app',
|
|
55
|
+
* script: './app.js',
|
|
56
|
+
* node_args: '-r securenow/register',
|
|
57
|
+
* env: {
|
|
58
|
+
* SECURENOW_APPID: 'my-app',
|
|
59
|
+
* SECURENOW_INSTANCE: 'http://signoz:4318',
|
|
60
|
+
* SECURENOW_CAPTURE_BODY: '1',
|
|
61
|
+
* }
|
|
62
|
+
* }]
|
|
63
|
+
* };
|
|
64
|
+
* ```
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```typescript
|
|
68
|
+
* // Explicit import (optional, mainly for side effects)
|
|
69
|
+
* import 'securenow/register';
|
|
70
|
+
*
|
|
71
|
+
* import express from 'express';
|
|
72
|
+
* const app = express();
|
|
73
|
+
* // Your app code...
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
package/tracing.d.ts
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SecureNow Tracing Module TypeScript Declarations
|
|
3
|
+
*
|
|
4
|
+
* Core tracing functionality for Node.js applications.
|
|
5
|
+
* This is typically loaded via register.js, not imported directly.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Default sensitive fields that are automatically redacted from request bodies
|
|
10
|
+
*/
|
|
11
|
+
export const DEFAULT_SENSITIVE_FIELDS: readonly string[];
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Redact sensitive fields from an object (recursively)
|
|
15
|
+
*
|
|
16
|
+
* @param obj - Object to redact (can be nested)
|
|
17
|
+
* @param sensitiveFields - Array of field names to redact (case-insensitive substring match)
|
|
18
|
+
* @returns Redacted copy of the object
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* import { redactSensitiveData } from 'securenow/tracing';
|
|
23
|
+
*
|
|
24
|
+
* const data = {
|
|
25
|
+
* email: 'user@example.com',
|
|
26
|
+
* password: 'secret123',
|
|
27
|
+
* nested: {
|
|
28
|
+
* api_key: 'sk_live_abc123'
|
|
29
|
+
* }
|
|
30
|
+
* };
|
|
31
|
+
*
|
|
32
|
+
* const redacted = redactSensitiveData(data);
|
|
33
|
+
* // Result: {
|
|
34
|
+
* // email: 'user@example.com',
|
|
35
|
+
* // password: '[REDACTED]',
|
|
36
|
+
* // nested: { api_key: '[REDACTED]' }
|
|
37
|
+
* // }
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export function redactSensitiveData<T = any>(
|
|
41
|
+
obj: T,
|
|
42
|
+
sensitiveFields?: string[]
|
|
43
|
+
): T;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Redact sensitive data from GraphQL query strings
|
|
47
|
+
*
|
|
48
|
+
* @param query - GraphQL query string
|
|
49
|
+
* @param sensitiveFields - Array of field names to redact
|
|
50
|
+
* @returns Redacted query string
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* import { redactGraphQLQuery } from 'securenow/tracing';
|
|
55
|
+
*
|
|
56
|
+
* const query = `
|
|
57
|
+
* mutation {
|
|
58
|
+
* login(email: "user@example.com", password: "secret123") {
|
|
59
|
+
* token
|
|
60
|
+
* }
|
|
61
|
+
* }
|
|
62
|
+
* `;
|
|
63
|
+
*
|
|
64
|
+
* const redacted = redactGraphQLQuery(query);
|
|
65
|
+
* // Result: mutation { login(email: "user@example.com", password: "[REDACTED]") { token } }
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export function redactGraphQLQuery(
|
|
69
|
+
query: string,
|
|
70
|
+
sensitiveFields?: string[]
|
|
71
|
+
): string;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Environment Variables (same as register.js):
|
|
75
|
+
*
|
|
76
|
+
* Required:
|
|
77
|
+
* - SECURENOW_APPID=your-app-name
|
|
78
|
+
* - SECURENOW_INSTANCE=http://host:4318
|
|
79
|
+
*
|
|
80
|
+
* Optional:
|
|
81
|
+
* - SECURENOW_NO_UUID=1
|
|
82
|
+
* - SECURENOW_STRICT=1
|
|
83
|
+
* - SECURENOW_CAPTURE_BODY=1
|
|
84
|
+
* - SECURENOW_MAX_BODY_SIZE=10240
|
|
85
|
+
* - SECURENOW_SENSITIVE_FIELDS=field1,field2
|
|
86
|
+
* - SECURENOW_DISABLE_INSTRUMENTATIONS=pkg1,pkg2
|
|
87
|
+
* - OTEL_LOG_LEVEL=info|debug
|
|
88
|
+
* - SECURENOW_TEST_SPAN=1
|
|
89
|
+
*/
|