diff --git a/.aspect/rules/external_repository_action_cache/npm_translate_lock_MzA5NzUwNzMx b/.aspect/rules/external_repository_action_cache/npm_translate_lock_MzA5NzUwNzMx index 384e2ecf129..f38a82788eb 100755 --- a/.aspect/rules/external_repository_action_cache/npm_translate_lock_MzA5NzUwNzMx +++ b/.aspect/rules/external_repository_action_cache/npm_translate_lock_MzA5NzUwNzMx @@ -5,7 +5,7 @@ package.json=-1892818434 packages/compiler-cli/package.json=-1396217149 packages/compiler/package.json=499550843 -pnpm-lock.yaml=-1041360686 +pnpm-lock.yaml=-903408509 pnpm-workspace.yaml=353334404 tools/bazel/rules_angular_store/package.json=-239561259 yarn.lock=1636150847 diff --git a/.github/workflows/dev-infra.yml b/.github/workflows/dev-infra.yml index 158ea1779ef..f27335163fa 100644 --- a/.github/workflows/dev-infra.yml +++ b/.github/workflows/dev-infra.yml @@ -12,14 +12,14 @@ jobs: labels: runs-on: ubuntu-latest steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: angular/dev-infra/github-actions/commit-message-based-labels@1f047e7dbae43ea969c2cafb53b33207e86b800f + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: angular/dev-infra/github-actions/pull-request-labeling@4b4659eabe75a67cebf4692c3c88a98275c67200 with: angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }} post_approval_changes: runs-on: ubuntu-latest steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: angular/dev-infra/github-actions/post-approval-changes@1f047e7dbae43ea969c2cafb53b33207e86b800f + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: angular/dev-infra/github-actions/post-approval-changes@4b4659eabe75a67cebf4692c3c88a98275c67200 with: angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }} diff --git a/WORKSPACE b/WORKSPACE index d248bc3af5f..43b61afccef 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -83,6 +83,7 @@ yarn_install( YARN_LABEL, "//:.yarnrc", "//:tools/npm-patches/@angular+ng-dev+0.0.0-a6dcd24107d12114198251ee5d20cda814a1986a.patch", + "//:tools/npm-patches/@angular+ssr+19.2.0-next.2.patch", "//:tools/npm-patches/@bazel+jasmine+5.8.1.patch", "//tools:postinstall-patches.js", "//tools/esm-interop:patches/npm/@angular+build-tooling+0.0.0-2670abf637fa155971cdd1f7e570a7f234922a65.patch", diff --git a/adev/src/main.server.ts b/adev/src/main.server.ts index 0e508858b9f..243b65ae925 100644 --- a/adev/src/main.server.ts +++ b/adev/src/main.server.ts @@ -6,10 +6,11 @@ * found in the LICENSE file at https://angular.dev/license */ -import {bootstrapApplication} from '@angular/platform-browser'; +import {bootstrapApplication, BootstrapContext} from '@angular/platform-browser'; import {AppComponent} from './app/app.component'; import {config} from './app/app.config.server'; -const bootstrap = () => bootstrapApplication(AppComponent, config); +const bootstrap = (context: BootstrapContext) => + bootstrapApplication(AppComponent, config, context); export default bootstrap; diff --git a/goldens/public-api/platform-browser/index.api.md b/goldens/public-api/platform-browser/index.api.md index 5cd1b53f014..2248262197b 100644 --- a/goldens/public-api/platform-browser/index.api.md +++ b/goldens/public-api/platform-browser/index.api.md @@ -29,7 +29,12 @@ import { Version } from '@angular/core'; export type ApplicationConfig = ApplicationConfig_2; // @public -export function bootstrapApplication(rootComponent: Type, options?: ApplicationConfig): Promise; +export function bootstrapApplication(rootComponent: Type, options?: ApplicationConfig, context?: BootstrapContext): Promise; + +// @public +export interface BootstrapContext { + platformRef: PlatformRef; +} // @public export class BrowserModule { diff --git a/goldens/public-api/platform-server/index.api.md b/goldens/public-api/platform-server/index.api.md index 210b2c93381..476de591676 100644 --- a/goldens/public-api/platform-server/index.api.md +++ b/goldens/public-api/platform-server/index.api.md @@ -5,6 +5,7 @@ ```ts import { ApplicationRef } from '@angular/core'; +import { BootstrapContext } from '@angular/platform-browser'; import { EnvironmentProviders } from '@angular/core'; import * as i0 from '@angular/core'; import * as i1 from '@angular/platform-browser'; @@ -27,7 +28,7 @@ export interface PlatformConfig { url?: string; } -// @public (undocumented) +// @public export function platformServer(extraProviders?: StaticProvider[] | undefined): PlatformRef; // @public @@ -45,7 +46,7 @@ export class PlatformState { export function provideServerRendering(): EnvironmentProviders; // @public -export function renderApplication(bootstrap: () => Promise, options: { +export function renderApplication(bootstrap: (context: BootstrapContext) => Promise, options: { document?: string | Document; url?: string; platformProviders?: Provider[]; diff --git a/integration/platform-server-hydration/src/main.server.ts b/integration/platform-server-hydration/src/main.server.ts index e83e990a42c..b8ddf22d452 100644 --- a/integration/platform-server-hydration/src/main.server.ts +++ b/integration/platform-server-hydration/src/main.server.ts @@ -1,7 +1,8 @@ -import {bootstrapApplication} from '@angular/platform-browser'; +import {bootstrapApplication, BootstrapContext} from '@angular/platform-browser'; import {AppComponent} from './app/app.component'; import {config} from './app/app.config.server'; -const bootstrap = () => bootstrapApplication(AppComponent, config); +const bootstrap = (context: BootstrapContext) => + bootstrapApplication(AppComponent, config, context); export default bootstrap; diff --git a/integration/platform-server-zoneless/projects/standalone/src/main.server.ts b/integration/platform-server-zoneless/projects/standalone/src/main.server.ts index e83e990a42c..b8ddf22d452 100644 --- a/integration/platform-server-zoneless/projects/standalone/src/main.server.ts +++ b/integration/platform-server-zoneless/projects/standalone/src/main.server.ts @@ -1,7 +1,8 @@ -import {bootstrapApplication} from '@angular/platform-browser'; +import {bootstrapApplication, BootstrapContext} from '@angular/platform-browser'; import {AppComponent} from './app/app.component'; import {config} from './app/app.config.server'; -const bootstrap = () => bootstrapApplication(AppComponent, config); +const bootstrap = (context: BootstrapContext) => + bootstrapApplication(AppComponent, config, context); export default bootstrap; diff --git a/integration/platform-server/projects/standalone/src/main.server.ts b/integration/platform-server/projects/standalone/src/main.server.ts index e83e990a42c..b8ddf22d452 100644 --- a/integration/platform-server/projects/standalone/src/main.server.ts +++ b/integration/platform-server/projects/standalone/src/main.server.ts @@ -1,7 +1,8 @@ -import {bootstrapApplication} from '@angular/platform-browser'; +import {bootstrapApplication, BootstrapContext} from '@angular/platform-browser'; import {AppComponent} from './app/app.component'; import {config} from './app/app.config.server'; -const bootstrap = () => bootstrapApplication(AppComponent, config); +const bootstrap = (context: BootstrapContext) => + bootstrapApplication(AppComponent, config, context); export default bootstrap; diff --git a/modules/ssr-benchmarks/src/main.server.ts b/modules/ssr-benchmarks/src/main.server.ts index c2a6866f6c7..bbb42b8278d 100644 --- a/modules/ssr-benchmarks/src/main.server.ts +++ b/modules/ssr-benchmarks/src/main.server.ts @@ -7,12 +7,13 @@ */ import {ɵenableProfiling} from '@angular/core'; -import {bootstrapApplication} from '@angular/platform-browser'; +import {bootstrapApplication, BootstrapContext} from '@angular/platform-browser'; import {AppComponent} from './app/app.component'; import {config} from './app/app.config.server'; import {renderApplication, ɵENABLE_DOM_EMULATION} from '@angular/platform-server'; -const bootstrap = () => bootstrapApplication(AppComponent, config); +const bootstrap = (context: BootstrapContext) => + bootstrapApplication(AppComponent, config, context); /** * Function that will profile the server-side rendering diff --git a/packages/core/schematics/BUILD.bazel b/packages/core/schematics/BUILD.bazel index efdaf610b0d..84fd56d56cd 100644 --- a/packages/core/schematics/BUILD.bazel +++ b/packages/core/schematics/BUILD.bazel @@ -67,6 +67,7 @@ rollup_bundle( "//packages/core/schematics/migrations/explicit-standalone-flag:index.ts": "explicit-standalone-flag", "//packages/core/schematics/migrations/pending-tasks:index.ts": "pending-tasks", "//packages/core/schematics/migrations/provide-initializer:index.ts": "provide-initializer", + "//packages/core/schematics/migrations/add-bootstrap-context-to-server-main:index.ts": "add-bootstrap-context-to-server-main", }, format = "cjs", link_workspace_root = True, @@ -76,6 +77,7 @@ rollup_bundle( "//packages/core/schematics/test:__pkg__", ], deps = [ + "//packages/core/schematics/migrations/add-bootstrap-context-to-server-main", "//packages/core/schematics/migrations/explicit-standalone-flag", "//packages/core/schematics/migrations/pending-tasks", "//packages/core/schematics/migrations/provide-initializer", diff --git a/packages/core/schematics/migrations.json b/packages/core/schematics/migrations.json index 098840373f1..8c21ab6731b 100644 --- a/packages/core/schematics/migrations.json +++ b/packages/core/schematics/migrations.json @@ -15,6 +15,11 @@ "description": "Replaces `APP_INITIALIZER`, `ENVIRONMENT_INITIALIZER` & `PLATFORM_INITIALIZER` respectively with `provideAppInitializer`, `provideEnvironmentInitializer` & `providePlatformInitializer`.", "factory": "./bundles/provide-initializer.cjs#migrate", "optional": true + }, + "add-bootstrap-context-to-server-main": { + "version": "19.2.15", + "description": "Adds `BootstrapContext` to `bootstrapApplication` calls in `main.server.ts` to support server rendering.", + "factory": "./bundles/add-bootstrap-context-to-server-main.cjs#migrate" } } } diff --git a/packages/core/schematics/migrations/add-bootstrap-context-to-server-main/BUILD.bazel b/packages/core/schematics/migrations/add-bootstrap-context-to-server-main/BUILD.bazel new file mode 100644 index 00000000000..fb62b8213c6 --- /dev/null +++ b/packages/core/schematics/migrations/add-bootstrap-context-to-server-main/BUILD.bazel @@ -0,0 +1,21 @@ +load("//tools:defaults2.bzl", "ts_project") + +package( + default_visibility = [ + "//packages/core/schematics:__pkg__", + "//packages/core/schematics/test:__pkg__", + ], +) + +ts_project( + name = "add-bootstrap-context-to-server-main", + srcs = glob(["**/*.ts"]), + interop_deps = [ + "//packages/compiler-cli/private", + "//packages/core/schematics/utils", + ], + deps = [ + "//:node_modules/@angular-devkit/schematics", + "//:node_modules/typescript", + ], +) diff --git a/packages/core/schematics/migrations/add-bootstrap-context-to-server-main/README.md b/packages/core/schematics/migrations/add-bootstrap-context-to-server-main/README.md new file mode 100644 index 00000000000..ee241c82124 --- /dev/null +++ b/packages/core/schematics/migrations/add-bootstrap-context-to-server-main/README.md @@ -0,0 +1,15 @@ +# Add Bootstrap Context to Server Main Migration + +This schematic updates `main.server.ts` files to correctly handle server-side rendering with `bootstrapApplication`. + +## How it works + +The migration performs the following transformations: + +1. **Identifies `bootstrapApplication` calls:** It specifically targets `main.server.ts` files to find calls to `bootstrapApplication` that are missing a third `context` argument. + +2. **Updates the function signature:** It adds a `(context: BootstrapContext)` parameter to the arrow function that typically wraps the `bootstrapApplication` call in a server entry file. + +3. **Passes the context:** It adds `, context` to the `bootstrapApplication` call, passing the newly added parameter. + +4. **Updates imports:** It ensures that `BootstrapContext` is imported from `@angular/platform-browser`. \ No newline at end of file diff --git a/packages/core/schematics/migrations/add-bootstrap-context-to-server-main/index.ts b/packages/core/schematics/migrations/add-bootstrap-context-to-server-main/index.ts new file mode 100644 index 00000000000..3cbc9437026 --- /dev/null +++ b/packages/core/schematics/migrations/add-bootstrap-context-to-server-main/index.ts @@ -0,0 +1,58 @@ +/*! + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import {Rule, SchematicsException, Tree, UpdateRecorder} from '@angular-devkit/schematics'; +import {relative} from 'path'; +import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths'; +import {canMigrateFile, createMigrationProgram} from '../../utils/typescript/compiler_host'; +import {migrateFile} from './migration'; + +export function migrate(): Rule { + return async (tree: Tree) => { + const {buildPaths, testPaths} = await getProjectTsConfigPaths(tree); + const basePath = process.cwd(); + const allPaths = [...buildPaths, ...testPaths]; + + if (!allPaths.length) { + throw new SchematicsException( + 'Could not find any tsconfig file. Cannot run the add-bootstrap-context-to-server-main migration.', + ); + } + + for (const tsconfigPath of allPaths) { + runMigration(tree, tsconfigPath, basePath); + } + }; +} + +function runMigration(tree: Tree, tsconfigPath: string, basePath: string) { + const program = createMigrationProgram(tree, tsconfigPath, basePath); + const sourceFiles = program + .getSourceFiles() + .filter((sourceFile) => canMigrateFile(basePath, sourceFile, program)); + + for (const sourceFile of sourceFiles) { + let update: UpdateRecorder | null = null; + + const rewriter = (startPos: number, width: number, text: string | null) => { + if (update === null) { + // Lazily initialize update, because most files will not require migration. + update = tree.beginUpdate(relative(basePath, sourceFile.fileName)); + } + update.remove(startPos, width); + if (text !== null) { + update.insertLeft(startPos, text); + } + }; + migrateFile(sourceFile, rewriter); + + if (update !== null) { + tree.commitUpdate(update); + } + } +} diff --git a/packages/core/schematics/migrations/add-bootstrap-context-to-server-main/migration.ts b/packages/core/schematics/migrations/add-bootstrap-context-to-server-main/migration.ts new file mode 100644 index 00000000000..975483be210 --- /dev/null +++ b/packages/core/schematics/migrations/add-bootstrap-context-to-server-main/migration.ts @@ -0,0 +1,78 @@ +/*! + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import {ImportManager} from '@angular/compiler-cli/private/migrations'; +import ts from 'typescript'; + +type Rewriter = (startPos: number, width: number, text: string | null) => void; + +function findArrowFunction(node: ts.Node): ts.ArrowFunction | undefined { + let current: ts.Node | undefined = node; + while (current) { + if (ts.isArrowFunction(current)) { + return current; + } + current = current.parent; + } + return undefined; +} + +export function migrateFile(sourceFile: ts.SourceFile, rewriter: Rewriter) { + if (!sourceFile.fileName.endsWith('main.server.ts')) { + return; + } + + const bootstrapAppCalls: ts.CallExpression[] = []; + ts.forEachChild(sourceFile, function findCalls(node) { + if ( + ts.isCallExpression(node) && + ts.isIdentifier(node.expression) && + node.expression.text === 'bootstrapApplication' && + node.arguments.length < 3 + ) { + bootstrapAppCalls.push(node); + } + ts.forEachChild(node, findCalls); + }); + + if (bootstrapAppCalls.length === 0) { + return; + } + + const importManager = new ImportManager({ + generateUniqueIdentifier: () => null, + shouldUseSingleQuotes: () => true, + }); + + for (const node of bootstrapAppCalls) { + const end = node.arguments[node.arguments.length - 1].getEnd(); + rewriter(end, 0, ', context'); + + const arrowFunction = findArrowFunction(node); + if (arrowFunction && arrowFunction.parameters.length === 0) { + const pos = arrowFunction.parameters.end; + rewriter(pos, 0, 'context: BootstrapContext'); + } + } + + importManager.addImport({ + exportSymbolName: 'BootstrapContext', + exportModuleSpecifier: '@angular/platform-browser', + requestedFile: sourceFile, + }); + + const finalization = importManager.finalize(); + const printer = ts.createPrinter(); + + for (const [oldBindings, newBindings] of finalization.updatedImports) { + const newText = printer.printNode(ts.EmitHint.Unspecified, newBindings, sourceFile); + const start = oldBindings.getStart(); + const width = oldBindings.getWidth(); + rewriter(start, width, newText); + } +} diff --git a/packages/core/schematics/test/add_bootstrap_context_to_server_main_spec.ts b/packages/core/schematics/test/add_bootstrap_context_to_server_main_spec.ts new file mode 100644 index 00000000000..e166dd4025e --- /dev/null +++ b/packages/core/schematics/test/add_bootstrap_context_to_server_main_spec.ts @@ -0,0 +1,169 @@ +/*! + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import {getSystemPath, normalize, virtualFs} from '@angular-devkit/core'; +import {TempScopedNodeJsSyncHost} from '@angular-devkit/core/node/testing'; +import {HostTree} from '@angular-devkit/schematics'; +import {SchematicTestRunner, UnitTestTree} from '@angular-devkit/schematics/testing/index.js'; +import {runfiles} from '@bazel/runfiles'; +import shx from 'shelljs'; + +describe('bootstrapApplication for server migration', () => { + let runner: SchematicTestRunner; + let host: TempScopedNodeJsSyncHost; + let tree: UnitTestTree; + let tmpDirPath: string; + + function writeFile(filePath: string, contents: string) { + host.sync.write(normalize(filePath), virtualFs.stringToFileBuffer(contents)); + } + + function runMigration() { + return runner.runSchematic('add-bootstrap-context-to-server-main', {}, tree); + } + + beforeEach(() => { + runner = new SchematicTestRunner('test', runfiles.resolvePackageRelative('../migrations.json')); + host = new TempScopedNodeJsSyncHost(); + tree = new UnitTestTree(new HostTree(host)); + + writeFile('/tsconfig.json', '{}'); + writeFile( + '/angular.json', + JSON.stringify({ + version: 1, + projects: { + t: { + root: '', + architect: { + build: {options: {tsConfig: './tsconfig.json'}}, + server: {options: {main: './main.server.ts'}}, + }, + }, + }, + }), + ); + + tmpDirPath = getSystemPath(host.root); + + // Switch into the temporary directory path. This allows us to run + // the schematic against our custom unit test tree. + shx.cd(tmpDirPath); + }); + + it('should add BootstrapContext to bootstrapApplication call', async () => { + const inputContent = ` +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { config } from './app/app.config.server'; + +const bootstrap = () => bootstrapApplication(AppComponent, config); + +export default bootstrap; +`; + const expectedContent = ` +import { bootstrapApplication, BootstrapContext } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { config } from './app/app.config.server'; + +const bootstrap = (context: BootstrapContext) => bootstrapApplication(AppComponent, config, context); + +export default bootstrap; +`; + writeFile('/main.server.ts', inputContent); + await runMigration(); + const newContent = tree.readContent('/main.server.ts'); + expect(newContent).toEqual(expectedContent); + }); + + it('should add BootstrapContext to bootstrapApplication call in a block body', async () => { + const inputContent = ` +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { config } from './app/app.config.server'; + +const bootstrap = () => { + return bootstrapApplication(AppComponent, config); +}; + +export default bootstrap; +`; + const expectedContent = ` +import { bootstrapApplication, BootstrapContext } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { config } from './app/app.config.server'; + +const bootstrap = (context: BootstrapContext) => { + return bootstrapApplication(AppComponent, config, context); +}; + +export default bootstrap; +`; + writeFile('/main.server.ts', inputContent); + await runMigration(); + const newContent = tree.readContent('/main.server.ts'); + expect(newContent).toEqual(expectedContent); + }); + + it('should not change bootstrapApplication call that already has a context', async () => { + const inputContent = ` +import { bootstrapApplication, BootstrapContext } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { config } from './app/app.config.server'; + +const bootstrap = (context: BootstrapContext) => bootstrapApplication(AppComponent, config, context); + +export default bootstrap; +`; + writeFile('/main.server.ts', inputContent); + await runMigration(); + const newContent = tree.readContent('/main.server.ts'); + expect(newContent).toEqual(inputContent); + }); + + it('should add BootstrapContext to existing platform-browser import', async () => { + const inputContent = ` +import { bootstrapApplication, BrowserModule } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { config } from './app/app.config.server'; + +const bootstrap = () => bootstrapApplication(AppComponent, config); + +export default bootstrap; +`; + const expectedContent = ` +import { bootstrapApplication, BrowserModule, BootstrapContext } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { config } from './app/app.config.server'; + +const bootstrap = (context: BootstrapContext) => bootstrapApplication(AppComponent, config, context); + +export default bootstrap; +`; + writeFile('/main.server.ts', inputContent); + await runMigration(); + const newContent = tree.readContent('/main.server.ts'); + expect(newContent).toEqual(expectedContent); + }); + + it('should not modify other files', async () => { + const inputContent = ` +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { config } from './app/app.config.server'; + +const bootstrap = () => bootstrapApplication(AppComponent, config); + +export default bootstrap; +`; + writeFile('/main.ts', inputContent); + await runMigration(); + const newContent = tree.readContent('/main.ts'); + expect(newContent).toEqual(inputContent); + }); +}); diff --git a/packages/core/src/application/create_application.ts b/packages/core/src/application/create_application.ts index 1b06ea8c819..75442f518cd 100644 --- a/packages/core/src/application/create_application.ts +++ b/packages/core/src/application/create_application.ts @@ -20,6 +20,8 @@ import {ChangeDetectionSchedulerImpl} from '../change_detection/scheduling/zonel import {bootstrap} from '../platform/bootstrap'; import {profiler} from '../render3/profiler'; import {ProfilerEvent} from '../render3/profiler_types'; +import {RuntimeError, RuntimeErrorCode} from '../errors'; +import {PlatformRef} from '../platform/platform_ref'; /** * Internal create application API that implements the core application creation logic and optional @@ -37,17 +39,28 @@ export function internalCreateApplication(config: { rootComponent?: Type; appProviders?: Array; platformProviders?: Provider[]; + platformRef?: PlatformRef; }): Promise { + const {rootComponent, appProviders, platformProviders, platformRef} = config; profiler(ProfilerEvent.BootstrapApplicationStart); + + if (typeof ngServerMode !== 'undefined' && ngServerMode && !platformRef) { + throw new RuntimeError( + RuntimeErrorCode.PLATFORM_NOT_FOUND, + ngDevMode && + 'Missing Platform: This may be due to using `bootstrapApplication` on the server without passing a `BootstrapContext`. ' + + 'Please make sure that `bootstrapApplication` is called with a `context` argument.', + ); + } + try { - const {rootComponent, appProviders, platformProviders} = config; + const platformInjector = + platformRef?.injector ?? createOrReusePlatformInjector(platformProviders as StaticProvider[]); if ((typeof ngDevMode === 'undefined' || ngDevMode) && rootComponent !== undefined) { assertStandaloneComponentType(rootComponent); } - const platformInjector = createOrReusePlatformInjector(platformProviders as StaticProvider[]); - // Create root application injector based on a set of providers configured at the platform // bootstrap level as well as providers passed to the bootstrap call by a user. const allAppProviders = [ diff --git a/packages/core/src/core_private_export.ts b/packages/core/src/core_private_export.ts index 6744277efa4..d25b3acfef1 100644 --- a/packages/core/src/core_private_export.ts +++ b/packages/core/src/core_private_export.ts @@ -122,7 +122,6 @@ export { restoreComponentResolutionQueue as ɵrestoreComponentResolutionQueue, } from './metadata/resource_loading'; export {PendingTasksInternal as ɵPendingTasksInternal} from './pending_tasks'; -export {ALLOW_MULTIPLE_PLATFORMS as ɵALLOW_MULTIPLE_PLATFORMS} from './platform/platform'; export {ENABLE_ROOT_COMPONENT_BOOTSTRAP as ɵENABLE_ROOT_COMPONENT_BOOTSTRAP} from './platform/bootstrap'; export {ReflectionCapabilities as ɵReflectionCapabilities} from './reflection/reflection_capabilities'; export {AnimationRendererType as ɵAnimationRendererType} from './render/api'; diff --git a/packages/core/src/platform/platform.ts b/packages/core/src/platform/platform.ts index 36179d84406..7427b2ead94 100644 --- a/packages/core/src/platform/platform.ts +++ b/packages/core/src/platform/platform.ts @@ -27,14 +27,6 @@ import {PLATFORM_DESTROY_LISTENERS} from './platform_destroy_listeners'; let _platformInjector: Injector | null = null; -/** - * Internal token to indicate whether having multiple bootstrapped platform should be allowed (only - * one bootstrapped platform is allowed by default). This token helps to support SSR scenarios. - */ -export const ALLOW_MULTIPLE_PLATFORMS = new InjectionToken( - ngDevMode ? 'AllowMultipleToken' : '', -); - /** * Creates a platform. * Platforms must be created on launch using this function. @@ -42,15 +34,20 @@ export const ALLOW_MULTIPLE_PLATFORMS = new InjectionToken( * @publicApi */ export function createPlatform(injector: Injector): PlatformRef { - if (_platformInjector && !_platformInjector.get(ALLOW_MULTIPLE_PLATFORMS, false)) { + if (getPlatform()) { throw new RuntimeError( RuntimeErrorCode.MULTIPLE_PLATFORMS, ngDevMode && 'There can be only one platform. Destroy the previous one to create a new one.', ); } + publishDefaultGlobalUtils(); publishSignalConfiguration(); - _platformInjector = injector; + + // During SSR, using this setting and using an injector from the global can cause the + // injector to be used for a different requjest due to concurrency. + _platformInjector = typeof ngServerMode === 'undefined' || !ngServerMode ? injector : null; + const platform = injector.get(PlatformRef); runPlatformInitializers(injector); return platform; @@ -76,19 +73,19 @@ export function createPlatformFactory( const marker = new InjectionToken(desc); return (extraProviders: StaticProvider[] = []) => { let platform = getPlatform(); - if (!platform || platform.injector.get(ALLOW_MULTIPLE_PLATFORMS, false)) { + if (!platform) { const platformProviders: StaticProvider[] = [ ...providers, ...extraProviders, {provide: marker, useValue: true}, ]; - if (parentPlatformFactory) { - parentPlatformFactory(platformProviders); - } else { + + platform = + parentPlatformFactory?.(platformProviders) ?? createPlatform(createPlatformInjector(platformProviders, desc)); - } } - return assertPlatform(marker); + + return typeof ngServerMode !== 'undefined' && ngServerMode ? platform : assertPlatform(marker); }; } @@ -114,7 +111,6 @@ function createPlatformInjector(providers: StaticProvider[] = [], name?: string) */ export function assertPlatform(requiredToken: any): PlatformRef { const platform = getPlatform(); - if (!platform) { throw new RuntimeError(RuntimeErrorCode.PLATFORM_NOT_FOUND, ngDevMode && 'No platform exists!'); } @@ -133,11 +129,16 @@ export function assertPlatform(requiredToken: any): PlatformRef { } /** - * Returns the current platform. + * Returns the current platform in the browser environment. In the server environment, + * returns `null`. If you need access to the platform information, inject `PlatformRef` in your application. * * @publicApi */ export function getPlatform(): PlatformRef | null { + if (typeof ngServerMode !== 'undefined' && ngServerMode) { + return null; + } + return _platformInjector?.get(PlatformRef) ?? null; } @@ -145,6 +146,8 @@ export function getPlatform(): PlatformRef | null { * Destroys the current Angular platform and all Angular applications on the page. * Destroys all modules and listeners registered with the platform. * + * This function should not be used in a server environment, as it will be a no-op. + * * @publicApi */ export function destroyPlatform(): void { @@ -162,9 +165,16 @@ export function createOrReusePlatformInjector(providers: StaticProvider[] = []): if (_platformInjector) return _platformInjector; publishDefaultGlobalUtils(); + // Otherwise, setup a new platform injector and run platform initializers. const injector = createPlatformInjector(providers); - _platformInjector = injector; + + // During SSR, using this setting and using an injector from the global can cause the + // injector to be used for a different request due to concurrency. + if (typeof ngServerMode === 'undefined' || !ngServerMode) { + _platformInjector = injector; + } + publishSignalConfiguration(); runPlatformInitializers(injector); return injector; diff --git a/packages/core/test/bundling/forms_reactive/bundle.golden_symbols.json b/packages/core/test/bundling/forms_reactive/bundle.golden_symbols.json index d4c2f448c90..3ca7af5cb8b 100644 --- a/packages/core/test/bundling/forms_reactive/bundle.golden_symbols.json +++ b/packages/core/test/bundling/forms_reactive/bundle.golden_symbols.json @@ -1,5 +1,4 @@ [ - "ALLOW_MULTIPLE_PLATFORMS", "APP_BOOTSTRAP_LISTENER", "APP_ID", "APP_INITIALIZER", @@ -661,4 +660,4 @@ "ɵɵproperty", "ɵɵtemplate", "ɵɵtext" -] +] \ No newline at end of file diff --git a/packages/core/test/bundling/forms_template_driven/bundle.golden_symbols.json b/packages/core/test/bundling/forms_template_driven/bundle.golden_symbols.json index 68d3a4742b8..38703c3ef1e 100644 --- a/packages/core/test/bundling/forms_template_driven/bundle.golden_symbols.json +++ b/packages/core/test/bundling/forms_template_driven/bundle.golden_symbols.json @@ -1,5 +1,4 @@ [ - "ALLOW_MULTIPLE_PLATFORMS", "APP_BOOTSTRAP_LISTENER", "APP_ID", "APP_INITIALIZER", @@ -661,4 +660,4 @@ "ɵɵtext", "ɵɵtwoWayListener", "ɵɵtwoWayProperty" -] +] \ No newline at end of file diff --git a/packages/platform-browser/src/browser.ts b/packages/platform-browser/src/browser.ts index 117e5b60dcf..c5b071b1f4b 100644 --- a/packages/platform-browser/src/browser.ts +++ b/packages/platform-browser/src/browser.ts @@ -62,6 +62,19 @@ import {RuntimeErrorCode} from './errors'; type ApplicationConfig = ApplicationConfigFromCore; export {ApplicationConfig}; +/** + * A context object that can be passed to `bootstrapApplication` to provide a pre-existing platform + * injector. + * + * @publicApi + */ +export interface BootstrapContext { + /** + * A reference to a platform. + */ + platformRef: PlatformRef; +} + /** * Bootstraps an instance of an Angular application and renders a standalone component as the * application's root component. More information about standalone components can be found in [this @@ -117,6 +130,9 @@ export {ApplicationConfig}; * @param rootComponent A reference to a standalone component that should be rendered. * @param options Extra configuration for the bootstrap operation, see `ApplicationConfig` for * additional info. + * @param context Optional context object that can be used to provide a pre-existing + * platform injector. This is useful for advanced use-cases, for example, server-side + * rendering, where the platform is created for each request. * @returns A promise that returns an `ApplicationRef` instance once resolved. * * @publicApi @@ -124,8 +140,13 @@ export {ApplicationConfig}; export function bootstrapApplication( rootComponent: Type, options?: ApplicationConfig, + context?: BootstrapContext, ): Promise { - return internalCreateApplication({rootComponent, ...createProvidersConfig(options)}); + return internalCreateApplication({ + rootComponent, + platformRef: context?.platformRef, + ...createProvidersConfig(options), + }); } /** @@ -140,7 +161,7 @@ export function bootstrapApplication( * * @publicApi */ -export function createApplication(options?: ApplicationConfig) { +export function createApplication(options?: ApplicationConfig): Promise { return internalCreateApplication(createProvidersConfig(options)); } diff --git a/packages/platform-browser/src/platform-browser.ts b/packages/platform-browser/src/platform-browser.ts index 34cef910a00..2e2a928477c 100644 --- a/packages/platform-browser/src/platform-browser.ts +++ b/packages/platform-browser/src/platform-browser.ts @@ -9,6 +9,7 @@ export { ApplicationConfig, bootstrapApplication, + BootstrapContext, BrowserModule, createApplication, platformBrowser, diff --git a/packages/platform-server/src/server.ts b/packages/platform-server/src/server.ts index b9ed814208d..f48b14f69c5 100644 --- a/packages/platform-server/src/server.ts +++ b/packages/platform-server/src/server.ts @@ -26,7 +26,6 @@ import { Provider, StaticProvider, Testability, - ɵALLOW_MULTIPLE_PLATFORMS as ALLOW_MULTIPLE_PLATFORMS, ɵsetDocument, ɵTESTABILITY as TESTABILITY, } from '@angular/core'; @@ -54,8 +53,6 @@ export const INTERNAL_SERVER_PLATFORM_PROVIDERS: StaticProvider[] = [ deps: [DOCUMENT, [Optional, INITIAL_CONFIG]], }, {provide: PlatformState, deps: [DOCUMENT]}, - // Add special provider that allows multiple instances of platformServer* to be created. - {provide: ALLOW_MULTIPLE_PLATFORMS, useValue: true}, ]; function initDominoAdapter(injector: Injector) { @@ -113,6 +110,13 @@ function _document(injector: Injector) { } /** + * Creates a server-side instance of an Angular platform. + * + * This platform should be used when performing server-side rendering of an Angular application. + * Standalone applications can be bootstrapped on the server using the `bootstrapApplication` + * function from `@angular/platform-browser`. When using `bootstrapApplication`, the `platformServer` + * should be created first and passed to the bootstrap function using the `BootstrapContext`. + * * @publicApi */ export function platformServer(extraProviders?: StaticProvider[] | undefined): PlatformRef { diff --git a/packages/platform-server/src/utils.ts b/packages/platform-server/src/utils.ts index aee7fe5c936..92baf0b6038 100644 --- a/packages/platform-server/src/utils.ts +++ b/packages/platform-server/src/utils.ts @@ -22,9 +22,10 @@ import { ɵstartMeasuring as startMeasuring, ɵstopMeasuring as stopMeasuring, } from '@angular/core'; +import {BootstrapContext} from '@angular/platform-browser'; -import {PlatformState} from './platform_state'; import {platformServer} from './server'; +import {PlatformState} from './platform_state'; import {BEFORE_APP_SERIALIZED, INITIAL_CONFIG} from './tokens'; import {createScript} from './transfer_state'; @@ -291,14 +292,24 @@ export async function renderModule( /** * Bootstraps an instance of an Angular application and renders it to a string. - + * + * @usageNotes + * * ```ts - * const bootstrap = () => bootstrapApplication(RootComponent, appConfig); - * const output: string = await renderApplication(bootstrap); + * import { BootstrapContext, bootstrapApplication } from '@angular/platform-browser'; + * import { renderApplication } from '@angular/platform-server'; + * import { ApplicationConfig } from '@angular/core'; + * import { AppComponent } from './app.component'; + * + * const appConfig: ApplicationConfig = { providers: [...] }; + * const bootstrap = (context: BootstrapContext) => + * bootstrapApplication(AppComponent, config, context); + * const output = await renderApplication(bootstrap); * ``` * * @param bootstrap A method that when invoked returns a promise that returns an `ApplicationRef` - * instance once resolved. + * instance once resolved. The method is invoked with an `Injector` instance that + * provides access to the platform-level dependency injection context. * @param options Additional configuration for the render operation: * - `document` - the document of the page to render, either as an HTML string or * as a reference to the `document` instance. @@ -309,8 +320,8 @@ export async function renderModule( * * @publicApi */ -export async function renderApplication( - bootstrap: () => Promise, +export async function renderApplication( + bootstrap: (context: BootstrapContext) => Promise, options: {document?: string | Document; url?: string; platformProviders?: Provider[]}, ): Promise { const renderAppLabel = 'renderApplication'; @@ -321,7 +332,7 @@ export async function renderApplication( const platformRef = createServerPlatform(options); try { startMeasuring(bootstrapLabel); - const applicationRef = await bootstrap(); + const applicationRef = await bootstrap({platformRef}); stopMeasuring(bootstrapLabel); startMeasuring(_renderLabel); diff --git a/packages/platform-server/test/hydration_utils.ts b/packages/platform-server/test/hydration_utils.ts index d070d7c4746..bbfdf73e832 100644 --- a/packages/platform-server/test/hydration_utils.ts +++ b/packages/platform-server/test/hydration_utils.ts @@ -20,6 +20,7 @@ import { } from '@angular/core'; import { bootstrapApplication, + BootstrapContext, HydrationFeature, provideClientHydration, HydrationFeatureKind, @@ -263,7 +264,8 @@ export async function ssr( enableHydration ? provideClientHydration(...hydrationFeatures()) : [], ]; - const bootstrap = () => bootstrapApplication(component, {providers}); + const bootstrap = (context: BootstrapContext) => + bootstrapApplication(component, {providers}, context); return await renderApplication(bootstrap, { document: options?.doc ?? defaultHtml, diff --git a/packages/platform-server/test/integration_spec.ts b/packages/platform-server/test/integration_spec.ts index 3814a878cdf..e64fc3121e7 100644 --- a/packages/platform-server/test/integration_spec.ts +++ b/packages/platform-server/test/integration_spec.ts @@ -49,6 +49,7 @@ import { import {TestBed} from '@angular/core/testing'; import { bootstrapApplication, + BootstrapContext, BrowserModule, provideClientHydration, Title, @@ -75,8 +76,9 @@ const APP_CONFIG: ApplicationConfig = { function getStandaloneBootstrapFn( component: Type, providers: Array = [], -): () => Promise { - return () => bootstrapApplication(component, mergeApplicationConfig(APP_CONFIG, {providers})); +): (context: BootstrapContext) => Promise { + return (context: BootstrapContext) => + bootstrapApplication(component, mergeApplicationConfig(APP_CONFIG, {providers}), context); } function createMyServerApp(standalone: boolean) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 101592bb126..a481e12be4e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,7 +16,7 @@ importers: dependencies: '@angular-devkit/build-angular': specifier: 19.2.0-next.2 - version: 19.2.0-next.2(@angular/compiler-cli@19.2.13)(@angular/compiler@19.2.13)(@angular/ssr@19.2.0-next.2)(@types/node@18.19.84)(chokidar@4.0.3)(karma@6.4.4)(protractor@7.0.0)(tsx@4.19.3)(typescript@5.8.2)(vite@6.1.0) + version: 19.2.0-next.2(@angular/compiler-cli@19.2.14)(@angular/compiler@19.2.14)(@angular/ssr@19.2.0-next.2)(@types/node@18.19.84)(chokidar@4.0.3)(karma@6.4.4)(protractor@7.0.0)(tsx@4.19.3)(typescript@5.8.2)(vite@6.1.0) '@angular-devkit/core': specifier: 19.2.0-next.2 version: 19.2.0-next.2(chokidar@4.0.3) @@ -25,19 +25,19 @@ importers: version: 19.2.0-next.2(chokidar@4.0.3) '@angular/build': specifier: 19.2.0-next.2 - version: 19.2.0-next.2(@angular/compiler-cli@19.2.13)(@angular/compiler@19.2.13)(@angular/ssr@19.2.0-next.2)(@types/node@18.19.84)(chokidar@4.0.3)(less@4.2.2)(postcss@8.5.2)(terser@5.39.0)(tsx@4.19.3)(typescript@5.8.2) + version: 19.2.0-next.2(@angular/compiler-cli@19.2.14)(@angular/compiler@19.2.14)(@angular/ssr@19.2.0-next.2)(@types/node@18.19.84)(chokidar@4.0.3)(less@4.2.2)(postcss@8.5.2)(terser@5.39.0)(tsx@4.19.3)(typescript@5.8.2) '@angular/cdk': specifier: 19.2.0-next.4 - version: 19.2.0-next.4(@angular/common@19.2.13)(@angular/core@19.2.11)(rxjs@7.8.2) + version: 19.2.0-next.4(@angular/core@19.2.11)(rxjs@7.8.2) '@angular/cli': specifier: 19.2.0-next.2 version: 19.2.0-next.2(@types/node@18.19.84)(chokidar@4.0.3) '@angular/material': specifier: 19.2.0-next.4 - version: 19.2.0-next.4(@angular/cdk@19.2.0-next.4)(@angular/common@19.2.13)(@angular/core@19.2.11)(@angular/forms@19.2.13)(@angular/platform-browser@19.2.13)(rxjs@7.8.2) + version: 19.2.0-next.4(@angular/cdk@19.2.0-next.4)(@angular/core@19.2.11)(@angular/forms@20.2.4)(@angular/platform-browser@20.2.4)(rxjs@7.8.2) '@angular/ssr': specifier: 19.2.0-next.2 - version: 19.2.0-next.2(@angular/common@19.2.13)(@angular/core@19.2.11)(@angular/router@19.2.13) + version: 19.2.0-next.2(@angular/core@19.2.11)(@angular/router@19.2.14) '@babel/cli': specifier: 7.26.4 version: 7.26.4(@babel/core@7.26.9) @@ -250,10 +250,10 @@ importers: version: 2.0.1 ngx-flamegraph: specifier: 0.0.12 - version: 0.0.12(@angular/common@19.2.13)(@angular/core@19.2.11) + version: 0.0.12(@angular/core@19.2.11) ngx-progressbar: specifier: ^14.0.0 - version: 14.0.0(@angular/cdk@19.2.0-next.4)(@angular/common@19.2.13)(@angular/core@19.2.11)(rxjs@7.8.2) + version: 14.0.0(@angular/cdk@19.2.0-next.4)(@angular/core@19.2.11)(rxjs@7.8.2) open-in-idx: specifier: ^0.1.1 version: 0.1.1 @@ -347,10 +347,10 @@ importers: version: 0.1902.0-next.2(chokidar@4.0.3) '@angular/animations': specifier: ^19.2.0-next - version: 19.2.11(@angular/common@19.2.13)(@angular/core@19.2.11) + version: 19.2.11(@angular/core@19.2.11) '@angular/build-tooling': specifier: https://github.com/angular/dev-infra-private-build-tooling-builds.git#5db176c0f3211663830fd3ff4064c1dff0eaccb4 - version: github.com/angular/dev-infra-private-build-tooling-builds/5db176c0f3211663830fd3ff4064c1dff0eaccb4(@angular/compiler-cli@19.2.13)(@angular/compiler@19.2.13)(@angular/ssr@19.2.0-next.2)(chokidar@4.0.3)(karma-chrome-launcher@3.2.0)(karma-firefox-launcher@2.1.3)(karma-jasmine@5.1.0)(karma-junit-reporter@2.0.1)(karma-requirejs@1.1.0)(karma-sourcemap-loader@0.4.0)(karma@6.4.4)(less@4.2.2)(postcss@8.5.2)(rxjs@7.8.2)(terser@5.39.0)(tsx@4.19.3) + version: github.com/angular/dev-infra-private-build-tooling-builds/5db176c0f3211663830fd3ff4064c1dff0eaccb4(@angular/compiler-cli@19.2.14)(@angular/compiler@19.2.14)(@angular/ssr@19.2.0-next.2)(chokidar@4.0.3)(karma-chrome-launcher@3.2.0)(karma-firefox-launcher@2.1.3)(karma-jasmine@5.1.0)(karma-junit-reporter@2.0.1)(karma-requirejs@1.1.0)(karma-sourcemap-loader@0.4.0)(karma@6.4.4)(less@4.2.2)(postcss@8.5.2)(rxjs@7.8.2)(terser@5.39.0)(tsx@4.19.3) '@angular/core': specifier: ^19.2.0-next version: 19.2.11(rxjs@7.8.2) @@ -452,7 +452,7 @@ importers: version: 0.5.16 angular-split: specifier: ^19.0.0 - version: 19.0.0(@angular/common@19.2.13)(@angular/core@19.2.11)(rxjs@7.8.2) + version: 19.0.0(@angular/core@19.2.11)(rxjs@7.8.2) check-side-effects: specifier: 0.0.23 version: 0.0.23 @@ -800,7 +800,7 @@ packages: transitivePeerDependencies: - chokidar - /@angular-devkit/build-angular@19.2.0-next.2(@angular/compiler-cli@19.2.13)(@angular/compiler@19.2.13)(@angular/ssr@19.2.0-next.2)(@types/node@18.19.84)(chokidar@4.0.3)(karma@6.4.4)(protractor@7.0.0)(tsx@4.19.3)(typescript@5.8.2)(vite@6.1.0): + /@angular-devkit/build-angular@19.2.0-next.2(@angular/compiler-cli@19.2.14)(@angular/compiler@19.2.14)(@angular/ssr@19.2.0-next.2)(@types/node@18.19.84)(chokidar@4.0.3)(karma@6.4.4)(protractor@7.0.0)(tsx@4.19.3)(typescript@5.8.2)(vite@6.1.0): resolution: {integrity: sha512-o3/X02x4p9pCVaPB4uoc2VUL2s2YvGW58jfSHRhwtiLVoIgpnbyHyyhtIdO8rLRr09Pk1fLUvXVY4/d6hjXt1Q==, tarball: https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-19.2.0-next.2.tgz} engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} peerDependencies: @@ -848,9 +848,9 @@ packages: '@angular-devkit/architect': 0.1902.0-next.2(chokidar@4.0.3) '@angular-devkit/build-webpack': 0.1902.0-next.2(chokidar@4.0.3)(webpack-dev-server@5.2.0)(webpack@5.97.1) '@angular-devkit/core': 19.2.0-next.2(chokidar@4.0.3) - '@angular/build': 19.2.0-next.2(@angular/compiler-cli@19.2.13)(@angular/compiler@19.2.13)(@angular/ssr@19.2.0-next.2)(@types/node@18.19.84)(chokidar@4.0.3)(less@4.2.2)(postcss@8.5.2)(terser@5.38.2)(tsx@4.19.3)(typescript@5.8.2) - '@angular/compiler-cli': 19.2.13(@angular/compiler@19.2.13)(typescript@5.8.2) - '@angular/ssr': 19.2.0-next.2(@angular/common@19.2.13)(@angular/core@19.2.11)(@angular/router@19.2.13) + '@angular/build': 19.2.0-next.2(@angular/compiler-cli@19.2.14)(@angular/compiler@19.2.14)(@angular/ssr@19.2.0-next.2)(@types/node@18.19.84)(chokidar@4.0.3)(less@4.2.2)(postcss@8.5.2)(terser@5.38.2)(tsx@4.19.3)(typescript@5.8.2) + '@angular/compiler-cli': 19.2.14(@angular/compiler@19.2.14)(typescript@5.8.2) + '@angular/ssr': 19.2.0-next.2(@angular/core@19.2.11)(@angular/router@19.2.14) '@babel/core': 7.26.8 '@babel/generator': 7.26.8 '@babel/helper-annotate-as-pure': 7.25.9 @@ -861,7 +861,7 @@ packages: '@babel/preset-env': 7.26.8(@babel/core@7.26.8) '@babel/runtime': 7.26.7 '@discoveryjs/json-ext': 0.6.3 - '@ngtools/webpack': 19.2.0-next.2(@angular/compiler-cli@19.2.13)(typescript@5.8.2)(webpack@5.97.1) + '@ngtools/webpack': 19.2.0-next.2(@angular/compiler-cli@19.2.14)(typescript@5.8.2)(webpack@5.97.1) '@vitejs/plugin-basic-ssl': 1.2.0(vite@6.1.0) ansi-colors: 4.1.3 autoprefixer: 10.4.20(postcss@8.5.2) @@ -1004,14 +1004,13 @@ packages: - chokidar dev: false - /@angular/animations@19.2.11(@angular/common@19.2.13)(@angular/core@19.2.11): + /@angular/animations@19.2.11(@angular/core@19.2.11): resolution: {integrity: sha512-NR33bZVho7EgTc1fmCnmkwc2/U266n311Wfvk7VVtz+0Q9WliNdDLBon654V8IWSKvlqKXyU3W+fp0VjH/FvSw==, tarball: https://registry.npmjs.org/@angular/animations/-/animations-19.2.11.tgz} engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} peerDependencies: '@angular/common': 19.2.11 '@angular/core': 19.2.11 dependencies: - '@angular/common': 19.2.13(@angular/core@19.2.11)(rxjs@7.8.2) '@angular/core': 19.2.11(rxjs@7.8.2) tslib: 2.8.1 @@ -1025,7 +1024,7 @@ packages: - zone.js dev: true - /@angular/build@19.1.0-rc.0(@angular/compiler-cli@19.2.13)(@angular/compiler@19.2.13)(@angular/ssr@19.2.0-next.2)(@types/node@18.19.84)(chokidar@4.0.3)(less@4.2.2)(postcss@8.5.2)(terser@5.39.0)(tsx@4.19.3)(typescript@5.7.3): + /@angular/build@19.1.0-rc.0(@angular/compiler-cli@19.2.14)(@angular/compiler@19.2.14)(@angular/ssr@19.2.0-next.2)(@types/node@18.19.84)(chokidar@4.0.3)(less@4.2.2)(postcss@8.5.2)(terser@5.39.0)(tsx@4.19.3)(typescript@5.7.3): resolution: {integrity: sha512-ALl+MVMYBF+E7HyAQ+1MtE6sNIOAX0o2Sfs0wdIQfM2unRl6jPsz/Ker4BjnNQIK4wRCcstyzBv5mZBDulfFIQ==, tarball: https://registry.npmjs.org/@angular/build/-/build-19.1.0-rc.0.tgz} engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} peerDependencies: @@ -1060,9 +1059,9 @@ packages: dependencies: '@ampproject/remapping': 2.3.0 '@angular-devkit/architect': 0.1901.0-rc.0(chokidar@4.0.3) - '@angular/compiler': 19.2.13 - '@angular/compiler-cli': 19.2.13(@angular/compiler@19.2.13)(typescript@5.8.2) - '@angular/ssr': 19.2.0-next.2(@angular/common@19.2.13)(@angular/core@19.2.11)(@angular/router@19.2.13) + '@angular/compiler': 19.2.14 + '@angular/compiler-cli': 19.2.14(@angular/compiler@19.2.14)(typescript@5.8.2) + '@angular/ssr': 19.2.0-next.2(@angular/core@19.2.11)(@angular/router@19.2.14) '@babel/core': 7.26.0 '@babel/helper-annotate-as-pure': 7.25.9 '@babel/helper-split-export-declaration': 7.24.7 @@ -1105,7 +1104,7 @@ packages: - yaml dev: true - /@angular/build@19.2.0-next.2(@angular/compiler-cli@19.2.13)(@angular/compiler@19.2.13)(@angular/ssr@19.2.0-next.2)(@types/node@18.19.84)(chokidar@4.0.3)(less@4.2.2)(postcss@8.5.2)(terser@5.38.2)(tsx@4.19.3)(typescript@5.8.2): + /@angular/build@19.2.0-next.2(@angular/compiler-cli@19.2.14)(@angular/compiler@19.2.14)(@angular/ssr@19.2.0-next.2)(@types/node@18.19.84)(chokidar@4.0.3)(less@4.2.2)(postcss@8.5.2)(terser@5.38.2)(tsx@4.19.3)(typescript@5.8.2): resolution: {integrity: sha512-FmpJla0+M+BE1bQbHIKbl5wKrHsSg6JTIl+kiW/kW4GKKZsS4FJkg56UhyI7+bjuId9s3wptpdMIFpRDaDytRg==, tarball: https://registry.npmjs.org/@angular/build/-/build-19.2.0-next.2.tgz} engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} peerDependencies: @@ -1140,9 +1139,9 @@ packages: dependencies: '@ampproject/remapping': 2.3.0 '@angular-devkit/architect': 0.1902.0-next.2(chokidar@4.0.3) - '@angular/compiler': 19.2.13 - '@angular/compiler-cli': 19.2.13(@angular/compiler@19.2.13)(typescript@5.8.2) - '@angular/ssr': 19.2.0-next.2(@angular/common@19.2.13)(@angular/core@19.2.11)(@angular/router@19.2.13) + '@angular/compiler': 19.2.14 + '@angular/compiler-cli': 19.2.14(@angular/compiler@19.2.14)(typescript@5.8.2) + '@angular/ssr': 19.2.0-next.2(@angular/core@19.2.11)(@angular/router@19.2.14) '@babel/core': 7.26.8 '@babel/helper-annotate-as-pure': 7.25.9 '@babel/helper-split-export-declaration': 7.24.7 @@ -1185,7 +1184,7 @@ packages: - yaml dev: false - /@angular/build@19.2.0-next.2(@angular/compiler-cli@19.2.13)(@angular/compiler@19.2.13)(@angular/ssr@19.2.0-next.2)(@types/node@18.19.84)(chokidar@4.0.3)(less@4.2.2)(postcss@8.5.2)(terser@5.39.0)(tsx@4.19.3)(typescript@5.8.2): + /@angular/build@19.2.0-next.2(@angular/compiler-cli@19.2.14)(@angular/compiler@19.2.14)(@angular/ssr@19.2.0-next.2)(@types/node@18.19.84)(chokidar@4.0.3)(less@4.2.2)(postcss@8.5.2)(terser@5.39.0)(tsx@4.19.3)(typescript@5.8.2): resolution: {integrity: sha512-FmpJla0+M+BE1bQbHIKbl5wKrHsSg6JTIl+kiW/kW4GKKZsS4FJkg56UhyI7+bjuId9s3wptpdMIFpRDaDytRg==, tarball: https://registry.npmjs.org/@angular/build/-/build-19.2.0-next.2.tgz} engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} peerDependencies: @@ -1220,9 +1219,9 @@ packages: dependencies: '@ampproject/remapping': 2.3.0 '@angular-devkit/architect': 0.1902.0-next.2(chokidar@4.0.3) - '@angular/compiler': 19.2.13 - '@angular/compiler-cli': 19.2.13(@angular/compiler@19.2.13)(typescript@5.8.2) - '@angular/ssr': 19.2.0-next.2(@angular/common@19.2.13)(@angular/core@19.2.11)(@angular/router@19.2.13) + '@angular/compiler': 19.2.14 + '@angular/compiler-cli': 19.2.14(@angular/compiler@19.2.14)(typescript@5.8.2) + '@angular/ssr': 19.2.0-next.2(@angular/core@19.2.11)(@angular/router@19.2.14) '@babel/core': 7.26.8 '@babel/helper-annotate-as-pure': 7.25.9 '@babel/helper-split-export-declaration': 7.24.7 @@ -1265,14 +1264,13 @@ packages: - yaml dev: false - /@angular/cdk@19.2.0-next.4(@angular/common@19.2.13)(@angular/core@19.2.11)(rxjs@7.8.2): + /@angular/cdk@19.2.0-next.4(@angular/core@19.2.11)(rxjs@7.8.2): resolution: {integrity: sha512-fmmwokyT2IGLRGzQEj2j4EoQBNdML+QYKyH3J3KlGN7i3p3G63uitzrvz5sEAdsXnpebxemhAs9aPW+HPhsvew==, tarball: https://registry.npmjs.org/@angular/cdk/-/cdk-19.2.0-next.4.tgz} peerDependencies: '@angular/common': ^19.0.0-0 || ^19.1.0-0 || ^19.2.0-0 || ^19.3.0-0 || ^20.0.0-0 '@angular/core': ^19.0.0-0 || ^19.1.0-0 || ^19.2.0-0 || ^19.3.0-0 || ^20.0.0-0 rxjs: ^6.5.3 || ^7.4.0 dependencies: - '@angular/common': 19.2.13(@angular/core@19.2.11)(rxjs@7.8.2) '@angular/core': 19.2.11(rxjs@7.8.2) rxjs: 7.8.2 tslib: 2.8.1 @@ -1308,26 +1306,15 @@ packages: - supports-color dev: false - /@angular/common@19.2.13(@angular/core@19.2.11)(rxjs@7.8.2): - resolution: {integrity: sha512-k7I4bLH+bgI02VL81MaL0NcZPfVl153KAiARwk+ZlkmQjMnWlmsAHQ6054SWoNEXwP855ATR6YYDVqJh8TZaqw==, tarball: https://registry.npmjs.org/@angular/common/-/common-19.2.13.tgz} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} - peerDependencies: - '@angular/core': 19.2.13 - rxjs: ^6.5.3 || ^7.4.0 - dependencies: - '@angular/core': 19.2.11(rxjs@7.8.2) - rxjs: 7.8.2 - tslib: 2.8.1 - - /@angular/compiler-cli@19.2.13(@angular/compiler@19.2.13)(typescript@5.8.2): - resolution: {integrity: sha512-SSuzKMcktvd6VexivDwhP7ctQBD6yyoo5E91I7Frn5nrvYNM+TIyYcXmJ4dgby5/GrPZGfm2sWl3ARr2vbCgtA==, tarball: https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-19.2.13.tgz} + /@angular/compiler-cli@19.2.14(@angular/compiler@19.2.14)(typescript@5.8.2): + resolution: {integrity: sha512-e9/h86ETjoIK2yTLE9aUeMCKujdg/du2pq7run/aINjop4RtnNOw+ZlSTUa6R65lP5CVwDup1kPytpAoifw8cA==, tarball: https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-19.2.14.tgz} engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} hasBin: true peerDependencies: - '@angular/compiler': 19.2.13 + '@angular/compiler': 19.2.14 typescript: '>=5.5 <5.9' dependencies: - '@angular/compiler': 19.2.13 + '@angular/compiler': 19.2.14 '@babel/core': 7.26.9 '@jridgewell/sourcemap-codec': 1.5.0 chokidar: 4.0.3 @@ -1340,8 +1327,8 @@ packages: transitivePeerDependencies: - supports-color - /@angular/compiler@19.2.13: - resolution: {integrity: sha512-xAj1peVrQtb65NsULmz8ocH4QZ4ESG5YiiVzJ0tLz8t280xY+QhJiM6C0+jaCVHLXvZp0c7GEzsYjL6x1HmabQ==, tarball: https://registry.npmjs.org/@angular/compiler/-/compiler-19.2.13.tgz} + /@angular/compiler@19.2.14: + resolution: {integrity: sha512-ZqJDYOdhgKpVGNq3+n/Gbxma8DVYElDsoRe0tvNtjkWBVdaOxdZZUqmJ3kdCBsqD/aqTRvRBu0KGo9s2fCChkA==, tarball: https://registry.npmjs.org/@angular/compiler/-/compiler-19.2.14.tgz} engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} dependencies: tslib: 2.8.1 @@ -1367,23 +1354,22 @@ packages: rxjs: 7.8.2 tslib: 2.8.1 - /@angular/forms@19.2.13(@angular/common@19.2.13)(@angular/core@19.2.11)(@angular/platform-browser@19.2.13)(rxjs@7.8.2): - resolution: {integrity: sha512-g46KQFrBJhmknczlGEYvWVsPhk7ZI8WOuWkzWEl81Lf3ojEVA/OF8w4VwKZL7wOMKRxOUhuYq6tNPm8tBjtryw==, tarball: https://registry.npmjs.org/@angular/forms/-/forms-19.2.13.tgz} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + /@angular/forms@20.2.4(@angular/core@19.2.11)(@angular/platform-browser@20.2.4)(rxjs@7.8.2): + resolution: {integrity: sha512-wbgnW+GALVAmK6hgFegkwlHKw35onvh9Z5A236HCyUySEAOiaD/3CoDg5Hw4iHQAiSU6Fn2NwDiv+W0xki6WDw==, tarball: https://registry.npmjs.org/@angular/forms/-/forms-20.2.4.tgz} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/common': 19.2.13 - '@angular/core': 19.2.13 - '@angular/platform-browser': 19.2.13 + '@angular/common': 20.2.4 + '@angular/core': 20.2.4 + '@angular/platform-browser': 20.2.4 rxjs: ^6.5.3 || ^7.4.0 dependencies: - '@angular/common': 19.2.13(@angular/core@19.2.11)(rxjs@7.8.2) '@angular/core': 19.2.11(rxjs@7.8.2) - '@angular/platform-browser': 19.2.13(@angular/animations@19.2.11)(@angular/common@19.2.13)(@angular/core@19.2.11) + '@angular/platform-browser': 20.2.4(@angular/animations@19.2.11)(@angular/core@19.2.11) rxjs: 7.8.2 tslib: 2.8.1 dev: false - /@angular/material@19.2.0-next.4(@angular/cdk@19.2.0-next.4)(@angular/common@19.2.13)(@angular/core@19.2.11)(@angular/forms@19.2.13)(@angular/platform-browser@19.2.13)(rxjs@7.8.2): + /@angular/material@19.2.0-next.4(@angular/cdk@19.2.0-next.4)(@angular/core@19.2.11)(@angular/forms@20.2.4)(@angular/platform-browser@20.2.4)(rxjs@7.8.2): resolution: {integrity: sha512-darSa77CFdlVFax88GLNJWstHJp8j5qUo/kbQwUNsN0ltigS4o7eaczBA9ukekoSpXSgijq6y2VfnkkYi8hCZQ==, tarball: https://registry.npmjs.org/@angular/material/-/material-19.2.0-next.4.tgz} peerDependencies: '@angular/cdk': 19.2.0-next.4 @@ -1393,47 +1379,44 @@ packages: '@angular/platform-browser': ^19.0.0-0 || ^19.1.0-0 || ^19.2.0-0 || ^19.3.0-0 || ^20.0.0-0 rxjs: ^6.5.3 || ^7.4.0 dependencies: - '@angular/cdk': 19.2.0-next.4(@angular/common@19.2.13)(@angular/core@19.2.11)(rxjs@7.8.2) - '@angular/common': 19.2.13(@angular/core@19.2.11)(rxjs@7.8.2) + '@angular/cdk': 19.2.0-next.4(@angular/core@19.2.11)(rxjs@7.8.2) '@angular/core': 19.2.11(rxjs@7.8.2) - '@angular/forms': 19.2.13(@angular/common@19.2.13)(@angular/core@19.2.11)(@angular/platform-browser@19.2.13)(rxjs@7.8.2) - '@angular/platform-browser': 19.2.13(@angular/animations@19.2.11)(@angular/common@19.2.13)(@angular/core@19.2.11) + '@angular/forms': 20.2.4(@angular/core@19.2.11)(@angular/platform-browser@20.2.4)(rxjs@7.8.2) + '@angular/platform-browser': 20.2.4(@angular/animations@19.2.11)(@angular/core@19.2.11) rxjs: 7.8.2 tslib: 2.8.1 dev: false - /@angular/platform-browser@19.2.13(@angular/animations@19.2.11)(@angular/common@19.2.13)(@angular/core@19.2.11): - resolution: {integrity: sha512-YeuRfGbo8qFepoAUoubk/1079wOown5Qgr9eAhgCXxoXb2rt87xbJF3YCSSim38SP3kK1rJQqP+Sr8n7ef+n5Q==, tarball: https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-19.2.13.tgz} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + /@angular/platform-browser@20.2.4(@angular/animations@19.2.11)(@angular/core@19.2.11): + resolution: {integrity: sha512-81vzW8xhnJU7AiYJKXLR2MuvawzhRDgwyNkPEep58wty5zNuIUCXdUERJSsXo7m/U2Dg1FUFfqLm4RC2UkqLzA==, tarball: https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-20.2.4.tgz} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/animations': 19.2.13 - '@angular/common': 19.2.13 - '@angular/core': 19.2.13 + '@angular/animations': 20.2.4 + '@angular/common': 20.2.4 + '@angular/core': 20.2.4 peerDependenciesMeta: '@angular/animations': optional: true dependencies: - '@angular/animations': 19.2.11(@angular/common@19.2.13)(@angular/core@19.2.11) - '@angular/common': 19.2.13(@angular/core@19.2.11)(rxjs@7.8.2) + '@angular/animations': 19.2.11(@angular/core@19.2.11) '@angular/core': 19.2.11(rxjs@7.8.2) tslib: 2.8.1 - /@angular/router@19.2.13(@angular/common@19.2.13)(@angular/core@19.2.11)(@angular/platform-browser@19.2.13)(rxjs@7.8.2): - resolution: {integrity: sha512-BZObWQtGkDv2WHyLVRRecGbLwalbI8kOXKaVgN5dqP4z/t5bpzYXZixPO9e0E1Ff0+m4tQalhTc84j8X7XZuTw==, tarball: https://registry.npmjs.org/@angular/router/-/router-19.2.13.tgz} + /@angular/router@19.2.14(@angular/core@19.2.11)(@angular/platform-browser@20.2.4)(rxjs@7.8.2): + resolution: {integrity: sha512-cBTWY9Jx7YhbmDYDb7Hqz4Q7UNIMlKTkdKToJd2pbhIXyoS+kHVQrySmyca+jgvYMjWnIjsAEa3dpje12D4mFw==, tarball: https://registry.npmjs.org/@angular/router/-/router-19.2.14.tgz} engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} peerDependencies: - '@angular/common': 19.2.13 - '@angular/core': 19.2.13 - '@angular/platform-browser': 19.2.13 + '@angular/common': 19.2.14 + '@angular/core': 19.2.14 + '@angular/platform-browser': 19.2.14 rxjs: ^6.5.3 || ^7.4.0 dependencies: - '@angular/common': 19.2.13(@angular/core@19.2.11)(rxjs@7.8.2) '@angular/core': 19.2.11(rxjs@7.8.2) - '@angular/platform-browser': 19.2.13(@angular/animations@19.2.11)(@angular/common@19.2.13)(@angular/core@19.2.11) + '@angular/platform-browser': 20.2.4(@angular/animations@19.2.11)(@angular/core@19.2.11) rxjs: 7.8.2 tslib: 2.8.1 - /@angular/ssr@19.2.0-next.2(@angular/common@19.2.13)(@angular/core@19.2.11)(@angular/router@19.2.13): + /@angular/ssr@19.2.0-next.2(@angular/core@19.2.11)(@angular/router@19.2.14): resolution: {integrity: sha512-JN5Utru8xJRpCF+ArG3CCgzlCYgbnB2XUV4J6uO56KgdqK5OeCOCcsuJYBHu+ifaF4ecb74JdXWm0VgB/HQKXA==, tarball: https://registry.npmjs.org/@angular/ssr/-/ssr-19.2.0-next.2.tgz} peerDependencies: '@angular/common': ^19.0.0 || ^19.2.0-next.0 @@ -1444,9 +1427,8 @@ packages: '@angular/platform-server': optional: true dependencies: - '@angular/common': 19.2.13(@angular/core@19.2.11)(rxjs@7.8.2) '@angular/core': 19.2.11(rxjs@7.8.2) - '@angular/router': 19.2.13(@angular/common@19.2.13)(@angular/core@19.2.11)(@angular/platform-browser@19.2.13)(rxjs@7.8.2) + '@angular/router': 19.2.14(@angular/core@19.2.11)(@angular/platform-browser@20.2.4)(rxjs@7.8.2) tslib: 2.8.1 /@antfu/install-pkg@1.0.0: @@ -3826,7 +3808,7 @@ packages: lodash.snakecase: 4.1.1 merge-stream: 2.0.0 p-queue: 6.6.2 - protobufjs: 7.4.0 + protobufjs: 7.5.2 retry-request: 7.0.2(supports-color@10.0.0) split-array-stream: 2.0.0 stack-trace: 0.0.10 @@ -3863,7 +3845,7 @@ packages: dependencies: lodash.camelcase: 4.3.0 long: 5.3.1 - protobufjs: 7.4.0 + protobufjs: 7.5.2 yargs: 17.7.2 dev: true @@ -4653,7 +4635,7 @@ packages: '@napi-rs/nice-win32-x64-msvc': 1.0.1 optional: true - /@ngtools/webpack@19.2.0-next.2(@angular/compiler-cli@19.2.13)(typescript@5.8.2)(webpack@5.97.1): + /@ngtools/webpack@19.2.0-next.2(@angular/compiler-cli@19.2.14)(typescript@5.8.2)(webpack@5.97.1): resolution: {integrity: sha512-YxtR1+YiXjOmaunOIt3CpmEQunV42pbG5pYd/l6Pjqg/83MHxO8h2ax51By/LIzKm6P1qKsGTEtyZBanG7JgGQ==, tarball: https://registry.npmjs.org/@ngtools/webpack/-/webpack-19.2.0-next.2.tgz} engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} peerDependencies: @@ -4661,7 +4643,7 @@ packages: typescript: '>=5.5 <5.8' webpack: ^5.54.0 dependencies: - '@angular/compiler-cli': 19.2.13(@angular/compiler@19.2.13)(typescript@5.8.2) + '@angular/compiler-cli': 19.2.14(@angular/compiler@19.2.14)(typescript@5.8.2) typescript: 5.8.2 webpack: 5.97.1(esbuild@0.25.0) dev: false @@ -7179,14 +7161,13 @@ packages: resolution: {integrity: sha512-vqsT6zwu80cZ8RY7qRQBZuy6Fq5X7/N5hkV9LzNT0c8b546rw4ErGK6muW1u2JnDKYa7+jJuaGM702bWir4HGw==, tarball: https://registry.npmjs.org/angular-mocks/-/angular-mocks-1.8.3.tgz} dev: false - /angular-split@19.0.0(@angular/common@19.2.13)(@angular/core@19.2.11)(rxjs@7.8.2): + /angular-split@19.0.0(@angular/core@19.2.11)(rxjs@7.8.2): resolution: {integrity: sha512-vQqXWLcCimFmInu2lpGKIfS9FtYBgKmoWenPjeYkHSRdWmb7HLGlQoNPj1oALrwdhIWFPdySgp0BIXDe2IAepQ==, tarball: https://registry.npmjs.org/angular-split/-/angular-split-19.0.0.tgz} peerDependencies: '@angular/common': '>=19.0.0' '@angular/core': '>=19.0.0' rxjs: '>=7.0.0' dependencies: - '@angular/common': 19.2.13(@angular/core@19.2.11)(rxjs@7.8.2) '@angular/core': 19.2.11(rxjs@7.8.2) rxjs: 7.8.2 tslib: 2.8.1 @@ -11435,7 +11416,7 @@ packages: node-fetch: 2.7.0 object-hash: 3.0.0 proto3-json-serializer: 2.0.2 - protobufjs: 7.4.0 + protobufjs: 7.5.2 retry-request: 7.0.2(supports-color@10.0.0) uuid: 9.0.1 transitivePeerDependencies: @@ -14329,18 +14310,17 @@ packages: engines: {node: '>= 0.4.0'} dev: true - /ngx-flamegraph@0.0.12(@angular/common@19.2.13)(@angular/core@19.2.11): + /ngx-flamegraph@0.0.12(@angular/core@19.2.11): resolution: {integrity: sha512-YoxrqlL36Bg5Ca9fu10kuSUmaWHAvx7jkxINF4/4cXn9bBPRfu78FqnZ5LIULC0+iScZcSDSWDAnUdn8H7+wGw==, tarball: https://registry.npmjs.org/ngx-flamegraph/-/ngx-flamegraph-0.0.12.tgz} peerDependencies: '@angular/common': ^9.0.0 '@angular/core': ^9.0.0 dependencies: - '@angular/common': 19.2.13(@angular/core@19.2.11)(rxjs@7.8.2) '@angular/core': 19.2.11(rxjs@7.8.2) tslib: 2.8.1 dev: false - /ngx-progressbar@14.0.0(@angular/cdk@19.2.0-next.4)(@angular/common@19.2.13)(@angular/core@19.2.11)(rxjs@7.8.2): + /ngx-progressbar@14.0.0(@angular/cdk@19.2.0-next.4)(@angular/core@19.2.11)(rxjs@7.8.2): resolution: {integrity: sha512-tDj7h5F2aSI4/XaJjs50FnELVe6qFqyz3vVq22acacd3oDW2EyJB4c+IYaxMf5972OdTw0WL4n6UwQ3dqC+gCA==, tarball: https://registry.npmjs.org/ngx-progressbar/-/ngx-progressbar-14.0.0.tgz} peerDependencies: '@angular/cdk': '>=17.3.0' @@ -14348,8 +14328,7 @@ packages: '@angular/core': '>=17.3.0' rxjs: '>=7.0.0' dependencies: - '@angular/cdk': 19.2.0-next.4(@angular/common@19.2.13)(@angular/core@19.2.11)(rxjs@7.8.2) - '@angular/common': 19.2.13(@angular/core@19.2.11)(rxjs@7.8.2) + '@angular/cdk': 19.2.0-next.4(@angular/core@19.2.11)(rxjs@7.8.2) '@angular/core': 19.2.11(rxjs@7.8.2) rxjs: 7.8.2 tslib: 2.8.1 @@ -15517,7 +15496,7 @@ packages: resolution: {integrity: sha512-SAzp/O4Yh02jGdRc+uIrGoe87dkN/XtwxfZ4ZyafJHymd79ozp5VG5nyZ7ygqPM5+cpLDjjGnYFUkngonyDPOQ==, tarball: https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-2.0.2.tgz} engines: {node: '>=14.0.0'} dependencies: - protobufjs: 7.4.0 + protobufjs: 7.5.2 dev: true /protobufjs@6.8.8: @@ -15538,8 +15517,8 @@ packages: '@types/node': 10.17.60 long: 4.0.0 - /protobufjs@7.4.0: - resolution: {integrity: sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==, tarball: https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz} + /protobufjs@7.5.2: + resolution: {integrity: sha512-f2ls6rpO6G153Cy+o2XQ+Y0sARLOZ17+OGVLHrc3VUKcLHYKEKWbkSujdBWQXM7gKn5NTfp0XnRPZn1MIu8n9w==, tarball: https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.2.tgz} engines: {node: '>=12.0.0'} dependencies: '@protobufjs/aspromise': 1.1.2 @@ -15699,6 +15678,7 @@ packages: /puppeteer@24.4.0(typescript@5.8.2): resolution: {integrity: sha512-E4JhJzjS8AAI+6N/b+Utwarhz6zWl3+MR725fal+s3UlOlX2eWdsvYYU+Q5bXMjs9eZEGkNQroLkn7j11s2k1Q==, tarball: https://registry.npmjs.org/puppeteer/-/puppeteer-24.4.0.tgz} engines: {node: '>=18'} + deprecated: < 24.10.2 is no longer supported hasBin: true dependencies: '@puppeteer/browsers': 2.8.0 @@ -19777,14 +19757,14 @@ packages: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==, tarball: https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz} dev: true - github.com/angular/dev-infra-private-build-tooling-builds/5db176c0f3211663830fd3ff4064c1dff0eaccb4(@angular/compiler-cli@19.2.13)(@angular/compiler@19.2.13)(@angular/ssr@19.2.0-next.2)(chokidar@4.0.3)(karma-chrome-launcher@3.2.0)(karma-firefox-launcher@2.1.3)(karma-jasmine@5.1.0)(karma-junit-reporter@2.0.1)(karma-requirejs@1.1.0)(karma-sourcemap-loader@0.4.0)(karma@6.4.4)(less@4.2.2)(postcss@8.5.2)(rxjs@7.8.2)(terser@5.39.0)(tsx@4.19.3): + github.com/angular/dev-infra-private-build-tooling-builds/5db176c0f3211663830fd3ff4064c1dff0eaccb4(@angular/compiler-cli@19.2.14)(@angular/compiler@19.2.14)(@angular/ssr@19.2.0-next.2)(chokidar@4.0.3)(karma-chrome-launcher@3.2.0)(karma-firefox-launcher@2.1.3)(karma-jasmine@5.1.0)(karma-junit-reporter@2.0.1)(karma-requirejs@1.1.0)(karma-sourcemap-loader@0.4.0)(karma@6.4.4)(less@4.2.2)(postcss@8.5.2)(rxjs@7.8.2)(terser@5.39.0)(tsx@4.19.3): resolution: {tarball: https://codeload.github.com/angular/dev-infra-private-build-tooling-builds/tar.gz/5db176c0f3211663830fd3ff4064c1dff0eaccb4} id: github.com/angular/dev-infra-private-build-tooling-builds/5db176c0f3211663830fd3ff4064c1dff0eaccb4 name: '@angular/build-tooling' version: 0.0.0-d44be7e28087c3499d70dda9859d51c1cd3fe1bf dependencies: '@angular/benchpress': 0.3.0(rxjs@7.8.2) - '@angular/build': 19.1.0-rc.0(@angular/compiler-cli@19.2.13)(@angular/compiler@19.2.13)(@angular/ssr@19.2.0-next.2)(@types/node@18.19.84)(chokidar@4.0.3)(less@4.2.2)(postcss@8.5.2)(terser@5.39.0)(tsx@4.19.3)(typescript@5.7.3) + '@angular/build': 19.1.0-rc.0(@angular/compiler-cli@19.2.14)(@angular/compiler@19.2.14)(@angular/ssr@19.2.0-next.2)(@types/node@18.19.84)(chokidar@4.0.3)(less@4.2.2)(postcss@8.5.2)(terser@5.39.0)(tsx@4.19.3)(typescript@5.7.3) '@babel/core': 7.26.10 '@babel/plugin-proposal-async-generator-functions': 7.20.7(@babel/core@7.26.10) '@bazel/buildifier': 6.3.3 diff --git a/tools/npm-patches/@angular+ssr+19.2.0-next.2.patch b/tools/npm-patches/@angular+ssr+19.2.0-next.2.patch new file mode 100644 index 00000000000..7e749b74ff9 --- /dev/null +++ b/tools/npm-patches/@angular+ssr+19.2.0-next.2.patch @@ -0,0 +1,13 @@ +diff --git a/node_modules/@angular/ssr/fesm2022/ssr.mjs b/node_modules/@angular/ssr/fesm2022/ssr.mjs +index 3267e86..1b628be 100755 +--- a/node_modules/@angular/ssr/fesm2022/ssr.mjs ++++ b/node_modules/@angular/ssr/fesm2022/ssr.mjs +@@ -1093,7 +1093,7 @@ async function getRoutesFromAngularRouterConfig(bootstrap, document, url, invoke + applicationRef = moduleRef.injector.get(ApplicationRef); + } + else { +- applicationRef = await bootstrap(); ++ applicationRef = await bootstrap({platformRef}); + } + const injector = applicationRef.injector; + const router = injector.get(Router);