@netlify/plugin-nextjs 5.0.0-beta.2 → 5.0.0-beta.3
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 +5 -2
- package/dist/build/cache.js +1 -1
- package/dist/build/functions/edge.js +2 -1
- package/dist/esm-chunks/{chunk-3PTPU5GO.js → chunk-FFCTA32Q.js} +30 -3
- package/dist/esm-chunks/chunk-GHDGGK6V.js +105 -0
- package/dist/esm-chunks/{chunk-R4NHZWGU.js → chunk-OIL5MDCV.js} +1 -1
- package/dist/esm-chunks/{chunk-GGHAQM5D.js → chunk-XQ65S4R2.js} +5 -1
- package/dist/index.js +2 -2
- package/dist/run/config.js +1 -1
- package/dist/run/handlers/server.js +4 -4
- package/dist/run/systemlog.js +6 -5
- package/edge-runtime/lib/headers.ts +5 -0
- package/edge-runtime/lib/logging.ts +5 -0
- package/edge-runtime/lib/next-request.ts +43 -1
- package/edge-runtime/lib/response.ts +81 -19
- package/edge-runtime/lib/util.test.ts +39 -0
- package/edge-runtime/lib/util.ts +79 -7
- package/edge-runtime/middleware.ts +19 -2
- package/edge-runtime/next.config.json +1 -0
- package/edge-runtime/vendor/import_map.json +2 -1
- package/edge-runtime/vendor/v1-7-0--edge-utils.netlify.app/logger/logger.ts +164 -0
- package/edge-runtime/vendor/v1-7-0--edge-utils.netlify.app/logger/mod.ts +1 -0
- package/edge-runtime/vendor.ts +2 -0
- package/package.json +1 -1
- package/dist/esm-chunks/chunk-YZXA5QBC.js +0 -60
package/README.md
CHANGED
|
@@ -17,8 +17,11 @@ How to add new integration test scenarios to the application:
|
|
|
17
17
|
4. Add your test
|
|
18
18
|
|
|
19
19
|
> Currently the tests require a built version of the `dist/run/handlers/cache.cjs` so you need to
|
|
20
|
-
> run `npm run build` before executing the integration tests.
|
|
21
|
-
|
|
20
|
+
> run `npm run build` before executing the integration tests.
|
|
21
|
+
|
|
22
|
+
In addition, the integration tests need to be prepared before first use. You can do this by running
|
|
23
|
+
`npm run pretest`. To speed up this process and build only the fixtures whose name starts with a
|
|
24
|
+
given prefix, run `npm run pretest -- <prefix>`.
|
|
22
25
|
|
|
23
26
|
### E2E testing
|
|
24
27
|
|
package/dist/build/cache.js
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
8
|
createEdgeHandlers
|
|
9
|
-
} from "../../esm-chunks/chunk-
|
|
9
|
+
} from "../../esm-chunks/chunk-FFCTA32Q.js";
|
|
10
|
+
import "../../esm-chunks/chunk-AVWFCGVE.js";
|
|
10
11
|
import "../../esm-chunks/chunk-TJKO3X6O.js";
|
|
11
12
|
import "../../esm-chunks/chunk-RSKIKBZH.js";
|
|
12
13
|
export {
|
|
@@ -4,25 +4,52 @@
|
|
|
4
4
|
return createRequire(import.meta.url);
|
|
5
5
|
})();
|
|
6
6
|
|
|
7
|
+
import {
|
|
8
|
+
require_out
|
|
9
|
+
} from "./chunk-AVWFCGVE.js";
|
|
7
10
|
import {
|
|
8
11
|
EDGE_HANDLER_NAME
|
|
9
12
|
} from "./chunk-TJKO3X6O.js";
|
|
13
|
+
import {
|
|
14
|
+
__toESM
|
|
15
|
+
} from "./chunk-RSKIKBZH.js";
|
|
10
16
|
|
|
11
17
|
// src/build/functions/edge.ts
|
|
18
|
+
var import_fast_glob = __toESM(require_out(), 1);
|
|
12
19
|
import { cp, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
13
20
|
import { dirname, join } from "node:path";
|
|
14
21
|
var writeEdgeManifest = async (ctx, manifest) => {
|
|
15
22
|
await mkdir(ctx.edgeFunctionsDir, { recursive: true });
|
|
16
23
|
await writeFile(join(ctx.edgeFunctionsDir, "manifest.json"), JSON.stringify(manifest, null, 2));
|
|
17
24
|
};
|
|
25
|
+
var copyRuntime = async (ctx, handlerDirectory) => {
|
|
26
|
+
const files = await (0, import_fast_glob.glob)("edge-runtime/**/*", {
|
|
27
|
+
cwd: ctx.pluginDir,
|
|
28
|
+
ignore: ["**/*.test.ts"],
|
|
29
|
+
dot: true
|
|
30
|
+
});
|
|
31
|
+
await Promise.all(
|
|
32
|
+
files.map(
|
|
33
|
+
(path) => cp(join(ctx.pluginDir, path), join(handlerDirectory, path), { recursive: true })
|
|
34
|
+
)
|
|
35
|
+
);
|
|
36
|
+
};
|
|
18
37
|
var writeHandlerFile = async (ctx, { matchers, name }) => {
|
|
38
|
+
const nextConfig = await ctx.getBuildConfig();
|
|
19
39
|
const handlerName = getHandlerName({ name });
|
|
20
40
|
const handlerDirectory = join(ctx.edgeFunctionsDir, handlerName);
|
|
21
41
|
const handlerRuntimeDirectory = join(handlerDirectory, "edge-runtime");
|
|
22
|
-
await
|
|
23
|
-
recursive: true
|
|
24
|
-
});
|
|
42
|
+
await copyRuntime(ctx, handlerDirectory);
|
|
25
43
|
await writeFile(join(handlerRuntimeDirectory, "matchers.json"), JSON.stringify(matchers));
|
|
44
|
+
const minimalNextConfig = {
|
|
45
|
+
basePath: nextConfig.basePath,
|
|
46
|
+
i18n: nextConfig.i18n,
|
|
47
|
+
trailingSlash: nextConfig.trailingSlash
|
|
48
|
+
};
|
|
49
|
+
await writeFile(
|
|
50
|
+
join(handlerRuntimeDirectory, "next.config.json"),
|
|
51
|
+
JSON.stringify(minimalNextConfig)
|
|
52
|
+
);
|
|
26
53
|
await writeFile(
|
|
27
54
|
join(handlerDirectory, `${handlerName}.js`),
|
|
28
55
|
`
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
|
|
2
|
+
const require = await (async () => {
|
|
3
|
+
const { createRequire } = await import("node:module");
|
|
4
|
+
return createRequire(import.meta.url);
|
|
5
|
+
})();
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
__commonJS,
|
|
9
|
+
__require,
|
|
10
|
+
__toESM
|
|
11
|
+
} from "./chunk-RSKIKBZH.js";
|
|
12
|
+
|
|
13
|
+
// node_modules/@netlify/functions/dist/lib/system_logger.js
|
|
14
|
+
var require_system_logger = __commonJS({
|
|
15
|
+
"node_modules/@netlify/functions/dist/lib/system_logger.js"(exports) {
|
|
16
|
+
"use strict";
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.systemLogger = exports.LogLevel = void 0;
|
|
19
|
+
var process_1 = __require("process");
|
|
20
|
+
var systemLogTag = "__nfSystemLog";
|
|
21
|
+
var serializeError = (error) => {
|
|
22
|
+
const cause = error?.cause instanceof Error ? serializeError(error.cause) : error.cause;
|
|
23
|
+
return {
|
|
24
|
+
error: error.message,
|
|
25
|
+
error_cause: cause,
|
|
26
|
+
error_stack: error.stack
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
var LogLevel2;
|
|
30
|
+
(function(LogLevel3) {
|
|
31
|
+
LogLevel3[LogLevel3["Debug"] = 1] = "Debug";
|
|
32
|
+
LogLevel3[LogLevel3["Log"] = 2] = "Log";
|
|
33
|
+
LogLevel3[LogLevel3["Error"] = 3] = "Error";
|
|
34
|
+
})(LogLevel2 = exports.LogLevel || (exports.LogLevel = {}));
|
|
35
|
+
var SystemLogger = class _SystemLogger {
|
|
36
|
+
fields;
|
|
37
|
+
logLevel;
|
|
38
|
+
constructor(fields = {}, logLevel = LogLevel2.Log) {
|
|
39
|
+
this.fields = fields;
|
|
40
|
+
this.logLevel = logLevel;
|
|
41
|
+
}
|
|
42
|
+
doLog(logger, message) {
|
|
43
|
+
if (process_1.env.NETLIFY_DEV && !process_1.env.NETLIFY_ENABLE_SYSTEM_LOGGING) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
logger(systemLogTag, JSON.stringify({ msg: message, fields: this.fields }));
|
|
47
|
+
}
|
|
48
|
+
log(message) {
|
|
49
|
+
if (this.logLevel > LogLevel2.Log) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
this.doLog(console.log, message);
|
|
53
|
+
}
|
|
54
|
+
debug(message) {
|
|
55
|
+
if (this.logLevel > LogLevel2.Debug) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
this.doLog(console.debug, message);
|
|
59
|
+
}
|
|
60
|
+
error(message) {
|
|
61
|
+
if (this.logLevel > LogLevel2.Error) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
this.doLog(console.error, message);
|
|
65
|
+
}
|
|
66
|
+
withLogLevel(level) {
|
|
67
|
+
return new _SystemLogger(this.fields, level);
|
|
68
|
+
}
|
|
69
|
+
withFields(fields) {
|
|
70
|
+
return new _SystemLogger({
|
|
71
|
+
...this.fields,
|
|
72
|
+
...fields
|
|
73
|
+
}, this.logLevel);
|
|
74
|
+
}
|
|
75
|
+
withError(error) {
|
|
76
|
+
const fields = error instanceof Error ? serializeError(error) : { error };
|
|
77
|
+
return this.withFields(fields);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
exports.systemLogger = new SystemLogger();
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// node_modules/@netlify/functions/dist/internal.js
|
|
85
|
+
var require_internal = __commonJS({
|
|
86
|
+
"node_modules/@netlify/functions/dist/internal.js"(exports) {
|
|
87
|
+
"use strict";
|
|
88
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
89
|
+
exports.LogLevel = exports.systemLogger = void 0;
|
|
90
|
+
var system_logger_js_1 = require_system_logger();
|
|
91
|
+
Object.defineProperty(exports, "systemLogger", { enumerable: true, get: function() {
|
|
92
|
+
return system_logger_js_1.systemLogger;
|
|
93
|
+
} });
|
|
94
|
+
Object.defineProperty(exports, "LogLevel", { enumerable: true, get: function() {
|
|
95
|
+
return system_logger_js_1.LogLevel;
|
|
96
|
+
} });
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// src/run/systemlog.ts
|
|
101
|
+
var import_internal = __toESM(require_internal(), 1);
|
|
102
|
+
|
|
103
|
+
export {
|
|
104
|
+
import_internal
|
|
105
|
+
};
|
|
@@ -22,7 +22,7 @@ var setRunConfig = (config) => {
|
|
|
22
22
|
process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(config);
|
|
23
23
|
};
|
|
24
24
|
var getTagsManifest = async () => {
|
|
25
|
-
return JSON.parse(await readFile(resolve(".netlify/tags-manifest.json"), "utf-8"));
|
|
25
|
+
return JSON.parse(await readFile(resolve(PLUGIN_DIR, ".netlify/tags-manifest.json"), "utf-8"));
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
export {
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
// src/build/cache.ts
|
|
9
|
+
import { existsSync } from "node:fs";
|
|
9
10
|
import { join } from "node:path";
|
|
10
11
|
var saveBuildCache = async (ctx) => {
|
|
11
12
|
if (await ctx.utils.cache.save(join(ctx.publishDir, "cache"))) {
|
|
@@ -15,7 +16,10 @@ var saveBuildCache = async (ctx) => {
|
|
|
15
16
|
}
|
|
16
17
|
};
|
|
17
18
|
var restoreBuildCache = async (ctx) => {
|
|
18
|
-
|
|
19
|
+
const { cache } = ctx.utils;
|
|
20
|
+
if (existsSync(join(ctx.publishDir, "cache"))) {
|
|
21
|
+
console.log("Next.js cache found.");
|
|
22
|
+
} else if (await cache.restore(join(ctx.publishDir, "cache"))) {
|
|
19
23
|
console.log("Next.js cache restored.");
|
|
20
24
|
} else {
|
|
21
25
|
console.log("No Next.js cache to restore.");
|
package/dist/index.js
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
} from "./esm-chunks/chunk-Z7ZMLVTM.js";
|
|
17
17
|
import {
|
|
18
18
|
createEdgeHandlers
|
|
19
|
-
} from "./esm-chunks/chunk-
|
|
19
|
+
} from "./esm-chunks/chunk-FFCTA32Q.js";
|
|
20
20
|
import {
|
|
21
21
|
createServerHandler
|
|
22
22
|
} from "./esm-chunks/chunk-ALO2SSMH.js";
|
|
@@ -25,7 +25,7 @@ import "./esm-chunks/chunk-AVWFCGVE.js";
|
|
|
25
25
|
import {
|
|
26
26
|
restoreBuildCache,
|
|
27
27
|
saveBuildCache
|
|
28
|
-
} from "./esm-chunks/chunk-
|
|
28
|
+
} from "./esm-chunks/chunk-XQ65S4R2.js";
|
|
29
29
|
import {
|
|
30
30
|
setImageConfig
|
|
31
31
|
} from "./esm-chunks/chunk-H46DW7YI.js";
|
package/dist/run/config.js
CHANGED
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
})();
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
|
-
|
|
9
|
-
} from "../../esm-chunks/chunk-
|
|
8
|
+
import_internal
|
|
9
|
+
} from "../../esm-chunks/chunk-GHDGGK6V.js";
|
|
10
10
|
import {
|
|
11
11
|
getTagsManifest
|
|
12
|
-
} from "../../esm-chunks/chunk-
|
|
12
|
+
} from "../../esm-chunks/chunk-OIL5MDCV.js";
|
|
13
13
|
import "../../esm-chunks/chunk-4AJYXTWN.js";
|
|
14
14
|
import {
|
|
15
15
|
adjustDateHeader,
|
|
@@ -3278,7 +3278,7 @@ var server_default = async (request) => {
|
|
|
3278
3278
|
try {
|
|
3279
3279
|
await nextHandler(req, resProxy);
|
|
3280
3280
|
} catch (error) {
|
|
3281
|
-
|
|
3281
|
+
import_internal.systemLogger.withError(error).error("next handler error");
|
|
3282
3282
|
console.error(error);
|
|
3283
3283
|
resProxy.statusCode = 500;
|
|
3284
3284
|
resProxy.end("Internal Server Error");
|
package/dist/run/systemlog.js
CHANGED
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
})();
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
} from "../esm-chunks/chunk-YZXA5QBC.js";
|
|
8
|
+
import_internal
|
|
9
|
+
} from "../esm-chunks/chunk-GHDGGK6V.js";
|
|
11
10
|
import "../esm-chunks/chunk-RSKIKBZH.js";
|
|
11
|
+
var export_LogLevel = import_internal.LogLevel;
|
|
12
|
+
var export_logger = import_internal.systemLogger;
|
|
12
13
|
export {
|
|
13
|
-
|
|
14
|
-
logger
|
|
14
|
+
export_LogLevel as LogLevel,
|
|
15
|
+
export_logger as logger
|
|
15
16
|
};
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
export const InternalHeaders = {
|
|
2
|
+
NFDebugLogging: 'x-nf-debug-logging',
|
|
3
|
+
NFRequestID: 'x-nf-request-id',
|
|
4
|
+
}
|
|
5
|
+
|
|
1
6
|
// Next 13 supports request header mutations and has the side effect of prepending header values with 'x-middleware-request'
|
|
2
7
|
// as part of invoking NextResponse.next() in the middleware. We need to remove that before sending the response the user
|
|
3
8
|
// as the code that removes it in Next isn't run based on how we handle the middleware
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { Context } from '@netlify/edge-functions'
|
|
2
2
|
|
|
3
|
+
import { normalizeDataUrl, removeBasePath, normalizeLocalePath } from './util.ts'
|
|
4
|
+
|
|
3
5
|
interface I18NConfig {
|
|
4
6
|
defaultLocale: string
|
|
5
7
|
localeDetection?: false
|
|
@@ -29,6 +31,43 @@ export interface RequestData {
|
|
|
29
31
|
}
|
|
30
32
|
url: string
|
|
31
33
|
body?: ReadableStream<Uint8Array>
|
|
34
|
+
detectedLocale?: string
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const normalizeRequestURL = (
|
|
38
|
+
originalURL: string,
|
|
39
|
+
nextConfig?: RequestData['nextConfig'],
|
|
40
|
+
): { url: string; detectedLocale?: string } => {
|
|
41
|
+
const url = new URL(originalURL)
|
|
42
|
+
|
|
43
|
+
url.pathname = removeBasePath(url.pathname, nextConfig?.basePath)
|
|
44
|
+
|
|
45
|
+
let detectedLocale: string | undefined
|
|
46
|
+
|
|
47
|
+
if (nextConfig?.i18n) {
|
|
48
|
+
const { pathname, detectedLocale: detected } = normalizeLocalePath(
|
|
49
|
+
url.pathname,
|
|
50
|
+
nextConfig?.i18n?.locales,
|
|
51
|
+
)
|
|
52
|
+
url.pathname = pathname
|
|
53
|
+
detectedLocale = detected
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// We want to run middleware for data requests and expose the URL of the
|
|
57
|
+
// corresponding pages, so we have to normalize the URLs before running
|
|
58
|
+
// the handler.
|
|
59
|
+
url.pathname = normalizeDataUrl(url.pathname)
|
|
60
|
+
|
|
61
|
+
// Normalizing the trailing slash based on the `trailingSlash` configuration
|
|
62
|
+
// property from the Next.js config.
|
|
63
|
+
if (nextConfig?.trailingSlash && url.pathname !== '/' && !url.pathname.endsWith('/')) {
|
|
64
|
+
url.pathname = `${url.pathname}/`
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
url: url.toString(),
|
|
69
|
+
detectedLocale,
|
|
70
|
+
}
|
|
32
71
|
}
|
|
33
72
|
|
|
34
73
|
export const buildNextRequest = (
|
|
@@ -47,13 +86,16 @@ export const buildNextRequest = (
|
|
|
47
86
|
timezone,
|
|
48
87
|
}
|
|
49
88
|
|
|
89
|
+
const { detectedLocale, url: normalizedUrl } = normalizeRequestURL(url, nextConfig)
|
|
90
|
+
|
|
50
91
|
return {
|
|
51
92
|
headers: Object.fromEntries(headers.entries()),
|
|
52
93
|
geo,
|
|
53
|
-
url,
|
|
94
|
+
url: normalizedUrl,
|
|
54
95
|
method,
|
|
55
96
|
ip: context.ip,
|
|
56
97
|
body: body ?? undefined,
|
|
57
98
|
nextConfig,
|
|
99
|
+
detectedLocale,
|
|
58
100
|
}
|
|
59
101
|
}
|
|
@@ -2,23 +2,37 @@ import type { Context } from '@netlify/edge-functions'
|
|
|
2
2
|
import { HTMLRewriter } from '../vendor/deno.land/x/html_rewriter@v0.1.0-pre.17/index.ts'
|
|
3
3
|
|
|
4
4
|
import { updateModifiedHeaders } from './headers.ts'
|
|
5
|
-
import {
|
|
5
|
+
import type { StructuredLogger } from './logging.ts'
|
|
6
|
+
import { normalizeDataUrl, normalizeLocalePath, relativizeURL, rewriteDataPath } from './util.ts'
|
|
6
7
|
import { addMiddlewareHeaders, isMiddlewareRequest, isMiddlewareResponse } from './middleware.ts'
|
|
8
|
+
import { RequestData } from './next-request.ts'
|
|
7
9
|
|
|
8
10
|
export interface FetchEventResult {
|
|
9
11
|
response: Response
|
|
10
12
|
waitUntil: Promise<any>
|
|
11
13
|
}
|
|
12
14
|
|
|
15
|
+
interface BuildResponseOptions {
|
|
16
|
+
context: Context
|
|
17
|
+
logger: StructuredLogger
|
|
18
|
+
request: Request
|
|
19
|
+
result: FetchEventResult
|
|
20
|
+
nextConfig?: RequestData['nextConfig']
|
|
21
|
+
requestLocale?: string
|
|
22
|
+
}
|
|
23
|
+
|
|
13
24
|
export const buildResponse = async ({
|
|
14
|
-
result,
|
|
15
|
-
request,
|
|
16
25
|
context,
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
26
|
+
logger,
|
|
27
|
+
request,
|
|
28
|
+
result,
|
|
29
|
+
nextConfig,
|
|
30
|
+
requestLocale,
|
|
31
|
+
}: BuildResponseOptions): Promise<Response | void> => {
|
|
32
|
+
logger
|
|
33
|
+
.withFields({ is_nextresponse_next: result.response.headers.has('x-middleware-next') })
|
|
34
|
+
.debug('Building Next.js response')
|
|
35
|
+
|
|
22
36
|
updateModifiedHeaders(request.headers, result.response.headers)
|
|
23
37
|
|
|
24
38
|
// They've returned the MiddlewareRequest directly, so we'll call `next()` for them.
|
|
@@ -99,32 +113,79 @@ export const buildResponse = async ({
|
|
|
99
113
|
const rewrite = res.headers.get('x-middleware-rewrite')
|
|
100
114
|
|
|
101
115
|
// Data requests (i.e. requests for /_next/data ) need special handling
|
|
102
|
-
const isDataReq = request.headers.
|
|
116
|
+
const isDataReq = request.headers.has('x-nextjs-data')
|
|
103
117
|
|
|
104
118
|
if (rewrite) {
|
|
119
|
+
logger.withFields({ rewrite_url: rewrite }).debug('Found middleware rewrite')
|
|
120
|
+
|
|
105
121
|
const rewriteUrl = new URL(rewrite, request.url)
|
|
106
122
|
const baseUrl = new URL(request.url)
|
|
123
|
+
if (rewriteUrl.toString() === baseUrl.toString()) {
|
|
124
|
+
logger.withFields({ rewrite_url: rewrite }).debug('Rewrite url is same as original url')
|
|
125
|
+
return
|
|
126
|
+
}
|
|
127
|
+
|
|
107
128
|
const relativeUrl = relativizeURL(rewrite, request.url)
|
|
129
|
+
const originalPath = new URL(request.url, `http://n`).pathname
|
|
108
130
|
|
|
109
|
-
// Data requests might be rewritten to an external URL
|
|
110
|
-
// This header tells the client router the redirect target, and if it's external then it will do a full navigation
|
|
111
131
|
if (isDataReq) {
|
|
132
|
+
// Data requests might be rewritten to an external URL
|
|
133
|
+
// This header tells the client router the redirect target, and if it's external then it will do a full navigation
|
|
134
|
+
|
|
112
135
|
res.headers.set('x-nextjs-rewrite', relativeUrl)
|
|
113
136
|
}
|
|
137
|
+
|
|
114
138
|
if (rewriteUrl.origin !== baseUrl.origin) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
139
|
+
logger.withFields({ rewrite_url: rewrite }).debug('Rewriting to external url')
|
|
140
|
+
let proxyRequest: Request
|
|
141
|
+
|
|
142
|
+
// Remove Netlify internal headers
|
|
143
|
+
const headers = new Headers(
|
|
144
|
+
[...request.headers.entries()].filter(([key]) => !key.startsWith('x-nf-')),
|
|
145
|
+
)
|
|
146
|
+
if (request.body && !request.bodyUsed) {
|
|
147
|
+
// This is not ideal, but streaming to an external URL doesn't work
|
|
148
|
+
const body = await request.arrayBuffer()
|
|
149
|
+
proxyRequest = new Request(rewriteUrl, {
|
|
150
|
+
headers,
|
|
151
|
+
method: request.method,
|
|
152
|
+
body,
|
|
153
|
+
})
|
|
154
|
+
} else {
|
|
155
|
+
proxyRequest = new Request(rewriteUrl, {
|
|
156
|
+
headers,
|
|
157
|
+
method: request.method,
|
|
158
|
+
})
|
|
159
|
+
}
|
|
160
|
+
return addMiddlewareHeaders(fetch(proxyRequest), res)
|
|
161
|
+
} else if (isDataReq) {
|
|
162
|
+
rewriteUrl.pathname = rewriteDataPath({
|
|
163
|
+
dataUrl: originalPath,
|
|
164
|
+
newRoute: rewriteUrl.pathname,
|
|
165
|
+
basePath: nextConfig?.basePath,
|
|
166
|
+
})
|
|
118
167
|
}
|
|
119
168
|
res.headers.set('x-middleware-rewrite', relativeUrl)
|
|
120
|
-
|
|
121
|
-
request.headers.set('x-original-path', new URL(request.url, `http://n`).pathname)
|
|
122
169
|
request.headers.set('x-middleware-rewrite', rewrite)
|
|
123
|
-
|
|
124
|
-
return addMiddlewareHeaders(context.rewrite(rewrite), res)
|
|
170
|
+
return addMiddlewareHeaders(fetch(new Request(rewriteUrl, request)), res)
|
|
125
171
|
}
|
|
126
172
|
|
|
127
|
-
|
|
173
|
+
let redirect = res.headers.get('location')
|
|
174
|
+
|
|
175
|
+
// If we are redirecting a request that had a locale in the URL, we need to add it back in
|
|
176
|
+
if (redirect && requestLocale) {
|
|
177
|
+
const redirectUrl = new URL(redirect, request.url)
|
|
178
|
+
|
|
179
|
+
const normalizedRedirect = normalizeLocalePath(redirectUrl.pathname, nextConfig?.i18n?.locales)
|
|
180
|
+
|
|
181
|
+
const locale = normalizedRedirect.detectedLocale ?? requestLocale
|
|
182
|
+
// Pages router API routes don't have a locale in the URL
|
|
183
|
+
if (locale && !redirectUrl.pathname.startsWith(`/api/`)) {
|
|
184
|
+
redirectUrl.pathname = `/${locale}${normalizedRedirect.pathname}`
|
|
185
|
+
redirect = redirectUrl.toString()
|
|
186
|
+
res.headers.set('location', redirect)
|
|
187
|
+
}
|
|
188
|
+
}
|
|
128
189
|
|
|
129
190
|
// Data requests shouldn't automatically redirect in the browser (they might be HTML pages): they're handled by the router
|
|
130
191
|
if (redirect && isDataReq) {
|
|
@@ -142,5 +203,6 @@ export const buildResponse = async ({
|
|
|
142
203
|
res.headers.delete('x-middleware-next')
|
|
143
204
|
return addMiddlewareHeaders(context.next(), res)
|
|
144
205
|
}
|
|
206
|
+
|
|
145
207
|
return res
|
|
146
208
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { assertEquals } from 'https://deno.land/std@0.175.0/testing/asserts.ts'
|
|
2
|
+
import { rewriteDataPath } from './util.ts'
|
|
3
|
+
|
|
4
|
+
Deno.test('rewriteDataPath', async (t) => {
|
|
5
|
+
await t.step('should rewrite a data url', async () => {
|
|
6
|
+
const dataUrl = '/_next/data/build-id/rewrite-me.json'
|
|
7
|
+
const newRoute = '/target'
|
|
8
|
+
const result = rewriteDataPath({ dataUrl, newRoute })
|
|
9
|
+
assertEquals(result, '/_next/data/build-id/target.json')
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
await t.step('should rewrite a data url with a base path', async () => {
|
|
13
|
+
const dataUrl = '/baseDir/_next/data/build-id/rewrite-me.json'
|
|
14
|
+
const newRoute = '/target'
|
|
15
|
+
const result = rewriteDataPath({ dataUrl, newRoute, basePath: '/baseDir' })
|
|
16
|
+
assertEquals(result, '/baseDir/_next/data/build-id/target.json')
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
await t.step('should rewrite from an index data url', async () => {
|
|
20
|
+
const dataUrl = '/_next/data/build-id/index.json'
|
|
21
|
+
const newRoute = '/target'
|
|
22
|
+
const result = rewriteDataPath({ dataUrl, newRoute })
|
|
23
|
+
assertEquals(result, '/_next/data/build-id/target.json')
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
await t.step('should rewrite to an index data url', async () => {
|
|
27
|
+
const dataUrl = '/_next/data/build-id/rewrite-me.json'
|
|
28
|
+
const newRoute = '/'
|
|
29
|
+
const result = rewriteDataPath({ dataUrl, newRoute })
|
|
30
|
+
assertEquals(result, '/_next/data/build-id/index.json')
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
await t.step('should rewrite to a route with a trailing slash', async () => {
|
|
34
|
+
const dataUrl = '/_next/data/build-id/rewrite-me.json'
|
|
35
|
+
const newRoute = '/target/'
|
|
36
|
+
const result = rewriteDataPath({ dataUrl, newRoute })
|
|
37
|
+
assertEquals(result, '/_next/data/build-id/target.json')
|
|
38
|
+
})
|
|
39
|
+
})
|
package/edge-runtime/lib/util.ts
CHANGED
|
@@ -1,16 +1,63 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import type { RequestData } from './next-request.ts'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Normalize a data URL into a route path.
|
|
5
|
+
* @see https://github.com/vercel/next.js/blob/25e0988e7c9033cb1503cbe0c62ba5de2e97849c/packages/next/src/shared/lib/router/utils/get-next-pathname-info.ts#L69-L76
|
|
6
|
+
*/
|
|
7
|
+
export function normalizeDataUrl(urlPath: string) {
|
|
8
|
+
if (urlPath.startsWith('/_next/data/') && urlPath.includes('.json')) {
|
|
9
|
+
const paths = urlPath
|
|
6
10
|
.replace(/^\/_next\/data\//, '')
|
|
7
11
|
.replace(/\.json/, '')
|
|
8
12
|
.split('/')
|
|
9
13
|
|
|
10
|
-
|
|
14
|
+
urlPath = paths[1] !== 'index' ? `/${paths.slice(1).join('/')}` : '/'
|
|
11
15
|
}
|
|
12
16
|
|
|
13
|
-
return
|
|
17
|
+
return urlPath
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const removeBasePath = (path: string, basePath?: string) => {
|
|
21
|
+
if (basePath && path.startsWith(basePath)) {
|
|
22
|
+
return path.replace(basePath, '')
|
|
23
|
+
}
|
|
24
|
+
return path
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// https://github.com/vercel/next.js/blob/canary/packages/next/src/shared/lib/i18n/normalize-locale-path.ts
|
|
28
|
+
|
|
29
|
+
export interface PathLocale {
|
|
30
|
+
detectedLocale?: string
|
|
31
|
+
pathname: string
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* For a pathname that may include a locale from a list of locales, it
|
|
36
|
+
* removes the locale from the pathname returning it alongside with the
|
|
37
|
+
* detected locale.
|
|
38
|
+
*
|
|
39
|
+
* @param pathname A pathname that may include a locale.
|
|
40
|
+
* @param locales A list of locales.
|
|
41
|
+
* @returns The detected locale and pathname without locale
|
|
42
|
+
*/
|
|
43
|
+
export function normalizeLocalePath(pathname: string, locales?: string[]): PathLocale {
|
|
44
|
+
let detectedLocale: string | undefined
|
|
45
|
+
// first item will be empty string from splitting at first char
|
|
46
|
+
const pathnameParts = pathname.split('/')
|
|
47
|
+
|
|
48
|
+
;(locales || []).some((locale) => {
|
|
49
|
+
if (pathnameParts[1] && pathnameParts[1].toLowerCase() === locale.toLowerCase()) {
|
|
50
|
+
detectedLocale = locale
|
|
51
|
+
pathnameParts.splice(1, 1)
|
|
52
|
+
pathname = pathnameParts.join('/') || '/'
|
|
53
|
+
return true
|
|
54
|
+
}
|
|
55
|
+
return false
|
|
56
|
+
})
|
|
57
|
+
return {
|
|
58
|
+
pathname,
|
|
59
|
+
detectedLocale,
|
|
60
|
+
}
|
|
14
61
|
}
|
|
15
62
|
|
|
16
63
|
/**
|
|
@@ -24,3 +71,28 @@ export function relativizeURL(url: string | string, base: string | URL) {
|
|
|
24
71
|
? relative.toString().replace(origin, '')
|
|
25
72
|
: relative.toString()
|
|
26
73
|
}
|
|
74
|
+
|
|
75
|
+
export const normalizeIndex = (path: string) => (path === '/' ? '/index' : path)
|
|
76
|
+
|
|
77
|
+
const stripTrailingSlash = (path: string) =>
|
|
78
|
+
path !== '/' && path.endsWith('/') ? path.slice(0, -1) : path
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Modify a data url to point to a new page route.
|
|
82
|
+
*/
|
|
83
|
+
export function rewriteDataPath({
|
|
84
|
+
dataUrl,
|
|
85
|
+
newRoute,
|
|
86
|
+
basePath,
|
|
87
|
+
}: {
|
|
88
|
+
dataUrl: string
|
|
89
|
+
newRoute: string
|
|
90
|
+
basePath?: string
|
|
91
|
+
}) {
|
|
92
|
+
const normalizedDataUrl = normalizeDataUrl(removeBasePath(dataUrl, basePath))
|
|
93
|
+
|
|
94
|
+
return dataUrl.replace(
|
|
95
|
+
normalizeIndex(normalizedDataUrl),
|
|
96
|
+
stripTrailingSlash(normalizeIndex(newRoute)),
|
|
97
|
+
)
|
|
98
|
+
}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import type { Context } from '@netlify/edge-functions'
|
|
2
2
|
|
|
3
3
|
import matchers from './matchers.json' assert { type: 'json' }
|
|
4
|
+
import nextConfig from './next.config.json' assert { type: 'json' }
|
|
4
5
|
|
|
6
|
+
import { InternalHeaders } from './lib/headers.ts'
|
|
7
|
+
import { logger, LogLevel } from './lib/logging.ts'
|
|
5
8
|
import { buildNextRequest, RequestData } from './lib/next-request.ts'
|
|
6
9
|
import { buildResponse } from './lib/response.ts'
|
|
7
10
|
import { FetchEventResult } from './lib/response.ts'
|
|
@@ -29,20 +32,34 @@ export async function handleMiddleware(
|
|
|
29
32
|
context: Context,
|
|
30
33
|
nextHandler: NextHandler,
|
|
31
34
|
) {
|
|
32
|
-
const nextRequest = buildNextRequest(request, context)
|
|
35
|
+
const nextRequest = buildNextRequest(request, context, nextConfig)
|
|
33
36
|
const url = new URL(request.url)
|
|
37
|
+
const reqLogger = logger
|
|
38
|
+
.withLogLevel(
|
|
39
|
+
request.headers.has(InternalHeaders.NFDebugLogging) ? LogLevel.Debug : LogLevel.Log,
|
|
40
|
+
)
|
|
41
|
+
.withFields({ url_path: url.pathname })
|
|
42
|
+
.withRequestID(request.headers.get(InternalHeaders.NFRequestID))
|
|
34
43
|
|
|
35
44
|
// While we have already checked the path when mapping to the edge function,
|
|
36
45
|
// Next.js supports extra rules that we need to check here too, because we
|
|
37
46
|
// might be running an edge function for a path we should not. If we find
|
|
38
47
|
// that's the case, short-circuit the execution.
|
|
39
48
|
if (!matchesMiddleware(url.pathname, request, searchParamsToUrlQuery(url.searchParams))) {
|
|
49
|
+
reqLogger.debug('Aborting middleware due to runtime rules')
|
|
50
|
+
|
|
40
51
|
return
|
|
41
52
|
}
|
|
42
53
|
|
|
43
54
|
try {
|
|
44
55
|
const result = await nextHandler({ request: nextRequest })
|
|
45
|
-
const response = await buildResponse({
|
|
56
|
+
const response = await buildResponse({
|
|
57
|
+
context,
|
|
58
|
+
logger: reqLogger,
|
|
59
|
+
request,
|
|
60
|
+
result,
|
|
61
|
+
requestLocale: nextRequest.detectedLocale,
|
|
62
|
+
})
|
|
46
63
|
|
|
47
64
|
return response
|
|
48
65
|
} catch (error) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
"https://ghuc.cc/worker-tools/resolvable-promise/index.ts": "./raw.githubusercontent.com/worker-tools/resolvable-promise/master/index.ts",
|
|
4
4
|
"https://deno.land/": "./deno.land/",
|
|
5
5
|
"https://esm.sh/": "./esm.sh/",
|
|
6
|
-
"https://raw.githubusercontent.com/": "./raw.githubusercontent.com/"
|
|
6
|
+
"https://raw.githubusercontent.com/": "./raw.githubusercontent.com/",
|
|
7
|
+
"https://v1-7-0--edge-utils.netlify.app/": "./v1-7-0--edge-utils.netlify.app/"
|
|
7
8
|
},
|
|
8
9
|
"scopes": {
|
|
9
10
|
"./esm.sh/": {
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
type Logger = (...data: unknown[]) => void;
|
|
2
|
+
|
|
3
|
+
export enum LogLevel {
|
|
4
|
+
Debug = 1,
|
|
5
|
+
Log,
|
|
6
|
+
Error,
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const serializeError = (error: Error): Record<string, unknown> => {
|
|
10
|
+
const cause = error?.cause instanceof Error
|
|
11
|
+
? serializeError(error.cause)
|
|
12
|
+
: error.cause;
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
error: error.message,
|
|
16
|
+
error_cause: cause,
|
|
17
|
+
error_stack: error.stack,
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export class StructuredLogger {
|
|
22
|
+
private fields: Record<string, unknown>;
|
|
23
|
+
private logLevel: LogLevel;
|
|
24
|
+
private message: string;
|
|
25
|
+
private rawLogger?: Logger;
|
|
26
|
+
private requestID?: string;
|
|
27
|
+
__netlifyStructuredLogger: number;
|
|
28
|
+
|
|
29
|
+
constructor(
|
|
30
|
+
message?: string,
|
|
31
|
+
fields?: Record<string, unknown>,
|
|
32
|
+
requestID?: string,
|
|
33
|
+
rawLogger?: Logger,
|
|
34
|
+
logLevel?: LogLevel,
|
|
35
|
+
) {
|
|
36
|
+
this.fields = fields ?? {};
|
|
37
|
+
this.logLevel = logLevel ?? LogLevel.Log;
|
|
38
|
+
this.message = message ?? "";
|
|
39
|
+
this.rawLogger = rawLogger;
|
|
40
|
+
this.requestID = requestID;
|
|
41
|
+
|
|
42
|
+
// Value should be equal to the major version
|
|
43
|
+
this.__netlifyStructuredLogger = 1;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
debug(message: string) {
|
|
47
|
+
if (this.logLevel > LogLevel.Debug) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const logger = this.rawLogger ?? globalThis.console.log;
|
|
52
|
+
|
|
53
|
+
logger(
|
|
54
|
+
new StructuredLogger(
|
|
55
|
+
message,
|
|
56
|
+
this.fields,
|
|
57
|
+
this.requestID,
|
|
58
|
+
this.rawLogger,
|
|
59
|
+
this.logLevel,
|
|
60
|
+
),
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
error(message: string) {
|
|
65
|
+
if (this.logLevel > LogLevel.Error) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const logger = this.rawLogger ?? globalThis.console.log;
|
|
70
|
+
|
|
71
|
+
logger(
|
|
72
|
+
new StructuredLogger(
|
|
73
|
+
message,
|
|
74
|
+
this.fields,
|
|
75
|
+
this.requestID,
|
|
76
|
+
this.rawLogger,
|
|
77
|
+
this.logLevel,
|
|
78
|
+
),
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
log(message: string) {
|
|
83
|
+
if (this.logLevel > LogLevel.Log) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const logger = this.rawLogger ?? globalThis.console.log;
|
|
88
|
+
|
|
89
|
+
logger(
|
|
90
|
+
new StructuredLogger(
|
|
91
|
+
message,
|
|
92
|
+
this.fields,
|
|
93
|
+
this.requestID,
|
|
94
|
+
this.rawLogger,
|
|
95
|
+
this.logLevel,
|
|
96
|
+
),
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
serialize() {
|
|
101
|
+
const log = {
|
|
102
|
+
fields: this.fields,
|
|
103
|
+
message: this.message,
|
|
104
|
+
requestID: this.requestID,
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
return log;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
withError(error: unknown) {
|
|
111
|
+
const fields = error instanceof Error ? serializeError(error) : { error };
|
|
112
|
+
|
|
113
|
+
return this.withFields(fields);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
withFields(fields: Record<string, unknown>) {
|
|
117
|
+
return new StructuredLogger(
|
|
118
|
+
this.message,
|
|
119
|
+
{
|
|
120
|
+
...this.fields,
|
|
121
|
+
...fields,
|
|
122
|
+
},
|
|
123
|
+
this.requestID,
|
|
124
|
+
this.rawLogger,
|
|
125
|
+
this.logLevel,
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
withLogLevel(logLevel: LogLevel) {
|
|
130
|
+
return new StructuredLogger(
|
|
131
|
+
this.message,
|
|
132
|
+
this.fields,
|
|
133
|
+
this.requestID,
|
|
134
|
+
this.rawLogger,
|
|
135
|
+
logLevel,
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
withRawLogger(logger: Logger) {
|
|
140
|
+
return new StructuredLogger(
|
|
141
|
+
this.message,
|
|
142
|
+
this.fields,
|
|
143
|
+
this.requestID,
|
|
144
|
+
logger,
|
|
145
|
+
this.logLevel,
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
withRequestID(requestID: string | null) {
|
|
150
|
+
if (requestID === null) {
|
|
151
|
+
return this;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return new StructuredLogger(
|
|
155
|
+
this.message,
|
|
156
|
+
this.fields,
|
|
157
|
+
requestID,
|
|
158
|
+
this.rawLogger,
|
|
159
|
+
this.logLevel,
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export const logger = new StructuredLogger();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./logger.ts";
|
package/edge-runtime/vendor.ts
CHANGED
|
@@ -16,3 +16,5 @@ import 'https://deno.land/x/html_rewriter@v0.1.0-pre.17/index.ts'
|
|
|
16
16
|
|
|
17
17
|
import 'https://esm.sh/v91/next@12.2.5/deno/dist/server/web/spec-extension/request.js'
|
|
18
18
|
import 'https://esm.sh/v91/next@12.2.5/deno/dist/server/web/spec-extension/response.js'
|
|
19
|
+
|
|
20
|
+
import 'https://v1-7-0--edge-utils.netlify.app/logger/mod.ts'
|
package/package.json
CHANGED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
const require = await (async () => {
|
|
3
|
-
const { createRequire } = await import("node:module");
|
|
4
|
-
return createRequire(import.meta.url);
|
|
5
|
-
})();
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
// src/run/systemlog.ts
|
|
9
|
-
var systemLogTag = "__nfSystemLog";
|
|
10
|
-
var serializeError = (error) => {
|
|
11
|
-
const cause = error?.cause instanceof Error ? serializeError(error.cause) : error.cause;
|
|
12
|
-
return {
|
|
13
|
-
error: error.message,
|
|
14
|
-
error_cause: cause,
|
|
15
|
-
error_stack: error.stack
|
|
16
|
-
};
|
|
17
|
-
};
|
|
18
|
-
var StructuredLogger = class _StructuredLogger {
|
|
19
|
-
fields;
|
|
20
|
-
message;
|
|
21
|
-
constructor(message, fields) {
|
|
22
|
-
this.fields = fields ?? {};
|
|
23
|
-
this.message = message ?? "";
|
|
24
|
-
}
|
|
25
|
-
// TODO: add sampling
|
|
26
|
-
doLog(logger2, message) {
|
|
27
|
-
logger2(systemLogTag, JSON.stringify({ msg: message, fields: this.fields }));
|
|
28
|
-
}
|
|
29
|
-
log(message) {
|
|
30
|
-
this.doLog(console.log, message);
|
|
31
|
-
}
|
|
32
|
-
info(message) {
|
|
33
|
-
this.doLog(console.info, message);
|
|
34
|
-
}
|
|
35
|
-
debug(message) {
|
|
36
|
-
this.doLog(console.debug, message);
|
|
37
|
-
}
|
|
38
|
-
warn(message) {
|
|
39
|
-
this.doLog(console.warn, message);
|
|
40
|
-
}
|
|
41
|
-
error(message) {
|
|
42
|
-
this.doLog(console.error, message);
|
|
43
|
-
}
|
|
44
|
-
withError(error) {
|
|
45
|
-
const fields = error instanceof Error ? serializeError(error) : { error };
|
|
46
|
-
return this.withFields(fields);
|
|
47
|
-
}
|
|
48
|
-
withFields(fields) {
|
|
49
|
-
return new _StructuredLogger(this.message, {
|
|
50
|
-
...this.fields,
|
|
51
|
-
...fields
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
var logger = new StructuredLogger();
|
|
56
|
-
|
|
57
|
-
export {
|
|
58
|
-
StructuredLogger,
|
|
59
|
-
logger
|
|
60
|
-
};
|