import{dirname,join,resolve}from"node:path";import{readFile,readdir}from"node:fs/promises";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"#discover/filesystem.js";import{parseWithNitroRolldownAst}from"#internal/bundler/nitro-rolldown.js";const STATE_MODULE=`eve/context`,STATE_EXPORT=`defineState`;async function extensionUsesState(e){let t=await collectAuthoredModules(e),n=new Map;for(let e of t)n.set(e,await readFile(e,`utf8`));if(![...n.values()].some(e=>e.includes(STATE_EXPORT)))return!1;let i=new Set(t),a=new Map;for(let[e,t]of n){let n=await parseWithNitroRolldownAst(e,t);a.set(e,analyzeModule(n))}let l=computeStateExports(a,i);for(let[e,t]of a){for(let[n,r]of t.imports)if(t.calledIdentifiers.has(n)&&specifierExportsState({...r,fromModulePath:e,stateExports:l,moduleSet:i}))return!0;for(let[n,r]of t.namespaceImports){let a=t.calledMembers.get(n);if(a===void 0)continue;if(r===STATE_MODULE){if(a.has(STATE_EXPORT))return!0;continue}let o=resolveLocalSpecifier(e,r,i),u=o===null?void 0:l.get(o);if(u!==void 0&&[...a].some(e=>u.has(e)))return!0}}return!1}async function collectAuthoredModules(e){let n=[];for(let r of await readdir(e,{withFileTypes:!0})){let i=join(e,r.name);r.isDirectory()?n.push(...await collectAuthoredModules(i)):r.isFile()&&!/\.d\.[cm]?ts$/.test(r.name)&&SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS.some(e=>r.name.endsWith(e))&&n.push(i)}return n.sort()}function analyzeModule(e){let t={imports:new Map,namespaceImports:new Map,reexports:new Map,starReexportSpecifiers:[],localReexports:new Map,calledIdentifiers:new Set,calledMembers:new Map};return walkAst(e,e=>{if(e.type===`ImportDeclaration`){let n=stringValue(e.source);if(n===null)return;for(let r of e.specifiers??[]){let e=moduleName(r.local);if(e!==null){if(r.type===`ImportNamespaceSpecifier`)t.namespaceImports.set(e,n);else if(r.type===`ImportSpecifier`){let i=moduleName(r.imported);i!==null&&t.imports.set(e,{specifier:n,importedName:i})}}}}else if(e.type===`ExportNamedDeclaration`){let n=stringValue(e.source);for(let r of e.specifiers??[]){if(r.type!==`ExportSpecifier`)continue;let e=moduleName(r.local),i=moduleName(r.exported)??e;e===null||i===null||(n===null?t.localReexports.set(i,e):t.reexports.set(i,{specifier:n,importedName:e}))}}else if(e.type===`ExportAllDeclaration`){let n=stringValue(e.source);n!==null&&e.exported==null&&t.starReexportSpecifiers.push(n)}else if(e.type===`CallExpression`){let n=e.callee;if(n?.type===`Identifier`){let e=moduleName(n);e!==null&&t.calledIdentifiers.add(e)}else if(n?.type===`MemberExpression`&&n.object?.type===`Identifier`){let e=moduleName(n.object),r=moduleName(n.property);if(e!==null&&r!==null){let n=t.calledMembers.get(e)??new Set;n.add(r),t.calledMembers.set(e,n)}}}}),t}function computeStateExports(e,t){let n=new Map;for(let t of e.keys())n.set(t,new Set);let r=!0;for(;r;){r=!1;for(let[i,a]of e){let e=n.get(i),add=t=>{e.has(t)||(e.add(t),r=!0)};for(let[e,r]of a.reexports)specifierExportsState({...r,fromModulePath:i,stateExports:n,moduleSet:t})&&add(e);for(let e of a.starReexportSpecifiers){if(e===STATE_MODULE){add(STATE_EXPORT);continue}let r=resolveLocalSpecifier(i,e,t);if(r!==null)for(let e of n.get(r)??[])add(e)}for(let[e,r]of a.localReexports){let o=a.imports.get(r);o!==void 0&&specifierExportsState({...o,fromModulePath:i,stateExports:n,moduleSet:t})&&add(e)}}}return n}function specifierExportsState(e){if(e.specifier===STATE_MODULE)return e.importedName===STATE_EXPORT;let t=resolveLocalSpecifier(e.fromModulePath,e.specifier,e.moduleSet);return t!==null&&(e.stateExports.get(t)?.has(e.importedName)??!1)}function resolveLocalSpecifier(r,i,o){if(!i.startsWith(`.`))return null;let s=resolve(dirname(r),i),c=[s,...emittedExtensionVariants(s)];for(let e of SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS)c.push(`${s}${e}`,join(s,`index${e}`));return c.find(e=>o.has(e))??null}function emittedExtensionVariants(e){return[[`.js`,`.ts`],[`.jsx`,`.tsx`],[`.mjs`,`.mts`],[`.cjs`,`.cts`]].filter(([t])=>e.endsWith(t)).map(([t,n])=>e.slice(0,-t.length)+n)}function moduleName(e){return e==null?null:typeof e.name==`string`?e.name:typeof e.value==`string`?e.value:null}function stringValue(e){return typeof e?.value==`string`?e.value:null}function walkAst(e,t){t(e);for(let n of Object.values(e))if(Array.isArray(n))for(let e of n)typeof e==`object`&&e&&`type`in e&&walkAst(e,t);else typeof n==`object`&&n&&`type`in n&&walkAst(n,t)}export{extensionUsesState};