This commit is contained in:
CHEVALLIER Abel
2025-11-13 16:23:22 +01:00
parent de9c515a47
commit cb235644dc
34924 changed files with 3811102 additions and 0 deletions

2067
node_modules/@angular/common/fesm2022/common.mjs generated vendored Executable file

File diff suppressed because it is too large Load Diff

1
node_modules/@angular/common/fesm2022/common.mjs.map generated vendored Executable file

File diff suppressed because one or more lines are too long

4684
node_modules/@angular/common/fesm2022/common_module.mjs generated vendored Executable file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

428
node_modules/@angular/common/fesm2022/http.mjs generated vendored Executable file
View File

@@ -0,0 +1,428 @@
/**
* @license Angular v20.3.11
* (c) 2010-2025 Google LLC. https://angular.dev/
* License: MIT
*/
import { HttpHeaders, HttpParams, HttpRequest, HttpEventType, HttpErrorResponse, HttpClient, HTTP_ROOT_INTERCEPTOR_FNS, HttpResponse } from './module.mjs';
export { FetchBackend, HTTP_INTERCEPTORS, HttpBackend, HttpClientJsonpModule, HttpClientModule, HttpClientXsrfModule, HttpContext, HttpContextToken, HttpFeatureKind, HttpHandler, HttpHeaderResponse, HttpResponseBase, HttpStatusCode, HttpUrlEncodingCodec, HttpXhrBackend, HttpXsrfTokenExtractor, JsonpClientBackend, JsonpInterceptor, provideHttpClient, withFetch, withInterceptors, withInterceptorsFromDi, withJsonpSupport, withNoXsrfProtection, withRequestsMadeViaParent, withXsrfConfiguration, HttpInterceptorHandler as ɵHttpInterceptingHandler, HttpInterceptorHandler as ɵHttpInterceptorHandler, REQUESTS_CONTRIBUTE_TO_STABILITY as ɵREQUESTS_CONTRIBUTE_TO_STABILITY } from './module.mjs';
import { assertInInjectionContext, inject, Injector, ɵResourceImpl as _ResourceImpl, linkedSignal, computed, signal, ɵencapsulateResourceError as _encapsulateResourceError, ɵRuntimeError as _RuntimeError, InjectionToken, ɵperformanceMarkFeature as _performanceMarkFeature, APP_BOOTSTRAP_LISTENER, ApplicationRef, TransferState, makeStateKey, ɵtruncateMiddle as _truncateMiddle, ɵformatRuntimeError as _formatRuntimeError } from '@angular/core';
import { of } from 'rxjs';
import { tap } from 'rxjs/operators';
import './xhr.mjs';
/**
* `httpResource` makes a reactive HTTP request and exposes the request status and response value as
* a `WritableResource`. By default, it assumes that the backend will return JSON data. To make a
* request that expects a different kind of data, you can use a sub-constructor of `httpResource`,
* such as `httpResource.text`.
*
* @experimental 19.2
* @initializerApiFunction
*/
const httpResource = (() => {
const jsonFn = makeHttpResourceFn('json');
jsonFn.arrayBuffer = makeHttpResourceFn('arraybuffer');
jsonFn.blob = makeHttpResourceFn('blob');
jsonFn.text = makeHttpResourceFn('text');
return jsonFn;
})();
function makeHttpResourceFn(responseType) {
return function httpResource(request, options) {
if (ngDevMode && !options?.injector) {
assertInInjectionContext(httpResource);
}
const injector = options?.injector ?? inject(Injector);
return new HttpResourceImpl(injector, () => normalizeRequest(request, responseType), options?.defaultValue, options?.parse, options?.equal);
};
}
function normalizeRequest(request, responseType) {
let unwrappedRequest = typeof request === 'function' ? request() : request;
if (unwrappedRequest === undefined) {
return undefined;
}
else if (typeof unwrappedRequest === 'string') {
unwrappedRequest = { url: unwrappedRequest };
}
const headers = unwrappedRequest.headers instanceof HttpHeaders
? unwrappedRequest.headers
: new HttpHeaders(unwrappedRequest.headers);
const params = unwrappedRequest.params instanceof HttpParams
? unwrappedRequest.params
: new HttpParams({ fromObject: unwrappedRequest.params });
return new HttpRequest(unwrappedRequest.method ?? 'GET', unwrappedRequest.url, unwrappedRequest.body ?? null, {
headers,
params,
reportProgress: unwrappedRequest.reportProgress,
withCredentials: unwrappedRequest.withCredentials,
keepalive: unwrappedRequest.keepalive,
cache: unwrappedRequest.cache,
priority: unwrappedRequest.priority,
mode: unwrappedRequest.mode,
redirect: unwrappedRequest.redirect,
responseType,
context: unwrappedRequest.context,
transferCache: unwrappedRequest.transferCache,
credentials: unwrappedRequest.credentials,
referrer: unwrappedRequest.referrer,
integrity: unwrappedRequest.integrity,
timeout: unwrappedRequest.timeout,
});
}
class HttpResourceImpl extends _ResourceImpl {
client;
_headers = linkedSignal(...(ngDevMode ? [{ debugName: "_headers", source: this.extRequest,
computation: () => undefined }] : [{
source: this.extRequest,
computation: () => undefined,
}]));
_progress = linkedSignal(...(ngDevMode ? [{ debugName: "_progress", source: this.extRequest,
computation: () => undefined }] : [{
source: this.extRequest,
computation: () => undefined,
}]));
_statusCode = linkedSignal(...(ngDevMode ? [{ debugName: "_statusCode", source: this.extRequest,
computation: () => undefined }] : [{
source: this.extRequest,
computation: () => undefined,
}]));
headers = computed(() => this.status() === 'resolved' || this.status() === 'error' ? this._headers() : undefined, ...(ngDevMode ? [{ debugName: "headers" }] : []));
progress = this._progress.asReadonly();
statusCode = this._statusCode.asReadonly();
constructor(injector, request, defaultValue, parse, equal) {
super(request, ({ params: request, abortSignal }) => {
let sub;
// Track the abort listener so it can be removed if the Observable completes (as a memory
// optimization).
const onAbort = () => sub.unsubscribe();
abortSignal.addEventListener('abort', onAbort);
// Start off stream as undefined.
const stream = signal({ value: undefined }, ...(ngDevMode ? [{ debugName: "stream" }] : []));
let resolve;
const promise = new Promise((r) => (resolve = r));
const send = (value) => {
stream.set(value);
resolve?.(stream);
resolve = undefined;
};
sub = this.client.request(request).subscribe({
next: (event) => {
switch (event.type) {
case HttpEventType.Response:
this._headers.set(event.headers);
this._statusCode.set(event.status);
try {
send({ value: parse ? parse(event.body) : event.body });
}
catch (error) {
send({ error: _encapsulateResourceError(error) });
}
break;
case HttpEventType.DownloadProgress:
this._progress.set(event);
break;
}
},
error: (error) => {
if (error instanceof HttpErrorResponse) {
this._headers.set(error.headers);
this._statusCode.set(error.status);
}
send({ error });
abortSignal.removeEventListener('abort', onAbort);
},
complete: () => {
if (resolve) {
send({
error: new _RuntimeError(991 /* ɵRuntimeErrorCode.RESOURCE_COMPLETED_BEFORE_PRODUCING_VALUE */, ngDevMode && 'Resource completed before producing a value'),
});
}
abortSignal.removeEventListener('abort', onAbort);
},
});
return promise;
}, defaultValue, equal, injector);
this.client = injector.get(HttpClient);
}
set(value) {
super.set(value);
this._headers.set(undefined);
this._progress.set(undefined);
this._statusCode.set(undefined);
}
}
/**
* If your application uses different HTTP origins to make API calls (via `HttpClient`) on the server and
* on the client, the `HTTP_TRANSFER_CACHE_ORIGIN_MAP` token allows you to establish a mapping
* between those origins, so that `HttpTransferCache` feature can recognize those requests as the same
* ones and reuse the data cached on the server during hydration on the client.
*
* **Important note**: the `HTTP_TRANSFER_CACHE_ORIGIN_MAP` token should *only* be provided in
* the *server* code of your application (typically in the `app.server.config.ts` script). Angular throws an
* error if it detects that the token is defined while running on the client.
*
* @usageNotes
*
* When the same API endpoint is accessed via `http://internal-domain.com:8080` on the server and
* via `https://external-domain.com` on the client, you can use the following configuration:
* ```ts
* // in app.server.config.ts
* {
* provide: HTTP_TRANSFER_CACHE_ORIGIN_MAP,
* useValue: {
* 'http://internal-domain.com:8080': 'https://external-domain.com'
* }
* }
* ```
*
* @publicApi
*/
const HTTP_TRANSFER_CACHE_ORIGIN_MAP = new InjectionToken(ngDevMode ? 'HTTP_TRANSFER_CACHE_ORIGIN_MAP' : '');
/**
* Keys within cached response data structure.
*/
const BODY = 'b';
const HEADERS = 'h';
const STATUS = 's';
const STATUS_TEXT = 'st';
const REQ_URL = 'u';
const RESPONSE_TYPE = 'rt';
const CACHE_OPTIONS = new InjectionToken(ngDevMode ? 'HTTP_TRANSFER_STATE_CACHE_OPTIONS' : '');
/**
* A list of allowed HTTP methods to cache.
*/
const ALLOWED_METHODS = ['GET', 'HEAD'];
function transferCacheInterceptorFn(req, next) {
const { isCacheActive, ...globalOptions } = inject(CACHE_OPTIONS);
const { transferCache: requestOptions, method: requestMethod } = req;
// In the following situations we do not want to cache the request
if (!isCacheActive ||
requestOptions === false ||
// POST requests are allowed either globally or at request level
(requestMethod === 'POST' && !globalOptions.includePostRequests && !requestOptions) ||
(requestMethod !== 'POST' && !ALLOWED_METHODS.includes(requestMethod)) ||
// Do not cache request that require authorization when includeRequestsWithAuthHeaders is falsey
(!globalOptions.includeRequestsWithAuthHeaders && hasAuthHeaders(req)) ||
globalOptions.filter?.(req) === false) {
return next(req);
}
const transferState = inject(TransferState);
const originMap = inject(HTTP_TRANSFER_CACHE_ORIGIN_MAP, {
optional: true,
});
if (typeof ngServerMode !== 'undefined' && !ngServerMode && originMap) {
throw new _RuntimeError(2803 /* RuntimeErrorCode.HTTP_ORIGIN_MAP_USED_IN_CLIENT */, ngDevMode &&
'Angular detected that the `HTTP_TRANSFER_CACHE_ORIGIN_MAP` token is configured and ' +
'present in the client side code. Please ensure that this token is only provided in the ' +
'server code of the application.');
}
const requestUrl = typeof ngServerMode !== 'undefined' && ngServerMode && originMap
? mapRequestOriginUrl(req.url, originMap)
: req.url;
const storeKey = makeCacheKey(req, requestUrl);
const response = transferState.get(storeKey, null);
let headersToInclude = globalOptions.includeHeaders;
if (typeof requestOptions === 'object' && requestOptions.includeHeaders) {
// Request-specific config takes precedence over the global config.
headersToInclude = requestOptions.includeHeaders;
}
if (response) {
const { [BODY]: undecodedBody, [RESPONSE_TYPE]: responseType, [HEADERS]: httpHeaders, [STATUS]: status, [STATUS_TEXT]: statusText, [REQ_URL]: url, } = response;
// Request found in cache. Respond using it.
let body = undecodedBody;
switch (responseType) {
case 'arraybuffer':
body = new TextEncoder().encode(undecodedBody).buffer;
break;
case 'blob':
body = new Blob([undecodedBody]);
break;
}
// We want to warn users accessing a header provided from the cache
// That HttpTransferCache alters the headers
// The warning will be logged a single time by HttpHeaders instance
let headers = new HttpHeaders(httpHeaders);
if (typeof ngDevMode === 'undefined' || ngDevMode) {
// Append extra logic in dev mode to produce a warning when a header
// that was not transferred to the client is accessed in the code via `get`
// and `has` calls.
headers = appendMissingHeadersDetection(req.url, headers, headersToInclude ?? []);
}
return of(new HttpResponse({
body,
headers,
status,
statusText,
url,
}));
}
const event$ = next(req);
if (typeof ngServerMode !== 'undefined' && ngServerMode) {
// Request not found in cache. Make the request and cache it if on the server.
return event$.pipe(tap((event) => {
// Only cache successful HTTP responses.
if (event instanceof HttpResponse) {
transferState.set(storeKey, {
[BODY]: event.body,
[HEADERS]: getFilteredHeaders(event.headers, headersToInclude),
[STATUS]: event.status,
[STATUS_TEXT]: event.statusText,
[REQ_URL]: requestUrl,
[RESPONSE_TYPE]: req.responseType,
});
}
}));
}
return event$;
}
/** @returns true when the requests contains autorization related headers. */
function hasAuthHeaders(req) {
return req.headers.has('authorization') || req.headers.has('proxy-authorization');
}
function getFilteredHeaders(headers, includeHeaders) {
if (!includeHeaders) {
return {};
}
const headersMap = {};
for (const key of includeHeaders) {
const values = headers.getAll(key);
if (values !== null) {
headersMap[key] = values;
}
}
return headersMap;
}
function sortAndConcatParams(params) {
return [...params.keys()]
.sort()
.map((k) => `${k}=${params.getAll(k)}`)
.join('&');
}
function makeCacheKey(request, mappedRequestUrl) {
// make the params encoded same as a url so it's easy to identify
const { params, method, responseType } = request;
const encodedParams = sortAndConcatParams(params);
let serializedBody = request.serializeBody();
if (serializedBody instanceof URLSearchParams) {
serializedBody = sortAndConcatParams(serializedBody);
}
else if (typeof serializedBody !== 'string') {
serializedBody = '';
}
const key = [method, responseType, mappedRequestUrl, serializedBody, encodedParams].join('|');
const hash = generateHash(key);
return makeStateKey(hash);
}
/**
* A method that returns a hash representation of a string using a variant of DJB2 hash
* algorithm.
*
* This is the same hashing logic that is used to generate component ids.
*/
function generateHash(value) {
let hash = 0;
for (const char of value) {
hash = (Math.imul(31, hash) + char.charCodeAt(0)) << 0;
}
// Force positive number hash.
// 2147483647 = equivalent of Integer.MAX_VALUE.
hash += 2147483647 + 1;
return hash.toString();
}
/**
* Returns the DI providers needed to enable HTTP transfer cache.
*
* By default, when using server rendering, requests are performed twice: once on the server and
* other one on the browser.
*
* When these providers are added, requests performed on the server are cached and reused during the
* bootstrapping of the application in the browser thus avoiding duplicate requests and reducing
* load time.
*
* @see [Caching data when using HttpClient](guide/ssr#configuring-the-caching-options)
*
*/
function withHttpTransferCache(cacheOptions) {
return [
{
provide: CACHE_OPTIONS,
useFactory: () => {
_performanceMarkFeature('NgHttpTransferCache');
return { isCacheActive: true, ...cacheOptions };
},
},
{
provide: HTTP_ROOT_INTERCEPTOR_FNS,
useValue: transferCacheInterceptorFn,
multi: true,
},
{
provide: APP_BOOTSTRAP_LISTENER,
multi: true,
useFactory: () => {
const appRef = inject(ApplicationRef);
const cacheState = inject(CACHE_OPTIONS);
return () => {
appRef.whenStable().then(() => {
cacheState.isCacheActive = false;
});
};
},
},
];
}
/**
* This function will add a proxy to an HttpHeader to intercept calls to get/has
* and log a warning if the header entry requested has been removed
*/
function appendMissingHeadersDetection(url, headers, headersToInclude) {
const warningProduced = new Set();
return new Proxy(headers, {
get(target, prop) {
const value = Reflect.get(target, prop);
const methods = new Set(['get', 'has', 'getAll']);
if (typeof value !== 'function' || !methods.has(prop)) {
return value;
}
return (headerName) => {
// We log when the key has been removed and a warning hasn't been produced for the header
const key = (prop + ':' + headerName).toLowerCase(); // e.g. `get:cache-control`
if (!headersToInclude.includes(headerName) && !warningProduced.has(key)) {
warningProduced.add(key);
const truncatedUrl = _truncateMiddle(url);
console.warn(_formatRuntimeError(-2802 /* RuntimeErrorCode.HEADERS_ALTERED_BY_TRANSFER_CACHE */, `Angular detected that the \`${headerName}\` header is accessed, but the value of the header ` +
`was not transferred from the server to the client by the HttpTransferCache. ` +
`To include the value of the \`${headerName}\` header for the \`${truncatedUrl}\` request, ` +
`use the \`includeHeaders\` list. The \`includeHeaders\` can be defined either ` +
`on a request level by adding the \`transferCache\` parameter, or on an application ` +
`level by adding the \`httpCacheTransfer.includeHeaders\` argument to the ` +
`\`provideClientHydration()\` call. `));
}
// invoking the original method
return value.apply(target, [headerName]);
};
},
});
}
function mapRequestOriginUrl(url, originMap) {
const origin = new URL(url, 'resolve://').origin;
const mappedOrigin = originMap[origin];
if (!mappedOrigin) {
return url;
}
if (typeof ngDevMode === 'undefined' || ngDevMode) {
verifyMappedOrigin(mappedOrigin);
}
return url.replace(origin, mappedOrigin);
}
function verifyMappedOrigin(url) {
if (new URL(url, 'resolve://').pathname !== '/') {
throw new _RuntimeError(2804 /* RuntimeErrorCode.HTTP_ORIGIN_MAP_CONTAINS_PATH */, 'Angular detected a URL with a path segment in the value provided for the ' +
`\`HTTP_TRANSFER_CACHE_ORIGIN_MAP\` token: ${url}. The map should only contain origins ` +
'without any other segments.');
}
}
export { HTTP_TRANSFER_CACHE_ORIGIN_MAP, HttpClient, HttpErrorResponse, HttpEventType, HttpHeaders, HttpParams, HttpRequest, HttpResponse, httpResource, HTTP_ROOT_INTERCEPTOR_FNS as ɵHTTP_ROOT_INTERCEPTOR_FNS, withHttpTransferCache as ɵwithHttpTransferCache };
//# sourceMappingURL=http.mjs.map

