securenow 3.0.14 → 4.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/cli.js ADDED
@@ -0,0 +1,264 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * SecureNow CLI
6
+ *
7
+ * Usage: npx securenow init [options]
8
+ */
9
+
10
+ const fs = require('fs');
11
+ const path = require('path');
12
+
13
+ const commands = {
14
+ init: initCommand,
15
+ help: helpCommand,
16
+ version: versionCommand,
17
+ };
18
+
19
+ // Templates
20
+ const templates = {
21
+ typescript: `import { registerSecureNow } from 'securenow/nextjs';
22
+
23
+ export function register() {
24
+ registerSecureNow();
25
+ }
26
+
27
+ /**
28
+ * Configuration via .env.local:
29
+ *
30
+ * Required:
31
+ * SECURENOW_APPID=my-nextjs-app
32
+ *
33
+ * Optional:
34
+ * SECURENOW_INSTANCE=http://your-signoz-server:4318
35
+ * OTEL_EXPORTER_OTLP_HEADERS="x-api-key=your-key"
36
+ * OTEL_LOG_LEVEL=info
37
+ */
38
+ `,
39
+ javascript: `const { registerSecureNow } = require('securenow/nextjs');
40
+
41
+ export function register() {
42
+ registerSecureNow();
43
+ }
44
+
45
+ /**
46
+ * Configuration via .env.local:
47
+ *
48
+ * Required:
49
+ * SECURENOW_APPID=my-nextjs-app
50
+ *
51
+ * Optional:
52
+ * SECURENOW_INSTANCE=http://your-signoz-server:4318
53
+ * OTEL_EXPORTER_OTLP_HEADERS="x-api-key=your-key"
54
+ * OTEL_LOG_LEVEL=info
55
+ */
56
+ `,
57
+ env: `# SecureNow Configuration
58
+ # Required: Your application identifier
59
+ SECURENOW_APPID=my-nextjs-app
60
+
61
+ # Optional: Your SigNoz/OpenTelemetry collector endpoint
62
+ # Default: http://46.62.173.237:4318
63
+ SECURENOW_INSTANCE=http://your-signoz-server:4318
64
+
65
+ # Optional: API key or authentication headers
66
+ # OTEL_EXPORTER_OTLP_HEADERS="x-api-key=your-api-key-here"
67
+
68
+ # Optional: Log level (debug|info|warn|error)
69
+ # OTEL_LOG_LEVEL=info
70
+ `,
71
+ };
72
+
73
+ function initCommand(args) {
74
+ const flags = parseFlags(args);
75
+ const cwd = process.cwd();
76
+
77
+ console.log('\nšŸš€ SecureNow Setup\n');
78
+
79
+ // Check if Next.js project
80
+ const isNextJs = isNextJsProject(cwd);
81
+ if (!isNextJs && !flags.force) {
82
+ console.log('āš ļø This doesn\'t appear to be a Next.js project.');
83
+ console.log(' If you want to proceed anyway, use: npx securenow init --force\n');
84
+ process.exit(1);
85
+ }
86
+
87
+ // Determine TypeScript or JavaScript
88
+ const useTypeScript = flags.typescript ||
89
+ (!flags.javascript && fs.existsSync(path.join(cwd, 'tsconfig.json')));
90
+
91
+ // Determine if using src folder
92
+ const useSrc = flags.src ||
93
+ (!flags.root && fs.existsSync(path.join(cwd, 'src')));
94
+
95
+ // Construct file paths
96
+ const fileName = useTypeScript ? 'instrumentation.ts' : 'instrumentation.js';
97
+ const filePath = useSrc
98
+ ? path.join(cwd, 'src', fileName)
99
+ : path.join(cwd, fileName);
100
+
101
+ // Check if file already exists
102
+ if (fs.existsSync(filePath) && !flags.force) {
103
+ console.log(`āŒ ${useSrc ? 'src/' : ''}${fileName} already exists`);
104
+ console.log(' Use --force to overwrite\n');
105
+ process.exit(1);
106
+ }
107
+
108
+ // Create instrumentation file
109
+ try {
110
+ const template = useTypeScript ? templates.typescript : templates.javascript;
111
+
112
+ // Ensure src directory exists if needed
113
+ if (useSrc) {
114
+ fs.mkdirSync(path.join(cwd, 'src'), { recursive: true });
115
+ }
116
+
117
+ fs.writeFileSync(filePath, template, 'utf8');
118
+ console.log(`āœ… Created ${useSrc ? 'src/' : ''}${fileName}`);
119
+ } catch (error) {
120
+ console.error(`āŒ Failed to create instrumentation file: ${error.message}\n`);
121
+ process.exit(1);
122
+ }
123
+
124
+ // Create .env.local if it doesn't exist
125
+ const envPath = path.join(cwd, '.env.local');
126
+ if (!fs.existsSync(envPath) || flags.force) {
127
+ try {
128
+ fs.writeFileSync(envPath, templates.env, 'utf8');
129
+ console.log('āœ… Created .env.local template');
130
+ } catch (error) {
131
+ console.warn(`āš ļø Could not create .env.local: ${error.message}`);
132
+ }
133
+ } else {
134
+ console.log('ā„¹ļø .env.local already exists (skipped)');
135
+ }
136
+
137
+ // Success message
138
+ console.log('\nā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”');
139
+ console.log('│ šŸŽ‰ Setup Complete! │');
140
+ console.log('│ │');
141
+ console.log('│ Next steps: │');
142
+ console.log('│ │');
143
+ console.log('│ 1. Edit .env.local and configure: │');
144
+ console.log('│ SECURENOW_APPID=your-app-name │');
145
+ console.log('│ SECURENOW_INSTANCE=http://signoz:4318 │');
146
+ console.log('│ │');
147
+ console.log('│ 2. Start your Next.js app: npm run dev │');
148
+ console.log('│ │');
149
+ console.log('│ 3. Check SigNoz dashboard for traces! │');
150
+ console.log('│ │');
151
+ console.log('│ šŸ“š Documentation: │');
152
+ console.log('│ node_modules/securenow/NEXTJS-GUIDE.md │');
153
+ console.log('ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜\n');
154
+ }
155
+
156
+ function helpCommand() {
157
+ console.log(`
158
+ SecureNow CLI - OpenTelemetry instrumentation for Next.js
159
+
160
+ USAGE:
161
+ npx securenow <command> [options]
162
+
163
+ COMMANDS:
164
+ init Initialize SecureNow in your Next.js project
165
+ help Show this help message
166
+ version Show package version
167
+
168
+ OPTIONS:
169
+ --typescript, --ts Force TypeScript (creates instrumentation.ts)
170
+ --javascript, --js Force JavaScript (creates instrumentation.js)
171
+ --src Create file in src/ folder
172
+ --root Create file in project root
173
+ --force, -f Overwrite existing files
174
+
175
+ EXAMPLES:
176
+ # Auto-detect and setup
177
+ npx securenow init
178
+
179
+ # Force TypeScript in src folder
180
+ npx securenow init --typescript --src
181
+
182
+ # Force JavaScript in root
183
+ npx securenow init --javascript --root
184
+
185
+ # Overwrite existing files
186
+ npx securenow init --force
187
+
188
+ DOCUMENTATION:
189
+ Quick Start: node_modules/securenow/NEXTJS-QUICKSTART.md
190
+ Full Guide: node_modules/securenow/NEXTJS-GUIDE.md
191
+ Examples: node_modules/securenow/examples/
192
+ `);
193
+ }
194
+
195
+ function versionCommand() {
196
+ try {
197
+ const packageJson = require('./package.json');
198
+ console.log(`securenow v${packageJson.version}`);
199
+ } catch (error) {
200
+ console.log('securenow (version unknown)');
201
+ }
202
+ }
203
+
204
+ // Utility functions
205
+ function parseFlags(args) {
206
+ const flags = {};
207
+
208
+ for (let i = 0; i < args.length; i++) {
209
+ const arg = args[i];
210
+
211
+ if (arg === '--typescript' || arg === '--ts') {
212
+ flags.typescript = true;
213
+ } else if (arg === '--javascript' || arg === '--js') {
214
+ flags.javascript = true;
215
+ } else if (arg === '--src') {
216
+ flags.src = true;
217
+ } else if (arg === '--root') {
218
+ flags.root = true;
219
+ } else if (arg === '--force' || arg === '-f') {
220
+ flags.force = true;
221
+ }
222
+ }
223
+
224
+ return flags;
225
+ }
226
+
227
+ function isNextJsProject(dir) {
228
+ try {
229
+ const packageJsonPath = path.join(dir, 'package.json');
230
+ if (!fs.existsSync(packageJsonPath)) return false;
231
+
232
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
233
+ const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
234
+
235
+ return !!deps.next;
236
+ } catch (error) {
237
+ return false;
238
+ }
239
+ }
240
+
241
+ // Main
242
+ function main() {
243
+ const args = process.argv.slice(2);
244
+ const command = args[0] || 'help';
245
+ const commandFn = commands[command];
246
+
247
+ if (!commandFn) {
248
+ console.error(`Unknown command: ${command}`);
249
+ console.log('Run "npx securenow help" for usage\n');
250
+ process.exit(1);
251
+ }
252
+
253
+ commandFn(args.slice(1));
254
+ }
255
+
256
+ if (require.main === module) {
257
+ main();
258
+ }
259
+
260
+ module.exports = { main };
261
+
262
+
263
+
264
+
@@ -0,0 +1,262 @@
1
+ # SecureNow Next.js Examples
2
+
3
+ This folder contains example files to help you integrate SecureNow with your Next.js application.
4
+
5
+ ---
6
+
7
+ ## šŸ“ Files
8
+
9
+ ### 1. `nextjs-instrumentation.ts`
10
+ **TypeScript setup (recommended for TS projects)**
11
+
12
+ Basic Next.js instrumentation setup using TypeScript.
13
+
14
+ **Usage:**
15
+ 1. Copy this file to your project root as `instrumentation.ts`
16
+ 2. Set environment variables in `.env.local`
17
+ 3. Run your Next.js app
18
+
19
+ ---
20
+
21
+ ### 2. `nextjs-instrumentation.js`
22
+ **JavaScript setup (for JS projects)**
23
+
24
+ Basic Next.js instrumentation setup using JavaScript.
25
+
26
+ **Usage:**
27
+ 1. Copy this file to your project root as `instrumentation.js`
28
+ 2. Set environment variables in `.env.local`
29
+ 3. Run your Next.js app
30
+
31
+ ---
32
+
33
+ ### 3. `nextjs-with-options.ts`
34
+ **Advanced configuration with programmatic options**
35
+
36
+ Shows how to pass configuration options directly to `registerSecureNow()` instead of using only environment variables.
37
+
38
+ **Usage:**
39
+ 1. Copy to project root as `instrumentation.ts`
40
+ 2. Customize the options object
41
+ 3. Set sensitive values (API keys) via environment variables
42
+
43
+ **Good for:**
44
+ - Complex configurations
45
+ - Multiple environments
46
+ - Custom headers
47
+ - Selective instrumentation
48
+
49
+ ---
50
+
51
+ ### 4. `nextjs-env-example.txt`
52
+ **Complete environment variables reference**
53
+
54
+ Lists all available environment variables with explanations.
55
+
56
+ **Usage:**
57
+ 1. Copy contents to your `.env.local` file
58
+ 2. Uncomment and set the variables you need
59
+ 3. Remove or comment out unused variables
60
+
61
+ ---
62
+
63
+ ### 5. `test-nextjs-setup.js`
64
+ **Test script to verify your setup**
65
+
66
+ A standalone script to test SecureNow configuration before integrating with Next.js.
67
+
68
+ **Usage:**
69
+ ```bash
70
+ # Test with environment variables
71
+ SECURENOW_APPID=test-app \
72
+ SECURENOW_INSTANCE=http://localhost:4318 \
73
+ node examples/test-nextjs-setup.js
74
+
75
+ # Or set them in .env first
76
+ node examples/test-nextjs-setup.js
77
+ ```
78
+
79
+ **What it tests:**
80
+ - āœ… Package installation
81
+ - āœ… SDK registration
82
+ - āœ… Span creation
83
+ - āœ… Configuration loading
84
+ - āœ… Export functionality
85
+
86
+ ---
87
+
88
+ ## šŸš€ Quick Start Guide
89
+
90
+ ### Step 1: Choose Your Setup
91
+
92
+ **TypeScript project?** → Use `nextjs-instrumentation.ts`
93
+ **JavaScript project?** → Use `nextjs-instrumentation.js`
94
+ **Need advanced config?** → Use `nextjs-with-options.ts`
95
+
96
+ ### Step 2: Copy File
97
+
98
+ ```bash
99
+ # From your project root
100
+ cp node_modules/securenow/examples/nextjs-instrumentation.ts instrumentation.ts
101
+ # or
102
+ cp node_modules/securenow/examples/nextjs-instrumentation.js instrumentation.js
103
+ ```
104
+
105
+ ### Step 3: Configure Environment
106
+
107
+ ```bash
108
+ # Copy environment variables template
109
+ cp node_modules/securenow/examples/nextjs-env-example.txt .env.local
110
+ # Edit .env.local with your values
111
+ ```
112
+
113
+ ### Step 4: Test (Optional)
114
+
115
+ ```bash
116
+ # Verify setup works
117
+ node node_modules/securenow/examples/test-nextjs-setup.js
118
+ ```
119
+
120
+ ### Step 5: Run Your App
121
+
122
+ ```bash
123
+ npm run dev
124
+ ```
125
+
126
+ ---
127
+
128
+ ## šŸ“š Documentation
129
+
130
+ - **[Quick Start](../NEXTJS-QUICKSTART.md)** - 30-second setup
131
+ - **[Complete Guide](../NEXTJS-GUIDE.md)** - Full documentation
132
+ - **[Customer Guide](../CUSTOMER-GUIDE.md)** - User-friendly guide
133
+ - **[Architecture](../ARCHITECTURE.md)** - Technical details
134
+
135
+ ---
136
+
137
+ ## šŸ’” Tips
138
+
139
+ ### For Development
140
+ ```bash
141
+ # Use simpler service names
142
+ SECURENOW_NO_UUID=1
143
+ SECURENOW_APPID=my-app-dev
144
+
145
+ # Enable debug logging
146
+ OTEL_LOG_LEVEL=debug
147
+ ```
148
+
149
+ ### For Production
150
+ ```bash
151
+ # Use descriptive names with UUID
152
+ SECURENOW_APPID=my-app-prod
153
+ # UUID is auto-appended
154
+
155
+ # Use info or warn level
156
+ OTEL_LOG_LEVEL=info
157
+ ```
158
+
159
+ ### For Vercel
160
+ ```bash
161
+ # Set in Vercel dashboard:
162
+ SECURENOW_APPID=my-app
163
+ SECURENOW_INSTANCE=http://your-signoz:4318
164
+ OTEL_EXPORTER_OTLP_HEADERS="x-api-key=your-key"
165
+ ```
166
+
167
+ ---
168
+
169
+ ## šŸ†˜ Troubleshooting
170
+
171
+ ### "Cannot find module 'securenow/nextjs'"
172
+
173
+ Make sure you're on the latest version:
174
+ ```bash
175
+ npm install securenow@latest
176
+ ```
177
+
178
+ ### Traces not appearing
179
+
180
+ 1. Check console for `[securenow] āœ… OpenTelemetry started`
181
+ 2. Enable debug mode: `OTEL_LOG_LEVEL=debug`
182
+ 3. Run test script: `node examples/test-nextjs-setup.js`
183
+ 4. Verify SigNoz accessibility: `curl http://your-signoz:4318/v1/traces`
184
+
185
+ ### Too many spans
186
+
187
+ Disable noisy instrumentations:
188
+ ```bash
189
+ SECURENOW_DISABLE_INSTRUMENTATIONS=fs,dns
190
+ ```
191
+
192
+ ---
193
+
194
+ ## šŸ“ Customization
195
+
196
+ ### Disable Specific Instrumentations
197
+
198
+ ```typescript
199
+ registerSecureNow({
200
+ disableInstrumentations: ['fs', 'dns', 'net'],
201
+ });
202
+ ```
203
+
204
+ ### Add Custom Headers
205
+
206
+ ```typescript
207
+ registerSecureNow({
208
+ headers: {
209
+ 'x-api-key': process.env.SIGNOZ_API_KEY,
210
+ 'x-environment': process.env.NODE_ENV,
211
+ },
212
+ });
213
+ ```
214
+
215
+ ### Use Different Service Name
216
+
217
+ ```typescript
218
+ registerSecureNow({
219
+ serviceName: 'my-custom-app-name',
220
+ noUuid: false, // Still append UUID
221
+ });
222
+ ```
223
+
224
+ ---
225
+
226
+ ## šŸŽÆ Next Steps
227
+
228
+ After setting up:
229
+
230
+ 1. **Run your app** and verify traces appear
231
+ 2. **Test key user flows** to see end-to-end tracing
232
+ 3. **Check SigNoz dashboard** for service map and traces
233
+ 4. **Adjust configuration** based on your needs
234
+ 5. **Deploy to production** with proper environment variables
235
+
236
+ ---
237
+
238
+ ## 🌟 Success Looks Like
239
+
240
+ ```bash
241
+ $ npm run dev
242
+
243
+ [securenow] Next.js integration loading (pid=12345)
244
+ [securenow] šŸš€ Next.js App → service.name=my-app-abc123
245
+ [securenow] āœ… OpenTelemetry started for Next.js → http://signoz:4318/v1/traces
246
+
247
+ āœ“ Ready in 1.2s
248
+ ```
249
+
250
+ Then in SigNoz:
251
+ - āœ… See your service in service map
252
+ - āœ… View traces for requests
253
+ - āœ… Analyze performance metrics
254
+ - āœ… Debug issues with distributed tracing
255
+
256
+ ---
257
+
258
+ **Happy tracing! šŸŽ‰**
259
+
260
+
261
+
262
+
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Example Next.js configuration for SecureNow
3
+ *
4
+ * This configuration suppresses OpenTelemetry instrumentation warnings
5
+ */
6
+
7
+ const { getSecureNowWebpackConfig } = require('securenow/nextjs-webpack-config');
8
+
9
+ /** @type {import('next').NextConfig} */
10
+ const nextConfig = {
11
+ // Next.js 15+ doesn't need this
12
+ // For Next.js 14 and below, uncomment:
13
+ // experimental: {
14
+ // instrumentationHook: true,
15
+ // },
16
+
17
+ // Suppress OpenTelemetry bundling warnings
18
+ webpack: (config, options) => {
19
+ return getSecureNowWebpackConfig(config, options);
20
+ },
21
+
22
+ // Optional: Tell Next.js not to bundle OpenTelemetry packages
23
+ serverExternalPackages: [
24
+ '@opentelemetry/sdk-node',
25
+ '@opentelemetry/auto-instrumentations-node',
26
+ '@opentelemetry/instrumentation',
27
+ ],
28
+ };
29
+
30
+ module.exports = nextConfig;
31
+
32
+
33
+
34
+
@@ -0,0 +1,31 @@
1
+ # SecureNow Configuration for Next.js
2
+ # Place these in your .env.local file
3
+
4
+ # Required: Your application identifier
5
+ SECURENOW_APPID=my-nextjs-app
6
+
7
+ # Optional: Your SigNoz/OpenTelemetry collector endpoint
8
+ # Default: http://46.62.173.237:4318
9
+ SECURENOW_INSTANCE=http://your-signoz-server:4318
10
+
11
+ # Optional: API Key or authentication headers
12
+ OTEL_EXPORTER_OTLP_HEADERS="x-api-key=your-api-key-here"
13
+
14
+ # Optional: Don't append UUID to service name (useful for dev)
15
+ # SECURENOW_NO_UUID=1
16
+
17
+ # Optional: Log level
18
+ # OTEL_LOG_LEVEL=info
19
+
20
+ # Optional: Disable specific instrumentations (comma-separated)
21
+ # SECURENOW_DISABLE_INSTRUMENTATIONS=fs,dns
22
+
23
+ # Optional: Create a test span on startup
24
+ # SECURENOW_TEST_SPAN=1
25
+
26
+ # Next.js will automatically use NODE_ENV
27
+ # NODE_ENV=production
28
+
29
+
30
+
31
+
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Next.js Instrumentation with SecureNow (JavaScript version)
3
+ *
4
+ * Place this file at the root of your Next.js project as: instrumentation.js
5
+ * (or in the src/ folder if you're using it)
6
+ *
7
+ * For Next.js 14 and below, also add to next.config.js:
8
+ * experimental: { instrumentationHook: true }
9
+ */
10
+
11
+ const { registerSecureNow } = require('securenow/nextjs');
12
+
13
+ export function register() {
14
+ registerSecureNow();
15
+ }
16
+
17
+ /**
18
+ * Configuration via Environment Variables (.env.local):
19
+ *
20
+ * Required:
21
+ * SECURENOW_APPID=my-nextjs-app
22
+ *
23
+ * Optional:
24
+ * SECURENOW_INSTANCE=http://your-signoz-server:4318
25
+ * SECURENOW_NO_UUID=1 # Don't append UUID to service name
26
+ * OTEL_LOG_LEVEL=info # debug|info|warn|error
27
+ * SECURENOW_DISABLE_INSTRUMENTATIONS=fs # Comma-separated list
28
+ * SECURENOW_TEST_SPAN=1 # Create test span on startup
29
+ */
30
+
31
+
32
+
33
+
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Next.js Instrumentation with SecureNow
3
+ *
4
+ * Place this file at the root of your Next.js project as: instrumentation.ts
5
+ * (or in the src/ folder if you're using it)
6
+ *
7
+ * For Next.js 14 and below, also add to next.config.js:
8
+ * experimental: { instrumentationHook: true }
9
+ */
10
+
11
+ import { registerSecureNow } from 'securenow/nextjs';
12
+
13
+ export function register() {
14
+ registerSecureNow();
15
+ }
16
+
17
+ /**
18
+ * Configuration via Environment Variables (.env.local):
19
+ *
20
+ * Required:
21
+ * SECURENOW_APPID=my-nextjs-app
22
+ *
23
+ * Optional:
24
+ * SECURENOW_INSTANCE=http://your-signoz-server:4318
25
+ * SECURENOW_NO_UUID=1 # Don't append UUID to service name
26
+ * OTEL_LOG_LEVEL=info # debug|info|warn|error
27
+ * SECURENOW_DISABLE_INSTRUMENTATIONS=fs # Comma-separated list
28
+ * SECURENOW_TEST_SPAN=1 # Create test span on startup
29
+ */
30
+
31
+
32
+
33
+
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Next.js Instrumentation with SecureNow - Advanced Configuration
3
+ *
4
+ * This example shows how to pass configuration options programmatically
5
+ * instead of using environment variables.
6
+ */
7
+
8
+ import { registerSecureNow } from 'securenow/nextjs';
9
+
10
+ export function register() {
11
+ registerSecureNow({
12
+ serviceName: 'my-nextjs-app',
13
+ endpoint: 'http://your-signoz-server:4318',
14
+ noUuid: false,
15
+ disableInstrumentations: ['fs', 'dns'],
16
+ headers: {
17
+ 'x-api-key': process.env.SECURENOW_API_KEY || '',
18
+ },
19
+ });
20
+ }
21
+
22
+ /**
23
+ * You can still use environment variables alongside options.
24
+ * Options take precedence over environment variables.
25
+ *
26
+ * Mix and match as needed:
27
+ * - Use options for static config
28
+ * - Use env vars for secrets and per-environment config
29
+ */
30
+
31
+
32
+
33
+