diff --git a/.all-contributorsrc b/.all-contributorsrc index d9e2ffb63..b071c9af2 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1205,6 +1205,15 @@ "contributions": [ "infra" ] + }, + { + "login": "mattlewis92", + "name": "Matt Lewis", + "avatar_url": "https://avatars.githubusercontent.com/u/6425649?v=4", + "profile": "https://mattlewis.me/", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/.gitignore b/.gitignore index 96fd2f3e1..415d0841d 100644 --- a/.gitignore +++ b/.gitignore @@ -66,4 +66,5 @@ tmpanalogapp* .nx/cache .nx/workspace-data -vite.config.*.timestamp* \ No newline at end of file +vite.config.*.timestamp* +.vite-inspect \ No newline at end of file diff --git a/README.md b/README.md index a5c715e03..af2c3379a 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ -[![All Contributors](https://img.shields.io/badge/all_contributors-127-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-128-orange.svg?style=flat-square)](#contributors-) @@ -276,6 +276,7 @@ Thanks goes to these wonderful people for contributing to Analog ([emoji key](ht Alex Rose-Pizant
Alex Rose-Pizant

πŸš‡ + Matt Lewis
Matt Lewis

πŸ’» diff --git a/apps/analog-app/vite.config.ts b/apps/analog-app/vite.config.ts index 920c32039..23208b512 100644 --- a/apps/analog-app/vite.config.ts +++ b/apps/analog-app/vite.config.ts @@ -4,6 +4,7 @@ import analog from '@analogjs/platform'; import { visualizer } from 'rollup-plugin-visualizer'; import { defineConfig, Plugin, splitVendorChunkPlugin } from 'vite'; import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; +import inspect from 'vite-plugin-inspect'; // Only run in Netlify CI let base = process.env['URL'] || 'http://localhost:3000'; @@ -14,7 +15,7 @@ if (process.env['NETLIFY'] === 'true') { } // https://vitejs.dev/config/ -export default defineConfig(({ mode }) => { +export default defineConfig(({ mode, isSsrBuild }) => { return { root: __dirname, publicDir: 'src/public', @@ -47,7 +48,12 @@ export default defineConfig(({ mode }) => { }), nxViteTsPaths(), visualizer() as Plugin, - splitVendorChunkPlugin(), + // splitVendorChunkPlugin(), + !isSsrBuild && + inspect({ + build: true, + outputDir: '../../.vite-inspect/analog-app', + }), ], test: { reporters: ['default'], diff --git a/apps/docs-app/docs/contributors.mdx b/apps/docs-app/docs/contributors.mdx index 15bc59f00..ddfa06628 100644 --- a/apps/docs-app/docs/contributors.mdx +++ b/apps/docs-app/docs/contributors.mdx @@ -223,6 +223,7 @@ Andres is a software engineer for HeroDevs, Angular and Firebase GDE. Alex Rose-Pizant
Alex Rose-Pizant

πŸš‡ + Matt Lewis
Matt Lewis

πŸ’» diff --git a/apps/docs-app/docs/features/deployment/providers.md b/apps/docs-app/docs/features/deployment/providers.md index f199c0b97..c499eedf6 100644 --- a/apps/docs-app/docs/features/deployment/providers.md +++ b/apps/docs-app/docs/features/deployment/providers.md @@ -5,6 +5,137 @@ import TabItem from '@theme/TabItem'; Analog supports deployment to many providers with little or no additional configuration using [Nitro](https://nitro.unjs.io) as its underlying server engine. You can find more providers in the [Nitro deployment docs](https://nitro.unjs.io/deploy). +## Zerops + +:::info +[Zerops](https://zerops.io) is the **official** deployment partner for AnalogJS. +::: + +Analog supports deploying both static and server-side rendered apps to [Zerops](https://zerops.io) with a simple configuration file. + +> One Zerops project can contain multiple Analog projects. See example repositories for [static](https://github.com/zeropsio/recipe-analog-static) and [server-side rendered](https://github.com/zeropsio/recipe-analog-nodejs) Analog apps for a quick start. + +### Static (SSG) Analog app + +If your project is not SSG Ready, set up your project for [Static Site Generation](/docs/features/server/static-site-generation). + +#### 1. Create a project in Zerops + +Projects and services can be added either through a [Project add](https://app.zerops.io/dashboard/project-add) wizard or imported using a YAML structure: + +```yml +project: + name: recipe-analog +services: + - hostname: app + type: static +``` + +This creates a project called `recipe-analog` with a Zerops Static service called `app`. + +#### 2. Add zerops.yml configuration + +To tell Zerops how to build and run your site, add a `zerops.yml` to your repository: + +```yml +zerops: + - setup: app + build: + base: nodejs@20 + buildCommands: + - pnpm i + - pnpm build + deployFiles: + - public + - dist/analog/public/~ + run: + base: static +``` + +#### 3. [Trigger the build & deploy pipeline](#build--deploy-your-code) + +### Server-side rendered (SSR) Analog app + +If your project is not SSR Ready, set up your project for [Server Side Rendering](/docs/features/server/server-side-rendering). + +#### 1. Create a project in Zerops + +Projects and services can be added either through a [Project add](https://app.zerops.io/dashboard/project-add) wizard or imported using a YAML structure: + +```yml +project: + name: recipe-analog +services: + - hostname: app + type: nodejs@20 +``` + +This creates a project called `recipe-analog` with a Zerops Node.js service called `app`. + +#### 2. Add zerops.yml configuration + +To tell Zerops how to build and run your site, add a `zerops.yml` to your repository: + +```yml +zerops: + - setup: app + build: + base: nodejs@20 + buildCommands: + - pnpm i + - pnpm build + deployFiles: + - public + - node_modules + - dist + run: + base: nodejs@20 + ports: + - port: 3000 + httpSupport: true + start: node dist/analog/server/index.mjs +``` + +#### 3. [Trigger the build & deploy pipeline](#build-deploy-your-code) + +--- + +### Build & deploy your code + +#### Trigger the pipeline by connecting the service with your GitHub / GitLab repository + +Your code can be deployed automatically on each commit or a new tag by connecting the service with your GitHub / GitLab repository. This connection can be set up in the service detail. + +#### Trigger the pipeline using Zerops CLI (zcli) + +You can also trigger the pipeline manually from your terminal or your existing CI/CD by using Zerops CLI. + +1. Install the Zerops CLI. + +```bash +# To download the zcli binary directly, +# use https://github.com/zeropsio/zcli/releases +npm i -g @zerops/zcli +``` + +2. Open [Settings > Access Token Management](https://app.zerops.io/settings/token-management) in the Zerops app and generate a new access token. + +3. Log in using your access token with the following command: + +```bash +zcli login +``` + +4. Navigate to the root of your app (where `zerops.yml` is located) and run the following command to trigger the deploy: + +```bash +zcli push +``` + +#### Trigger the pipeline using GitHub / Gitlab + +You can also check out [Github Integration](https://docs.zerops.io/references/github-integration) / [Gitlab Integration](https://docs.zerops.io/references/gitlab-integration) in [Zerops Docs](https://docs.zerops.io/) for git integration. + ## Netlify Analog supports deploying on [Netlify](https://netlify.com/) with minimal configuration. @@ -161,9 +292,17 @@ BUILD_PRESET=cloudflare-pages npm run build npx wrangler pages dev ./dist/analog/public ``` -## Firebase +## Firebase App Hosting + +Analog supports [Firebase App Hosting](https://firebase.google.com/docs/app-hosting) with no additional configuration out of the box. + +**Note**: You need to be on the **Blaze plan** to deploy Analog applications with Firebase App Hosting. -Analog supports [Firebase Hosting](https://firebase.google.com/docs/hosting) with Cloud Functions out of the box. +Follow the [Getting Started instructions](https://firebase.google.com/docs/app-hosting/get-started#step-1:) to connect your GitHub repository to Firebase App Hosting. + +## Firebase Hosting + +Analog supports [Firebase Hosting](https://firebase.google.com/docs/hosting) with Cloud Functions and [Firebase App Hosting](https://firebase.google.com/docs/app-hosting) out of the box. See a [Sample Repo](https://github.com/brandonroberts/analog-angular-firebase-example) with Firebase configured @@ -462,132 +601,3 @@ jobs: echo "DRY_RUN_OPTION=$DRY_RUN_OPTION" npx angular-cli-ghpages --no-silent --dir="${{env.TARGET_DIR}}" $CNAME_OPTION $DRY_RUN_OPTION ``` - -## Zerops - -Analog supports deploying both static and server-side rendered apps to [Zerops](https://zerops.io) with a simple configuration file. - -:::info -One Zerops project can contain multiple Analog projects. See example repositories for [static](https://github.com/zeropsio/recipe-analog-static) and [server-side rendered](https://github.com/zeropsio/recipe-analog-nodejs) Analog apps for a quick start. -::: - -### Static (SSG) Analog app - -If your project is not SSG Ready, set up your project for [Static Site Generation](/docs/features/server/static-site-generation). - -#### 1. Create a project in Zerops - -Projects and services can be added either through a [Project add](https://app.zerops.io/dashboard/project-add) wizard or imported using a YAML structure: - -```yml -project: - name: recipe-analog -services: - - hostname: app - type: static -``` - -This creates a project called `recipe-analog` with a Zerops Static service called `app`. - -#### 2. Add zerops.yml configuration - -To tell Zerops how to build and run your site, add a `zerops.yml` to your repository: - -```yml -zerops: - - setup: app - build: - base: nodejs@20 - buildCommands: - - pnpm i - - pnpm build - deployFiles: - - public - - dist/analog/public/~ - run: - base: static -``` - -#### 3. [Trigger the build & deploy pipeline](#build--deploy-your-code) - -### Server-side rendered (SSR) Analog app - -If your project is not SSR Ready, set up your project for [Server Side Rendering](/docs/features/server/server-side-rendering). - -#### 1. Create a project in Zerops - -Projects and services can be added either through a [Project add](https://app.zerops.io/dashboard/project-add) wizard or imported using a YAML structure: - -```yml -project: - name: recipe-analog -services: - - hostname: app - type: nodejs@20 -``` - -This creates a project called `recipe-analog` with a Zerops Node.js service called `app`. - -#### 2. Add zerops.yml configuration - -To tell Zerops how to build and run your site, add a `zerops.yml` to your repository: - -```yml -zerops: - - setup: app - build: - base: nodejs@20 - buildCommands: - - pnpm i - - pnpm build - deployFiles: - - public - - node_modules - - dist - run: - base: nodejs@20 - ports: - - port: 3000 - httpSupport: true - start: node dist/analog/server/index.mjs -``` - -#### 3. [Trigger the build & deploy pipeline](#build-deploy-your-code) - ---- - -### Build & deploy your code - -#### Trigger the pipeline by connecting the service with your GitHub / GitLab repository - -Your code can be deployed automatically on each commit or a new tag by connecting the service with your GitHub / GitLab repository. This connection can be set up in the service detail. - -#### Trigger the pipeline using Zerops CLI (zcli) - -You can also trigger the pipeline manually from your terminal or your existing CI/CD by using Zerops CLI. - -1. Install the Zerops CLI. - -```bash -# To download the zcli binary directly, -# use https://github.com/zeropsio/zcli/releases -npm i -g @zerops/zcli -``` - -2. Open [Settings > Access Token Management](https://app.zerops.io/settings/token-management) in the Zerops app and generate a new access token. - -3. Log in using your access token with the following command: - -```bash -zcli login -``` - -4. Navigate to the root of your app (where `zerops.yml` is located) and run the following command to trigger the deploy: - -```bash -zcli push -``` - -#### Trigger the pipeline using Github / Gitlab - -You can also check out [Github Integration](https://docs.zerops.io/references/github-integration) / [Gitlab Integration](https://docs.zerops.io/references/gitlab-integration) in [Zerops Docs](https://docs.zerops.io/) for git integration. diff --git a/apps/docs-app/i18n/de/docusaurus-plugin-content-docs/current/contributors.mdx b/apps/docs-app/i18n/de/docusaurus-plugin-content-docs/current/contributors.mdx index a5ba41148..5f8fe3303 100644 --- a/apps/docs-app/i18n/de/docusaurus-plugin-content-docs/current/contributors.mdx +++ b/apps/docs-app/i18n/de/docusaurus-plugin-content-docs/current/contributors.mdx @@ -223,6 +223,7 @@ Andres ist Softwareentwickler fΓΌr HeroDevs, Angular und Firebase GDE. Alex Rose-Pizant
Alex Rose-Pizant

πŸš‡ + Matt Lewis
Matt Lewis

πŸ’» diff --git a/apps/docs-app/i18n/es/docusaurus-plugin-content-docs/current/contributors.mdx b/apps/docs-app/i18n/es/docusaurus-plugin-content-docs/current/contributors.mdx index 8c6c194de..ef501305d 100644 --- a/apps/docs-app/i18n/es/docusaurus-plugin-content-docs/current/contributors.mdx +++ b/apps/docs-app/i18n/es/docusaurus-plugin-content-docs/current/contributors.mdx @@ -223,6 +223,7 @@ Andres es un ingeniero en software para HeroDevs, GDE en Angular y Firebase. Alex Rose-Pizant
Alex Rose-Pizant

πŸš‡ + Matt Lewis
Matt Lewis

πŸ’» diff --git a/libs/card/vite.config.ts b/libs/card/vite.config.ts index d68a9fa3a..5ec2c5193 100644 --- a/libs/card/vite.config.ts +++ b/libs/card/vite.config.ts @@ -15,6 +15,8 @@ export default defineConfig(({ mode }) => { setupFiles: ['src/test-setup.ts'], include: ['**/*.spec.ts'], cacheDir: '../../node_modules/.vitest', + pool: 'vmForks', + fileParallelism: false, }, define: { 'import.meta.vitest': mode !== 'production', diff --git a/package.json b/package.json index 0371321fb..11620113f 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "e2e": "nx run-many --target e2e --projects create-analog-e2e,analog-app-e2e-cypress --parallel=1 --exclude analog-app-e2e-playwright", "test": "nx run-many --target test", "build:vite-ci": "npm run build", - "test:vite-ci": "nx run-many --target test --all", + "test:vite-ci": "nx run-many --target test --all --skip-nx-cache", "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0", "contributors:add": "all-contributors add", "contributors:generate": "all-contributors generate", @@ -175,6 +175,7 @@ "vfile": "^6.0.3", "vite": "^6.0.0", "vite-plugin-eslint": "^1.8.1", + "vite-plugin-inspect": "~0.8", "vite-tsconfig-paths": "4.2.0", "vitefu": "^0.2.5", "vitest": "^2.0.0", diff --git a/packages/platform/src/lib/deps-plugin.ts b/packages/platform/src/lib/deps-plugin.ts index 1d913f110..a91405123 100644 --- a/packages/platform/src/lib/deps-plugin.ts +++ b/packages/platform/src/lib/deps-plugin.ts @@ -12,6 +12,7 @@ export function depsPlugin(options?: Options): Plugin[] { name: 'analogjs-deps-plugin', config() { return { + esbuild: { exclude: ['**/*.ts', '**/*.js'] }, ssr: { noExternal: [ '@analogjs/**', diff --git a/packages/vite-plugin-angular/src/lib/angular-vite-plugin.ts b/packages/vite-plugin-angular/src/lib/angular-vite-plugin.ts index 9212b6e6c..635908a98 100644 --- a/packages/vite-plugin-angular/src/lib/angular-vite-plugin.ts +++ b/packages/vite-plugin-angular/src/lib/angular-vite-plugin.ts @@ -14,6 +14,7 @@ import { ResolvedConfig, Connect, } from 'vite'; +import * as ngCompiler from '@angular/compiler'; import { createCompilerPlugin } from './compiler-plugin.js'; import { @@ -78,6 +79,7 @@ export interface PluginOptions { include?: string[]; additionalContentDirs?: string[]; liveReload?: boolean; + disableTypeChecking?: boolean; } interface EmitFileResult { @@ -135,6 +137,7 @@ export function angular(options?: PluginOptions): Plugin[] { include: options?.include ?? [], additionalContentDirs: options?.additionalContentDirs ?? [], liveReload: options?.liveReload ?? false, + disableTypeChecking: options?.disableTypeChecking ?? false, }; // The file emitter created during `onStart` that will be used during the build in `onLoad` callbacks for TS files @@ -149,6 +152,7 @@ export function angular(options?: PluginOptions): Plugin[] { let builderProgram: ts.EmitAndSemanticDiagnosticsBuilderProgram; let watchMode = false; let testWatchMode = false; + let inlineComponentStyles: Map | undefined; const sourceFileCache = new SourceFileCache(); const isTest = process.env['NODE_ENV'] === 'test' || !!process.env['VITEST']; const isStackBlitz = !!process.versions['webcontainer']; @@ -278,8 +282,20 @@ export function angular(options?: PluginOptions): Plugin[] { } const [fileId] = decodeURIComponent(componentId).split('@'); - const result = await fileEmitter?.(resolve(process.cwd(), fileId)); + const resolvedId = resolve(process.cwd(), fileId); + const invalidated = + !!server.moduleGraph.getModuleById(resolvedId) + ?.lastInvalidationTimestamp; + + // don't send an HMR update until the file has been invalidated + if (!invalidated) { + res.setHeader('Content-Type', 'text/javascript'); + res.setHeader('Cache-Control', 'no-cache'); + res.end(''); + return; + } + const result = await fileEmitter?.(resolvedId); res.setHeader('Content-Type', 'text/javascript'); res.setHeader('Cache-Control', 'no-cache'); res.end(`${result?.hmrUpdateCode || ''}`); @@ -308,9 +324,15 @@ export function angular(options?: PluginOptions): Plugin[] { } if (TS_EXT_REGEX.test(ctx.file)) { - const fileId = - ctx.file.split('?')[0] + - (pluginOptions.supportAnalogFormat ? '.ts' : ''); + let [fileId] = ctx.file.split('?'); + + if ( + pluginOptions.supportAnalogFormat && + ['ag', 'analog', 'agx'].some((ext) => fileId.endsWith(ext)) + ) { + fileId += '.ts'; + } + const stale = sourceFileCache.get(fileId); sourceFileCache.invalidate([fileId]); await buildAndAnalyze(); @@ -328,10 +350,14 @@ export function angular(options?: PluginOptions): Plugin[] { )}@${classNames.get(fileId)}`; sendHMRComponentUpdate(ctx.server, relativeFileId); - ctx.server.config.logger.info( - `[HMR Update]: ${relativeFileId.split('@')[0]}` - ); - return []; + + return ctx.modules.map((mod) => { + if (mod.id === ctx.file) { + return markModuleSelfAccepting(mod); + } + + return mod; + }); } } @@ -344,6 +370,45 @@ export function angular(options?: PluginOptions): Plugin[] { (mod) => ctx.file === mod.file && mod.id?.includes('?direct') ); if (isDirect) { + if (pluginOptions.liveReload && isDirect?.id && isDirect.file) { + const isComponentStyle = + isDirect.type === 'css' && isComponentStyleSheet(isDirect.id); + if (isComponentStyle) { + const { encapsulation } = getComponentStyleSheetMeta( + isDirect.id + ); + + // Track if the component uses ShadowDOM encapsulation + // Shadow DOM components currently require a full reload. + // Vite's CSS hot replacement does not support shadow root searching. + if (encapsulation !== 'shadow') { + ctx.server.ws.send({ + type: 'update', + updates: [ + { + type: 'css-update', + timestamp: Date.now(), + path: isDirect.id, + acceptedPath: isDirect.file, + }, + ], + }); + + return ctx.modules + .filter((mod) => { + // Component stylesheets will have 2 modules (*.component.scss and *.component.scss?direct&ngcomp=xyz&e=x) + // We remove the module with the query params to prevent vite double logging the stylesheet name "hmr update *.component.scss, *.component.scss?direct&ngcomp=xyz&e=x" + return mod.file !== ctx.file || mod.id !== isDirect.id; + }) + .map((mod) => { + if (mod.file === ctx.file) { + return markModuleSelfAccepting(mod); + } + return mod; + }) as ModuleNode[]; + } + } + } return ctx.modules; } @@ -376,10 +441,7 @@ export function angular(options?: PluginOptions): Plugin[] { return ctx.modules.map((mod) => { if (mod.id === ctx.file) { - return { - ...mod, - isSelfAccepting: true, - } as ModuleNode; + return markModuleSelfAccepting(mod); } return mod; @@ -402,6 +464,17 @@ export function angular(options?: PluginOptions): Plugin[] { return undefined; }, async load(id, options) { + if (isComponentStyleSheet(id)) { + const filename = new URL(id, 'http://localhost').pathname.replace( + /^\//, + '' + ); + const componentStyles = inlineComponentStyles?.get(filename); + if (componentStyles) { + return componentStyles; + } + } + if ( pluginOptions.liveReload && options?.ssr && @@ -461,6 +534,20 @@ export function angular(options?: PluginOptions): Plugin[] { return; } + /** + * Encapsulate component stylesheets that use emulated encapsulation + */ + if (pluginOptions.liveReload && isComponentStyleSheet(id)) { + const { encapsulation, componentId } = getComponentStyleSheetMeta(id); + if (encapsulation === 'emulated' && componentId) { + const encapsulated = ngCompiler.encapsulateStyle(code, componentId); + return { + code: encapsulated, + map: null, + }; + } + } + if (TS_EXT_REGEX.test(id)) { if (id.includes('.ts?')) { // Strip the query string off the ID @@ -475,9 +562,11 @@ export function angular(options?: PluginOptions): Plugin[] { if (isTest) { const tsMod = viteServer?.moduleGraph.getModuleById(id); if (tsMod) { - sourceFileCache.invalidate([id]); + const invalidated = tsMod.lastInvalidationTimestamp; + + if (testWatchMode && invalidated) { + sourceFileCache.invalidate([id]); - if (testWatchMode) { await buildAndAnalyze(); } } @@ -674,8 +763,12 @@ export function angular(options?: PluginOptions): Plugin[] { tsCompilerOptions.compilationMode = 'experimental-local'; } - if (pluginOptions.liveReload) { + if (pluginOptions.liveReload && watchMode) { tsCompilerOptions['_enableHmr'] = true; + tsCompilerOptions['externalRuntimeStyles'] = true; + // Workaround for https://github.com/angular/angular/issues/59310 + // Force extra instructions to be generated for HMR w/defer + tsCompilerOptions['supportTestBed'] = true; } rootNames = rn.concat(analogFiles, includeFiles); @@ -686,11 +779,15 @@ export function angular(options?: PluginOptions): Plugin[] { preprocessCSS(code, filename, config as any); if (!jit) { + inlineComponentStyles = tsCompilerOptions['externalRuntimeStyles'] + ? new Map() + : undefined; augmentHostWithResources(host, styleTransform, { inlineStylesExtension: pluginOptions.inlineStylesExtension, supportAnalogFormat: pluginOptions.supportAnalogFormat, isProd, markdownTemplateTransforms: pluginOptions.markdownTemplateTransforms, + inlineComponentStyles, }); } } @@ -772,7 +869,8 @@ export function angular(options?: PluginOptions): Plugin[] { ), () => [], angularCompiler!, - pluginOptions.liveReload + pluginOptions.liveReload, + pluginOptions.disableTypeChecking ); } } @@ -791,7 +889,8 @@ export function createFileEmitter( transformers: ts.CustomTransformers = {}, onAfterEmit?: (sourceFile: ts.SourceFile) => void, angularCompiler?: NgtscProgram['compiler'], - liveReload?: boolean + liveReload?: boolean, + disableTypeChecking?: boolean ): FileEmitter { return async (file: string, stale?: ts.SourceFile) => { const sourceFile = program.getSourceFile(file); @@ -808,9 +907,12 @@ export function createFileEmitter( return { dependencies: [], hmrEligible }; } - const diagnostics = angularCompiler - ? angularCompiler.getDiagnosticsForFile(sourceFile, 1) - : []; + const diagnostics = getDiagnosticsForSourceFile( + sourceFile, + !!disableTypeChecking, + program, + angularCompiler + ); const errors = diagnostics .filter((d) => d.category === ts.DiagnosticCategory?.Error) @@ -849,3 +951,62 @@ export function createFileEmitter( return { content, dependencies: [], errors, warnings, hmrUpdateCode }; }; } + +function getDiagnosticsForSourceFile( + sourceFile: ts.SourceFile, + disableTypeChecking: boolean, + program: ts.BuilderProgram, + angularCompiler?: NgtscProgram['compiler'] +) { + const syntacticDiagnostics = program.getSyntacticDiagnostics(sourceFile); + + if (disableTypeChecking) { + // Syntax errors are cheap to compute and the app will not run if there are any + // So always show these types of errors regardless if type checking is disabled + return syntacticDiagnostics; + } + + const semanticDiagnostics = program.getSemanticDiagnostics(sourceFile); + const angularDiagnostics = angularCompiler + ? angularCompiler.getDiagnosticsForFile(sourceFile, 1) + : []; + return [ + ...syntacticDiagnostics, + ...semanticDiagnostics, + ...angularDiagnostics, + ]; +} + +function markModuleSelfAccepting(mod: ModuleNode): ModuleNode { + // support Vite 6 + if ('_clientModule' in mod) { + (mod as any)['_clientModule'].isSelfAccepting = true; + } + + return { + ...mod, + isSelfAccepting: true, + } as ModuleNode; +} + +function isComponentStyleSheet(id: string): boolean { + return id.includes('ngcomp='); +} + +function getComponentStyleSheetMeta(id: string): { + componentId: string; + encapsulation: 'emulated' | 'shadow' | 'none'; +} { + const params = new URL(id, 'http://localhost').searchParams; + const encapsulationMapping = { + '0': 'emulated', + '2': 'none', + '3': 'shadow', + }; + return { + componentId: params.get('ngcomp')!, + encapsulation: encapsulationMapping[ + params.get('e') as keyof typeof encapsulationMapping + ] as 'emulated' | 'shadow' | 'none', + }; +} diff --git a/packages/vite-plugin-angular/src/lib/angular-vitest-plugin.ts b/packages/vite-plugin-angular/src/lib/angular-vitest-plugin.ts index efa484ff0..8dab1124d 100644 --- a/packages/vite-plugin-angular/src/lib/angular-vitest-plugin.ts +++ b/packages/vite-plugin-angular/src/lib/angular-vitest-plugin.ts @@ -18,15 +18,10 @@ export function angularVitestPlugin(): Plugin { exclude: ['@angular/cdk/testing'], }, ssr: { - noExternal: [/cdk\/fesm2022/], + noExternal: [/cdk\/fesm2022/, /fesm2022(.*?)testing/, /fesm2015/], }, test: { pool: (userConfig as any).test?.pool ?? 'vmThreads', - server: { - deps: { - inline: [/fesm2022(.*?)testing/], - }, - }, }, }; }, diff --git a/packages/vite-plugin-angular/src/lib/host.ts b/packages/vite-plugin-angular/src/lib/host.ts index 3b29fc241..8b0ac807b 100644 --- a/packages/vite-plugin-angular/src/lib/host.ts +++ b/packages/vite-plugin-angular/src/lib/host.ts @@ -23,7 +23,7 @@ export function augmentHostWithResources( options?: { ssr?: boolean } ) => ReturnType | null, options: { - inlineStylesExtension?: string; + inlineStylesExtension: string; supportAnalogFormat?: | boolean | { @@ -32,13 +32,15 @@ export function augmentHostWithResources( isProd?: boolean; markdownTemplateTransforms?: MarkdownTemplateTransform[]; - } = {} + inlineComponentStyles?: Map; + } ) { const ts = require('typescript'); const resourceHost = host as CompilerHost; const baseGetSourceFile = ( resourceHost as ts.CompilerHost ).getSourceFile.bind(resourceHost); + const externalStylesheets = new Map(); if (options.supportAnalogFormat) { (resourceHost as ts.CompilerHost).getSourceFile = ( @@ -146,36 +148,43 @@ export function augmentHostWithResources( return null; } - if (options.inlineStylesExtension) { - // Resource file only exists for external stylesheets - const filename = - context.resourceFile ?? - `${context.containingFile.replace( - /(\.analog|\.ag)?\.ts$/, - (...args) => { - // NOTE: if the original file name contains `.analog`, we turn that into `-analog.css` - if ( - args.includes('.analog') || - args.includes('.ag') || - args.includes('.agx') - ) { - return `-analog.${options?.inlineStylesExtension}`; - } - return `.${options?.inlineStylesExtension}`; - } - )}`; - - let stylesheetResult; - - try { - stylesheetResult = await transform(data, `${filename}?direct`); - } catch (e) { - console.error(`${e}`); - } + if (options.inlineComponentStyles) { + const id = createHash('sha256') + .update(context.containingFile) + .update(context.className) + .update(String(context.order)) + .update(data) + .digest('hex'); + const filename = id + '.' + options.inlineStylesExtension; + options.inlineComponentStyles.set(filename, data); + return { content: filename }; + } - return { content: stylesheetResult?.code || '' }; + // Resource file only exists for external stylesheets + const filename = + context.resourceFile ?? + `${context.containingFile.replace(/(\.analog|\.ag)?\.ts$/, (...args) => { + // NOTE: if the original file name contains `.analog`, we turn that into `-analog.css` + if ( + args.includes('.analog') || + args.includes('.ag') || + args.includes('.agx') + ) { + return `-analog.${options?.inlineStylesExtension}`; + } + return `.${options?.inlineStylesExtension}`; + })}`; + + let stylesheetResult; + + try { + stylesheetResult = await transform(data, `${filename}?direct`); + } catch (e) { + console.error(`${e}`); } + return { content: stylesheetResult?.code || '' }; + return null; }; } diff --git a/packages/vite-plugin-nitro/src/lib/vite-plugin-nitro.ts b/packages/vite-plugin-nitro/src/lib/vite-plugin-nitro.ts index ffc646b95..471ef7d95 100644 --- a/packages/vite-plugin-nitro/src/lib/vite-plugin-nitro.ts +++ b/packages/vite-plugin-nitro/src/lib/vite-plugin-nitro.ts @@ -4,7 +4,7 @@ import type { Plugin, UserConfig, ViteDevServer } from 'vite'; import { mergeConfig, normalizePath } from 'vite'; import { dirname, join, relative, resolve } from 'node:path'; import { platform } from 'node:os'; -import { fileURLToPath } from 'node:url'; +import { fileURLToPath, pathToFileURL } from 'node:url'; import { readFileSync, writeFileSync } from 'node:fs'; import { buildServer } from './build-server.js'; @@ -174,6 +174,10 @@ export function nitro(options?: Options, nitroOptions?: NitroConfig): Plugin[] { nitroConfig = withCloudflareOutput(nitroConfig); } + if (isFirebaseAppHosting()) { + nitroConfig = withAppHostingOutput(nitroConfig); + } + if (!ssrBuild && !isTest) { // store the client output path for the SSR build config clientOutputPath = resolve( @@ -434,3 +438,40 @@ const withCloudflareOutput = (nitroConfig: NitroConfig | undefined) => ({ serverDir: '{{ output.publicDir }}/_worker.js', }, }); + +const isFirebaseAppHosting = () => !!process.env['NG_BUILD_LOGS_JSON']; +const withAppHostingOutput = (nitroConfig: NitroConfig) => { + let hasOutput = false; + + return { + ...nitroConfig, + serveStatic: true, + rollupConfig: { + ...nitroConfig.rollupConfig, + output: { + ...nitroConfig.rollupConfig?.output, + entryFileNames: 'server.mjs', + }, + }, + hooks: { + ...nitroConfig.hooks, + compiled: () => { + if (!hasOutput) { + const buildOutput = { + errors: [], + warnings: [], + outputPaths: { + root: pathToFileURL(`${nitroConfig.output?.dir}`), + browser: pathToFileURL(`${nitroConfig.output?.publicDir}`), + server: pathToFileURL(`${nitroConfig.output?.dir}/server`), + }, + }; + + // Log the build output for Firebase App Hosting to pick up + console.log(JSON.stringify(buildOutput, null, 2)); + hasOutput = true; + } + }, + }, + }; +}; diff --git a/packages/vitest-angular/src/lib/builders/test/schema.d.ts b/packages/vitest-angular/src/lib/builders/test/schema.d.ts index 9b8062140..1cdd3d006 100644 --- a/packages/vitest-angular/src/lib/builders/test/schema.d.ts +++ b/packages/vitest-angular/src/lib/builders/test/schema.d.ts @@ -4,4 +4,6 @@ export interface VitestSchema { reportsDirectory?: string; testFiles?: string[]; watch?: boolean; + ui?: boolean; + coverage?: boolean; } diff --git a/packages/vitest-angular/src/lib/builders/test/schema.json b/packages/vitest-angular/src/lib/builders/test/schema.json index 95a643bb9..2a7877312 100644 --- a/packages/vitest-angular/src/lib/builders/test/schema.json +++ b/packages/vitest-angular/src/lib/builders/test/schema.json @@ -28,6 +28,14 @@ "watch": { "description": "Watch files for changes and rerun tests related to changed files.", "type": "boolean" + }, + "ui": { + "description": "Run tests using Vitest UI Mode.", + "type": "boolean" + }, + "coverage": { + "description": "Enable code coverage analysis.", + "type": "boolean" } }, "required": [] diff --git a/packages/vitest-angular/src/lib/builders/test/vitest.impl.ts b/packages/vitest-angular/src/lib/builders/test/vitest.impl.ts index 2ed1a49b0..e957cb7d5 100644 --- a/packages/vitest-angular/src/lib/builders/test/vitest.impl.ts +++ b/packages/vitest-angular/src/lib/builders/test/vitest.impl.ts @@ -20,12 +20,19 @@ async function vitestBuilder( const projectConfig = await context.getProjectMetadata( context.target as unknown as string ); - const extraArgs = await getExtraArgs(options); + const { coverageArgs, ...extraArgs } = await getExtraArgs(options); const watch = options.watch === true; + const ui = options.ui === true; + const coverageEnabled = options.coverage === true; const config = { root: `${projectConfig['root'] || '.'}`, watch, + ui, config: options.configFile, + coverage: { + enabled: coverageEnabled, + ...coverageArgs, + }, ...extraArgs, }; const viteOverrides: any = { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6fc466585..edb428de6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -405,6 +405,9 @@ importers: vite-plugin-eslint: specifier: ^1.8.1 version: 1.8.1(eslint@8.57.0)(vite@6.0.3(@types/node@18.19.15)(jiti@2.4.0)(less@4.1.3)(sass@1.80.7)(stylus@0.64.0)(terser@5.36.0)(yaml@2.5.1)) + vite-plugin-inspect: + specifier: ~0.8 + version: 0.8.9(rollup@4.26.0)(vite@6.0.3(@types/node@18.19.15)(jiti@2.4.0)(less@4.1.3)(sass@1.80.7)(stylus@0.64.0)(terser@5.36.0)(yaml@2.5.1)) vite-tsconfig-paths: specifier: 4.2.0 version: 4.2.0(typescript@5.5.4)(vite@6.0.3(@types/node@18.19.15)(jiti@2.4.0)(less@4.1.3)(sass@1.80.7)(stylus@0.64.0)(terser@5.36.0)(yaml@2.5.1)) @@ -800,6 +803,9 @@ packages: '@angular/platform-browser': 19.0.4 rxjs: ^6.5.3 || ^7.4.0 + '@antfu/utils@0.7.10': + resolution: {integrity: sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==} + '@astrojs/compiler@2.8.0': resolution: {integrity: sha512-yrpD1WRGqsJwANaDIdtHo+YVjvIOFAjC83lu5qENIgrafwZcJgSXDuwVMXOgok4tFzpeKLsFQ6c3FoUdloLWBQ==} @@ -4132,9 +4138,6 @@ packages: resolution: {integrity: sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==} engines: {node: '>=12'} - '@polka/url@1.0.0-next.21': - resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==} - '@polka/url@1.0.0-next.25': resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==} @@ -4224,6 +4227,15 @@ packages: rollup: optional: true + '@rollup/pluginutils@5.1.4': + resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + '@rollup/rollup-android-arm-eabi@4.24.4': resolution: {integrity: sha512-jfUJrFct/hTA0XDM5p/htWKoNNTbDLY0KRwEt6pyOA6k2fmk0WVwl65PdUdJZgzGEHWx+49LilkcSaumQRyNQw==} cpu: [arm] @@ -4829,9 +4841,6 @@ packages: '@types/estree-jsx@1.0.1': resolution: {integrity: sha512-sHyakZlAezNFxmYRo0fopDZW+XvK6ipeZkkp5EAOLjdPfZp8VjZBJ67vSRI99RSCAoqXVmXOHS4fnWoxpuGQtQ==} - '@types/estree@1.0.0': - resolution: {integrity: sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==} - '@types/estree@1.0.1': resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==} @@ -4886,9 +4895,6 @@ packages: '@types/jsdom@20.0.1': resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} - '@types/json-schema@7.0.11': - resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} - '@types/json-schema@7.0.12': resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==} @@ -7012,6 +7018,15 @@ packages: supports-color: optional: true + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + decamelize-keys@1.1.0: resolution: {integrity: sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg==} engines: {node: '>=0.10.0'} @@ -7387,6 +7402,9 @@ packages: error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + error-stack-parser-es@0.1.5: + resolution: {integrity: sha512-xHku1X40RO+fO8yJ8Wh2f2rZWVjqyhb1zgq1yZ8aZRQkv6OOKhKWRUaht3eSCUbAOBaKIgM+ykwFLE+QUxgGeg==} + es-define-property@1.0.0: resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} engines: {node: '>= 0.4'} @@ -7487,6 +7505,7 @@ packages: eslint@8.57.0: resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true espree@9.5.0: @@ -12667,6 +12686,10 @@ packages: resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} engines: {node: '>= 10'} + sirv@3.0.0: + resolution: {integrity: sha512-BPwJGUeDaDCHihkORDchNyyTvWFhcusy1XMmhEVTQTwGeybFbp8YEmB+njbPnth1FibULBSBVwCQni25XlCUDg==} + engines: {node: '>=18'} + sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} @@ -13865,6 +13888,16 @@ packages: eslint: '>=7' vite: '>=2' + vite-plugin-inspect@0.8.9: + resolution: {integrity: sha512-22/8qn+LYonzibb1VeFZmISdVao5kC22jmEKm24vfFE8siEn47EpVcCLYMv6iKOYMJfjSvSJfueOwcFCkUnV3A==} + engines: {node: '>=14'} + peerDependencies: + '@nuxt/kit': '*' + vite: ^3.1.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.1 + peerDependenciesMeta: + '@nuxt/kit': + optional: true + vite-tsconfig-paths@4.2.0: resolution: {integrity: sha512-jGpus0eUy5qbbMVGiTxCL1iB9ZGN6Bd37VGLJU39kTDD6ZfULTTb1bcc5IeTWqWJKiWV5YihCaibeASPiGi8kw==} peerDependencies: @@ -14951,6 +14984,8 @@ snapshots: rxjs: 7.8.1 tslib: 2.8.1 + '@antfu/utils@0.7.10': {} + '@astrojs/compiler@2.8.0': {} '@astrojs/internal-helpers@0.2.0': {} @@ -15023,7 +15058,7 @@ snapshots: '@astrojs/telemetry@3.1.0': dependencies: ci-info: 4.0.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.4.0(supports-color@9.4.0) dlv: 1.1.3 dset: 3.1.3 is-docker: 3.0.0 @@ -15101,7 +15136,7 @@ snapshots: '@babel/traverse': 7.24.5 '@babel/types': 7.24.6 convert-source-map: 2.0.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.4.0(supports-color@9.4.0) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -15121,7 +15156,7 @@ snapshots: '@babel/traverse': 7.25.6 '@babel/types': 7.25.6 convert-source-map: 2.0.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.4.0(supports-color@9.4.0) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -15324,7 +15359,7 @@ snapshots: '@babel/core': 7.25.2 '@babel/helper-compilation-targets': 7.25.9 '@babel/helper-plugin-utils': 7.25.9 - debug: 4.3.7(supports-color@9.4.0) + debug: 4.4.0(supports-color@9.4.0) lodash.debounce: 4.0.8 resolve: 1.22.8 transitivePeerDependencies: @@ -15335,7 +15370,7 @@ snapshots: '@babel/core': 7.26.0 '@babel/helper-compilation-targets': 7.25.9 '@babel/helper-plugin-utils': 7.25.9 - debug: 4.3.7(supports-color@9.4.0) + debug: 4.4.0(supports-color@9.4.0) lodash.debounce: 4.0.8 resolve: 1.22.8 transitivePeerDependencies: @@ -17149,7 +17184,7 @@ snapshots: '@babel/helper-split-export-declaration': 7.24.7 '@babel/parser': 7.23.0 '@babel/types': 7.23.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.4.0(supports-color@9.4.0) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -17164,7 +17199,7 @@ snapshots: '@babel/helper-split-export-declaration': 7.24.7 '@babel/parser': 7.24.5 '@babel/types': 7.24.5 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.4.0(supports-color@9.4.0) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -17176,7 +17211,7 @@ snapshots: '@babel/parser': 7.25.6 '@babel/template': 7.25.0 '@babel/types': 7.25.6 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.4.0(supports-color@9.4.0) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -17188,7 +17223,7 @@ snapshots: '@babel/parser': 7.26.2 '@babel/template': 7.25.9 '@babel/types': 7.26.0 - debug: 4.3.7(supports-color@9.4.0) + debug: 4.4.0(supports-color@9.4.0) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -17342,7 +17377,7 @@ snapshots: dependencies: '@commitlint/top-level': 17.4.0 '@commitlint/types': 17.4.0 - fs-extra: 11.1.1 + fs-extra: 11.2.0 git-raw-commits: 2.0.11 minimist: 1.2.8 @@ -18449,7 +18484,7 @@ snapshots: '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.4.0(supports-color@9.4.0) espree: 9.6.1 globals: 13.21.0 ignore: 5.2.4 @@ -18471,7 +18506,7 @@ snapshots: '@humanwhocodes/config-array@0.11.14': dependencies: '@humanwhocodes/object-schema': 2.0.2 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.4.0(supports-color@9.4.0) minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -19953,8 +19988,6 @@ snapshots: '@pnpm/network.ca-file': 1.0.2 config-chain: 1.1.13 - '@polka/url@1.0.0-next.21': {} - '@polka/url@1.0.0-next.25': {} '@redocly/ajv@8.11.2': @@ -19989,7 +20022,7 @@ snapshots: '@rollup/plugin-commonjs@28.0.1(rollup@4.26.0)': dependencies: - '@rollup/pluginutils': 5.1.3(rollup@4.26.0) + '@rollup/pluginutils': 5.1.4(rollup@4.26.0) commondir: 1.0.1 estree-walker: 2.0.2 fdir: 6.4.2(picomatch@4.0.2) @@ -20001,7 +20034,7 @@ snapshots: '@rollup/plugin-inject@5.0.5(rollup@4.26.0)': dependencies: - '@rollup/pluginutils': 5.1.3(rollup@4.26.0) + '@rollup/pluginutils': 5.1.4(rollup@4.26.0) estree-walker: 2.0.2 magic-string: 0.30.12 optionalDependencies: @@ -20009,19 +20042,19 @@ snapshots: '@rollup/plugin-json@6.1.0(rollup@4.24.4)': dependencies: - '@rollup/pluginutils': 5.1.3(rollup@4.24.4) + '@rollup/pluginutils': 5.1.4(rollup@4.24.4) optionalDependencies: rollup: 4.24.4 '@rollup/plugin-json@6.1.0(rollup@4.26.0)': dependencies: - '@rollup/pluginutils': 5.1.3(rollup@4.26.0) + '@rollup/pluginutils': 5.1.4(rollup@4.26.0) optionalDependencies: rollup: 4.26.0 '@rollup/plugin-node-resolve@15.3.0(rollup@4.26.0)': dependencies: - '@rollup/pluginutils': 5.1.3(rollup@4.26.0) + '@rollup/pluginutils': 5.1.4(rollup@4.26.0) '@types/resolve': 1.20.2 deepmerge: 4.3.1 is-module: 1.0.0 @@ -20031,7 +20064,7 @@ snapshots: '@rollup/plugin-replace@6.0.1(rollup@4.26.0)': dependencies: - '@rollup/pluginutils': 5.1.3(rollup@4.26.0) + '@rollup/pluginutils': 5.1.4(rollup@4.26.0) magic-string: 0.30.12 optionalDependencies: rollup: 4.26.0 @@ -20049,7 +20082,15 @@ snapshots: estree-walker: 2.0.2 picomatch: 2.3.1 - '@rollup/pluginutils@5.1.3(rollup@4.24.4)': + '@rollup/pluginutils@5.1.3(rollup@4.26.0)': + dependencies: + '@types/estree': 1.0.6 + estree-walker: 2.0.2 + picomatch: 4.0.2 + optionalDependencies: + rollup: 4.26.0 + + '@rollup/pluginutils@5.1.4(rollup@4.24.4)': dependencies: '@types/estree': 1.0.6 estree-walker: 2.0.2 @@ -20057,7 +20098,7 @@ snapshots: optionalDependencies: rollup: 4.24.4 - '@rollup/pluginutils@5.1.3(rollup@4.26.0)': + '@rollup/pluginutils@5.1.4(rollup@4.26.0)': dependencies: '@types/estree': 1.0.6 estree-walker: 2.0.2 @@ -20208,7 +20249,7 @@ snapshots: conventional-changelog-angular: 7.0.0 conventional-commits-filter: 4.0.0 conventional-commits-parser: 5.0.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.4.0(supports-color@9.4.0) import-from-esm: 1.3.3 lodash-es: 4.17.21 micromatch: 4.0.5 @@ -20254,7 +20295,7 @@ snapshots: '@octokit/plugin-throttling': 8.1.3(@octokit/core@5.1.0) '@semantic-release/error': 4.0.0 aggregate-error: 5.0.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.4.0(supports-color@9.4.0) dir-glob: 3.0.1 globby: 14.0.0 http-proxy-agent: 7.0.0 @@ -20291,7 +20332,7 @@ snapshots: conventional-changelog-writer: 7.0.1 conventional-commits-filter: 4.0.0 conventional-commits-parser: 5.0.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.4.0(supports-color@9.4.0) get-stream: 7.0.1 import-from-esm: 1.3.3 into-stream: 7.0.0 @@ -20684,15 +20725,13 @@ snapshots: '@types/eslint@8.37.0': dependencies: - '@types/estree': 1.0.0 - '@types/json-schema': 7.0.11 + '@types/estree': 1.0.6 + '@types/json-schema': 7.0.12 '@types/estree-jsx@1.0.1': dependencies: '@types/estree': 1.0.6 - '@types/estree@1.0.0': {} - '@types/estree@1.0.1': {} '@types/estree@1.0.5': {} @@ -20756,8 +20795,6 @@ snapshots: '@types/tough-cookie': 4.0.2 parse5: 7.1.2 - '@types/json-schema@7.0.11': {} - '@types/json-schema@7.0.12': {} '@types/keyv@3.1.4': @@ -20967,7 +21004,7 @@ snapshots: dependencies: '@typescript-eslint/typescript-estree': 7.4.0(typescript@5.5.4) '@typescript-eslint/utils': 7.4.0(eslint@8.57.0)(typescript@5.5.4) - debug: 4.3.4(supports-color@8.1.1) + debug: 4.4.0(supports-color@9.4.0) eslint: 8.57.0 ts-api-utils: 1.3.0(typescript@5.5.4) optionalDependencies: @@ -20997,7 +21034,7 @@ snapshots: dependencies: '@typescript-eslint/types': 7.4.0 '@typescript-eslint/visitor-keys': 7.4.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.4.0(supports-color@9.4.0) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.3 @@ -21012,7 +21049,7 @@ snapshots: dependencies: '@typescript-eslint/types': 8.13.0 '@typescript-eslint/visitor-keys': 8.13.0 - debug: 4.3.7(supports-color@9.4.0) + debug: 4.4.0(supports-color@9.4.0) fast-glob: 3.3.2 is-glob: 4.0.3 minimatch: 9.0.5 @@ -21027,7 +21064,7 @@ snapshots: dependencies: '@typescript-eslint/types': 8.5.0 '@typescript-eslint/visitor-keys': 8.5.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.4.0(supports-color@9.4.0) fast-glob: 3.3.2 is-glob: 4.0.3 minimatch: 9.0.4 @@ -21330,13 +21367,13 @@ snapshots: agent-base@6.0.2: dependencies: - debug: 4.3.7(supports-color@9.4.0) + debug: 4.4.0(supports-color@9.4.0) transitivePeerDependencies: - supports-color agent-base@7.1.1(supports-color@9.4.0): dependencies: - debug: 4.3.7(supports-color@9.4.0) + debug: 4.4.0(supports-color@9.4.0) transitivePeerDependencies: - supports-color @@ -21651,7 +21688,7 @@ snapshots: caniuse-lite: 1.0.30001660 fraction.js: 4.3.7 normalize-range: 0.1.2 - picocolors: 1.0.1 + picocolors: 1.1.1 postcss: 8.4.41 postcss-value-parser: 4.2.0 @@ -21661,7 +21698,7 @@ snapshots: caniuse-lite: 1.0.30001660 fraction.js: 4.3.7 normalize-range: 0.1.2 - picocolors: 1.0.1 + picocolors: 1.1.1 postcss: 8.4.49 postcss-value-parser: 4.2.0 @@ -23462,6 +23499,18 @@ snapshots: optionalDependencies: supports-color: 9.4.0 + debug@4.4.0(supports-color@8.1.1): + dependencies: + ms: 2.1.3 + optionalDependencies: + supports-color: 8.1.1 + + debug@4.4.0(supports-color@9.4.0): + dependencies: + ms: 2.1.3 + optionalDependencies: + supports-color: 9.4.0 + decamelize-keys@1.1.0: dependencies: decamelize: 1.2.0 @@ -23583,7 +23632,7 @@ snapshots: detect-port@1.5.1: dependencies: address: 1.2.1 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.4.0(supports-color@9.4.0) transitivePeerDependencies: - supports-color @@ -23785,6 +23834,8 @@ snapshots: dependencies: is-arrayish: 0.2.1 + error-stack-parser-es@0.1.5: {} + es-define-property@1.0.0: dependencies: get-intrinsic: 1.2.4 @@ -24248,7 +24299,7 @@ snapshots: extract-zip@2.0.1(supports-color@8.1.1): dependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.4.0(supports-color@8.1.1) get-stream: 5.2.0 yauzl: 2.10.0 optionalDependencies: @@ -25270,14 +25321,14 @@ snapshots: dependencies: '@tootallnate/once': 2.0.0 agent-base: 6.0.2 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.4.0(supports-color@9.4.0) transitivePeerDependencies: - supports-color http-proxy-agent@7.0.0: dependencies: agent-base: 7.1.1(supports-color@9.4.0) - debug: 4.3.7(supports-color@9.4.0) + debug: 4.4.0(supports-color@9.4.0) transitivePeerDependencies: - supports-color @@ -25352,7 +25403,7 @@ snapshots: https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.4.0(supports-color@9.4.0) transitivePeerDependencies: - supports-color @@ -25423,7 +25474,7 @@ snapshots: import-from-esm@1.3.3: dependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.4.0(supports-color@9.4.0) import-meta-resolve: 4.0.0 transitivePeerDependencies: - supports-color @@ -25503,7 +25554,7 @@ snapshots: dependencies: '@ioredis/commands': 1.2.0 cluster-key-slot: 1.1.1 - debug: 4.3.7(supports-color@9.4.0) + debug: 4.4.0(supports-color@9.4.0) denque: 2.1.0 lodash.defaults: 4.2.0 lodash.isarguments: 3.1.0 @@ -25747,7 +25798,7 @@ snapshots: istanbul-lib-source-maps@4.0.1: dependencies: - debug: 4.3.7(supports-color@9.4.0) + debug: 4.4.0(supports-color@9.4.0) istanbul-lib-coverage: 3.2.0 source-map: 0.6.1 transitivePeerDependencies: @@ -26340,7 +26391,7 @@ snapshots: content-disposition: 0.5.4 content-type: 1.0.5 cookies: 0.9.1 - debug: 4.3.7(supports-color@9.4.0) + debug: 4.4.0(supports-color@9.4.0) delegates: 1.0.0 depd: 2.0.0 destroy: 1.2.0 @@ -26677,7 +26728,7 @@ snapshots: log4js@6.9.1: dependencies: date-format: 4.0.14 - debug: 4.3.7(supports-color@9.4.0) + debug: 4.4.0(supports-color@9.4.0) flatted: 3.2.7 rfdc: 1.4.1 streamroller: 3.1.5 @@ -27494,7 +27545,7 @@ snapshots: micromark@3.1.0: dependencies: '@types/debug': 4.1.7 - debug: 4.3.7(supports-color@9.4.0) + debug: 4.4.0(supports-color@9.4.0) decode-named-character-reference: 1.0.2 micromark-core-commonmark: 1.0.6 micromark-factory-space: 1.0.0 @@ -27516,7 +27567,7 @@ snapshots: micromark@4.0.0: dependencies: '@types/debug': 4.1.7 - debug: 4.3.7(supports-color@9.4.0) + debug: 4.4.0(supports-color@9.4.0) decode-named-character-reference: 1.0.2 devlop: 1.1.0 micromark-core-commonmark: 2.0.0 @@ -29465,7 +29516,7 @@ snapshots: postcss@8.4.41: dependencies: nanoid: 3.3.7 - picocolors: 1.0.1 + picocolors: 1.1.1 source-map-js: 1.2.0 postcss@8.4.47: @@ -30688,7 +30739,7 @@ snapshots: sirv@1.0.19: dependencies: - '@polka/url': 1.0.0-next.21 + '@polka/url': 1.0.0-next.25 mrmime: 1.0.1 totalist: 1.1.0 @@ -30698,6 +30749,12 @@ snapshots: mrmime: 2.0.0 totalist: 3.0.1 + sirv@3.0.0: + dependencies: + '@polka/url': 1.0.0-next.25 + mrmime: 2.0.0 + totalist: 3.0.1 + sisteransi@1.0.5: {} sitemap@7.1.2: @@ -30757,7 +30814,7 @@ snapshots: socks-proxy-agent@8.0.4: dependencies: agent-base: 7.1.1(supports-color@9.4.0) - debug: 4.3.7(supports-color@9.4.0) + debug: 4.4.0(supports-color@9.4.0) socks: 2.8.3 transitivePeerDependencies: - supports-color @@ -30833,7 +30890,7 @@ snapshots: spdy-transport@3.0.0: dependencies: - debug: 4.3.7(supports-color@9.4.0) + debug: 4.4.0(supports-color@9.4.0) detect-node: 2.1.0 hpack.js: 2.1.6 obuf: 1.1.2 @@ -30844,7 +30901,7 @@ snapshots: spdy@4.0.2: dependencies: - debug: 4.3.7(supports-color@9.4.0) + debug: 4.4.0(supports-color@9.4.0) handle-thing: 2.0.1 http-deceiver: 1.2.7 select-hose: 2.0.0 @@ -30939,7 +30996,7 @@ snapshots: streamroller@3.1.5: dependencies: date-format: 4.0.14 - debug: 4.3.7(supports-color@9.4.0) + debug: 4.4.0(supports-color@9.4.0) fs-extra: 8.1.0 transitivePeerDependencies: - supports-color @@ -31080,7 +31137,7 @@ snapshots: stylus@0.64.0: dependencies: '@adobe/css-tools': 4.3.3 - debug: 4.3.7(supports-color@9.4.0) + debug: 4.4.0(supports-color@9.4.0) glob: 10.4.5 sax: 1.4.1 source-map: 0.7.4 @@ -31526,7 +31583,7 @@ snapshots: tuf-js@3.0.1: dependencies: '@tufjs/models': 3.0.1 - debug: 4.3.7(supports-color@9.4.0) + debug: 4.4.0(supports-color@9.4.0) make-fetch-happen: 14.0.3 transitivePeerDependencies: - supports-color @@ -31656,7 +31713,7 @@ snapshots: unimport@3.13.2(rollup@4.26.0): dependencies: - '@rollup/pluginutils': 5.1.3(rollup@4.26.0) + '@rollup/pluginutils': 5.1.4(rollup@4.26.0) acorn: 8.14.0 escape-string-regexp: 5.0.0 estree-walker: 3.0.3 @@ -31993,7 +32050,7 @@ snapshots: vite-node@2.1.5(@types/node@18.19.15)(less@4.1.3)(sass@1.80.7)(stylus@0.64.0)(terser@5.36.0): dependencies: cac: 6.7.14 - debug: 4.3.7(supports-color@9.4.0) + debug: 4.4.0(supports-color@9.4.0) es-module-lexer: 1.5.4 pathe: 1.1.2 vite: 5.4.11(@types/node@18.19.15)(less@4.1.3)(sass@1.80.7)(stylus@0.64.0)(terser@5.36.0) @@ -32016,6 +32073,22 @@ snapshots: rollup: 2.79.1 vite: 6.0.3(@types/node@18.19.15)(jiti@2.4.0)(less@4.1.3)(sass@1.80.7)(stylus@0.64.0)(terser@5.36.0)(yaml@2.5.1) + vite-plugin-inspect@0.8.9(rollup@4.26.0)(vite@6.0.3(@types/node@18.19.15)(jiti@2.4.0)(less@4.1.3)(sass@1.80.7)(stylus@0.64.0)(terser@5.36.0)(yaml@2.5.1)): + dependencies: + '@antfu/utils': 0.7.10 + '@rollup/pluginutils': 5.1.4(rollup@4.26.0) + debug: 4.4.0(supports-color@9.4.0) + error-stack-parser-es: 0.1.5 + fs-extra: 11.2.0 + open: 10.1.0 + perfect-debounce: 1.0.0 + picocolors: 1.1.1 + sirv: 3.0.0 + vite: 6.0.3(@types/node@18.19.15)(jiti@2.4.0)(less@4.1.3)(sass@1.80.7)(stylus@0.64.0)(terser@5.36.0)(yaml@2.5.1) + transitivePeerDependencies: + - rollup + - supports-color + vite-tsconfig-paths@4.2.0(typescript@5.5.4)(vite@6.0.3(@types/node@18.19.15)(jiti@2.4.0)(less@4.1.3)(sass@1.80.7)(stylus@0.64.0)(terser@5.36.0)(yaml@2.5.1)): dependencies: debug: 4.3.4(supports-color@8.1.1) @@ -32171,7 +32244,7 @@ snapshots: gzip-size: 6.0.0 html-escaper: 2.0.2 opener: 1.5.2 - picocolors: 1.0.1 + picocolors: 1.1.1 sirv: 2.0.4 ws: 7.5.9 transitivePeerDependencies: