securenow 5.18.0 → 6.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +40 -239
  3. package/cli.js +455 -415
  4. package/console-instrumentation.js +136 -147
  5. package/docs/ALL-FRAMEWORKS-QUICKSTART.md +455 -1339
  6. package/docs/ARCHITECTURE.md +3 -3
  7. package/docs/AUTO-BODY-CAPTURE.md +1 -1
  8. package/docs/AUTO-SETUP.md +4 -4
  9. package/docs/AUTOMATIC-IP-CAPTURE.md +5 -5
  10. package/docs/BODY-CAPTURE-QUICKSTART.md +2 -2
  11. package/docs/CHANGELOG-NEXTJS.md +35 -1
  12. package/docs/CUSTOMER-GUIDE.md +16 -16
  13. package/docs/EASIEST-SETUP.md +5 -5
  14. package/docs/ENVIRONMENT-VARIABLES.md +652 -880
  15. package/docs/EXPRESS-BODY-CAPTURE.md +12 -13
  16. package/docs/EXPRESS-SETUP-GUIDE.md +720 -719
  17. package/docs/INDEX.md +4 -22
  18. package/docs/LOGGING-GUIDE.md +708 -701
  19. package/docs/LOGGING-QUICKSTART.md +255 -234
  20. package/docs/NEXTJS-BODY-CAPTURE.md +2 -2
  21. package/docs/NEXTJS-GUIDE.md +14 -14
  22. package/docs/NEXTJS-QUICKSTART.md +1 -1
  23. package/docs/NEXTJS-WRAPPER-APPROACH.md +1 -1
  24. package/docs/QUICKSTART-BODY-CAPTURE.md +2 -2
  25. package/docs/REDACTION-EXAMPLES.md +1 -1
  26. package/docs/REQUEST-BODY-CAPTURE.md +10 -19
  27. package/docs/VERCEL-OTEL-MIGRATION.md +3 -3
  28. package/examples/README.md +6 -6
  29. package/examples/instrumentation-with-auto-capture.ts +1 -1
  30. package/examples/nextjs-env-example.txt +2 -2
  31. package/examples/nextjs-instrumentation.js +1 -1
  32. package/examples/nextjs-instrumentation.ts +1 -1
  33. package/examples/nextjs-with-logging-example.md +6 -6
  34. package/examples/nextjs-with-options.ts +1 -1
  35. package/examples/test-nextjs-setup.js +1 -1
  36. package/nextjs-auto-capture.js +207 -199
  37. package/nextjs-middleware.js +181 -186
  38. package/nextjs-webpack-config.js +53 -88
  39. package/nextjs-wrapper.js +158 -158
  40. package/nextjs.d.ts +1 -1
  41. package/nextjs.js +198 -186
  42. package/package.json +45 -67
  43. package/postinstall.js +6 -6
  44. package/register.d.ts +1 -1
  45. package/register.js +4 -39
  46. package/tracing.d.ts +1 -2
  47. package/tracing.js +26 -286
  48. package/web-vite.mjs +156 -239
  49. package/CONSUMING-APPS-GUIDE.md +0 -455
  50. package/NPM_README.md +0 -1933
  51. package/SKILL-API.md +0 -600
  52. package/SKILL-CLI.md +0 -409
  53. package/cidr.js +0 -83
  54. package/cli/apps.js +0 -585
  55. package/cli/auth.js +0 -280
  56. package/cli/client.js +0 -115
  57. package/cli/config.js +0 -173
  58. package/cli/firewall.js +0 -100
  59. package/cli/fp.js +0 -638
  60. package/cli/init.js +0 -201
  61. package/cli/monitor.js +0 -440
  62. package/cli/run.js +0 -133
  63. package/cli/security.js +0 -1064
  64. package/cli/ui.js +0 -386
  65. package/docs/API-KEYS-GUIDE.md +0 -233
  66. package/docs/AUTO-SETUP-SUMMARY.md +0 -331
  67. package/docs/BODY-CAPTURE-FIX.md +0 -261
  68. package/docs/COMPLETION-REPORT.md +0 -408
  69. package/docs/FINAL-SOLUTION.md +0 -335
  70. package/docs/FIREWALL-GUIDE.md +0 -426
  71. package/docs/IMPLEMENTATION-SUMMARY.md +0 -410
  72. package/docs/NEXTJS-BODY-CAPTURE-COMPARISON.md +0 -323
  73. package/docs/NEXTJS-SETUP-COMPLETE.md +0 -795
  74. package/docs/NUXT-GUIDE.md +0 -166
  75. package/docs/SOLUTION-SUMMARY.md +0 -312
  76. package/firewall-cloud.js +0 -212
  77. package/firewall-iptables.js +0 -139
  78. package/firewall-only.js +0 -38
  79. package/firewall-tcp.js +0 -74
  80. package/firewall.js +0 -720
  81. package/free-trial-banner.js +0 -174
  82. package/nuxt-server-plugin.mjs +0 -423
  83. package/nuxt.d.ts +0 -60
  84. package/nuxt.mjs +0 -75
  85. package/resolve-ip.js +0 -77
