diff --git a/packages/qwik/package.json b/packages/qwik/package.json index 5ee9e734bbf..13514913ce6 100644 --- a/packages/qwik/package.json +++ b/packages/qwik/package.json @@ -31,7 +31,9 @@ "@builder.io/qwik": "workspace:^", "@builder.io/qwik-dom": "workspace:^", "image-size": "1.1.1", - "kleur": "4.1.5" + "kleur": "4.1.5", + "ignore": "5.3.1", + "ts-morph": "23.0.0" }, "engines": { "node": ">=16.8.0 <18.0.0 || >=18.11" diff --git a/packages/qwik/src/cli/migrate-v2/rename-import.ts b/packages/qwik/src/cli/migrate-v2/rename-import.ts new file mode 100644 index 00000000000..d75d1ba8367 --- /dev/null +++ b/packages/qwik/src/cli/migrate-v2/rename-import.ts @@ -0,0 +1,49 @@ +import { Project, ts } from 'ts-morph'; +import { visitNotIgnoredFiles } from './tools/visit-not-ignored-files'; +import { log } from '@clack/prompts'; + +export function replaceImportInFiles( + changes: [oldImport: string, newImport: string][], + library: string +) { + const project = new Project(); + + visitNotIgnoredFiles('.', (path) => { + if (!path.endsWith('.ts') && !path.endsWith('.tsx')) { + return; + } + project.addSourceFileAtPath(path); + }); + + project.getSourceFiles().forEach((sourceFile) => { + let hasChanges = false; + + sourceFile.getImportDeclarations().forEach((importDeclaration) => { + // startsWith is used in order to handle nested imports + if (importDeclaration.getModuleSpecifierValue().startsWith(library)) { + for (const [oldImport, newImport] of changes) { + importDeclaration.getNamedImports().forEach((namedImport) => { + if (namedImport.getName() === oldImport) { + namedImport.setName(newImport); + hasChanges = true; + } + }); + } + } + }); + + sourceFile.getDescendantsOfKind(ts.SyntaxKind.Identifier).forEach((identifier) => { + for (const [oldImport, newImport] of changes) { + if (identifier.getText() === oldImport) { + identifier.replaceWithText(newImport); + hasChanges = true; + } + } + }); + + if (hasChanges) { + sourceFile.saveSync(); + log.info(`Updated imports in ${sourceFile.getFilePath()}`); + } + }); +} diff --git a/packages/qwik/src/cli/migrate-v2/replace-package.ts b/packages/qwik/src/cli/migrate-v2/replace-package.ts new file mode 100644 index 00000000000..86826e52794 --- /dev/null +++ b/packages/qwik/src/cli/migrate-v2/replace-package.ts @@ -0,0 +1,85 @@ +import { basename } from 'path'; +import { isBinaryPath } from './tools/binary-extensions'; +import { visitNotIgnoredFiles } from './tools/visit-not-ignored-files'; +import { readFileSync, writeFileSync } from 'fs'; +import { log } from '@clack/prompts'; + +function updateFileContent(path: string, content: string) { + writeFileSync(path, content); + log.info(`"${path}" has been updated`); +} + +export function replacePackage( + oldPackageName: string, + newPackageName: string, + newPackageVersion: string +): void { + replacePackageInDependencies(oldPackageName, newPackageName, newPackageVersion); + + replaceMentions(oldPackageName, newPackageName); +} + +function replacePackageInDependencies( + oldPackageName: string, + newPackageName: string, + newPackageVersion: string +) { + visitNotIgnoredFiles('.', (path) => { + if (basename(path) !== 'package.json') { + return; + } + + try { + const packageJson = JSON.parse(readFileSync(path, 'utf-8')); + for (const deps of [ + packageJson.dependencies ?? {}, + packageJson.devDependencies ?? {}, + packageJson.peerDependencies ?? {}, + packageJson.optionalDependencies ?? {}, + ]) { + if (oldPackageName in deps) { + deps[newPackageName] = newPackageVersion; + delete deps[oldPackageName]; + } + } + updateFileContent(path, JSON.stringify(packageJson, null, 2)); + } catch (e) { + console.warn(`Could not replace ${oldPackageName} with ${newPackageName} in ${path}.`); + } + }); +} + +function replaceMentions(oldPackageName: string, newPackageName: string) { + visitNotIgnoredFiles('.', (path) => { + if (isBinaryPath(path)) { + return; + } + + const ignoredFiles = [ + 'yarn.lock', + 'package-lock.json', + 'pnpm-lock.yaml', + 'bun.lockb', + 'CHANGELOG.md', + ]; + if (ignoredFiles.includes(basename(path))) { + return; + } + + try { + const contents = readFileSync(path, 'utf-8'); + + if (!contents.includes(oldPackageName)) { + return; + } + + updateFileContent(path, contents.replace(new RegExp(oldPackageName, 'g'), newPackageName)); + } catch { + // Its **probably** ok, contents can be null if the file is too large or + // there was an access exception. + log.warn( + `An error was thrown when trying to update ${path}. If you believe the migration should have updated it, be sure to review the file and open an issue.` + ); + } + }); +} diff --git a/packages/qwik/src/cli/migrate-v2/run-migration.ts b/packages/qwik/src/cli/migrate-v2/run-migration.ts new file mode 100644 index 00000000000..7dcdb6c0591 --- /dev/null +++ b/packages/qwik/src/cli/migrate-v2/run-migration.ts @@ -0,0 +1,60 @@ +import { confirm, intro, isCancel, log } from '@clack/prompts'; +import type { AppCommand } from '../utils/app-command'; +import { bgMagenta, green } from 'kleur/colors'; +import { bye } from '../utils/utils'; +import { replacePackage } from './replace-package'; +import { + installTsMorph, + removeTsMorphFromPackageJson, + updateDependencies, +} from './update-dependencies'; +import { versions } from './versions'; +import { replaceImportInFiles } from './rename-import'; + +export async function runV2Migration(app: AppCommand) { + intro( + `✨ ${bgMagenta(' This command will migrate your Qwik application from v1 to v2 \n')}` + + `This includes the following: \n` + + ` - "@builder.io/qwik", "@builder.io/qwik-city" and "@builder.io/qwik-react" packages will be rescoped to "@qwik.dev/core", "@qwik.dev/router" and "@qwik.dev/react" respectively \n` + + ` - related dependencies will be updated \n` + ); + const proceed = await confirm({ + message: 'Do you want to proceed?', + initialValue: true, + }); + + if (isCancel(proceed) || !proceed) { + bye(); + } + + try { + const installedTsMorph = await installTsMorph(); + + replaceImportInFiles( + [ + ['QwikCityProvider', 'QwikRouterProvider'], + ['qwikCity', 'qwikRouter'], + ['QwikCityVitePluginOptions', 'QwikRouterVitePluginOptions'], + ['QwikCityPlugin', 'QwikRouterPlugin'], + ['createQwikCity', 'createQwikRouter'], + ['QwikCityNodeRequestOptions', 'QwikRouterNodeRequestOptions'], + ], + '@builder.io/qwik-city' + ); + + replacePackage('@builder.io/qwik-city', '@qwik.dev/router', versions['@qwik.dev/router']); + replacePackage('@builder.io/qwik-react', '@qwik.dev/react', versions['@qwik.dev/react']); + // "@builder.io/qwik" should be the last one because it's name is a substring of the package names above + replacePackage('@builder.io/qwik', '@qwik.dev/core', versions['@qwik.dev/core']); + + if (installedTsMorph) { + await removeTsMorphFromPackageJson(); + } + + await updateDependencies(); + log.success(`${green(`Your application has been successfully migrated to v2!`)}`); + } catch (error) { + console.error(error); + throw error; + } +} diff --git a/packages/qwik/src/cli/migrate-v2/tools/binary-extensions.ts b/packages/qwik/src/cli/migrate-v2/tools/binary-extensions.ts new file mode 100644 index 00000000000..d4aa5d3401b --- /dev/null +++ b/packages/qwik/src/cli/migrate-v2/tools/binary-extensions.ts @@ -0,0 +1,277 @@ +import { extname } from 'path'; + +const binaryExtensions = new Set([ + // types originally from https://github.com/sindresorhus/binary-extensions/blob/40e44b510d87a63dcf42300bc8fbcb105f45a61c/binary-extensions.json + '.3dm', + '.3ds', + '.3g2', + '.3gp', + '.7z', + '.a', + '.aac', + '.adp', + '.ai', + '.aif', + '.aiff', + '.als', + '.alz', + '.ape', + '.apk', + '.appimage', + '.ar', + '.arj', + '.asf', + '.au', + '.avi', + '.bak', + '.baml', + '.bh', + '.bin', + '.bk', + '.bmp', + '.btif', + '.bz2', + '.bzip2', + '.cab', + '.caf', + '.cgm', + '.class', + '.cmx', + '.cpio', + '.cr2', + '.cur', + '.dat', + '.dcm', + '.deb', + '.dex', + '.djvu', + '.dll', + '.dmg', + '.dng', + '.doc', + '.docm', + '.docx', + '.dot', + '.dotm', + '.dra', + '.DS_Store', + '.dsk', + '.dts', + '.dtshd', + '.dvb', + '.dwg', + '.dxf', + '.ecelp4800', + '.ecelp7470', + '.ecelp9600', + '.egg', + '.eol', + '.eot', + '.epub', + '.exe', + '.f4v', + '.fbs', + '.fh', + '.fla', + '.flac', + '.flatpak', + '.fli', + '.flv', + '.fpx', + '.fst', + '.fvt', + '.g3', + '.gh', + '.gif', + '.glb', + '.graffle', + '.gz', + '.gzip', + '.h261', + '.h263', + '.h264', + '.icns', + '.ico', + '.ief', + '.img', + '.ipa', + '.iso', + '.jar', + '.jpeg', + '.jpg', + '.jpgv', + '.jpm', + '.jxr', + '.key', + '.keystore', + '.ktx', + '.lha', + '.lib', + '.lvp', + '.lz', + '.lzh', + '.lzma', + '.lzo', + '.m3u', + '.m4a', + '.m4v', + '.mar', + '.mdi', + '.mht', + '.mid', + '.midi', + '.mj2', + '.mka', + '.mkv', + '.mmr', + '.mng', + '.mobi', + '.mov', + '.movie', + '.mp3', + '.mp4', + '.mp4a', + '.mpeg', + '.mpg', + '.mpga', + '.msi', + '.mxu', + '.nef', + '.npx', + '.npy', + '.numbers', + '.nupkg', + '.o', + '.odp', + '.ods', + '.odt', + '.oga', + '.ogg', + '.ogv', + '.otf', + '.ott', + '.pages', + '.pbm', + '.pbf', + '.pcx', + '.pdb', + '.pdf', + '.pea', + '.pgm', + '.pic', + '.pkg', + '.plist', + '.png', + '.pnm', + '.pot', + '.potm', + '.potx', + '.ppa', + '.ppam', + '.ppm', + '.pps', + '.ppsm', + '.ppsx', + '.ppt', + '.pptm', + '.pptx', + '.psd', + '.pxd', + '.pxz', + '.pya', + '.pyc', + '.pyo', + '.pyv', + '.qt', + '.rar', + '.ras', + '.raw', + '.resources', + '.rgb', + '.rip', + '.rlc', + '.rmf', + '.rmvb', + '.rpm', + '.rtf', + '.rz', + '.s3m', + '.s7z', + '.scpt', + '.sgi', + '.shar', + '.snap', + '.sil', + '.sketch', + '.slk', + '.smv', + '.snk', + '.so', + '.stl', + '.suo', + '.sub', + '.swf', + '.tar', + '.tbz', + '.tbz2', + '.tga', + '.tgz', + '.thmx', + '.tif', + '.tiff', + '.tlz', + '.ttc', + '.ttf', + '.txz', + '.udf', + '.uvh', + '.uvi', + '.uvm', + '.uvp', + '.uvs', + '.uvu', + '.viv', + '.vob', + '.war', + '.wav', + '.wax', + '.wbmp', + '.wdp', + '.weba', + '.webm', + '.webp', + '.whl', + '.wim', + '.wm', + '.wma', + '.wmv', + '.wmx', + '.woff', + '.woff2', + '.wrm', + '.wvx', + '.xbm', + '.xif', + '.xla', + '.xlam', + '.xls', + '.xlsb', + '.xlsm', + '.xlsx', + '.xlt', + '.xltm', + '.xltx', + '.xm', + '.xmind', + '.xpi', + '.xpm', + '.xwd', + '.xz', + '.z', + '.zip', + '.zipx', +]); + +export function isBinaryPath(path: string): boolean { + return binaryExtensions.has(extname(path).toLowerCase()); +} diff --git a/packages/qwik/src/cli/migrate-v2/tools/visit-not-ignored-files.ts b/packages/qwik/src/cli/migrate-v2/tools/visit-not-ignored-files.ts new file mode 100644 index 00000000000..6312e8f1a1f --- /dev/null +++ b/packages/qwik/src/cli/migrate-v2/tools/visit-not-ignored-files.ts @@ -0,0 +1,28 @@ +import { existsSync, lstatSync, readFileSync, readdirSync } from 'fs'; +import ignore from 'ignore'; +import { join, relative } from 'path'; + +/** Utility to act on all files in a tree that are not ignored by git. */ +export function visitNotIgnoredFiles(dirPath: string, visitor: (path: string) => void): void { + let ig: ReturnType | undefined; + if (existsSync('.gitignore')) { + ig = ignore(); + ig.add('.git'); + ig.add(readFileSync('.gitignore', 'utf-8')); + } + dirPath = relative(process.cwd(), dirPath); + if (dirPath !== '' && ig?.ignores(dirPath)) { + return; + } + for (const child of readdirSync(join(process.cwd(), dirPath))) { + const fullPath = join(dirPath, child); + if (ig?.ignores(fullPath)) { + continue; + } + if (lstatSync(fullPath).isFile()) { + visitor(fullPath); + } else { + visitNotIgnoredFiles(fullPath, visitor); + } + } +} diff --git a/packages/qwik/src/cli/migrate-v2/update-dependencies.ts b/packages/qwik/src/cli/migrate-v2/update-dependencies.ts new file mode 100644 index 00000000000..7ae96782127 --- /dev/null +++ b/packages/qwik/src/cli/migrate-v2/update-dependencies.ts @@ -0,0 +1,48 @@ +import { installDeps } from '../utils/install-deps'; +import { getPackageManager, readPackageJson, writePackageJson } from './../utils/utils'; +import { versions } from './versions'; + +export async function updateDependencies() { + // TODO(migrate-v2): rely on workspaceRoot instead? + const packageJson = await readPackageJson(process.cwd()); + const devDependencies = (packageJson.devDependencies ??= {}); + const dependencies = (packageJson.dependencies ??= {}); + + for (const key of Object.keys(devDependencies)) { + if (Object.prototype.hasOwnProperty.call(versions, key)) { + devDependencies[key] = versions[key as unknown as keyof typeof versions]; + } + } + for (const key of Object.keys(dependencies)) { + if (Object.prototype.hasOwnProperty.call(versions, key)) { + dependencies[key] = versions[key as unknown as keyof typeof versions]; + } + } + + await writePackageJson(process.cwd(), packageJson); + runInstall(); +} + +export async function installTsMorph() { + const packageJson = await readPackageJson(process.cwd()); + if (packageJson.dependencies?.['ts-morph'] || packageJson.devDependencies?.['ts-morph']) { + return false; + } + (packageJson.devDependencies ??= {})['ts-morph'] = 'latest'; + await runInstall(); + return true; +} + +async function runInstall() { + const { install } = installDeps(getPackageManager(), process.cwd()); + const passed = await install; + if (!passed) { + throw new Error('Failed to install dependencies'); + } +} + +export async function removeTsMorphFromPackageJson() { + const packageJson = await readPackageJson(process.cwd()); + delete packageJson.dependencies?.['ts-morph']; + delete packageJson.devDependencies?.['ts-morph']; +} diff --git a/packages/qwik/src/cli/migrate-v2/versions.ts b/packages/qwik/src/cli/migrate-v2/versions.ts new file mode 100644 index 00000000000..c56be3a8b52 --- /dev/null +++ b/packages/qwik/src/cli/migrate-v2/versions.ts @@ -0,0 +1,6 @@ +export const versions = { + '@qwik.dev/core': '2.0.0-alpha.0', + '@qwik.dev/router': '2.0.0-alpha.0', + '@qwik.dev/react': '2.0.0-alpha.0', + 'eslint-plugin-qwik': '2.0.0-alpha.0', +}; diff --git a/packages/qwik/src/cli/run.ts b/packages/qwik/src/cli/run.ts index fe9ed7f2f9b..cd4dccd0987 100644 --- a/packages/qwik/src/cli/run.ts +++ b/packages/qwik/src/cli/run.ts @@ -7,6 +7,7 @@ import { runJokeCommand } from './joke/run-joke-command'; import { note, panic, pmRunCmd, printHeader, bye } from './utils/utils'; import { runBuildCommand } from './utils/run-build-command'; import { intro, isCancel, select, confirm } from '@clack/prompts'; +import { runV2Migration } from './migrate-v2/run-migration'; const SPACE_TO_HINT = 18; const COMMANDS = [ @@ -45,6 +46,13 @@ const COMMANDS = [ run: () => runJokeCommand(), showInHelp: true, }, + { + value: 'migrate-v2', + label: 'migrate-v2', + hint: 'Rescopes the application from @builder.io/* namespace to @qwik.dev/*', + run: (app: AppCommand) => runV2Migration(app), + showInHelp: false, + }, { value: 'help', label: 'help', @@ -98,6 +106,10 @@ async function runCommand(app: AppCommand) { await runJokeCommand(); return; } + case 'migrate-v2': { + await runV2Migration(app); + return; + } case 'version': { printVersion(); return; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f9852ac1851..849aa89f9a4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -565,12 +565,18 @@ importers: '@builder.io/qwik-dom': specifier: workspace:^ version: link:../qwik-dom + ignore: + specifier: 5.3.1 + version: 5.3.1 image-size: specifier: 1.1.1 version: 1.1.1 kleur: specifier: 4.1.5 version: 4.1.5 + ts-morph: + specifier: 23.0.0 + version: 23.0.0 packages/qwik-auth: dependencies: @@ -2410,79 +2416,67 @@ packages: resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} cpu: [arm64] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-arm@1.0.5': resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} cpu: [arm] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-s390x@1.0.4': resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==} cpu: [s390x] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-x64@1.0.4': resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} cpu: [x64] os: [linux] - libc: [glibc] '@img/sharp-libvips-linuxmusl-arm64@1.0.4': resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==} cpu: [arm64] os: [linux] - libc: [musl] '@img/sharp-libvips-linuxmusl-x64@1.0.4': resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==} cpu: [x64] os: [linux] - libc: [musl] '@img/sharp-linux-arm64@0.33.5': resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] - libc: [glibc] '@img/sharp-linux-arm@0.33.5': resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] - libc: [glibc] '@img/sharp-linux-s390x@0.33.5': resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [s390x] os: [linux] - libc: [glibc] '@img/sharp-linux-x64@0.33.5': resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] - libc: [glibc] '@img/sharp-linuxmusl-arm64@0.33.5': resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] - libc: [musl] '@img/sharp-linuxmusl-x64@0.33.5': resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] - libc: [musl] '@img/sharp-wasm32@0.33.5': resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==} @@ -3034,35 +3028,30 @@ packages: engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] - libc: [glibc] '@parcel/watcher-linux-arm64-glibc@2.4.1': resolution: {integrity: sha512-BJ7mH985OADVLpbrzCLgrJ3TOpiZggE9FMblfO65PlOCdG++xJpKUJ0Aol74ZUIYfb8WsRlUdgrZxKkz3zXWYA==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] - libc: [glibc] '@parcel/watcher-linux-arm64-musl@2.4.1': resolution: {integrity: sha512-p4Xb7JGq3MLgAfYhslU2SjoV9G0kI0Xry0kuxeG/41UfpjHGOhv7UoUDAz/jb1u2elbhazy4rRBL8PegPJFBhA==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] - libc: [musl] '@parcel/watcher-linux-x64-glibc@2.4.1': resolution: {integrity: sha512-s9O3fByZ/2pyYDPoLM6zt92yu6P4E39a03zvO0qCHOTjxmt3GHRMLuRZEWhWLASTMSrrnVNWdVI/+pUElJBBBg==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] - libc: [glibc] '@parcel/watcher-linux-x64-musl@2.4.1': resolution: {integrity: sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] - libc: [musl] '@parcel/watcher-wasm@2.4.0': resolution: {integrity: sha512-MNgQ4WCbBybqQ97KwR/hqJGYTg3+s8qHpgIyFWB2qJOBvoJWbXuJGmm4ZkPLq2bMaANqCZqrXwmKYagZTkMKZA==} @@ -3167,55 +3156,46 @@ packages: resolution: {integrity: sha512-2Rn36Ubxdv32NUcfm0wB1tgKqkQuft00PtM23VqLuCUR4N5jcNWDoV5iBC9jeGdgS38WK66ElncprqgMUOyomw==} cpu: [arm] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.19.0': resolution: {integrity: sha512-gJuzIVdq/X1ZA2bHeCGCISe0VWqCoNT8BvkQ+BfsixXwTOndhtLUpOg0A1Fcx/+eA6ei6rMBzlOz4JzmiDw7JQ==} cpu: [arm] os: [linux] - libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.19.0': resolution: {integrity: sha512-0EkX2HYPkSADo9cfeGFoQ7R0/wTKb7q6DdwI4Yn/ULFE1wuRRCHybxpl2goQrx4c/yzK3I8OlgtBu4xvted0ug==} cpu: [arm64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.19.0': resolution: {integrity: sha512-GlIQRj9px52ISomIOEUq/IojLZqzkvRpdP3cLgIE1wUWaiU5Takwlzpz002q0Nxxr1y2ZgxC2obWxjr13lvxNQ==} cpu: [arm64] os: [linux] - libc: [musl] '@rollup/rollup-linux-powerpc64le-gnu@4.19.0': resolution: {integrity: sha512-N6cFJzssruDLUOKfEKeovCKiHcdwVYOT1Hs6dovDQ61+Y9n3Ek4zXvtghPPelt6U0AH4aDGnDLb83uiJMkWYzQ==} cpu: [ppc64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-riscv64-gnu@4.19.0': resolution: {integrity: sha512-2DnD3mkS2uuam/alF+I7M84koGwvn3ZVD7uG+LEWpyzo/bq8+kKnus2EVCkcvh6PlNB8QPNFOz6fWd5N8o1CYg==} cpu: [riscv64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-s390x-gnu@4.19.0': resolution: {integrity: sha512-D6pkaF7OpE7lzlTOFCB2m3Ngzu2ykw40Nka9WmKGUOTS3xcIieHe82slQlNq69sVB04ch73thKYIWz/Ian8DUA==} cpu: [s390x] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.19.0': resolution: {integrity: sha512-HBndjQLP8OsdJNSxpNIN0einbDmRFg9+UQeZV1eiYupIRuZsDEoeGU43NQsS34Pp166DtwQOnpcbV/zQxM+rWA==} cpu: [x64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-musl@4.19.0': resolution: {integrity: sha512-HxfbvfCKJe/RMYJJn0a12eiOI9OOtAUF4G6ozrFUK95BNyoJaSiBjIOHjZskTUffUrB84IPKkFG9H9nEvJGW6A==} cpu: [x64] os: [linux] - libc: [musl] '@rollup/rollup-win32-arm64-msvc@4.19.0': resolution: {integrity: sha512-HxDMKIhmcguGTiP5TsLNolwBUK3nGGUEoV/BO9ldUBoMLBssvh4J0X8pf11i1fTV7WShWItB1bKAKjX4RQeYmg==} @@ -3342,6 +3322,9 @@ packages: resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} + '@ts-morph/common@0.24.0': + resolution: {integrity: sha512-c1xMmNHWpNselmpIqursHeOHHBTIsJLbB+NuovbTTRCNiTLEr/U9dbJ8qy0jd/O2x5pc3seWuOUN5R2IoOTp8A==} + '@tsconfig/node10@1.0.9': resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} @@ -4415,6 +4398,9 @@ packages: resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} engines: {node: '>=0.10.0'} + code-block-writer@13.0.3: + resolution: {integrity: sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==} + code-point-at@1.1.0: resolution: {integrity: sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==} engines: {node: '>=0.10.0'} @@ -6209,8 +6195,8 @@ packages: resolution: {integrity: sha512-t7sv42WkwFkyKbivUCglsQW5YWMskWtbEf4MNKX5u/CCWHKSPzN4FtBQGsQZgCLbxOzpVlcbWVK5KB3auIOjSw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - ignore@5.3.2: - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + ignore@5.3.1: + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} image-meta@0.2.0: @@ -7353,6 +7339,11 @@ packages: engines: {node: '>=10'} hasBin: true + mkdirp@3.0.1: + resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==} + engines: {node: '>=10'} + hasBin: true + mlly@1.6.1: resolution: {integrity: sha512-vLgaHvaeunuOXHSmEbZ9izxPx3USsk8KCQ8iC+aTlp5sKRSoZvwhHh5L9VbKSaVC6sJDqbyohIS76E2VmHIPAA==} @@ -9284,6 +9275,9 @@ packages: ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + ts-morph@23.0.0: + resolution: {integrity: sha512-FcvFx7a9E8TUe6T3ShihXJLiJOiqyafzFKUO4aqIHDUCIvADdGNShcbc2W5PMr3LerXRv7mafvFZ9lRENxJmug==} + ts-node@10.9.2: resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} hasBin: true @@ -11166,7 +11160,7 @@ snapshots: debug: 4.3.7(supports-color@9.4.0) espree: 9.6.1 globals: 13.24.0 - ignore: 5.3.2 + ignore: 5.3.1 import-fresh: 3.3.0 js-yaml: 4.1.0 minimatch: 3.1.2 @@ -11180,7 +11174,7 @@ snapshots: debug: 4.3.7(supports-color@9.4.0) espree: 10.2.0 globals: 14.0.0 - ignore: 5.3.2 + ignore: 5.3.1 import-fresh: 3.3.0 js-yaml: 4.1.0 minimatch: 3.1.2 @@ -12001,7 +11995,7 @@ snapshots: junk: 4.0.1 locate-path: 7.2.0 merge-options: 3.0.4 - minimatch: 9.0.4 + minimatch: 9.0.5 normalize-path: 3.0.0 p-map: 5.5.0 path-exists: 5.0.0 @@ -12436,6 +12430,13 @@ snapshots: '@trysound/sax@0.2.0': {} + '@ts-morph/common@0.24.0': + dependencies: + fast-glob: 3.3.2 + minimatch: 9.0.5 + mkdirp: 3.0.1 + path-browserify: 1.0.1 + '@tsconfig/node10@1.0.9': {} '@tsconfig/node12@1.0.11': {} @@ -12667,7 +12668,7 @@ snapshots: '@typescript-eslint/visitor-keys': 7.16.1 eslint: 8.57.0 graphemer: 1.4.0 - ignore: 5.3.2 + ignore: 5.3.1 natural-compare: 1.4.0 ts-api-utils: 1.3.0(typescript@5.4.5) optionalDependencies: @@ -13726,6 +13727,8 @@ snapshots: cluster-key-slot@1.1.2: {} + code-block-writer@13.0.3: {} + code-point-at@1.1.0: {} collapse-white-space@2.1.0: {} @@ -14817,7 +14820,7 @@ snapshots: glob-parent: 6.0.2 globals: 13.24.0 graphemer: 1.4.0 - ignore: 5.3.2 + ignore: 5.3.1 imurmurhash: 0.1.4 is-glob: 4.0.3 is-path-inside: 3.0.3 @@ -15492,7 +15495,7 @@ snapshots: dependencies: foreground-child: 3.1.1 jackspeak: 2.3.6 - minimatch: 9.0.4 + minimatch: 9.0.5 minipass: 7.0.4 path-scurry: 1.10.1 @@ -15542,7 +15545,7 @@ snapshots: array-union: 2.1.0 dir-glob: 3.0.1 fast-glob: 3.3.2 - ignore: 5.3.2 + ignore: 5.3.1 merge2: 1.4.1 slash: 3.0.0 @@ -15550,7 +15553,7 @@ snapshots: dependencies: dir-glob: 3.0.1 fast-glob: 3.3.2 - ignore: 5.3.2 + ignore: 5.3.1 merge2: 1.4.1 slash: 4.0.0 @@ -15558,7 +15561,7 @@ snapshots: dependencies: '@sindresorhus/merge-streams': 2.3.0 fast-glob: 3.3.2 - ignore: 5.3.2 + ignore: 5.3.1 path-type: 5.0.0 slash: 5.1.0 unicorn-magic: 0.1.0 @@ -15883,9 +15886,9 @@ snapshots: ignore-walk@6.0.4: dependencies: - minimatch: 9.0.4 + minimatch: 9.0.5 - ignore@5.3.2: {} + ignore@5.3.1: {} image-meta@0.2.0: {} @@ -17316,6 +17319,8 @@ snapshots: mkdirp@1.0.4: {} + mkdirp@3.0.1: {} + mlly@1.6.1: dependencies: acorn: 8.12.1 @@ -18255,7 +18260,7 @@ snapshots: dependencies: execa: 5.1.1 find-up: 5.0.0 - ignore: 5.3.2 + ignore: 5.3.1 mri: 1.2.0 picocolors: 1.0.1 picomatch: 3.0.1 @@ -19560,6 +19565,11 @@ snapshots: ts-interface-checker@0.1.13: {} + ts-morph@23.0.0: + dependencies: + '@ts-morph/common': 0.24.0 + code-block-writer: 13.0.3 + ts-node@10.9.2(@types/node@20.14.11)(typescript@5.4.5): dependencies: '@cspotcode/source-map-support': 0.8.1