* Builds the lookup state from a list of keyed functions. * * Note: `namesToSourcesToFunctionMeta` is a global copy that maps exported names to sources. * It does NOT include local import renames — the transform handler builds per-file local * name mappings separately. The `source`s have resolve
(keyedFunctions: KeyedFunction[])
| 43 | * name mappings separately. The `source`s have resolved aliases and are without extensions. |
| 44 | */ |
| 45 | function buildKeyedFunctionsState (keyedFunctions: KeyedFunction[]) { |
| 46 | const namesToSourcesToFunctionMeta = new Map<string, Map<string, BackwardsCompatibleKeyedFunction>>() |
| 47 | // filenames (without extension) of files that have a `default` keyed function export |
| 48 | const defaultExportSources = new Set<string>() |
| 49 | |
| 50 | for (const f of keyedFunctions) { |
| 51 | let functionName = f.name |
| 52 | const fnSource = typeof f.source === 'string' ? stripExtension(f.source) : '' |
| 53 | |
| 54 | if (f.name === 'default') { |
| 55 | const parsedSource = parse(f.source) |
| 56 | defaultExportSources.add(parsedSource.name) |
| 57 | functionName = camelCase(parsedSource.name) |
| 58 | } |
| 59 | |
| 60 | if (import.meta.dev) { |
| 61 | const sourcesToFunctionMeta = namesToSourcesToFunctionMeta.get(functionName) |
| 62 | const existingEntry = sourcesToFunctionMeta?.get(fnSource) |
| 63 | if (existingEntry?.source && existingEntry.source === fnSource) { |
| 64 | logger.warn(`[nuxt:compiler] [keyed-functions] Duplicate function name \`${functionName}\`${functionName !== f.name ? ` defined as \`${f.name}\`` : ''} with ${f.source ? `the same source \`${f.source}\`` : 'no source'} found. Overwriting the existing entry.`) |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | let sourcesToFunctionMeta = namesToSourcesToFunctionMeta.get(functionName) |
| 69 | if (!sourcesToFunctionMeta) { |
| 70 | sourcesToFunctionMeta = new Map<string, KeyedFunction>() |
| 71 | namesToSourcesToFunctionMeta.set(functionName, sourcesToFunctionMeta) |
| 72 | } |
| 73 | |
| 74 | sourcesToFunctionMeta.set(fnSource, { |
| 75 | ...f, |
| 76 | // TODO: use only `fnSource` in Nuxt 5 |
| 77 | source: typeof f.source === 'string' ? fnSource : f.source, |
| 78 | }) |
| 79 | } |
| 80 | |
| 81 | // resolved paths of all the sources WITHOUT EXTENSIONS |
| 82 | const sources = new Set<string>() |
| 83 | for (const sourcesToFunctionMeta of namesToSourcesToFunctionMeta.values()) { |
| 84 | for (const f of sourcesToFunctionMeta.values()) { |
| 85 | // TODO: remove check in Nuxt 5 (keeping it at the moment for the case when there is a RegExp in `source`) |
| 86 | if (f.source && typeof f.source === 'string') { |
| 87 | sources.add(f.source) |
| 88 | } |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | // TODO: come up with a better way to include files importing a `default` export (imported name can be arbitrary) |
| 93 | const codeIncludeRE = new RegExp(`\\b(${[...namesToSourcesToFunctionMeta.keys(), ...defaultExportSources].map(f => escapeRE(f)).join('|')})\\b`) |
| 94 | |
| 95 | return { namesToSourcesToFunctionMeta, defaultExportSources, sources, codeIncludeRE } |
| 96 | } |
| 97 | |
| 98 | export const KeyedFunctionsPlugin = (options: KeyedFunctionsOptions) => createUnplugin(() => { |
| 99 | // Build initial state from the static keyedFunctions list |
no test coverage detected
searching dependent graphs…