1
node_modules/@angular/common/fesm2022/http.mjs.map generated vendored Executable file

File diff suppressed because one or more lines are too long

361
node_modules/@angular/common/fesm2022/http/testing.mjs generated vendored Executable file
View File

@@ -0,0 +1,361 @@
/**
* @license Angular v20.3.11
* (c) 2010-2025 Google LLC. https://angular.dev/
* License: MIT
*/
import * as i0 from '@angular/core';
import { Injectable, NgModule } from '@angular/core';
import { Observable } from 'rxjs';
import { HttpHeaders, HttpResponse, HttpErrorResponse, HttpStatusCode, HttpEventType, HttpBackend, REQUESTS_CONTRIBUTE_TO_STABILITY, HttpClientModule } from '../module.mjs';
import 'rxjs/operators';
import '../xhr.mjs';
/**
* Controller to be injected into tests, that allows for mocking and flushing
* of requests.
*
* @publicApi
*/
class HttpTestingController {
}
/**
* A mock requests that was received and is ready to be answered.
*
* This interface allows access to the underlying `HttpRequest`, and allows
* responding with `HttpEvent`s or `HttpErrorResponse`s.
*
* @publicApi
*/
class TestRequest {
request;
observer;
/**
* Whether the request was cancelled after it was sent.
*/
get cancelled() {
return this._cancelled;
}
/**
* @internal set by `HttpClientTestingBackend`
*/
_cancelled = false;
constructor(request, observer) {
this.request = request;
this.observer = observer;
}
/**
* Resolve the request by returning a body plus additional HTTP information (such as response
* headers) if provided.
* If the request specifies an expected body type, the body is converted into the requested type.
* Otherwise, the body is converted to `JSON` by default.
*
* Both successful and unsuccessful responses can be delivered via `flush()`.
*/
flush(body, opts = {}) {
if (this.cancelled) {
throw new Error(`Cannot flush a cancelled request.`);
}
const url = this.request.urlWithParams;
const headers = opts.headers instanceof HttpHeaders ? opts.headers : new HttpHeaders(opts.headers);
body = _maybeConvertBody(this.request.responseType, body);
let statusText = opts.statusText;
let status = opts.status !== undefined ? opts.status : HttpStatusCode.Ok;
if (opts.status === undefined) {
if (body === null) {
status = HttpStatusCode.NoContent;
statusText ||= 'No Content';
}
else {
statusText ||= 'OK';
}
}
if (statusText === undefined) {
throw new Error('statusText is required when setting a custom status.');
}
if (status >= 200 && status < 300) {
this.observer.next(new HttpResponse({ body, headers, status, statusText, url }));
this.observer.complete();
}
else {
this.observer.error(new HttpErrorResponse({ error: body, headers, status, statusText, url }));
}
}
error(error, opts = {}) {
if (this.cancelled) {
throw new Error(`Cannot return an error for a cancelled request.`);
}
const headers = opts.headers instanceof HttpHeaders ? opts.headers : new HttpHeaders(opts.headers);
this.observer.error(new HttpErrorResponse({
error,
headers,
status: opts.status || 0,
statusText: opts.statusText || '',
url: this.request.urlWithParams,
}));
}
/**
* Deliver an arbitrary `HttpEvent` (such as a progress event) on the response stream for this
* request.
*/
event(event) {
if (this.cancelled) {
throw new Error(`Cannot send events to a cancelled request.`);
}
this.observer.next(event);
}
}
/**
* Helper function to convert a response body to an ArrayBuffer.
*/
function _toArrayBufferBody(body) {
if (typeof ArrayBuffer === 'undefined') {
throw new Error('ArrayBuffer responses are not supported on this platform.');
}
if (body instanceof ArrayBuffer) {
return body;
}
throw new Error('Automatic conversion to ArrayBuffer is not supported for response type.');
}
/**
* Helper function to convert a response body to a Blob.
*/
function _toBlob(body) {
if (typeof Blob === 'undefined') {
throw new Error('Blob responses are not supported on this platform.');
}
if (body instanceof Blob) {
return body;
}
if (ArrayBuffer && body instanceof ArrayBuffer) {
return new Blob([body]);
}
throw new Error('Automatic conversion to Blob is not supported for response type.');
}
/**
* Helper function to convert a response body to JSON data.
*/
function _toJsonBody(body, format = 'JSON') {
if (typeof ArrayBuffer !== 'undefined' && body instanceof ArrayBuffer) {
throw new Error(`Automatic conversion to ${format} is not supported for ArrayBuffers.`);
}
if (typeof Blob !== 'undefined' && body instanceof Blob) {
throw new Error(`Automatic conversion to ${format} is not supported for Blobs.`);
}
if (typeof body === 'string' ||
typeof body === 'number' ||
typeof body === 'object' ||
typeof body === 'boolean' ||
Array.isArray(body)) {
return body;
}
throw new Error(`Automatic conversion to ${format} is not supported for response type.`);
}
/**
* Helper function to convert a response body to a string.
*/
function _toTextBody(body) {
if (typeof body === 'string') {
return body;
}
if (typeof ArrayBuffer !== 'undefined' && body instanceof ArrayBuffer) {
throw new Error('Automatic conversion to text is not supported for ArrayBuffers.');
}
if (typeof Blob !== 'undefined' && body instanceof Blob) {
throw new Error('Automatic conversion to text is not supported for Blobs.');
}
return JSON.stringify(_toJsonBody(body, 'text'));
}
/**
* Convert a response body to the requested type.
*/
function _maybeConvertBody(responseType, body) {
if (body === null) {
return null;
}
switch (responseType) {
case 'arraybuffer':
return _toArrayBufferBody(body);
case 'blob':
return _toBlob(body);
case 'json':
return _toJsonBody(body);
case 'text':
return _toTextBody(body);
default:
throw new Error(`Unsupported responseType: ${responseType}`);
}
}
/**
* A testing backend for `HttpClient` which both acts as an `HttpBackend`
* and as the `HttpTestingController`.
*
* `HttpClientTestingBackend` works by keeping a list of all open requests.
* As requests come in, they're added to the list. Users can assert that specific
* requests were made and then flush them. In the end, a verify() method asserts
* that no unexpected requests were made.
*
*
*/
class HttpClientTestingBackend {
/**
* List of pending requests which have not yet been expected.
*/
open = [];
/**
* Used when checking if we need to throw the NOT_USING_FETCH_BACKEND_IN_SSR error
*/
isTestingBackend = true;
/**
* Handle an incoming request by queueing it in the list of open requests.
*/
handle(req) {
return new Observable((observer) => {
const testReq = new TestRequest(req, observer);
this.open.push(testReq);
observer.next({ type: HttpEventType.Sent });
return () => {
testReq._cancelled = true;
};
});
}
/**
* Helper function to search for requests in the list of open requests.
*/
_match(match) {
if (typeof match === 'string') {
return this.open.filter((testReq) => testReq.request.urlWithParams === match);
}
else if (typeof match === 'function') {
return this.open.filter((testReq) => match(testReq.request));
}
else {
return this.open.filter((testReq) => (!match.method || testReq.request.method === match.method.toUpperCase()) &&
(!match.url || testReq.request.urlWithParams === match.url));
}
}
/**
* Search for requests in the list of open requests, and return all that match
* without asserting anything about the number of matches.
*/
match(match) {
const results = this._match(match);
results.forEach((result) => {
const index = this.open.indexOf(result);
if (index !== -1) {
this.open.splice(index, 1);
}
});
return results;
}
/**
* Expect that a single outstanding request matches the given matcher, and return
* it.
*
* Requests returned through this API will no longer be in the list of open requests,
* and thus will not match twice.
*/
expectOne(match, description) {
description ||= this.descriptionFromMatcher(match);
const matches = this.match(match);
if (matches.length > 1) {
throw new Error(`Expected one matching request for criteria "${description}", found ${matches.length} requests.`);
}
if (matches.length === 0) {
let message = `Expected one matching request for criteria "${description}", found none.`;
if (this.open.length > 0) {
// Show the methods and URLs of open requests in the error, for convenience.
const requests = this.open.map(describeRequest).join(', ');
message += ` Requests received are: ${requests}.`;
}
throw new Error(message);
}
return matches[0];
}
/**
* Expect that no outstanding requests match the given matcher, and throw an error
* if any do.
*/
expectNone(match, description) {
description ||= this.descriptionFromMatcher(match);
const matches = this.match(match);
if (matches.length > 0) {
throw new Error(`Expected zero matching requests for criteria "${description}", found ${matches.length}.`);
}
}
/**
* Validate that there are no outstanding requests.
*/
verify(opts = {}) {
let open = this.open;
// It's possible that some requests may be cancelled, and this is expected.
// The user can ask to ignore open requests which have been cancelled.
if (opts.ignoreCancelled) {
open = open.filter((testReq) => !testReq.cancelled);
}
if (open.length > 0) {
// Show the methods and URLs of open requests in the error, for convenience.
const requests = open.map(describeRequest).join(', ');
throw new Error(`Expected no open requests, found ${open.length}: ${requests}`);
}
}
descriptionFromMatcher(matcher) {
if (typeof matcher === 'string') {
return `Match URL: ${matcher}`;
}
else if (typeof matcher === 'object') {
const method = matcher.method || '(any)';
const url = matcher.url || '(any)';
return `Match method: ${method}, URL: ${url}`;
}
else {
return `Match by function: ${matcher.name}`;
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: HttpClientTestingBackend, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: HttpClientTestingBackend });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: HttpClientTestingBackend, decorators: [{
type: Injectable
}] });
function describeRequest(testRequest) {
const url = testRequest.request.urlWithParams;
const method = testRequest.request.method;
return `${method} ${url}`;
}
function provideHttpClientTesting() {
return [
HttpClientTestingBackend,
{ provide: HttpBackend, useExisting: HttpClientTestingBackend },
{ provide: HttpTestingController, useExisting: HttpClientTestingBackend },
{ provide: REQUESTS_CONTRIBUTE_TO_STABILITY, useValue: false },
];
}
/**
* Configures `HttpClientTestingBackend` as the `HttpBackend` used by `HttpClient`.
*
* Inject `HttpTestingController` to expect and flush requests in your tests.
*
* @publicApi
*
* @deprecated Add `provideHttpClientTesting()` to your providers instead.
*/
class HttpClientTestingModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: HttpClientTestingModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.11", ngImport: i0, type: HttpClientTestingModule, imports: [HttpClientModule] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: HttpClientTestingModule, providers: [provideHttpClientTesting()], imports: [HttpClientModule] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: HttpClientTestingModule, decorators: [{
type: NgModule,
args: [{
imports: [HttpClientModule],
providers: [provideHttpClientTesting()],
}]
}] });
export { HttpClientTestingModule, HttpTestingController, TestRequest, provideHttpClientTesting };
//# sourceMappingURL=testing.mjs.map

1
node_modules/@angular/common/fesm2022/http/testing.mjs.map generated vendored Executable file

File diff suppressed because one or more lines are too long

637
node_modules/@angular/common/fesm2022/location.mjs generated vendored Executable file
View File

@@ -0,0 +1,637 @@
/**
* @license Angular v20.3.11
* (c) 2010-2025 Google LLC. https://angular.dev/
* License: MIT
*/
import * as i0 from '@angular/core';
import { inject, Injectable, InjectionToken, DOCUMENT, Optional, Inject, ɵɵinject as __inject } from '@angular/core';
import { Subject } from 'rxjs';
let _DOM = null;
function getDOM() {
return _DOM;
}
function setRootDomAdapter(adapter) {
_DOM ??= adapter;
}
/**
* Provides DOM operations in an environment-agnostic way.
*
* @security Tread carefully! Interacting with the DOM directly is dangerous and
* can introduce XSS risks.
*/
class DomAdapter {
}
/**
* This class should not be used directly by an application developer. Instead, use
* {@link Location}.
*
* `PlatformLocation` encapsulates all calls to DOM APIs, which allows the Router to be
* platform-agnostic.
* This means that we can have different implementation of `PlatformLocation` for the different
* platforms that Angular supports. For example, `@angular/platform-browser` provides an
* implementation specific to the browser environment, while `@angular/platform-server` provides
* one suitable for use with server-side rendering.
*
* The `PlatformLocation` class is used directly by all implementations of {@link LocationStrategy}
* when they need to interact with the DOM APIs like pushState, popState, etc.
*
* {@link LocationStrategy} in turn is used by the {@link Location} service which is used directly
* by the {@link /api/router/Router Router} in order to navigate between routes. Since all interactions between
* {@link /api/router/Router Router} /
* {@link Location} / {@link LocationStrategy} and DOM APIs flow through the `PlatformLocation`
* class, they are all platform-agnostic.
*
* @publicApi
*/
class PlatformLocation {
historyGo(relativePosition) {
throw new Error(ngDevMode ? 'Not implemented' : '');
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: PlatformLocation, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: PlatformLocation, providedIn: 'platform', useFactory: () => inject(BrowserPlatformLocation) });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: PlatformLocation, decorators: [{
type: Injectable,
args: [{ providedIn: 'platform', useFactory: () => inject(BrowserPlatformLocation) }]
}] });
/**
* @description
* Indicates when a location is initialized.
*
* @publicApi
*/
const LOCATION_INITIALIZED = new InjectionToken(ngDevMode ? 'Location Initialized' : '');
/**
* `PlatformLocation` encapsulates all of the direct calls to platform APIs.
* This class should not be used directly by an application developer. Instead, use
* {@link Location}.
*
* @publicApi
*/
class BrowserPlatformLocation extends PlatformLocation {
_location;
_history;
_doc = inject(DOCUMENT);
constructor() {
super();
this._location = window.location;
this._history = window.history;
}
getBaseHrefFromDOM() {
return getDOM().getBaseHref(this._doc);
}
onPopState(fn) {
const window = getDOM().getGlobalEventTarget(this._doc, 'window');
window.addEventListener('popstate', fn, false);
return () => window.removeEventListener('popstate', fn);
}
onHashChange(fn) {
const window = getDOM().getGlobalEventTarget(this._doc, 'window');
window.addEventListener('hashchange', fn, false);
return () => window.removeEventListener('hashchange', fn);
}
get href() {
return this._location.href;
}
get protocol() {
return this._location.protocol;
}
get hostname() {
return this._location.hostname;
}
get port() {
return this._location.port;
}
get pathname() {
return this._location.pathname;
}
get search() {
return this._location.search;
}
get hash() {
return this._location.hash;
}
set pathname(newPath) {
this._location.pathname = newPath;
}
pushState(state, title, url) {
this._history.pushState(state, title, url);
}
replaceState(state, title, url) {
this._history.replaceState(state, title, url);
}
forward() {
this._history.forward();
}
back() {
this._history.back();
}
historyGo(relativePosition = 0) {
this._history.go(relativePosition);
}
getState() {
return this._history.state;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: BrowserPlatformLocation, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: BrowserPlatformLocation, providedIn: 'platform', useFactory: () => new BrowserPlatformLocation() });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: BrowserPlatformLocation, decorators: [{
type: Injectable,
args: [{
providedIn: 'platform',
useFactory: () => new BrowserPlatformLocation(),
}]
}], ctorParameters: () => [] });
/**
* Joins two parts of a URL with a slash if needed.
*
* @param start URL string
* @param end URL string
*
*
* @returns The joined URL string.
*/
function joinWithSlash(start, end) {
// If `start` is an empty string, return `end` as the result.
if (!start)
return end;
// If `end` is an empty string, return `start` as the result.
if (!end)
return start;
// If `start` ends with a slash, remove the leading slash from `end`.
if (start.endsWith('/')) {
return end.startsWith('/') ? start + end.slice(1) : start + end;
}
// If `start` doesn't end with a slash, add one if `end` doesn't start with a slash.
return end.startsWith('/') ? start + end : `${start}/${end}`;
}
/**
* Removes a trailing slash from a URL string if needed.
* Looks for the first occurrence of either `#`, `?`, or the end of the
* line as `/` characters and removes the trailing slash if one exists.
*
* @param url URL string.
*
* @returns The URL string, modified if needed.
*/
function stripTrailingSlash(url) {
// Find the index of the first occurrence of `#`, `?`, or the end of the string.
// This marks the start of the query string, fragment, or the end of the URL path.
const pathEndIdx = url.search(/#|\?|$/);
// Check if the character before `pathEndIdx` is a trailing slash.
// If it is, remove the trailing slash and return the modified URL.
// Otherwise, return the URL as is.
return url[pathEndIdx - 1] === '/' ? url.slice(0, pathEndIdx - 1) + url.slice(pathEndIdx) : url;
}
/**
* Normalizes URL parameters by prepending with `?` if needed.
*
* @param params String of URL parameters.
*
* @returns The normalized URL parameters string.
*/
function normalizeQueryParams(params) {
return params && params[0] !== '?' ? `?${params}` : params;
}
/**
* Enables the `Location` service to read route state from the browser's URL.
* Angular provides two strategies:
* `HashLocationStrategy` and `PathLocationStrategy`.
*
* Applications should use the `Router` or `Location` services to
* interact with application route state.
*
* For instance, `HashLocationStrategy` produces URLs like
* <code class="no-auto-link">http://example.com/#/foo</code>,
* and `PathLocationStrategy` produces
* <code class="no-auto-link">http://example.com/foo</code> as an equivalent URL.
*
* See these two classes for more.
*
* @publicApi
*/
class LocationStrategy {
historyGo(relativePosition) {
throw new Error(ngDevMode ? 'Not implemented' : '');
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: LocationStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: LocationStrategy, providedIn: 'root', useFactory: () => inject(PathLocationStrategy) });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: LocationStrategy, decorators: [{
type: Injectable,
args: [{ providedIn: 'root', useFactory: () => inject(PathLocationStrategy) }]
}] });
/**
* A predefined DI token for the base href
* to be used with the `PathLocationStrategy`.
* The base href is the URL prefix that should be preserved when generating
* and recognizing URLs.
*
* @usageNotes
*
* The following example shows how to use this token to configure the root app injector
* with a base href value, so that the DI framework can supply the dependency anywhere in the app.
*
* ```ts
* import {NgModule} from '@angular/core';
* import {APP_BASE_HREF} from '@angular/common';
*
* @NgModule({
* providers: [{provide: APP_BASE_HREF, useValue: '/my/app'}]
* })
* class AppModule {}
* ```
*
* @publicApi
*/
const APP_BASE_HREF = new InjectionToken(ngDevMode ? 'appBaseHref' : '');
/**
* @description
* A {@link LocationStrategy} used to configure the {@link Location} service to
* represent its state in the
* [path](https://en.wikipedia.org/wiki/Uniform_Resource_Locator#Syntax) of the
* browser's URL.
*
* If you're using `PathLocationStrategy`, you may provide a {@link APP_BASE_HREF}
* or add a `<base href>` element to the document to override the default.
*
* For instance, if you provide an `APP_BASE_HREF` of `'/my/app/'` and call
* `location.go('/foo')`, the browser's URL will become
* `example.com/my/app/foo`. To ensure all relative URIs resolve correctly,
* the `<base href>` and/or `APP_BASE_HREF` should end with a `/`.
*
* Similarly, if you add `<base href='/my/app/'/>` to the document and call
* `location.go('/foo')`, the browser's URL will become
* `example.com/my/app/foo`.
*
* Note that when using `PathLocationStrategy`, neither the query nor
* the fragment in the `<base href>` will be preserved, as outlined
* by the [RFC](https://tools.ietf.org/html/rfc3986#section-5.2.2).
*
* @usageNotes
*
* ### Example
*
* {@example common/location/ts/path_location_component.ts region='LocationComponent'}
*
* @publicApi
*/
class PathLocationStrategy extends LocationStrategy {
_platformLocation;
_baseHref;
_removeListenerFns = [];
constructor(_platformLocation, href) {
super();
this._platformLocation = _platformLocation;
this._baseHref =
href ??
this._platformLocation.getBaseHrefFromDOM() ??
inject(DOCUMENT).location?.origin ??
'';
}
/** @docs-private */
ngOnDestroy() {
while (this._removeListenerFns.length) {
this._removeListenerFns.pop()();
}
}
onPopState(fn) {
this._removeListenerFns.push(this._platformLocation.onPopState(fn), this._platformLocation.onHashChange(fn));
}
getBaseHref() {
return this._baseHref;
}
prepareExternalUrl(internal) {
return joinWithSlash(this._baseHref, internal);
}
path(includeHash = false) {
const pathname = this._platformLocation.pathname + normalizeQueryParams(this._platformLocation.search);
const hash = this._platformLocation.hash;
return hash && includeHash ? `${pathname}${hash}` : pathname;
}
pushState(state, title, url, queryParams) {
const externalUrl = this.prepareExternalUrl(url + normalizeQueryParams(queryParams));
this._platformLocation.pushState(state, title, externalUrl);
}
replaceState(state, title, url, queryParams) {
const externalUrl = this.prepareExternalUrl(url + normalizeQueryParams(queryParams));
this._platformLocation.replaceState(state, title, externalUrl);
}
forward() {
this._platformLocation.forward();
}
back() {
this._platformLocation.back();
}
getState() {
return this._platformLocation.getState();
}
historyGo(relativePosition = 0) {
this._platformLocation.historyGo?.(relativePosition);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: PathLocationStrategy, deps: [{ token: PlatformLocation }, { token: APP_BASE_HREF, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: PathLocationStrategy, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: PathLocationStrategy, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}], ctorParameters: () => [{ type: PlatformLocation }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [APP_BASE_HREF]
}] }] });
/**
* @description
*
* A service that applications can use to interact with a browser's URL.
*
* Depending on the `LocationStrategy` used, `Location` persists
* to the URL's path or the URL's hash segment.
*
* @usageNotes
*
* It's better to use the `Router.navigate()` service to trigger route changes. Use
* `Location` only if you need to interact with or create normalized URLs outside of
* routing.
*
* `Location` is responsible for normalizing the URL against the application's base href.
* A normalized URL is absolute from the URL host, includes the application's base href, and has no
* trailing slash:
* - `/my/app/user/123` is normalized
* - `my/app/user/123` **is not** normalized
* - `/my/app/user/123/` **is not** normalized
*
* ### Example
*
* {@example common/location/ts/path_location_component.ts region='LocationComponent'}
*
* @publicApi
*/
class Location {
/** @internal */
_subject = new Subject();
/** @internal */
_basePath;
/** @internal */
_locationStrategy;
/** @internal */
_urlChangeListeners = [];
/** @internal */
_urlChangeSubscription = null;
constructor(locationStrategy) {
this._locationStrategy = locationStrategy;
const baseHref = this._locationStrategy.getBaseHref();
// Note: This class's interaction with base HREF does not fully follow the rules
// outlined in the spec https://www.freesoft.org/CIE/RFC/1808/18.htm.
// Instead of trying to fix individual bugs with more and more code, we should
// investigate using the URL constructor and providing the base as a second
// argument.
// https://developer.mozilla.org/en-US/docs/Web/API/URL/URL#parameters
this._basePath = _stripOrigin(stripTrailingSlash(_stripIndexHtml(baseHref)));
this._locationStrategy.onPopState((ev) => {
this._subject.next({
'url': this.path(true),
'pop': true,
'state': ev.state,
'type': ev.type,
});
});
}
/** @docs-private */
ngOnDestroy() {
this._urlChangeSubscription?.unsubscribe();
this._urlChangeListeners = [];
}
/**
* Normalizes the URL path for this location.
*
* @param includeHash True to include an anchor fragment in the path.
*
* @returns The normalized URL path.
*/
// TODO: vsavkin. Remove the boolean flag and always include hash once the deprecated router is
// removed.
path(includeHash = false) {
return this.normalize(this._locationStrategy.path(includeHash));
}
/**
* Reports the current state of the location history.
* @returns The current value of the `history.state` object.
*/
getState() {
return this._locationStrategy.getState();
}
/**
* Normalizes the given path and compares to the current normalized path.
*
* @param path The given URL path.
* @param query Query parameters.
*
* @returns True if the given URL path is equal to the current normalized path, false
* otherwise.
*/
isCurrentPathEqualTo(path, query = '') {
return this.path() == this.normalize(path + normalizeQueryParams(query));
}
/**
* Normalizes a URL path by stripping any trailing slashes.
*
* @param url String representing a URL.
*
* @returns The normalized URL string.
*/
normalize(url) {
return Location.stripTrailingSlash(_stripBasePath(this._basePath, _stripIndexHtml(url)));
}
/**
* Normalizes an external URL path.
* If the given URL doesn't begin with a leading slash (`'/'`), adds one
* before normalizing. Adds a hash if `HashLocationStrategy` is
* in use, or the `APP_BASE_HREF` if the `PathLocationStrategy` is in use.
*
* @param url String representing a URL.
*
* @returns A normalized platform-specific URL.
*/
prepareExternalUrl(url) {
if (url && url[0] !== '/') {
url = '/' + url;
}
return this._locationStrategy.prepareExternalUrl(url);
}
// TODO: rename this method to pushState
/**
* Changes the browser's URL to a normalized version of a given URL, and pushes a
* new item onto the platform's history.
*
* @param path URL path to normalize.
* @param query Query parameters.
* @param state Location history state.
*
*/
go(path, query = '', state = null) {
this._locationStrategy.pushState(state, '', path, query);
this._notifyUrlChangeListeners(this.prepareExternalUrl(path + normalizeQueryParams(query)), state);
}
/**
* Changes the browser's URL to a normalized version of the given URL, and replaces
* the top item on the platform's history stack.
*
* @param path URL path to normalize.
* @param query Query parameters.
* @param state Location history state.
*/
replaceState(path, query = '', state = null) {
this._locationStrategy.replaceState(state, '', path, query);
this._notifyUrlChangeListeners(this.prepareExternalUrl(path + normalizeQueryParams(query)), state);
}
/**
* Navigates forward in the platform's history.
*/
forward() {
this._locationStrategy.forward();
}
/**
* Navigates back in the platform's history.
*/
back() {
this._locationStrategy.back();
}
/**
* Navigate to a specific page from session history, identified by its relative position to the
* current page.
*
* @param relativePosition Position of the target page in the history relative to the current
* page.
* A negative value moves backwards, a positive value moves forwards, e.g. `location.historyGo(2)`
* moves forward two pages and `location.historyGo(-2)` moves back two pages. When we try to go
* beyond what's stored in the history session, we stay in the current page. Same behaviour occurs
* when `relativePosition` equals 0.
* @see https://developer.mozilla.org/en-US/docs/Web/API/History_API#Moving_to_a_specific_point_in_history
*/
historyGo(relativePosition = 0) {
this._locationStrategy.historyGo?.(relativePosition);
}
/**
* Registers a URL change listener. Use to catch updates performed by the Angular
* framework that are not detectible through "popstate" or "hashchange" events.
*
* @param fn The change handler function, which take a URL and a location history state.
* @returns A function that, when executed, unregisters a URL change listener.
*/
onUrlChange(fn) {
this._urlChangeListeners.push(fn);
this._urlChangeSubscription ??= this.subscribe((v) => {
this._notifyUrlChangeListeners(v.url, v.state);
});
return () => {
const fnIndex = this._urlChangeListeners.indexOf(fn);
this._urlChangeListeners.splice(fnIndex, 1);
if (this._urlChangeListeners.length === 0) {
this._urlChangeSubscription?.unsubscribe();
this._urlChangeSubscription = null;
}
};
}
/** @internal */
_notifyUrlChangeListeners(url = '', state) {
this._urlChangeListeners.forEach((fn) => fn(url, state));
}
/**
* Subscribes to the platform's `popState` events.
*
* Note: `Location.go()` does not trigger the `popState` event in the browser. Use
* `Location.onUrlChange()` to subscribe to URL changes instead.
*
* @param value Event that is triggered when the state history changes.
* @param exception The exception to throw.
*
* @see [onpopstate](https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onpopstate)
*
* @returns Subscribed events.
*/
subscribe(onNext, onThrow, onReturn) {
return this._subject.subscribe({
next: onNext,
error: onThrow ?? undefined,
complete: onReturn ?? undefined,
});
}
/**
* Normalizes URL parameters by prepending with `?` if needed.
*
* @param params String of URL parameters.
*
* @returns The normalized URL parameters string.
*/
static normalizeQueryParams = normalizeQueryParams;
/**
* Joins two parts of a URL with a slash if needed.
*
* @param start URL string
* @param end URL string
*
*
* @returns The joined URL string.
*/
static joinWithSlash = joinWithSlash;
/**
* Removes a trailing slash from a URL string if needed.
* Looks for the first occurrence of either `#`, `?`, or the end of the
* line as `/` characters and removes the trailing slash if one exists.
*
* @param url URL string.
*
* @returns The URL string, modified if needed.
*/
static stripTrailingSlash = stripTrailingSlash;
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: Location, deps: [{ token: LocationStrategy }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: Location, providedIn: 'root', useFactory: createLocation });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: Location, decorators: [{
type: Injectable,
args: [{
providedIn: 'root',
// See #23917
useFactory: createLocation,
}]
}], ctorParameters: () => [{ type: LocationStrategy }] });
function createLocation() {
return new Location(__inject(LocationStrategy));
}
function _stripBasePath(basePath, url) {
if (!basePath || !url.startsWith(basePath)) {
return url;
}
const strippedUrl = url.substring(basePath.length);
if (strippedUrl === '' || ['/', ';', '?', '#'].includes(strippedUrl[0])) {
return strippedUrl;
}
return url;
}
function _stripIndexHtml(url) {
return url.replace(/\/index.html$/, '');
}
function _stripOrigin(baseHref) {
// DO NOT REFACTOR! Previously, this check looked like this:
// `/^(https?:)?\/\//.test(baseHref)`, but that resulted in
// syntactically incorrect code after Closure Compiler minification.
// This was likely caused by a bug in Closure Compiler, but
// for now, the check is rewritten to use `new RegExp` instead.
const isAbsoluteUrl = new RegExp('^(https?:)?//').test(baseHref);
if (isAbsoluteUrl) {
const [, pathname] = baseHref.split(/\/\/[^\/]+/);
return pathname;
}
return baseHref;
}
export { APP_BASE_HREF, BrowserPlatformLocation, DomAdapter, LOCATION_INITIALIZED, Location, LocationStrategy, PathLocationStrategy, PlatformLocation, getDOM, joinWithSlash, normalizeQueryParams, setRootDomAdapter };
//# sourceMappingURL=location.mjs.map

