"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.injectedClientEntries = void 0;
var _querystring = require("querystring");
var _webpack = require("next/dist/compiled/webpack/webpack");
var _constants = require("../../../shared/lib/constants");
var _utils = require("../loaders/utils");
var _normalizePagePath = require("../../../shared/lib/page-path/normalize-page-path");
var _denormalizePagePath = require("../../../shared/lib/page-path/denormalize-page-path");
var _onDemandEntryHandler = require("../../../server/dev/on-demand-entry-handler");
var _getPageStaticInfo = require("../../analysis/get-page-static-info");
var _constants1 = require("../../../lib/constants");
const PLUGIN_NAME = "ClientEntryPlugin";
const injectedClientEntries = new Map();
exports.injectedClientEntries = injectedClientEntries;
const regexCSS = /\.css$/;
class FlightClientEntryPlugin {
    dev = false;
    constructor(options){
        if (typeof options.dev === "boolean") {
            this.dev = options.dev;
        }
        this.isEdgeServer = options.isEdgeServer;
    }
    apply(compiler) {
        compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation, { normalModuleFactory  })=>{
            compilation.dependencyFactories.set(_webpack.webpack.dependencies.ModuleDependency, normalModuleFactory);
            compilation.dependencyTemplates.set(_webpack.webpack.dependencies.ModuleDependency, new _webpack.webpack.dependencies.NullDependency.Template());
        });
        compiler.hooks.finishMake.tapPromise(PLUGIN_NAME, (compilation)=>{
            return this.createClientEndpoints(compilation);
        });
    }
    async createClientEndpoints(compilation) {
        const context = this.context;
        const promises = [];
        // For each SC server compilation entry, we need to create its corresponding
        // client component entry.
        for (const [name, entry] of compilation.entries.entries()){
            var ref2, ref1;
            // Check if the page entry is a server component or not.
            const entryDependency = (ref2 = entry.dependencies) == null ? void 0 : ref2[0];
            const request = entryDependency == null ? void 0 : entryDependency.request;
            if (request && ((ref1 = entry.options) == null ? void 0 : ref1.layer) === "sc_server") {
                const visited = new Set();
                const clientComponentImports = [];
                function filterClientComponents(dependency) {
                    var ref;
                    const mod = compilation.moduleGraph.getResolvedModule(dependency);
                    if (!mod) return;
                    // Keep client imports as simple
                    // native or installed js module: -> raw request, e.g. next/head
                    // client js or css: -> user request
                    const rawRequest = mod.rawRequest || "";
                    const modRequest = !rawRequest.endsWith(".css") && !rawRequest.startsWith(".") && !rawRequest.startsWith("/") ? rawRequest : (ref = mod.resourceResolveData) == null ? void 0 : ref.path;
                    if (!modRequest || visited.has(modRequest)) return;
                    visited.add(modRequest);
                    if (_utils.clientComponentRegex.test(modRequest) || regexCSS.test(modRequest)) {
                        clientComponentImports.push(modRequest);
                    }
                    compilation.moduleGraph.getOutgoingConnections(mod).forEach((connection)=>{
                        filterClientComponents(connection.dependency);
                    });
                }
                // Traverse the module graph to find all client components.
                filterClientComponents(entryDependency);
                const entryModule = compilation.moduleGraph.getResolvedModule(entryDependency);
                const routeInfo = entryModule.buildInfo.route || {
                    page: (0, _denormalizePagePath).denormalizePagePath(name.replace(/^pages/, "")),
                    absolutePagePath: entryModule.resource
                };
                // Parse gSSP and gSP exports from the page source.
                const pageStaticInfo = this.isEdgeServer ? {} : await (0, _getPageStaticInfo).getPageStaticInfo({
                    pageFilePath: routeInfo.absolutePagePath,
                    nextConfig: {},
                    isDev: this.dev
                });
                const loaderOptions = {
                    modules: clientComponentImports,
                    runtime: this.isEdgeServer ? _constants1.SERVER_RUNTIME.edge : _constants1.SERVER_RUNTIME.nodejs,
                    ssr: pageStaticInfo.ssr,
                    // Adding name here to make the entry key unique.
                    name
                };
                const clientLoader = `next-flight-client-entry-loader?${(0, _querystring).stringify(loaderOptions)}!`;
                const clientSSRLoader = `next-flight-client-entry-loader?${(0, _querystring).stringify({
                    ...loaderOptions,
                    server: true
                })}!`;
                const bundlePath = "app" + (0, _normalizePagePath).normalizePagePath(routeInfo.page);
                // Inject the entry to the client compiler.
                if (this.dev) {
                    const pageKey = "client" + routeInfo.page;
                    if (!_onDemandEntryHandler.entries[pageKey]) {
                        _onDemandEntryHandler.entries[pageKey] = {
                            bundlePath,
                            absolutePagePath: routeInfo.absolutePagePath,
                            clientLoader,
                            dispose: false,
                            lastActiveTime: Date.now()
                        };
                        const invalidator = (0, _onDemandEntryHandler).getInvalidator();
                        if (invalidator) {
                            invalidator.invalidate();
                        }
                    }
                } else {
                    injectedClientEntries.set(bundlePath, `next-client-pages-loader?${(0, _querystring).stringify({
                        isServerComponent: true,
                        page: (0, _denormalizePagePath).denormalizePagePath(bundlePath.replace(/^pages/, "")),
                        absolutePagePath: clientLoader
                    })}!` + clientLoader);
                }
                // Inject the entry to the server compiler (__sc_client__).
                const clientComponentEntryDep = _webpack.webpack.EntryPlugin.createDependency(clientSSRLoader, {
                    name: name + _constants.NEXT_CLIENT_SSR_ENTRY_SUFFIX
                });
                promises.push(new Promise((res, rej)=>{
                    compilation.addEntry(context, clientComponentEntryDep, this.isEdgeServer ? {
                        name: name + _constants.NEXT_CLIENT_SSR_ENTRY_SUFFIX,
                        library: {
                            name: [
                                "self._CLIENT_ENTRY"
                            ],
                            type: "assign"
                        },
                        runtime: _constants.EDGE_RUNTIME_WEBPACK,
                        asyncChunks: false
                    } : {
                        name: name + _constants.NEXT_CLIENT_SSR_ENTRY_SUFFIX,
                        runtime: "webpack-runtime"
                    }, (err)=>{
                        if (err) {
                            rej(err);
                        } else {
                            res();
                        }
                    });
                }));
            }
        }
        await Promise.all(promises);
    }
}
exports.FlightClientEntryPlugin = FlightClientEntryPlugin;

//# sourceMappingURL=flight-client-entry-plugin.js.map