From 0dac0e38cb8508ef2c861b84fd99ca78d5ef0565 Mon Sep 17 00:00:00 2001 From: Jack Steam Date: Sat, 26 Oct 2024 19:32:36 -0600 Subject: [PATCH] Clean up archived files and update magic-string (#943) * chore: update magic-string * chore: remove unused files and deps * Add changeset --- .changeset/modern-countries-tell.md | 5 + packages/vite-plugin/package.json | 3 +- .../vite-plugin/src/node/archive/fileMeta.ts | 74 -- .../src/node/archive/fileWriter.ts | 255 ------- .../src/node/archive/hmrPayload.ts | 146 ---- .../src/node/archive/plugin-contentScripts.ts | 677 ------------------ .../node/archive/plugin-fileWriter--pages.ts | 55 -- .../archive/plugin-fileWriter--polyfill.ts | 56 -- .../archive/plugin-fileWriter--public-dir.ts | 27 - .../src/node/archive/plugin-fileWriter.ts | 52 -- pnpm-lock.yaml | 68 +- 11 files changed, 23 insertions(+), 1395 deletions(-) create mode 100644 .changeset/modern-countries-tell.md delete mode 100644 packages/vite-plugin/src/node/archive/fileMeta.ts delete mode 100644 packages/vite-plugin/src/node/archive/fileWriter.ts delete mode 100644 packages/vite-plugin/src/node/archive/hmrPayload.ts delete mode 100644 packages/vite-plugin/src/node/archive/plugin-contentScripts.ts delete mode 100644 packages/vite-plugin/src/node/archive/plugin-fileWriter--pages.ts delete mode 100644 packages/vite-plugin/src/node/archive/plugin-fileWriter--polyfill.ts delete mode 100644 packages/vite-plugin/src/node/archive/plugin-fileWriter--public-dir.ts delete mode 100644 packages/vite-plugin/src/node/archive/plugin-fileWriter.ts diff --git a/.changeset/modern-countries-tell.md b/.changeset/modern-countries-tell.md new file mode 100644 index 000000000..ce2860627 --- /dev/null +++ b/.changeset/modern-countries-tell.md @@ -0,0 +1,5 @@ +--- +"@fake-scope/fake-pkg": patch +--- + +Clean up archived files and update magic-string diff --git a/packages/vite-plugin/package.json b/packages/vite-plugin/package.json index 66d651363..f66850e78 100644 --- a/packages/vite-plugin/package.json +++ b/packages/vite-plugin/package.json @@ -67,14 +67,13 @@ "@webcomponents/custom-elements": "^1.5.0", "acorn-walk": "^8.2.0", "cheerio": "^1.0.0-rc.10", - "connect-injector": "^0.4.4", "convert-source-map": "^1.7.0", "debug": "^4.3.3", "es-module-lexer": "^0.10.0", "fast-glob": "^3.2.11", "fs-extra": "^10.0.1", "jsesc": "^3.0.2", - "magic-string": "^0.26.0", + "magic-string": "^0.30.12", "picocolors": "^1.0.0", "react-refresh": "^0.13.0", "rollup": "2.79.2", diff --git a/packages/vite-plugin/src/node/archive/fileMeta.ts b/packages/vite-plugin/src/node/archive/fileMeta.ts deleted file mode 100644 index 2fca95fa8..000000000 --- a/packages/vite-plugin/src/node/archive/fileMeta.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { TransformResult } from 'vite' - -export const idBySource = new Map() -export const idByUrl = new Map() -export const urlById = new Map() - -export function setUrlMeta({ - id, - source, - url, -}: { - id: string - url: string - source: string -}) { - idBySource.set(source, id) - idByUrl.set(url, id) - urlById.set(id, url) -} - -export const fileById = new Map() -export const fileByUrl = new Map() -export const pathById = new Map() -export const pathByUrl = new Map() - -export const idByFile = new Map() -export const urlByFile = new Map() - -/** Set the filename of the source file */ -export const setFileMeta = ({ file, id }: { file: string; id: string }) => { - const url = urlById.get(id) - if (!url) return - - fileById.set(id, file) - fileByUrl.set(url, file) - - const pathName = `/${file}` - pathById.set(id, pathName) - pathByUrl.set(url, pathName) -} - -export const ownerById = new Map() -export const pathByOwner = new Map() -export const ownersByFile = new Map>() -export const setOwnerMeta = ({ owner, id }: { owner: string; id: string }) => { - const pathName = pathById.get(id) - if (!pathName) return - - pathByOwner.set(owner, pathName) - ownerById.set(id, owner) - - const fileName = fileById.get(id)! - const owners = ownersByFile.get(fileName) ?? new Set() - owners.add(owner) - ownersByFile.set(fileName, owners) -} - -export const outputById = new Map() -export const outputByOwner = new Map() -export const setOutputMeta = ({ - output, - id, -}: { - output: string - id: string -}) => { - const ownerName = ownerById.get(id) - if (!ownerName) return - outputByOwner.set(ownerName, output) - outputById.set(id, output) -} - -/** "owner" is same as Update["path"] in Vite */ -export const transformResultByOwner = new Map() diff --git a/packages/vite-plugin/src/node/archive/fileWriter.ts b/packages/vite-plugin/src/node/archive/fileWriter.ts deleted file mode 100644 index b7ebab3f5..000000000 --- a/packages/vite-plugin/src/node/archive/fileWriter.ts +++ /dev/null @@ -1,255 +0,0 @@ -import fsx from 'fs-extra' -import { - NormalizedInputOptions, - NormalizedOutputOptions, - OutputBundle, - rollup, -} from 'rollup' -import { - BehaviorSubject, - EMPTY, - first, - firstValueFrom, - mergeMap, - of, - ReplaySubject, - retry, - switchMap, -} from 'rxjs' -import { TransformResult, ViteDevServer } from 'vite' -import { _debug } from '../helpers' -import { isAbsolute, join } from '../path' -import { CrxPlugin } from '../types' -import { stubId } from '../virtualFileIds' - -const debug = _debug('file-writer') - -const { outputFile } = fsx - -export type ScriptType = 'loader' | 'module' | 'iife' -export interface ScriptModule { - type: ScriptType - file?: Promise<{ modules: ScriptModule[]; target: string }> - fileName: string - viteUrl: string -} - -const scriptModulesChange$ = new BehaviorSubject(undefined) -type MapProp = keyof Map -const mapProps: MapProp[] = ['clear', 'set', 'delete'] -// spy on changes to script module -export const scriptModules = new Proxy(new Map(), { - get(target, prop: MapProp) { - const method = Reflect.get(target, prop) - // @ts-expect-error too dynamic for typescript - if (!mapProps.includes(prop)) return method?.bind(target) - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return function (this: typeof target, ...args: any[]) { - scriptModulesChange$.next(undefined) - // @ts-expect-error too dynamic for typescript - return method.call(this, ...args) - }.bind(target) - }, -}) - -export const buildEvent$ = new ReplaySubject< - | { - type: 'buildStart' - options: NormalizedInputOptions - } - | { - type: 'writeBundle' - options: NormalizedOutputOptions - bundle: OutputBundle - } ->() -export const filesReady$ = buildEvent$.pipe( - first(({ type }) => type === 'writeBundle'), - switchMap(() => scriptModulesChange$), - mergeMap(() => - Promise.all([...scriptModules.values()].map(({ file }) => file)), - ), -) -export const serverEvent$ = new ReplaySubject< - | { - type: 'start' - server: ViteDevServer - } - | { type: 'close' } ->(1) - -buildEvent$.subscribe(({ type }) => debug(type)) -serverEvent$.subscribe(() => debug('server')) -filesReady$.subscribe(() => debug('filesReady')) - -export async function filesReady(): Promise { - await firstValueFrom(filesReady$) - return scriptModules -} - -/** Resolves when initial file write is complete. */ -export async function start({ - server, - plugins, -}: { - server: ViteDevServer - plugins: CrxPlugin[] -}) { - serverEvent$.next({ type: 'start', server }) - try { - for (const script of scriptModules.values()) { - scriptModules.set(script.viteUrl, { - ...script, - file: write(script), - }) - } - - const build = await rollup({ - input: stubId, - plugins: [ - { - name: 'crx:file-writer-rollup-events', - buildStart(options) { - buildEvent$.next({ type: 'buildStart', options }) - }, - }, - ...plugins, - { - name: 'crx:file-writer-rollup-events', - writeBundle(options, bundle) { - buildEvent$.next({ type: 'writeBundle', options, bundle }) - }, - }, - ], - }) - - await build.write({ - dir: server.config.build.outDir, - format: 'es', - ...server.config.build.rollupOptions.output, - assetFileNames: 'assets/[name].[ext].js', - }) - } catch (error) { - console.error(error) - } -} - -/** Signals file writer to abandon active write operations. */ -export function close() { - serverEvent$.next({ type: 'close' }) -} - -/** - * Call `add` if you don't want to update existing files. ScriptModule.file - * resolves when the file and all dependencies are ready. - */ -export function add({ - type, - viteUrl, -}: { - type: ScriptType - viteUrl: string -}): ScriptModule { - const fileName = toFileName({ viteUrl, type }) - const script = scriptModules.get(fileName) ?? { - viteUrl, - type, - file: write({ viteUrl, type }), - fileName, - } - scriptModules.set(viteUrl, script) - debug('add %o', script) - return script -} - -/** - * It's possible for multiple script types to have the same URL, this function - * updates all types. - */ -export function update(viteUrl: string): ScriptModule[] { - const types: ScriptType[] = ['iife', 'loader', 'module'] - const result: ScriptModule[] = [] - for (const type of types) { - const fileName = toFileName({ type, viteUrl }) - const script = scriptModules.get(fileName) - if (script) { - script.file = write({ viteUrl, type }) - result.push(script) - scriptModules.set(fileName, script) - } - } - - return result -} - -/** Call `write` to force a file write. Waits until the server is ready & writes the file. */ -export async function write({ - type, - viteUrl, -}: { - type: ScriptType - viteUrl: string -}): Promise<{ modules: ScriptModule[]; target: string }> { - const fileName = toFileName({ type, viteUrl }) - // using an observable so that update is cancellable - // when update is cancelled this promise will never resolve - // depending on when the switch happens, it may abort the file write - const results = await firstValueFrom( - serverEvent$.pipe( - // cancel previous update when file writer is closed - // subsequent mappings points to possibly cut work short - switchMap((event) => (event.type === 'start' ? of(event.server) : EMPTY)), - // load the module - mergeMap(async (server) => { - let serverModule = await server.moduleGraph.getModuleByUrl(viteUrl) - let transformResult: TransformResult | null = null - if (!serverModule) { - // first time, always transform - transformResult = await server.transformRequest(viteUrl) - serverModule = await server.moduleGraph.getModuleByUrl(viteUrl) - } - if (!serverModule) - throw new Error(`Unable to load "${viteUrl}" from server.`) - - if (!transformResult) - transformResult = await server.transformRequest(viteUrl) - if (!transformResult) - throw new TypeError(`Unable to load "${viteUrl}" from server.`) - - const { code, deps = [], dynamicDeps = [] } = transformResult - const { - root, - build: { outDir }, - } = server.config - const target = isAbsolute(outDir) - ? join(outDir, fileName) - : join(root, outDir, fileName) - - return { target, code, deps: [deps, dynamicDeps].flat() } - }), - // retry in case of dependency rebundle - retry({ count: 10, delay: 100 }), - // concurrently output file and add dependencies - mergeMap(async ({ target, code, deps }) => { - const output = outputFile(target, code, { encoding: 'utf8' }) - const added = deps.map((viteUrl: string) => add({ viteUrl, type })) - const [, ...modules] = await Promise.all([output, ...added]) - return { modules, target } - }), - ), - ) - debug('update %o', { type, viteUrl }) - return results -} - -/** Deterministic conversion of Vite URL to output filename. */ -export function toFileName({ - viteUrl, -}: { - type: ScriptType - viteUrl: string -}): string { - let replaced = viteUrl.replace(/\?/g, '__') - replaced = replaced.replace(/&/g, '--') - return `${replaced}.js` -} diff --git a/packages/vite-plugin/src/node/archive/hmrPayload.ts b/packages/vite-plugin/src/node/archive/hmrPayload.ts deleted file mode 100644 index 3bac515f7..000000000 --- a/packages/vite-plugin/src/node/archive/hmrPayload.ts +++ /dev/null @@ -1,146 +0,0 @@ -import { - buffer, - debounce, - filter, - map, - merge, - mergeMap, - Observable, - Subject, -} from 'rxjs' -import { - FullReloadPayload, - HMRPayload, - PrunePayload, - Update, - UpdatePayload, -} from 'vite' -import { outputByOwner, transformResultByOwner } from './fileMeta' -import { filesReady$ } from './fileWriter' -import { CrxHMRPayload } from '../types' - -export function isUpdatePayload(p: HMRPayload): p is UpdatePayload { - return p.type === 'update' -} -export function isFullReloadPayload(p: HMRPayload): p is FullReloadPayload { - return p.type === 'full-reload' -} -export function isPrunePayload(p: HMRPayload): p is PrunePayload { - return p.type === 'prune' -} -function isCrxHMRPayload(x: HMRPayload): x is CrxHMRPayload { - return x.type === 'custom' && x.event.startsWith('crx:') -} - -export const hmrPayload$ = new Subject() - -const hmrPrune$ = hmrPayload$.pipe(filter(isPrunePayload)) -const hmrFullReload$ = hmrPayload$.pipe(filter(isFullReloadPayload)) -const hmrUpdate$ = hmrPayload$.pipe(filter(isUpdatePayload)) -const payload$ = merge(hmrFullReload$, hmrPrune$, hmrUpdate$) - -type RebuildType = - | { - type: 'partial' - owners: Set - } - | { - type: 'full' - } -/** Emits based on buffered HMRPayloads */ -export const rebuildSignal$ = payload$.pipe( - // emit buffer when files are ready (now or later) - buffer(payload$.pipe(debounce(() => filesReady$))), - // flatten payloads - map((payloads): RebuildType => { - if (payloads.every(isUpdatePayload)) { - const owners = new Set() - for (const { updates } of payloads) - for (const { path } of updates) - if (transformResultByOwner.has(path)) owners.add(path) - - return { type: 'partial', owners } - } - - return { type: 'full' } - }), - // exclude empty rebuilds - filter((rebuild) => - rebuild.type === 'partial' ? rebuild.owners.size > 0 : true, - ), -) - -/** - * Buffer hmrPayloads by filesReady - * - * What about assets and manifest? - */ -export const crxHmrPayload$: Observable = hmrPayload$.pipe( - filter((p) => !isCrxHMRPayload(p)), - buffer(filesReady$), - mergeMap((pps) => { - let fullReload: FullReloadPayload | undefined - const payloads: HMRPayload[] = [] - for (const p of pps.slice(-50)) // payloads could accumulate during HTML development - if (p.type === 'full-reload') { - fullReload = p // only one full reload per build - } else { - payloads.push(p) - } - if (fullReload) payloads.push(fullReload) - return payloads - }), - map((p): HMRPayload => { - switch (p.type) { - case 'full-reload': { - const path = p.path && outputByOwner.get(p.path) - const fullReload: FullReloadPayload = { - type: 'full-reload', - path, - } - return fullReload - } - - case 'prune': { - const paths: string[] = [] - for (const owner of p.paths) - if (outputByOwner.has(owner)) paths.push(outputByOwner.get(owner)!) - return { type: 'prune', paths } - } - - case 'update': { - const updates: Update[] = [] - for (const { acceptedPath, path, ...rest } of p.updates) - if (outputByOwner.has(acceptedPath) && outputByOwner.has(path)) - updates.push({ - ...rest, - acceptedPath: outputByOwner.get(acceptedPath)!, - path: outputByOwner.get(path)!, - }) - return { type: 'update', updates } - } - - default: - return p // connected, custom, error - } - }), - filter((p) => { - switch (p.type) { - case 'full-reload': - return typeof p.path === 'undefined' - case 'prune': - return p.paths.length > 0 - case 'update': - return p.updates.length > 0 - default: - return true - } - }), - map( - (data): CrxHMRPayload => ({ - type: 'custom', - event: 'crx:content-script-payload', - data, - }), - ), -) diff --git a/packages/vite-plugin/src/node/archive/plugin-contentScripts.ts b/packages/vite-plugin/src/node/archive/plugin-contentScripts.ts deleted file mode 100644 index 8938e0a80..000000000 --- a/packages/vite-plugin/src/node/archive/plugin-contentScripts.ts +++ /dev/null @@ -1,677 +0,0 @@ -import contentHmrPort from 'client/es/hmr-content-port.ts' -import contentDevLoader from 'client/iife/content-dev-loader.ts' -import contentProLoader from 'client/iife/content-pro-loader.ts' -import injector from 'connect-injector' -import { createHash } from 'crypto' -import MagicString from 'magic-string' -import { OutputAsset, PluginContext } from 'rollup' -import { Manifest, ManifestChunk, ViteDevServer } from 'vite' -import { - isResourceByMatch, - isString, - getMatchPatternOrigin, - _debug, -} from '../helpers' -import { - WebAccessibleResourceById, - WebAccessibleResourceByMatch, -} from '../manifest' -import { parse } from '../path' -import { filesReady } from '../fileWriter' -import { crxRuntimeReload } from '../plugin-hmr' -import { CrxPluginFn } from '../types' -import { contentHmrPortId, preambleId } from '../virtualFileIds' - -interface Resources { - assets: Set - css: Set - imports: Set -} - -type DynamicScriptFormat = 'loader' | 'module' | 'iife' -interface DynamicScriptData { - id: string - importer: string - scriptId: string - finalId: string - format: DynamicScriptFormat - fileName?: string - loaderName?: string - loaderRefId?: string - refId?: string -} -// const scriptTypes: DynamicScriptFormat[] = ['module', 'iife', 'loader'] -// function isDynamicScriptFormat(x: string): x is DynamicScriptFormat { -// return scriptTypes.includes(x as DynamicScriptFormat) -// } - -function getScriptId({ - format, - id, -}: { - format: DynamicScriptFormat - id: string -}) { - return createHash('sha1') - .update(format) - .update(id) - .digest('base64') - .replace(/[^A-Za-z0-9]/g, '') - .slice(0, 8) -} - -const debug = _debug('content-scripts') - -export const dynamicResourcesName = '' as const - -/** - * This plugin creates `web_accessible_resources` entries for each declared - * content script and one entry for all the dynamic content scripts, then - * combines entries that share match patterns. - * - * This plugin leverages Vite's manifest feature to determine the exact - * resources for each script. The Vite manifest is not emitted b/c we overwrite - * it when we emit the CRX manifest. - * - * During development we use a dynamic CRX id and make all resources available - * to all urls. This is secure enough for our purposes b/c the CRX origin is - * changed randomly each runtime reload. - */ -export const pluginContentScripts: CrxPluginFn = ({ - contentScripts = {}, - browser = 'chrome', -}) => { - const { hmrTimeout = 5000, injectCss = true } = contentScripts - const dynamicScriptsById = new Map() - const dynamicScriptsByLoaderRefId = new Map() - const dynamicScriptsByRefId = new Map() - const dynamicScriptsByScriptId = new Map() - function emitDynamicScript( - this: PluginContext, - data: DynamicScriptData, - ): void { - if (data.format === 'iife') { - throw new Error( - `Dynamic script format IIFE is unimplemented (imported in file: ${data.importer})`.trim(), - ) - } else { - data.refId = this.emitFile({ type: 'chunk', id: data.id }) - dynamicScriptsByRefId.set(data.refId, data) - } - - if (data.format === 'loader') { - data.loaderRefId = this.emitFile({ - type: 'asset', - name: `content-script-loader.${parse(data.id).name}.js`, - // unset source causes Rollup error "Plugin error - Unable to get file name for asset..." - // we're referencing it in `import.meta.ROLLUP_FILE_URL_` below and Rollup wants to generate a hash - source: JSON.stringify(data), // set real source in generateBundle - }) - dynamicScriptsByLoaderRefId.set(data.loaderRefId, data) - } - } - async function resolveDynamicScript( - this: PluginContext, - _source: string, - importer?: string, - ) { - if (importer && _source.includes('?script')) { - const url = new URL(_source, 'stub://stub') - if (url.searchParams.has('scriptId')) { - const scriptId = url.searchParams.get('scriptId')! - const { finalId } = dynamicScriptsByScriptId.get(scriptId)! - return finalId - } else if (url.searchParams.has('script')) { - const [source] = _source.split('?') - const resolved = await this.resolve(source, importer, { - skipSelf: true, - }) - if (!resolved) - throw new Error( - `Could not resolve dynamic script: "${_source}" from "${importer}"`, - ) - const { id } = resolved - - let format: DynamicScriptFormat = 'loader' - if (url.searchParams.has('module')) { - format = 'module' - } else if (url.searchParams.has('iife')) { - format = 'iife' - } - - const scriptId = getScriptId({ format, id }) - const finalId = `${id}?scriptId=${scriptId}` - - const data = dynamicScriptsByScriptId.get(scriptId) ?? { - format, - id, - importer, - scriptId, - finalId, - } - dynamicScriptsByScriptId.set(scriptId, data) - dynamicScriptsById.set(finalId, data) - - return finalId - } - } - } - function loadDynamicScript(this: PluginContext, id: string) { - const data = dynamicScriptsById.get(id) - if (data) - return `export default import.meta.CRX_DYNAMIC_SCRIPT_${data.scriptId};` - } - - let port: string - let server: ViteDevServer - - let { preambleCode } = contentScripts - let preambleRefId: string - let contentClientRefId: string - - return [ - { - name: 'crx:content-scripts-pre', - apply: 'build', - enforce: 'pre', - async configureServer(_server) { - server = _server - port = server.config.server.port!.toString() - if ( - typeof preambleCode === 'undefined' && - server.config.plugins.some(({ name }) => - name.toLowerCase().includes('react'), - ) - ) { - try { - // rollup compiles this correctly for cjs output - const react = await import('@vitejs/plugin-react') - // auto config for react users - preambleCode = react.default.preambleCode - } catch (error) { - preambleCode = false - } - } - }, - buildStart() { - if (this.meta.watchMode) { - if (preambleCode) { - preambleRefId = this.emitFile({ - type: 'chunk', - id: preambleId, - name: 'content-script-preamble.js', - }) - } - - contentClientRefId = this.emitFile({ - type: 'chunk', - id: '/@vite/client', - name: 'content-script-client.js', - }) - } - }, - resolveId(source) { - if (source === preambleId) return preambleId - if (source === contentHmrPortId) return contentHmrPortId - }, - load(id) { - if (server && id === preambleId && typeof preambleCode === 'string') { - const defined = preambleCode.replace(/__BASE__/g, server.config.base) - return defined - } - - if (id === contentHmrPortId) { - const defined = contentHmrPort.replace( - '__CRX_HMR_TIMEOUT__', - JSON.stringify(hmrTimeout), - ) - return defined - } - }, - }, - { - name: 'crx:dynamic-scripts-load', - apply: 'serve', - enforce: 'pre', - // this.meta.watchMode is true for server - resolveId: resolveDynamicScript, - load: loadDynamicScript, - }, - { - name: 'crx:dynamic-scripts-load', - apply: 'build', - enforce: 'pre', - resolveId(id, importer) { - // should not run on file writer - if (!this.meta.watchMode) - return resolveDynamicScript.call(this, id, importer) - }, - load(id) { - // should not run on file writer - if (!this.meta.watchMode) return loadDynamicScript.call(this, id) - }, - }, - { - name: 'crx:dynamic-scripts-build', - apply: 'build', - buildStart() { - dynamicScriptsByLoaderRefId.clear() - dynamicScriptsByRefId.clear() - for (const [, data] of dynamicScriptsByScriptId) { - emitDynamicScript.call(this, data) - } - }, - async transform(code) { - if (code.includes('import.meta.CRX_DYNAMIC_SCRIPT_')) { - const match = code.match(/import.meta.CRX_DYNAMIC_SCRIPT_(.+?);/)! - const index = match.index! // only undefined when match is entire string - const [statement, scriptId] = match // only undefined when no groups - const data = dynamicScriptsByScriptId.get(scriptId)! - if (!data.refId) emitDynamicScript.call(this, data) - const magic = new MagicString(code) - magic.overwrite( - index, - index + statement.length, - `import.meta.ROLLUP_FILE_URL_${data.loaderRefId ?? data.refId};`, - ) - return { code: magic.toString(), map: magic.generateMap() } - } - }, - resolveFileUrl({ referenceId, fileName, moduleId }) { - if (moduleId && referenceId) - if ( - dynamicScriptsByRefId.has(referenceId) || - dynamicScriptsByLoaderRefId.has(referenceId) - ) { - return `"/${fileName}"` - } - }, - generateBundle(options, bundle) { - const preambleName = - this.meta.watchMode && preambleRefId - ? this.getFileName(preambleRefId) - : '' - const contentClientName = - this.meta.watchMode && contentClientRefId - ? this.getFileName(contentClientRefId) - : '' - - /* -------- SET DYNAMIC SCRIPT LOADER SOURCE ------- */ - - for (const data of dynamicScriptsByScriptId.values()) { - if (data.refId && data.loaderRefId) { - const scriptName = this.getFileName(data.refId) - const loaderName = this.getFileName(data.loaderRefId) - - const source = this.meta.watchMode - ? contentDevLoader - .replace(/__PREAMBLE__/g, JSON.stringify(preambleName)) - .replace(/__CLIENT__/g, JSON.stringify(contentClientName)) - .replace(/__SCRIPT__/g, JSON.stringify(scriptName)) - : contentProLoader.replace( - /__SCRIPT__/g, - JSON.stringify(scriptName), - ) - - const asset = bundle[loaderName] - if (asset?.type === 'asset') asset.source = source - } - } - }, - writeBundle() { - /* ------ CLEAN UP DATA FOR SERVER MIDDLEWARE ------ */ - for (const [, data] of dynamicScriptsByScriptId) { - if (data.refId) { - data.fileName = this.getFileName(data.refId) - delete data.refId - } - if (data.loaderRefId) { - data.loaderName = this.getFileName(data.loaderRefId) - delete data.loaderRefId - } - } - }, - }, - { - name: 'crx:dynamic-scripts-serve', - apply: 'serve', - configureServer(server) { - server.middlewares.use( - injector( - (req) => { - return !!req.url?.includes('?scriptId') - }, - // http requests are delayed until content scripts are available on disk - async (content, req, res, callback) => { - const code = isString(content) ? content : content.toString() - if (code.includes('import.meta.CRX_DYNAMIC_SCRIPT_')) { - const matches = Array.from( - code.matchAll(/import.meta.CRX_DYNAMIC_SCRIPT_(.+?);/g), - ).map((m) => ({ - statement: m[0], - index: m.index, - data: dynamicScriptsByScriptId.get(m[1])!, - })) - - // build is in progress, wait - if (matches.some(({ data }) => data.refId)) await filesReady() - - // some content scripts are new and don't exist on disk - if ( - matches.some( - ({ data }) => !(data.loaderName ?? data.fileName), - ) - ) { - // await rebuildFiles() - // new content scripts require a runtime reload - server.ws.send(crxRuntimeReload) - } - - const magic = new MagicString(code) - for (const { index, statement, data } of matches) - if (typeof index === 'number') { - magic.overwrite( - index, - index + statement.length, - `"/${data.loaderName ?? data.fileName}"`, - ) - } - - callback(null, magic.toString()) - } else { - callback(null, code) - } - }, - ), - ) - }, - }, - { - name: 'crx:∏content-script-resources', - apply: 'build', - enforce: 'post', - config({ build, ...config }, { command }) { - return { ...config, build: { ...build, manifest: command === 'build' } } - }, - renderCrxManifest(manifest, bundle) { - // set default value for web_accessible_resources - manifest.web_accessible_resources = - manifest.web_accessible_resources ?? [] - - // add resources from declared and dynamic scripts - if (manifest.content_scripts?.length || dynamicScriptsByRefId.size) - if (this.meta.watchMode) { - // remove dynamic resources placeholder - manifest.web_accessible_resources = - manifest.web_accessible_resources - .map(({ resources, ...rest }) => ({ - resources: resources.filter( - (r) => r !== dynamicResourcesName, - ), - ...rest, - })) - .filter(({ resources }) => resources.length) - - // during development don't specific resources - const war: WebAccessibleResourceByMatch = { - // all web origins can access - matches: [''], - // all resources are web accessible - resources: ['**/*', '*'], - } - - // if (browser !== 'firefox') { - // // change the extension origin on every reload - // // not allowed in FF b/c FF does this by default - // war.use_dynamic_url = true - // } - - manifest.web_accessible_resources.push(war) - } else { - const vmAsset = bundle['manifest.json'] as OutputAsset - if (!vmAsset) throw new Error('vite manifest is missing') - const viteManifest: Manifest = JSON.parse(vmAsset.source as string) - debug('vite manifest %O', viteManifest) - if (Object.keys(viteManifest).length === 0) return - - /* -------------- CONTENT SCRIPT DATA -------------- */ - - const filesByName = new Map() - for (const file of Object.values(viteManifest)) - filesByName.set(file.file, file) - - const chunksById = new Map() - for (const [name, chunk] of Object.entries(bundle)) - if (chunk.type === 'chunk' && chunk.facadeModuleId) - chunksById.set(chunk.facadeModuleId, name) - - /* ------------ CONTENT SCRIPT FUNCTIONS ----------- */ - - const getChunkResources = (chunk: typeof bundle[string]) => { - const chunks = new Set() - const assets = new Set() - if (chunk.type === 'asset') return { chunks, assets } - - const { dynamicImports, imports, modules } = chunk - for (const i of dynamicImports) chunks.add(i) - for (const i of imports) chunks.add(i) - - for (const id of Object.keys(modules)) - if (dynamicScriptsById.has(id)) { - const data = dynamicScriptsById.get(id)! - const fileName = this.getFileName(data.refId!) - const chunk = bundle[fileName] - if (chunk.type === 'chunk') chunks.add(fileName) - else assets.add(fileName) - } - - return { chunks, assets } - } - - const getResources = ( - name: string, - sets: Resources = { - assets: new Set(), - css: new Set(), - imports: new Set(), - }, - ): Resources => { - const { - assets = [], - css = [], - dynamicImports = [], - imports = [], - file, - } = filesByName.get(name) ?? // lookup by output filename - viteManifest[name] ?? // lookup by vite manifest import key - ({} as ManifestChunk) // if script is OutputAsset - - const chunk = bundle[file] - if (chunk?.type === 'chunk') { - const r = getChunkResources(chunk) - assets.push(...r.assets) - for (const chunk of r.chunks) { - sets.imports.add(chunk) - getResources(chunk, sets) - } - } - - for (const a of assets) sets.assets.add(a) - for (const c of css) sets.css.add(c) - for (const key of [...dynamicImports, ...imports]) { - const i = viteManifest[key].file - sets.imports.add(i) - getResources(key, sets) - } - - return sets - } - - /* ---------------- PROCESS SCRIPTS ---------------- */ - - for (const script of manifest.content_scripts ?? []) - if (script.js?.length) - for (const name of script.js) - if (script.matches?.length) { - const { assets, css, imports } = getResources(name) - - imports.add(name) - - const resource: - | WebAccessibleResourceById - | WebAccessibleResourceByMatch = { - matches: script.matches, - resources: [...assets, ...imports], - use_dynamic_url: false, - } - - if (css.size) - if (injectCss) { - // inject css through content script - script.css = script.css ?? [] - script.css.push(...css) - } else { - resource.resources.push(...css) - } - - if (resource.resources.length) { - // chromium only uses origin of match pattern - resource.matches = resource.matches.map( - getMatchPatternOrigin, - ) - manifest.web_accessible_resources.push(resource) - } - } - - const dynamicResourceSet = new Set() - for (const [refId, { format }] of dynamicScriptsByRefId) - if (format === 'loader') { - const name = this.getFileName(refId) - const { assets, css, imports } = getResources(name) - - dynamicResourceSet.add(name) - for (const a of assets) dynamicResourceSet.add(a) - for (const c of css) dynamicResourceSet.add(c) - for (const i of imports) dynamicResourceSet.add(i) - } - - if (dynamicResourceSet.size) { - let resource = manifest.web_accessible_resources!.find( - ({ resources: [r] }) => r === dynamicResourcesName, - ) - if (!resource) { - resource = { - resources: [dynamicResourcesName], - matches: ['http://*/*', 'https://*/*'], - } - manifest.web_accessible_resources!.push(resource) - } - - resource.resources = [...dynamicResourceSet] - } - } - - // clean up web_accessible_resources - if (manifest.web_accessible_resources?.length) { - const wars = manifest.web_accessible_resources - manifest.web_accessible_resources = [] - const map = new Map>() - for (const war of wars) - if (isResourceByMatch(war)) { - // combine resources that share match patterns - const { matches, resources, use_dynamic_url = false } = war - const key = [use_dynamic_url, matches.sort()] - .map((x) => JSON.stringify(x)) - .join('::') - const set = map.get(key) ?? new Set() - resources.forEach((r) => set.add(r)) - map.set(key, set) - } else { - // FF does not allow the use_dynamic_url key b/c the urls are always - // dynamic in FF - if (browser === 'firefox' && 'use_dynamic_url' in war) - delete war.use_dynamic_url - - // don't touch resources by CRX_id - manifest.web_accessible_resources.push(war) - } - // rebuild combined resources - for (const [key, set] of map) { - const [use_dynamic_url, matches] = key - .split('::') - .map((x) => JSON.parse(x)) as [boolean, string[]] - - const war: - | WebAccessibleResourceById - | WebAccessibleResourceByMatch = { - matches, - resources: [...set], - } - - // FF does not allow the use_dynamic_url key b/c the urls are always - // dynamic in FF - if (browser !== 'firefox') war.use_dynamic_url = use_dynamic_url - - manifest.web_accessible_resources.push(war) - } - } else { - // array is empty or undefined - delete manifest.web_accessible_resources - } - - return manifest - }, - }, - { - name: 'crx:content-scripts-post', - apply: 'build', - enforce: 'post', - renderCrxManifest(manifest, bundle) { - if (this.meta.watchMode && typeof port === 'undefined') - throw new Error('server port is undefined') - - const preambleName = - this.meta.watchMode && preambleRefId - ? this.getFileName(preambleRefId) - : '' - const contentClientName = - this.meta.watchMode && contentClientRefId - ? this.getFileName(contentClientRefId) - : '' - - if (!manifest.content_scripts?.length && !dynamicScriptsByRefId.size) { - delete bundle[contentClientName] - return manifest - } - - /* --------- APPLY DECLARED SCRIPT LOADERS --------- */ - - manifest.content_scripts = manifest.content_scripts?.map( - ({ js, ...rest }) => ({ - js: js?.map((f: string) => { - const name = `content-script-loader.${parse(f).name}.js` - const source = this.meta.watchMode - ? contentDevLoader - .replace(/__PREAMBLE__/g, JSON.stringify(preambleName)) - .replace(/__CLIENT__/g, JSON.stringify(contentClientName)!) - .replace(/__SCRIPT__/g, JSON.stringify(f)) - .replace(/__TIMESTAMP__/g, JSON.stringify(Date.now())) - : contentProLoader.replace(/__SCRIPT__/g, JSON.stringify(f)) - - const refId = this.emitFile({ - type: 'asset', - name, - source, - }) - - return this.getFileName(refId) - }), - ...rest, - }), - ) - - return manifest - }, - }, - ] -} diff --git a/packages/vite-plugin/src/node/archive/plugin-fileWriter--pages.ts b/packages/vite-plugin/src/node/archive/plugin-fileWriter--pages.ts deleted file mode 100644 index 47848d893..000000000 --- a/packages/vite-plugin/src/node/archive/plugin-fileWriter--pages.ts +++ /dev/null @@ -1,55 +0,0 @@ -import precontrollerScript from 'client/es/page-precontroller-script.ts' -import precontrollerHtml from 'client/html/precontroller.html' -import { htmlFiles } from '../helpers' -import { CrxPlugin, CrxPluginFn } from '../types' - -export const pluginFileWriterPages: CrxPluginFn = () => { - let precontrollerName: string | undefined - - return { - name: 'crx:file-writer-pages', - apply: 'build', - // using configure server to co-locate related code - configureServer(server) { - const plugins = server.config.plugins as CrxPlugin[] - const i = plugins.findIndex(({ name }) => name === 'alias') - plugins.splice(i, 0, { - name: 'crx:load-precontroller', - apply: 'serve', - load(id) { - // if the placeholder html loads before the service worker controls fetch, - // the script may load from the devserver; in this case the page should reload - if (id === `/${precontrollerName}`) return 'location.reload();' - }, - }) - }, - renderCrxManifest(manifest) { - /** - * We don't bundle HTML files during development b/c the background HMR - * client to redirects all HTML requests to the dev server. - * - * Chrome checks that all the HTML pages in the manifest have files to - * match, so we emit a stub HTML page. This page is never used. - * - * The only case where we use the stub page is if the background opens a - * page immediately upon start. The background HMR client might not be - * ready in those ~100ms after installation, so we use a simple script to - * reload the stub page. - */ - const refId = this.emitFile({ - type: 'asset', - name: 'precontroller.js', - source: precontrollerScript, - }) - precontrollerName = this.getFileName(refId) - for (const fileName of htmlFiles(manifest)) { - this.emitFile({ - type: 'asset', - fileName, - source: precontrollerHtml.replace('%PATH%', `/${precontrollerName}`), - }) - } - return manifest - }, - } -} diff --git a/packages/vite-plugin/src/node/archive/plugin-fileWriter--polyfill.ts b/packages/vite-plugin/src/node/archive/plugin-fileWriter--polyfill.ts deleted file mode 100644 index 52ad228fa..000000000 --- a/packages/vite-plugin/src/node/archive/plugin-fileWriter--polyfill.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { readFileSync } from 'fs' -import MagicString from 'magic-string' -import { createRequire } from 'module' -import { idByUrl } from './fileMeta' -import { CrxPluginFn } from './types' -import { - contentHmrPortId, - customElementsId, - viteClientId, -} from './virtualFileIds' - -const _require = - typeof require === 'undefined' ? createRequire(import.meta.url) : require -const customElementsPath = _require.resolve(customElementsId) -const customElementsCode = readFileSync(customElementsPath, 'utf8') -const customElementsMap = readFileSync(`${customElementsPath}.map`, 'utf8') - -/** - * Adds polyfills for content scripts: - * - * - In `@vite/client`, replace WebSocket with HMRPort to connect content scripts - * to background, which uses custom client to connect to server - * - Enable custom elements in content scripts during development, used by Vite - * HMR Error Overlay. - * - * See Chromium bug [390807 - Content scripts can't define custom - * elements](https://bugs.chromium.org/p/chromium/issues/detail?id=390807) - * - * This means custom elements will work in development but not in production. - * - * TODO: Autodetect calls to `customElements.define` during build; import the - * polyfill when appropriate. - */ -export const pluginCustomElementsPolyfill: CrxPluginFn = () => { - return { - name: 'crx:custom-elements-polyfill', - apply: 'serve', - enforce: 'pre', - load(id) { - if (id === idByUrl.get(customElementsId)) { - return { code: customElementsCode, map: customElementsMap } - } - }, - transform(code, id) { - if (id === idByUrl.get(viteClientId)) { - const magic = new MagicString(code) - magic.prepend(`import '${customElementsId}';`) - magic.prepend(`import { HMRPort } from '${contentHmrPortId}';`) - const ws = 'new WebSocket' - const index = code.indexOf(ws) - magic.overwrite(index, index + ws.length, 'new HMRPort') - return { code: magic.toString(), map: magic.generateMap() } - } - }, - } -} diff --git a/packages/vite-plugin/src/node/archive/plugin-fileWriter--public-dir.ts b/packages/vite-plugin/src/node/archive/plugin-fileWriter--public-dir.ts deleted file mode 100644 index bcfddcc23..000000000 --- a/packages/vite-plugin/src/node/archive/plugin-fileWriter--public-dir.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { CrxPluginFn } from './types' -import glob from 'fast-glob' -import { ResolvedConfig } from 'vite' -import { relative } from './path' -import { promises as fs } from 'fs' -const { readFile } = fs - -export const pluginFileWriterPublicDir: CrxPluginFn = () => { - let config: ResolvedConfig - return { - name: 'crx:file-writer-public-dir', - apply: 'build', - configResolved(_config) { - config = _config - }, - async buildStart() { - // rebuild when files in public dir are added or changed - // Rollup feature PR: https://github.com/rollup/rollup/pull/3812 - const publicFiles = await glob(`${config.publicDir}/**/*`) - for (const file of publicFiles) { - const source = await readFile(file) - const fileName = relative(config.publicDir, file) - this.emitFile({ type: 'asset', fileName, source }) - } - }, - } -} diff --git a/packages/vite-plugin/src/node/archive/plugin-fileWriter.ts b/packages/vite-plugin/src/node/archive/plugin-fileWriter.ts deleted file mode 100644 index aaa33095c..000000000 --- a/packages/vite-plugin/src/node/archive/plugin-fileWriter.ts +++ /dev/null @@ -1,52 +0,0 @@ -import * as fileWriter from './fileWriter' -import { CrxPlugin, CrxPluginFn } from './types' - -function sortPlugins(plugins: CrxPlugin[], command?: 'build' | 'serve') { - const pre: CrxPlugin[] = [] - const mid: CrxPlugin[] = [] - const post: CrxPlugin[] = [] - for (const p of plugins) { - if (p.apply === command || !p.apply || !command) { - if (p.enforce === 'pre') pre.push(p) - else if (p.enforce === 'post') post.push(p) - else mid.push(p) - } - } - return { pre, mid, post } -} - -export const pluginFileWriter = - (crxPlugins: CrxPlugin[]): CrxPluginFn => - () => { - const { pre, mid, post } = sortPlugins(crxPlugins, 'build') - // crx plugins, does not include plugins from vite config - const plugins = [...pre, ...mid, ...post].flat() - - return { - name: 'crx:file-writer', - apply: 'serve', - async config(_config, env) { - let config = _config - for (const p of plugins) { - const r = await p.config?.(config, env) - config = r ?? config - } - return config - }, - async configResolved(_config) { - await Promise.all(plugins.map((p) => p.configResolved?.(_config))) - }, - async configureServer(server) { - server.httpServer?.once('listening', () => { - fileWriter.start({ server, plugins }) - }) - }, - closeBundle() { - try { - fileWriter.close() - } catch (error) { - console.error(error) - } - }, - } - } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6aade6cc3..a683aebae 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -241,9 +241,6 @@ importers: cheerio: specifier: ^1.0.0-rc.10 version: 1.0.0-rc.10 - connect-injector: - specifier: ^0.4.4 - version: 0.4.4 convert-source-map: specifier: ^1.7.0 version: 1.8.0 @@ -263,8 +260,8 @@ importers: specifier: ^3.0.2 version: 3.0.2 magic-string: - specifier: ^0.26.0 - version: 0.26.2 + specifier: ^0.30.12 + version: 0.30.12 picocolors: specifier: ^1.0.0 version: 1.0.0 @@ -5378,7 +5375,7 @@ packages: engines: {node: '>=6.0.0'} dependencies: '@jridgewell/set-array': 1.1.1 - '@jridgewell/sourcemap-codec': 1.4.13 + '@jridgewell/sourcemap-codec': 1.4.14 '@jridgewell/trace-mapping': 0.3.13 /@jridgewell/resolve-uri@3.0.7: @@ -5399,17 +5396,18 @@ packages: '@jridgewell/gen-mapping': 0.3.2 '@jridgewell/trace-mapping': 0.3.17 - /@jridgewell/sourcemap-codec@1.4.13: - resolution: {integrity: sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==} - /@jridgewell/sourcemap-codec@1.4.14: resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} + /@jridgewell/sourcemap-codec@1.5.0: + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + dev: false + /@jridgewell/trace-mapping@0.3.13: resolution: {integrity: sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==} dependencies: '@jridgewell/resolve-uri': 3.0.7 - '@jridgewell/sourcemap-codec': 1.4.13 + '@jridgewell/sourcemap-codec': 1.4.14 /@jridgewell/trace-mapping@0.3.17: resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==} @@ -6753,7 +6751,7 @@ packages: '@babel/plugin-transform-react-jsx-development': 7.18.6(@babel/core@7.19.1) '@babel/plugin-transform-react-jsx-self': 7.18.6(@babel/core@7.19.1) '@babel/plugin-transform-react-jsx-source': 7.18.6(@babel/core@7.19.1) - magic-string: 0.26.6 + magic-string: 0.26.7 react-refresh: 0.14.0 vite: 3.2.11(@types/node@17.0.18) transitivePeerDependencies: @@ -8323,18 +8321,6 @@ packages: engines: {node: '>=0.8'} dev: false - /connect-injector@0.4.4: - resolution: {integrity: sha1-qBlZwx7PXKoPPcwyXCjtkLgwqpA=} - engines: {node: '>= 0.8.0'} - dependencies: - debug: 2.6.9 - q: 1.5.1 - stream-buffers: 0.2.6 - uberproto: 1.2.0 - transitivePeerDependencies: - - supports-color - dev: false - /consola@2.15.3: resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==} dev: false @@ -12648,19 +12634,6 @@ packages: sourcemap-codec: 1.4.8 dev: true - /magic-string@0.26.2: - resolution: {integrity: sha512-NzzlXpclt5zAbmo6h6jNc8zl2gNRGHvmsZW4IvZhTC4W7k4OlLP+S5YLussa/r3ixNT66KOQfNORlXHSOy/X4A==} - engines: {node: '>=12'} - dependencies: - sourcemap-codec: 1.4.8 - - /magic-string@0.26.6: - resolution: {integrity: sha512-6d+3bFybzyQFJYSoRsl9ZC0wheze8M1LrQC7tNMRqXR4izUTDOLMd9BtSuExK9iAukFh+s5K0WAhc/dlQ+HKYA==} - engines: {node: '>=12'} - dependencies: - sourcemap-codec: 1.4.8 - dev: true - /magic-string@0.26.7: resolution: {integrity: sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==} engines: {node: '>=12'} @@ -12668,6 +12641,12 @@ packages: sourcemap-codec: 1.4.8 dev: true + /magic-string@0.30.12: + resolution: {integrity: sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==} + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + dev: false + /make-dir@3.1.0: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} @@ -14465,11 +14444,6 @@ packages: resolution: {integrity: sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA==} dev: false - /q@1.5.1: - resolution: {integrity: sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=} - engines: {node: '>=0.6.0', teleport: '>=0.2.0'} - dev: false - /qs@6.10.3: resolution: {integrity: sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==} engines: {node: '>=0.6'} @@ -15137,7 +15111,7 @@ packages: rollup: ^2.70 typescript: ^4.6 dependencies: - magic-string: 0.26.2 + magic-string: 0.26.7 rollup: 2.79.2 typescript: 4.6.4 optionalDependencies: @@ -15679,6 +15653,7 @@ packages: /sourcemap-codec@1.4.8: resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} + dev: true /space-separated-tokens@1.1.5: resolution: {integrity: sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==} @@ -15795,11 +15770,6 @@ packages: resolution: {integrity: sha512-uUZI65yrV2Qva5gqE0+A7uVAvO40iPo6jGhs7s8keRfHCmtg+uB2X6EiLGCI9IgL1J17xGhvoOqSz79lzICPTA==} dev: true - /stream-buffers@0.2.6: - resolution: {integrity: sha1-GBwI1bs2kARfaUAbmuanoM8zE/w=} - engines: {node: '>= 0.3.0'} - dev: false - /stream-transform@2.1.3: resolution: {integrity: sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==} dependencies: @@ -16433,10 +16403,6 @@ packages: resolution: {integrity: sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==} dev: false - /uberproto@1.2.0: - resolution: {integrity: sha1-YdTqsCT5CcTm6lK+hnxIlKS+63Y=} - dev: false - /ufo@1.1.0: resolution: {integrity: sha512-LQc2s/ZDMaCN3QLpa+uzHUOQ7SdV0qgv3VBXOolQGXTaaZpIur6PwUclF5nN2hNkiTRcUugXd1zFOW3FLJ135Q==} dev: true