1
node_modules/@angular/common/fesm2022/location.mjs.map generated vendored Executable file

File diff suppressed because one or more lines are too long

3184
node_modules/@angular/common/fesm2022/module.mjs generated vendored Executable file

File diff suppressed because it is too large Load Diff

1
node_modules/@angular/common/fesm2022/module.mjs.map generated vendored Executable file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,24 @@
/**
* @license Angular v20.3.11
* (c) 2010-2025 Google LLC. https://angular.dev/
* License: MIT
*/
import * as i0 from '@angular/core';
import { Injectable } from '@angular/core';
/**
* This class wraps the platform Navigation API which allows server-specific and test
* implementations.
*/
class PlatformNavigation {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: PlatformNavigation, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: PlatformNavigation, providedIn: 'platform', useFactory: () => window.navigation });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: PlatformNavigation, decorators: [{
type: Injectable,
args: [{ providedIn: 'platform', useFactory: () => window.navigation }]
}] });
export { PlatformNavigation };
//# sourceMappingURL=platform_navigation.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"platform_navigation.mjs","sources":["../../../../../k8-fastbuild-ST-199a4f3c4e20/bin/packages/common/src/navigation/platform_navigation.ts"],"sourcesContent":["/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.dev/license\n */\n\nimport {\n Injectable,\n ɵNavigateEvent as NavigateEvent,\n ɵNavigation as Navigation,\n ɵNavigationCurrentEntryChangeEvent as NavigationCurrentEntryChangeEvent,\n ɵNavigationHistoryEntry as NavigationHistoryEntry,\n ɵNavigationNavigateOptions as NavigationNavigateOptions,\n ɵNavigationOptions as NavigationOptions,\n ɵNavigationReloadOptions as NavigationReloadOptions,\n ɵNavigationResult as NavigationResult,\n ɵNavigationTransition as NavigationTransition,\n ɵNavigationUpdateCurrentEntryOptions as NavigationUpdateCurrentEntryOptions,\n} from '@angular/core';\n\n/**\n * This class wraps the platform Navigation API which allows server-specific and test\n * implementations.\n */\n@Injectable({providedIn: 'platform', useFactory: () => (window as any).navigation})\nexport abstract class PlatformNavigation implements Navigation {\n abstract entries(): NavigationHistoryEntry[];\n abstract currentEntry: NavigationHistoryEntry | null;\n abstract updateCurrentEntry(options: NavigationUpdateCurrentEntryOptions): void;\n abstract transition: NavigationTransition | null;\n abstract canGoBack: boolean;\n abstract canGoForward: boolean;\n abstract navigate(url: string, options?: NavigationNavigateOptions | undefined): NavigationResult;\n abstract reload(options?: NavigationReloadOptions | undefined): NavigationResult;\n abstract traverseTo(key: string, options?: NavigationOptions | undefined): NavigationResult;\n abstract back(options?: NavigationOptions | undefined): NavigationResult;\n abstract forward(options?: NavigationOptions | undefined): NavigationResult;\n abstract onnavigate: ((this: Navigation, ev: NavigateEvent) => any) | null;\n abstract onnavigatesuccess: ((this: Navigation, ev: Event) => any) | null;\n abstract onnavigateerror: ((this: Navigation, ev: ErrorEvent) => any) | null;\n abstract oncurrententrychange:\n | ((this: Navigation, ev: NavigationCurrentEntryChangeEvent) => any)\n | null;\n abstract addEventListener(type: unknown, listener: unknown, options?: unknown): void;\n abstract removeEventListener(type: unknown, listener: unknown, options?: unknown): void;\n abstract dispatchEvent(event: Event): boolean;\n}\n"],"names":[],"mappings":";;;;;;;;;AAsBA;;;AAGG;MAEmB,kBAAkB,CAAA;kHAAlB,kBAAkB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;sHAAlB,kBAAkB,EAAA,UAAA,EADf,UAAU,EAAc,UAAA,EAAA,MAAO,MAAc,CAAC,UAAU,EAAA,CAAA;;sGAC3D,kBAAkB,EAAA,UAAA,EAAA,CAAA;kBADvC,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA,EAAC,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAO,MAAc,CAAC,UAAU,EAAC;;;;;"}

