├── .eslintignore
├── .gitattributes
├── .npmignore
├── example
├── page-router
│ ├── src
│ │ ├── pages
│ │ │ ├── a
│ │ │ │ └── b.tsx
│ │ │ ├── 404.tsx
│ │ │ ├── _app.tsx
│ │ │ ├── api
│ │ │ │ └── hello.ts
│ │ │ ├── second.tsx
│ │ │ └── index.tsx
│ │ ├── constants.ts
│ │ ├── components
│ │ │ ├── sharedComponent.tsx
│ │ │ ├── injectDescription.tsx
│ │ │ └── header.tsx
│ │ └── styles
│ │ │ ├── globals.css
│ │ │ └── Home.module.css
│ ├── public
│ │ ├── favicon.ico
│ │ └── vercel.svg
│ ├── README.md
│ ├── .gitignore
│ ├── next.config.js
│ ├── package.json
│ ├── tsconfig.json
│ └── obfuscator-options.js
└── app-router
│ ├── .yarnrc.yml
│ ├── .vscode
│ ├── extensions.json
│ └── settings.json
│ ├── src
│ └── app
│ │ ├── favicon.ico
│ │ ├── layout.tsx
│ │ ├── client.tsx
│ │ ├── globals.css
│ │ ├── page.tsx
│ │ └── page.module.css
│ ├── .yarn
│ └── sdks
│ │ ├── integrations.yml
│ │ └── typescript
│ │ ├── package.json
│ │ ├── lib
│ │ ├── typescript.js
│ │ ├── tsc.js
│ │ ├── tsserver.js
│ │ └── tsserverlibrary.js
│ │ └── bin
│ │ ├── tsc
│ │ └── tsserver
│ ├── package.json
│ ├── public
│ ├── vercel.svg
│ └── next.svg
│ ├── next.config.js
│ ├── .gitignore
│ ├── tsconfig.json
│ ├── README.md
│ ├── yarn.lock
│ └── .pnp.loader.mjs
├── .eslintrc.json
├── .gitignore
├── tsconfig.json
├── .swcrc
├── src
├── debug.ts
├── type.ts
├── loader.ts
└── index.ts
├── LICENSE
├── package.json
└── README.md
/.eslintignore:
--------------------------------------------------------------------------------
1 | example
2 | *.js
3 | *.d.ts
4 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | example/* linguist-documentation
2 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | example
2 | src
3 | tsconfig.json
4 | .swcrc
5 | .git*
6 | .eslint*
7 |
--------------------------------------------------------------------------------
/example/page-router/src/pages/a/b.tsx:
--------------------------------------------------------------------------------
1 | export default function(){
2 | return
a
3 | }
--------------------------------------------------------------------------------
/example/app-router/.yarnrc.yml:
--------------------------------------------------------------------------------
1 | yarnPath: .yarn/releases/yarn-3.6.0.cjs
2 | nodeLinker: pnp
3 |
--------------------------------------------------------------------------------
/example/page-router/src/pages/404.tsx:
--------------------------------------------------------------------------------
1 | export default function C404(){
2 | return 404
3 | }
4 |
--------------------------------------------------------------------------------
/example/app-router/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "arcanis.vscode-zipfs"
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/example/page-router/src/constants.ts:
--------------------------------------------------------------------------------
1 | export const GitHubPageUrl = "https://github.com/mtripg6666tdr/nextjs-obfuscator";
2 |
--------------------------------------------------------------------------------
/example/app-router/src/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mtripg6666tdr/nextjs-obfuscator/HEAD/example/app-router/src/app/favicon.ico
--------------------------------------------------------------------------------
/example/page-router/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mtripg6666tdr/nextjs-obfuscator/HEAD/example/page-router/public/favicon.ico
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "@mtripg6666tdr/eslint-config/nodejs-typescript"
4 | ],
5 | "parserOptions": {
6 | "project": "./tsconfig.json"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/example/app-router/.yarn/sdks/integrations.yml:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by @yarnpkg/sdks.
2 | # Manual changes might be lost!
3 |
4 | integrations:
5 | - vscode
6 |
--------------------------------------------------------------------------------
/example/page-router/README.md:
--------------------------------------------------------------------------------
1 | This directory contains an example app that have been obfuscated by nextjs-obfuscator.
2 | Almost all of These files were generated by `create-next-app`.
3 |
--------------------------------------------------------------------------------
/example/app-router/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "search.exclude": {
3 | "**/.yarn": true,
4 | "**/.pnp.*": true
5 | },
6 | "typescript.tsdk": ".yarn/sdks/typescript/lib",
7 | "typescript.enablePromptUseWorkspaceTsdk": true
8 | }
9 |
--------------------------------------------------------------------------------
/example/page-router/src/components/sharedComponent.tsx:
--------------------------------------------------------------------------------
1 | import { AnimatePresence } from "framer-motion";
2 |
3 | export default function SharedComponent(){
4 | return (
5 |
6 | あいうえお
7 |
8 | );
9 | }
10 |
--------------------------------------------------------------------------------
/example/app-router/.yarn/sdks/typescript/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "typescript",
3 | "version": "5.2.2-sdk",
4 | "main": "./lib/typescript.js",
5 | "type": "commonjs",
6 | "bin": {
7 | "tsc": "./bin/tsc",
8 | "tsserver": "./bin/tsserver"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/example/page-router/src/pages/_app.tsx:
--------------------------------------------------------------------------------
1 | import '../styles/globals.css'
2 | import type { AppProps } from 'next/app'
3 | import ExampleHeader from '../components/header'
4 |
5 | function MyApp({ Component, pageProps }: AppProps) {
6 | return (
7 | <>
8 |
9 |
10 | >
11 | )
12 | }
13 |
14 | export default MyApp
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *node_modules
2 | index.js
3 | loader.js
4 | loader.d.ts
5 | type.js
6 | type.d.ts
7 | index.d.ts
8 | debug.js
9 | debug.d.ts
10 | *.temp.*
11 | *.tmp.*
12 | *.temp
13 | *.tmp
14 | *.log
15 |
16 | # VSCode
17 | **/.vscode/*
18 | !**/.vscode/settings.json
19 | !**/.vscode/tasks.json
20 | !**/.vscode/launch.json
21 | !**/.vscode/extensions.json
22 | !**/.vscode/*.code-snippets
23 |
--------------------------------------------------------------------------------
/example/page-router/src/pages/api/hello.ts:
--------------------------------------------------------------------------------
1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction
2 | import type { NextApiRequest, NextApiResponse } from 'next'
3 |
4 | type Data = {
5 | name: string
6 | }
7 |
8 | export default function handler(
9 | req: NextApiRequest,
10 | res: NextApiResponse
11 | ) {
12 | res.status(200).json({ name: 'John Doe' })
13 | }
14 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "@tsconfig/node16/tsconfig.json"
4 | ],
5 | "compilerOptions": {
6 | "allowSyntheticDefaultImports": true,
7 | "esModuleInterop": true,
8 | "strict": true,
9 | "outDir": "./",
10 | "declaration": true,
11 | "declarationDir": ".",
12 | "emitDeclarationOnly": true,
13 | "skipLibCheck": true
14 | },
15 | "include": [
16 | "./src/**/*.ts"
17 | ],
18 | "exclude": [
19 | "**/node_modules"
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/example/app-router/src/app/layout.tsx:
--------------------------------------------------------------------------------
1 | import './globals.css'
2 | import { Inter } from 'next/font/google'
3 |
4 | const inter = Inter({ subsets: ['latin'] })
5 |
6 | export const metadata = {
7 | title: 'Create Next App',
8 | description: 'Generated by create next app',
9 | }
10 |
11 | export default function RootLayout({
12 | children,
13 | }: {
14 | children: React.ReactNode
15 | }) {
16 | return (
17 |
18 | {children}
19 |
20 | )
21 | }
22 |
--------------------------------------------------------------------------------
/example/app-router/src/app/client.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { useEffect } from "react";
4 |
5 | export default function Alerter(){
6 | useEffect(() => {
7 | let timeout: any = setTimeout(() => {
8 | window.alert("a");
9 | timeout = null;
10 | }, 5e3);
11 | return () => timeout && clearTimeout(timeout);
12 | }, []);
13 |
14 | return (
15 | <>
16 | client component
17 | (env: NEXT_PUBLIC_FOOBAR: {process.env.NEXT_PUBLIC_FOOBAR})
18 | >
19 | )
20 | }
21 |
--------------------------------------------------------------------------------
/example/page-router/src/components/injectDescription.tsx:
--------------------------------------------------------------------------------
1 | import Link from "next/link";
2 | import { GitHubPageUrl } from "../constants";
3 |
4 | export default function InjectDescription(){
5 | return (
6 | <>
7 | *This website is obfuscated by nextjs-obfuscator powered by javascript-obfuscator.
11 |
12 | Go to 2nd page.
13 |
14 | >
15 | )
16 | }
17 |
--------------------------------------------------------------------------------
/.swcrc:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/swcrc",
3 | "jsc": {
4 | "parser": {
5 | "syntax": "typescript",
6 | "tsx": false,
7 | "decorators": false,
8 | "dynamicImport": false
9 | },
10 | "transform": {},
11 | "target": "es2021",
12 | "loose": false,
13 | "externalHelpers": false,
14 | // Requires v1.2.50 or upper and requires target to be es2016 or upper.
15 | "keepClassNames": false
16 | },
17 | "minify": false,
18 | "module": {
19 | "type": "commonjs"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/example/page-router/src/styles/globals.css:
--------------------------------------------------------------------------------
1 | html,
2 | body {
3 | padding: 0;
4 | margin: 0;
5 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
6 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
7 | }
8 |
9 | a {
10 | color: inherit;
11 | text-decoration: none;
12 | }
13 |
14 | * {
15 | box-sizing: border-box;
16 | }
17 |
18 | @media (prefers-color-scheme: dark) {
19 | html {
20 | color-scheme: dark;
21 | }
22 | body {
23 | color: white;
24 | background: black;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/example/page-router/src/pages/second.tsx:
--------------------------------------------------------------------------------
1 | import Link from "next/link";
2 | import SharedComponent from "../components/sharedComponent";
3 |
4 | export default function SecondPage(){
5 | const style = {
6 | textAlign: "center" as const,
7 | fontSize: "1.4rem",
8 | };
9 |
10 | return (
11 |
12 |
This is the 2nd test page!
13 |
14 |
15 |
16 | Return to top
17 |
18 |
19 |
20 | )
21 | }
22 |
--------------------------------------------------------------------------------
/example/page-router/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /out/
14 |
15 | # production
16 | /build
17 |
18 | # misc
19 | .DS_Store
20 | *.pem
21 |
22 | # debug
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 | .pnpm-debug.log*
27 |
28 | # local env files
29 | .env*.local
30 |
31 | # vercel
32 | .vercel
33 |
34 | # typescript
35 | *.tsbuildinfo
36 | next-env.d.ts
37 |
--------------------------------------------------------------------------------
/src/debug.ts:
--------------------------------------------------------------------------------
1 | import fs from "fs";
2 |
3 | export function writeDownWebpackConfig(config: any){
4 | const stringified = JSON.stringify(config, jsonStringifyReplacer, " ");
5 |
6 | fs.writeFileSync(`./webpack-config-${Date.now()}.temp.json`, stringified);
7 | }
8 |
9 | function jsonStringifyReplacer(_key: string, value: any){
10 | if(value instanceof RegExp){
11 | return { "[__type]": "RegExp", value: value.toString() };
12 | }else if(typeof value === "bigint"){
13 | return { "[__type": "BigInt", value: value.toString() };
14 | }
15 |
16 | return value;
17 | }
18 |
--------------------------------------------------------------------------------
/example/page-router/next.config.js:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | const obfuscatorOptions = require("./obfuscator-options");
3 | const withNextJSObfuscatorPlugin = require("../..")(obfuscatorOptions, {
4 | log: true,
5 | obfuscateFiles: {
6 | buildManifest: true,
7 | ssgManifest: true,
8 | webpack: true,
9 | additionalModules: ["es6-object-assign"],
10 | },
11 | });
12 |
13 | /** @type {import('next').NextConfig} */
14 | module.exports = withNextJSObfuscatorPlugin({
15 | productionBrowserSourceMaps: true,
16 | eslint: {
17 | ignoreDuringBuilds: true,
18 | }
19 | });
20 |
--------------------------------------------------------------------------------
/example/app-router/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example-nextjs-obfuscated-app-with-app-router",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint"
10 | },
11 | "dependencies": {
12 | "next": "15.0.2",
13 | "react": "18.3.1",
14 | "react-dom": "18.3.1",
15 | "typescript": "5.6.3"
16 | },
17 | "devDependencies": {
18 | "@types/node": "22.8.7",
19 | "@types/react": "18.3.12",
20 | "@types/react-dom": "^18.3.1"
21 | },
22 | "packageManager": "yarn@3.6.0"
23 | }
24 |
--------------------------------------------------------------------------------
/example/app-router/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/example/app-router/next.config.js:
--------------------------------------------------------------------------------
1 | const withNextjsObfuscator = require("../..")(
2 | require("../page-router/obfuscator-options"),
3 | {
4 | log: true,
5 | // writeConfig: true,
6 | obfuscateFiles: {
7 | buildManifest: true,
8 | ssgManifest: true,
9 | webpack: true,
10 | additionalModules: ["es6-object-assign"],
11 | },
12 | }
13 | );
14 |
15 | /** @type {import('next').NextConfig} */
16 | const nextConfig = {
17 | eslint: {
18 | ignoreDuringBuilds: true,
19 | },
20 | env: {
21 | NEXT_PUBLIC_FOOBAR: "foobar",
22 | },
23 | };
24 |
25 | module.exports = withNextjsObfuscator(nextConfig);
26 |
--------------------------------------------------------------------------------
/example/page-router/src/components/header.tsx:
--------------------------------------------------------------------------------
1 | import { GitHubPageUrl } from "../constants";
2 |
3 | export default function ExampleHeader(){
4 | return (
5 |
11 | An example obfuscated Next.js app
12 |
19 |
20 | );
21 | }
22 |
--------------------------------------------------------------------------------
/example/app-router/.yarn/sdks/typescript/lib/typescript.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | const {existsSync} = require(`fs`);
4 | const {createRequire} = require(`module`);
5 | const {resolve} = require(`path`);
6 |
7 | const relPnpApiPath = "../../../../.pnp.cjs";
8 |
9 | const absPnpApiPath = resolve(__dirname, relPnpApiPath);
10 | const absRequire = createRequire(absPnpApiPath);
11 |
12 | if (existsSync(absPnpApiPath)) {
13 | if (!process.versions.pnp) {
14 | // Setup the environment to be able to require typescript
15 | require(absPnpApiPath).setup();
16 | }
17 | }
18 |
19 | // Defer to the real typescript your application uses
20 | module.exports = absRequire(`typescript`);
21 |
--------------------------------------------------------------------------------
/example/app-router/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /out/
14 |
15 | # production
16 | /build
17 |
18 | # misc
19 | .DS_Store
20 | *.pem
21 |
22 | # debug
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 |
27 | # local env files
28 | .env*.local
29 |
30 | # vercel
31 | .vercel
32 |
33 | # typescript
34 | *.tsbuildinfo
35 | next-env.d.ts
36 |
37 | # Yarn (without zero-install)
38 | .yarn/*
39 | !.yarn/releases
40 | !.yarn/patches
41 | !.yarn/plugins
42 | !.yarn/sdks
43 | !.yarn/versions
44 |
--------------------------------------------------------------------------------
/example/app-router/.yarn/sdks/typescript/bin/tsc:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | const {existsSync} = require(`fs`);
4 | const {createRequire} = require(`module`);
5 | const {resolve} = require(`path`);
6 |
7 | const relPnpApiPath = "../../../../.pnp.cjs";
8 |
9 | const absPnpApiPath = resolve(__dirname, relPnpApiPath);
10 | const absRequire = createRequire(absPnpApiPath);
11 |
12 | if (existsSync(absPnpApiPath)) {
13 | if (!process.versions.pnp) {
14 | // Setup the environment to be able to require typescript/bin/tsc
15 | require(absPnpApiPath).setup();
16 | }
17 | }
18 |
19 | // Defer to the real typescript/bin/tsc your application uses
20 | module.exports = absRequire(`typescript/bin/tsc`);
21 |
--------------------------------------------------------------------------------
/example/app-router/.yarn/sdks/typescript/lib/tsc.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | const {existsSync} = require(`fs`);
4 | const {createRequire} = require(`module`);
5 | const {resolve} = require(`path`);
6 |
7 | const relPnpApiPath = "../../../../.pnp.cjs";
8 |
9 | const absPnpApiPath = resolve(__dirname, relPnpApiPath);
10 | const absRequire = createRequire(absPnpApiPath);
11 |
12 | if (existsSync(absPnpApiPath)) {
13 | if (!process.versions.pnp) {
14 | // Setup the environment to be able to require typescript/lib/tsc.js
15 | require(absPnpApiPath).setup();
16 | }
17 | }
18 |
19 | // Defer to the real typescript/lib/tsc.js your application uses
20 | module.exports = absRequire(`typescript/lib/tsc.js`);
21 |
--------------------------------------------------------------------------------
/example/app-router/.yarn/sdks/typescript/bin/tsserver:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | const {existsSync} = require(`fs`);
4 | const {createRequire} = require(`module`);
5 | const {resolve} = require(`path`);
6 |
7 | const relPnpApiPath = "../../../../.pnp.cjs";
8 |
9 | const absPnpApiPath = resolve(__dirname, relPnpApiPath);
10 | const absRequire = createRequire(absPnpApiPath);
11 |
12 | if (existsSync(absPnpApiPath)) {
13 | if (!process.versions.pnp) {
14 | // Setup the environment to be able to require typescript/bin/tsserver
15 | require(absPnpApiPath).setup();
16 | }
17 | }
18 |
19 | // Defer to the real typescript/bin/tsserver your application uses
20 | module.exports = absRequire(`typescript/bin/tsserver`);
21 |
--------------------------------------------------------------------------------
/example/page-router/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example-nextjs-obfuscated-app",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "cross-env NODE_OPTIONS='--inspect' next dev",
7 | "build": "next build",
8 | "start": "cross-env NODE_OPTIONS='--inspect' next start",
9 | "lint": "next lint"
10 | },
11 | "dependencies": {
12 | "cross-env": "^7.0.3",
13 | "framer-motion": "^11.11.11",
14 | "next": "^15.0.2",
15 | "react": "^18.3.1",
16 | "react-dom": "^18.3.1"
17 | },
18 | "devDependencies": {
19 | "@types/node": "22.8.7",
20 | "@types/react": "18.3.12",
21 | "@types/react-dom": "18.3.1",
22 | "javascript-obfuscator": "^4.1.1",
23 | "typescript": "5.6.3"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/example/page-router/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": false,
6 | "skipLibCheck": true,
7 | "strict": false,
8 | "forceConsistentCasingInFileNames": true,
9 | "noEmit": true,
10 | "noImplicitAny": true,
11 | "noImplicitReturns": true,
12 | "noImplicitThis": true,
13 | "esModuleInterop": true,
14 | "allowSyntheticDefaultImports": true,
15 | "module": "esnext",
16 | "moduleResolution": "node",
17 | "resolveJsonModule": true,
18 | "isolatedModules": true,
19 | "jsx": "preserve",
20 | "incremental": true
21 | },
22 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
23 | "exclude": ["node_modules"]
24 | }
25 |
--------------------------------------------------------------------------------
/example/page-router/obfuscator-options.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | compact: true,
3 | controlFlowFlattening: false,
4 | controlFlowFlatteningThreshold: 0.75,
5 | disableConsoleOutput: false,
6 | domainLock: [
7 | ".usamyon.moe",
8 | "localhost",
9 | ],
10 | domainLockRedirectUrl: "about:blank",
11 | identifierNamesCache: null,
12 | identifierNamesGenerator: "mangled",
13 | optionsPreset: "low-obfuscation",
14 | rotateStringArray: true,
15 | seed: 0,
16 | selfDefending: true,
17 | shuffleStringArray: true,
18 | simplify: true,
19 | splitStrings: true,
20 | splitStringsChunkLength: 10,
21 | stringArray: true,
22 | stringArrayIndexesType: [
23 | "hexadecimal-number"
24 | ],
25 | target: "browser",
26 | sourceMap: true,
27 | }
28 |
--------------------------------------------------------------------------------
/example/app-router/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "forceConsistentCasingInFileNames": true,
9 | "noEmit": true,
10 | "esModuleInterop": true,
11 | "module": "esnext",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "jsx": "preserve",
16 | "incremental": true,
17 | "plugins": [
18 | {
19 | "name": "next"
20 | }
21 | ],
22 | "paths": {
23 | "@/*": ["./src/*"]
24 | }
25 | },
26 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
27 | "exclude": ["node_modules"]
28 | }
29 |
--------------------------------------------------------------------------------
/example/page-router/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Redistribution and use in source and binary forms, with or without
2 | modification, are permitted provided that the following conditions are met:
3 |
4 | * Redistributions of source code must retain the above copyright
5 | notice, this list of conditions and the following disclaimer.
6 | * Redistributions in binary form must reproduce the above copyright
7 | notice, this list of conditions and the following disclaimer in the
8 | documentation and/or other materials provided with the distribution.
9 |
10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
11 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
14 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
15 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
16 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
17 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
18 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
19 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
/example/app-router/public/next.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/example/app-router/README.md:
--------------------------------------------------------------------------------
1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
2 |
3 | ## Getting Started
4 |
5 | First, run the development server:
6 |
7 | ```bash
8 | npm run dev
9 | # or
10 | yarn dev
11 | # or
12 | pnpm dev
13 | ```
14 |
15 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
16 |
17 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
18 |
19 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
20 |
21 | ## Learn More
22 |
23 | To learn more about Next.js, take a look at the following resources:
24 |
25 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
26 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
27 |
28 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
29 |
30 | ## Deploy on Vercel
31 |
32 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
33 |
34 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
35 |
--------------------------------------------------------------------------------
/src/type.ts:
--------------------------------------------------------------------------------
1 | import type { ObfuscatorOptions } from "javascript-obfuscator";
2 |
3 | type OmitKeys = T & { [key in U]: never };
4 |
5 | export type PluginOptions = {
6 | enabled: boolean | "detect",
7 | /**
8 | * determines which files to be obfuscated
9 | */
10 | patterns: string[],
11 | /**
12 | * Additional files to be obfuscated
13 | */
14 | obfuscateFiles: Partial<{
15 | buildManifest: boolean,
16 | ssgManifest: boolean,
17 | webpack: boolean,
18 | additionalModules: string[],
19 | }>,
20 | /**
21 | * indicates whether the plugin logs to console
22 | */
23 | log: boolean,
24 | };
25 |
26 | export type ObjectWithUnconstantString> = {
27 | [key in keyof T]: Required[key] extends string
28 | ? string
29 | : Required[key] extends number
30 | ? number
31 | : Required[key] extends string[]
32 | ? string[]
33 | : Required[key] extends number[]
34 | ? number[]
35 | : Required[key] extends Record
36 | ? Partial>
37 | : T[key]
38 | };
39 |
40 | export type NextjsObfuscatorOptions = OmitKeys<
41 | ObfuscatorOptions,
42 | | "inputFileName"
43 | | "sourceMapBaseUrl"
44 | | "sourceMapFileName"
45 | | "sourceMapMode"
46 | | "sourceMapSourcesMode"
47 | >;
48 |
49 | export const LoggerSymbol = Symbol("NextJsObfuscatorLogger");
50 | export const PublicEnvVariablesSymbol = Symbol("NextJsObfuscatorPublicEnvVariables");
51 |
52 | export type InternalNextjsObfuscatorOptions = NextjsObfuscatorOptions & {
53 | [LoggerSymbol]: (...messages: any[]) => void,
54 | [PublicEnvVariablesSymbol]: Map,
55 | };
56 |
--------------------------------------------------------------------------------
/src/loader.ts:
--------------------------------------------------------------------------------
1 | import type { InternalNextjsObfuscatorOptions } from "./type";
2 | import type { RawSourceMap } from "source-map";
3 | import type webpack from "webpack";
4 |
5 | import * as path from "path";
6 | // import fs from "fs";
7 |
8 | import { obfuscate } from "javascript-obfuscator";
9 | import { transfer as transferSourceMap } from "multi-stage-sourcemap";
10 |
11 | import { LoggerSymbol, PublicEnvVariablesSymbol } from "./type";
12 |
13 | function loader(this: webpack.LoaderContext, source: string, map: RawSourceMap){
14 | const moduleRelativePath = path.relative(this.rootContext, this.resourcePath);
15 | const options = this.getOptions();
16 | const logger = options[LoggerSymbol];
17 | const publicEnvVariables = options[PublicEnvVariablesSymbol];
18 | const sourceMapRequired = options.sourceMap;
19 |
20 | const sortedEntries = Array.from(publicEnvVariables.entries())
21 | .sort(([keyA], [keyB]) => keyB.length - keyA.length);
22 |
23 | for (const [key, value] of sortedEntries){
24 | source = source.replaceAll(key, value);
25 | }
26 |
27 | const finalOptions = Object.assign(options, {
28 | ignoreRequireImports: true,
29 | inputFileName: moduleRelativePath,
30 | sourceMapMode: "separate",
31 | });
32 |
33 | // obfuscation
34 | const obfuscationResult = obfuscate(source, finalOptions);
35 | const obfuscated = obfuscationResult.getObfuscatedCode();
36 |
37 | logger("Obfuscated:", moduleRelativePath, source.length, "->", obfuscated.length);
38 |
39 | // eslint-disable-next-line @typescript-eslint/init-declarations
40 | let sourceMap: string | undefined;
41 | if(map && sourceMapRequired){
42 | sourceMap = transferSourceMap({
43 | fromSourceMap: obfuscationResult.getSourceMap(),
44 | toSourceMap: map,
45 | });
46 | }
47 |
48 | this.callback(null, obfuscated, sourceMap);
49 | }
50 |
51 | export = loader;
52 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nextjs-obfuscator",
3 | "version": "3.1.0",
4 | "description": "javascript obfuscator plugin for next.js",
5 | "main": "./index.js",
6 | "types": "./index.d.ts",
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1",
9 | "build": "swc -d . ./src --strip-leading-paths && tsc",
10 | "watch": "swc -w -d . ./src --strip-leading-paths",
11 | "cleanup": "rimraf index.js index.d.ts loader.js loader.d.ts type.js type.d.ts debug.js debug.d.ts",
12 | "lint": "eslint ."
13 | },
14 | "keywords": [
15 | "obfuscator",
16 | "obfuscation",
17 | "code protection",
18 | "javascript obfuscator",
19 | "js obfuscator",
20 | "next obfuscator",
21 | "next.js obfuscator",
22 | "nextjs",
23 | "next",
24 | "obfuscation",
25 | "plugin",
26 | "obfuscate"
27 | ],
28 | "author": "mtripg6666tdr",
29 | "license": "BSD-2-Clause",
30 | "dependencies": {
31 | "minimatch": "^9",
32 | "multi-stage-sourcemap": "^0.3.1",
33 | "safe-traverse": "^0.2.1",
34 | "source-map": "^0.7.4"
35 | },
36 | "devDependencies": {
37 | "@mtripg6666tdr/eslint-config": "^3.0.19",
38 | "@swc/cli": "^0.5.0",
39 | "@swc/core": "^1.8.0",
40 | "@tsconfig/node16": "^16.1.3",
41 | "@types/loader-utils": "^2.0.6",
42 | "@types/multi-stage-sourcemap": "^0.3.4",
43 | "@types/react": "^18.3.12",
44 | "@types/react-dom": "^18.3.1",
45 | "chokidar": "^3.6.0",
46 | "eslint": "^8.54.0",
47 | "javascript-obfuscator": "*",
48 | "next": "*",
49 | "rimraf": "^6.0.1",
50 | "typescript": "^5.6.3",
51 | "webpack": "^5.96.1"
52 | },
53 | "peerDependencies": {
54 | "javascript-obfuscator": "^4.0.0",
55 | "next": "^13.0.0 || ^14.0.0 || ^15.0.0"
56 | },
57 | "engines": {
58 | "node": ">=16.14.0"
59 | },
60 | "repository": {
61 | "type": "git",
62 | "url": "git+https://github.com/mtripg6666tdr/nextjs-obfuscator.git"
63 | },
64 | "bugs": {
65 | "url": "https://github.com/mtripg6666tdr/nextjs-obfuscator/issues"
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/example/page-router/src/styles/Home.module.css:
--------------------------------------------------------------------------------
1 | .container {
2 | padding: 0 2rem;
3 | }
4 |
5 | .main {
6 | min-height: 100vh;
7 | padding: 4rem 0;
8 | flex: 1;
9 | display: flex;
10 | flex-direction: column;
11 | justify-content: center;
12 | align-items: center;
13 | }
14 |
15 | .footer {
16 | display: flex;
17 | flex: 1;
18 | padding: 2rem 0;
19 | border-top: 1px solid #eaeaea;
20 | justify-content: center;
21 | align-items: center;
22 | }
23 |
24 | .footer a {
25 | display: flex;
26 | justify-content: center;
27 | align-items: center;
28 | flex-grow: 1;
29 | }
30 |
31 | .title a {
32 | color: #0070f3;
33 | text-decoration: none;
34 | }
35 |
36 | .title a:hover,
37 | .title a:focus,
38 | .title a:active {
39 | text-decoration: underline;
40 | }
41 |
42 | .title {
43 | margin: 0;
44 | line-height: 1.15;
45 | font-size: 4rem;
46 | }
47 |
48 | .title,
49 | .description {
50 | text-align: center;
51 | }
52 |
53 | .description {
54 | margin: 4rem 0;
55 | line-height: 1.5;
56 | font-size: 1.5rem;
57 | }
58 |
59 | .code {
60 | background: #fafafa;
61 | border-radius: 5px;
62 | padding: 0.75rem;
63 | font-size: 1.1rem;
64 | font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
65 | Bitstream Vera Sans Mono, Courier New, monospace;
66 | }
67 |
68 | .grid {
69 | display: flex;
70 | align-items: center;
71 | justify-content: center;
72 | flex-wrap: wrap;
73 | max-width: 800px;
74 | }
75 |
76 | .card {
77 | margin: 1rem;
78 | padding: 1.5rem;
79 | text-align: left;
80 | color: inherit;
81 | text-decoration: none;
82 | border: 1px solid #eaeaea;
83 | border-radius: 10px;
84 | transition: color 0.15s ease, border-color 0.15s ease;
85 | max-width: 300px;
86 | }
87 |
88 | .card:hover,
89 | .card:focus,
90 | .card:active {
91 | color: #0070f3;
92 | border-color: #0070f3;
93 | }
94 |
95 | .card h2 {
96 | margin: 0 0 1rem 0;
97 | font-size: 1.5rem;
98 | }
99 |
100 | .card p {
101 | margin: 0;
102 | font-size: 1.25rem;
103 | line-height: 1.5;
104 | }
105 |
106 | .logo {
107 | height: 1em;
108 | margin-left: 0.5rem;
109 | }
110 |
111 | @media (max-width: 600px) {
112 | .grid {
113 | width: 100%;
114 | flex-direction: column;
115 | }
116 | }
117 |
118 | @media (prefers-color-scheme: dark) {
119 | .card,
120 | .footer {
121 | border-color: #222;
122 | }
123 | .code {
124 | background: #111;
125 | }
126 | .logo img {
127 | filter: invert(1);
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/example/app-router/src/app/globals.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --max-width: 1100px;
3 | --border-radius: 12px;
4 | --font-mono: ui-monospace, Menlo, Monaco, 'Cascadia Mono', 'Segoe UI Mono',
5 | 'Roboto Mono', 'Oxygen Mono', 'Ubuntu Monospace', 'Source Code Pro',
6 | 'Fira Mono', 'Droid Sans Mono', 'Courier New', monospace;
7 |
8 | --foreground-rgb: 0, 0, 0;
9 | --background-start-rgb: 214, 219, 220;
10 | --background-end-rgb: 255, 255, 255;
11 |
12 | --primary-glow: conic-gradient(
13 | from 180deg at 50% 50%,
14 | #16abff33 0deg,
15 | #0885ff33 55deg,
16 | #54d6ff33 120deg,
17 | #0071ff33 160deg,
18 | transparent 360deg
19 | );
20 | --secondary-glow: radial-gradient(
21 | rgba(255, 255, 255, 1),
22 | rgba(255, 255, 255, 0)
23 | );
24 |
25 | --tile-start-rgb: 239, 245, 249;
26 | --tile-end-rgb: 228, 232, 233;
27 | --tile-border: conic-gradient(
28 | #00000080,
29 | #00000040,
30 | #00000030,
31 | #00000020,
32 | #00000010,
33 | #00000010,
34 | #00000080
35 | );
36 |
37 | --callout-rgb: 238, 240, 241;
38 | --callout-border-rgb: 172, 175, 176;
39 | --card-rgb: 180, 185, 188;
40 | --card-border-rgb: 131, 134, 135;
41 | }
42 |
43 | @media (prefers-color-scheme: dark) {
44 | :root {
45 | --foreground-rgb: 255, 255, 255;
46 | --background-start-rgb: 0, 0, 0;
47 | --background-end-rgb: 0, 0, 0;
48 |
49 | --primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0));
50 | --secondary-glow: linear-gradient(
51 | to bottom right,
52 | rgba(1, 65, 255, 0),
53 | rgba(1, 65, 255, 0),
54 | rgba(1, 65, 255, 0.3)
55 | );
56 |
57 | --tile-start-rgb: 2, 13, 46;
58 | --tile-end-rgb: 2, 5, 19;
59 | --tile-border: conic-gradient(
60 | #ffffff80,
61 | #ffffff40,
62 | #ffffff30,
63 | #ffffff20,
64 | #ffffff10,
65 | #ffffff10,
66 | #ffffff80
67 | );
68 |
69 | --callout-rgb: 20, 20, 20;
70 | --callout-border-rgb: 108, 108, 108;
71 | --card-rgb: 100, 100, 100;
72 | --card-border-rgb: 200, 200, 200;
73 | }
74 | }
75 |
76 | * {
77 | box-sizing: border-box;
78 | padding: 0;
79 | margin: 0;
80 | }
81 |
82 | html,
83 | body {
84 | max-width: 100vw;
85 | overflow-x: hidden;
86 | }
87 |
88 | body {
89 | color: rgb(var(--foreground-rgb));
90 | background: linear-gradient(
91 | to bottom,
92 | transparent,
93 | rgb(var(--background-end-rgb))
94 | )
95 | rgb(var(--background-start-rgb));
96 | }
97 |
98 | a {
99 | color: inherit;
100 | text-decoration: none;
101 | }
102 |
103 | @media (prefers-color-scheme: dark) {
104 | html {
105 | color-scheme: dark;
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/example/page-router/src/pages/index.tsx:
--------------------------------------------------------------------------------
1 | import type { NextPage } from 'next'
2 | import Head from 'next/head'
3 | import Image from 'next/image'
4 | import InjectDescription from '../components/injectDescription'
5 | import styles from '../styles/Home.module.css'
6 | import Shared from "../components/sharedComponent";
7 | // this is just a test for module obfuscation
8 | // @ts-ignore
9 | import object from "es6-object-assign";
10 | console.log(object);
11 |
12 | const Home: NextPage = () => {
13 | return (
14 |
15 |
16 |
Create Next App
17 |
18 |
19 |
20 |
21 |
22 |
23 | Welcome to Next.js!
24 |
25 |
26 |
27 |
28 |
29 | Get started by editing{' '}
30 | pages/index.tsx
31 |
32 |
33 |
62 |
63 |
64 |
65 |
66 |
78 |
79 | )
80 | }
81 |
82 | export default Home
83 |
--------------------------------------------------------------------------------
/example/app-router/src/app/page.tsx:
--------------------------------------------------------------------------------
1 | import Image from 'next/image'
2 | import styles from './page.module.css'
3 | import Alerter from './client'
4 |
5 | export default function Home() {
6 | return (
7 |
8 |
9 |
10 | Get started by editing
11 | src/app/page.tsx
12 |
13 |
14 |
31 |
32 |
33 |
34 |
42 |
43 |
44 |
95 |
96 | )
97 | }
98 |
--------------------------------------------------------------------------------
/example/app-router/src/app/page.module.css:
--------------------------------------------------------------------------------
1 | .main {
2 | display: flex;
3 | flex-direction: column;
4 | justify-content: space-between;
5 | align-items: center;
6 | padding: 6rem;
7 | min-height: 100vh;
8 | }
9 |
10 | .description {
11 | display: inherit;
12 | justify-content: inherit;
13 | align-items: inherit;
14 | font-size: 0.85rem;
15 | max-width: var(--max-width);
16 | width: 100%;
17 | z-index: 2;
18 | font-family: var(--font-mono);
19 | }
20 |
21 | .description a {
22 | display: flex;
23 | justify-content: center;
24 | align-items: center;
25 | gap: 0.5rem;
26 | }
27 |
28 | .description p {
29 | position: relative;
30 | margin: 0;
31 | padding: 1rem;
32 | background-color: rgba(var(--callout-rgb), 0.5);
33 | border: 1px solid rgba(var(--callout-border-rgb), 0.3);
34 | border-radius: var(--border-radius);
35 | }
36 |
37 | .code {
38 | font-weight: 700;
39 | font-family: var(--font-mono);
40 | }
41 |
42 | .grid {
43 | display: grid;
44 | grid-template-columns: repeat(4, minmax(25%, auto));
45 | width: var(--max-width);
46 | max-width: 100%;
47 | }
48 |
49 | .card {
50 | padding: 1rem 1.2rem;
51 | border-radius: var(--border-radius);
52 | background: rgba(var(--card-rgb), 0);
53 | border: 1px solid rgba(var(--card-border-rgb), 0);
54 | transition: background 200ms, border 200ms;
55 | }
56 |
57 | .card span {
58 | display: inline-block;
59 | transition: transform 200ms;
60 | }
61 |
62 | .card h2 {
63 | font-weight: 600;
64 | margin-bottom: 0.7rem;
65 | }
66 |
67 | .card p {
68 | margin: 0;
69 | opacity: 0.6;
70 | font-size: 0.9rem;
71 | line-height: 1.5;
72 | max-width: 30ch;
73 | }
74 |
75 | .center {
76 | display: flex;
77 | justify-content: center;
78 | align-items: center;
79 | position: relative;
80 | padding: 4rem 0;
81 | }
82 |
83 | .center::before {
84 | background: var(--secondary-glow);
85 | border-radius: 50%;
86 | width: 480px;
87 | height: 360px;
88 | margin-left: -400px;
89 | }
90 |
91 | .center::after {
92 | background: var(--primary-glow);
93 | width: 240px;
94 | height: 180px;
95 | z-index: -1;
96 | }
97 |
98 | .center::before,
99 | .center::after {
100 | content: '';
101 | left: 50%;
102 | position: absolute;
103 | filter: blur(45px);
104 | transform: translateZ(0);
105 | }
106 |
107 | .logo {
108 | position: relative;
109 | }
110 | /* Enable hover only on non-touch devices */
111 | @media (hover: hover) and (pointer: fine) {
112 | .card:hover {
113 | background: rgba(var(--card-rgb), 0.1);
114 | border: 1px solid rgba(var(--card-border-rgb), 0.15);
115 | }
116 |
117 | .card:hover span {
118 | transform: translateX(4px);
119 | }
120 | }
121 |
122 | @media (prefers-reduced-motion) {
123 | .card:hover span {
124 | transform: none;
125 | }
126 | }
127 |
128 | /* Mobile */
129 | @media (max-width: 700px) {
130 | .content {
131 | padding: 4rem;
132 | }
133 |
134 | .grid {
135 | grid-template-columns: 1fr;
136 | margin-bottom: 120px;
137 | max-width: 320px;
138 | text-align: center;
139 | }
140 |
141 | .card {
142 | padding: 1rem 2.5rem;
143 | }
144 |
145 | .card h2 {
146 | margin-bottom: 0.5rem;
147 | }
148 |
149 | .center {
150 | padding: 8rem 0 6rem;
151 | }
152 |
153 | .center::before {
154 | transform: none;
155 | height: 300px;
156 | }
157 |
158 | .description {
159 | font-size: 0.8rem;
160 | }
161 |
162 | .description a {
163 | padding: 1rem;
164 | }
165 |
166 | .description p,
167 | .description div {
168 | display: flex;
169 | justify-content: center;
170 | position: fixed;
171 | width: 100%;
172 | }
173 |
174 | .description p {
175 | align-items: center;
176 | inset: 0 0 auto;
177 | padding: 2rem 1rem 1.4rem;
178 | border-radius: 0;
179 | border: none;
180 | border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25);
181 | background: linear-gradient(
182 | to bottom,
183 | rgba(var(--background-start-rgb), 1),
184 | rgba(var(--callout-rgb), 0.5)
185 | );
186 | background-clip: padding-box;
187 | backdrop-filter: blur(24px);
188 | }
189 |
190 | .description div {
191 | align-items: flex-end;
192 | pointer-events: none;
193 | inset: auto 0 0;
194 | padding: 2rem;
195 | height: 200px;
196 | background: linear-gradient(
197 | to bottom,
198 | transparent 0%,
199 | rgb(var(--background-end-rgb)) 40%
200 | );
201 | z-index: 1;
202 | }
203 | }
204 |
205 | /* Tablet and Smaller Desktop */
206 | @media (min-width: 701px) and (max-width: 1120px) {
207 | .grid {
208 | grid-template-columns: repeat(2, 50%);
209 | }
210 | }
211 |
212 | @media (prefers-color-scheme: dark) {
213 | .vercelLogo {
214 | filter: invert(1);
215 | }
216 |
217 | .logo {
218 | filter: invert(1) drop-shadow(0 0 0.3rem #ffffff70);
219 | }
220 | }
221 |
222 | @keyframes rotate {
223 | from {
224 | transform: rotate(360deg);
225 | }
226 | to {
227 | transform: rotate(0deg);
228 | }
229 | }
230 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # javascript-obfuscator plugin for Next.js
2 | [](https://www.npmjs.com/package/nextjs-obfuscator)
3 |
4 | The `nextjs-obfuscator` enables you to make your Next.js app difficult to be reverse-engineered, using [javascript-obfuscator](https://github.com/javascript-obfuscator/javascript-obfuscator).
5 |
6 | ### ℹ️ If you are looking for README for v1, see [here](https://github.com/mtripg6666tdr/nextjs-obfuscator/tree/v1#readme).
7 |
8 | There are some useful notes:
9 | - The app router is supported.
10 | - Building by turbopack is currently NOT supported.
11 | - Minimum supported Next.js version is v13.
12 |
13 | ## Installation
14 | You have to install javascript-obfuscator separately.
15 |
16 | On npm:
17 | ```
18 | npm i -D javascript-obfuscator nextjs-obfuscator
19 | ```
20 | On yarn:
21 | ```
22 | yarn add -D javascript-obfuscator nextjs-obfuscator
23 | ```
24 |
25 | ## Usage
26 | Wrap your configuration in your `next.config.js` to use this plugin, for example:
27 | ```js
28 | const withNextJsObfuscator = require("nextjs-obfuscator")(obfuscatorOptions, pluginOptions);
29 |
30 | /** @type {import("next").NextConfig} */
31 | const nextConfig = withNextJsObfuscator({
32 | // ... your next.js configuration
33 | });
34 |
35 | module.exports = nextConfig;
36 | ```
37 | Or if you use `next.config.mjs`:
38 | ```js
39 | import createNextJsObfuscator from "nextjs-obfuscator";
40 |
41 | const withNextJsObfuscator = createNextJsObfuscator(obfuscatorOptions, pluginOptions);
42 |
43 | /** @type {import("next").NextConfig} */
44 | const nextConfig = withNextJsObfuscator({
45 | // ... your next.js configuration
46 | });
47 |
48 | export default nextConfig;
49 | ```
50 |
51 | ## API
52 |
53 | require("nextjs-obfuscator")(obfuscatorOptions, pluginOptions)
54 |
55 | ### `obfuscatorOptions`
56 | Type: `Object` (required)
57 | This is [the options](https://github.com/javascript-obfuscator/javascript-obfuscator#javascript-obfuscator-options) of [javascript-obfuscator](https://github.com/javascript-obfuscator/javascript-obfuscator), but there are some important notes:
58 | * [`disableConsoleOutput`](https://github.com/javascript-obfuscator/javascript-obfuscator#disableconsoleoutput) should be set to `false` and you can easily notice the error logging by React on console. If they are present, they indicate your app has been broken.
59 | * There are some options that MUST NOT be set:
60 | * [`inputFileName`](https://github.com/javascript-obfuscator/javascript-obfuscator#inputfilename)
61 | * [`sourceMapBaseUrl`](https://github.com/javascript-obfuscator/javascript-obfuscator#sourcemapbaseurl)
62 | * [`sourceMapFileName`](https://github.com/javascript-obfuscator/javascript-obfuscator#sourcemapfilename)
63 | * [`sourceMapMode`](https://github.com/javascript-obfuscator/javascript-obfuscator#sourcemapmode)
64 | * [`sourceMapSourcesMode`](https://github.com/javascript-obfuscator/javascript-obfuscator#sourcemapsourcesmode)
65 |
66 | These options will be set by the nextjs-obfuscator plugin internally if necessary.
67 |
68 | ### `pluginOptions`
69 | Type: `Object` (optional)
70 | More options for this plugin. All properties are optional.
71 | ```ts
72 | {
73 | enabled: boolean | "detect",
74 | patterns: string[],
75 | obfuscateFiles: Partial<{
76 | buildManifest: boolean,
77 | ssgManifest: boolean,
78 | webpack: boolean,
79 | additionalModules: string[],
80 | }>,
81 | log: boolean,
82 | };
83 | ```
84 |
85 | |Option |Type |Default Value|Description|
86 | |---------|------------------------------------|-------------|-----------|
87 | |`enabled`|boolean | "detect"|`"detect"`|Indicates if the plugin is enabled or not.
If `"detect"` specified, the plugin will be enabled only when building for production.|
88 | |`patterns`|`string[]`|["./**/*.(js|jsx|ts|tsx)"]|Glob patterns to determine which files to be obfuscated. They must be relative paths from the directory where `next.config.js` is placed.|
89 | |`obfuscateFiles`|`object`||Additional files to be obfuscated.|
90 | |`obfuscateFiles.buildManifest`|`boolean`|`false`|If set to true, the plugin will obfuscate `_buildManifest.js`|
91 | |`obfuscateFiles.ssgManifest`|`boolean`|`false`|If set to true, the plugin will obfuscate `_ssgManifest.js`|
92 | |`obfuscateFiles.webpack`|`boolean`|`false`|If set to true, the plugin will obfuscate `webpack.js`, which is an entry point.|
93 | |`obfuscateFiles.additionalModules`|`string[]`|`[]`|Names of additional external modules to be obfuscated. Convenient if you are using custom npm package, for instance. Use like `["module-a", "module-b", ...]`.|
94 | |`log`|`boolean`|`false`|If set to true, the plugin will use `console.log` as logger. Otherwise, it uses webpack's standard logger.|
95 |
96 | ## How it works
97 | * This plugin inserts a custom loader to obfuscate project files and external modules.
98 | * This plugin inserts a custom plugin to obfuscate `buildManifest`, `ssgManifest`, `webpack` assets.
99 |
100 | ## Disclaimer
101 | Using this plugin can break your next.js app, so you have to check carefully your app works fine.
102 |
103 | ## License
104 | [LICENSE](LICENSE)
105 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import type { ObjectWithUnconstantString, PluginOptions } from "./type";
2 | import type { NextConfig } from "next";
3 |
4 | import * as path from "path";
5 |
6 | import { obfuscate } from "javascript-obfuscator";
7 | import { Minimatch } from "minimatch";
8 | import { safeTraverse } from "safe-traverse";
9 | import webpack, { sources } from "webpack";
10 |
11 | import { writeDownWebpackConfig } from "./debug";
12 | import { LoggerSymbol, PublicEnvVariablesSymbol, type NextjsObfuscatorOptions } from "./type";
13 |
14 | const craeteError = (message = "An error occurred.") =>
15 | new Error(`${message} If you think this is a bug of nextjs-obfuscator, please file an issue at https://github.com/mtripg6666tdr/nextjs-obfuscator/issues`);
16 |
17 | function main(
18 | obfuscatorOptions: NextjsObfuscatorOptions | Partial>,
19 | pluginOptions?: Partial
20 | ) {
21 | // initialize options
22 | pluginOptions = Object.assign({
23 | enabled: "detect",
24 | patterns: [
25 | "./**/*.js",
26 | "./**/*.jsx",
27 | "./**/*.ts",
28 | "./**/*.tsx",
29 | ],
30 | log: false,
31 | }, pluginOptions);
32 | pluginOptions.obfuscateFiles = Object.assign({
33 | buildManifest: false,
34 | ssgManifest: false,
35 | webpack: false,
36 | additionalModules: [],
37 | }, pluginOptions.obfuscateFiles);
38 |
39 | const logger: ((...message: string[]) => void) = pluginOptions.log ? console.log.bind(console, "\n") : () => {};
40 | const matchers = pluginOptions.patterns!.map(pattern => new Minimatch(pattern));
41 |
42 | return function(nextConfig: NextConfig) {
43 | if(!nextConfig || typeof nextConfig !== "object"){
44 | throw new TypeError("Invalid configuration object passed.");
45 | }
46 |
47 | const moduleRegEx = /\.(tsx|ts|js|cjs|mjs|jsx)$/;
48 |
49 | const originalWebpackFn = nextConfig.webpack;
50 | nextConfig.webpack = function(config: webpack.Configuration, context){
51 | if("writeConfig" in pluginOptions && pluginOptions.writeConfig){
52 | writeDownWebpackConfig(config);
53 | }
54 |
55 | const basePath = config.context!;
56 |
57 | if(!basePath){
58 | throw craeteError("No context detected.");
59 | }
60 |
61 | // extract public environment variables
62 | const publicEnvVariables = new Map();
63 | config.plugins?.forEach(plugin => {
64 | const entries = safeTraverse(plugin)
65 | .get("definitions")
66 | .entries()
67 | .value || [];
68 | for(const kv of entries){
69 | const key = kv?.[0];
70 | const value = kv?.[1];
71 | if(typeof key === "string" && key.startsWith("process.env.") && typeof value === "string"){
72 | publicEnvVariables.set(key, value);
73 | }
74 | }
75 | });
76 |
77 | const moduleMatcher = (value: string) => {
78 | if(moduleRegEx.test(value)){
79 | if(!value.includes("node_modules")){
80 | const relativePath = `.${path.sep}${path.relative(basePath, value)}`;
81 | logger("Detected:", relativePath);
82 |
83 | if(
84 | matchers.some(matcher => {
85 | const matched = matcher.match(relativePath);
86 | if(matched){
87 | logger("Matched:", relativePath, `(pattern: ${matcher.pattern})`);
88 | }
89 | return matched;
90 | })
91 | ){
92 | return true;
93 | }
94 | }else{
95 | const matched = pluginOptions.obfuscateFiles!.additionalModules!.some(mod => value.includes(`${path.sep}node_modules${path.sep}${mod}`));
96 | if(matched){
97 | logger("Matched:", value);
98 | }
99 | return matched;
100 | }
101 | }
102 | return false;
103 | };
104 |
105 | // obfuscate only if the chunk is for browser
106 | if(
107 | pluginOptions.enabled === true || (pluginOptions.enabled === "detect" && !context.dev)
108 | ){
109 | if(
110 | !context.isServer
111 | && !context.nextRuntime
112 | && config.module?.rules
113 | ){
114 | config.module.rules.unshift({
115 | test: moduleMatcher,
116 | enforce: "post" as const,
117 | use: {
118 | loader: require.resolve("./loader"),
119 | options: Object.assign({
120 | [LoggerSymbol]: logger,
121 | [PublicEnvVariablesSymbol]: publicEnvVariables,
122 | }, obfuscatorOptions),
123 | },
124 | });
125 |
126 | const buildId = context.buildId;
127 |
128 | if(!buildId){
129 | throw craeteError("No buildId found.");
130 | }
131 |
132 | if(Object.values(pluginOptions.obfuscateFiles!).some(val => val)){
133 | config.plugins!.push(
134 | new NextJSObfuscatorPlugin(
135 | obfuscatorOptions as NextjsObfuscatorOptions,
136 | buildId,
137 | pluginOptions.obfuscateFiles!,
138 | logger,
139 | )
140 | );
141 | }
142 | }
143 | }
144 |
145 | // by using below code we can obfuscator server components but at most cases it is not necessary
146 | // const appDirEnabled = (
147 | // config.plugins?.find(p => p && typeof p === "object" && "appDirEnabled" in p) as ({ appDirEnabled: boolean } | undefined)
148 | // )?.appDirEnabled;
149 |
150 | // if(appDirEnabled && context.isServer && context.nextRuntime === "nodejs"){
151 | // config.module!.rules!.unshift({
152 | // test: moduleMatcher,
153 | // enforce: "post",
154 | // use: {
155 | // loader: require.resolve("./loader"),
156 | // options: Object.assign({
157 | // [LoggerSymbol]: logger,
158 | // }, obfuscatorOptions, {
159 | // target: "node",
160 | // domainLock: [],
161 | // }),
162 | // },
163 | // });
164 | // }
165 |
166 | if(originalWebpackFn){
167 | return originalWebpackFn(config, context);
168 | }
169 | return config;
170 | };
171 |
172 | return nextConfig;
173 | };
174 | }
175 |
176 | export = main;
177 |
178 | class NextJSObfuscatorPlugin {
179 | protected logger: ((...messages: any[]) => void);
180 | protected obfuscatorOptions: NextjsObfuscatorOptions;
181 |
182 | constructor(
183 | obfuscatorOptions: NextjsObfuscatorOptions,
184 | protected buildId: string,
185 | protected target: PluginOptions["obfuscateFiles"],
186 | logger: (...messages: any[]) => void,
187 | ) {
188 | this.logger = (...messages: any[]) => logger("(Plugin)", ...messages);
189 | this.obfuscatorOptions = Object.assign(obfuscatorOptions, {
190 | splitStrings: false,
191 | });
192 | }
193 |
194 | apply(compiler: webpack.Compiler) {
195 | const PluginName = this.constructor.name;
196 |
197 | compiler.hooks.compilation.tap(
198 | PluginName,
199 | (compilation) => {
200 | compilation.hooks.processAssets.tap({
201 | name: PluginName.slice(0, -6),
202 | stage: webpack.Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING,
203 | }, (assets) => {
204 | this.logger("Initialized");
205 | const assetNames = Object.keys(assets);
206 | this.logger(assetNames);
207 |
208 | for(let i = 0; i < assetNames.length; i++){
209 | const assetName = assetNames[i];
210 |
211 | if(
212 | (this.target.webpack && assetName.match(/^static\/chunks\/webpack-[abcdef\d]+\.js$/))
213 | || (this.target.buildManifest && assetName === `static/${this.buildId}/_buildManifest.js`)
214 | || (this.target.ssgManifest && assetName === `static/${this.buildId}/_ssgManifest.js`)
215 | ){
216 | const asset = assets[assetName];
217 | if(!asset) return;
218 | const source = asset.source() as string;
219 | const obfuscatedCode = obfuscate(source, this.obfuscatorOptions).getObfuscatedCode();
220 | assets[assetName] = new sources.RawSource(`!function(){${obfuscatedCode}}()`, false);
221 | this.logger("Obfuscated:", assetName, source.length, "->", obfuscatedCode.length);
222 | }
223 | }
224 | });
225 | }
226 | );
227 | }
228 | }
229 |
--------------------------------------------------------------------------------
/example/app-router/.yarn/sdks/typescript/lib/tsserver.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | const {existsSync} = require(`fs`);
4 | const {createRequire} = require(`module`);
5 | const {resolve} = require(`path`);
6 |
7 | const relPnpApiPath = "../../../../.pnp.cjs";
8 |
9 | const absPnpApiPath = resolve(__dirname, relPnpApiPath);
10 | const absRequire = createRequire(absPnpApiPath);
11 |
12 | const moduleWrapper = tsserver => {
13 | if (!process.versions.pnp) {
14 | return tsserver;
15 | }
16 |
17 | const {isAbsolute} = require(`path`);
18 | const pnpApi = require(`pnpapi`);
19 |
20 | const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//);
21 | const isPortal = str => str.startsWith("portal:/");
22 | const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);
23 |
24 | const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => {
25 | return `${locator.name}@${locator.reference}`;
26 | }));
27 |
28 | // VSCode sends the zip paths to TS using the "zip://" prefix, that TS
29 | // doesn't understand. This layer makes sure to remove the protocol
30 | // before forwarding it to TS, and to add it back on all returned paths.
31 |
32 | function toEditorPath(str) {
33 | // We add the `zip:` prefix to both `.zip/` paths and virtual paths
34 | if (isAbsolute(str) && !str.match(/^\^?(zip:|\/zip\/)/) && (str.match(/\.zip\//) || isVirtual(str))) {
35 | // We also take the opportunity to turn virtual paths into physical ones;
36 | // this makes it much easier to work with workspaces that list peer
37 | // dependencies, since otherwise Ctrl+Click would bring us to the virtual
38 | // file instances instead of the real ones.
39 | //
40 | // We only do this to modules owned by the the dependency tree roots.
41 | // This avoids breaking the resolution when jumping inside a vendor
42 | // with peer dep (otherwise jumping into react-dom would show resolution
43 | // errors on react).
44 | //
45 | const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str;
46 | if (resolved) {
47 | const locator = pnpApi.findPackageLocator(resolved);
48 | if (locator && (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))) {
49 | str = resolved;
50 | }
51 | }
52 |
53 | str = normalize(str);
54 |
55 | if (str.match(/\.zip\//)) {
56 | switch (hostInfo) {
57 | // Absolute VSCode `Uri.fsPath`s need to start with a slash.
58 | // VSCode only adds it automatically for supported schemes,
59 | // so we have to do it manually for the `zip` scheme.
60 | // The path needs to start with a caret otherwise VSCode doesn't handle the protocol
61 | //
62 | // Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910
63 | //
64 | // 2021-10-08: VSCode changed the format in 1.61.
65 | // Before | ^zip:/c:/foo/bar.zip/package.json
66 | // After | ^/zip//c:/foo/bar.zip/package.json
67 | //
68 | // 2022-04-06: VSCode changed the format in 1.66.
69 | // Before | ^/zip//c:/foo/bar.zip/package.json
70 | // After | ^/zip/c:/foo/bar.zip/package.json
71 | //
72 | // 2022-05-06: VSCode changed the format in 1.68
73 | // Before | ^/zip/c:/foo/bar.zip/package.json
74 | // After | ^/zip//c:/foo/bar.zip/package.json
75 | //
76 | case `vscode <1.61`: {
77 | str = `^zip:${str}`;
78 | } break;
79 |
80 | case `vscode <1.66`: {
81 | str = `^/zip/${str}`;
82 | } break;
83 |
84 | case `vscode <1.68`: {
85 | str = `^/zip${str}`;
86 | } break;
87 |
88 | case `vscode`: {
89 | str = `^/zip/${str}`;
90 | } break;
91 |
92 | // To make "go to definition" work,
93 | // We have to resolve the actual file system path from virtual path
94 | // and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip)
95 | case `coc-nvim`: {
96 | str = normalize(resolved).replace(/\.zip\//, `.zip::`);
97 | str = resolve(`zipfile:${str}`);
98 | } break;
99 |
100 | // Support neovim native LSP and [typescript-language-server](https://github.com/theia-ide/typescript-language-server)
101 | // We have to resolve the actual file system path from virtual path,
102 | // everything else is up to neovim
103 | case `neovim`: {
104 | str = normalize(resolved).replace(/\.zip\//, `.zip::`);
105 | str = `zipfile://${str}`;
106 | } break;
107 |
108 | default: {
109 | str = `zip:${str}`;
110 | } break;
111 | }
112 | } else {
113 | str = str.replace(/^\/?/, process.platform === `win32` ? `` : `/`);
114 | }
115 | }
116 |
117 | return str;
118 | }
119 |
120 | function fromEditorPath(str) {
121 | switch (hostInfo) {
122 | case `coc-nvim`: {
123 | str = str.replace(/\.zip::/, `.zip/`);
124 | // The path for coc-nvim is in format of //zipfile://.yarn/...
125 | // So in order to convert it back, we use .* to match all the thing
126 | // before `zipfile:`
127 | return process.platform === `win32`
128 | ? str.replace(/^.*zipfile:\//, ``)
129 | : str.replace(/^.*zipfile:/, ``);
130 | } break;
131 |
132 | case `neovim`: {
133 | str = str.replace(/\.zip::/, `.zip/`);
134 | // The path for neovim is in format of zipfile:////.yarn/...
135 | return str.replace(/^zipfile:\/\//, ``);
136 | } break;
137 |
138 | case `vscode`:
139 | default: {
140 | return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`)
141 | } break;
142 | }
143 | }
144 |
145 | // Force enable 'allowLocalPluginLoads'
146 | // TypeScript tries to resolve plugins using a path relative to itself
147 | // which doesn't work when using the global cache
148 | // https://github.com/microsoft/TypeScript/blob/1b57a0395e0bff191581c9606aab92832001de62/src/server/project.ts#L2238
149 | // VSCode doesn't want to enable 'allowLocalPluginLoads' due to security concerns but
150 | // TypeScript already does local loads and if this code is running the user trusts the workspace
151 | // https://github.com/microsoft/vscode/issues/45856
152 | const ConfiguredProject = tsserver.server.ConfiguredProject;
153 | const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype;
154 | ConfiguredProject.prototype.enablePluginsWithOptions = function() {
155 | this.projectService.allowLocalPluginLoads = true;
156 | return originalEnablePluginsWithOptions.apply(this, arguments);
157 | };
158 |
159 | // And here is the point where we hijack the VSCode <-> TS communications
160 | // by adding ourselves in the middle. We locate everything that looks
161 | // like an absolute path of ours and normalize it.
162 |
163 | const Session = tsserver.server.Session;
164 | const {onMessage: originalOnMessage, send: originalSend} = Session.prototype;
165 | let hostInfo = `unknown`;
166 |
167 | Object.assign(Session.prototype, {
168 | onMessage(/** @type {string | object} */ message) {
169 | const isStringMessage = typeof message === 'string';
170 | const parsedMessage = isStringMessage ? JSON.parse(message) : message;
171 |
172 | if (
173 | parsedMessage != null &&
174 | typeof parsedMessage === `object` &&
175 | parsedMessage.arguments &&
176 | typeof parsedMessage.arguments.hostInfo === `string`
177 | ) {
178 | hostInfo = parsedMessage.arguments.hostInfo;
179 | if (hostInfo === `vscode` && process.env.VSCODE_IPC_HOOK) {
180 | const [, major, minor] = (process.env.VSCODE_IPC_HOOK.match(
181 | // The RegExp from https://semver.org/ but without the caret at the start
182 | /(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
183 | ) ?? []).map(Number)
184 |
185 | if (major === 1) {
186 | if (minor < 61) {
187 | hostInfo += ` <1.61`;
188 | } else if (minor < 66) {
189 | hostInfo += ` <1.66`;
190 | } else if (minor < 68) {
191 | hostInfo += ` <1.68`;
192 | }
193 | }
194 | }
195 | }
196 |
197 | const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => {
198 | return typeof value === 'string' ? fromEditorPath(value) : value;
199 | });
200 |
201 | return originalOnMessage.call(
202 | this,
203 | isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON)
204 | );
205 | },
206 |
207 | send(/** @type {any} */ msg) {
208 | return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => {
209 | return typeof value === `string` ? toEditorPath(value) : value;
210 | })));
211 | }
212 | });
213 |
214 | return tsserver;
215 | };
216 |
217 | if (existsSync(absPnpApiPath)) {
218 | if (!process.versions.pnp) {
219 | // Setup the environment to be able to require typescript/lib/tsserver.js
220 | require(absPnpApiPath).setup();
221 | }
222 | }
223 |
224 | // Defer to the real typescript/lib/tsserver.js your application uses
225 | module.exports = moduleWrapper(absRequire(`typescript/lib/tsserver.js`));
226 |
--------------------------------------------------------------------------------
/example/app-router/.yarn/sdks/typescript/lib/tsserverlibrary.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | const {existsSync} = require(`fs`);
4 | const {createRequire} = require(`module`);
5 | const {resolve} = require(`path`);
6 |
7 | const relPnpApiPath = "../../../../.pnp.cjs";
8 |
9 | const absPnpApiPath = resolve(__dirname, relPnpApiPath);
10 | const absRequire = createRequire(absPnpApiPath);
11 |
12 | const moduleWrapper = tsserver => {
13 | if (!process.versions.pnp) {
14 | return tsserver;
15 | }
16 |
17 | const {isAbsolute} = require(`path`);
18 | const pnpApi = require(`pnpapi`);
19 |
20 | const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//);
21 | const isPortal = str => str.startsWith("portal:/");
22 | const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);
23 |
24 | const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => {
25 | return `${locator.name}@${locator.reference}`;
26 | }));
27 |
28 | // VSCode sends the zip paths to TS using the "zip://" prefix, that TS
29 | // doesn't understand. This layer makes sure to remove the protocol
30 | // before forwarding it to TS, and to add it back on all returned paths.
31 |
32 | function toEditorPath(str) {
33 | // We add the `zip:` prefix to both `.zip/` paths and virtual paths
34 | if (isAbsolute(str) && !str.match(/^\^?(zip:|\/zip\/)/) && (str.match(/\.zip\//) || isVirtual(str))) {
35 | // We also take the opportunity to turn virtual paths into physical ones;
36 | // this makes it much easier to work with workspaces that list peer
37 | // dependencies, since otherwise Ctrl+Click would bring us to the virtual
38 | // file instances instead of the real ones.
39 | //
40 | // We only do this to modules owned by the the dependency tree roots.
41 | // This avoids breaking the resolution when jumping inside a vendor
42 | // with peer dep (otherwise jumping into react-dom would show resolution
43 | // errors on react).
44 | //
45 | const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str;
46 | if (resolved) {
47 | const locator = pnpApi.findPackageLocator(resolved);
48 | if (locator && (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))) {
49 | str = resolved;
50 | }
51 | }
52 |
53 | str = normalize(str);
54 |
55 | if (str.match(/\.zip\//)) {
56 | switch (hostInfo) {
57 | // Absolute VSCode `Uri.fsPath`s need to start with a slash.
58 | // VSCode only adds it automatically for supported schemes,
59 | // so we have to do it manually for the `zip` scheme.
60 | // The path needs to start with a caret otherwise VSCode doesn't handle the protocol
61 | //
62 | // Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910
63 | //
64 | // 2021-10-08: VSCode changed the format in 1.61.
65 | // Before | ^zip:/c:/foo/bar.zip/package.json
66 | // After | ^/zip//c:/foo/bar.zip/package.json
67 | //
68 | // 2022-04-06: VSCode changed the format in 1.66.
69 | // Before | ^/zip//c:/foo/bar.zip/package.json
70 | // After | ^/zip/c:/foo/bar.zip/package.json
71 | //
72 | // 2022-05-06: VSCode changed the format in 1.68
73 | // Before | ^/zip/c:/foo/bar.zip/package.json
74 | // After | ^/zip//c:/foo/bar.zip/package.json
75 | //
76 | case `vscode <1.61`: {
77 | str = `^zip:${str}`;
78 | } break;
79 |
80 | case `vscode <1.66`: {
81 | str = `^/zip/${str}`;
82 | } break;
83 |
84 | case `vscode <1.68`: {
85 | str = `^/zip${str}`;
86 | } break;
87 |
88 | case `vscode`: {
89 | str = `^/zip/${str}`;
90 | } break;
91 |
92 | // To make "go to definition" work,
93 | // We have to resolve the actual file system path from virtual path
94 | // and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip)
95 | case `coc-nvim`: {
96 | str = normalize(resolved).replace(/\.zip\//, `.zip::`);
97 | str = resolve(`zipfile:${str}`);
98 | } break;
99 |
100 | // Support neovim native LSP and [typescript-language-server](https://github.com/theia-ide/typescript-language-server)
101 | // We have to resolve the actual file system path from virtual path,
102 | // everything else is up to neovim
103 | case `neovim`: {
104 | str = normalize(resolved).replace(/\.zip\//, `.zip::`);
105 | str = `zipfile://${str}`;
106 | } break;
107 |
108 | default: {
109 | str = `zip:${str}`;
110 | } break;
111 | }
112 | } else {
113 | str = str.replace(/^\/?/, process.platform === `win32` ? `` : `/`);
114 | }
115 | }
116 |
117 | return str;
118 | }
119 |
120 | function fromEditorPath(str) {
121 | switch (hostInfo) {
122 | case `coc-nvim`: {
123 | str = str.replace(/\.zip::/, `.zip/`);
124 | // The path for coc-nvim is in format of //zipfile://.yarn/...
125 | // So in order to convert it back, we use .* to match all the thing
126 | // before `zipfile:`
127 | return process.platform === `win32`
128 | ? str.replace(/^.*zipfile:\//, ``)
129 | : str.replace(/^.*zipfile:/, ``);
130 | } break;
131 |
132 | case `neovim`: {
133 | str = str.replace(/\.zip::/, `.zip/`);
134 | // The path for neovim is in format of zipfile:////.yarn/...
135 | return str.replace(/^zipfile:\/\//, ``);
136 | } break;
137 |
138 | case `vscode`:
139 | default: {
140 | return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`)
141 | } break;
142 | }
143 | }
144 |
145 | // Force enable 'allowLocalPluginLoads'
146 | // TypeScript tries to resolve plugins using a path relative to itself
147 | // which doesn't work when using the global cache
148 | // https://github.com/microsoft/TypeScript/blob/1b57a0395e0bff191581c9606aab92832001de62/src/server/project.ts#L2238
149 | // VSCode doesn't want to enable 'allowLocalPluginLoads' due to security concerns but
150 | // TypeScript already does local loads and if this code is running the user trusts the workspace
151 | // https://github.com/microsoft/vscode/issues/45856
152 | const ConfiguredProject = tsserver.server.ConfiguredProject;
153 | const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype;
154 | ConfiguredProject.prototype.enablePluginsWithOptions = function() {
155 | this.projectService.allowLocalPluginLoads = true;
156 | return originalEnablePluginsWithOptions.apply(this, arguments);
157 | };
158 |
159 | // And here is the point where we hijack the VSCode <-> TS communications
160 | // by adding ourselves in the middle. We locate everything that looks
161 | // like an absolute path of ours and normalize it.
162 |
163 | const Session = tsserver.server.Session;
164 | const {onMessage: originalOnMessage, send: originalSend} = Session.prototype;
165 | let hostInfo = `unknown`;
166 |
167 | Object.assign(Session.prototype, {
168 | onMessage(/** @type {string | object} */ message) {
169 | const isStringMessage = typeof message === 'string';
170 | const parsedMessage = isStringMessage ? JSON.parse(message) : message;
171 |
172 | if (
173 | parsedMessage != null &&
174 | typeof parsedMessage === `object` &&
175 | parsedMessage.arguments &&
176 | typeof parsedMessage.arguments.hostInfo === `string`
177 | ) {
178 | hostInfo = parsedMessage.arguments.hostInfo;
179 | if (hostInfo === `vscode` && process.env.VSCODE_IPC_HOOK) {
180 | const [, major, minor] = (process.env.VSCODE_IPC_HOOK.match(
181 | // The RegExp from https://semver.org/ but without the caret at the start
182 | /(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
183 | ) ?? []).map(Number)
184 |
185 | if (major === 1) {
186 | if (minor < 61) {
187 | hostInfo += ` <1.61`;
188 | } else if (minor < 66) {
189 | hostInfo += ` <1.66`;
190 | } else if (minor < 68) {
191 | hostInfo += ` <1.68`;
192 | }
193 | }
194 | }
195 | }
196 |
197 | const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => {
198 | return typeof value === 'string' ? fromEditorPath(value) : value;
199 | });
200 |
201 | return originalOnMessage.call(
202 | this,
203 | isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON)
204 | );
205 | },
206 |
207 | send(/** @type {any} */ msg) {
208 | return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => {
209 | return typeof value === `string` ? toEditorPath(value) : value;
210 | })));
211 | }
212 | });
213 |
214 | return tsserver;
215 | };
216 |
217 | if (existsSync(absPnpApiPath)) {
218 | if (!process.versions.pnp) {
219 | // Setup the environment to be able to require typescript/lib/tsserverlibrary.js
220 | require(absPnpApiPath).setup();
221 | }
222 | }
223 |
224 | // Defer to the real typescript/lib/tsserverlibrary.js your application uses
225 | module.exports = moduleWrapper(absRequire(`typescript/lib/tsserverlibrary.js`));
226 |
--------------------------------------------------------------------------------
/example/app-router/yarn.lock:
--------------------------------------------------------------------------------
1 | # This file is generated by running "yarn install" inside your project.
2 | # Manual changes might be lost - proceed with caution!
3 |
4 | __metadata:
5 | version: 6
6 | cacheKey: 8
7 |
8 | "@emnapi/runtime@npm:^1.2.0":
9 | version: 1.3.1
10 | resolution: "@emnapi/runtime@npm:1.3.1"
11 | dependencies:
12 | tslib: ^2.4.0
13 | checksum: 9a16ae7905a9c0e8956cf1854ef74e5087fbf36739abdba7aa6b308485aafdc993da07c19d7af104cd5f8e425121120852851bb3a0f78e2160e420a36d47f42f
14 | languageName: node
15 | linkType: hard
16 |
17 | "@img/sharp-darwin-arm64@npm:0.33.5":
18 | version: 0.33.5
19 | resolution: "@img/sharp-darwin-arm64@npm:0.33.5"
20 | dependencies:
21 | "@img/sharp-libvips-darwin-arm64": 1.0.4
22 | dependenciesMeta:
23 | "@img/sharp-libvips-darwin-arm64":
24 | optional: true
25 | conditions: os=darwin & cpu=arm64
26 | languageName: node
27 | linkType: hard
28 |
29 | "@img/sharp-darwin-x64@npm:0.33.5":
30 | version: 0.33.5
31 | resolution: "@img/sharp-darwin-x64@npm:0.33.5"
32 | dependencies:
33 | "@img/sharp-libvips-darwin-x64": 1.0.4
34 | dependenciesMeta:
35 | "@img/sharp-libvips-darwin-x64":
36 | optional: true
37 | conditions: os=darwin & cpu=x64
38 | languageName: node
39 | linkType: hard
40 |
41 | "@img/sharp-libvips-darwin-arm64@npm:1.0.4":
42 | version: 1.0.4
43 | resolution: "@img/sharp-libvips-darwin-arm64@npm:1.0.4"
44 | conditions: os=darwin & cpu=arm64
45 | languageName: node
46 | linkType: hard
47 |
48 | "@img/sharp-libvips-darwin-x64@npm:1.0.4":
49 | version: 1.0.4
50 | resolution: "@img/sharp-libvips-darwin-x64@npm:1.0.4"
51 | conditions: os=darwin & cpu=x64
52 | languageName: node
53 | linkType: hard
54 |
55 | "@img/sharp-libvips-linux-arm64@npm:1.0.4":
56 | version: 1.0.4
57 | resolution: "@img/sharp-libvips-linux-arm64@npm:1.0.4"
58 | conditions: os=linux & cpu=arm64 & libc=glibc
59 | languageName: node
60 | linkType: hard
61 |
62 | "@img/sharp-libvips-linux-arm@npm:1.0.5":
63 | version: 1.0.5
64 | resolution: "@img/sharp-libvips-linux-arm@npm:1.0.5"
65 | conditions: os=linux & cpu=arm & libc=glibc
66 | languageName: node
67 | linkType: hard
68 |
69 | "@img/sharp-libvips-linux-s390x@npm:1.0.4":
70 | version: 1.0.4
71 | resolution: "@img/sharp-libvips-linux-s390x@npm:1.0.4"
72 | conditions: os=linux & cpu=s390x & libc=glibc
73 | languageName: node
74 | linkType: hard
75 |
76 | "@img/sharp-libvips-linux-x64@npm:1.0.4":
77 | version: 1.0.4
78 | resolution: "@img/sharp-libvips-linux-x64@npm:1.0.4"
79 | conditions: os=linux & cpu=x64 & libc=glibc
80 | languageName: node
81 | linkType: hard
82 |
83 | "@img/sharp-libvips-linuxmusl-arm64@npm:1.0.4":
84 | version: 1.0.4
85 | resolution: "@img/sharp-libvips-linuxmusl-arm64@npm:1.0.4"
86 | conditions: os=linux & cpu=arm64 & libc=musl
87 | languageName: node
88 | linkType: hard
89 |
90 | "@img/sharp-libvips-linuxmusl-x64@npm:1.0.4":
91 | version: 1.0.4
92 | resolution: "@img/sharp-libvips-linuxmusl-x64@npm:1.0.4"
93 | conditions: os=linux & cpu=x64 & libc=musl
94 | languageName: node
95 | linkType: hard
96 |
97 | "@img/sharp-linux-arm64@npm:0.33.5":
98 | version: 0.33.5
99 | resolution: "@img/sharp-linux-arm64@npm:0.33.5"
100 | dependencies:
101 | "@img/sharp-libvips-linux-arm64": 1.0.4
102 | dependenciesMeta:
103 | "@img/sharp-libvips-linux-arm64":
104 | optional: true
105 | conditions: os=linux & cpu=arm64 & libc=glibc
106 | languageName: node
107 | linkType: hard
108 |
109 | "@img/sharp-linux-arm@npm:0.33.5":
110 | version: 0.33.5
111 | resolution: "@img/sharp-linux-arm@npm:0.33.5"
112 | dependencies:
113 | "@img/sharp-libvips-linux-arm": 1.0.5
114 | dependenciesMeta:
115 | "@img/sharp-libvips-linux-arm":
116 | optional: true
117 | conditions: os=linux & cpu=arm & libc=glibc
118 | languageName: node
119 | linkType: hard
120 |
121 | "@img/sharp-linux-s390x@npm:0.33.5":
122 | version: 0.33.5
123 | resolution: "@img/sharp-linux-s390x@npm:0.33.5"
124 | dependencies:
125 | "@img/sharp-libvips-linux-s390x": 1.0.4
126 | dependenciesMeta:
127 | "@img/sharp-libvips-linux-s390x":
128 | optional: true
129 | conditions: os=linux & cpu=s390x & libc=glibc
130 | languageName: node
131 | linkType: hard
132 |
133 | "@img/sharp-linux-x64@npm:0.33.5":
134 | version: 0.33.5
135 | resolution: "@img/sharp-linux-x64@npm:0.33.5"
136 | dependencies:
137 | "@img/sharp-libvips-linux-x64": 1.0.4
138 | dependenciesMeta:
139 | "@img/sharp-libvips-linux-x64":
140 | optional: true
141 | conditions: os=linux & cpu=x64 & libc=glibc
142 | languageName: node
143 | linkType: hard
144 |
145 | "@img/sharp-linuxmusl-arm64@npm:0.33.5":
146 | version: 0.33.5
147 | resolution: "@img/sharp-linuxmusl-arm64@npm:0.33.5"
148 | dependencies:
149 | "@img/sharp-libvips-linuxmusl-arm64": 1.0.4
150 | dependenciesMeta:
151 | "@img/sharp-libvips-linuxmusl-arm64":
152 | optional: true
153 | conditions: os=linux & cpu=arm64 & libc=musl
154 | languageName: node
155 | linkType: hard
156 |
157 | "@img/sharp-linuxmusl-x64@npm:0.33.5":
158 | version: 0.33.5
159 | resolution: "@img/sharp-linuxmusl-x64@npm:0.33.5"
160 | dependencies:
161 | "@img/sharp-libvips-linuxmusl-x64": 1.0.4
162 | dependenciesMeta:
163 | "@img/sharp-libvips-linuxmusl-x64":
164 | optional: true
165 | conditions: os=linux & cpu=x64 & libc=musl
166 | languageName: node
167 | linkType: hard
168 |
169 | "@img/sharp-wasm32@npm:0.33.5":
170 | version: 0.33.5
171 | resolution: "@img/sharp-wasm32@npm:0.33.5"
172 | dependencies:
173 | "@emnapi/runtime": ^1.2.0
174 | conditions: cpu=wasm32
175 | languageName: node
176 | linkType: hard
177 |
178 | "@img/sharp-win32-ia32@npm:0.33.5":
179 | version: 0.33.5
180 | resolution: "@img/sharp-win32-ia32@npm:0.33.5"
181 | conditions: os=win32 & cpu=ia32
182 | languageName: node
183 | linkType: hard
184 |
185 | "@img/sharp-win32-x64@npm:0.33.5":
186 | version: 0.33.5
187 | resolution: "@img/sharp-win32-x64@npm:0.33.5"
188 | conditions: os=win32 & cpu=x64
189 | languageName: node
190 | linkType: hard
191 |
192 | "@next/env@npm:15.0.2":
193 | version: 15.0.2
194 | resolution: "@next/env@npm:15.0.2"
195 | checksum: 6a347035e72f30c64547b01bdea2f0da53e3bdbc892ca62220bd03633db0a2484be6ce67f6e441f457b9c3b92ea09eb05fb339b529228e7d1540524c79b9c010
196 | languageName: node
197 | linkType: hard
198 |
199 | "@next/swc-darwin-arm64@npm:15.0.2":
200 | version: 15.0.2
201 | resolution: "@next/swc-darwin-arm64@npm:15.0.2"
202 | conditions: os=darwin & cpu=arm64
203 | languageName: node
204 | linkType: hard
205 |
206 | "@next/swc-darwin-x64@npm:15.0.2":
207 | version: 15.0.2
208 | resolution: "@next/swc-darwin-x64@npm:15.0.2"
209 | conditions: os=darwin & cpu=x64
210 | languageName: node
211 | linkType: hard
212 |
213 | "@next/swc-linux-arm64-gnu@npm:15.0.2":
214 | version: 15.0.2
215 | resolution: "@next/swc-linux-arm64-gnu@npm:15.0.2"
216 | conditions: os=linux & cpu=arm64 & libc=glibc
217 | languageName: node
218 | linkType: hard
219 |
220 | "@next/swc-linux-arm64-musl@npm:15.0.2":
221 | version: 15.0.2
222 | resolution: "@next/swc-linux-arm64-musl@npm:15.0.2"
223 | conditions: os=linux & cpu=arm64 & libc=musl
224 | languageName: node
225 | linkType: hard
226 |
227 | "@next/swc-linux-x64-gnu@npm:15.0.2":
228 | version: 15.0.2
229 | resolution: "@next/swc-linux-x64-gnu@npm:15.0.2"
230 | conditions: os=linux & cpu=x64 & libc=glibc
231 | languageName: node
232 | linkType: hard
233 |
234 | "@next/swc-linux-x64-musl@npm:15.0.2":
235 | version: 15.0.2
236 | resolution: "@next/swc-linux-x64-musl@npm:15.0.2"
237 | conditions: os=linux & cpu=x64 & libc=musl
238 | languageName: node
239 | linkType: hard
240 |
241 | "@next/swc-win32-arm64-msvc@npm:15.0.2":
242 | version: 15.0.2
243 | resolution: "@next/swc-win32-arm64-msvc@npm:15.0.2"
244 | conditions: os=win32 & cpu=arm64
245 | languageName: node
246 | linkType: hard
247 |
248 | "@next/swc-win32-x64-msvc@npm:15.0.2":
249 | version: 15.0.2
250 | resolution: "@next/swc-win32-x64-msvc@npm:15.0.2"
251 | conditions: os=win32 & cpu=x64
252 | languageName: node
253 | linkType: hard
254 |
255 | "@swc/counter@npm:0.1.3":
256 | version: 0.1.3
257 | resolution: "@swc/counter@npm:0.1.3"
258 | checksum: df8f9cfba9904d3d60f511664c70d23bb323b3a0803ec9890f60133954173047ba9bdeabce28cd70ba89ccd3fd6c71c7b0bd58be85f611e1ffbe5d5c18616598
259 | languageName: node
260 | linkType: hard
261 |
262 | "@swc/helpers@npm:0.5.13":
263 | version: 0.5.13
264 | resolution: "@swc/helpers@npm:0.5.13"
265 | dependencies:
266 | tslib: ^2.4.0
267 | checksum: d50c2c10da6ef940af423c6b03ad9c3c94cf9de59314b1e921a7d1bcc081a6074481c9d67b655fc8fe66a73288f98b25950743792a63882bfb5793b362494fc0
268 | languageName: node
269 | linkType: hard
270 |
271 | "@types/node@npm:22.8.7":
272 | version: 22.8.7
273 | resolution: "@types/node@npm:22.8.7"
274 | dependencies:
275 | undici-types: ~6.19.8
276 | checksum: c7b200d06da97a4d4f46528ae962c028bb06b6ef9ab7f7949639420f3b3d236f041756ca1945dcaec0fcefbafd07b8ca47bbc1b47b77d33a4173211425641426
277 | languageName: node
278 | linkType: hard
279 |
280 | "@types/prop-types@npm:*":
281 | version: 15.7.12
282 | resolution: "@types/prop-types@npm:15.7.12"
283 | checksum: ac16cc3d0a84431ffa5cfdf89579ad1e2269549f32ce0c769321fdd078f84db4fbe1b461ed5a1a496caf09e637c0e367d600c541435716a55b1d9713f5035dfe
284 | languageName: node
285 | linkType: hard
286 |
287 | "@types/react-dom@npm:^18.3.1":
288 | version: 18.3.1
289 | resolution: "@types/react-dom@npm:18.3.1"
290 | dependencies:
291 | "@types/react": "*"
292 | checksum: ad28ecce3915d30dc76adc2a1373fda1745ba429cea290e16c6628df9a05fd80b6403c8e87d78b45e6c60e51df7a67add389ab62b90070fbfdc9bda8307d9953
293 | languageName: node
294 | linkType: hard
295 |
296 | "@types/react@npm:*, @types/react@npm:18.3.12":
297 | version: 18.3.12
298 | resolution: "@types/react@npm:18.3.12"
299 | dependencies:
300 | "@types/prop-types": "*"
301 | csstype: ^3.0.2
302 | checksum: 4ab1577a8c2105a5e316536f724117c90eee5f4bd5c137fc82a2253d8c1fd299dedaa07e8dfc95d6e2f04a4be3cb8b0e1b06098c6233ebd55c508d88099395b7
303 | languageName: node
304 | linkType: hard
305 |
306 | "busboy@npm:1.6.0":
307 | version: 1.6.0
308 | resolution: "busboy@npm:1.6.0"
309 | dependencies:
310 | streamsearch: ^1.1.0
311 | checksum: 32801e2c0164e12106bf236291a00795c3c4e4b709ae02132883fe8478ba2ae23743b11c5735a0aae8afe65ac4b6ca4568b91f0d9fed1fdbc32ede824a73746e
312 | languageName: node
313 | linkType: hard
314 |
315 | "caniuse-lite@npm:^1.0.30001579":
316 | version: 1.0.30001649
317 | resolution: "caniuse-lite@npm:1.0.30001649"
318 | checksum: 7952512a243f22c942e0e99249def19d781ad1900db101f2d8de9d83de37db000a7dc7f226c9c99134001975e22852becf1677539c24c7ecae53467b681c400f
319 | languageName: node
320 | linkType: hard
321 |
322 | "client-only@npm:0.0.1":
323 | version: 0.0.1
324 | resolution: "client-only@npm:0.0.1"
325 | checksum: 0c16bf660dadb90610553c1d8946a7fdfb81d624adea073b8440b7d795d5b5b08beb3c950c6a2cf16279365a3265158a236876d92bce16423c485c322d7dfaf8
326 | languageName: node
327 | linkType: hard
328 |
329 | "color-convert@npm:^2.0.1":
330 | version: 2.0.1
331 | resolution: "color-convert@npm:2.0.1"
332 | dependencies:
333 | color-name: ~1.1.4
334 | checksum: 79e6bdb9fd479a205c71d89574fccfb22bd9053bd98c6c4d870d65c132e5e904e6034978e55b43d69fcaa7433af2016ee203ce76eeba9cfa554b373e7f7db336
335 | languageName: node
336 | linkType: hard
337 |
338 | "color-name@npm:^1.0.0, color-name@npm:~1.1.4":
339 | version: 1.1.4
340 | resolution: "color-name@npm:1.1.4"
341 | checksum: b0445859521eb4021cd0fb0cc1a75cecf67fceecae89b63f62b201cca8d345baf8b952c966862a9d9a2632987d4f6581f0ec8d957dfacece86f0a7919316f610
342 | languageName: node
343 | linkType: hard
344 |
345 | "color-string@npm:^1.9.0":
346 | version: 1.9.1
347 | resolution: "color-string@npm:1.9.1"
348 | dependencies:
349 | color-name: ^1.0.0
350 | simple-swizzle: ^0.2.2
351 | checksum: c13fe7cff7885f603f49105827d621ce87f4571d78ba28ef4a3f1a104304748f620615e6bf065ecd2145d0d9dad83a3553f52bb25ede7239d18e9f81622f1cc5
352 | languageName: node
353 | linkType: hard
354 |
355 | "color@npm:^4.2.3":
356 | version: 4.2.3
357 | resolution: "color@npm:4.2.3"
358 | dependencies:
359 | color-convert: ^2.0.1
360 | color-string: ^1.9.0
361 | checksum: 0579629c02c631b426780038da929cca8e8d80a40158b09811a0112a107c62e10e4aad719843b791b1e658ab4e800558f2e87ca4522c8b32349d497ecb6adeb4
362 | languageName: node
363 | linkType: hard
364 |
365 | "csstype@npm:^3.0.2":
366 | version: 3.1.3
367 | resolution: "csstype@npm:3.1.3"
368 | checksum: 8db785cc92d259102725b3c694ec0c823f5619a84741b5c7991b8ad135dfaa66093038a1cc63e03361a6cd28d122be48f2106ae72334e067dd619a51f49eddf7
369 | languageName: node
370 | linkType: hard
371 |
372 | "detect-libc@npm:^2.0.3":
373 | version: 2.0.3
374 | resolution: "detect-libc@npm:2.0.3"
375 | checksum: 2ba6a939ae55f189aea996ac67afceb650413c7a34726ee92c40fb0deb2400d57ef94631a8a3f052055eea7efb0f99a9b5e6ce923415daa3e68221f963cfc27d
376 | languageName: node
377 | linkType: hard
378 |
379 | "example-nextjs-obfuscated-app-with-app-router@workspace:.":
380 | version: 0.0.0-use.local
381 | resolution: "example-nextjs-obfuscated-app-with-app-router@workspace:."
382 | dependencies:
383 | "@types/node": 22.8.7
384 | "@types/react": 18.3.12
385 | "@types/react-dom": ^18.3.1
386 | next: 15.0.2
387 | react: 18.3.1
388 | react-dom: 18.3.1
389 | typescript: 5.6.3
390 | languageName: unknown
391 | linkType: soft
392 |
393 | "is-arrayish@npm:^0.3.1":
394 | version: 0.3.2
395 | resolution: "is-arrayish@npm:0.3.2"
396 | checksum: 977e64f54d91c8f169b59afcd80ff19227e9f5c791fa28fa2e5bce355cbaf6c2c356711b734656e80c9dd4a854dd7efcf7894402f1031dfc5de5d620775b4d5f
397 | languageName: node
398 | linkType: hard
399 |
400 | "js-tokens@npm:^3.0.0 || ^4.0.0":
401 | version: 4.0.0
402 | resolution: "js-tokens@npm:4.0.0"
403 | checksum: 8a95213a5a77deb6cbe94d86340e8d9ace2b93bc367790b260101d2f36a2eaf4e4e22d9fa9cf459b38af3a32fb4190e638024cf82ec95ef708680e405ea7cc78
404 | languageName: node
405 | linkType: hard
406 |
407 | "loose-envify@npm:^1.1.0":
408 | version: 1.4.0
409 | resolution: "loose-envify@npm:1.4.0"
410 | dependencies:
411 | js-tokens: ^3.0.0 || ^4.0.0
412 | bin:
413 | loose-envify: cli.js
414 | checksum: 6517e24e0cad87ec9888f500c5b5947032cdfe6ef65e1c1936a0c48a524b81e65542c9c3edc91c97d5bddc806ee2a985dbc79be89215d613b1de5db6d1cfe6f4
415 | languageName: node
416 | linkType: hard
417 |
418 | "nanoid@npm:^3.3.6":
419 | version: 3.3.7
420 | resolution: "nanoid@npm:3.3.7"
421 | bin:
422 | nanoid: bin/nanoid.cjs
423 | checksum: d36c427e530713e4ac6567d488b489a36582ef89da1d6d4e3b87eded11eb10d7042a877958c6f104929809b2ab0bafa17652b076cdf84324aa75b30b722204f2
424 | languageName: node
425 | linkType: hard
426 |
427 | "next@npm:15.0.2":
428 | version: 15.0.2
429 | resolution: "next@npm:15.0.2"
430 | dependencies:
431 | "@next/env": 15.0.2
432 | "@next/swc-darwin-arm64": 15.0.2
433 | "@next/swc-darwin-x64": 15.0.2
434 | "@next/swc-linux-arm64-gnu": 15.0.2
435 | "@next/swc-linux-arm64-musl": 15.0.2
436 | "@next/swc-linux-x64-gnu": 15.0.2
437 | "@next/swc-linux-x64-musl": 15.0.2
438 | "@next/swc-win32-arm64-msvc": 15.0.2
439 | "@next/swc-win32-x64-msvc": 15.0.2
440 | "@swc/counter": 0.1.3
441 | "@swc/helpers": 0.5.13
442 | busboy: 1.6.0
443 | caniuse-lite: ^1.0.30001579
444 | postcss: 8.4.31
445 | sharp: ^0.33.5
446 | styled-jsx: 5.1.6
447 | peerDependencies:
448 | "@opentelemetry/api": ^1.1.0
449 | "@playwright/test": ^1.41.2
450 | babel-plugin-react-compiler: "*"
451 | react: ^18.2.0 || 19.0.0-rc-02c0e824-20241028
452 | react-dom: ^18.2.0 || 19.0.0-rc-02c0e824-20241028
453 | sass: ^1.3.0
454 | dependenciesMeta:
455 | "@next/swc-darwin-arm64":
456 | optional: true
457 | "@next/swc-darwin-x64":
458 | optional: true
459 | "@next/swc-linux-arm64-gnu":
460 | optional: true
461 | "@next/swc-linux-arm64-musl":
462 | optional: true
463 | "@next/swc-linux-x64-gnu":
464 | optional: true
465 | "@next/swc-linux-x64-musl":
466 | optional: true
467 | "@next/swc-win32-arm64-msvc":
468 | optional: true
469 | "@next/swc-win32-x64-msvc":
470 | optional: true
471 | sharp:
472 | optional: true
473 | peerDependenciesMeta:
474 | "@opentelemetry/api":
475 | optional: true
476 | "@playwright/test":
477 | optional: true
478 | babel-plugin-react-compiler:
479 | optional: true
480 | sass:
481 | optional: true
482 | bin:
483 | next: dist/bin/next
484 | checksum: e2430ee430033aa651319453e6194aa13d3fe217a9d8126d3e286ab1c74f13f529f9a0067e0b68ed3f84be4d6383b831db61f9a14673fb3f49789f1dd81c4de6
485 | languageName: node
486 | linkType: hard
487 |
488 | "picocolors@npm:^1.0.0":
489 | version: 1.0.1
490 | resolution: "picocolors@npm:1.0.1"
491 | checksum: fa68166d1f56009fc02a34cdfd112b0dd3cf1ef57667ac57281f714065558c01828cdf4f18600ad6851cbe0093952ed0660b1e0156bddf2184b6aaf5817553a5
492 | languageName: node
493 | linkType: hard
494 |
495 | "postcss@npm:8.4.31":
496 | version: 8.4.31
497 | resolution: "postcss@npm:8.4.31"
498 | dependencies:
499 | nanoid: ^3.3.6
500 | picocolors: ^1.0.0
501 | source-map-js: ^1.0.2
502 | checksum: 1d8611341b073143ad90486fcdfeab49edd243377b1f51834dc4f6d028e82ce5190e4f11bb2633276864503654fb7cab28e67abdc0fbf9d1f88cad4a0ff0beea
503 | languageName: node
504 | linkType: hard
505 |
506 | "react-dom@npm:18.3.1":
507 | version: 18.3.1
508 | resolution: "react-dom@npm:18.3.1"
509 | dependencies:
510 | loose-envify: ^1.1.0
511 | scheduler: ^0.23.2
512 | peerDependencies:
513 | react: ^18.3.1
514 | checksum: 298954ecd8f78288dcaece05e88b570014d8f6dce5db6f66e6ee91448debeb59dcd31561dddb354eee47e6c1bb234669459060deb238ed0213497146e555a0b9
515 | languageName: node
516 | linkType: hard
517 |
518 | "react@npm:18.3.1":
519 | version: 18.3.1
520 | resolution: "react@npm:18.3.1"
521 | dependencies:
522 | loose-envify: ^1.1.0
523 | checksum: a27bcfa8ff7c15a1e50244ad0d0c1cb2ad4375eeffefd266a64889beea6f6b64c4966c9b37d14ee32d6c9fcd5aa6ba183b6988167ab4d127d13e7cb5b386a376
524 | languageName: node
525 | linkType: hard
526 |
527 | "scheduler@npm:^0.23.2":
528 | version: 0.23.2
529 | resolution: "scheduler@npm:0.23.2"
530 | dependencies:
531 | loose-envify: ^1.1.0
532 | checksum: 3e82d1f419e240ef6219d794ff29c7ee415fbdc19e038f680a10c067108e06284f1847450a210b29bbaf97b9d8a97ced5f624c31c681248ac84c80d56ad5a2c4
533 | languageName: node
534 | linkType: hard
535 |
536 | "semver@npm:^7.6.3":
537 | version: 7.6.3
538 | resolution: "semver@npm:7.6.3"
539 | bin:
540 | semver: bin/semver.js
541 | checksum: 4110ec5d015c9438f322257b1c51fe30276e5f766a3f64c09edd1d7ea7118ecbc3f379f3b69032bacf13116dc7abc4ad8ce0d7e2bd642e26b0d271b56b61a7d8
542 | languageName: node
543 | linkType: hard
544 |
545 | "sharp@npm:^0.33.5":
546 | version: 0.33.5
547 | resolution: "sharp@npm:0.33.5"
548 | dependencies:
549 | "@img/sharp-darwin-arm64": 0.33.5
550 | "@img/sharp-darwin-x64": 0.33.5
551 | "@img/sharp-libvips-darwin-arm64": 1.0.4
552 | "@img/sharp-libvips-darwin-x64": 1.0.4
553 | "@img/sharp-libvips-linux-arm": 1.0.5
554 | "@img/sharp-libvips-linux-arm64": 1.0.4
555 | "@img/sharp-libvips-linux-s390x": 1.0.4
556 | "@img/sharp-libvips-linux-x64": 1.0.4
557 | "@img/sharp-libvips-linuxmusl-arm64": 1.0.4
558 | "@img/sharp-libvips-linuxmusl-x64": 1.0.4
559 | "@img/sharp-linux-arm": 0.33.5
560 | "@img/sharp-linux-arm64": 0.33.5
561 | "@img/sharp-linux-s390x": 0.33.5
562 | "@img/sharp-linux-x64": 0.33.5
563 | "@img/sharp-linuxmusl-arm64": 0.33.5
564 | "@img/sharp-linuxmusl-x64": 0.33.5
565 | "@img/sharp-wasm32": 0.33.5
566 | "@img/sharp-win32-ia32": 0.33.5
567 | "@img/sharp-win32-x64": 0.33.5
568 | color: ^4.2.3
569 | detect-libc: ^2.0.3
570 | semver: ^7.6.3
571 | dependenciesMeta:
572 | "@img/sharp-darwin-arm64":
573 | optional: true
574 | "@img/sharp-darwin-x64":
575 | optional: true
576 | "@img/sharp-libvips-darwin-arm64":
577 | optional: true
578 | "@img/sharp-libvips-darwin-x64":
579 | optional: true
580 | "@img/sharp-libvips-linux-arm":
581 | optional: true
582 | "@img/sharp-libvips-linux-arm64":
583 | optional: true
584 | "@img/sharp-libvips-linux-s390x":
585 | optional: true
586 | "@img/sharp-libvips-linux-x64":
587 | optional: true
588 | "@img/sharp-libvips-linuxmusl-arm64":
589 | optional: true
590 | "@img/sharp-libvips-linuxmusl-x64":
591 | optional: true
592 | "@img/sharp-linux-arm":
593 | optional: true
594 | "@img/sharp-linux-arm64":
595 | optional: true
596 | "@img/sharp-linux-s390x":
597 | optional: true
598 | "@img/sharp-linux-x64":
599 | optional: true
600 | "@img/sharp-linuxmusl-arm64":
601 | optional: true
602 | "@img/sharp-linuxmusl-x64":
603 | optional: true
604 | "@img/sharp-wasm32":
605 | optional: true
606 | "@img/sharp-win32-ia32":
607 | optional: true
608 | "@img/sharp-win32-x64":
609 | optional: true
610 | checksum: 04beae89910ac65c5f145f88de162e8466bec67705f497ace128de849c24d168993e016f33a343a1f3c30b25d2a90c3e62b017a9a0d25452371556f6cd2471e4
611 | languageName: node
612 | linkType: hard
613 |
614 | "simple-swizzle@npm:^0.2.2":
615 | version: 0.2.2
616 | resolution: "simple-swizzle@npm:0.2.2"
617 | dependencies:
618 | is-arrayish: ^0.3.1
619 | checksum: a7f3f2ab5c76c4472d5c578df892e857323e452d9f392e1b5cf74b74db66e6294a1e1b8b390b519fa1b96b5b613f2a37db6cffef52c3f1f8f3c5ea64eb2d54c0
620 | languageName: node
621 | linkType: hard
622 |
623 | "source-map-js@npm:^1.0.2":
624 | version: 1.2.0
625 | resolution: "source-map-js@npm:1.2.0"
626 | checksum: 791a43306d9223792e84293b00458bf102a8946e7188f3db0e4e22d8d530b5f80a4ce468eb5ec0bf585443ad55ebbd630bf379c98db0b1f317fd902500217f97
627 | languageName: node
628 | linkType: hard
629 |
630 | "streamsearch@npm:^1.1.0":
631 | version: 1.1.0
632 | resolution: "streamsearch@npm:1.1.0"
633 | checksum: 1cce16cea8405d7a233d32ca5e00a00169cc0e19fbc02aa839959985f267335d435c07f96e5e0edd0eadc6d39c98d5435fb5bbbdefc62c41834eadc5622ad942
634 | languageName: node
635 | linkType: hard
636 |
637 | "styled-jsx@npm:5.1.6":
638 | version: 5.1.6
639 | resolution: "styled-jsx@npm:5.1.6"
640 | dependencies:
641 | client-only: 0.0.1
642 | peerDependencies:
643 | react: ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0"
644 | peerDependenciesMeta:
645 | "@babel/core":
646 | optional: true
647 | babel-plugin-macros:
648 | optional: true
649 | checksum: 879ad68e3e81adcf4373038aaafe55f968294955593660e173fbf679204aff158c59966716a60b29af72dc88795cfb2c479b6d2c3c87b2b2d282f3e27cc66461
650 | languageName: node
651 | linkType: hard
652 |
653 | "tslib@npm:^2.4.0":
654 | version: 2.8.1
655 | resolution: "tslib@npm:2.8.1"
656 | checksum: e4aba30e632b8c8902b47587fd13345e2827fa639e7c3121074d5ee0880723282411a8838f830b55100cbe4517672f84a2472667d355b81e8af165a55dc6203a
657 | languageName: node
658 | linkType: hard
659 |
660 | "typescript@npm:5.6.3":
661 | version: 5.6.3
662 | resolution: "typescript@npm:5.6.3"
663 | bin:
664 | tsc: bin/tsc
665 | tsserver: bin/tsserver
666 | checksum: ba302f8822777ebefb28b554105f3e074466b671e7444ec6b75dadc008a62f46f373d9e57ceced1c433756d06c8b7dc569a7eefdf3a9573122a49205ff99021a
667 | languageName: node
668 | linkType: hard
669 |
670 | "typescript@patch:typescript@5.6.3#~builtin":
671 | version: 5.6.3
672 | resolution: "typescript@patch:typescript@npm%3A5.6.3#~builtin::version=5.6.3&hash=5da071"
673 | bin:
674 | tsc: bin/tsc
675 | tsserver: bin/tsserver
676 | checksum: ade87bce2363ee963eed0e4ca8a312ea02c81873ebd53609bc3f6dc0a57f6e61ad7e3fb8cbb7f7ab8b5081cbee801b023f7c4823ee70b1c447eae050e6c7622b
677 | languageName: node
678 | linkType: hard
679 |
680 | "undici-types@npm:~6.19.8":
681 | version: 6.19.8
682 | resolution: "undici-types@npm:6.19.8"
683 | checksum: de51f1b447d22571cf155dfe14ff6d12c5bdaec237c765085b439c38ca8518fc360e88c70f99469162bf2e14188a7b0bcb06e1ed2dc031042b984b0bb9544017
684 | languageName: node
685 | linkType: hard
686 |
--------------------------------------------------------------------------------
/example/app-router/.pnp.loader.mjs:
--------------------------------------------------------------------------------
1 | import { URL as URL$1, fileURLToPath, pathToFileURL } from 'url';
2 | import fs from 'fs';
3 | import path from 'path';
4 | import moduleExports, { Module } from 'module';
5 | import { EOL } from 'os';
6 | import assert from 'assert';
7 |
8 | const SAFE_TIME = 456789e3;
9 |
10 | const PortablePath = {
11 | root: `/`,
12 | dot: `.`,
13 | parent: `..`
14 | };
15 | const npath = Object.create(path);
16 | const ppath = Object.create(path.posix);
17 | npath.cwd = () => process.cwd();
18 | ppath.cwd = () => toPortablePath(process.cwd());
19 | ppath.resolve = (...segments) => {
20 | if (segments.length > 0 && ppath.isAbsolute(segments[0])) {
21 | return path.posix.resolve(...segments);
22 | } else {
23 | return path.posix.resolve(ppath.cwd(), ...segments);
24 | }
25 | };
26 | const contains = function(pathUtils, from, to) {
27 | from = pathUtils.normalize(from);
28 | to = pathUtils.normalize(to);
29 | if (from === to)
30 | return `.`;
31 | if (!from.endsWith(pathUtils.sep))
32 | from = from + pathUtils.sep;
33 | if (to.startsWith(from)) {
34 | return to.slice(from.length);
35 | } else {
36 | return null;
37 | }
38 | };
39 | npath.fromPortablePath = fromPortablePath;
40 | npath.toPortablePath = toPortablePath;
41 | npath.contains = (from, to) => contains(npath, from, to);
42 | ppath.contains = (from, to) => contains(ppath, from, to);
43 | const WINDOWS_PATH_REGEXP = /^([a-zA-Z]:.*)$/;
44 | const UNC_WINDOWS_PATH_REGEXP = /^\/\/(\.\/)?(.*)$/;
45 | const PORTABLE_PATH_REGEXP = /^\/([a-zA-Z]:.*)$/;
46 | const UNC_PORTABLE_PATH_REGEXP = /^\/unc\/(\.dot\/)?(.*)$/;
47 | function fromPortablePath(p) {
48 | if (process.platform !== `win32`)
49 | return p;
50 | let portablePathMatch, uncPortablePathMatch;
51 | if (portablePathMatch = p.match(PORTABLE_PATH_REGEXP))
52 | p = portablePathMatch[1];
53 | else if (uncPortablePathMatch = p.match(UNC_PORTABLE_PATH_REGEXP))
54 | p = `\\\\${uncPortablePathMatch[1] ? `.\\` : ``}${uncPortablePathMatch[2]}`;
55 | else
56 | return p;
57 | return p.replace(/\//g, `\\`);
58 | }
59 | function toPortablePath(p) {
60 | if (process.platform !== `win32`)
61 | return p;
62 | p = p.replace(/\\/g, `/`);
63 | let windowsPathMatch, uncWindowsPathMatch;
64 | if (windowsPathMatch = p.match(WINDOWS_PATH_REGEXP))
65 | p = `/${windowsPathMatch[1]}`;
66 | else if (uncWindowsPathMatch = p.match(UNC_WINDOWS_PATH_REGEXP))
67 | p = `/unc/${uncWindowsPathMatch[1] ? `.dot/` : ``}${uncWindowsPathMatch[2]}`;
68 | return p;
69 | }
70 | function convertPath(targetPathUtils, sourcePath) {
71 | return targetPathUtils === npath ? fromPortablePath(sourcePath) : toPortablePath(sourcePath);
72 | }
73 |
74 | const defaultTime = new Date(SAFE_TIME * 1e3);
75 | async function copyPromise(destinationFs, destination, sourceFs, source, opts) {
76 | const normalizedDestination = destinationFs.pathUtils.normalize(destination);
77 | const normalizedSource = sourceFs.pathUtils.normalize(source);
78 | const prelayout = [];
79 | const postlayout = [];
80 | const { atime, mtime } = opts.stableTime ? { atime: defaultTime, mtime: defaultTime } : await sourceFs.lstatPromise(normalizedSource);
81 | await destinationFs.mkdirpPromise(destinationFs.pathUtils.dirname(destination), { utimes: [atime, mtime] });
82 | const updateTime = typeof destinationFs.lutimesPromise === `function` ? destinationFs.lutimesPromise.bind(destinationFs) : destinationFs.utimesPromise.bind(destinationFs);
83 | await copyImpl(prelayout, postlayout, updateTime, destinationFs, normalizedDestination, sourceFs, normalizedSource, { ...opts, didParentExist: true });
84 | for (const operation of prelayout)
85 | await operation();
86 | await Promise.all(postlayout.map((operation) => {
87 | return operation();
88 | }));
89 | }
90 | async function copyImpl(prelayout, postlayout, updateTime, destinationFs, destination, sourceFs, source, opts) {
91 | var _a, _b;
92 | const destinationStat = opts.didParentExist ? await maybeLStat(destinationFs, destination) : null;
93 | const sourceStat = await sourceFs.lstatPromise(source);
94 | const { atime, mtime } = opts.stableTime ? { atime: defaultTime, mtime: defaultTime } : sourceStat;
95 | let updated;
96 | switch (true) {
97 | case sourceStat.isDirectory():
98 | {
99 | updated = await copyFolder(prelayout, postlayout, updateTime, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts);
100 | }
101 | break;
102 | case sourceStat.isFile():
103 | {
104 | updated = await copyFile(prelayout, postlayout, updateTime, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts);
105 | }
106 | break;
107 | case sourceStat.isSymbolicLink():
108 | {
109 | updated = await copySymlink(prelayout, postlayout, updateTime, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts);
110 | }
111 | break;
112 | default:
113 | {
114 | throw new Error(`Unsupported file type (${sourceStat.mode})`);
115 | }
116 | }
117 | if (updated || ((_a = destinationStat == null ? void 0 : destinationStat.mtime) == null ? void 0 : _a.getTime()) !== mtime.getTime() || ((_b = destinationStat == null ? void 0 : destinationStat.atime) == null ? void 0 : _b.getTime()) !== atime.getTime()) {
118 | postlayout.push(() => updateTime(destination, atime, mtime));
119 | updated = true;
120 | }
121 | if (destinationStat === null || (destinationStat.mode & 511) !== (sourceStat.mode & 511)) {
122 | postlayout.push(() => destinationFs.chmodPromise(destination, sourceStat.mode & 511));
123 | updated = true;
124 | }
125 | return updated;
126 | }
127 | async function maybeLStat(baseFs, p) {
128 | try {
129 | return await baseFs.lstatPromise(p);
130 | } catch (e) {
131 | return null;
132 | }
133 | }
134 | async function copyFolder(prelayout, postlayout, updateTime, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts) {
135 | if (destinationStat !== null && !destinationStat.isDirectory()) {
136 | if (opts.overwrite) {
137 | prelayout.push(async () => destinationFs.removePromise(destination));
138 | destinationStat = null;
139 | } else {
140 | return false;
141 | }
142 | }
143 | let updated = false;
144 | if (destinationStat === null) {
145 | prelayout.push(async () => {
146 | try {
147 | await destinationFs.mkdirPromise(destination, { mode: sourceStat.mode });
148 | } catch (err) {
149 | if (err.code !== `EEXIST`) {
150 | throw err;
151 | }
152 | }
153 | });
154 | updated = true;
155 | }
156 | const entries = await sourceFs.readdirPromise(source);
157 | const nextOpts = opts.didParentExist && !destinationStat ? { ...opts, didParentExist: false } : opts;
158 | if (opts.stableSort) {
159 | for (const entry of entries.sort()) {
160 | if (await copyImpl(prelayout, postlayout, updateTime, destinationFs, destinationFs.pathUtils.join(destination, entry), sourceFs, sourceFs.pathUtils.join(source, entry), nextOpts)) {
161 | updated = true;
162 | }
163 | }
164 | } else {
165 | const entriesUpdateStatus = await Promise.all(entries.map(async (entry) => {
166 | await copyImpl(prelayout, postlayout, updateTime, destinationFs, destinationFs.pathUtils.join(destination, entry), sourceFs, sourceFs.pathUtils.join(source, entry), nextOpts);
167 | }));
168 | if (entriesUpdateStatus.some((status) => status)) {
169 | updated = true;
170 | }
171 | }
172 | return updated;
173 | }
174 | const isCloneSupportedCache = /* @__PURE__ */ new WeakMap();
175 | function makeLinkOperation(opFs, destination, source, sourceStat, linkStrategy) {
176 | return async () => {
177 | await opFs.linkPromise(source, destination);
178 | if (linkStrategy === "readOnly" /* ReadOnly */) {
179 | sourceStat.mode &= ~146;
180 | await opFs.chmodPromise(destination, sourceStat.mode);
181 | }
182 | };
183 | }
184 | function makeCloneLinkOperation(opFs, destination, source, sourceStat, linkStrategy) {
185 | const isCloneSupported = isCloneSupportedCache.get(opFs);
186 | if (typeof isCloneSupported === `undefined`) {
187 | return async () => {
188 | try {
189 | await opFs.copyFilePromise(source, destination, fs.constants.COPYFILE_FICLONE_FORCE);
190 | isCloneSupportedCache.set(opFs, true);
191 | } catch (err) {
192 | if (err.code === `ENOSYS` || err.code === `ENOTSUP`) {
193 | isCloneSupportedCache.set(opFs, false);
194 | await makeLinkOperation(opFs, destination, source, sourceStat, linkStrategy)();
195 | } else {
196 | throw err;
197 | }
198 | }
199 | };
200 | } else {
201 | if (isCloneSupported) {
202 | return async () => opFs.copyFilePromise(source, destination, fs.constants.COPYFILE_FICLONE_FORCE);
203 | } else {
204 | return makeLinkOperation(opFs, destination, source, sourceStat, linkStrategy);
205 | }
206 | }
207 | }
208 | async function copyFile(prelayout, postlayout, updateTime, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts) {
209 | var _a;
210 | if (destinationStat !== null) {
211 | if (opts.overwrite) {
212 | prelayout.push(async () => destinationFs.removePromise(destination));
213 | destinationStat = null;
214 | } else {
215 | return false;
216 | }
217 | }
218 | const linkStrategy = (_a = opts.linkStrategy) != null ? _a : null;
219 | const op = destinationFs === sourceFs ? linkStrategy !== null ? makeCloneLinkOperation(destinationFs, destination, source, sourceStat, linkStrategy) : async () => destinationFs.copyFilePromise(source, destination, fs.constants.COPYFILE_FICLONE) : linkStrategy !== null ? makeLinkOperation(destinationFs, destination, source, sourceStat, linkStrategy) : async () => destinationFs.writeFilePromise(destination, await sourceFs.readFilePromise(source));
220 | prelayout.push(async () => op());
221 | return true;
222 | }
223 | async function copySymlink(prelayout, postlayout, updateTime, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts) {
224 | if (destinationStat !== null) {
225 | if (opts.overwrite) {
226 | prelayout.push(async () => destinationFs.removePromise(destination));
227 | destinationStat = null;
228 | } else {
229 | return false;
230 | }
231 | }
232 | prelayout.push(async () => {
233 | await destinationFs.symlinkPromise(convertPath(destinationFs.pathUtils, await sourceFs.readlinkPromise(source)), destination);
234 | });
235 | return true;
236 | }
237 |
238 | function makeError(code, message) {
239 | return Object.assign(new Error(`${code}: ${message}`), { code });
240 | }
241 | function ENOSYS(message, reason) {
242 | return makeError(`ENOSYS`, `${message}, ${reason}`);
243 | }
244 |
245 | class FakeFS {
246 | constructor(pathUtils) {
247 | this.pathUtils = pathUtils;
248 | }
249 | async *genTraversePromise(init, { stableSort = false } = {}) {
250 | const stack = [init];
251 | while (stack.length > 0) {
252 | const p = stack.shift();
253 | const entry = await this.lstatPromise(p);
254 | if (entry.isDirectory()) {
255 | const entries = await this.readdirPromise(p);
256 | if (stableSort) {
257 | for (const entry2 of entries.sort()) {
258 | stack.push(this.pathUtils.join(p, entry2));
259 | }
260 | } else {
261 | throw new Error(`Not supported`);
262 | }
263 | } else {
264 | yield p;
265 | }
266 | }
267 | }
268 | async removePromise(p, { recursive = true, maxRetries = 5 } = {}) {
269 | let stat;
270 | try {
271 | stat = await this.lstatPromise(p);
272 | } catch (error) {
273 | if (error.code === `ENOENT`) {
274 | return;
275 | } else {
276 | throw error;
277 | }
278 | }
279 | if (stat.isDirectory()) {
280 | if (recursive) {
281 | const entries = await this.readdirPromise(p);
282 | await Promise.all(entries.map((entry) => {
283 | return this.removePromise(this.pathUtils.resolve(p, entry));
284 | }));
285 | }
286 | for (let t = 0; t <= maxRetries; t++) {
287 | try {
288 | await this.rmdirPromise(p);
289 | break;
290 | } catch (error) {
291 | if (error.code !== `EBUSY` && error.code !== `ENOTEMPTY`) {
292 | throw error;
293 | } else if (t < maxRetries) {
294 | await new Promise((resolve) => setTimeout(resolve, t * 100));
295 | }
296 | }
297 | }
298 | } else {
299 | await this.unlinkPromise(p);
300 | }
301 | }
302 | removeSync(p, { recursive = true } = {}) {
303 | let stat;
304 | try {
305 | stat = this.lstatSync(p);
306 | } catch (error) {
307 | if (error.code === `ENOENT`) {
308 | return;
309 | } else {
310 | throw error;
311 | }
312 | }
313 | if (stat.isDirectory()) {
314 | if (recursive)
315 | for (const entry of this.readdirSync(p))
316 | this.removeSync(this.pathUtils.resolve(p, entry));
317 | this.rmdirSync(p);
318 | } else {
319 | this.unlinkSync(p);
320 | }
321 | }
322 | async mkdirpPromise(p, { chmod, utimes } = {}) {
323 | p = this.resolve(p);
324 | if (p === this.pathUtils.dirname(p))
325 | return void 0;
326 | const parts = p.split(this.pathUtils.sep);
327 | let createdDirectory;
328 | for (let u = 2; u <= parts.length; ++u) {
329 | const subPath = parts.slice(0, u).join(this.pathUtils.sep);
330 | if (!this.existsSync(subPath)) {
331 | try {
332 | await this.mkdirPromise(subPath);
333 | } catch (error) {
334 | if (error.code === `EEXIST`) {
335 | continue;
336 | } else {
337 | throw error;
338 | }
339 | }
340 | createdDirectory != null ? createdDirectory : createdDirectory = subPath;
341 | if (chmod != null)
342 | await this.chmodPromise(subPath, chmod);
343 | if (utimes != null) {
344 | await this.utimesPromise(subPath, utimes[0], utimes[1]);
345 | } else {
346 | const parentStat = await this.statPromise(this.pathUtils.dirname(subPath));
347 | await this.utimesPromise(subPath, parentStat.atime, parentStat.mtime);
348 | }
349 | }
350 | }
351 | return createdDirectory;
352 | }
353 | mkdirpSync(p, { chmod, utimes } = {}) {
354 | p = this.resolve(p);
355 | if (p === this.pathUtils.dirname(p))
356 | return void 0;
357 | const parts = p.split(this.pathUtils.sep);
358 | let createdDirectory;
359 | for (let u = 2; u <= parts.length; ++u) {
360 | const subPath = parts.slice(0, u).join(this.pathUtils.sep);
361 | if (!this.existsSync(subPath)) {
362 | try {
363 | this.mkdirSync(subPath);
364 | } catch (error) {
365 | if (error.code === `EEXIST`) {
366 | continue;
367 | } else {
368 | throw error;
369 | }
370 | }
371 | createdDirectory != null ? createdDirectory : createdDirectory = subPath;
372 | if (chmod != null)
373 | this.chmodSync(subPath, chmod);
374 | if (utimes != null) {
375 | this.utimesSync(subPath, utimes[0], utimes[1]);
376 | } else {
377 | const parentStat = this.statSync(this.pathUtils.dirname(subPath));
378 | this.utimesSync(subPath, parentStat.atime, parentStat.mtime);
379 | }
380 | }
381 | }
382 | return createdDirectory;
383 | }
384 | async copyPromise(destination, source, { baseFs = this, overwrite = true, stableSort = false, stableTime = false, linkStrategy = null } = {}) {
385 | return await copyPromise(this, destination, baseFs, source, { overwrite, stableSort, stableTime, linkStrategy });
386 | }
387 | copySync(destination, source, { baseFs = this, overwrite = true } = {}) {
388 | const stat = baseFs.lstatSync(source);
389 | const exists = this.existsSync(destination);
390 | if (stat.isDirectory()) {
391 | this.mkdirpSync(destination);
392 | const directoryListing = baseFs.readdirSync(source);
393 | for (const entry of directoryListing) {
394 | this.copySync(this.pathUtils.join(destination, entry), baseFs.pathUtils.join(source, entry), { baseFs, overwrite });
395 | }
396 | } else if (stat.isFile()) {
397 | if (!exists || overwrite) {
398 | if (exists)
399 | this.removeSync(destination);
400 | const content = baseFs.readFileSync(source);
401 | this.writeFileSync(destination, content);
402 | }
403 | } else if (stat.isSymbolicLink()) {
404 | if (!exists || overwrite) {
405 | if (exists)
406 | this.removeSync(destination);
407 | const target = baseFs.readlinkSync(source);
408 | this.symlinkSync(convertPath(this.pathUtils, target), destination);
409 | }
410 | } else {
411 | throw new Error(`Unsupported file type (file: ${source}, mode: 0o${stat.mode.toString(8).padStart(6, `0`)})`);
412 | }
413 | const mode = stat.mode & 511;
414 | this.chmodSync(destination, mode);
415 | }
416 | async changeFilePromise(p, content, opts = {}) {
417 | if (Buffer.isBuffer(content)) {
418 | return this.changeFileBufferPromise(p, content, opts);
419 | } else {
420 | return this.changeFileTextPromise(p, content, opts);
421 | }
422 | }
423 | async changeFileBufferPromise(p, content, { mode } = {}) {
424 | let current = Buffer.alloc(0);
425 | try {
426 | current = await this.readFilePromise(p);
427 | } catch (error) {
428 | }
429 | if (Buffer.compare(current, content) === 0)
430 | return;
431 | await this.writeFilePromise(p, content, { mode });
432 | }
433 | async changeFileTextPromise(p, content, { automaticNewlines, mode } = {}) {
434 | let current = ``;
435 | try {
436 | current = await this.readFilePromise(p, `utf8`);
437 | } catch (error) {
438 | }
439 | const normalizedContent = automaticNewlines ? normalizeLineEndings(current, content) : content;
440 | if (current === normalizedContent)
441 | return;
442 | await this.writeFilePromise(p, normalizedContent, { mode });
443 | }
444 | changeFileSync(p, content, opts = {}) {
445 | if (Buffer.isBuffer(content)) {
446 | return this.changeFileBufferSync(p, content, opts);
447 | } else {
448 | return this.changeFileTextSync(p, content, opts);
449 | }
450 | }
451 | changeFileBufferSync(p, content, { mode } = {}) {
452 | let current = Buffer.alloc(0);
453 | try {
454 | current = this.readFileSync(p);
455 | } catch (error) {
456 | }
457 | if (Buffer.compare(current, content) === 0)
458 | return;
459 | this.writeFileSync(p, content, { mode });
460 | }
461 | changeFileTextSync(p, content, { automaticNewlines = false, mode } = {}) {
462 | let current = ``;
463 | try {
464 | current = this.readFileSync(p, `utf8`);
465 | } catch (error) {
466 | }
467 | const normalizedContent = automaticNewlines ? normalizeLineEndings(current, content) : content;
468 | if (current === normalizedContent)
469 | return;
470 | this.writeFileSync(p, normalizedContent, { mode });
471 | }
472 | async movePromise(fromP, toP) {
473 | try {
474 | await this.renamePromise(fromP, toP);
475 | } catch (error) {
476 | if (error.code === `EXDEV`) {
477 | await this.copyPromise(toP, fromP);
478 | await this.removePromise(fromP);
479 | } else {
480 | throw error;
481 | }
482 | }
483 | }
484 | moveSync(fromP, toP) {
485 | try {
486 | this.renameSync(fromP, toP);
487 | } catch (error) {
488 | if (error.code === `EXDEV`) {
489 | this.copySync(toP, fromP);
490 | this.removeSync(fromP);
491 | } else {
492 | throw error;
493 | }
494 | }
495 | }
496 | async lockPromise(affectedPath, callback) {
497 | const lockPath = `${affectedPath}.flock`;
498 | const interval = 1e3 / 60;
499 | const startTime = Date.now();
500 | let fd = null;
501 | const isAlive = async () => {
502 | let pid;
503 | try {
504 | [pid] = await this.readJsonPromise(lockPath);
505 | } catch (error) {
506 | return Date.now() - startTime < 500;
507 | }
508 | try {
509 | process.kill(pid, 0);
510 | return true;
511 | } catch (error) {
512 | return false;
513 | }
514 | };
515 | while (fd === null) {
516 | try {
517 | fd = await this.openPromise(lockPath, `wx`);
518 | } catch (error) {
519 | if (error.code === `EEXIST`) {
520 | if (!await isAlive()) {
521 | try {
522 | await this.unlinkPromise(lockPath);
523 | continue;
524 | } catch (error2) {
525 | }
526 | }
527 | if (Date.now() - startTime < 60 * 1e3) {
528 | await new Promise((resolve) => setTimeout(resolve, interval));
529 | } else {
530 | throw new Error(`Couldn't acquire a lock in a reasonable time (via ${lockPath})`);
531 | }
532 | } else {
533 | throw error;
534 | }
535 | }
536 | }
537 | await this.writePromise(fd, JSON.stringify([process.pid]));
538 | try {
539 | return await callback();
540 | } finally {
541 | try {
542 | await this.closePromise(fd);
543 | await this.unlinkPromise(lockPath);
544 | } catch (error) {
545 | }
546 | }
547 | }
548 | async readJsonPromise(p) {
549 | const content = await this.readFilePromise(p, `utf8`);
550 | try {
551 | return JSON.parse(content);
552 | } catch (error) {
553 | error.message += ` (in ${p})`;
554 | throw error;
555 | }
556 | }
557 | readJsonSync(p) {
558 | const content = this.readFileSync(p, `utf8`);
559 | try {
560 | return JSON.parse(content);
561 | } catch (error) {
562 | error.message += ` (in ${p})`;
563 | throw error;
564 | }
565 | }
566 | async writeJsonPromise(p, data) {
567 | return await this.writeFilePromise(p, `${JSON.stringify(data, null, 2)}
568 | `);
569 | }
570 | writeJsonSync(p, data) {
571 | return this.writeFileSync(p, `${JSON.stringify(data, null, 2)}
572 | `);
573 | }
574 | async preserveTimePromise(p, cb) {
575 | const stat = await this.lstatPromise(p);
576 | const result = await cb();
577 | if (typeof result !== `undefined`)
578 | p = result;
579 | if (this.lutimesPromise) {
580 | await this.lutimesPromise(p, stat.atime, stat.mtime);
581 | } else if (!stat.isSymbolicLink()) {
582 | await this.utimesPromise(p, stat.atime, stat.mtime);
583 | }
584 | }
585 | async preserveTimeSync(p, cb) {
586 | const stat = this.lstatSync(p);
587 | const result = cb();
588 | if (typeof result !== `undefined`)
589 | p = result;
590 | if (this.lutimesSync) {
591 | this.lutimesSync(p, stat.atime, stat.mtime);
592 | } else if (!stat.isSymbolicLink()) {
593 | this.utimesSync(p, stat.atime, stat.mtime);
594 | }
595 | }
596 | }
597 | class BasePortableFakeFS extends FakeFS {
598 | constructor() {
599 | super(ppath);
600 | }
601 | }
602 | function getEndOfLine(content) {
603 | const matches = content.match(/\r?\n/g);
604 | if (matches === null)
605 | return EOL;
606 | const crlf = matches.filter((nl) => nl === `\r
607 | `).length;
608 | const lf = matches.length - crlf;
609 | return crlf > lf ? `\r
610 | ` : `
611 | `;
612 | }
613 | function normalizeLineEndings(originalContent, newContent) {
614 | return newContent.replace(/\r?\n/g, getEndOfLine(originalContent));
615 | }
616 |
617 | class NodeFS extends BasePortableFakeFS {
618 | constructor(realFs = fs) {
619 | super();
620 | this.realFs = realFs;
621 | if (typeof this.realFs.lutimes !== `undefined`) {
622 | this.lutimesPromise = this.lutimesPromiseImpl;
623 | this.lutimesSync = this.lutimesSyncImpl;
624 | }
625 | }
626 | getExtractHint() {
627 | return false;
628 | }
629 | getRealPath() {
630 | return PortablePath.root;
631 | }
632 | resolve(p) {
633 | return ppath.resolve(p);
634 | }
635 | async openPromise(p, flags, mode) {
636 | return await new Promise((resolve, reject) => {
637 | this.realFs.open(npath.fromPortablePath(p), flags, mode, this.makeCallback(resolve, reject));
638 | });
639 | }
640 | openSync(p, flags, mode) {
641 | return this.realFs.openSync(npath.fromPortablePath(p), flags, mode);
642 | }
643 | async opendirPromise(p, opts) {
644 | return await new Promise((resolve, reject) => {
645 | if (typeof opts !== `undefined`) {
646 | this.realFs.opendir(npath.fromPortablePath(p), opts, this.makeCallback(resolve, reject));
647 | } else {
648 | this.realFs.opendir(npath.fromPortablePath(p), this.makeCallback(resolve, reject));
649 | }
650 | }).then((dir) => {
651 | return Object.defineProperty(dir, `path`, { value: p, configurable: true, writable: true });
652 | });
653 | }
654 | opendirSync(p, opts) {
655 | const dir = typeof opts !== `undefined` ? this.realFs.opendirSync(npath.fromPortablePath(p), opts) : this.realFs.opendirSync(npath.fromPortablePath(p));
656 | return Object.defineProperty(dir, `path`, { value: p, configurable: true, writable: true });
657 | }
658 | async readPromise(fd, buffer, offset = 0, length = 0, position = -1) {
659 | return await new Promise((resolve, reject) => {
660 | this.realFs.read(fd, buffer, offset, length, position, (error, bytesRead) => {
661 | if (error) {
662 | reject(error);
663 | } else {
664 | resolve(bytesRead);
665 | }
666 | });
667 | });
668 | }
669 | readSync(fd, buffer, offset, length, position) {
670 | return this.realFs.readSync(fd, buffer, offset, length, position);
671 | }
672 | async writePromise(fd, buffer, offset, length, position) {
673 | return await new Promise((resolve, reject) => {
674 | if (typeof buffer === `string`) {
675 | return this.realFs.write(fd, buffer, offset, this.makeCallback(resolve, reject));
676 | } else {
677 | return this.realFs.write(fd, buffer, offset, length, position, this.makeCallback(resolve, reject));
678 | }
679 | });
680 | }
681 | writeSync(fd, buffer, offset, length, position) {
682 | if (typeof buffer === `string`) {
683 | return this.realFs.writeSync(fd, buffer, offset);
684 | } else {
685 | return this.realFs.writeSync(fd, buffer, offset, length, position);
686 | }
687 | }
688 | async closePromise(fd) {
689 | await new Promise((resolve, reject) => {
690 | this.realFs.close(fd, this.makeCallback(resolve, reject));
691 | });
692 | }
693 | closeSync(fd) {
694 | this.realFs.closeSync(fd);
695 | }
696 | createReadStream(p, opts) {
697 | const realPath = p !== null ? npath.fromPortablePath(p) : p;
698 | return this.realFs.createReadStream(realPath, opts);
699 | }
700 | createWriteStream(p, opts) {
701 | const realPath = p !== null ? npath.fromPortablePath(p) : p;
702 | return this.realFs.createWriteStream(realPath, opts);
703 | }
704 | async realpathPromise(p) {
705 | return await new Promise((resolve, reject) => {
706 | this.realFs.realpath(npath.fromPortablePath(p), {}, this.makeCallback(resolve, reject));
707 | }).then((path) => {
708 | return npath.toPortablePath(path);
709 | });
710 | }
711 | realpathSync(p) {
712 | return npath.toPortablePath(this.realFs.realpathSync(npath.fromPortablePath(p), {}));
713 | }
714 | async existsPromise(p) {
715 | return await new Promise((resolve) => {
716 | this.realFs.exists(npath.fromPortablePath(p), resolve);
717 | });
718 | }
719 | accessSync(p, mode) {
720 | return this.realFs.accessSync(npath.fromPortablePath(p), mode);
721 | }
722 | async accessPromise(p, mode) {
723 | return await new Promise((resolve, reject) => {
724 | this.realFs.access(npath.fromPortablePath(p), mode, this.makeCallback(resolve, reject));
725 | });
726 | }
727 | existsSync(p) {
728 | return this.realFs.existsSync(npath.fromPortablePath(p));
729 | }
730 | async statPromise(p, opts) {
731 | return await new Promise((resolve, reject) => {
732 | if (opts) {
733 | this.realFs.stat(npath.fromPortablePath(p), opts, this.makeCallback(resolve, reject));
734 | } else {
735 | this.realFs.stat(npath.fromPortablePath(p), this.makeCallback(resolve, reject));
736 | }
737 | });
738 | }
739 | statSync(p, opts) {
740 | if (opts) {
741 | return this.realFs.statSync(npath.fromPortablePath(p), opts);
742 | } else {
743 | return this.realFs.statSync(npath.fromPortablePath(p));
744 | }
745 | }
746 | async fstatPromise(fd, opts) {
747 | return await new Promise((resolve, reject) => {
748 | if (opts) {
749 | this.realFs.fstat(fd, opts, this.makeCallback(resolve, reject));
750 | } else {
751 | this.realFs.fstat(fd, this.makeCallback(resolve, reject));
752 | }
753 | });
754 | }
755 | fstatSync(fd, opts) {
756 | if (opts) {
757 | return this.realFs.fstatSync(fd, opts);
758 | } else {
759 | return this.realFs.fstatSync(fd);
760 | }
761 | }
762 | async lstatPromise(p, opts) {
763 | return await new Promise((resolve, reject) => {
764 | if (opts) {
765 | this.realFs.lstat(npath.fromPortablePath(p), opts, this.makeCallback(resolve, reject));
766 | } else {
767 | this.realFs.lstat(npath.fromPortablePath(p), this.makeCallback(resolve, reject));
768 | }
769 | });
770 | }
771 | lstatSync(p, opts) {
772 | if (opts) {
773 | return this.realFs.lstatSync(npath.fromPortablePath(p), opts);
774 | } else {
775 | return this.realFs.lstatSync(npath.fromPortablePath(p));
776 | }
777 | }
778 | async fchmodPromise(fd, mask) {
779 | return await new Promise((resolve, reject) => {
780 | this.realFs.fchmod(fd, mask, this.makeCallback(resolve, reject));
781 | });
782 | }
783 | fchmodSync(fd, mask) {
784 | return this.realFs.fchmodSync(fd, mask);
785 | }
786 | async chmodPromise(p, mask) {
787 | return await new Promise((resolve, reject) => {
788 | this.realFs.chmod(npath.fromPortablePath(p), mask, this.makeCallback(resolve, reject));
789 | });
790 | }
791 | chmodSync(p, mask) {
792 | return this.realFs.chmodSync(npath.fromPortablePath(p), mask);
793 | }
794 | async fchownPromise(fd, uid, gid) {
795 | return await new Promise((resolve, reject) => {
796 | this.realFs.fchown(fd, uid, gid, this.makeCallback(resolve, reject));
797 | });
798 | }
799 | fchownSync(fd, uid, gid) {
800 | return this.realFs.fchownSync(fd, uid, gid);
801 | }
802 | async chownPromise(p, uid, gid) {
803 | return await new Promise((resolve, reject) => {
804 | this.realFs.chown(npath.fromPortablePath(p), uid, gid, this.makeCallback(resolve, reject));
805 | });
806 | }
807 | chownSync(p, uid, gid) {
808 | return this.realFs.chownSync(npath.fromPortablePath(p), uid, gid);
809 | }
810 | async renamePromise(oldP, newP) {
811 | return await new Promise((resolve, reject) => {
812 | this.realFs.rename(npath.fromPortablePath(oldP), npath.fromPortablePath(newP), this.makeCallback(resolve, reject));
813 | });
814 | }
815 | renameSync(oldP, newP) {
816 | return this.realFs.renameSync(npath.fromPortablePath(oldP), npath.fromPortablePath(newP));
817 | }
818 | async copyFilePromise(sourceP, destP, flags = 0) {
819 | return await new Promise((resolve, reject) => {
820 | this.realFs.copyFile(npath.fromPortablePath(sourceP), npath.fromPortablePath(destP), flags, this.makeCallback(resolve, reject));
821 | });
822 | }
823 | copyFileSync(sourceP, destP, flags = 0) {
824 | return this.realFs.copyFileSync(npath.fromPortablePath(sourceP), npath.fromPortablePath(destP), flags);
825 | }
826 | async appendFilePromise(p, content, opts) {
827 | return await new Promise((resolve, reject) => {
828 | const fsNativePath = typeof p === `string` ? npath.fromPortablePath(p) : p;
829 | if (opts) {
830 | this.realFs.appendFile(fsNativePath, content, opts, this.makeCallback(resolve, reject));
831 | } else {
832 | this.realFs.appendFile(fsNativePath, content, this.makeCallback(resolve, reject));
833 | }
834 | });
835 | }
836 | appendFileSync(p, content, opts) {
837 | const fsNativePath = typeof p === `string` ? npath.fromPortablePath(p) : p;
838 | if (opts) {
839 | this.realFs.appendFileSync(fsNativePath, content, opts);
840 | } else {
841 | this.realFs.appendFileSync(fsNativePath, content);
842 | }
843 | }
844 | async writeFilePromise(p, content, opts) {
845 | return await new Promise((resolve, reject) => {
846 | const fsNativePath = typeof p === `string` ? npath.fromPortablePath(p) : p;
847 | if (opts) {
848 | this.realFs.writeFile(fsNativePath, content, opts, this.makeCallback(resolve, reject));
849 | } else {
850 | this.realFs.writeFile(fsNativePath, content, this.makeCallback(resolve, reject));
851 | }
852 | });
853 | }
854 | writeFileSync(p, content, opts) {
855 | const fsNativePath = typeof p === `string` ? npath.fromPortablePath(p) : p;
856 | if (opts) {
857 | this.realFs.writeFileSync(fsNativePath, content, opts);
858 | } else {
859 | this.realFs.writeFileSync(fsNativePath, content);
860 | }
861 | }
862 | async unlinkPromise(p) {
863 | return await new Promise((resolve, reject) => {
864 | this.realFs.unlink(npath.fromPortablePath(p), this.makeCallback(resolve, reject));
865 | });
866 | }
867 | unlinkSync(p) {
868 | return this.realFs.unlinkSync(npath.fromPortablePath(p));
869 | }
870 | async utimesPromise(p, atime, mtime) {
871 | return await new Promise((resolve, reject) => {
872 | this.realFs.utimes(npath.fromPortablePath(p), atime, mtime, this.makeCallback(resolve, reject));
873 | });
874 | }
875 | utimesSync(p, atime, mtime) {
876 | this.realFs.utimesSync(npath.fromPortablePath(p), atime, mtime);
877 | }
878 | async lutimesPromiseImpl(p, atime, mtime) {
879 | const lutimes = this.realFs.lutimes;
880 | if (typeof lutimes === `undefined`)
881 | throw ENOSYS(`unavailable Node binding`, `lutimes '${p}'`);
882 | return await new Promise((resolve, reject) => {
883 | lutimes.call(this.realFs, npath.fromPortablePath(p), atime, mtime, this.makeCallback(resolve, reject));
884 | });
885 | }
886 | lutimesSyncImpl(p, atime, mtime) {
887 | const lutimesSync = this.realFs.lutimesSync;
888 | if (typeof lutimesSync === `undefined`)
889 | throw ENOSYS(`unavailable Node binding`, `lutimes '${p}'`);
890 | lutimesSync.call(this.realFs, npath.fromPortablePath(p), atime, mtime);
891 | }
892 | async mkdirPromise(p, opts) {
893 | return await new Promise((resolve, reject) => {
894 | this.realFs.mkdir(npath.fromPortablePath(p), opts, this.makeCallback(resolve, reject));
895 | });
896 | }
897 | mkdirSync(p, opts) {
898 | return this.realFs.mkdirSync(npath.fromPortablePath(p), opts);
899 | }
900 | async rmdirPromise(p, opts) {
901 | return await new Promise((resolve, reject) => {
902 | if (opts) {
903 | this.realFs.rmdir(npath.fromPortablePath(p), opts, this.makeCallback(resolve, reject));
904 | } else {
905 | this.realFs.rmdir(npath.fromPortablePath(p), this.makeCallback(resolve, reject));
906 | }
907 | });
908 | }
909 | rmdirSync(p, opts) {
910 | return this.realFs.rmdirSync(npath.fromPortablePath(p), opts);
911 | }
912 | async linkPromise(existingP, newP) {
913 | return await new Promise((resolve, reject) => {
914 | this.realFs.link(npath.fromPortablePath(existingP), npath.fromPortablePath(newP), this.makeCallback(resolve, reject));
915 | });
916 | }
917 | linkSync(existingP, newP) {
918 | return this.realFs.linkSync(npath.fromPortablePath(existingP), npath.fromPortablePath(newP));
919 | }
920 | async symlinkPromise(target, p, type) {
921 | return await new Promise((resolve, reject) => {
922 | this.realFs.symlink(npath.fromPortablePath(target.replace(/\/+$/, ``)), npath.fromPortablePath(p), type, this.makeCallback(resolve, reject));
923 | });
924 | }
925 | symlinkSync(target, p, type) {
926 | return this.realFs.symlinkSync(npath.fromPortablePath(target.replace(/\/+$/, ``)), npath.fromPortablePath(p), type);
927 | }
928 | async readFilePromise(p, encoding) {
929 | return await new Promise((resolve, reject) => {
930 | const fsNativePath = typeof p === `string` ? npath.fromPortablePath(p) : p;
931 | this.realFs.readFile(fsNativePath, encoding, this.makeCallback(resolve, reject));
932 | });
933 | }
934 | readFileSync(p, encoding) {
935 | const fsNativePath = typeof p === `string` ? npath.fromPortablePath(p) : p;
936 | return this.realFs.readFileSync(fsNativePath, encoding);
937 | }
938 | async readdirPromise(p, opts) {
939 | return await new Promise((resolve, reject) => {
940 | if (opts == null ? void 0 : opts.withFileTypes) {
941 | this.realFs.readdir(npath.fromPortablePath(p), { withFileTypes: true }, this.makeCallback(resolve, reject));
942 | } else {
943 | this.realFs.readdir(npath.fromPortablePath(p), this.makeCallback((value) => resolve(value), reject));
944 | }
945 | });
946 | }
947 | readdirSync(p, opts) {
948 | if (opts == null ? void 0 : opts.withFileTypes) {
949 | return this.realFs.readdirSync(npath.fromPortablePath(p), { withFileTypes: true });
950 | } else {
951 | return this.realFs.readdirSync(npath.fromPortablePath(p));
952 | }
953 | }
954 | async readlinkPromise(p) {
955 | return await new Promise((resolve, reject) => {
956 | this.realFs.readlink(npath.fromPortablePath(p), this.makeCallback(resolve, reject));
957 | }).then((path) => {
958 | return npath.toPortablePath(path);
959 | });
960 | }
961 | readlinkSync(p) {
962 | return npath.toPortablePath(this.realFs.readlinkSync(npath.fromPortablePath(p)));
963 | }
964 | async truncatePromise(p, len) {
965 | return await new Promise((resolve, reject) => {
966 | this.realFs.truncate(npath.fromPortablePath(p), len, this.makeCallback(resolve, reject));
967 | });
968 | }
969 | truncateSync(p, len) {
970 | return this.realFs.truncateSync(npath.fromPortablePath(p), len);
971 | }
972 | async ftruncatePromise(fd, len) {
973 | return await new Promise((resolve, reject) => {
974 | this.realFs.ftruncate(fd, len, this.makeCallback(resolve, reject));
975 | });
976 | }
977 | ftruncateSync(fd, len) {
978 | return this.realFs.ftruncateSync(fd, len);
979 | }
980 | watch(p, a, b) {
981 | return this.realFs.watch(
982 | npath.fromPortablePath(p),
983 | a,
984 | b
985 | );
986 | }
987 | watchFile(p, a, b) {
988 | return this.realFs.watchFile(
989 | npath.fromPortablePath(p),
990 | a,
991 | b
992 | );
993 | }
994 | unwatchFile(p, cb) {
995 | return this.realFs.unwatchFile(npath.fromPortablePath(p), cb);
996 | }
997 | makeCallback(resolve, reject) {
998 | return (err, result) => {
999 | if (err) {
1000 | reject(err);
1001 | } else {
1002 | resolve(result);
1003 | }
1004 | };
1005 | }
1006 | }
1007 |
1008 | class ProxiedFS extends FakeFS {
1009 | getExtractHint(hints) {
1010 | return this.baseFs.getExtractHint(hints);
1011 | }
1012 | resolve(path) {
1013 | return this.mapFromBase(this.baseFs.resolve(this.mapToBase(path)));
1014 | }
1015 | getRealPath() {
1016 | return this.mapFromBase(this.baseFs.getRealPath());
1017 | }
1018 | async openPromise(p, flags, mode) {
1019 | return this.baseFs.openPromise(this.mapToBase(p), flags, mode);
1020 | }
1021 | openSync(p, flags, mode) {
1022 | return this.baseFs.openSync(this.mapToBase(p), flags, mode);
1023 | }
1024 | async opendirPromise(p, opts) {
1025 | return Object.assign(await this.baseFs.opendirPromise(this.mapToBase(p), opts), { path: p });
1026 | }
1027 | opendirSync(p, opts) {
1028 | return Object.assign(this.baseFs.opendirSync(this.mapToBase(p), opts), { path: p });
1029 | }
1030 | async readPromise(fd, buffer, offset, length, position) {
1031 | return await this.baseFs.readPromise(fd, buffer, offset, length, position);
1032 | }
1033 | readSync(fd, buffer, offset, length, position) {
1034 | return this.baseFs.readSync(fd, buffer, offset, length, position);
1035 | }
1036 | async writePromise(fd, buffer, offset, length, position) {
1037 | if (typeof buffer === `string`) {
1038 | return await this.baseFs.writePromise(fd, buffer, offset);
1039 | } else {
1040 | return await this.baseFs.writePromise(fd, buffer, offset, length, position);
1041 | }
1042 | }
1043 | writeSync(fd, buffer, offset, length, position) {
1044 | if (typeof buffer === `string`) {
1045 | return this.baseFs.writeSync(fd, buffer, offset);
1046 | } else {
1047 | return this.baseFs.writeSync(fd, buffer, offset, length, position);
1048 | }
1049 | }
1050 | async closePromise(fd) {
1051 | return this.baseFs.closePromise(fd);
1052 | }
1053 | closeSync(fd) {
1054 | this.baseFs.closeSync(fd);
1055 | }
1056 | createReadStream(p, opts) {
1057 | return this.baseFs.createReadStream(p !== null ? this.mapToBase(p) : p, opts);
1058 | }
1059 | createWriteStream(p, opts) {
1060 | return this.baseFs.createWriteStream(p !== null ? this.mapToBase(p) : p, opts);
1061 | }
1062 | async realpathPromise(p) {
1063 | return this.mapFromBase(await this.baseFs.realpathPromise(this.mapToBase(p)));
1064 | }
1065 | realpathSync(p) {
1066 | return this.mapFromBase(this.baseFs.realpathSync(this.mapToBase(p)));
1067 | }
1068 | async existsPromise(p) {
1069 | return this.baseFs.existsPromise(this.mapToBase(p));
1070 | }
1071 | existsSync(p) {
1072 | return this.baseFs.existsSync(this.mapToBase(p));
1073 | }
1074 | accessSync(p, mode) {
1075 | return this.baseFs.accessSync(this.mapToBase(p), mode);
1076 | }
1077 | async accessPromise(p, mode) {
1078 | return this.baseFs.accessPromise(this.mapToBase(p), mode);
1079 | }
1080 | async statPromise(p, opts) {
1081 | return this.baseFs.statPromise(this.mapToBase(p), opts);
1082 | }
1083 | statSync(p, opts) {
1084 | return this.baseFs.statSync(this.mapToBase(p), opts);
1085 | }
1086 | async fstatPromise(fd, opts) {
1087 | return this.baseFs.fstatPromise(fd, opts);
1088 | }
1089 | fstatSync(fd, opts) {
1090 | return this.baseFs.fstatSync(fd, opts);
1091 | }
1092 | lstatPromise(p, opts) {
1093 | return this.baseFs.lstatPromise(this.mapToBase(p), opts);
1094 | }
1095 | lstatSync(p, opts) {
1096 | return this.baseFs.lstatSync(this.mapToBase(p), opts);
1097 | }
1098 | async fchmodPromise(fd, mask) {
1099 | return this.baseFs.fchmodPromise(fd, mask);
1100 | }
1101 | fchmodSync(fd, mask) {
1102 | return this.baseFs.fchmodSync(fd, mask);
1103 | }
1104 | async chmodPromise(p, mask) {
1105 | return this.baseFs.chmodPromise(this.mapToBase(p), mask);
1106 | }
1107 | chmodSync(p, mask) {
1108 | return this.baseFs.chmodSync(this.mapToBase(p), mask);
1109 | }
1110 | async fchownPromise(fd, uid, gid) {
1111 | return this.baseFs.fchownPromise(fd, uid, gid);
1112 | }
1113 | fchownSync(fd, uid, gid) {
1114 | return this.baseFs.fchownSync(fd, uid, gid);
1115 | }
1116 | async chownPromise(p, uid, gid) {
1117 | return this.baseFs.chownPromise(this.mapToBase(p), uid, gid);
1118 | }
1119 | chownSync(p, uid, gid) {
1120 | return this.baseFs.chownSync(this.mapToBase(p), uid, gid);
1121 | }
1122 | async renamePromise(oldP, newP) {
1123 | return this.baseFs.renamePromise(this.mapToBase(oldP), this.mapToBase(newP));
1124 | }
1125 | renameSync(oldP, newP) {
1126 | return this.baseFs.renameSync(this.mapToBase(oldP), this.mapToBase(newP));
1127 | }
1128 | async copyFilePromise(sourceP, destP, flags = 0) {
1129 | return this.baseFs.copyFilePromise(this.mapToBase(sourceP), this.mapToBase(destP), flags);
1130 | }
1131 | copyFileSync(sourceP, destP, flags = 0) {
1132 | return this.baseFs.copyFileSync(this.mapToBase(sourceP), this.mapToBase(destP), flags);
1133 | }
1134 | async appendFilePromise(p, content, opts) {
1135 | return this.baseFs.appendFilePromise(this.fsMapToBase(p), content, opts);
1136 | }
1137 | appendFileSync(p, content, opts) {
1138 | return this.baseFs.appendFileSync(this.fsMapToBase(p), content, opts);
1139 | }
1140 | async writeFilePromise(p, content, opts) {
1141 | return this.baseFs.writeFilePromise(this.fsMapToBase(p), content, opts);
1142 | }
1143 | writeFileSync(p, content, opts) {
1144 | return this.baseFs.writeFileSync(this.fsMapToBase(p), content, opts);
1145 | }
1146 | async unlinkPromise(p) {
1147 | return this.baseFs.unlinkPromise(this.mapToBase(p));
1148 | }
1149 | unlinkSync(p) {
1150 | return this.baseFs.unlinkSync(this.mapToBase(p));
1151 | }
1152 | async utimesPromise(p, atime, mtime) {
1153 | return this.baseFs.utimesPromise(this.mapToBase(p), atime, mtime);
1154 | }
1155 | utimesSync(p, atime, mtime) {
1156 | return this.baseFs.utimesSync(this.mapToBase(p), atime, mtime);
1157 | }
1158 | async mkdirPromise(p, opts) {
1159 | return this.baseFs.mkdirPromise(this.mapToBase(p), opts);
1160 | }
1161 | mkdirSync(p, opts) {
1162 | return this.baseFs.mkdirSync(this.mapToBase(p), opts);
1163 | }
1164 | async rmdirPromise(p, opts) {
1165 | return this.baseFs.rmdirPromise(this.mapToBase(p), opts);
1166 | }
1167 | rmdirSync(p, opts) {
1168 | return this.baseFs.rmdirSync(this.mapToBase(p), opts);
1169 | }
1170 | async linkPromise(existingP, newP) {
1171 | return this.baseFs.linkPromise(this.mapToBase(existingP), this.mapToBase(newP));
1172 | }
1173 | linkSync(existingP, newP) {
1174 | return this.baseFs.linkSync(this.mapToBase(existingP), this.mapToBase(newP));
1175 | }
1176 | async symlinkPromise(target, p, type) {
1177 | const mappedP = this.mapToBase(p);
1178 | if (this.pathUtils.isAbsolute(target))
1179 | return this.baseFs.symlinkPromise(this.mapToBase(target), mappedP, type);
1180 | const mappedAbsoluteTarget = this.mapToBase(this.pathUtils.join(this.pathUtils.dirname(p), target));
1181 | const mappedTarget = this.baseFs.pathUtils.relative(this.baseFs.pathUtils.dirname(mappedP), mappedAbsoluteTarget);
1182 | return this.baseFs.symlinkPromise(mappedTarget, mappedP, type);
1183 | }
1184 | symlinkSync(target, p, type) {
1185 | const mappedP = this.mapToBase(p);
1186 | if (this.pathUtils.isAbsolute(target))
1187 | return this.baseFs.symlinkSync(this.mapToBase(target), mappedP, type);
1188 | const mappedAbsoluteTarget = this.mapToBase(this.pathUtils.join(this.pathUtils.dirname(p), target));
1189 | const mappedTarget = this.baseFs.pathUtils.relative(this.baseFs.pathUtils.dirname(mappedP), mappedAbsoluteTarget);
1190 | return this.baseFs.symlinkSync(mappedTarget, mappedP, type);
1191 | }
1192 | async readFilePromise(p, encoding) {
1193 | if (encoding === `utf8`) {
1194 | return this.baseFs.readFilePromise(this.fsMapToBase(p), encoding);
1195 | } else {
1196 | return this.baseFs.readFilePromise(this.fsMapToBase(p), encoding);
1197 | }
1198 | }
1199 | readFileSync(p, encoding) {
1200 | if (encoding === `utf8`) {
1201 | return this.baseFs.readFileSync(this.fsMapToBase(p), encoding);
1202 | } else {
1203 | return this.baseFs.readFileSync(this.fsMapToBase(p), encoding);
1204 | }
1205 | }
1206 | async readdirPromise(p, opts) {
1207 | return this.baseFs.readdirPromise(this.mapToBase(p), opts);
1208 | }
1209 | readdirSync(p, opts) {
1210 | return this.baseFs.readdirSync(this.mapToBase(p), opts);
1211 | }
1212 | async readlinkPromise(p) {
1213 | return this.mapFromBase(await this.baseFs.readlinkPromise(this.mapToBase(p)));
1214 | }
1215 | readlinkSync(p) {
1216 | return this.mapFromBase(this.baseFs.readlinkSync(this.mapToBase(p)));
1217 | }
1218 | async truncatePromise(p, len) {
1219 | return this.baseFs.truncatePromise(this.mapToBase(p), len);
1220 | }
1221 | truncateSync(p, len) {
1222 | return this.baseFs.truncateSync(this.mapToBase(p), len);
1223 | }
1224 | async ftruncatePromise(fd, len) {
1225 | return this.baseFs.ftruncatePromise(fd, len);
1226 | }
1227 | ftruncateSync(fd, len) {
1228 | return this.baseFs.ftruncateSync(fd, len);
1229 | }
1230 | watch(p, a, b) {
1231 | return this.baseFs.watch(
1232 | this.mapToBase(p),
1233 | a,
1234 | b
1235 | );
1236 | }
1237 | watchFile(p, a, b) {
1238 | return this.baseFs.watchFile(
1239 | this.mapToBase(p),
1240 | a,
1241 | b
1242 | );
1243 | }
1244 | unwatchFile(p, cb) {
1245 | return this.baseFs.unwatchFile(this.mapToBase(p), cb);
1246 | }
1247 | fsMapToBase(p) {
1248 | if (typeof p === `number`) {
1249 | return p;
1250 | } else {
1251 | return this.mapToBase(p);
1252 | }
1253 | }
1254 | }
1255 |
1256 | const NUMBER_REGEXP = /^[0-9]+$/;
1257 | const VIRTUAL_REGEXP = /^(\/(?:[^/]+\/)*?(?:\$\$virtual|__virtual__))((?:\/((?:[^/]+-)?[a-f0-9]+)(?:\/([^/]+))?)?((?:\/.*)?))$/;
1258 | const VALID_COMPONENT = /^([^/]+-)?[a-f0-9]+$/;
1259 | class VirtualFS extends ProxiedFS {
1260 | constructor({ baseFs = new NodeFS() } = {}) {
1261 | super(ppath);
1262 | this.baseFs = baseFs;
1263 | }
1264 | static makeVirtualPath(base, component, to) {
1265 | if (ppath.basename(base) !== `__virtual__`)
1266 | throw new Error(`Assertion failed: Virtual folders must be named "__virtual__"`);
1267 | if (!ppath.basename(component).match(VALID_COMPONENT))
1268 | throw new Error(`Assertion failed: Virtual components must be ended by an hexadecimal hash`);
1269 | const target = ppath.relative(ppath.dirname(base), to);
1270 | const segments = target.split(`/`);
1271 | let depth = 0;
1272 | while (depth < segments.length && segments[depth] === `..`)
1273 | depth += 1;
1274 | const finalSegments = segments.slice(depth);
1275 | const fullVirtualPath = ppath.join(base, component, String(depth), ...finalSegments);
1276 | return fullVirtualPath;
1277 | }
1278 | static resolveVirtual(p) {
1279 | const match = p.match(VIRTUAL_REGEXP);
1280 | if (!match || !match[3] && match[5])
1281 | return p;
1282 | const target = ppath.dirname(match[1]);
1283 | if (!match[3] || !match[4])
1284 | return target;
1285 | const isnum = NUMBER_REGEXP.test(match[4]);
1286 | if (!isnum)
1287 | return p;
1288 | const depth = Number(match[4]);
1289 | const backstep = `../`.repeat(depth);
1290 | const subpath = match[5] || `.`;
1291 | return VirtualFS.resolveVirtual(ppath.join(target, backstep, subpath));
1292 | }
1293 | getExtractHint(hints) {
1294 | return this.baseFs.getExtractHint(hints);
1295 | }
1296 | getRealPath() {
1297 | return this.baseFs.getRealPath();
1298 | }
1299 | realpathSync(p) {
1300 | const match = p.match(VIRTUAL_REGEXP);
1301 | if (!match)
1302 | return this.baseFs.realpathSync(p);
1303 | if (!match[5])
1304 | return p;
1305 | const realpath = this.baseFs.realpathSync(this.mapToBase(p));
1306 | return VirtualFS.makeVirtualPath(match[1], match[3], realpath);
1307 | }
1308 | async realpathPromise(p) {
1309 | const match = p.match(VIRTUAL_REGEXP);
1310 | if (!match)
1311 | return await this.baseFs.realpathPromise(p);
1312 | if (!match[5])
1313 | return p;
1314 | const realpath = await this.baseFs.realpathPromise(this.mapToBase(p));
1315 | return VirtualFS.makeVirtualPath(match[1], match[3], realpath);
1316 | }
1317 | mapToBase(p) {
1318 | if (p === ``)
1319 | return p;
1320 | if (this.pathUtils.isAbsolute(p))
1321 | return VirtualFS.resolveVirtual(p);
1322 | const resolvedRoot = VirtualFS.resolveVirtual(this.baseFs.resolve(PortablePath.dot));
1323 | const resolvedP = VirtualFS.resolveVirtual(this.baseFs.resolve(p));
1324 | return ppath.relative(resolvedRoot, resolvedP) || PortablePath.dot;
1325 | }
1326 | mapFromBase(p) {
1327 | return p;
1328 | }
1329 | }
1330 |
1331 | const [major, minor] = process.versions.node.split(`.`).map((value) => parseInt(value, 10));
1332 | const HAS_CONSOLIDATED_HOOKS = major > 16 || major === 16 && minor >= 12;
1333 | const HAS_UNFLAGGED_JSON_MODULES = major > 17 || major === 17 && minor >= 5 || major === 16 && minor >= 15;
1334 | const HAS_JSON_IMPORT_ASSERTION_REQUIREMENT = major > 17 || major === 17 && minor >= 1 || major === 16 && minor > 14;
1335 | const WATCH_MODE_MESSAGE_USES_ARRAYS = major > 19 || major === 19 && minor >= 2 || major === 18 && minor >= 13;
1336 | const HAS_LAZY_LOADED_TRANSLATORS = major > 19 || major === 19 && minor >= 3;
1337 |
1338 | const builtinModules = new Set(Module.builtinModules || Object.keys(process.binding(`natives`)));
1339 | const isBuiltinModule = (request) => request.startsWith(`node:`) || builtinModules.has(request);
1340 | function readPackageScope(checkPath) {
1341 | const rootSeparatorIndex = checkPath.indexOf(npath.sep);
1342 | let separatorIndex;
1343 | do {
1344 | separatorIndex = checkPath.lastIndexOf(npath.sep);
1345 | checkPath = checkPath.slice(0, separatorIndex);
1346 | if (checkPath.endsWith(`${npath.sep}node_modules`))
1347 | return false;
1348 | const pjson = readPackage(checkPath + npath.sep);
1349 | if (pjson) {
1350 | return {
1351 | data: pjson,
1352 | path: checkPath
1353 | };
1354 | }
1355 | } while (separatorIndex > rootSeparatorIndex);
1356 | return false;
1357 | }
1358 | function readPackage(requestPath) {
1359 | const jsonPath = npath.resolve(requestPath, `package.json`);
1360 | if (!fs.existsSync(jsonPath))
1361 | return null;
1362 | return JSON.parse(fs.readFileSync(jsonPath, `utf8`));
1363 | }
1364 |
1365 | async function tryReadFile$1(path2) {
1366 | try {
1367 | return await fs.promises.readFile(path2, `utf8`);
1368 | } catch (error) {
1369 | if (error.code === `ENOENT`)
1370 | return null;
1371 | throw error;
1372 | }
1373 | }
1374 | function tryParseURL(str, base) {
1375 | try {
1376 | return new URL$1(str, base);
1377 | } catch {
1378 | return null;
1379 | }
1380 | }
1381 | let entrypointPath = null;
1382 | function setEntrypointPath(file) {
1383 | entrypointPath = file;
1384 | }
1385 | function getFileFormat(filepath) {
1386 | var _a, _b;
1387 | const ext = path.extname(filepath);
1388 | switch (ext) {
1389 | case `.mjs`: {
1390 | return `module`;
1391 | }
1392 | case `.cjs`: {
1393 | return `commonjs`;
1394 | }
1395 | case `.wasm`: {
1396 | throw new Error(
1397 | `Unknown file extension ".wasm" for ${filepath}`
1398 | );
1399 | }
1400 | case `.json`: {
1401 | if (HAS_UNFLAGGED_JSON_MODULES)
1402 | return `json`;
1403 | throw new Error(
1404 | `Unknown file extension ".json" for ${filepath}`
1405 | );
1406 | }
1407 | case `.js`: {
1408 | const pkg = readPackageScope(filepath);
1409 | if (!pkg)
1410 | return `commonjs`;
1411 | return (_a = pkg.data.type) != null ? _a : `commonjs`;
1412 | }
1413 | default: {
1414 | if (entrypointPath !== filepath)
1415 | return null;
1416 | const pkg = readPackageScope(filepath);
1417 | if (!pkg)
1418 | return `commonjs`;
1419 | if (pkg.data.type === `module`)
1420 | return null;
1421 | return (_b = pkg.data.type) != null ? _b : `commonjs`;
1422 | }
1423 | }
1424 | }
1425 |
1426 | async function getFormat$1(resolved, context, defaultGetFormat) {
1427 | const url = tryParseURL(resolved);
1428 | if ((url == null ? void 0 : url.protocol) !== `file:`)
1429 | return defaultGetFormat(resolved, context, defaultGetFormat);
1430 | const format = getFileFormat(fileURLToPath(url));
1431 | if (format) {
1432 | return {
1433 | format
1434 | };
1435 | }
1436 | return defaultGetFormat(resolved, context, defaultGetFormat);
1437 | }
1438 |
1439 | async function getSource$1(urlString, context, defaultGetSource) {
1440 | const url = tryParseURL(urlString);
1441 | if ((url == null ? void 0 : url.protocol) !== `file:`)
1442 | return defaultGetSource(urlString, context, defaultGetSource);
1443 | return {
1444 | source: await fs.promises.readFile(fileURLToPath(url), `utf8`)
1445 | };
1446 | }
1447 |
1448 | async function load$1(urlString, context, nextLoad) {
1449 | var _a;
1450 | const url = tryParseURL(urlString);
1451 | if ((url == null ? void 0 : url.protocol) !== `file:`)
1452 | return nextLoad(urlString, context, nextLoad);
1453 | const filePath = fileURLToPath(url);
1454 | const format = getFileFormat(filePath);
1455 | if (!format)
1456 | return nextLoad(urlString, context, nextLoad);
1457 | if (HAS_JSON_IMPORT_ASSERTION_REQUIREMENT && format === `json` && ((_a = context.importAssertions) == null ? void 0 : _a.type) !== `json`) {
1458 | const err = new TypeError(`[ERR_IMPORT_ASSERTION_TYPE_MISSING]: Module "${urlString}" needs an import assertion of type "json"`);
1459 | err.code = `ERR_IMPORT_ASSERTION_TYPE_MISSING`;
1460 | throw err;
1461 | }
1462 | if (process.env.WATCH_REPORT_DEPENDENCIES && process.send) {
1463 | const pathToSend = pathToFileURL(
1464 | npath.fromPortablePath(
1465 | VirtualFS.resolveVirtual(npath.toPortablePath(filePath))
1466 | )
1467 | ).href;
1468 | process.send({
1469 | "watch:import": WATCH_MODE_MESSAGE_USES_ARRAYS ? [pathToSend] : pathToSend
1470 | });
1471 | }
1472 | return {
1473 | format,
1474 | source: await fs.promises.readFile(filePath, `utf8`),
1475 | shortCircuit: true
1476 | };
1477 | }
1478 |
1479 | const ArrayIsArray = Array.isArray;
1480 | const JSONStringify = JSON.stringify;
1481 | const ObjectGetOwnPropertyNames = Object.getOwnPropertyNames;
1482 | const ObjectPrototypeHasOwnProperty = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
1483 | const RegExpPrototypeExec = (obj, string) => RegExp.prototype.exec.call(obj, string);
1484 | const RegExpPrototypeSymbolReplace = (obj, ...rest) => RegExp.prototype[Symbol.replace].apply(obj, rest);
1485 | const StringPrototypeEndsWith = (str, ...rest) => String.prototype.endsWith.apply(str, rest);
1486 | const StringPrototypeIncludes = (str, ...rest) => String.prototype.includes.apply(str, rest);
1487 | const StringPrototypeLastIndexOf = (str, ...rest) => String.prototype.lastIndexOf.apply(str, rest);
1488 | const StringPrototypeIndexOf = (str, ...rest) => String.prototype.indexOf.apply(str, rest);
1489 | const StringPrototypeReplace = (str, ...rest) => String.prototype.replace.apply(str, rest);
1490 | const StringPrototypeSlice = (str, ...rest) => String.prototype.slice.apply(str, rest);
1491 | const StringPrototypeStartsWith = (str, ...rest) => String.prototype.startsWith.apply(str, rest);
1492 | const SafeMap = Map;
1493 | const JSONParse = JSON.parse;
1494 |
1495 | function createErrorType(code, messageCreator, errorType) {
1496 | return class extends errorType {
1497 | constructor(...args) {
1498 | super(messageCreator(...args));
1499 | this.code = code;
1500 | this.name = `${errorType.name} [${code}]`;
1501 | }
1502 | };
1503 | }
1504 | const ERR_PACKAGE_IMPORT_NOT_DEFINED = createErrorType(
1505 | `ERR_PACKAGE_IMPORT_NOT_DEFINED`,
1506 | (specifier, packagePath, base) => {
1507 | return `Package import specifier "${specifier}" is not defined${packagePath ? ` in package ${packagePath}package.json` : ``} imported from ${base}`;
1508 | },
1509 | TypeError
1510 | );
1511 | const ERR_INVALID_MODULE_SPECIFIER = createErrorType(
1512 | `ERR_INVALID_MODULE_SPECIFIER`,
1513 | (request, reason, base = void 0) => {
1514 | return `Invalid module "${request}" ${reason}${base ? ` imported from ${base}` : ``}`;
1515 | },
1516 | TypeError
1517 | );
1518 | const ERR_INVALID_PACKAGE_TARGET = createErrorType(
1519 | `ERR_INVALID_PACKAGE_TARGET`,
1520 | (pkgPath, key, target, isImport = false, base = void 0) => {
1521 | const relError = typeof target === `string` && !isImport && target.length && !StringPrototypeStartsWith(target, `./`);
1522 | if (key === `.`) {
1523 | assert(isImport === false);
1524 | return `Invalid "exports" main target ${JSONStringify(target)} defined in the package config ${pkgPath}package.json${base ? ` imported from ${base}` : ``}${relError ? `; targets must start with "./"` : ``}`;
1525 | }
1526 | return `Invalid "${isImport ? `imports` : `exports`}" target ${JSONStringify(
1527 | target
1528 | )} defined for '${key}' in the package config ${pkgPath}package.json${base ? ` imported from ${base}` : ``}${relError ? `; targets must start with "./"` : ``}`;
1529 | },
1530 | Error
1531 | );
1532 | const ERR_INVALID_PACKAGE_CONFIG = createErrorType(
1533 | `ERR_INVALID_PACKAGE_CONFIG`,
1534 | (path, base, message) => {
1535 | return `Invalid package config ${path}${base ? ` while importing ${base}` : ``}${message ? `. ${message}` : ``}`;
1536 | },
1537 | Error
1538 | );
1539 |
1540 | function filterOwnProperties(source, keys) {
1541 | const filtered = /* @__PURE__ */ Object.create(null);
1542 | for (let i = 0; i < keys.length; i++) {
1543 | const key = keys[i];
1544 | if (ObjectPrototypeHasOwnProperty(source, key)) {
1545 | filtered[key] = source[key];
1546 | }
1547 | }
1548 | return filtered;
1549 | }
1550 |
1551 | const packageJSONCache = new SafeMap();
1552 | function getPackageConfig(path, specifier, base, readFileSyncFn) {
1553 | const existing = packageJSONCache.get(path);
1554 | if (existing !== void 0) {
1555 | return existing;
1556 | }
1557 | const source = readFileSyncFn(path);
1558 | if (source === void 0) {
1559 | const packageConfig2 = {
1560 | pjsonPath: path,
1561 | exists: false,
1562 | main: void 0,
1563 | name: void 0,
1564 | type: "none",
1565 | exports: void 0,
1566 | imports: void 0
1567 | };
1568 | packageJSONCache.set(path, packageConfig2);
1569 | return packageConfig2;
1570 | }
1571 | let packageJSON;
1572 | try {
1573 | packageJSON = JSONParse(source);
1574 | } catch (error) {
1575 | throw new ERR_INVALID_PACKAGE_CONFIG(
1576 | path,
1577 | (base ? `"${specifier}" from ` : "") + fileURLToPath(base || specifier),
1578 | error.message
1579 | );
1580 | }
1581 | let { imports, main, name, type } = filterOwnProperties(packageJSON, [
1582 | "imports",
1583 | "main",
1584 | "name",
1585 | "type"
1586 | ]);
1587 | const exports = ObjectPrototypeHasOwnProperty(packageJSON, "exports") ? packageJSON.exports : void 0;
1588 | if (typeof imports !== "object" || imports === null) {
1589 | imports = void 0;
1590 | }
1591 | if (typeof main !== "string") {
1592 | main = void 0;
1593 | }
1594 | if (typeof name !== "string") {
1595 | name = void 0;
1596 | }
1597 | if (type !== "module" && type !== "commonjs") {
1598 | type = "none";
1599 | }
1600 | const packageConfig = {
1601 | pjsonPath: path,
1602 | exists: true,
1603 | main,
1604 | name,
1605 | type,
1606 | exports,
1607 | imports
1608 | };
1609 | packageJSONCache.set(path, packageConfig);
1610 | return packageConfig;
1611 | }
1612 | function getPackageScopeConfig(resolved, readFileSyncFn) {
1613 | let packageJSONUrl = new URL("./package.json", resolved);
1614 | while (true) {
1615 | const packageJSONPath2 = packageJSONUrl.pathname;
1616 | if (StringPrototypeEndsWith(packageJSONPath2, "node_modules/package.json")) {
1617 | break;
1618 | }
1619 | const packageConfig2 = getPackageConfig(
1620 | fileURLToPath(packageJSONUrl),
1621 | resolved,
1622 | void 0,
1623 | readFileSyncFn
1624 | );
1625 | if (packageConfig2.exists) {
1626 | return packageConfig2;
1627 | }
1628 | const lastPackageJSONUrl = packageJSONUrl;
1629 | packageJSONUrl = new URL("../package.json", packageJSONUrl);
1630 | if (packageJSONUrl.pathname === lastPackageJSONUrl.pathname) {
1631 | break;
1632 | }
1633 | }
1634 | const packageJSONPath = fileURLToPath(packageJSONUrl);
1635 | const packageConfig = {
1636 | pjsonPath: packageJSONPath,
1637 | exists: false,
1638 | main: void 0,
1639 | name: void 0,
1640 | type: "none",
1641 | exports: void 0,
1642 | imports: void 0
1643 | };
1644 | packageJSONCache.set(packageJSONPath, packageConfig);
1645 | return packageConfig;
1646 | }
1647 |
1648 | /**
1649 | @license
1650 | Copyright Node.js contributors. All rights reserved.
1651 |
1652 | Permission is hereby granted, free of charge, to any person obtaining a copy
1653 | of this software and associated documentation files (the "Software"), to
1654 | deal in the Software without restriction, including without limitation the
1655 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1656 | sell copies of the Software, and to permit persons to whom the Software is
1657 | furnished to do so, subject to the following conditions:
1658 |
1659 | The above copyright notice and this permission notice shall be included in
1660 | all copies or substantial portions of the Software.
1661 |
1662 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1663 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1664 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1665 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1666 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1667 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
1668 | IN THE SOFTWARE.
1669 | */
1670 | function throwImportNotDefined(specifier, packageJSONUrl, base) {
1671 | throw new ERR_PACKAGE_IMPORT_NOT_DEFINED(
1672 | specifier,
1673 | packageJSONUrl && fileURLToPath(new URL(".", packageJSONUrl)),
1674 | fileURLToPath(base)
1675 | );
1676 | }
1677 | function throwInvalidSubpath(subpath, packageJSONUrl, internal, base) {
1678 | const reason = `request is not a valid subpath for the "${internal ? "imports" : "exports"}" resolution of ${fileURLToPath(packageJSONUrl)}`;
1679 | throw new ERR_INVALID_MODULE_SPECIFIER(
1680 | subpath,
1681 | reason,
1682 | base && fileURLToPath(base)
1683 | );
1684 | }
1685 | function throwInvalidPackageTarget(subpath, target, packageJSONUrl, internal, base) {
1686 | if (typeof target === "object" && target !== null) {
1687 | target = JSONStringify(target, null, "");
1688 | } else {
1689 | target = `${target}`;
1690 | }
1691 | throw new ERR_INVALID_PACKAGE_TARGET(
1692 | fileURLToPath(new URL(".", packageJSONUrl)),
1693 | subpath,
1694 | target,
1695 | internal,
1696 | base && fileURLToPath(base)
1697 | );
1698 | }
1699 | const invalidSegmentRegEx = /(^|\\|\/)((\.|%2e)(\.|%2e)?|(n|%6e|%4e)(o|%6f|%4f)(d|%64|%44)(e|%65|%45)(_|%5f)(m|%6d|%4d)(o|%6f|%4f)(d|%64|%44)(u|%75|%55)(l|%6c|%4c)(e|%65|%45)(s|%73|%53))(\\|\/|$)/i;
1700 | const patternRegEx = /\*/g;
1701 | function resolvePackageTargetString(target, subpath, match, packageJSONUrl, base, pattern, internal, conditions) {
1702 | if (subpath !== "" && !pattern && target[target.length - 1] !== "/")
1703 | throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base);
1704 | if (!StringPrototypeStartsWith(target, "./")) {
1705 | if (internal && !StringPrototypeStartsWith(target, "../") && !StringPrototypeStartsWith(target, "/")) {
1706 | let isURL = false;
1707 | try {
1708 | new URL(target);
1709 | isURL = true;
1710 | } catch {
1711 | }
1712 | if (!isURL) {
1713 | const exportTarget = pattern ? RegExpPrototypeSymbolReplace(patternRegEx, target, () => subpath) : target + subpath;
1714 | return exportTarget;
1715 | }
1716 | }
1717 | throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base);
1718 | }
1719 | if (RegExpPrototypeExec(
1720 | invalidSegmentRegEx,
1721 | StringPrototypeSlice(target, 2)
1722 | ) !== null)
1723 | throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base);
1724 | const resolved = new URL(target, packageJSONUrl);
1725 | const resolvedPath = resolved.pathname;
1726 | const packagePath = new URL(".", packageJSONUrl).pathname;
1727 | if (!StringPrototypeStartsWith(resolvedPath, packagePath))
1728 | throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base);
1729 | if (subpath === "")
1730 | return resolved;
1731 | if (RegExpPrototypeExec(invalidSegmentRegEx, subpath) !== null) {
1732 | const request = pattern ? StringPrototypeReplace(match, "*", () => subpath) : match + subpath;
1733 | throwInvalidSubpath(request, packageJSONUrl, internal, base);
1734 | }
1735 | if (pattern) {
1736 | return new URL(
1737 | RegExpPrototypeSymbolReplace(patternRegEx, resolved.href, () => subpath)
1738 | );
1739 | }
1740 | return new URL(subpath, resolved);
1741 | }
1742 | function isArrayIndex(key) {
1743 | const keyNum = +key;
1744 | if (`${keyNum}` !== key)
1745 | return false;
1746 | return keyNum >= 0 && keyNum < 4294967295;
1747 | }
1748 | function resolvePackageTarget(packageJSONUrl, target, subpath, packageSubpath, base, pattern, internal, conditions) {
1749 | if (typeof target === "string") {
1750 | return resolvePackageTargetString(
1751 | target,
1752 | subpath,
1753 | packageSubpath,
1754 | packageJSONUrl,
1755 | base,
1756 | pattern,
1757 | internal);
1758 | } else if (ArrayIsArray(target)) {
1759 | if (target.length === 0) {
1760 | return null;
1761 | }
1762 | let lastException;
1763 | for (let i = 0; i < target.length; i++) {
1764 | const targetItem = target[i];
1765 | let resolveResult;
1766 | try {
1767 | resolveResult = resolvePackageTarget(
1768 | packageJSONUrl,
1769 | targetItem,
1770 | subpath,
1771 | packageSubpath,
1772 | base,
1773 | pattern,
1774 | internal,
1775 | conditions
1776 | );
1777 | } catch (e) {
1778 | lastException = e;
1779 | if (e.code === "ERR_INVALID_PACKAGE_TARGET") {
1780 | continue;
1781 | }
1782 | throw e;
1783 | }
1784 | if (resolveResult === void 0) {
1785 | continue;
1786 | }
1787 | if (resolveResult === null) {
1788 | lastException = null;
1789 | continue;
1790 | }
1791 | return resolveResult;
1792 | }
1793 | if (lastException === void 0 || lastException === null)
1794 | return lastException;
1795 | throw lastException;
1796 | } else if (typeof target === "object" && target !== null) {
1797 | const keys = ObjectGetOwnPropertyNames(target);
1798 | for (let i = 0; i < keys.length; i++) {
1799 | const key = keys[i];
1800 | if (isArrayIndex(key)) {
1801 | throw new ERR_INVALID_PACKAGE_CONFIG(
1802 | fileURLToPath(packageJSONUrl),
1803 | base,
1804 | '"exports" cannot contain numeric property keys.'
1805 | );
1806 | }
1807 | }
1808 | for (let i = 0; i < keys.length; i++) {
1809 | const key = keys[i];
1810 | if (key === "default" || conditions.has(key)) {
1811 | const conditionalTarget = target[key];
1812 | const resolveResult = resolvePackageTarget(
1813 | packageJSONUrl,
1814 | conditionalTarget,
1815 | subpath,
1816 | packageSubpath,
1817 | base,
1818 | pattern,
1819 | internal,
1820 | conditions
1821 | );
1822 | if (resolveResult === void 0)
1823 | continue;
1824 | return resolveResult;
1825 | }
1826 | }
1827 | return void 0;
1828 | } else if (target === null) {
1829 | return null;
1830 | }
1831 | throwInvalidPackageTarget(
1832 | packageSubpath,
1833 | target,
1834 | packageJSONUrl,
1835 | internal,
1836 | base
1837 | );
1838 | }
1839 | function patternKeyCompare(a, b) {
1840 | const aPatternIndex = StringPrototypeIndexOf(a, "*");
1841 | const bPatternIndex = StringPrototypeIndexOf(b, "*");
1842 | const baseLenA = aPatternIndex === -1 ? a.length : aPatternIndex + 1;
1843 | const baseLenB = bPatternIndex === -1 ? b.length : bPatternIndex + 1;
1844 | if (baseLenA > baseLenB)
1845 | return -1;
1846 | if (baseLenB > baseLenA)
1847 | return 1;
1848 | if (aPatternIndex === -1)
1849 | return 1;
1850 | if (bPatternIndex === -1)
1851 | return -1;
1852 | if (a.length > b.length)
1853 | return -1;
1854 | if (b.length > a.length)
1855 | return 1;
1856 | return 0;
1857 | }
1858 | function packageImportsResolve({ name, base, conditions, readFileSyncFn }) {
1859 | if (name === "#" || StringPrototypeStartsWith(name, "#/") || StringPrototypeEndsWith(name, "/")) {
1860 | const reason = "is not a valid internal imports specifier name";
1861 | throw new ERR_INVALID_MODULE_SPECIFIER(name, reason, fileURLToPath(base));
1862 | }
1863 | let packageJSONUrl;
1864 | const packageConfig = getPackageScopeConfig(base, readFileSyncFn);
1865 | if (packageConfig.exists) {
1866 | packageJSONUrl = pathToFileURL(packageConfig.pjsonPath);
1867 | const imports = packageConfig.imports;
1868 | if (imports) {
1869 | if (ObjectPrototypeHasOwnProperty(imports, name) && !StringPrototypeIncludes(name, "*")) {
1870 | const resolveResult = resolvePackageTarget(
1871 | packageJSONUrl,
1872 | imports[name],
1873 | "",
1874 | name,
1875 | base,
1876 | false,
1877 | true,
1878 | conditions
1879 | );
1880 | if (resolveResult != null) {
1881 | return resolveResult;
1882 | }
1883 | } else {
1884 | let bestMatch = "";
1885 | let bestMatchSubpath;
1886 | const keys = ObjectGetOwnPropertyNames(imports);
1887 | for (let i = 0; i < keys.length; i++) {
1888 | const key = keys[i];
1889 | const patternIndex = StringPrototypeIndexOf(key, "*");
1890 | if (patternIndex !== -1 && StringPrototypeStartsWith(
1891 | name,
1892 | StringPrototypeSlice(key, 0, patternIndex)
1893 | )) {
1894 | const patternTrailer = StringPrototypeSlice(key, patternIndex + 1);
1895 | if (name.length >= key.length && StringPrototypeEndsWith(name, patternTrailer) && patternKeyCompare(bestMatch, key) === 1 && StringPrototypeLastIndexOf(key, "*") === patternIndex) {
1896 | bestMatch = key;
1897 | bestMatchSubpath = StringPrototypeSlice(
1898 | name,
1899 | patternIndex,
1900 | name.length - patternTrailer.length
1901 | );
1902 | }
1903 | }
1904 | }
1905 | if (bestMatch) {
1906 | const target = imports[bestMatch];
1907 | const resolveResult = resolvePackageTarget(
1908 | packageJSONUrl,
1909 | target,
1910 | bestMatchSubpath,
1911 | bestMatch,
1912 | base,
1913 | true,
1914 | true,
1915 | conditions
1916 | );
1917 | if (resolveResult != null) {
1918 | return resolveResult;
1919 | }
1920 | }
1921 | }
1922 | }
1923 | }
1924 | throwImportNotDefined(name, packageJSONUrl, base);
1925 | }
1926 |
1927 | const pathRegExp = /^(?![a-zA-Z]:[\\/]|\\\\|\.{0,2}(?:\/|$))((?:node:)?(?:@[^/]+\/)?[^/]+)\/*(.*|)$/;
1928 | const isRelativeRegexp = /^\.{0,2}\//;
1929 | function tryReadFile(filePath) {
1930 | try {
1931 | return fs.readFileSync(filePath, `utf8`);
1932 | } catch (err) {
1933 | if (err.code === `ENOENT`)
1934 | return void 0;
1935 | throw err;
1936 | }
1937 | }
1938 | async function resolvePrivateRequest(specifier, issuer, context, nextResolve) {
1939 | const resolved = packageImportsResolve({
1940 | name: specifier,
1941 | base: pathToFileURL(issuer),
1942 | conditions: new Set(context.conditions),
1943 | readFileSyncFn: tryReadFile
1944 | });
1945 | if (resolved instanceof URL$1) {
1946 | return { url: resolved.href, shortCircuit: true };
1947 | } else {
1948 | if (resolved.startsWith(`#`))
1949 | throw new Error(`Mapping from one private import to another isn't allowed`);
1950 | return resolve$1(resolved, context, nextResolve);
1951 | }
1952 | }
1953 | async function resolve$1(originalSpecifier, context, nextResolve) {
1954 | var _a, _b;
1955 | const { findPnpApi } = moduleExports;
1956 | if (!findPnpApi || isBuiltinModule(originalSpecifier))
1957 | return nextResolve(originalSpecifier, context, nextResolve);
1958 | let specifier = originalSpecifier;
1959 | const url = tryParseURL(specifier, isRelativeRegexp.test(specifier) ? context.parentURL : void 0);
1960 | if (url) {
1961 | if (url.protocol !== `file:`)
1962 | return nextResolve(originalSpecifier, context, nextResolve);
1963 | specifier = fileURLToPath(url);
1964 | }
1965 | const { parentURL, conditions = [] } = context;
1966 | const issuer = parentURL && ((_a = tryParseURL(parentURL)) == null ? void 0 : _a.protocol) === `file:` ? fileURLToPath(parentURL) : process.cwd();
1967 | const pnpapi = (_b = findPnpApi(issuer)) != null ? _b : url ? findPnpApi(specifier) : null;
1968 | if (!pnpapi)
1969 | return nextResolve(originalSpecifier, context, nextResolve);
1970 | if (specifier.startsWith(`#`))
1971 | return resolvePrivateRequest(specifier, issuer, context, nextResolve);
1972 | const dependencyNameMatch = specifier.match(pathRegExp);
1973 | let allowLegacyResolve = false;
1974 | if (dependencyNameMatch) {
1975 | const [, dependencyName, subPath] = dependencyNameMatch;
1976 | if (subPath === `` && dependencyName !== `pnpapi`) {
1977 | const resolved = pnpapi.resolveToUnqualified(`${dependencyName}/package.json`, issuer);
1978 | if (resolved) {
1979 | const content = await tryReadFile$1(resolved);
1980 | if (content) {
1981 | const pkg = JSON.parse(content);
1982 | allowLegacyResolve = pkg.exports == null;
1983 | }
1984 | }
1985 | }
1986 | }
1987 | let result;
1988 | try {
1989 | result = pnpapi.resolveRequest(specifier, issuer, {
1990 | conditions: new Set(conditions),
1991 | extensions: allowLegacyResolve ? void 0 : []
1992 | });
1993 | } catch (err) {
1994 | if (err instanceof Error && `code` in err && err.code === `MODULE_NOT_FOUND`)
1995 | err.code = `ERR_MODULE_NOT_FOUND`;
1996 | throw err;
1997 | }
1998 | if (!result)
1999 | throw new Error(`Resolving '${specifier}' from '${issuer}' failed`);
2000 | const resultURL = pathToFileURL(result);
2001 | if (url) {
2002 | resultURL.search = url.search;
2003 | resultURL.hash = url.hash;
2004 | }
2005 | if (!parentURL)
2006 | setEntrypointPath(fileURLToPath(resultURL));
2007 | return {
2008 | url: resultURL.href,
2009 | shortCircuit: true
2010 | };
2011 | }
2012 |
2013 | if (!HAS_LAZY_LOADED_TRANSLATORS) {
2014 | const binding = process.binding(`fs`);
2015 | const originalfstat = binding.fstat;
2016 | const ZIP_MASK = 4278190080;
2017 | const ZIP_MAGIC = 704643072;
2018 | binding.fstat = function(...args) {
2019 | const [fd, useBigint, req] = args;
2020 | if ((fd & ZIP_MASK) === ZIP_MAGIC && useBigint === false && req === void 0) {
2021 | try {
2022 | const stats = fs.fstatSync(fd);
2023 | return new Float64Array([
2024 | stats.dev,
2025 | stats.mode,
2026 | stats.nlink,
2027 | stats.uid,
2028 | stats.gid,
2029 | stats.rdev,
2030 | stats.blksize,
2031 | stats.ino,
2032 | stats.size,
2033 | stats.blocks
2034 | ]);
2035 | } catch {
2036 | }
2037 | }
2038 | return originalfstat.apply(this, args);
2039 | };
2040 | }
2041 |
2042 | const resolve = resolve$1;
2043 | const getFormat = HAS_CONSOLIDATED_HOOKS ? void 0 : getFormat$1;
2044 | const getSource = HAS_CONSOLIDATED_HOOKS ? void 0 : getSource$1;
2045 | const load = HAS_CONSOLIDATED_HOOKS ? load$1 : void 0;
2046 |
2047 | export { getFormat, getSource, load, resolve };
2048 |
--------------------------------------------------------------------------------