@netlify/plugin-nextjs 5.15.1 → 5.15.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -31,13 +31,13 @@ import {
31
31
  writeFile
32
32
  } from "node:fs/promises";
33
33
  import { createRequire } from "node:module";
34
- import { dirname, join, resolve, sep } from "node:path";
35
- import { join as posixJoin, sep as posixSep } from "node:path/posix";
34
+ import { dirname, join, sep } from "node:path";
35
+ import { join as posixJoin, relative as posixRelative, sep as posixSep } from "node:path/posix";
36
36
  var import_fast_glob = __toESM(require_out(), 1);
37
37
  var import_semver = __toESM(require_semver(), 1);
38
38
  import { RUN_CONFIG_FILE } from "../../run/constants.js";
39
39
  var tracer = wrapTracer(trace.getTracer("Next runtime"));
40
- var toPosixPath = (path) => path.split(sep).join(posixSep);
40
+ var toPosixPath = (path) => path.replace(/^\\+\?\\+/, "").split(sep).join(posixSep);
41
41
  function isError(error) {
42
42
  return error instanceof Error;
43
43
  }
@@ -98,29 +98,39 @@ var copyNextServerCode = async (ctx) => {
98
98
  extglob: true
99
99
  }
100
100
  );
101
- await Promise.all(
102
- paths.map(async (path) => {
103
- const srcPath = join(srcDir, path);
104
- const destPath = join(destDir, path);
105
- if (path === "server/middleware-manifest.json") {
106
- try {
107
- await replaceMiddlewareManifest(srcPath, destPath);
108
- } catch (error) {
109
- throw new Error("Could not patch middleware manifest file", { cause: error });
110
- }
111
- return;
101
+ const promises = paths.map(async (path) => {
102
+ const srcPath = join(srcDir, path);
103
+ const destPath = join(destDir, path);
104
+ if (path === "server/middleware-manifest.json") {
105
+ try {
106
+ await replaceMiddlewareManifest(srcPath, destPath);
107
+ } catch (error) {
108
+ throw new Error("Could not patch middleware manifest file", { cause: error });
112
109
  }
113
- if (path === "server/functions-config-manifest.json") {
114
- try {
115
- await replaceFunctionsConfigManifest(srcPath, destPath);
116
- } catch (error) {
117
- throw new Error("Could not patch functions config manifest file", { cause: error });
118
- }
119
- return;
110
+ return;
111
+ }
112
+ if (path === "server/functions-config-manifest.json") {
113
+ try {
114
+ await replaceFunctionsConfigManifest(srcPath, destPath);
115
+ } catch (error) {
116
+ throw new Error("Could not patch functions config manifest file", { cause: error });
120
117
  }
121
- await cp(srcPath, destPath, { recursive: true, force: true });
122
- })
123
- );
118
+ return;
119
+ }
120
+ await cp(srcPath, destPath, { recursive: true, force: true });
121
+ });
122
+ if (existsSync(join(srcDir, "node_modules"))) {
123
+ const filter = ctx.constants.IS_LOCAL ? void 0 : nodeModulesFilter;
124
+ const src = join(srcDir, "node_modules");
125
+ const dest = join(destDir, "node_modules");
126
+ await cp(src, dest, {
127
+ recursive: true,
128
+ verbatimSymlinks: true,
129
+ force: true,
130
+ filter
131
+ });
132
+ }
133
+ await Promise.all(promises);
124
134
  });
125
135
  };