596
node_modules/@angular/common/fesm2022/testing.mjs generated vendored Executable file
View File

@@ -0,0 +1,596 @@
/**
* @license Angular v20.3.11
* (c) 2010-2025 Google LLC. https://angular.dev/
* License: MIT
*/
import { ɵnormalizeQueryParams as _normalizeQueryParams, LocationStrategy } from '@angular/common';
import * as i0 from '@angular/core';
import { InjectionToken, Injectable, Inject, Optional, inject, DOCUMENT } from '@angular/core';
import { Subject } from 'rxjs';
import { PlatformNavigation } from './platform_navigation.mjs';
import { ɵFakeNavigation as _FakeNavigation } from '@angular/core/testing';
export { ɵFakeNavigation } from '@angular/core/testing';
import { PlatformLocation, Location, LocationStrategy as LocationStrategy$1 } from './location.mjs';
/**
* Parser from https://tools.ietf.org/html/rfc3986#appendix-B
* ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
* 12 3 4 5 6 7 8 9
*
* Example: http://www.ics.uci.edu/pub/ietf/uri/#Related
*
* Results in:
*
* $1 = http:
* $2 = http
* $3 = //www.ics.uci.edu
* $4 = www.ics.uci.edu
* $5 = /pub/ietf/uri/
* $6 = <undefined>
* $7 = <undefined>
* $8 = #Related
* $9 = Related
*/
const urlParse = /^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/;
function parseUrl(urlStr, baseHref) {
const verifyProtocol = /^((http[s]?|ftp):\/\/)/;
let serverBase;
// URL class requires full URL. If the URL string doesn't start with protocol, we need to add
// an arbitrary base URL which can be removed afterward.
if (!verifyProtocol.test(urlStr)) {
serverBase = 'http://empty.com/';
}
let parsedUrl;
try {
parsedUrl = new URL(urlStr, serverBase);
}
catch (e) {
const result = urlParse.exec(serverBase || '' + urlStr);
if (!result) {
throw new Error(`Invalid URL: ${urlStr} with base: ${baseHref}`);
}
const hostSplit = result[4].split(':');
parsedUrl = {
protocol: result[1],
hostname: hostSplit[0],
port: hostSplit[1] || '',
pathname: result[5],
search: result[6],
hash: result[8],
};
}
if (parsedUrl.pathname && parsedUrl.pathname.indexOf(baseHref) === 0) {
parsedUrl.pathname = parsedUrl.pathname.substring(baseHref.length);
}
return {
hostname: (!serverBase && parsedUrl.hostname) || '',
protocol: (!serverBase && parsedUrl.protocol) || '',
port: (!serverBase && parsedUrl.port) || '',
pathname: parsedUrl.pathname || '/',
search: parsedUrl.search || '',
hash: parsedUrl.hash || '',
};
}
/**
* Provider for mock platform location config
*
* @publicApi
*/
const MOCK_PLATFORM_LOCATION_CONFIG = new InjectionToken('MOCK_PLATFORM_LOCATION_CONFIG');
/**
* Mock implementation of URL state.
*
* @publicApi
*/
class MockPlatformLocation {
baseHref = '';
hashUpdate = new Subject();
popStateSubject = new Subject();
urlChangeIndex = 0;
urlChanges = [{ hostname: '', protocol: '', port: '', pathname: '/', search: '', hash: '', state: null }];
constructor(config) {
if (config) {
this.baseHref = config.appBaseHref || '';
const parsedChanges = this.parseChanges(null, config.startUrl || 'http://_empty_/', this.baseHref);
this.urlChanges[0] = { ...parsedChanges };
}
}
get hostname() {
return this.urlChanges[this.urlChangeIndex].hostname;
}
get protocol() {
return this.urlChanges[this.urlChangeIndex].protocol;
}
get port() {
return this.urlChanges[this.urlChangeIndex].port;
}
get pathname() {
return this.urlChanges[this.urlChangeIndex].pathname;
}
get search() {
return this.urlChanges[this.urlChangeIndex].search;
}
get hash() {
return this.urlChanges[this.urlChangeIndex].hash;
}
get state() {
return this.urlChanges[this.urlChangeIndex].state;
}
getBaseHrefFromDOM() {
return this.baseHref;
}
onPopState(fn) {
const subscription = this.popStateSubject.subscribe(fn);
return () => subscription.unsubscribe();
}
onHashChange(fn) {
const subscription = this.hashUpdate.subscribe(fn);
return () => subscription.unsubscribe();
}
get href() {
let url = `${this.protocol}//${this.hostname}${this.port ? ':' + this.port : ''}`;
url += `${this.pathname === '/' ? '' : this.pathname}${this.search}${this.hash}`;
return url;
}
get url() {
return `${this.pathname}${this.search}${this.hash}`;
}
parseChanges(state, url, baseHref = '') {
// When the `history.state` value is stored, it is always copied.
state = JSON.parse(JSON.stringify(state));
return { ...parseUrl(url, baseHref), state };
}
replaceState(state, title, newUrl) {
const { pathname, search, state: parsedState, hash } = this.parseChanges(state, newUrl);
this.urlChanges[this.urlChangeIndex] = {
...this.urlChanges[this.urlChangeIndex],
pathname,
search,
hash,
state: parsedState,
};
}
pushState(state, title, newUrl) {
const { pathname, search, state: parsedState, hash } = this.parseChanges(state, newUrl);
if (this.urlChangeIndex > 0) {
this.urlChanges.splice(this.urlChangeIndex + 1);
}
this.urlChanges.push({
...this.urlChanges[this.urlChangeIndex],
pathname,
search,
hash,
state: parsedState,
});
this.urlChangeIndex = this.urlChanges.length - 1;
}
forward() {
const oldUrl = this.url;
const oldHash = this.hash;
if (this.urlChangeIndex < this.urlChanges.length) {
this.urlChangeIndex++;
}
this.emitEvents(oldHash, oldUrl);
}
back() {
const oldUrl = this.url;
const oldHash = this.hash;
if (this.urlChangeIndex > 0) {
this.urlChangeIndex--;
}
this.emitEvents(oldHash, oldUrl);
}
historyGo(relativePosition = 0) {
const oldUrl = this.url;
const oldHash = this.hash;
const nextPageIndex = this.urlChangeIndex + relativePosition;
if (nextPageIndex >= 0 && nextPageIndex < this.urlChanges.length) {
this.urlChangeIndex = nextPageIndex;
}
this.emitEvents(oldHash, oldUrl);
}
getState() {
return this.state;
}
/**
* Browsers are inconsistent in when they fire events and perform the state updates
* The most easiest thing to do in our mock is synchronous and that happens to match
* Firefox and Chrome, at least somewhat closely
*
* https://github.com/WICG/navigation-api#watching-for-navigations
* https://docs.google.com/document/d/1Pdve-DJ1JCGilj9Yqf5HxRJyBKSel5owgOvUJqTauwU/edit#heading=h.3ye4v71wsz94
* popstate is always sent before hashchange:
* https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event#when_popstate_is_sent
*/
emitEvents(oldHash, oldUrl) {
this.popStateSubject.next({
type: 'popstate',
state: this.getState(),
oldUrl,
newUrl: this.url,
});
if (oldHash !== this.hash) {
this.hashUpdate.next({
type: 'hashchange',
state: null,
oldUrl,
newUrl: this.url,
});
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: MockPlatformLocation, deps: [{ token: MOCK_PLATFORM_LOCATION_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: MockPlatformLocation });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: MockPlatformLocation, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Inject,
args: [MOCK_PLATFORM_LOCATION_CONFIG]
}, {
type: Optional
}] }] });
/**
* Mock implementation of URL state.
*/
class FakeNavigationPlatformLocation {
_platformNavigation;
constructor() {
const platformNavigation = inject(PlatformNavigation);
if (!(platformNavigation instanceof _FakeNavigation)) {
throw new Error('FakePlatformNavigation cannot be used without FakeNavigation. Use ' +
'`provideFakeNavigation` to have all these services provided together.');
}
this._platformNavigation = platformNavigation;
}
config = inject(MOCK_PLATFORM_LOCATION_CONFIG, { optional: true });
getBaseHrefFromDOM() {
return this.config?.appBaseHref ?? '';
}
onPopState(fn) {
this._platformNavigation.window.addEventListener('popstate', fn);
return () => this._platformNavigation.window.removeEventListener('popstate', fn);
}
onHashChange(fn) {
this._platformNavigation.window.addEventListener('hashchange', fn);
return () => this._platformNavigation.window.removeEventListener('hashchange', fn);
}
get href() {
return this._platformNavigation.currentEntry.url;
}
get protocol() {
return new URL(this._platformNavigation.currentEntry.url).protocol;
}
get hostname() {
return new URL(this._platformNavigation.currentEntry.url).hostname;
}
get port() {
return new URL(this._platformNavigation.currentEntry.url).port;
}
get pathname() {
return new URL(this._platformNavigation.currentEntry.url).pathname;
}
get search() {
return new URL(this._platformNavigation.currentEntry.url).search;
}
get hash() {
return new URL(this._platformNavigation.currentEntry.url).hash;
}
pushState(state, title, url) {
this._platformNavigation.pushState(state, title, url);
}
replaceState(state, title, url) {
this._platformNavigation.replaceState(state, title, url);
}
forward() {
this._platformNavigation.forward();
}
back() {
this._platformNavigation.back();
}
historyGo(relativePosition = 0) {
this._platformNavigation.go(relativePosition);
}
getState() {
return this._platformNavigation.currentEntry.getHistoryState();
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: FakeNavigationPlatformLocation, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: FakeNavigationPlatformLocation });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: FakeNavigationPlatformLocation, decorators: [{
type: Injectable
}], ctorParameters: () => [] });
const FAKE_NAVIGATION = new InjectionToken('fakeNavigation', {
providedIn: 'root',
factory: () => {
const config = inject(MOCK_PLATFORM_LOCATION_CONFIG, { optional: true });
const baseFallback = 'http://_empty_/';
const startUrl = new URL(config?.startUrl || baseFallback, baseFallback);
const fakeNavigation = new _FakeNavigation(inject(DOCUMENT), startUrl.href);
fakeNavigation.setSynchronousTraversalsForTesting(true);
return fakeNavigation;
},
});
/**
* Return a provider for the `FakeNavigation` in place of the real Navigation API.
*/
function provideFakePlatformNavigation() {
return [
{
provide: PlatformNavigation,
useFactory: () => inject(FAKE_NAVIGATION),
},
{ provide: PlatformLocation, useClass: FakeNavigationPlatformLocation },
];
}
/**
* A spy for {@link Location} that allows tests to fire simulated location events.
*
* @publicApi
*/
class SpyLocation {
urlChanges = [];
_history = [new LocationState('', '', null)];
_historyIndex = 0;
/** @internal */
_subject = new Subject();
/** @internal */
_basePath = '';
/** @internal */
_locationStrategy = null;
/** @internal */
_urlChangeListeners = [];
/** @internal */
_urlChangeSubscription = null;
/** @docs-private */
ngOnDestroy() {
this._urlChangeSubscription?.unsubscribe();
this._urlChangeListeners = [];
}
setInitialPath(url) {
this._history[this._historyIndex].path = url;
}
setBaseHref(url) {
this._basePath = url;
}
path() {
return this._history[this._historyIndex].path;
}
getState() {
return this._history[this._historyIndex].state;
}
isCurrentPathEqualTo(path, query = '') {
const givenPath = path.endsWith('/') ? path.substring(0, path.length - 1) : path;
const currPath = this.path().endsWith('/')
? this.path().substring(0, this.path().length - 1)
: this.path();
return currPath == givenPath + (query.length > 0 ? '?' + query : '');
}
simulateUrlPop(pathname) {
this._subject.next({ 'url': pathname, 'pop': true, 'type': 'popstate' });
}
simulateHashChange(pathname) {
const path = this.prepareExternalUrl(pathname);
this.pushHistory(path, '', null);
this.urlChanges.push('hash: ' + pathname);
// the browser will automatically fire popstate event before each `hashchange` event, so we need
// to simulate it.
this._subject.next({ 'url': pathname, 'pop': true, 'type': 'popstate' });
this._subject.next({ 'url': pathname, 'pop': true, 'type': 'hashchange' });
}
prepareExternalUrl(url) {
if (url.length > 0 && !url.startsWith('/')) {
url = '/' + url;
}
return this._basePath + url;
}
go(path, query = '', state = null) {
path = this.prepareExternalUrl(path);
this.pushHistory(path, query, state);
const locationState = this._history[this._historyIndex - 1];
if (locationState.path == path && locationState.query == query) {
return;
}
const url = path + (query.length > 0 ? '?' + query : '');
this.urlChanges.push(url);
this._notifyUrlChangeListeners(path + _normalizeQueryParams(query), state);
}
replaceState(path, query = '', state = null) {
path = this.prepareExternalUrl(path);
const history = this._history[this._historyIndex];
history.state = state;
if (history.path == path && history.query == query) {
return;
}
history.path = path;
history.query = query;
const url = path + (query.length > 0 ? '?' + query : '');
this.urlChanges.push('replace: ' + url);
this._notifyUrlChangeListeners(path + _normalizeQueryParams(query), state);
}
forward() {
if (this._historyIndex < this._history.length - 1) {
this._historyIndex++;
this._subject.next({
'url': this.path(),
'state': this.getState(),
'pop': true,
'type': 'popstate',
});
}
}
back() {
if (this._historyIndex > 0) {
this._historyIndex--;
this._subject.next({
'url': this.path(),
'state': this.getState(),
'pop': true,
'type': 'popstate',
});
}
}
historyGo(relativePosition = 0) {
const nextPageIndex = this._historyIndex + relativePosition;
if (nextPageIndex >= 0 && nextPageIndex < this._history.length) {
this._historyIndex = nextPageIndex;
this._subject.next({
'url': this.path(),
'state': this.getState(),
'pop': true,
'type': 'popstate',
});
}
}
onUrlChange(fn) {
this._urlChangeListeners.push(fn);
this._urlChangeSubscription ??= this.subscribe((v) => {
this._notifyUrlChangeListeners(v.url, v.state);
});
return () => {
const fnIndex = this._urlChangeListeners.indexOf(fn);
this._urlChangeListeners.splice(fnIndex, 1);
if (this._urlChangeListeners.length === 0) {
this._urlChangeSubscription?.unsubscribe();
this._urlChangeSubscription = null;
}
};
}
/** @internal */
_notifyUrlChangeListeners(url = '', state) {
this._urlChangeListeners.forEach((fn) => fn(url, state));
}
subscribe(onNext, onThrow, onReturn) {
return this._subject.subscribe({
next: onNext,
error: onThrow ?? undefined,
complete: onReturn ?? undefined,
});
}
normalize(url) {
return null;
}
pushHistory(path, query, state) {
if (this._historyIndex > 0) {
this._history.splice(this._historyIndex + 1);
}
this._history.push(new LocationState(path, query, state));
this._historyIndex = this._history.length - 1;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: SpyLocation, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: SpyLocation });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: SpyLocation, decorators: [{
type: Injectable
}] });
class LocationState {
path;
query;
state;
constructor(path, query, state) {
this.path = path;
this.query = query;
this.state = state;
}
}
/**
* A mock implementation of {@link LocationStrategy} that allows tests to fire simulated
* location events.
*
* @publicApi
*/
class MockLocationStrategy extends LocationStrategy {
internalBaseHref = '/';
internalPath = '/';
internalTitle = '';
urlChanges = [];
/** @internal */
_subject = new Subject();
stateChanges = [];
constructor() {
super();
}
simulatePopState(url) {
this.internalPath = url;
this._subject.next(new _MockPopStateEvent(this.path()));
}
path(includeHash = false) {
return this.internalPath;
}
prepareExternalUrl(internal) {
if (internal.startsWith('/') && this.internalBaseHref.endsWith('/')) {
return this.internalBaseHref + internal.substring(1);
}
return this.internalBaseHref + internal;
}
pushState(ctx, title, path, query) {
// Add state change to changes array
this.stateChanges.push(ctx);
this.internalTitle = title;
const url = path + (query.length > 0 ? '?' + query : '');
this.internalPath = url;
const externalUrl = this.prepareExternalUrl(url);
this.urlChanges.push(externalUrl);
}
replaceState(ctx, title, path, query) {
// Reset the last index of stateChanges to the ctx (state) object
this.stateChanges[(this.stateChanges.length || 1) - 1] = ctx;
this.internalTitle = title;
const url = path + (query.length > 0 ? '?' + query : '');
this.internalPath = url;
const externalUrl = this.prepareExternalUrl(url);
this.urlChanges.push('replace: ' + externalUrl);
}
onPopState(fn) {
this._subject.subscribe({ next: fn });
}
getBaseHref() {
return this.internalBaseHref;
}
back() {
if (this.urlChanges.length > 0) {
this.urlChanges.pop();
this.stateChanges.pop();
const nextUrl = this.urlChanges.length > 0 ? this.urlChanges[this.urlChanges.length - 1] : '';
this.simulatePopState(nextUrl);
}
}
forward() {
throw 'not implemented';
}
getState() {
return this.stateChanges[(this.stateChanges.length || 1) - 1];
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: MockLocationStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: MockLocationStrategy });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: MockLocationStrategy, decorators: [{
type: Injectable
}], ctorParameters: () => [] });
class _MockPopStateEvent {
newUrl;
pop = true;
type = 'popstate';
constructor(newUrl) {
this.newUrl = newUrl;
}
}
/**
* Returns mock providers for the `Location` and `LocationStrategy` classes.
* The mocks are helpful in tests to fire simulated location events.
*
* @publicApi
*/
function provideLocationMocks() {
return [
{ provide: Location, useClass: SpyLocation },
{ provide: LocationStrategy$1, useClass: MockLocationStrategy },
];
}
export { MOCK_PLATFORM_LOCATION_CONFIG, MockLocationStrategy, MockPlatformLocation, SpyLocation, provideLocationMocks, provideFakePlatformNavigation as ɵprovideFakePlatformNavigation };
//# sourceMappingURL=testing.mjs.map

