"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
Object.defineProperty(exports, "default", {
    enumerable: true,
    get: function() {
        return exportPage;
    }
});
require("../server/node-polyfill-fetch");
require("../server/node-environment");
const _path = require("path");
const _fs = /*#__PURE__*/ _interop_require_wildcard(require("fs"));
const _amphtmlvalidator = /*#__PURE__*/ _interop_require_default(require("next/dist/compiled/amphtml-validator"));
const _loadcomponents = require("../server/load-components");
const _isdynamic = require("../shared/lib/router/utils/is-dynamic");
const _routematcher = require("../shared/lib/router/utils/route-matcher");
const _routeregex = require("../shared/lib/router/utils/route-regex");
const _normalizepagepath = require("../shared/lib/page-path/normalize-page-path");
const _constants = require("../lib/constants");
const _require = require("../server/require");
const _normalizelocalepath = require("../shared/lib/i18n/normalize-locale-path");
const _trace = require("../trace");
const _ampmode = require("../shared/lib/amp-mode");
const _setuphttpagentenv = require("../server/setup-http-agent-env");
const _renderresult = /*#__PURE__*/ _interop_require_default(require("../server/render-result"));
const _iserror = /*#__PURE__*/ _interop_require_default(require("../lib/is-error"));
const _requestmeta = require("../server/request-meta");
const _apppaths = require("../shared/lib/router/utils/app-paths");
const _hooksservercontext = require("../client/components/hooks-server-context");
const _incrementalcache = require("../server/lib/incremental-cache");
const _notfound = require("../client/components/not-found");
const _redirect = require("../client/components/redirect");
const _nossrerror = require("../shared/lib/lazy-dynamic/no-ssr-error");
const _mockrequest = require("../server/lib/mock-request");
const _node = require("../server/base-http/node");
const _isapprouteroute = require("../lib/is-app-route-route");
const _utils = require("../server/web/utils");
const _routemoduleloader = require("../server/future/helpers/module-loader/route-module-loader");
const _nextrequest = require("../server/web/spec-extension/adapters/next-request");
const _ciinfo = /*#__PURE__*/ _interop_require_wildcard(require("../telemetry/ci-info"));
function _interop_require_default(obj) {
    return obj && obj.__esModule ? obj : {
        default: obj
    };
}
function _getRequireWildcardCache(nodeInterop) {
    if (typeof WeakMap !== "function") return null;
    var cacheBabelInterop = new WeakMap();
    var cacheNodeInterop = new WeakMap();
    return (_getRequireWildcardCache = function(nodeInterop) {
        return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
    })(nodeInterop);
}
function _interop_require_wildcard(obj, nodeInterop) {
    if (!nodeInterop && obj && obj.__esModule) {
        return obj;
    }
    if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
        return {
            default: obj
        };
    }
    var cache = _getRequireWildcardCache(nodeInterop);
    if (cache && cache.has(obj)) {
        return cache.get(obj);
    }
    var newObj = {};
    var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
    for(var key in obj){
        if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
            var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
            if (desc && (desc.get || desc.set)) {
                Object.defineProperty(newObj, key, desc);
            } else {
                newObj[key] = obj[key];
            }
        }
    }
    newObj.default = obj;
    if (cache) {
        cache.set(obj, newObj);
    }
    return newObj;
}
const envConfig = require("../shared/lib/runtime-config");
globalThis.__NEXT_DATA__ = {
    nextExport: true
};
async function exportPage({ parentSpanId , path , pathMap , distDir , outDir , pagesDataDir , renderOpts , buildExport , serverRuntimeConfig , subFolders , optimizeFonts , optimizeCss , disableOptimizedLoading , httpAgentOptions , debugOutput , isrMemoryCacheSize , fetchCache , fetchCacheKeyPrefix , incrementalCacheHandlerPath  }) {
    (0, _setuphttpagentenv.setHttpClientAndAgentOptions)({
        httpAgentOptions
    });
    const exportPageSpan = (0, _trace.trace)("export-page-worker", parentSpanId);
    return exportPageSpan.traceAsyncFn(async ()=>{
        const start = Date.now();
        let results = {
            ampValidations: []
        };
        try {
            var _req_url, _components_pageConfig, _components_pageConfig1;
            if (renderOpts.deploymentId) {
                process.env.NEXT_DEPLOYMENT_ID = renderOpts.deploymentId;
            }
            const { query: originalQuery = {}  } = pathMap;
            const { page  } = pathMap;
            const pathname = (0, _apppaths.normalizeAppPath)(page);
            const isAppDir = pathMap._isAppDir;
            const isDynamicError = pathMap._isDynamicError;
            const filePath = (0, _normalizepagepath.normalizePagePath)(path);
            const isDynamic = (0, _isdynamic.isDynamicRoute)(page);
            const ampPath = `${filePath}.amp`;
            let renderAmpPath = ampPath;
            let query = {
                ...originalQuery
            };
            let params;
            const isRouteHandler = isAppDir && (0, _isapprouteroute.isAppRouteRoute)(page);
            if (isAppDir) {
                outDir = (0, _path.join)(distDir, "server/app");
            }
            let updatedPath = query.__nextSsgPath || path;
            let locale = query.__nextLocale || renderOpts.locale;
            delete query.__nextLocale;
            delete query.__nextSsgPath;
            if (renderOpts.locale) {
                const localePathResult = (0, _normalizelocalepath.normalizeLocalePath)(path, renderOpts.locales);
                if (localePathResult.detectedLocale) {
                    updatedPath = localePathResult.pathname;
                    locale = localePathResult.detectedLocale;
                    if (locale === renderOpts.defaultLocale) {
                        renderAmpPath = `${(0, _normalizepagepath.normalizePagePath)(updatedPath)}.amp`;
                    }
                }
            }
            // We need to show a warning if they try to provide query values
            // for an auto-exported page since they won't be available
            const hasOrigQueryValues = Object.keys(originalQuery).length > 0;
            const queryWithAutoExportWarn = ()=>{
                if (hasOrigQueryValues) {
                    throw new Error(`\nError: you provided query values for ${path} which is an auto-exported page. These can not be applied since the page can no longer be re-rendered on the server. To disable auto-export for this page add \`getInitialProps\`\n`);
                }
            };
            // Check if the page is a specified dynamic route
            const nonLocalizedPath = (0, _normalizelocalepath.normalizeLocalePath)(path, renderOpts.locales).pathname;
            if (isDynamic && page !== nonLocalizedPath) {
                const normalizedPage = isAppDir ? (0, _apppaths.normalizeAppPath)(page) : page;
                params = (0, _routematcher.getRouteMatcher)((0, _routeregex.getRouteRegex)(normalizedPage))(updatedPath) || undefined;
                if (params) {
                    query = {
                        ...query,
                        ...params
                    };
                } else {
                    throw new Error(`The provided export path '${updatedPath}' doesn't match the '${page}' page.\nRead more: https://nextjs.org/docs/messages/export-path-mismatch`);
                }
            }
            const { req , res  } = (0, _mockrequest.createRequestResponseMocks)({
                url: updatedPath
            });
            for (const statusCode of [
                404,
                500
            ]){
                if ([
                    `/${statusCode}`,
                    `/${statusCode}.html`,
                    `/${statusCode}/index.html`
                ].some((p)=>p === updatedPath || `/${locale}${p}` === updatedPath)) {
                    res.statusCode = statusCode;
                }
            }
            if (renderOpts.trailingSlash && !((_req_url = req.url) == null ? void 0 : _req_url.endsWith("/"))) {
                req.url += "/";
            }
            if (locale && buildExport && renderOpts.domainLocales && renderOpts.domainLocales.some((dl)=>{
                var _dl_locales;
                return dl.defaultLocale === locale || ((_dl_locales = dl.locales) == null ? void 0 : _dl_locales.includes(locale || ""));
            })) {
                (0, _requestmeta.addRequestMeta)(req, "__nextIsLocaleDomain", true);
            }
            envConfig.setConfig({
                serverRuntimeConfig,
                publicRuntimeConfig: renderOpts.runtimeConfig
            });
            const getHtmlFilename = (_path1)=>subFolders ? `${_path1}${_path.sep}index.html` : `${_path1}.html`;
            let htmlFilename = getHtmlFilename(filePath);
            // dynamic routes can provide invalid extensions e.g. /blog/[...slug] returns an
            // extension of `.slug]`
            const pageExt = isDynamic || isAppDir ? "" : (0, _path.extname)(page);
            const pathExt = isDynamic || isAppDir ? "" : (0, _path.extname)(path);
            // force output 404.html for backwards compat
            if (path === "/404.html") {
                htmlFilename = path;
            } else if (pageExt !== pathExt && pathExt !== "") {
                const isBuiltinPaths = [
                    "/500",
                    "/404"
                ].some((p)=>p === path || p === path + ".html");
                // If the ssg path has .html extension, and it's not builtin paths, use it directly
                // Otherwise, use that as the filename instead
                const isHtmlExtPath = !isBuiltinPaths && path.endsWith(".html");
                htmlFilename = isHtmlExtPath ? getHtmlFilename(path) : path;
            } else if (path === "/") {
                // If the path is the root, just use index.html
                htmlFilename = "index.html";
            }
            const baseDir = (0, _path.join)(outDir, (0, _path.dirname)(htmlFilename));
            let htmlFilepath = (0, _path.join)(outDir, htmlFilename);
            await _fs.promises.mkdir(baseDir, {
                recursive: true
            });
            let renderResult;
            let curRenderOpts = {};
            const { renderToHTML  } = require("../server/render");
            let renderMethod = renderToHTML;
            let inAmpMode = false, hybridAmp = false;
            const renderedDuringBuild = (getStaticProps)=>{
                return !buildExport && getStaticProps && !(0, _isdynamic.isDynamicRoute)(path);
            };
            let components = null;
            if (!isRouteHandler) {
                components = await (0, _loadcomponents.loadComponents)({
                    distDir,
                    pathname: page,
                    isAppPath: isAppDir
                });
                curRenderOpts = {
                    ...components,
                    ...renderOpts,
                    strictNextHead: !!renderOpts.strictNextHead,
                    ampPath: renderAmpPath,
                    params,
                    optimizeFonts,
                    optimizeCss,
                    disableOptimizedLoading,
                    fontManifest: optimizeFonts ? (0, _require.requireFontManifest)(distDir) : null,
                    locale: locale,
                    supportsDynamicHTML: false,
                    originalPathname: page,
                    ..._ciinfo.hasNextSupport ? {
                        isRevalidate: true
                    } : {}
                };
            }
            // during build we attempt rendering app dir paths
            // and bail when dynamic dependencies are detected
            // only fully static paths are fully generated here
            if (isAppDir) {
                if (fetchCache) {
                    let CacheHandler;
                    if (incrementalCacheHandlerPath) {
                        CacheHandler = require(incrementalCacheHandlerPath);
                        CacheHandler = CacheHandler.default || CacheHandler;
                    }
                    const incrementalCache = new _incrementalcache.IncrementalCache({
                        dev: false,
                        requestHeaders: {},
                        flushToDisk: true,
                        fetchCache: true,
                        maxMemoryCacheSize: isrMemoryCacheSize,
                        fetchCacheKeyPrefix,
                        getPrerenderManifest: ()=>({
                                version: 4,
                                routes: {},
                                dynamicRoutes: {},
                                preview: {
                                    previewModeEncryptionKey: "",
                                    previewModeId: "",
                                    previewModeSigningKey: ""
                                },
                                notFoundRoutes: []
                            }),
                        fs: {
                            readFile: (f)=>_fs.default.promises.readFile(f),
                            readFileSync: (f)=>_fs.default.readFileSync(f),
                            writeFile: (f, d)=>_fs.default.promises.writeFile(f, d),
                            mkdir: (dir)=>_fs.default.promises.mkdir(dir, {
                                    recursive: true
                                }),
                            stat: (f)=>_fs.default.promises.stat(f)
                        },
                        serverDistDir: (0, _path.join)(distDir, "server"),
                        CurCacheHandler: CacheHandler,
                        minimalMode: _ciinfo.hasNextSupport
                    });
                    globalThis.__incrementalCache = incrementalCache;
                    curRenderOpts.incrementalCache = incrementalCache;
                }
                const isDynamicUsageError = (err)=>err.digest === _hooksservercontext.DYNAMIC_ERROR_CODE || (0, _notfound.isNotFoundError)(err) || err.digest === _nossrerror.NEXT_DYNAMIC_NO_SSR_CODE || (0, _redirect.isRedirectError)(err);
                if (isRouteHandler) {
                    // Ensure that the url for the page is absolute.
                    req.url = `http://localhost:3000${req.url}`;
                    const request = _nextrequest.NextRequestAdapter.fromNodeNextRequest(new _node.NodeNextRequest(req));
                    // Create the context for the handler. This contains the params from
                    // the route and the context for the request.
                    const context = {
                        params,
                        prerenderManifest: {
                            version: 4,
                            routes: {},
                            dynamicRoutes: {},
                            preview: {
                                previewModeEncryptionKey: "",
                                previewModeId: "",
                                previewModeSigningKey: ""
                            },
                            notFoundRoutes: []
                        },
                        staticGenerationContext: {
                            originalPathname: page,
                            nextExport: true,
                            supportsDynamicHTML: false,
                            incrementalCache: curRenderOpts.incrementalCache,
                            ..._ciinfo.hasNextSupport ? {
                                isRevalidate: true
                            } : {}
                        }
                    };
                    try {
                        // This is a route handler, which means it has it's handler in the
                        // bundled file already, we should just use that.
                        const filename = _path.posix.join(distDir, "server", "app", page);
                        // Load the module for the route.
                        const module = await _routemoduleloader.RouteModuleLoader.load(filename);
                        // Call the handler with the request and context from the module.
                        const response = await module.handle(request, context);
                        // TODO: (wyattjoh) if cookie headers are present, should we bail?
                        // we don't consider error status for static generation
                        // except for 404
                        // TODO: do we want to cache other status codes?
                        const isValidStatus = response.status < 400 || response.status === 404;
                        if (isValidStatus) {
                            var _context_staticGenerationContext_store;
                            const body = await response.blob();
                            const revalidate = ((_context_staticGenerationContext_store = context.staticGenerationContext.store) == null ? void 0 : _context_staticGenerationContext_store.revalidate) || false;
                            results.fromBuildExportRevalidate = revalidate;
                            const headers = (0, _utils.toNodeOutgoingHttpHeaders)(response.headers);
                            const cacheTags = context.staticGenerationContext.fetchTags;
                            if (cacheTags) {
                                headers["x-next-cache-tags"] = cacheTags;
                            }
                            if (!headers["content-type"] && body.type) {
                                headers["content-type"] = body.type;
                            }
                            results.fromBuildExportMeta = {
                                status: response.status,
                                headers
                            };
                            await _fs.promises.writeFile(htmlFilepath.replace(/\.html$/, ".body"), Buffer.from(await body.arrayBuffer()), "utf8");
                            await _fs.promises.writeFile(htmlFilepath.replace(/\.html$/, ".meta"), JSON.stringify({
                                status: response.status,
                                headers
                            }));
                        } else {
                            results.fromBuildExportRevalidate = 0;
                        }
                    } catch (err) {
                        if (!isDynamicUsageError(err)) {
                            throw err;
                        }
                        results.fromBuildExportRevalidate = 0;
                    }
                } else {
                    const { renderToHTMLOrFlight  } = require("../server/app-render/app-render");
                    try {
                        curRenderOpts.params ||= {};
                        const isNotFoundPage = page === "/_not-found";
                        const result = await renderToHTMLOrFlight(req, res, isNotFoundPage ? "/404" : pathname, query, curRenderOpts);
                        const html = result.toUnchunkedString();
                        const { metadata  } = result;
                        const flightData = metadata.pageData;
                        const revalidate = metadata.revalidate;
                        results.fromBuildExportRevalidate = revalidate;
                        if (revalidate !== 0) {
                            const cacheTags = curRenderOpts.fetchTags;
                            const headers = cacheTags ? {
                                "x-next-cache-tags": cacheTags
                            } : undefined;
                            if (_ciinfo.hasNextSupport) {
                                if (cacheTags) {
                                    results.fromBuildExportMeta = {
                                        headers
                                    };
                                }
                            }
                            await _fs.promises.writeFile(htmlFilepath, html ?? "", "utf8");
                            await _fs.promises.writeFile(htmlFilepath.replace(/\.html$/, ".meta"), JSON.stringify({
                                headers
                            }));
                            await _fs.promises.writeFile(htmlFilepath.replace(/\.html$/, ".rsc"), flightData);
                        } else if (isDynamicError) {
                            throw new Error(`Page with dynamic = "error" encountered dynamic data method on ${path}.`);
                        }
                        const staticBailoutInfo = metadata.staticBailoutInfo || {};
                        if (revalidate === 0 && debugOutput && (staticBailoutInfo == null ? void 0 : staticBailoutInfo.description)) {
                            const bailErr = new Error(`Static generation failed due to dynamic usage on ${path}, reason: ${staticBailoutInfo.description}`);
                            const stack = staticBailoutInfo.stack;
                            if (stack) {
                                bailErr.stack = bailErr.message + stack.substring(stack.indexOf("\n"));
                            }
                            console.warn(bailErr);
                        }
                    } catch (err) {
                        if (!isDynamicUsageError(err)) {
                            throw err;
                        }
                    }
                }
                return {
                    ...results,
                    duration: Date.now() - start
                };
            }
            if (!components) {
                throw new Error(`invariant: components were not loaded correctly during export for path: ${path}`);
            }
            const ampState = {
                ampFirst: ((_components_pageConfig = components.pageConfig) == null ? void 0 : _components_pageConfig.amp) === true,
                hasQuery: Boolean(query.amp),
                hybrid: ((_components_pageConfig1 = components.pageConfig) == null ? void 0 : _components_pageConfig1.amp) === "hybrid"
            };
            inAmpMode = (0, _ampmode.isInAmpMode)(ampState);
            hybridAmp = ampState.hybrid;
            if (components.getServerSideProps) {
                throw new Error(`Error for page ${page}: ${_constants.SERVER_PROPS_EXPORT_ERROR}`);
            }
            // for non-dynamic SSG pages we should have already
            // prerendered the file
            if (renderedDuringBuild(components.getStaticProps)) {
                return {
                    ...results,
                    duration: Date.now() - start
                };
            }
            if (components.getStaticProps && !htmlFilepath.endsWith(".html")) {
                // make sure it ends with .html if the name contains a dot
                htmlFilepath += ".html";
                htmlFilename += ".html";
            }
            if (typeof components.Component === "string") {
                renderResult = _renderresult.default.fromStatic(components.Component);
                queryWithAutoExportWarn();
            } else {
                /**
         * This sets environment variable to be used at the time of static export by head.tsx.
         * Using this from process.env allows targeting SSR by calling
         * `process.env.__NEXT_OPTIMIZE_FONTS`.
         * TODO(prateekbh@): Remove this when experimental.optimizeFonts are being cleaned up.
         */ if (optimizeFonts) {
                    process.env.__NEXT_OPTIMIZE_FONTS = JSON.stringify(optimizeFonts);
                }
                if (optimizeCss) {
                    process.env.__NEXT_OPTIMIZE_CSS = JSON.stringify(true);
                }
                try {
                    renderResult = await renderMethod(req, res, page, query, // @ts-ignore
                    curRenderOpts);
                } catch (err) {
                    if (err.digest !== _nossrerror.NEXT_DYNAMIC_NO_SSR_CODE) {
                        throw err;
                    }
                }
            }
            results.ssgNotFound = renderResult == null ? void 0 : renderResult.metadata.isNotFound;
            const validateAmp = async (rawAmpHtml, ampPageName, validatorPath)=>{
                const validator = await _amphtmlvalidator.default.getInstance(validatorPath);
                const result = validator.validateString(rawAmpHtml);
                const errors = result.errors.filter((e)=>e.severity === "ERROR");
                const warnings = result.errors.filter((e)=>e.severity !== "ERROR");
                if (warnings.length || errors.length) {
                    results.ampValidations.push({
                        page: ampPageName,
                        result: {
                            errors,
                            warnings
                        }
                    });
                }
            };
            const html = renderResult && !renderResult.isNull ? renderResult.toUnchunkedString() : "";
            let ampRenderResult;
            if (inAmpMode && !curRenderOpts.ampSkipValidation) {
                if (!results.ssgNotFound) {
                    await validateAmp(html, path, curRenderOpts.ampValidatorPath);
                }
            } else if (hybridAmp) {
                // we need to render the AMP version
                let ampHtmlFilename = `${ampPath}${_path.sep}index.html`;
                if (!subFolders) {
                    ampHtmlFilename = `${ampPath}.html`;
                }
                const ampBaseDir = (0, _path.join)(outDir, (0, _path.dirname)(ampHtmlFilename));
                const ampHtmlFilepath = (0, _path.join)(outDir, ampHtmlFilename);
                try {
                    await _fs.promises.access(ampHtmlFilepath);
                } catch (_) {
                    // make sure it doesn't exist from manual mapping
                    try {
                        ampRenderResult = await renderMethod(req, res, page, // @ts-ignore
                        {
                            ...query,
                            amp: "1"
                        }, curRenderOpts);
                    } catch (err) {
                        if (err.digest !== _nossrerror.NEXT_DYNAMIC_NO_SSR_CODE) {
                            throw err;
                        }
                    }
                    const ampHtml = ampRenderResult && !ampRenderResult.isNull ? ampRenderResult.toUnchunkedString() : "";
                    if (!curRenderOpts.ampSkipValidation) {
                        await validateAmp(ampHtml, page + "?amp=1");
                    }
                    await _fs.promises.mkdir(ampBaseDir, {
                        recursive: true
                    });
                    await _fs.promises.writeFile(ampHtmlFilepath, ampHtml, "utf8");
                }
            }
            const metadata = (renderResult == null ? void 0 : renderResult.metadata) || (ampRenderResult == null ? void 0 : ampRenderResult.metadata) || {};
            if (metadata.pageData) {
                const dataFile = (0, _path.join)(pagesDataDir, htmlFilename.replace(/\.html$/, ".json"));
                await _fs.promises.mkdir((0, _path.dirname)(dataFile), {
                    recursive: true
                });
                await _fs.promises.writeFile(dataFile, JSON.stringify(metadata.pageData), "utf8");
                if (hybridAmp) {
                    await _fs.promises.writeFile(dataFile.replace(/\.json$/, ".amp.json"), JSON.stringify(metadata.pageData), "utf8");
                }
            }
            results.fromBuildExportRevalidate = metadata.revalidate;
            if (!results.ssgNotFound) {
                // don't attempt writing to disk if getStaticProps returned not found
                await _fs.promises.writeFile(htmlFilepath, html, "utf8");
            }
        } catch (error) {
            console.error(`\nError occurred prerendering page "${path}". Read more: https://nextjs.org/docs/messages/prerender-error\n` + ((0, _iserror.default)(error) && error.stack ? error.stack : error));
            results.error = true;
        }
        return {
            ...results,
            duration: Date.now() - start
        };
    });
}

//# sourceMappingURL=worker.js.map