@use-tusk/drift-node-sdk 0.1.34 → 0.1.36
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/README.md +1 -1
- package/dist/chunk-Cd-22Um9.cjs +69 -0
- package/dist/index.cjs +928 -694
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -83
- package/dist/index.d.ts +1 -83
- package/dist/index.js +625 -353
- package/dist/index.js.map +1 -1
- package/dist/instrumentation-manifest.json +3 -5
- package/dist/next.cjs +211 -0
- package/dist/next.cjs.map +1 -0
- package/dist/next.d.cts +84 -0
- package/dist/next.d.ts +84 -0
- package/dist/next.js +207 -0
- package/dist/next.js.map +1 -0
- package/package.json +15 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"sdkVersion": "0.1.
|
|
2
|
+
"sdkVersion": "0.1.36",
|
|
3
3
|
"language": "node",
|
|
4
|
-
"generatedAt": "2026-03-
|
|
4
|
+
"generatedAt": "2026-03-11T22:44:41.220Z",
|
|
5
5
|
"instrumentations": [
|
|
6
6
|
{
|
|
7
7
|
"packageName": "@google-cloud/firestore",
|
|
@@ -96,9 +96,7 @@
|
|
|
96
96
|
{
|
|
97
97
|
"packageName": "mongodb",
|
|
98
98
|
"supportedVersions": [
|
|
99
|
-
"
|
|
100
|
-
"6.*",
|
|
101
|
-
"7.*"
|
|
99
|
+
"*"
|
|
102
100
|
]
|
|
103
101
|
},
|
|
104
102
|
{
|
package/dist/next.cjs
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
const require_chunk = require('./chunk-Cd-22Um9.cjs');
|
|
2
|
+
let fs = require("fs");
|
|
3
|
+
fs = require_chunk.__toESM(fs);
|
|
4
|
+
let path = require("path");
|
|
5
|
+
path = require_chunk.__toESM(path);
|
|
6
|
+
let semver = require("semver");
|
|
7
|
+
semver = require_chunk.__toESM(semver);
|
|
8
|
+
|
|
9
|
+
//#region src/nextjs/utils.ts
|
|
10
|
+
/**
|
|
11
|
+
* Get the installed Next.js version by reading package.json from node_modules.
|
|
12
|
+
*
|
|
13
|
+
* @returns The Next.js version string, or undefined if not found
|
|
14
|
+
*/
|
|
15
|
+
function getNextjsVersion() {
|
|
16
|
+
try {
|
|
17
|
+
const nextPackageJsonPath = path.join(process.cwd(), "node_modules", "next", "package.json");
|
|
18
|
+
if (fs.existsSync(nextPackageJsonPath)) return JSON.parse(fs.readFileSync(nextPackageJsonPath, "utf-8")).version;
|
|
19
|
+
} catch (error) {}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Parse a semantic version string into its components.
|
|
23
|
+
*
|
|
24
|
+
* @param version - The version string to parse (e.g., "15.0.0-canary.124")
|
|
25
|
+
* @returns Parsed version object with major, minor, patch, and prerelease
|
|
26
|
+
*/
|
|
27
|
+
function parseVersion(version) {
|
|
28
|
+
try {
|
|
29
|
+
const parsed = (0, semver.parse)(version);
|
|
30
|
+
if (!parsed) return {
|
|
31
|
+
major: void 0,
|
|
32
|
+
minor: void 0,
|
|
33
|
+
patch: void 0,
|
|
34
|
+
prerelease: void 0
|
|
35
|
+
};
|
|
36
|
+
return {
|
|
37
|
+
major: parsed.major,
|
|
38
|
+
minor: parsed.minor,
|
|
39
|
+
patch: parsed.patch,
|
|
40
|
+
prerelease: parsed.prerelease.length > 0 ? parsed.prerelease.join(".") : void 0
|
|
41
|
+
};
|
|
42
|
+
} catch {
|
|
43
|
+
return {
|
|
44
|
+
major: void 0,
|
|
45
|
+
minor: void 0,
|
|
46
|
+
patch: void 0,
|
|
47
|
+
prerelease: void 0
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Check if the Next.js version requires the instrumentationHook to be set.
|
|
53
|
+
* From Next.js 15.0.0-rc.1 onwards, the instrumentationHook is no longer needed
|
|
54
|
+
* and Next.js will warn if it's set.
|
|
55
|
+
*
|
|
56
|
+
* @param version - The Next.js version string
|
|
57
|
+
* @returns true if instrumentationHook should be set, false otherwise
|
|
58
|
+
*/
|
|
59
|
+
function shouldSetInstrumentationHook(version) {
|
|
60
|
+
if (!version) return true;
|
|
61
|
+
const { major, minor, patch, prerelease } = parseVersion(version);
|
|
62
|
+
if (major === void 0 || minor === void 0 || patch === void 0) return true;
|
|
63
|
+
if (major >= 16) return false;
|
|
64
|
+
if (major < 15) return true;
|
|
65
|
+
if (major === 15) {
|
|
66
|
+
if (minor > 0 || patch > 0) return false;
|
|
67
|
+
if (minor === 0 && patch === 0 && prerelease === void 0) return false;
|
|
68
|
+
if (prerelease?.startsWith("rc.")) {
|
|
69
|
+
if (parseInt(prerelease.split(".")[1] || "0", 10) >= 1) return false;
|
|
70
|
+
}
|
|
71
|
+
if (prerelease?.startsWith("canary.")) {
|
|
72
|
+
if (parseInt(prerelease.split(".")[1] || "0", 10) >= 124) return false;
|
|
73
|
+
}
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Log a message if debug mode is enabled.
|
|
80
|
+
*
|
|
81
|
+
* @param debug - Whether debug mode is enabled
|
|
82
|
+
* @param message - The message to log
|
|
83
|
+
*/
|
|
84
|
+
function debugLog(debug, message) {
|
|
85
|
+
if (debug) console.log(`[Tusk Drift] ${message}`);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Log a warning message if warnings are not suppressed.
|
|
89
|
+
*
|
|
90
|
+
* @param suppress - Whether to suppress the warning
|
|
91
|
+
* @param message - The warning message to log
|
|
92
|
+
*/
|
|
93
|
+
function warn(suppress, message) {
|
|
94
|
+
if (!suppress) console.warn(`[Tusk Drift] ${message}`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
//#endregion
|
|
98
|
+
//#region src/nextjs/withTuskDrift.ts
|
|
99
|
+
/**
|
|
100
|
+
* Wraps your Next.js configuration with Tusk Drift instrumentation setup.
|
|
101
|
+
*
|
|
102
|
+
* This function automatically configures Next.js to work with Tusk Drift by:
|
|
103
|
+
* - Enabling the Next.js instrumentation hook (for Next.js < 15.0.0-rc.1)
|
|
104
|
+
* - Configuring server external packages to prevent bundling of core instrumentation packages
|
|
105
|
+
* - Supporting both webpack and Turbopack bundlers
|
|
106
|
+
* - Preserving your existing Next.js configuration and webpack customizations
|
|
107
|
+
*
|
|
108
|
+
* @param nextConfig - Your existing Next.js configuration object (optional)
|
|
109
|
+
* @param options - Additional options to configure Tusk Drift's behavior (optional)
|
|
110
|
+
* @returns The wrapped Next.js configuration with Tusk Drift instrumentation enabled
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* Basic usage:
|
|
114
|
+
* ```javascript
|
|
115
|
+
* // next.config.js
|
|
116
|
+
* const { withTuskDrift } = require('@use-tusk/drift-node-sdk/next');
|
|
117
|
+
*
|
|
118
|
+
* module.exports = withTuskDrift({
|
|
119
|
+
* // Your Next.js config
|
|
120
|
+
* });
|
|
121
|
+
* ```
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* With debug logging:
|
|
125
|
+
* ```javascript
|
|
126
|
+
* // next.config.js
|
|
127
|
+
* const { withTuskDrift } = require('@use-tusk/drift-node-sdk/next');
|
|
128
|
+
*
|
|
129
|
+
* module.exports = withTuskDrift(
|
|
130
|
+
* {
|
|
131
|
+
* // Your Next.js config
|
|
132
|
+
* },
|
|
133
|
+
* {
|
|
134
|
+
* debug: true,
|
|
135
|
+
* }
|
|
136
|
+
* );
|
|
137
|
+
* ```
|
|
138
|
+
*
|
|
139
|
+
* @remarks
|
|
140
|
+
* The following packages are added as server externals for both webpack and Turbopack:
|
|
141
|
+
* - `require-in-the-middle` - Required for CommonJS module interception
|
|
142
|
+
* - `jsonpath` - Required for schema manipulation
|
|
143
|
+
* - Additional packages when TUSK_DRIFT_MODE is RECORD or REPLAY (e.g., database clients, etc.)
|
|
144
|
+
*
|
|
145
|
+
* Works with both webpack (default) and Turbopack (`next dev --turbo`).
|
|
146
|
+
*/
|
|
147
|
+
function withTuskDrift(nextConfig = {}, options = {}) {
|
|
148
|
+
const config = nextConfig;
|
|
149
|
+
const debug = options.debug || false;
|
|
150
|
+
const suppressAllWarnings = options.suppressWarnings || false;
|
|
151
|
+
const nextjsVersion = getNextjsVersion();
|
|
152
|
+
if (nextjsVersion) debugLog(debug, `Detected Next.js version: ${nextjsVersion}`);
|
|
153
|
+
else warn(suppressAllWarnings || false, "Could not detect Next.js version. Some features may not work correctly. If you encounter issues, please ensure Next.js is properly installed.");
|
|
154
|
+
const needsInstrumentationHook = !options.disableInstrumentationHook && shouldSetInstrumentationHook(nextjsVersion);
|
|
155
|
+
const mode = process.env.TUSK_DRIFT_MODE?.toUpperCase();
|
|
156
|
+
const coreExternals = [
|
|
157
|
+
"require-in-the-middle",
|
|
158
|
+
"jsonpath",
|
|
159
|
+
...mode === "RECORD" || mode === "REPLAY" ? [
|
|
160
|
+
"@upstash/redis",
|
|
161
|
+
"ioredis",
|
|
162
|
+
"pg",
|
|
163
|
+
"postgres",
|
|
164
|
+
"mysql2",
|
|
165
|
+
"@prisma/client",
|
|
166
|
+
"@google-cloud/firestore",
|
|
167
|
+
"@grpc/grpc-js",
|
|
168
|
+
"graphql",
|
|
169
|
+
"jsonwebtoken",
|
|
170
|
+
"jwks-rsa"
|
|
171
|
+
] : []
|
|
172
|
+
];
|
|
173
|
+
const wrappedConfig = {
|
|
174
|
+
...config,
|
|
175
|
+
...needsInstrumentationHook ? { experimental: {
|
|
176
|
+
...config.experimental,
|
|
177
|
+
instrumentationHook: true
|
|
178
|
+
} } : { experimental: config.experimental },
|
|
179
|
+
serverExternalPackages: [...config.serverExternalPackages || [], ...coreExternals],
|
|
180
|
+
webpack: (webpackConfig, webpackOptions) => {
|
|
181
|
+
if (webpackOptions.isServer) {
|
|
182
|
+
const originalExternals = webpackConfig.externals;
|
|
183
|
+
const externalsMapping = {};
|
|
184
|
+
for (const pkg of coreExternals) {
|
|
185
|
+
externalsMapping[pkg] = `commonjs ${pkg}`;
|
|
186
|
+
debugLog(debug, `Mapped external ${pkg} -> commonjs ${pkg}`);
|
|
187
|
+
}
|
|
188
|
+
if (!originalExternals) {
|
|
189
|
+
webpackConfig.externals = [externalsMapping];
|
|
190
|
+
debugLog(debug, "Created new externals with SDK paths");
|
|
191
|
+
} else if (Array.isArray(originalExternals)) {
|
|
192
|
+
originalExternals.push(externalsMapping);
|
|
193
|
+
debugLog(debug, "Added SDK paths to existing externals array");
|
|
194
|
+
} else {
|
|
195
|
+
webpackConfig.externals = [originalExternals, externalsMapping];
|
|
196
|
+
debugLog(debug, "Wrapped existing externals with SDK paths");
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (typeof config.webpack === "function") return config.webpack(webpackConfig, webpackOptions);
|
|
200
|
+
return webpackConfig;
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
if (needsInstrumentationHook) debugLog(debug, "Set experimental.instrumentationHook to true");
|
|
204
|
+
else debugLog(debug, "Skipped setting experimental.instrumentationHook (not needed for Next.js 15.0.0-rc.1+)");
|
|
205
|
+
if (options.disableInstrumentationHook && nextjsVersion && shouldSetInstrumentationHook(nextjsVersion)) warn(suppressAllWarnings || false, "You disabled instrumentationHook, but your Next.js version requires it. Tusk Drift may not initialize properly. Please remove the disableInstrumentationHook option.");
|
|
206
|
+
return wrappedConfig;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
//#endregion
|
|
210
|
+
exports.withTuskDrift = withTuskDrift;
|
|
211
|
+
//# sourceMappingURL=next.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"next.cjs","names":["wrappedConfig: NextConfig","externalsMapping: Record<string, string>"],"sources":["../src/nextjs/utils.ts","../src/nextjs/withTuskDrift.ts"],"sourcesContent":["import * as fs from \"fs\";\nimport * as path from \"path\";\nimport { parse as parseSemver } from \"semver\";\nimport type { ParsedVersion } from \"./types\";\n\n/**\n * Get the installed Next.js version by reading package.json from node_modules.\n *\n * @returns The Next.js version string, or undefined if not found\n */\nexport function getNextjsVersion(): string | undefined {\n try {\n // Try to read from node_modules/next/package.json\n const nextPackageJsonPath = path.join(process.cwd(), \"node_modules\", \"next\", \"package.json\");\n\n if (fs.existsSync(nextPackageJsonPath)) {\n const packageJson = JSON.parse(fs.readFileSync(nextPackageJsonPath, \"utf-8\"));\n return packageJson.version;\n }\n } catch (error) {\n // Silent failure - we'll warn the user in the main function\n }\n\n return undefined;\n}\n\n/**\n * Parse a semantic version string into its components.\n *\n * @param version - The version string to parse (e.g., \"15.0.0-canary.124\")\n * @returns Parsed version object with major, minor, patch, and prerelease\n */\nexport function parseVersion(version: string): ParsedVersion {\n try {\n const parsed = parseSemver(version);\n\n if (!parsed) {\n return {\n major: undefined,\n minor: undefined,\n patch: undefined,\n prerelease: undefined,\n };\n }\n\n return {\n major: parsed.major,\n minor: parsed.minor,\n patch: parsed.patch,\n prerelease: parsed.prerelease.length > 0 ? parsed.prerelease.join(\".\") : undefined,\n };\n } catch {\n return {\n major: undefined,\n minor: undefined,\n patch: undefined,\n prerelease: undefined,\n };\n }\n}\n\n/**\n * Check if the Next.js version requires the instrumentationHook to be set.\n * From Next.js 15.0.0-rc.1 onwards, the instrumentationHook is no longer needed\n * and Next.js will warn if it's set.\n *\n * @param version - The Next.js version string\n * @returns true if instrumentationHook should be set, false otherwise\n */\nexport function shouldSetInstrumentationHook(version: string | undefined): boolean {\n if (!version) {\n // If we can't detect the version, err on the side of setting it\n // (better to have a warning than broken instrumentation)\n return true;\n }\n\n const { major, minor, patch, prerelease } = parseVersion(version);\n\n // Unable to parse version\n if (major === undefined || minor === undefined || patch === undefined) {\n return true;\n }\n\n // Next.js 16+ definitely doesn't need it\n if (major >= 16) {\n return false;\n }\n\n // Next.js 14 and below need it\n if (major < 15) {\n return true;\n }\n\n // Next.js 15.x.x - check specific versions\n if (major === 15) {\n // 15.0.0 stable and higher don't need it\n if (minor > 0 || patch > 0) {\n return false;\n }\n\n // Check if it's 15.0.0 with no prerelease (stable)\n if (minor === 0 && patch === 0 && prerelease === undefined) {\n return false;\n }\n\n // Check for RC versions (rc.1 and higher don't need it)\n if (prerelease?.startsWith(\"rc.\")) {\n const rcNumber = parseInt(prerelease.split(\".\")[1] || \"0\", 10);\n if (rcNumber >= 1) {\n return false;\n }\n }\n\n // Check for canary versions (canary.124 and higher don't need it)\n if (prerelease?.startsWith(\"canary.\")) {\n const canaryNumber = parseInt(prerelease.split(\".\")[1] || \"0\", 10);\n if (canaryNumber >= 124) {\n return false;\n }\n }\n\n // All other 15.0.0 prereleases need it\n return true;\n }\n\n // Default to true for safety\n return true;\n}\n\n/**\n * Log a message if debug mode is enabled.\n *\n * @param debug - Whether debug mode is enabled\n * @param message - The message to log\n */\nexport function debugLog(debug: boolean, message: string): void {\n if (debug) {\n // eslint-disable-next-line no-console\n console.log(`[Tusk Drift] ${message}`);\n }\n}\n\n/**\n * Log a warning message if warnings are not suppressed.\n *\n * @param suppress - Whether to suppress the warning\n * @param message - The warning message to log\n */\nexport function warn(suppress: boolean, message: string): void {\n if (!suppress) {\n // eslint-disable-next-line no-console\n console.warn(`[Tusk Drift] ${message}`);\n }\n}\n","import type { NextConfig } from \"next\";\nimport type { TuskDriftNextOptions } from \"./types\";\nimport { getNextjsVersion, shouldSetInstrumentationHook, debugLog, warn } from \"./utils\";\n\n/**\n * Wraps your Next.js configuration with Tusk Drift instrumentation setup.\n *\n * This function automatically configures Next.js to work with Tusk Drift by:\n * - Enabling the Next.js instrumentation hook (for Next.js < 15.0.0-rc.1)\n * - Configuring server external packages to prevent bundling of core instrumentation packages\n * - Supporting both webpack and Turbopack bundlers\n * - Preserving your existing Next.js configuration and webpack customizations\n *\n * @param nextConfig - Your existing Next.js configuration object (optional)\n * @param options - Additional options to configure Tusk Drift's behavior (optional)\n * @returns The wrapped Next.js configuration with Tusk Drift instrumentation enabled\n *\n * @example\n * Basic usage:\n * ```javascript\n * // next.config.js\n * const { withTuskDrift } = require('@use-tusk/drift-node-sdk/next');\n *\n * module.exports = withTuskDrift({\n * // Your Next.js config\n * });\n * ```\n *\n * @example\n * With debug logging:\n * ```javascript\n * // next.config.js\n * const { withTuskDrift } = require('@use-tusk/drift-node-sdk/next');\n *\n * module.exports = withTuskDrift(\n * {\n * // Your Next.js config\n * },\n * {\n * debug: true,\n * }\n * );\n * ```\n *\n * @remarks\n * The following packages are added as server externals for both webpack and Turbopack:\n * - `require-in-the-middle` - Required for CommonJS module interception\n * - `jsonpath` - Required for schema manipulation\n * - Additional packages when TUSK_DRIFT_MODE is RECORD or REPLAY (e.g., database clients, etc.)\n *\n * Works with both webpack (default) and Turbopack (`next dev --turbo`).\n */\nexport function withTuskDrift(\n nextConfig: NextConfig = {},\n options: TuskDriftNextOptions = {},\n): NextConfig {\n const config = nextConfig;\n\n const debug = options.debug || false;\n const suppressAllWarnings = options.suppressWarnings || false;\n\n // Detect Next.js version\n const nextjsVersion = getNextjsVersion();\n\n if (nextjsVersion) {\n debugLog(debug, `Detected Next.js version: ${nextjsVersion}`);\n } else {\n warn(\n suppressAllWarnings || false,\n \"Could not detect Next.js version. Some features may not work correctly. \" +\n \"If you encounter issues, please ensure Next.js is properly installed.\",\n );\n }\n\n // Determine if we should set instrumentationHook\n const needsInstrumentationHook =\n !options.disableInstrumentationHook && shouldSetInstrumentationHook(nextjsVersion);\n\n // Check if we're in RECORD or REPLAY mode\n const mode = process.env.TUSK_DRIFT_MODE?.toUpperCase();\n const isRecordOrReplay = mode === \"RECORD\" || mode === \"REPLAY\";\n\n // Core packages that must be external for instrumentation\n //\n // Why these packages need to be external:\n //\n // 1. require-in-the-middle & jsonpath:\n // Required for the instrumentation infrastructure itself.\n //\n // 2. Others:\n // By default, Next.js bundlers (webpack/Turbopack) bundle packages into the server bundle at build time.\n // Once bundled, there's no runtime require() call for require-in-the-middle to intercept.\n // The instrumentation's patch callback never executes because module loading has already\n // happened during the build process, not at runtime.\n //\n // By adding packages to serverExternalPackages (for both webpack and Turbopack) and webpack externals\n // (for webpack specifically), we tell the bundler to exclude these packages from bundling.\n // Instead, the bundler leaves these packages as runtime require() calls. When the Next.js server starts,\n // require-in-the-middle intercepts these runtime require() calls, triggers our instrumentation's\n // patch callback, and successfully returns the wrapped moduleExports with the instrumented class.\n //\n // Next.js externalizes some packages by default, see: https://nextjs.org/docs/app/api-reference/config/next-config-js/serverExternalPackages\n // Others we need to add ourselves.\n //\n // Note: Other packages are only added when TUSK_DRIFT_MODE is RECORD or REPLAY\n const coreExternals = [\n \"require-in-the-middle\",\n \"jsonpath\",\n ...(isRecordOrReplay\n ? [\n \"@upstash/redis\",\n \"ioredis\",\n \"pg\",\n \"postgres\",\n \"mysql2\",\n \"@prisma/client\",\n \"@google-cloud/firestore\",\n \"@grpc/grpc-js\",\n \"graphql\",\n \"jsonwebtoken\",\n \"jwks-rsa\",\n ]\n : []),\n ];\n\n const wrappedConfig: NextConfig = {\n ...config,\n ...(needsInstrumentationHook\n ? {\n experimental: {\n ...config.experimental,\n instrumentationHook: true,\n } as any, // Type assertion for experimental features\n }\n : {\n experimental: config.experimental,\n }),\n\n // Add serverExternalPackages for Turbopack + Webpack support (Next.js 13.1+)\n // This ensures packages remain external regardless of which bundler is used\n serverExternalPackages: [...(config.serverExternalPackages || []), ...coreExternals],\n\n webpack: (webpackConfig: any, webpackOptions: any) => {\n if (webpackOptions.isServer) {\n // Safely handle different externals formats (array, function, object, or undefined)\n const originalExternals = webpackConfig.externals;\n\n // Create externals mapping - since SDK's node_modules aren't published,\n // we rely on these packages being available in the consumer's node_modules\n const externalsMapping: Record<string, string> = {};\n for (const pkg of coreExternals) {\n externalsMapping[pkg] = `commonjs ${pkg}`;\n debugLog(debug, `Mapped external ${pkg} -> commonjs ${pkg}`);\n }\n\n // Add our externals mapping\n if (!originalExternals) {\n webpackConfig.externals = [externalsMapping];\n debugLog(debug, \"Created new externals with SDK paths\");\n } else if (Array.isArray(originalExternals)) {\n originalExternals.push(externalsMapping);\n debugLog(debug, \"Added SDK paths to existing externals array\");\n } else {\n webpackConfig.externals = [originalExternals, externalsMapping];\n debugLog(debug, \"Wrapped existing externals with SDK paths\");\n }\n }\n\n // Call user's webpack function if they provided one\n if (typeof config.webpack === \"function\") {\n return config.webpack(webpackConfig, webpackOptions);\n }\n\n return webpackConfig;\n },\n };\n\n if (needsInstrumentationHook) {\n debugLog(debug, \"Set experimental.instrumentationHook to true\");\n } else {\n debugLog(\n debug,\n \"Skipped setting experimental.instrumentationHook (not needed for Next.js 15.0.0-rc.1+)\",\n );\n }\n\n // Warn if user explicitly disabled instrumentationHook but we need it\n if (\n options.disableInstrumentationHook &&\n nextjsVersion &&\n shouldSetInstrumentationHook(nextjsVersion)\n ) {\n warn(\n suppressAllWarnings || false,\n \"You disabled instrumentationHook, but your Next.js version requires it. \" +\n \"Tusk Drift may not initialize properly. Please remove the disableInstrumentationHook option.\",\n );\n }\n\n return wrappedConfig;\n}\n"],"mappings":"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"}
|
package/dist/next.d.cts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { NextConfig } from "next";
|
|
2
|
+
|
|
3
|
+
//#region src/nextjs/types.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Options for configuring Tusk Drift's Next.js integration.
|
|
7
|
+
*/
|
|
8
|
+
interface TuskDriftNextOptions {
|
|
9
|
+
/**
|
|
10
|
+
* Enable debug logging for Tusk Drift's Next.js integration.
|
|
11
|
+
* When enabled, logs information about configuration changes and version detection.
|
|
12
|
+
*
|
|
13
|
+
* @default false
|
|
14
|
+
*/
|
|
15
|
+
debug?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Disable automatic setting of `experimental.instrumentationHook`.
|
|
18
|
+
* Use this if you want to manually control the instrumentation hook setting.
|
|
19
|
+
*
|
|
20
|
+
* @default false
|
|
21
|
+
*/
|
|
22
|
+
disableInstrumentationHook?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Suppress all warnings from Tusk Drift's Next.js integration.
|
|
25
|
+
* Not recommended unless you know what you're doing.
|
|
26
|
+
*
|
|
27
|
+
* @default false
|
|
28
|
+
*/
|
|
29
|
+
suppressWarnings?: boolean;
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region src/nextjs/withTuskDrift.d.ts
|
|
33
|
+
/**
|
|
34
|
+
* Wraps your Next.js configuration with Tusk Drift instrumentation setup.
|
|
35
|
+
*
|
|
36
|
+
* This function automatically configures Next.js to work with Tusk Drift by:
|
|
37
|
+
* - Enabling the Next.js instrumentation hook (for Next.js < 15.0.0-rc.1)
|
|
38
|
+
* - Configuring server external packages to prevent bundling of core instrumentation packages
|
|
39
|
+
* - Supporting both webpack and Turbopack bundlers
|
|
40
|
+
* - Preserving your existing Next.js configuration and webpack customizations
|
|
41
|
+
*
|
|
42
|
+
* @param nextConfig - Your existing Next.js configuration object (optional)
|
|
43
|
+
* @param options - Additional options to configure Tusk Drift's behavior (optional)
|
|
44
|
+
* @returns The wrapped Next.js configuration with Tusk Drift instrumentation enabled
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* Basic usage:
|
|
48
|
+
* ```javascript
|
|
49
|
+
* // next.config.js
|
|
50
|
+
* const { withTuskDrift } = require('@use-tusk/drift-node-sdk/next');
|
|
51
|
+
*
|
|
52
|
+
* module.exports = withTuskDrift({
|
|
53
|
+
* // Your Next.js config
|
|
54
|
+
* });
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* With debug logging:
|
|
59
|
+
* ```javascript
|
|
60
|
+
* // next.config.js
|
|
61
|
+
* const { withTuskDrift } = require('@use-tusk/drift-node-sdk/next');
|
|
62
|
+
*
|
|
63
|
+
* module.exports = withTuskDrift(
|
|
64
|
+
* {
|
|
65
|
+
* // Your Next.js config
|
|
66
|
+
* },
|
|
67
|
+
* {
|
|
68
|
+
* debug: true,
|
|
69
|
+
* }
|
|
70
|
+
* );
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* @remarks
|
|
74
|
+
* The following packages are added as server externals for both webpack and Turbopack:
|
|
75
|
+
* - `require-in-the-middle` - Required for CommonJS module interception
|
|
76
|
+
* - `jsonpath` - Required for schema manipulation
|
|
77
|
+
* - Additional packages when TUSK_DRIFT_MODE is RECORD or REPLAY (e.g., database clients, etc.)
|
|
78
|
+
*
|
|
79
|
+
* Works with both webpack (default) and Turbopack (`next dev --turbo`).
|
|
80
|
+
*/
|
|
81
|
+
declare function withTuskDrift(nextConfig?: NextConfig, options?: TuskDriftNextOptions): NextConfig;
|
|
82
|
+
//#endregion
|
|
83
|
+
export { type TuskDriftNextOptions, withTuskDrift };
|
|
84
|
+
//# sourceMappingURL=next.d.cts.map
|
package/dist/next.d.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { NextConfig } from "next";
|
|
2
|
+
|
|
3
|
+
//#region src/nextjs/types.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Options for configuring Tusk Drift's Next.js integration.
|
|
7
|
+
*/
|
|
8
|
+
interface TuskDriftNextOptions {
|
|
9
|
+
/**
|
|
10
|
+
* Enable debug logging for Tusk Drift's Next.js integration.
|
|
11
|
+
* When enabled, logs information about configuration changes and version detection.
|
|
12
|
+
*
|
|
13
|
+
* @default false
|
|
14
|
+
*/
|
|
15
|
+
debug?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Disable automatic setting of `experimental.instrumentationHook`.
|
|
18
|
+
* Use this if you want to manually control the instrumentation hook setting.
|
|
19
|
+
*
|
|
20
|
+
* @default false
|
|
21
|
+
*/
|
|
22
|
+
disableInstrumentationHook?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Suppress all warnings from Tusk Drift's Next.js integration.
|
|
25
|
+
* Not recommended unless you know what you're doing.
|
|
26
|
+
*
|
|
27
|
+
* @default false
|
|
28
|
+
*/
|
|
29
|
+
suppressWarnings?: boolean;
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region src/nextjs/withTuskDrift.d.ts
|
|
33
|
+
/**
|
|
34
|
+
* Wraps your Next.js configuration with Tusk Drift instrumentation setup.
|
|
35
|
+
*
|
|
36
|
+
* This function automatically configures Next.js to work with Tusk Drift by:
|
|
37
|
+
* - Enabling the Next.js instrumentation hook (for Next.js < 15.0.0-rc.1)
|
|
38
|
+
* - Configuring server external packages to prevent bundling of core instrumentation packages
|
|
39
|
+
* - Supporting both webpack and Turbopack bundlers
|
|
40
|
+
* - Preserving your existing Next.js configuration and webpack customizations
|
|
41
|
+
*
|
|
42
|
+
* @param nextConfig - Your existing Next.js configuration object (optional)
|
|
43
|
+
* @param options - Additional options to configure Tusk Drift's behavior (optional)
|
|
44
|
+
* @returns The wrapped Next.js configuration with Tusk Drift instrumentation enabled
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* Basic usage:
|
|
48
|
+
* ```javascript
|
|
49
|
+
* // next.config.js
|
|
50
|
+
* const { withTuskDrift } = require('@use-tusk/drift-node-sdk/next');
|
|
51
|
+
*
|
|
52
|
+
* module.exports = withTuskDrift({
|
|
53
|
+
* // Your Next.js config
|
|
54
|
+
* });
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* With debug logging:
|
|
59
|
+
* ```javascript
|
|
60
|
+
* // next.config.js
|
|
61
|
+
* const { withTuskDrift } = require('@use-tusk/drift-node-sdk/next');
|
|
62
|
+
*
|
|
63
|
+
* module.exports = withTuskDrift(
|
|
64
|
+
* {
|
|
65
|
+
* // Your Next.js config
|
|
66
|
+
* },
|
|
67
|
+
* {
|
|
68
|
+
* debug: true,
|
|
69
|
+
* }
|
|
70
|
+
* );
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* @remarks
|
|
74
|
+
* The following packages are added as server externals for both webpack and Turbopack:
|
|
75
|
+
* - `require-in-the-middle` - Required for CommonJS module interception
|
|
76
|
+
* - `jsonpath` - Required for schema manipulation
|
|
77
|
+
* - Additional packages when TUSK_DRIFT_MODE is RECORD or REPLAY (e.g., database clients, etc.)
|
|
78
|
+
*
|
|
79
|
+
* Works with both webpack (default) and Turbopack (`next dev --turbo`).
|
|
80
|
+
*/
|
|
81
|
+
declare function withTuskDrift(nextConfig?: NextConfig, options?: TuskDriftNextOptions): NextConfig;
|
|
82
|
+
//#endregion
|
|
83
|
+
export { type TuskDriftNextOptions, withTuskDrift };
|
|
84
|
+
//# sourceMappingURL=next.d.ts.map
|
package/dist/next.js
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import * as fs$1 from "fs";
|
|
2
|
+
import * as path$1 from "path";
|
|
3
|
+
import { parse } from "semver";
|
|
4
|
+
|
|
5
|
+
//#region src/nextjs/utils.ts
|
|
6
|
+
/**
|
|
7
|
+
* Get the installed Next.js version by reading package.json from node_modules.
|
|
8
|
+
*
|
|
9
|
+
* @returns The Next.js version string, or undefined if not found
|
|
10
|
+
*/
|
|
11
|
+
function getNextjsVersion() {
|
|
12
|
+
try {
|
|
13
|
+
const nextPackageJsonPath = path$1.join(process.cwd(), "node_modules", "next", "package.json");
|
|
14
|
+
if (fs$1.existsSync(nextPackageJsonPath)) return JSON.parse(fs$1.readFileSync(nextPackageJsonPath, "utf-8")).version;
|
|
15
|
+
} catch (error) {}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Parse a semantic version string into its components.
|
|
19
|
+
*
|
|
20
|
+
* @param version - The version string to parse (e.g., "15.0.0-canary.124")
|
|
21
|
+
* @returns Parsed version object with major, minor, patch, and prerelease
|
|
22
|
+
*/
|
|
23
|
+
function parseVersion(version) {
|
|
24
|
+
try {
|
|
25
|
+
const parsed = parse(version);
|
|
26
|
+
if (!parsed) return {
|
|
27
|
+
major: void 0,
|
|
28
|
+
minor: void 0,
|
|
29
|
+
patch: void 0,
|
|
30
|
+
prerelease: void 0
|
|
31
|
+
};
|
|
32
|
+
return {
|
|
33
|
+
major: parsed.major,
|
|
34
|
+
minor: parsed.minor,
|
|
35
|
+
patch: parsed.patch,
|
|
36
|
+
prerelease: parsed.prerelease.length > 0 ? parsed.prerelease.join(".") : void 0
|
|
37
|
+
};
|
|
38
|
+
} catch {
|
|
39
|
+
return {
|
|
40
|
+
major: void 0,
|
|
41
|
+
minor: void 0,
|
|
42
|
+
patch: void 0,
|
|
43
|
+
prerelease: void 0
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Check if the Next.js version requires the instrumentationHook to be set.
|
|
49
|
+
* From Next.js 15.0.0-rc.1 onwards, the instrumentationHook is no longer needed
|
|
50
|
+
* and Next.js will warn if it's set.
|
|
51
|
+
*
|
|
52
|
+
* @param version - The Next.js version string
|
|
53
|
+
* @returns true if instrumentationHook should be set, false otherwise
|
|
54
|
+
*/
|
|
55
|
+
function shouldSetInstrumentationHook(version) {
|
|
56
|
+
if (!version) return true;
|
|
57
|
+
const { major, minor, patch, prerelease } = parseVersion(version);
|
|
58
|
+
if (major === void 0 || minor === void 0 || patch === void 0) return true;
|
|
59
|
+
if (major >= 16) return false;
|
|
60
|
+
if (major < 15) return true;
|
|
61
|
+
if (major === 15) {
|
|
62
|
+
if (minor > 0 || patch > 0) return false;
|
|
63
|
+
if (minor === 0 && patch === 0 && prerelease === void 0) return false;
|
|
64
|
+
if (prerelease?.startsWith("rc.")) {
|
|
65
|
+
if (parseInt(prerelease.split(".")[1] || "0", 10) >= 1) return false;
|
|
66
|
+
}
|
|
67
|
+
if (prerelease?.startsWith("canary.")) {
|
|
68
|
+
if (parseInt(prerelease.split(".")[1] || "0", 10) >= 124) return false;
|
|
69
|
+
}
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Log a message if debug mode is enabled.
|
|
76
|
+
*
|
|
77
|
+
* @param debug - Whether debug mode is enabled
|
|
78
|
+
* @param message - The message to log
|
|
79
|
+
*/
|
|
80
|
+
function debugLog(debug, message) {
|
|
81
|
+
if (debug) console.log(`[Tusk Drift] ${message}`);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Log a warning message if warnings are not suppressed.
|
|
85
|
+
*
|
|
86
|
+
* @param suppress - Whether to suppress the warning
|
|
87
|
+
* @param message - The warning message to log
|
|
88
|
+
*/
|
|
89
|
+
function warn(suppress, message) {
|
|
90
|
+
if (!suppress) console.warn(`[Tusk Drift] ${message}`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
//#endregion
|
|
94
|
+
//#region src/nextjs/withTuskDrift.ts
|
|
95
|
+
/**
|
|
96
|
+
* Wraps your Next.js configuration with Tusk Drift instrumentation setup.
|
|
97
|
+
*
|
|
98
|
+
* This function automatically configures Next.js to work with Tusk Drift by:
|
|
99
|
+
* - Enabling the Next.js instrumentation hook (for Next.js < 15.0.0-rc.1)
|
|
100
|
+
* - Configuring server external packages to prevent bundling of core instrumentation packages
|
|
101
|
+
* - Supporting both webpack and Turbopack bundlers
|
|
102
|
+
* - Preserving your existing Next.js configuration and webpack customizations
|
|
103
|
+
*
|
|
104
|
+
* @param nextConfig - Your existing Next.js configuration object (optional)
|
|
105
|
+
* @param options - Additional options to configure Tusk Drift's behavior (optional)
|
|
106
|
+
* @returns The wrapped Next.js configuration with Tusk Drift instrumentation enabled
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* Basic usage:
|
|
110
|
+
* ```javascript
|
|
111
|
+
* // next.config.js
|
|
112
|
+
* const { withTuskDrift } = require('@use-tusk/drift-node-sdk/next');
|
|
113
|
+
*
|
|
114
|
+
* module.exports = withTuskDrift({
|
|
115
|
+
* // Your Next.js config
|
|
116
|
+
* });
|
|
117
|
+
* ```
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* With debug logging:
|
|
121
|
+
* ```javascript
|
|
122
|
+
* // next.config.js
|
|
123
|
+
* const { withTuskDrift } = require('@use-tusk/drift-node-sdk/next');
|
|
124
|
+
*
|
|
125
|
+
* module.exports = withTuskDrift(
|
|
126
|
+
* {
|
|
127
|
+
* // Your Next.js config
|
|
128
|
+
* },
|
|
129
|
+
* {
|
|
130
|
+
* debug: true,
|
|
131
|
+
* }
|
|
132
|
+
* );
|
|
133
|
+
* ```
|
|
134
|
+
*
|
|
135
|
+
* @remarks
|
|
136
|
+
* The following packages are added as server externals for both webpack and Turbopack:
|
|
137
|
+
* - `require-in-the-middle` - Required for CommonJS module interception
|
|
138
|
+
* - `jsonpath` - Required for schema manipulation
|
|
139
|
+
* - Additional packages when TUSK_DRIFT_MODE is RECORD or REPLAY (e.g., database clients, etc.)
|
|
140
|
+
*
|
|
141
|
+
* Works with both webpack (default) and Turbopack (`next dev --turbo`).
|
|
142
|
+
*/
|
|
143
|
+
function withTuskDrift(nextConfig = {}, options = {}) {
|
|
144
|
+
const config = nextConfig;
|
|
145
|
+
const debug = options.debug || false;
|
|
146
|
+
const suppressAllWarnings = options.suppressWarnings || false;
|
|
147
|
+
const nextjsVersion = getNextjsVersion();
|
|
148
|
+
if (nextjsVersion) debugLog(debug, `Detected Next.js version: ${nextjsVersion}`);
|
|
149
|
+
else warn(suppressAllWarnings || false, "Could not detect Next.js version. Some features may not work correctly. If you encounter issues, please ensure Next.js is properly installed.");
|
|
150
|
+
const needsInstrumentationHook = !options.disableInstrumentationHook && shouldSetInstrumentationHook(nextjsVersion);
|
|
151
|
+
const mode = process.env.TUSK_DRIFT_MODE?.toUpperCase();
|
|
152
|
+
const coreExternals = [
|
|
153
|
+
"require-in-the-middle",
|
|
154
|
+
"jsonpath",
|
|
155
|
+
...mode === "RECORD" || mode === "REPLAY" ? [
|
|
156
|
+
"@upstash/redis",
|
|
157
|
+
"ioredis",
|
|
158
|
+
"pg",
|
|
159
|
+
"postgres",
|
|
160
|
+
"mysql2",
|
|
161
|
+
"@prisma/client",
|
|
162
|
+
"@google-cloud/firestore",
|
|
163
|
+
"@grpc/grpc-js",
|
|
164
|
+
"graphql",
|
|
165
|
+
"jsonwebtoken",
|
|
166
|
+
"jwks-rsa"
|
|
167
|
+
] : []
|
|
168
|
+
];
|
|
169
|
+
const wrappedConfig = {
|
|
170
|
+
...config,
|
|
171
|
+
...needsInstrumentationHook ? { experimental: {
|
|
172
|
+
...config.experimental,
|
|
173
|
+
instrumentationHook: true
|
|
174
|
+
} } : { experimental: config.experimental },
|
|
175
|
+
serverExternalPackages: [...config.serverExternalPackages || [], ...coreExternals],
|
|
176
|
+
webpack: (webpackConfig, webpackOptions) => {
|
|
177
|
+
if (webpackOptions.isServer) {
|
|
178
|
+
const originalExternals = webpackConfig.externals;
|
|
179
|
+
const externalsMapping = {};
|
|
180
|
+
for (const pkg of coreExternals) {
|
|
181
|
+
externalsMapping[pkg] = `commonjs ${pkg}`;
|
|
182
|
+
debugLog(debug, `Mapped external ${pkg} -> commonjs ${pkg}`);
|
|
183
|
+
}
|
|
184
|
+
if (!originalExternals) {
|
|
185
|
+
webpackConfig.externals = [externalsMapping];
|
|
186
|
+
debugLog(debug, "Created new externals with SDK paths");
|
|
187
|
+
} else if (Array.isArray(originalExternals)) {
|
|
188
|
+
originalExternals.push(externalsMapping);
|
|
189
|
+
debugLog(debug, "Added SDK paths to existing externals array");
|
|
190
|
+
} else {
|
|
191
|
+
webpackConfig.externals = [originalExternals, externalsMapping];
|
|
192
|
+
debugLog(debug, "Wrapped existing externals with SDK paths");
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (typeof config.webpack === "function") return config.webpack(webpackConfig, webpackOptions);
|
|
196
|
+
return webpackConfig;
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
if (needsInstrumentationHook) debugLog(debug, "Set experimental.instrumentationHook to true");
|
|
200
|
+
else debugLog(debug, "Skipped setting experimental.instrumentationHook (not needed for Next.js 15.0.0-rc.1+)");
|
|
201
|
+
if (options.disableInstrumentationHook && nextjsVersion && shouldSetInstrumentationHook(nextjsVersion)) warn(suppressAllWarnings || false, "You disabled instrumentationHook, but your Next.js version requires it. Tusk Drift may not initialize properly. Please remove the disableInstrumentationHook option.");
|
|
202
|
+
return wrappedConfig;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
//#endregion
|
|
206
|
+
export { withTuskDrift };
|
|
207
|
+
//# sourceMappingURL=next.js.map
|
package/dist/next.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"next.js","names":["path","fs","parseSemver","wrappedConfig: NextConfig","externalsMapping: Record<string, string>"],"sources":["../src/nextjs/utils.ts","../src/nextjs/withTuskDrift.ts"],"sourcesContent":["import * as fs from \"fs\";\nimport * as path from \"path\";\nimport { parse as parseSemver } from \"semver\";\nimport type { ParsedVersion } from \"./types\";\n\n/**\n * Get the installed Next.js version by reading package.json from node_modules.\n *\n * @returns The Next.js version string, or undefined if not found\n */\nexport function getNextjsVersion(): string | undefined {\n try {\n // Try to read from node_modules/next/package.json\n const nextPackageJsonPath = path.join(process.cwd(), \"node_modules\", \"next\", \"package.json\");\n\n if (fs.existsSync(nextPackageJsonPath)) {\n const packageJson = JSON.parse(fs.readFileSync(nextPackageJsonPath, \"utf-8\"));\n return packageJson.version;\n }\n } catch (error) {\n // Silent failure - we'll warn the user in the main function\n }\n\n return undefined;\n}\n\n/**\n * Parse a semantic version string into its components.\n *\n * @param version - The version string to parse (e.g., \"15.0.0-canary.124\")\n * @returns Parsed version object with major, minor, patch, and prerelease\n */\nexport function parseVersion(version: string): ParsedVersion {\n try {\n const parsed = parseSemver(version);\n\n if (!parsed) {\n return {\n major: undefined,\n minor: undefined,\n patch: undefined,\n prerelease: undefined,\n };\n }\n\n return {\n major: parsed.major,\n minor: parsed.minor,\n patch: parsed.patch,\n prerelease: parsed.prerelease.length > 0 ? parsed.prerelease.join(\".\") : undefined,\n };\n } catch {\n return {\n major: undefined,\n minor: undefined,\n patch: undefined,\n prerelease: undefined,\n };\n }\n}\n\n/**\n * Check if the Next.js version requires the instrumentationHook to be set.\n * From Next.js 15.0.0-rc.1 onwards, the instrumentationHook is no longer needed\n * and Next.js will warn if it's set.\n *\n * @param version - The Next.js version string\n * @returns true if instrumentationHook should be set, false otherwise\n */\nexport function shouldSetInstrumentationHook(version: string | undefined): boolean {\n if (!version) {\n // If we can't detect the version, err on the side of setting it\n // (better to have a warning than broken instrumentation)\n return true;\n }\n\n const { major, minor, patch, prerelease } = parseVersion(version);\n\n // Unable to parse version\n if (major === undefined || minor === undefined || patch === undefined) {\n return true;\n }\n\n // Next.js 16+ definitely doesn't need it\n if (major >= 16) {\n return false;\n }\n\n // Next.js 14 and below need it\n if (major < 15) {\n return true;\n }\n\n // Next.js 15.x.x - check specific versions\n if (major === 15) {\n // 15.0.0 stable and higher don't need it\n if (minor > 0 || patch > 0) {\n return false;\n }\n\n // Check if it's 15.0.0 with no prerelease (stable)\n if (minor === 0 && patch === 0 && prerelease === undefined) {\n return false;\n }\n\n // Check for RC versions (rc.1 and higher don't need it)\n if (prerelease?.startsWith(\"rc.\")) {\n const rcNumber = parseInt(prerelease.split(\".\")[1] || \"0\", 10);\n if (rcNumber >= 1) {\n return false;\n }\n }\n\n // Check for canary versions (canary.124 and higher don't need it)\n if (prerelease?.startsWith(\"canary.\")) {\n const canaryNumber = parseInt(prerelease.split(\".\")[1] || \"0\", 10);\n if (canaryNumber >= 124) {\n return false;\n }\n }\n\n // All other 15.0.0 prereleases need it\n return true;\n }\n\n // Default to true for safety\n return true;\n}\n\n/**\n * Log a message if debug mode is enabled.\n *\n * @param debug - Whether debug mode is enabled\n * @param message - The message to log\n */\nexport function debugLog(debug: boolean, message: string): void {\n if (debug) {\n // eslint-disable-next-line no-console\n console.log(`[Tusk Drift] ${message}`);\n }\n}\n\n/**\n * Log a warning message if warnings are not suppressed.\n *\n * @param suppress - Whether to suppress the warning\n * @param message - The warning message to log\n */\nexport function warn(suppress: boolean, message: string): void {\n if (!suppress) {\n // eslint-disable-next-line no-console\n console.warn(`[Tusk Drift] ${message}`);\n }\n}\n","import type { NextConfig } from \"next\";\nimport type { TuskDriftNextOptions } from \"./types\";\nimport { getNextjsVersion, shouldSetInstrumentationHook, debugLog, warn } from \"./utils\";\n\n/**\n * Wraps your Next.js configuration with Tusk Drift instrumentation setup.\n *\n * This function automatically configures Next.js to work with Tusk Drift by:\n * - Enabling the Next.js instrumentation hook (for Next.js < 15.0.0-rc.1)\n * - Configuring server external packages to prevent bundling of core instrumentation packages\n * - Supporting both webpack and Turbopack bundlers\n * - Preserving your existing Next.js configuration and webpack customizations\n *\n * @param nextConfig - Your existing Next.js configuration object (optional)\n * @param options - Additional options to configure Tusk Drift's behavior (optional)\n * @returns The wrapped Next.js configuration with Tusk Drift instrumentation enabled\n *\n * @example\n * Basic usage:\n * ```javascript\n * // next.config.js\n * const { withTuskDrift } = require('@use-tusk/drift-node-sdk/next');\n *\n * module.exports = withTuskDrift({\n * // Your Next.js config\n * });\n * ```\n *\n * @example\n * With debug logging:\n * ```javascript\n * // next.config.js\n * const { withTuskDrift } = require('@use-tusk/drift-node-sdk/next');\n *\n * module.exports = withTuskDrift(\n * {\n * // Your Next.js config\n * },\n * {\n * debug: true,\n * }\n * );\n * ```\n *\n * @remarks\n * The following packages are added as server externals for both webpack and Turbopack:\n * - `require-in-the-middle` - Required for CommonJS module interception\n * - `jsonpath` - Required for schema manipulation\n * - Additional packages when TUSK_DRIFT_MODE is RECORD or REPLAY (e.g., database clients, etc.)\n *\n * Works with both webpack (default) and Turbopack (`next dev --turbo`).\n */\nexport function withTuskDrift(\n nextConfig: NextConfig = {},\n options: TuskDriftNextOptions = {},\n): NextConfig {\n const config = nextConfig;\n\n const debug = options.debug || false;\n const suppressAllWarnings = options.suppressWarnings || false;\n\n // Detect Next.js version\n const nextjsVersion = getNextjsVersion();\n\n if (nextjsVersion) {\n debugLog(debug, `Detected Next.js version: ${nextjsVersion}`);\n } else {\n warn(\n suppressAllWarnings || false,\n \"Could not detect Next.js version. Some features may not work correctly. \" +\n \"If you encounter issues, please ensure Next.js is properly installed.\",\n );\n }\n\n // Determine if we should set instrumentationHook\n const needsInstrumentationHook =\n !options.disableInstrumentationHook && shouldSetInstrumentationHook(nextjsVersion);\n\n // Check if we're in RECORD or REPLAY mode\n const mode = process.env.TUSK_DRIFT_MODE?.toUpperCase();\n const isRecordOrReplay = mode === \"RECORD\" || mode === \"REPLAY\";\n\n // Core packages that must be external for instrumentation\n //\n // Why these packages need to be external:\n //\n // 1. require-in-the-middle & jsonpath:\n // Required for the instrumentation infrastructure itself.\n //\n // 2. Others:\n // By default, Next.js bundlers (webpack/Turbopack) bundle packages into the server bundle at build time.\n // Once bundled, there's no runtime require() call for require-in-the-middle to intercept.\n // The instrumentation's patch callback never executes because module loading has already\n // happened during the build process, not at runtime.\n //\n // By adding packages to serverExternalPackages (for both webpack and Turbopack) and webpack externals\n // (for webpack specifically), we tell the bundler to exclude these packages from bundling.\n // Instead, the bundler leaves these packages as runtime require() calls. When the Next.js server starts,\n // require-in-the-middle intercepts these runtime require() calls, triggers our instrumentation's\n // patch callback, and successfully returns the wrapped moduleExports with the instrumented class.\n //\n // Next.js externalizes some packages by default, see: https://nextjs.org/docs/app/api-reference/config/next-config-js/serverExternalPackages\n // Others we need to add ourselves.\n //\n // Note: Other packages are only added when TUSK_DRIFT_MODE is RECORD or REPLAY\n const coreExternals = [\n \"require-in-the-middle\",\n \"jsonpath\",\n ...(isRecordOrReplay\n ? [\n \"@upstash/redis\",\n \"ioredis\",\n \"pg\",\n \"postgres\",\n \"mysql2\",\n \"@prisma/client\",\n \"@google-cloud/firestore\",\n \"@grpc/grpc-js\",\n \"graphql\",\n \"jsonwebtoken\",\n \"jwks-rsa\",\n ]\n : []),\n ];\n\n const wrappedConfig: NextConfig = {\n ...config,\n ...(needsInstrumentationHook\n ? {\n experimental: {\n ...config.experimental,\n instrumentationHook: true,\n } as any, // Type assertion for experimental features\n }\n : {\n experimental: config.experimental,\n }),\n\n // Add serverExternalPackages for Turbopack + Webpack support (Next.js 13.1+)\n // This ensures packages remain external regardless of which bundler is used\n serverExternalPackages: [...(config.serverExternalPackages || []), ...coreExternals],\n\n webpack: (webpackConfig: any, webpackOptions: any) => {\n if (webpackOptions.isServer) {\n // Safely handle different externals formats (array, function, object, or undefined)\n const originalExternals = webpackConfig.externals;\n\n // Create externals mapping - since SDK's node_modules aren't published,\n // we rely on these packages being available in the consumer's node_modules\n const externalsMapping: Record<string, string> = {};\n for (const pkg of coreExternals) {\n externalsMapping[pkg] = `commonjs ${pkg}`;\n debugLog(debug, `Mapped external ${pkg} -> commonjs ${pkg}`);\n }\n\n // Add our externals mapping\n if (!originalExternals) {\n webpackConfig.externals = [externalsMapping];\n debugLog(debug, \"Created new externals with SDK paths\");\n } else if (Array.isArray(originalExternals)) {\n originalExternals.push(externalsMapping);\n debugLog(debug, \"Added SDK paths to existing externals array\");\n } else {\n webpackConfig.externals = [originalExternals, externalsMapping];\n debugLog(debug, \"Wrapped existing externals with SDK paths\");\n }\n }\n\n // Call user's webpack function if they provided one\n if (typeof config.webpack === \"function\") {\n return config.webpack(webpackConfig, webpackOptions);\n }\n\n return webpackConfig;\n },\n };\n\n if (needsInstrumentationHook) {\n debugLog(debug, \"Set experimental.instrumentationHook to true\");\n } else {\n debugLog(\n debug,\n \"Skipped setting experimental.instrumentationHook (not needed for Next.js 15.0.0-rc.1+)\",\n );\n }\n\n // Warn if user explicitly disabled instrumentationHook but we need it\n if (\n options.disableInstrumentationHook &&\n nextjsVersion &&\n shouldSetInstrumentationHook(nextjsVersion)\n ) {\n warn(\n suppressAllWarnings || false,\n \"You disabled instrumentationHook, but your Next.js version requires it. \" +\n \"Tusk Drift may not initialize properly. Please remove the disableInstrumentationHook option.\",\n );\n }\n\n return wrappedConfig;\n}\n"],"mappings":"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"}
|