1
node_modules/@angular/common/fesm2022/testing.mjs.map generated vendored Executable file

File diff suppressed because one or more lines are too long

899
node_modules/@angular/common/fesm2022/upgrade.mjs generated vendored Executable file
View File

@@ -0,0 +1,899 @@
/**
* @license Angular v20.3.11
* (c) 2010-2025 Google LLC. https://angular.dev/
* License: MIT
*/
import * as i0 from '@angular/core';
import { ɵisPromise as _isPromise, InjectionToken, Inject, Optional, NgModule } from '@angular/core';
import { ReplaySubject } from 'rxjs';
import { UpgradeModule } from '@angular/upgrade/static';
import { Location, PlatformLocation, LocationStrategy, APP_BASE_HREF, PathLocationStrategy } from './location.mjs';
import { CommonModule, HashLocationStrategy } from './common_module.mjs';
function deepEqual(a, b) {
if (a === b) {
return true;
}
else if (!a || !b) {
return false;
}
else {
try {
if (a.prototype !== b.prototype || (Array.isArray(a) && Array.isArray(b))) {
return false;
}
return JSON.stringify(a) === JSON.stringify(b);
}
catch (e) {
return false;
}
}
}
function isAnchor(el) {
return el.href !== undefined;
}
const PATH_MATCH = /^([^?#]*)(\?([^#]*))?(#(.*))?$/;
const DOUBLE_SLASH_REGEX = /^\s*[\\/]{2,}/;
const IGNORE_URI_REGEXP = /^\s*(javascript|mailto):/i;
const DEFAULT_PORTS = {
'http:': 80,
'https:': 443,
'ftp:': 21,
};
/**
* Location service that provides a drop-in replacement for the $location service
* provided in AngularJS.
*
* @see [Using the Angular Unified Location Service](guide/upgrade#using-the-unified-angular-location-service)
*
* @publicApi
*/
class $locationShim {
location;
platformLocation;
urlCodec;
locationStrategy;
initializing = true;
updateBrowser = false;
$$absUrl = '';
$$url = '';
$$protocol;
$$host = '';
$$port;
$$replace = false;
$$path = '';
$$search = '';
$$hash = '';
$$state;
$$changeListeners = [];
cachedState = null;
urlChanges = new ReplaySubject(1);
removeOnUrlChangeFn;
constructor($injector, location, platformLocation, urlCodec, locationStrategy) {
this.location = location;
this.platformLocation = platformLocation;
this.urlCodec = urlCodec;
this.locationStrategy = locationStrategy;
const initialUrl = this.browserUrl();
let parsedUrl = this.urlCodec.parse(initialUrl);
if (typeof parsedUrl === 'string') {
throw 'Invalid URL';
}
this.$$protocol = parsedUrl.protocol;
this.$$host = parsedUrl.hostname;
this.$$port = parseInt(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null;
this.$$parseLinkUrl(initialUrl, initialUrl);
this.cacheState();
this.$$state = this.browserState();
this.removeOnUrlChangeFn = this.location.onUrlChange((newUrl, newState) => {
this.urlChanges.next({ newUrl, newState });
});
if (_isPromise($injector)) {
$injector.then(($i) => this.initialize($i));
}
else {
this.initialize($injector);
}
}
initialize($injector) {
const $rootScope = $injector.get('$rootScope');
const $rootElement = $injector.get('$rootElement');
$rootElement.on('click', (event) => {
if (event.ctrlKey ||
event.metaKey ||
event.shiftKey ||
event.which === 2 ||
event.button === 2) {
return;
}
let elm = event.target;
// traverse the DOM up to find first A tag
while (elm && elm.nodeName.toLowerCase() !== 'a') {
// ignore rewriting if no A tag (reached root element, or no parent - removed from document)
if (elm === $rootElement[0] || !(elm = elm.parentNode)) {
return;
}
}
if (!isAnchor(elm)) {
return;
}
const absHref = elm.href;
const relHref = elm.getAttribute('href');
// Ignore when url is started with javascript: or mailto:
if (IGNORE_URI_REGEXP.test(absHref)) {
return;
}
if (absHref && !elm.getAttribute('target') && !event.isDefaultPrevented()) {
if (this.$$parseLinkUrl(absHref, relHref)) {
// We do a preventDefault for all urls that are part of the AngularJS application,
// in html5mode and also without, so that we are able to abort navigation without
// getting double entries in the location history.
event.preventDefault();
// update location manually
if (this.absUrl() !== this.browserUrl()) {
$rootScope.$apply();
}
}
}
});
this.urlChanges.subscribe(({ newUrl, newState }) => {
const oldUrl = this.absUrl();
const oldState = this.$$state;
this.$$parse(newUrl);
newUrl = this.absUrl();
this.$$state = newState;
const defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl, newState, oldState).defaultPrevented;
// if the location was changed by a `$locationChangeStart` handler then stop
// processing this location change
if (this.absUrl() !== newUrl)
return;
// If default was prevented, set back to old state. This is the state that was locally
// cached in the $location service.
if (defaultPrevented) {
this.$$parse(oldUrl);
this.state(oldState);
this.setBrowserUrlWithFallback(oldUrl, false, oldState);
this.$$notifyChangeListeners(this.url(), this.$$state, oldUrl, oldState);
}
else {
this.initializing = false;
$rootScope.$broadcast('$locationChangeSuccess', newUrl, oldUrl, newState, oldState);
this.resetBrowserUpdate();
}
if (!$rootScope.$$phase) {
$rootScope.$digest();
}
});
// Synchronize the browser's URL and state with the application.
// Note: There is no need to save the `$watch` return value (deregister listener)
// into a variable because `$scope.$$watchers` is automatically cleaned up when
// the root scope is destroyed.
$rootScope.$watch(() => {
if (this.initializing || this.updateBrowser) {
this.updateBrowser = false;
const oldUrl = this.browserUrl();
const newUrl = this.absUrl();
const oldState = this.browserState();
let currentReplace = this.$$replace;
const urlOrStateChanged = !this.urlCodec.areEqual(oldUrl, newUrl) || oldState !== this.$$state;
// Fire location changes one time to on initialization. This must be done on the
// next tick (thus inside $evalAsync()) in order for listeners to be registered
// before the event fires. Mimicing behavior from $locationWatch:
// https://github.com/angular/angular.js/blob/master/src/ng/location.js#L983
if (this.initializing || urlOrStateChanged) {
this.initializing = false;
$rootScope.$evalAsync(() => {
// Get the new URL again since it could have changed due to async update
const newUrl = this.absUrl();
const defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl, this.$$state, oldState).defaultPrevented;
// if the location was changed by a `$locationChangeStart` handler then stop
// processing this location change
if (this.absUrl() !== newUrl)
return;
if (defaultPrevented) {
this.$$parse(oldUrl);
this.$$state = oldState;
}
else {
// This block doesn't run when initializing because it's going to perform the update
// to the URL which shouldn't be needed when initializing.
if (urlOrStateChanged) {
this.setBrowserUrlWithFallback(newUrl, currentReplace, oldState === this.$$state ? null : this.$$state);
this.$$replace = false;
}
$rootScope.$broadcast('$locationChangeSuccess', newUrl, oldUrl, this.$$state, oldState);
if (urlOrStateChanged) {
this.$$notifyChangeListeners(this.url(), this.$$state, oldUrl, oldState);
}
}
});
}
}
this.$$replace = false;
});
$rootScope.$on('$destroy', () => {
this.removeOnUrlChangeFn();
// Complete the subject to release all active observers when the root
// scope is destroyed. Before this change, we subscribed to the `urlChanges`
// subject, and the subscriber captured `this`, leading to a memory leak
// after the root scope was destroyed.
this.urlChanges.complete();
});
}
resetBrowserUpdate() {
this.$$replace = false;
this.$$state = this.browserState();
this.updateBrowser = false;
this.lastBrowserUrl = this.browserUrl();
}
lastHistoryState;
lastBrowserUrl = '';
browserUrl(url, replace, state) {
// In modern browsers `history.state` is `null` by default; treating it separately
// from `undefined` would cause `$browser.url('/foo')` to change `history.state`
// to undefined via `pushState`. Instead, let's change `undefined` to `null` here.
if (typeof state === 'undefined') {
state = null;
}
// setter
if (url) {
let sameState = this.lastHistoryState === state;
// Normalize the inputted URL
url = this.urlCodec.parse(url).href;
// Don't change anything if previous and current URLs and states match.
if (this.lastBrowserUrl === url && sameState) {
return this;
}
this.lastBrowserUrl = url;
this.lastHistoryState = state;
// Remove server base from URL as the Angular APIs for updating URL require
// it to be the path+.
url = this.stripBaseUrl(this.getServerBase(), url) || url;
// Set the URL
if (replace) {
this.locationStrategy.replaceState(state, '', url, '');
}
else {
this.locationStrategy.pushState(state, '', url, '');
}
this.cacheState();
return this;
// getter
}
else {
return this.platformLocation.href;
}
}
// This variable should be used *only* inside the cacheState function.
lastCachedState = null;
cacheState() {
// This should be the only place in $browser where `history.state` is read.
this.cachedState = this.platformLocation.getState();
if (typeof this.cachedState === 'undefined') {
this.cachedState = null;
}
// Prevent callbacks fo fire twice if both hashchange & popstate were fired.
if (deepEqual(this.cachedState, this.lastCachedState)) {
this.cachedState = this.lastCachedState;
}
this.lastCachedState = this.cachedState;
this.lastHistoryState = this.cachedState;
}
/**
* This function emulates the $browser.state() function from AngularJS. It will cause
* history.state to be cached unless changed with deep equality check.
*/
browserState() {
return this.cachedState;
}
stripBaseUrl(base, url) {
if (url.startsWith(base)) {
return url.slice(base.length);
}
return undefined;
}
getServerBase() {
const { protocol, hostname, port } = this.platformLocation;
const baseHref = this.locationStrategy.getBaseHref();
let url = `${protocol}//${hostname}${port ? ':' + port : ''}${baseHref || '/'}`;
return url.endsWith('/') ? url : url + '/';
}
parseAppUrl(url) {
if (DOUBLE_SLASH_REGEX.test(url)) {
throw new Error(`Bad Path - URL cannot start with double slashes: ${url}`);
}
let prefixed = url.charAt(0) !== '/';
if (prefixed) {
url = '/' + url;
}
let match = this.urlCodec.parse(url, this.getServerBase());
if (typeof match === 'string') {
throw new Error(`Bad URL - Cannot parse URL: ${url}`);
}
let path = prefixed && match.pathname.charAt(0) === '/' ? match.pathname.substring(1) : match.pathname;
this.$$path = this.urlCodec.decodePath(path);
this.$$search = this.urlCodec.decodeSearch(match.search);
this.$$hash = this.urlCodec.decodeHash(match.hash);
// make sure path starts with '/';
if (this.$$path && this.$$path.charAt(0) !== '/') {
this.$$path = '/' + this.$$path;
}
}
/**
* Registers listeners for URL changes. This API is used to catch updates performed by the
* AngularJS framework. These changes are a subset of the `$locationChangeStart` and
* `$locationChangeSuccess` events which fire when AngularJS updates its internally-referenced
* version of the browser URL.
*
* It's possible for `$locationChange` events to happen, but for the browser URL
* (window.location) to remain unchanged. This `onChange` callback will fire only when AngularJS
* actually updates the browser URL (window.location).
*
* @param fn The callback function that is triggered for the listener when the URL changes.
* @param err The callback function that is triggered when an error occurs.
*/
onChange(fn, err = (e) => { }) {
this.$$changeListeners.push([fn, err]);
}
/** @internal */
$$notifyChangeListeners(url = '', state, oldUrl = '', oldState) {
this.$$changeListeners.forEach(([fn, err]) => {
try {
fn(url, state, oldUrl, oldState);
}
catch (e) {
err(e);
}
});
}
/**
* Parses the provided URL, and sets the current URL to the parsed result.
*
* @param url The URL string.
*/
$$parse(url) {
let pathUrl;
if (url.startsWith('/')) {
pathUrl = url;
}
else {
// Remove protocol & hostname if URL starts with it
pathUrl = this.stripBaseUrl(this.getServerBase(), url);
}
if (typeof pathUrl === 'undefined') {
throw new Error(`Invalid url "${url}", missing path prefix "${this.getServerBase()}".`);
}
this.parseAppUrl(pathUrl);
this.$$path ||= '/';
this.composeUrls();
}
/**
* Parses the provided URL and its relative URL.
*
* @param url The full URL string.
* @param relHref A URL string relative to the full URL string.
*/
$$parseLinkUrl(url, relHref) {
// When relHref is passed, it should be a hash and is handled separately
if (relHref && relHref[0] === '#') {
this.hash(relHref.slice(1));
return true;
}
let rewrittenUrl;
let appUrl = this.stripBaseUrl(this.getServerBase(), url);
if (typeof appUrl !== 'undefined') {
rewrittenUrl = this.getServerBase() + appUrl;
}
else if (this.getServerBase() === url + '/') {
rewrittenUrl = this.getServerBase();
}
// Set the URL
if (rewrittenUrl) {
this.$$parse(rewrittenUrl);
}
return !!rewrittenUrl;
}
setBrowserUrlWithFallback(url, replace, state) {
const oldUrl = this.url();
const oldState = this.$$state;
try {
this.browserUrl(url, replace, state);
// Make sure $location.state() returns referentially identical (not just deeply equal)
// state object; this makes possible quick checking if the state changed in the digest
// loop. Checking deep equality would be too expensive.
this.$$state = this.browserState();
}
catch (e) {
// Restore old values if pushState fails
this.url(oldUrl);
this.$$state = oldState;
throw e;
}
}
composeUrls() {
this.$$url = this.urlCodec.normalize(this.$$path, this.$$search, this.$$hash);
this.$$absUrl = this.getServerBase() + this.$$url.slice(1); // remove '/' from front of URL
this.updateBrowser = true;
}
/**
* Retrieves the full URL representation with all segments encoded according to
* rules specified in
* [RFC 3986](https://tools.ietf.org/html/rfc3986).
*
*
* ```js
* // given URL http://example.com/#/some/path?foo=bar&baz=xoxo
* let absUrl = $location.absUrl();
* // => "http://example.com/#/some/path?foo=bar&baz=xoxo"
* ```
*/
absUrl() {
return this.$$absUrl;
}
url(url) {
if (typeof url === 'string') {
if (!url.length) {
url = '/';
}
const match = PATH_MATCH.exec(url);
if (!match)
return this;
if (match[1] || url === '')
this.path(this.urlCodec.decodePath(match[1]));
if (match[2] || match[1] || url === '')
this.search(match[3] || '');
this.hash(match[5] || '');
// Chainable method
return this;
}
return this.$$url;
}
/**
* Retrieves the protocol of the current URL.
*
* ```js
* // given URL http://example.com/#/some/path?foo=bar&baz=xoxo
* let protocol = $location.protocol();
* // => "http"
* ```
*/
protocol() {
return this.$$protocol;
}
/**
* Retrieves the protocol of the current URL.
*
* In contrast to the non-AngularJS version `location.host` which returns `hostname:port`, this
* returns the `hostname` portion only.
*
*
* ```js
* // given URL http://example.com/#/some/path?foo=bar&baz=xoxo
* let host = $location.host();
* // => "example.com"
*
* // given URL http://user:password@example.com:8080/#/some/path?foo=bar&baz=xoxo
* host = $location.host();
* // => "example.com"
* host = location.host;
* // => "example.com:8080"
* ```
*/
host() {
return this.$$host;
}
/**
* Retrieves the port of the current URL.
*
* ```js
* // given URL http://example.com/#/some/path?foo=bar&baz=xoxo
* let port = $location.port();
* // => 80
* ```
*/
port() {
return this.$$port;
}
path(path) {
if (typeof path === 'undefined') {
return this.$$path;
}
// null path converts to empty string. Prepend with "/" if needed.
path = path !== null ? path.toString() : '';
path = path.charAt(0) === '/' ? path : '/' + path;
this.$$path = path;
this.composeUrls();
return this;
}
search(search, paramValue) {
switch (arguments.length) {
case 0:
return this.$$search;
case 1:
if (typeof search === 'string' || typeof search === 'number') {
this.$$search = this.urlCodec.decodeSearch(search.toString());
}
else if (typeof search === 'object' && search !== null) {
// Copy the object so it's never mutated
search = { ...search };
// remove object undefined or null properties
for (const key in search) {
if (search[key] == null)
delete search[key];
}
this.$$search = search;
}
else {
throw new Error('LocationProvider.search(): First argument must be a string or an object.');
}
break;
default:
if (typeof search === 'string') {
const currentSearch = this.search();
if (typeof paramValue === 'undefined' || paramValue === null) {
delete currentSearch[search];
return this.search(currentSearch);
}
else {
currentSearch[search] = paramValue;
return this.search(currentSearch);
}
}
}
this.composeUrls();
return this;
}
hash(hash) {
if (typeof hash === 'undefined') {
return this.$$hash;
}
this.$$hash = hash !== null ? hash.toString() : '';
this.composeUrls();
return this;
}
/**
* Changes to `$location` during the current `$digest` will replace the current
* history record, instead of adding a new one.
*/
replace() {
this.$$replace = true;
return this;
}
state(state) {
if (typeof state === 'undefined') {
return this.$$state;
}
this.$$state = state;
return this;
}
}
/**
* The factory function used to create an instance of the `$locationShim` in Angular,
* and provides an API-compatible `$locationProvider` for AngularJS.
*
* @publicApi
*/
class $locationShimProvider {
ngUpgrade;
location;
platformLocation;
urlCodec;
locationStrategy;
constructor(ngUpgrade, location, platformLocation, urlCodec, locationStrategy) {
this.ngUpgrade = ngUpgrade;
this.location = location;
this.platformLocation = platformLocation;
this.urlCodec = urlCodec;
this.locationStrategy = locationStrategy;
}
/**
* Factory method that returns an instance of the $locationShim
*/
$get() {
return new $locationShim(this.ngUpgrade.$injector, this.location, this.platformLocation, this.urlCodec, this.locationStrategy);
}
/**
* Stub method used to keep API compatible with AngularJS. This setting is configured through
* the LocationUpgradeModule's `config` method in your Angular app.
*/
hashPrefix(prefix) {
throw new Error('Configure LocationUpgrade through LocationUpgradeModule.config method.');
}
/**
* Stub method used to keep API compatible with AngularJS. This setting is configured through
* the LocationUpgradeModule's `config` method in your Angular app.
*/
html5Mode(mode) {
throw new Error('Configure LocationUpgrade through LocationUpgradeModule.config method.');
}
}
/**
* A codec for encoding and decoding URL parts.
*
* @publicApi
**/
class UrlCodec {
}
/**
* A `UrlCodec` that uses logic from AngularJS to serialize and parse URLs
* and URL parameters.
*
* @publicApi
*/
class AngularJSUrlCodec {
// https://github.com/angular/angular.js/blob/864c7f0/src/ng/location.js#L15
encodePath(path) {
const segments = path.split('/');
let i = segments.length;
while (i--) {
// decode forward slashes to prevent them from being double encoded
segments[i] = encodeUriSegment(segments[i].replace(/%2F/g, '/'));
}
path = segments.join('/');
return _stripIndexHtml(((path && path[0] !== '/' && '/') || '') + path);
}
// https://github.com/angular/angular.js/blob/864c7f0/src/ng/location.js#L42
encodeSearch(search) {
if (typeof search === 'string') {
search = parseKeyValue(search);
}
search = toKeyValue(search);
return search ? '?' + search : '';
}
// https://github.com/angular/angular.js/blob/864c7f0/src/ng/location.js#L44
encodeHash(hash) {
hash = encodeUriSegment(hash);
return hash ? '#' + hash : '';
}
// https://github.com/angular/angular.js/blob/864c7f0/src/ng/location.js#L27
decodePath(path, html5Mode = true) {
const segments = path.split('/');
let i = segments.length;
while (i--) {
segments[i] = decodeURIComponent(segments[i]);
if (html5Mode) {
// encode forward slashes to prevent them from being mistaken for path separators
segments[i] = segments[i].replace(/\//g, '%2F');
}
}
return segments.join('/');
}
// https://github.com/angular/angular.js/blob/864c7f0/src/ng/location.js#L72
decodeSearch(search) {
return parseKeyValue(search);
}
// https://github.com/angular/angular.js/blob/864c7f0/src/ng/location.js#L73
decodeHash(hash) {
hash = decodeURIComponent(hash);
return hash[0] === '#' ? hash.substring(1) : hash;
}
normalize(pathOrHref, search, hash, baseUrl) {
if (arguments.length === 1) {
const parsed = this.parse(pathOrHref, baseUrl);
if (typeof parsed === 'string') {
return parsed;
}
const serverUrl = `${parsed.protocol}://${parsed.hostname}${parsed.port ? ':' + parsed.port : ''}`;
return this.normalize(this.decodePath(parsed.pathname), this.decodeSearch(parsed.search), this.decodeHash(parsed.hash), serverUrl);
}
else {
const encPath = this.encodePath(pathOrHref);
const encSearch = (search && this.encodeSearch(search)) || '';
const encHash = (hash && this.encodeHash(hash)) || '';
let joinedPath = (baseUrl || '') + encPath;
if (!joinedPath.length || joinedPath[0] !== '/') {
joinedPath = '/' + joinedPath;
}
return joinedPath + encSearch + encHash;
}
}
areEqual(valA, valB) {
return this.normalize(valA) === this.normalize(valB);
}
// https://github.com/angular/angular.js/blob/864c7f0/src/ng/urlUtils.js#L60
parse(url, base) {
try {
// Safari 12 throws an error when the URL constructor is called with an undefined base.
const parsed = !base ? new URL(url) : new URL(url, base);
return {
href: parsed.href,
protocol: parsed.protocol ? parsed.protocol.replace(/:$/, '') : '',
host: parsed.host,
search: parsed.search ? parsed.search.replace(/^\?/, '') : '',
hash: parsed.hash ? parsed.hash.replace(/^#/, '') : '',
hostname: parsed.hostname,
port: parsed.port,
pathname: parsed.pathname.charAt(0) === '/' ? parsed.pathname : '/' + parsed.pathname,
};
}
catch (e) {
throw new Error(`Invalid URL (${url}) with base (${base})`);
}
}
}
function _stripIndexHtml(url) {
return url.replace(/\/index.html$/, '');
}
/**
* Tries to decode the URI component without throwing an exception.
*
* @param str value potential URI component to check.
* @returns the decoded URI if it can be decoded or else `undefined`.
*/
function tryDecodeURIComponent(value) {
try {
return decodeURIComponent(value);
}
catch (e) {
// Ignore any invalid uri component.
return undefined;
}
}
/**
* Parses an escaped url query string into key-value pairs. Logic taken from
* https://github.com/angular/angular.js/blob/864c7f0/src/Angular.js#L1382
*/
function parseKeyValue(keyValue) {
const obj = {};
(keyValue || '').split('&').forEach((keyValue) => {
let splitPoint, key, val;
if (keyValue) {
key = keyValue = keyValue.replace(/\+/g, '%20');
splitPoint = keyValue.indexOf('=');
if (splitPoint !== -1) {
key = keyValue.substring(0, splitPoint);
val = keyValue.substring(splitPoint + 1);
}
key = tryDecodeURIComponent(key);
if (typeof key !== 'undefined') {
val = typeof val !== 'undefined' ? tryDecodeURIComponent(val) : true;
if (!obj.hasOwnProperty(key)) {
obj[key] = val;
}
else if (Array.isArray(obj[key])) {
obj[key].push(val);
}
else {
obj[key] = [obj[key], val];
}
}
}
});
return obj;
}
/**
* Serializes into key-value pairs. Logic taken from
* https://github.com/angular/angular.js/blob/864c7f0/src/Angular.js#L1409
*/
function toKeyValue(obj) {
const parts = [];
for (const key in obj) {
let value = obj[key];
if (Array.isArray(value)) {
value.forEach((arrayValue) => {
parts.push(encodeUriQuery(key, true) +
(arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true)));
});
}
else {
parts.push(encodeUriQuery(key, true) +
(value === true ? '' : '=' + encodeUriQuery(value, true)));
}
}
return parts.length ? parts.join('&') : '';
}
/**
* We need our custom method because encodeURIComponent is too aggressive and doesn't follow
* https://tools.ietf.org/html/rfc3986 with regards to the character set (pchar) allowed in path
* segments:
* segment = *pchar
* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
* pct-encoded = "%" HEXDIG HEXDIG
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
* / "*" / "+" / "," / ";" / "="
*
* Logic from https://github.com/angular/angular.js/blob/864c7f0/src/Angular.js#L1437
*/
function encodeUriSegment(val) {
return encodeUriQuery(val, true).replace(/%26/g, '&').replace(/%3D/gi, '=').replace(/%2B/gi, '+');
}
/**
* This method is intended for encoding *key* or *value* parts of query component. We need a custom
* method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be
* encoded per https://tools.ietf.org/html/rfc3986:
* query = *( pchar / "/" / "?" )
* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
* pct-encoded = "%" HEXDIG HEXDIG
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
* / "*" / "+" / "," / ";" / "="
*
* Logic from https://github.com/angular/angular.js/blob/864c7f0/src/Angular.js#L1456
*/
function encodeUriQuery(val, pctEncodeSpaces = false) {
return encodeURIComponent(val)
.replace(/%40/g, '@')
.replace(/%3A/gi, ':')
.replace(/%24/g, '$')
.replace(/%2C/gi, ',')
.replace(/%3B/gi, ';')
.replace(/%20/g, pctEncodeSpaces ? '%20' : '+');
}
/**
* A provider token used to configure the location upgrade module.
*
* @publicApi
*/
const LOCATION_UPGRADE_CONFIGURATION = new InjectionToken(ngDevMode ? 'LOCATION_UPGRADE_CONFIGURATION' : '');
const APP_BASE_HREF_RESOLVED = new InjectionToken(ngDevMode ? 'APP_BASE_HREF_RESOLVED' : '');
/**
* `NgModule` used for providing and configuring Angular's Unified Location Service for upgrading.
*
* @see [Using the Unified Angular Location Service](https://angular.io/guide/upgrade#using-the-unified-angular-location-service)
*
* @publicApi
*/
class LocationUpgradeModule {
static config(config) {
return {
ngModule: LocationUpgradeModule,
providers: [
Location,
{
provide: $locationShim,
useFactory: provide$location,
deps: [UpgradeModule, Location, PlatformLocation, UrlCodec, LocationStrategy],
},
{ provide: LOCATION_UPGRADE_CONFIGURATION, useValue: config ? config : {} },
{ provide: UrlCodec, useFactory: provideUrlCodec, deps: [LOCATION_UPGRADE_CONFIGURATION] },
{
provide: APP_BASE_HREF_RESOLVED,
useFactory: provideAppBaseHref,
deps: [LOCATION_UPGRADE_CONFIGURATION, [new Inject(APP_BASE_HREF), new Optional()]],
},
{
provide: LocationStrategy,
useFactory: provideLocationStrategy,
deps: [PlatformLocation, APP_BASE_HREF_RESOLVED, LOCATION_UPGRADE_CONFIGURATION],
},
],
};
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: LocationUpgradeModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.11", ngImport: i0, type: LocationUpgradeModule, imports: [CommonModule] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: LocationUpgradeModule, imports: [CommonModule] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: LocationUpgradeModule, decorators: [{
type: NgModule,
args: [{ imports: [CommonModule] }]
}] });
function provideAppBaseHref(config, appBaseHref) {
if (config && config.appBaseHref != null) {
return config.appBaseHref;
}
else if (appBaseHref != null) {
return appBaseHref;
}
return '';
}
function provideUrlCodec(config) {
const codec = (config && config.urlCodec) || AngularJSUrlCodec;
return new codec();
}
function provideLocationStrategy(platformLocation, baseHref, options = {}) {
return options.useHash
? new HashLocationStrategy(platformLocation, baseHref)
: new PathLocationStrategy(platformLocation, baseHref);
}
function provide$location(ngUpgrade, location, platformLocation, urlCodec, locationStrategy) {
const $locationProvider = new $locationShimProvider(ngUpgrade, location, platformLocation, urlCodec, locationStrategy);
return $locationProvider.$get();
}
export { $locationShim, $locationShimProvider, AngularJSUrlCodec, LOCATION_UPGRADE_CONFIGURATION, LocationUpgradeModule, UrlCodec };
//# sourceMappingURL=upgrade.mjs.map