@@ -1,186 +1,181 @@
1
- /**
2
- * SecureNow Next.js Middleware for Body Capture
3
- *
4
- * OPTIONAL: Import this in your Next.js app to enable automatic body capture
5
- *
6
- * Usage:
7
- *
8
- * Create middleware.ts in your Next.js app root:
9
- *
10
- * export { middleware } from 'securenow/nextjs-middleware';
11
- * export const config = {
12
- * matcher: '/api/:path*', // Apply to API routes only
13
- * };
14
- *
15
- * That's it! Bodies are now captured with sensitive data redacted.
16
- */
17
-
18
- const { trace, context, SpanStatusCode } = require('@opentelemetry/api');
19
-
20
- // Default sensitive fields to redact
21
- const DEFAULT_SENSITIVE_FIELDS = [
22
- 'password', 'passwd', 'pwd', 'secret', 'token', 'api_key', 'apikey',
23
- 'access_token', 'auth', 'credentials', 'mysql_pwd', 'stripeToken',
24
- 'card', 'cardnumber', 'ccv', 'cvc', 'cvv', 'ssn', 'pin',
25
- ];
26
-
27
- /**
28
- * Redact sensitive fields from an object
29
- */
30
- function escapeRegex(str) {
31
- return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
32
- }
33
-
34
- function redactSensitiveData(obj, sensitiveFields = DEFAULT_SENSITIVE_FIELDS) {
35
- if (!obj || typeof obj !== 'object') return obj;
36
-
37
- const redacted = Array.isArray(obj) ? [...obj] : { ...obj };
38
-
39
- for (const key of Object.keys(redacted)) {
40
- const lowerKey = key.toLowerCase();
41
-
42
- if (sensitiveFields.some(field => lowerKey.includes(field.toLowerCase()))) {
43
- redacted[key] = '[REDACTED]';
44
- } else if (typeof redacted[key] === 'object' && redacted[key] !== null) {
45
- redacted[key] = redactSensitiveData(redacted[key], sensitiveFields);
46
- }
47
- }
48
-
49
- return redacted;
50
- }
51
-
52
- /**
53
- * Redact sensitive data from GraphQL query strings
54
- */
55
- function redactGraphQLQuery(query, sensitiveFields = DEFAULT_SENSITIVE_FIELDS) {
56
- if (!query || typeof query !== 'string') return query;
57
-
58
- let redacted = query;
59
-
60
- sensitiveFields.forEach(field => {
61
- const escaped = escapeRegex(field);
62
- const patterns = [
63
- new RegExp(`(${escaped}\\s*:\\s*["'])([^"']+)(["'])`, 'gi'),
64
- new RegExp(`(${escaped}\\s*:\\s*)([^\\s,})\n]+)`, 'gi'),
65
- ];
66
-
67
- patterns.forEach(pattern => {
68
- redacted = redacted.replace(pattern, (match, prefix, value, suffix) => {
69
- return suffix ? `${prefix}[REDACTED]${suffix}` : `${prefix}[REDACTED]`;
70
- });
71
- });
72
- });
73
-
74
- return redacted;
75
- }
76
-
77
- /**
78
- * Next.js Middleware for Body Capture
79
- */
80
- async function middleware(request) {
81
- const { NextResponse } = require('next/server');
82
-
83
- // Only capture for POST/PUT/PATCH
84
- if (!['POST', 'PUT', 'PATCH'].includes(request.method)) {
85
- return NextResponse.next();
86
- }
87
-
88
- // Get or create a tracer
89
- const tracer = trace.getTracer('securenow-middleware');
90
- let span = trace.getActiveSpan();
91
- let createdSpan = false;
92
-
93
- // If no active span, create one for this middleware
94
- if (!span) {
95
- const url = new URL(request.url);
96
- span = tracer.startSpan(`middleware ${request.method} ${url.pathname}`);
97
- createdSpan = true;
98
- }
99
-
100
- try {
101
- const contentType = request.headers.get('content-type') || '';
102
- const maxBodySize = Math.max(1024, parseInt(process.env.SECURENOW_MAX_BODY_SIZE, 10) || 10240);
103
- const customSensitiveFields = (process.env.SECURENOW_SENSITIVE_FIELDS || '').split(',').map(s => s.trim()).filter(Boolean);
104
- const allSensitiveFields = [...DEFAULT_SENSITIVE_FIELDS, ...customSensitiveFields];
105
-
106
- // Only capture supported types
107
- if (contentType.includes('application/json') ||
108
- contentType.includes('application/graphql')) {
109
-
110
- // Clone the request to read body without consuming the original
111
- const clonedRequest = request.clone();
112
- const bodyText = await clonedRequest.text();
113
-
114
- if (bodyText.length <= maxBodySize) {
115
- let redactedBody;
116
-
117
- if (contentType.includes('application/graphql')) {
118
- // GraphQL: redact query string
119
- redactedBody = redactGraphQLQuery(bodyText, allSensitiveFields);
120
- } else {
121
- // JSON: parse and redact
122
- try {
123
- const parsed = JSON.parse(bodyText);
124
- const redacted = redactSensitiveData(parsed, allSensitiveFields);
125
- redactedBody = JSON.stringify(redacted);
126
- } catch (e) {
127
- redactedBody = '[UNPARSEABLE - REDACTED FOR SAFETY]';
128
- }
129
- }
130
-
131
- span.setAttributes({
132
- 'http.request.body': redactedBody.substring(0, maxBodySize),
133
- 'http.request.body.type': contentType.includes('graphql') ? 'graphql' : 'json',
134
- 'http.request.body.size': bodyText.length,
135
- });
136
- } else {
137
- span.setAttribute('http.request.body', `[TOO LARGE: ${bodyText.length} bytes]`);
138
- }
139
- } else if (contentType.includes('application/x-www-form-urlencoded')) {
140
- const clonedRequest = request.clone();
141
- const formData = await clonedRequest.formData();
142
- const parsed = Object.fromEntries(formData);
143
- const redacted = redactSensitiveData(parsed, allSensitiveFields);
144
-
145
- span.setAttributes({
146
- 'http.request.body': JSON.stringify(redacted).substring(0, maxBodySize),
147
- 'http.request.body.type': 'form',
148
- 'http.request.body.size': JSON.stringify(parsed).length,
149
- });
150
- } else if (contentType.includes('multipart/form-data')) {
151
- span.setAttribute('http.request.body', '[MULTIPART - NOT CAPTURED]');
152
- span.setAttribute('http.request.body.type', 'multipart');
153
- }
154
-
155
- // End span if we created it
156
- if (createdSpan) {
157
- span.setStatus({ code: SpanStatusCode.OK });
158
- span.end();
159
- }
160
- } catch (error) {
161
- // Silently fail - don't break the request
162
- console.debug('[securenow] Body capture failed:', error.message);
163
-
164
- // End span with error if we created it
165
- if (createdSpan && span) {
166
- span.setStatus({
167
- code: SpanStatusCode.ERROR,
168
- message: error.message
169
- });
170
- span.end();
171
- }
172
- }
173
-
174
- return NextResponse.next();
175
- }
176
-
177
- module.exports = {
178
- middleware,
179
- redactSensitiveData,
180
- redactGraphQLQuery,
181
- DEFAULT_SENSITIVE_FIELDS,
182
- };
183
-
184
-
185
-
186
-
1
+ /**
2
+ * SecureNow Next.js Middleware for Body Capture
3
+ *
4
+ * OPTIONAL: Import this in your Next.js app to enable automatic body capture
5
+ *
6
+ * Usage:
7
+ *
8
+ * Create middleware.ts in your Next.js app root:
9
+ *
10
+ * export { middleware } from 'securenow/nextjs-middleware';
11
+ * export const config = {
12
+ * matcher: '/api/:path*', // Apply to API routes only
13
+ * };
14
+ *
15
+ * That's it! Bodies are now captured with sensitive data redacted.
16
+ */
17
+
18
+ const { trace, context, SpanStatusCode } = require('@opentelemetry/api');
19
+
20
+ // Default sensitive fields to redact
21
+ const DEFAULT_SENSITIVE_FIELDS = [
22
+ 'password', 'passwd', 'pwd', 'secret', 'token', 'api_key', 'apikey',
23
+ 'access_token', 'auth', 'credentials', 'mysql_pwd', 'stripeToken',
24
+ 'card', 'cardnumber', 'ccv', 'cvc', 'cvv', 'ssn', 'pin',
25
+ ];
26
+
27
+ /**
28
+ * Redact sensitive fields from an object
29
+ */
30
+ function redactSensitiveData(obj, sensitiveFields = DEFAULT_SENSITIVE_FIELDS) {
31
+ if (!obj || typeof obj !== 'object') return obj;
32
+
33
+ const redacted = Array.isArray(obj) ? [...obj] : { ...obj };
34
+
35
+ for (const key in redacted) {
36
+ const lowerKey = key.toLowerCase();
37
+
38
+ if (sensitiveFields.some(field => lowerKey.includes(field.toLowerCase()))) {
39
+ redacted[key] = '[REDACTED]';
40
+ } else if (typeof redacted[key] === 'object' && redacted[key] !== null) {
41
+ redacted[key] = redactSensitiveData(redacted[key], sensitiveFields);
42
+ }
43
+ }
44
+
45
+ return redacted;
46
+ }
47
+
48
+ /**
49
+ * Redact sensitive data from GraphQL query strings
50
+ */
51
+ function redactGraphQLQuery(query, sensitiveFields = DEFAULT_SENSITIVE_FIELDS) {
52
+ if (!query || typeof query !== 'string') return query;
53
+
54
+ let redacted = query;
55
+
56
+ sensitiveFields.forEach(field => {
57
+ const patterns = [
58
+ new RegExp(`(${field}\\s*:\\s*["'])([^"']+)(["'])`, 'gi'),
59
+ new RegExp(`(${field}\\s*:\\s*)([^\\s,})\n]+)`, 'gi'),
60
+ ];
61
+
62
+ patterns.forEach(pattern => {
63
+ redacted = redacted.replace(pattern, (match, prefix, value, suffix) => {
64
+ return suffix ? `${prefix}[REDACTED]${suffix}` : `${prefix}[REDACTED]`;
65
+ });
66
+ });
67
+ });
68
+
69
+ return redacted;
70
+ }
71
+
72
+ /**
73
+ * Next.js Middleware for Body Capture
74
+ */
75
+ async function middleware(request) {
76
+ const { NextResponse } = require('next/server');
77
+
78
+ // Only capture for POST/PUT/PATCH
79
+ if (!['POST', 'PUT', 'PATCH'].includes(request.method)) {
80
+ return NextResponse.next();
81
+ }
82
+
83
+ // Get or create a tracer
84
+ const tracer = trace.getTracer('securenow-middleware');
85
+ let span = trace.getActiveSpan();
86
+ let createdSpan = false;
87
+
88
+ // If no active span, create one for this middleware
89
+ if (!span) {
90
+ const url = new URL(request.url);
91
+ span = tracer.startSpan(`middleware ${request.method} ${url.pathname}`);
92
+ createdSpan = true;
93
+ }
94
+
95
+ try {
96
+ const contentType = request.headers.get('content-type') || '';
97
+ const maxBodySize = parseInt(process.env.SECURENOW_MAX_BODY_SIZE || '10240');
98
+ const customSensitiveFields = (process.env.SECURENOW_SENSITIVE_FIELDS || '').split(',').map(s => s.trim()).filter(Boolean);
99
+ const allSensitiveFields = [...DEFAULT_SENSITIVE_FIELDS, ...customSensitiveFields];
100
+
101
+ // Only capture supported types
102
+ if (contentType.includes('application/json') ||
103
+ contentType.includes('application/graphql')) {
104
+
105
+ // Clone the request to read body without consuming the original
106
+ const clonedRequest = request.clone();
107
+ const bodyText = await clonedRequest.text();
108
+
109
+ if (bodyText.length <= maxBodySize) {
110
+ let redactedBody;
111
+
112
+ if (contentType.includes('application/graphql')) {
113
+ // GraphQL: redact query string
114
+ redactedBody = redactGraphQLQuery(bodyText, allSensitiveFields);
115
+ } else {
116
+ // JSON: parse and redact
117
+ try {
118
+ const parsed = JSON.parse(bodyText);
119
+ const redacted = redactSensitiveData(parsed, allSensitiveFields);
120
+ redactedBody = JSON.stringify(redacted);
121
+ } catch (e) {
122
+ redactedBody = bodyText; // Keep as-is if parse fails
123
+ }
124
+ }
125
+
126
+ span.setAttributes({
127
+ 'http.request.body': redactedBody.substring(0, maxBodySize),
128
+ 'http.request.body.type': contentType.includes('graphql') ? 'graphql' : 'json',
129
+ 'http.request.body.size': bodyText.length,
130
+ });
131
+ } else {
132
+ span.setAttribute('http.request.body', `[TOO LARGE: ${bodyText.length} bytes]`);
133
+ }
134
+ } else if (contentType.includes('application/x-www-form-urlencoded')) {
135
+ const clonedRequest = request.clone();
136
+ const formData = await clonedRequest.formData();
137
+ const parsed = Object.fromEntries(formData);
138
+ const redacted = redactSensitiveData(parsed, allSensitiveFields);
139
+
140
+ span.setAttributes({
141
+ 'http.request.body': JSON.stringify(redacted).substring(0, maxBodySize),
142
+ 'http.request.body.type': 'form',
143
+ 'http.request.body.size': JSON.stringify(parsed).length,
144
+ });
145
+ } else if (contentType.includes('multipart/form-data')) {
146
+ span.setAttribute('http.request.body', '[MULTIPART - NOT CAPTURED]');
147
+ span.setAttribute('http.request.body.type', 'multipart');
148
+ }
149
+
150
+ // End span if we created it
151
+ if (createdSpan) {
152
+ span.setStatus({ code: SpanStatusCode.OK });
153
+ span.end();
154
+ }
155
+ } catch (error) {
156
+ // Silently fail - don't break the request
157
+ console.debug('[securenow] Body capture failed:', error.message);
158
+
159
+ // End span with error if we created it
160
+ if (createdSpan && span) {
161
+ span.setStatus({
162
+ code: SpanStatusCode.ERROR,
163
+ message: error.message
164
+ });
165
+ span.end();
166
+ }
167
+ }
168
+
169
+ return NextResponse.next();
170
+ }
171
+
172
+ module.exports = {
173
+ middleware,
174
+ redactSensitiveData,
175
+ redactGraphQLQuery,
176
+ DEFAULT_SENSITIVE_FIELDS,
177
+ };
178
+
179
+
180
+
181
+
@@ -1,100 +1,33 @@
1
- 'use strict';
2
-
3
- /**
4
- * Next.js configuration helpers for SecureNow
5
- *
6
- * Usage (recommended — zero-list approach):
7
- *
8
- * const { withSecureNow } = require('securenow/nextjs-webpack-config');
9
- * module.exports = withSecureNow({
10
- * // your existing next.config options
11
- * });
12
- *
13
- * Legacy webpack-only helper (still exported for backwards compat):
14
- *
15
- * const { getSecureNowWebpackConfig } = require('securenow/nextjs-webpack-config');
16
- * module.exports = { webpack: (config, opts) => getSecureNowWebpackConfig(config, opts) };
17
- */
18
-
19
- const EXTERNAL_PACKAGES = [
20
- 'securenow',
21
- '@opentelemetry/sdk-node',
22
- '@opentelemetry/auto-instrumentations-node',
23
- '@opentelemetry/instrumentation-http',
24
- '@opentelemetry/exporter-trace-otlp-http',
25
- '@opentelemetry/exporter-logs-otlp-http',
26
- '@opentelemetry/sdk-logs',
27
- '@opentelemetry/instrumentation',
28
- '@opentelemetry/resources',
29
- '@opentelemetry/semantic-conventions',
30
- '@opentelemetry/api',
31
- '@opentelemetry/api-logs',
32
- '@vercel/otel',
33
- ];
34
-
35
- function detectNextMajor() {
36
- try {
37
- const pkg = require('next/package.json');
38
- return parseInt(pkg.version, 10) || 14;
39
- } catch {
40
- return 14;
41
- }
42
- }
43
-
44
1
  /**
45
- * Wrap a Next.js config object to auto-externalize SecureNow + OTel
46
- * packages and enable the instrumentation hook.
47
- *
48
- * module.exports = withSecureNow({ reactStrictMode: true });
2
+ * Next.js webpack configuration for SecureNow
3
+ *
4
+ * Add this to your next.config.js to suppress OpenTelemetry instrumentation warnings
5
+ *
6
+ * Usage:
7
+ * const { getSecureNowWebpackConfig } = require('securenow/nextjs-webpack-config');
8
+ *
9
+ * module.exports = {
10
+ * webpack: (config, options) => {
11
+ * return getSecureNowWebpackConfig(config, options);
12
+ * }
13
+ * };
49
14
  */
