@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.
@@ -1,7 +1,7 @@
1
1
  {
2
- "sdkVersion": "0.1.34",
2
+ "sdkVersion": "0.1.36",
3
3
  "language": "node",
4
- "generatedAt": "2026-03-06T00:00:54.434Z",
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
- "5.*",
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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"}
@@ -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
@@ -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":";;;;;;;;;;AAUA,SAAgB,mBAAuC;AACrD,KAAI;EAEF,MAAM,sBAAsBA,OAAK,KAAK,QAAQ,KAAK,EAAE,gBAAgB,QAAQ,eAAe;AAE5F,MAAIC,KAAG,WAAW,oBAAoB,CAEpC,QADoB,KAAK,MAAMA,KAAG,aAAa,qBAAqB,QAAQ,CAAC,CAC1D;UAEd,OAAO;;;;;;;;AAalB,SAAgB,aAAa,SAAgC;AAC3D,KAAI;EACF,MAAM,SAASC,MAAY,QAAQ;AAEnC,MAAI,CAAC,OACH,QAAO;GACL,OAAO;GACP,OAAO;GACP,OAAO;GACP,YAAY;GACb;AAGH,SAAO;GACL,OAAO,OAAO;GACd,OAAO,OAAO;GACd,OAAO,OAAO;GACd,YAAY,OAAO,WAAW,SAAS,IAAI,OAAO,WAAW,KAAK,IAAI,GAAG;GAC1E;SACK;AACN,SAAO;GACL,OAAO;GACP,OAAO;GACP,OAAO;GACP,YAAY;GACb;;;;;;;;;;;AAYL,SAAgB,6BAA6B,SAAsC;AACjF,KAAI,CAAC,QAGH,QAAO;CAGT,MAAM,EAAE,OAAO,OAAO,OAAO,eAAe,aAAa,QAAQ;AAGjE,KAAI,UAAU,UAAa,UAAU,UAAa,UAAU,OAC1D,QAAO;AAIT,KAAI,SAAS,GACX,QAAO;AAIT,KAAI,QAAQ,GACV,QAAO;AAIT,KAAI,UAAU,IAAI;AAEhB,MAAI,QAAQ,KAAK,QAAQ,EACvB,QAAO;AAIT,MAAI,UAAU,KAAK,UAAU,KAAK,eAAe,OAC/C,QAAO;AAIT,MAAI,YAAY,WAAW,MAAM,EAE/B;OADiB,SAAS,WAAW,MAAM,IAAI,CAAC,MAAM,KAAK,GAAG,IAC9C,EACd,QAAO;;AAKX,MAAI,YAAY,WAAW,UAAU,EAEnC;OADqB,SAAS,WAAW,MAAM,IAAI,CAAC,MAAM,KAAK,GAAG,IAC9C,IAClB,QAAO;;AAKX,SAAO;;AAIT,QAAO;;;;;;;;AAST,SAAgB,SAAS,OAAgB,SAAuB;AAC9D,KAAI,MAEF,SAAQ,IAAI,gBAAgB,UAAU;;;;;;;;AAU1C,SAAgB,KAAK,UAAmB,SAAuB;AAC7D,KAAI,CAAC,SAEH,SAAQ,KAAK,gBAAgB,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACnG3C,SAAgB,cACd,aAAyB,EAAE,EAC3B,UAAgC,EAAE,EACtB;CACZ,MAAM,SAAS;CAEf,MAAM,QAAQ,QAAQ,SAAS;CAC/B,MAAM,sBAAsB,QAAQ,oBAAoB;CAGxD,MAAM,gBAAgB,kBAAkB;AAExC,KAAI,cACF,UAAS,OAAO,6BAA6B,gBAAgB;KAE7D,MACE,uBAAuB,OACvB,gJAED;CAIH,MAAM,2BACJ,CAAC,QAAQ,8BAA8B,6BAA6B,cAAc;CAGpF,MAAM,OAAO,QAAQ,IAAI,iBAAiB,aAAa;CA0BvD,MAAM,gBAAgB;EACpB;EACA;EACA,GA5BuB,SAAS,YAAY,SAAS,WA6BjD;GACE;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACD,GACD,EAAE;EACP;CAED,MAAMC,gBAA4B;EAChC,GAAG;EACH,GAAI,2BACA,EACE,cAAc;GACZ,GAAG,OAAO;GACV,qBAAqB;GACtB,EACF,GACD,EACE,cAAc,OAAO,cACtB;EAIL,wBAAwB,CAAC,GAAI,OAAO,0BAA0B,EAAE,EAAG,GAAG,cAAc;EAEpF,UAAU,eAAoB,mBAAwB;AACpD,OAAI,eAAe,UAAU;IAE3B,MAAM,oBAAoB,cAAc;IAIxC,MAAMC,mBAA2C,EAAE;AACnD,SAAK,MAAM,OAAO,eAAe;AAC/B,sBAAiB,OAAO,YAAY;AACpC,cAAS,OAAO,mBAAmB,IAAI,eAAe,MAAM;;AAI9D,QAAI,CAAC,mBAAmB;AACtB,mBAAc,YAAY,CAAC,iBAAiB;AAC5C,cAAS,OAAO,uCAAuC;eAC9C,MAAM,QAAQ,kBAAkB,EAAE;AAC3C,uBAAkB,KAAK,iBAAiB;AACxC,cAAS,OAAO,8CAA8C;WACzD;AACL,mBAAc,YAAY,CAAC,mBAAmB,iBAAiB;AAC/D,cAAS,OAAO,4CAA4C;;;AAKhE,OAAI,OAAO,OAAO,YAAY,WAC5B,QAAO,OAAO,QAAQ,eAAe,eAAe;AAGtD,UAAO;;EAEV;AAED,KAAI,yBACF,UAAS,OAAO,+CAA+C;KAE/D,UACE,OACA,yFACD;AAIH,KACE,QAAQ,8BACR,iBACA,6BAA6B,cAAc,CAE3C,MACE,uBAAuB,OACvB,uKAED;AAGH,QAAO"}