126
136
  async function recreateNodeModuleSymlinks(src, dest, org) {
@@ -188,32 +198,37 @@ async function patchNextModules(ctx, nextVersion, serverHandlerRequireResolve) {
188
198
  }
189
199
  var copyNextDependencies = async (ctx) => {
190
200
  await tracer.withActiveSpan("copyNextDependencies", async () => {
191
- const entries = await readdir(ctx.standaloneDir);
192
- const filter = ctx.constants.IS_LOCAL ? void 0 : nodeModulesFilter;
193
- const promises = entries.map(async (entry) => {
194
- if (entry === ctx.nextDistDir) {
195
- return;
196
- }
197
- const src = join(ctx.standaloneDir, entry);
198
- const dest = join(ctx.serverHandlerDir, entry);
199
- await cp(src, dest, {
200
- recursive: true,
201
- verbatimSymlinks: true,
202
- force: true,
203
- filter
204
- });
205
- if (entry === "node_modules") {
206
- await recreateNodeModuleSymlinks(ctx.resolveFromSiteDir("node_modules"), dest);
201
+ const promises = [];
202
+ const nodeModulesLocations = /* @__PURE__ */ new Set();
203
+ const commonFilter = ctx.constants.IS_LOCAL ? void 0 : nodeModulesFilter;
204
+ const dotNextDir = toPosixPath(join(ctx.standaloneDir, ctx.nextDistDir));
205
+ const standaloneRootDir = toPosixPath(ctx.standaloneRootDir);
206
+ const outputFileTracingRoot = toPosixPath(ctx.outputFileTracingRoot);
207
+ await cp(ctx.standaloneRootDir, ctx.serverHandlerRootDir, {
208
+ recursive: true,
209
+ verbatimSymlinks: true,
210
+ force: true,
211
+ filter: async (sourcePath, destination) => {
212
+ const posixSourcePath = toPosixPath(sourcePath);
213
+ if (posixSourcePath === dotNextDir) {
214
+ return false;
215
+ }
216
+ if (sourcePath.endsWith("node_modules")) {
217
+ nodeModulesLocations.add({
218
+ source: posixSourcePath,
219
+ destination: toPosixPath(destination)
220
+ });
221
+ }
222
+ return commonFilter?.(sourcePath) ?? true;
207
223
  }
208
224
  });
209
- const rootSrcDir = join(ctx.standaloneRootDir, "node_modules");
210
- const rootDestDir = join(ctx.serverHandlerRootDir, "node_modules");
211
- if (existsSync(rootSrcDir) && ctx.standaloneRootDir !== ctx.standaloneDir) {
212
- promises.push(
213
- cp(rootSrcDir, rootDestDir, { recursive: true, verbatimSymlinks: true, filter }).then(
214
- () => recreateNodeModuleSymlinks(resolve("node_modules"), rootDestDir)
215
- )
216
- );
225
+ for (const {
226
+ source: nodeModulesLocationInStandalone,
227
+ destination: locationInServerHandler
228
+ } of nodeModulesLocations) {
229
+ const relativeToRoot = posixRelative(standaloneRootDir, nodeModulesLocationInStandalone);
230
+ const locationInProject = posixJoin(outputFileTracingRoot, relativeToRoot);
231
+ promises.push(recreateNodeModuleSymlinks(locationInProject, locationInServerHandler));
217
232
  }
218
233
  await Promise.all(promises);
219
234
  const serverHandlerRequire = createRequire(posixJoin(ctx.serverHandlerDir, ":internal:"));
@@ -301,7 +316,7 @@ var verifyHandlerDirStructure = async (ctx) => {
301
316
  );
302
317
  }
303
318
  };
304
- var nodeModulesFilter = async (sourcePath) => {
319
+ var nodeModulesFilter = (sourcePath) => {
305
320
  if (sourcePath.includes(".pnpm") && (sourcePath.includes("linuxmusl-x64") || sourcePath.includes("linux-x64-musl"))) {
306
321
  return false;
307
322
  }
@@ -16,7 +16,7 @@ var import_semver = __toESM(require_semver(), 1);
16
16
  import { existsSync, readFileSync } from "node:fs";
17
17
  import { readFile } from "node:fs/promises";
18
18
  import { createRequire } from "node:module";
19
- import { join, relative, resolve } from "node:path";
19
+ import { join, relative, resolve, sep } from "node:path";
20
20
  import { join as posixJoin, relative as posixRelative } from "node:path/posix";
21
21
  import { fileURLToPath } from "node:url";
22
22
  var MODULE_DIR = fileURLToPath(new URL(".", import.meta.url));
@@ -54,6 +54,25 @@ var PluginContext = class {
54
54
  get relativeAppDir() {
55
55
  return this.requiredServerFiles.relativeAppDir ?? "";
56
56
  }
57
+ /**
58
+ * The root directory for output file tracing. Paths inside standalone directory preserve paths of project, relative to this directory.
59
+ */
60
+ get outputFileTracingRoot() {
61
+ const outputFileTracingRootFromRequiredServerFiles = this.requiredServerFiles.config.outputFileTracingRoot ?? // fallback for older Next.js versions that don't have outputFileTracingRoot in the config, but had it in config.experimental
62
+ this.requiredServerFiles.config.experimental.outputFileTracingRoot;
63
+ if (outputFileTracingRootFromRequiredServerFiles) {
64
+ return outputFileTracingRootFromRequiredServerFiles;
65
+ }
66
+ if (!this.relativeAppDir.includes("..")) {
67
+ const depth = this.relativeAppDir === "" ? 0 : this.relativeAppDir.split(sep).length;
68
+ const computedOutputFileTracingRoot = resolve(
69
+ this.requiredServerFiles.appDir,
70
+ ...Array.from({ length: depth }).fill("..")
71
+ );
72
+ return computedOutputFileTracingRoot;
73
+ }
74
+ return process.cwd();
75
+ }
57
76
  /**
58
77
  * The working directory inside the lambda that is used for monorepos to execute the serverless function
59
78
  */
@@ -86,7 +86,7 @@ var pipeline = (0, import_util.promisify)(import_stream.pipeline);
86
86
 
87
87
  // package.json
88
88
  var name = "@netlify/plugin-nextjs";
89
- var version = "5.15.1";
89
+ var version = "5.15.2";
90
90
 
91
91
  // src/run/handlers/tags-handler.cts
92
92
  var import_storage = require("../storage/storage.cjs");
@@ -30,7 +30,23 @@ var getString = (input) => typeof input === "string" ? input : JSON.stringify(in
30
30
  var base64Decode = globalThis.Buffer ? (input) => Buffer.from(input, "base64").toString() : (input) => atob(input);
31
31
  var base64Encode = globalThis.Buffer ? (input) => Buffer.from(getString(input)).toString("base64") : (input) => btoa(getString(input));
32
32
 
33
- // node_modules/@netlify/blobs/dist/chunk-HN33TXZT.js
33
+ // node_modules/@netlify/otel/dist/main.js
34
+ var GET_TRACER = "__netlify__getTracer";
35
+ var getTracer = (name, version) => {
36
+ return globalThis[GET_TRACER]?.(name, version);
37
+ };
38
+ function withActiveSpan(tracer, name, optionsOrFn, contextOrFn, fn) {
39
+ const func = typeof contextOrFn === "function" ? contextOrFn : typeof optionsOrFn === "function" ? optionsOrFn : fn;
40
+ if (!func) {
41
+ throw new Error("function to execute with active span is missing");
42
+ }
43
+ if (!tracer) {
44
+ return func();
45
+ }
46
+ return tracer.withActiveSpan(name, optionsOrFn, contextOrFn, func);
47
+ }
48
+
49
+ // node_modules/@netlify/blobs/dist/chunk-3OMJJ4EG.js
34
50
  var getEnvironment = () => {
35
51
  const { Deno, Netlify, process: process2 } = globalThis;
36
52
  return Netlify?.env ?? Deno?.env ?? {
@@ -123,6 +139,12 @@ var collectIterator = async (iterator) => {
123
139
  }
124
140
  return result;
125
141
  };
142
+ function withSpan(span, name, fn) {
143
+ if (span) return fn(span);
144
+ return withActiveSpan(getTracer(), name, (span2) => {
145
+ return fn(span2);
146
+ });
147
+ }
126
148
  var BlobsConsistencyError = class extends Error {
127
149
  constructor() {
128
150
  super(
@@ -337,22 +359,6 @@ var getClientOptions = (options, contextOverride) => {
337
359
  return clientOptions;
338
360
  };
339
361
 
340
- // node_modules/@netlify/otel/dist/main.js
341
- var GET_TRACER = "__netlify__getTracer";
342
- var getTracer = (name, version) => {
343
- return globalThis[GET_TRACER]?.(name, version);
344
- };
345
- function withActiveSpan(tracer, name, optionsOrFn, contextOrFn, fn) {
346
- const func = typeof contextOrFn === "function" ? contextOrFn : typeof optionsOrFn === "function" ? optionsOrFn : fn;
347
- if (!func) {
348
- throw new Error("function to execute with active span is missing");
349
- }
350
- if (!tracer) {
351
- return func();
352
- }
353
- return tracer.withActiveSpan(name, optionsOrFn, contextOrFn, func);
354
- }
355
-
356
362
  // node_modules/@netlify/blobs/dist/main.js
357
363
  var DEPLOY_STORE_PREFIX = "deploy:";
358
364
  var LEGACY_STORE_INTERNAL_PREFIX = "netlify-internal/legacy-namespace/";
@@ -404,7 +410,7 @@ var Store = class _Store {
404
410
  };
405
411
  }
406
412
  async get(key, options) {
407
- return withActiveSpan(getTracer(), "blobs.get", async (span) => {
413
+ return withSpan(options?.span, "blobs.get", async (span) => {
408
414
  const { consistency, type } = options ?? {};
409
415
  span?.setAttributes({
410
416
  "blobs.store": this.name,
@@ -447,15 +453,20 @@ var Store = class _Store {
447
453
  throw new BlobsInternalError(res);
448
454
  });
449
455
  }
450
- async getMetadata(key, { consistency } = {}) {
451
- return withActiveSpan(getTracer(), "blobs.getMetadata", async (span) => {
456
+ async getMetadata(key, options = {}) {
457
+ return withSpan(options?.span, "blobs.getMetadata", async (span) => {
452
458
  span?.setAttributes({
453
459
  "blobs.store": this.name,
454
460
  "blobs.key": key,
455
461
  "blobs.method": "HEAD",
456
- "blobs.consistency": consistency
462
+ "blobs.consistency": options.consistency
463
+ });
464
+ const res = await this.client.makeRequest({
465
+ consistency: options.consistency,
466
+ key,
467
+ method: "head",
468
+ storeName: this.name
457
469
  });
458
- const res = await this.client.makeRequest({ consistency, key, method: "head", storeName: this.name });
459
470
  span?.setAttributes({
460
471
  "blobs.response.status": res.status
461
472
  });
@@ -475,7 +486,7 @@ var Store = class _Store {
475
486
  });
476
487
  }
477
488
  async getWithMetadata(key, options) {
478
- return withActiveSpan(getTracer(), "blobs.getWithMetadata", async (span) => {
489
+ return withSpan(options?.span, "blobs.getWithMetadata", async (span) => {
479
490
  const { consistency, etag: requestETag, type } = options ?? {};
480
491
  const headers = requestETag ? { "if-none-match": requestETag } : void 0;
481
492
  span?.setAttributes({
@@ -532,7 +543,7 @@ var Store = class _Store {
532
543
  });
533
544
  }
534
545
  list(options = {}) {
535
- return withActiveSpan(getTracer(), "blobs.list", (span) => {
546
+ return withSpan(options.span, "blobs.list", (span) => {
536
547
  span?.setAttributes({
537
548
  "blobs.store": this.name,
538
549
  "blobs.method": "GET",
@@ -554,7 +565,7 @@ var Store = class _Store {
554
565
  });
555
566
  }
556
567
  async set(key, data, options = {}) {
557
- return withActiveSpan(getTracer(), "blobs.set", async (span) => {
568
+ return withSpan(options.span, "blobs.set", async (span) => {
558
569
  span?.setAttributes({
559
570
  "blobs.store": this.name,
560
571
  "blobs.key": key,
@@ -591,7 +602,7 @@ var Store = class _Store {
591
602
  });
592
603
  }
593
604
  async setJSON(key, data, options = {}) {
594
- return withActiveSpan(getTracer(), "blobs.setJSON", async (span) => {
605
+ return withSpan(options.span, "blobs.setJSON", async (span) => {
595
606
  span?.setAttributes({
596
607
  "blobs.store": this.name,
597
608
  "blobs.key": key,
@@ -707,7 +718,7 @@ var Store = class _Store {
707
718
  let done = false;
708
719
  return {
709
720
  async next() {
710
- return withActiveSpan(getTracer(), "blobs.list.next", async (span) => {
721
+ return withSpan(options?.span, "blobs.list.next", async (span) => {
711
722
  span?.setAttributes({
712
723
  "blobs.store": storeName,
713
724
  "blobs.method": "GET",
@@ -57,10 +57,11 @@ var getMemoizedKeyValueStoreBackedByRegionalBlobStore = (...args) => {
57
57
  const blobKey = await encodeBlobKey(key);
58
58
  const getPromise = (0, import_tracer.withActiveSpan)(tracer, otelSpanTitle, async (span) => {
59
59
  const { etag: previousEtag, globalValue: previousBlob } = memoizedValue?.conditional ? memoizedValue : {};
60
- span?.setAttributes({ key, blobKey, previousEtag });
60
+ span?.setAttributes({ key });
61
61
  const result = await store.getWithMetadata(blobKey, {
62
62
  type: "json",
63
- etag: previousEtag
63
+ etag: previousEtag,
64
+ span
64
65
  });
65
66
  const shouldReuseMemoizedBlob = result?.etag && previousEtag === result?.etag;
66
67
  const blob = shouldReuseMemoizedBlob ? previousBlob : result?.data;
@@ -72,11 +73,6 @@ var getMemoizedKeyValueStoreBackedByRegionalBlobStore = (...args) => {
72
73
  } else {
73
74
  inMemoryCache.set(key, blob);
74
75
  }
75
- span?.setAttributes({
76
- etag: result?.etag,
77
- reusingPreviouslyFetchedBlob: shouldReuseMemoizedBlob,
78
- status: blob ? shouldReuseMemoizedBlob ? "Hit, no change" : "Hit" : "Miss"
79
- });
80
76
  return blob;
81
77
  });
82
78
  inMemoryCache.set(key, getPromise);
@@ -87,8 +83,8 @@ var getMemoizedKeyValueStoreBackedByRegionalBlobStore = (...args) => {
87
83
  inMemoryCache.set(key, value);
88
84
  const blobKey = await encodeBlobKey(key);
89
85
  return (0, import_tracer.withActiveSpan)(tracer, otelSpanTitle, async (span) => {
90
- span?.setAttributes({ key, blobKey });
91
- const writeResult = await store.setJSON(blobKey, value);
86
+ span?.setAttributes({ key });
87
+ const writeResult = await store.setJSON(blobKey, value, { span });
92
88
  if (writeResult?.etag) {
93
89
  inMemoryCache.set(key, {
94
90
  data: value,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netlify/plugin-nextjs",
3
- "version": "5.15.1",
3
+ "version": "5.15.2",
4
4
  "description": "Run Next.js seamlessly on Netlify",
5
5
  "main": "./dist/index.js",
6
6
  "type": "module",