50
- function withSecureNow(userConfig) {
51
- if (typeof userConfig === 'function') {
52
- return (...args) => withSecureNow(userConfig(...args));
53
- }
54
-
55
- const cfg = { ...userConfig };
56
- const major = detectNextMajor();
57
-
58
- if (major >= 15) {
59
- cfg.serverExternalPackages = dedup([
60
- ...(cfg.serverExternalPackages || []),
61
- ...EXTERNAL_PACKAGES,
62
- ]);
63
- } else {
64
- cfg.experimental = { ...(cfg.experimental || {}) };
65
- cfg.experimental.instrumentationHook = true;
66
- cfg.experimental.serverComponentsExternalPackages = dedup([
67
- ...(cfg.experimental.serverComponentsExternalPackages || []),
68
- ...EXTERNAL_PACKAGES,
69
- ]);
70
- }
71
-
72
- const origWebpack = cfg.webpack;
73
- cfg.webpack = (config, options) => {
74
- const c = origWebpack ? origWebpack(config, options) : config;
75
- return getSecureNowWebpackConfig(c, options);
76
- };
77
-
78
- return cfg;
79
- }
80
15
 
81
- function dedup(arr) {
82
- return [...new Set(arr)];
83
- }
84
-
85
- /**
86
- * Legacy: suppress OTel webpack warnings and add externals.
87
- */
88
16
  function getSecureNowWebpackConfig(config, options) {
89
17
  const { isServer } = options;
90
-
18
+
19
+ // Only apply to server-side builds
91
20
  if (isServer) {
21
+ // Suppress warnings for OpenTelemetry instrumentations
92
22
  config.ignoreWarnings = config.ignoreWarnings || [];
23
+
93
24
  config.ignoreWarnings.push(
25
+ // Ignore "Critical dependency" warnings from instrumentations
94
26
  {
95
27
  module: /@opentelemetry\/instrumentation/,
96
28
  message: /Critical dependency: the request of a dependency is an expression/,
97
29
  },
30
+ // Ignore missing optional peer dependencies
98
31
  {
99
32
  module: /@opentelemetry/,
100
33
  message: /Module not found.*@opentelemetry\/winston-transport/,
@@ -102,11 +35,43 @@ function getSecureNowWebpackConfig(config, options) {
102
35
  {
103
36
  module: /@opentelemetry/,
104
37
  message: /Module not found.*@opentelemetry\/exporter-jaeger/,
105
- },
38
+ }
106
39
  );
40
+
41
+ // Externalize problematic packages (don't bundle them)
42
+ config.externals = config.externals || [];
43
+
44
+ // Add OpenTelemetry packages as externals
45
+ if (typeof config.externals === 'function') {
46
+ const originalExternals = config.externals;
47
+ config.externals = async (...args) => {
48
+ const result = await originalExternals(...args);
49
+ if (result) return result;
50
+
51
+ const [context, request] = args;
52
+
53
+ // Externalize OpenTelemetry instrumentation packages
54
+ if (request.startsWith('@opentelemetry/')) {
55
+ return `commonjs ${request}`;
56
+ }
57
+
58
+ return undefined;
59
+ };
60
+ } else if (Array.isArray(config.externals)) {
61
+ config.externals.push(/@opentelemetry\//);
62
+ } else {
63
+ config.externals = [/@opentelemetry\//];
64
+ }
107
65
  }
108
-
66
+
109
67
  return config;
110
68
  }
111
69
 
112
- module.exports = { withSecureNow, getSecureNowWebpackConfig, EXTERNAL_PACKAGES };
70
+ module.exports = { getSecureNowWebpackConfig };
71
+
72
+
73
+
74
+
75
+
76
+
77
+