1
node_modules/@angular/common/fesm2022/upgrade.mjs.map generated vendored Executable file

File diff suppressed because one or more lines are too long

28
node_modules/@angular/common/fesm2022/xhr.mjs generated vendored Executable file
View File

@@ -0,0 +1,28 @@
/**
* @license Angular v20.3.11
* (c) 2010-2025 Google LLC. https://angular.dev/
* License: MIT
*/
function parseCookieValue(cookieStr, name) {
name = encodeURIComponent(name);
for (const cookie of cookieStr.split(';')) {
const eqIndex = cookie.indexOf('=');
const [cookieName, cookieValue] = eqIndex == -1 ? [cookie, ''] : [cookie.slice(0, eqIndex), cookie.slice(eqIndex + 1)];
if (cookieName.trim() === name) {
return decodeURIComponent(cookieValue);
}
}
return null;
}
/**
* A wrapper around the `XMLHttpRequest` constructor.
*
* @publicApi
*/
class XhrFactory {
}
export { XhrFactory, parseCookieValue };
//# sourceMappingURL=xhr.mjs.map

1
node_modules/@angular/common/fesm2022/xhr.mjs.map generated vendored Executable file
View File

@@ -0,0 +1 @@
{"version":3,"file":"xhr.mjs","sources":["../../../../../k8-fastbuild-ST-199a4f3c4e20/bin/packages/common/src/cookie.ts","../../../../../k8-fastbuild-ST-199a4f3c4e20/bin/packages/common/src/xhr.ts"],"sourcesContent":["/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.dev/license\n */\n\nexport function parseCookieValue(cookieStr: string, name: string): string | null {\n name = encodeURIComponent(name);\n for (const cookie of cookieStr.split(';')) {\n const eqIndex = cookie.indexOf('=');\n const [cookieName, cookieValue]: string[] =\n eqIndex == -1 ? [cookie, ''] : [cookie.slice(0, eqIndex), cookie.slice(eqIndex + 1)];\n if (cookieName.trim() === name) {\n return decodeURIComponent(cookieValue);\n }\n }\n return null;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.dev/license\n */\n\n/**\n * A wrapper around the `XMLHttpRequest` constructor.\n *\n * @publicApi\n */\nexport abstract class XhrFactory {\n abstract build(): XMLHttpRequest;\n}\n"],"names":[],"mappings":";;;;;;AAQgB,SAAA,gBAAgB,CAAC,SAAiB,EAAE,IAAY,EAAA;AAC9D,IAAA,IAAI,GAAG,kBAAkB,CAAC,IAAI,CAAC;IAC/B,KAAK,MAAM,MAAM,IAAI,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;QACzC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC;AACnC,QAAA,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,GAC7B,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;AACtF,QAAA,IAAI,UAAU,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE;AAC9B,YAAA,OAAO,kBAAkB,CAAC,WAAW,CAAC;;;AAG1C,IAAA,OAAO,IAAI;AACb;;ACXA;;;;AAIG;MACmB,UAAU,CAAA;AAE/B;;;;"}