Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ Thumbs.db

# Caches
.angular
.nx
.nx/cache
.nx/workspace-data
.sass-cache

# Logs
Expand Down
28 changes: 28 additions & 0 deletions .verdaccio/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# path to a directory with all packages
storage: ../tmp/local-registry/storage

# a list of other known repositories we can talk to
uplinks:
npmjs:
url: https://registry.npmjs.org/
maxage: 60m

packages:
'**':
# give all users (including non-authenticated users) full access
# because it is a local registry
access: $all
publish: $all
unpublish: $all

# if package is not available locally, proxy requests to npm registry
proxy: npmjs

# log settings
log:
type: stdout
format: pretty
level: warn

publish:
allow_offline: true # set offline to true to allow publish offline
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ResolveFn } from '@angular/router';
import { joinWithSlash } from '@hra-ui/common/url';
import { joinWithSlashes } from '@hra-ui/utils/paths';
import { ContentPageData, ContentPageDataSchema } from '@hra-ui/design-system/content-templates/content-page';
import { createYamlSpecResolver } from '@hra-ui/design-system/content-templates/resolvers';

Expand All @@ -11,7 +11,7 @@ import { createYamlSpecResolver } from '@hra-ui/design-system/content-templates/
export function createReleaseNotesContentResolver(baseUrl: string): ResolveFn<ContentPageData> {
return (route, state) => {
const version = route.params['version'] as string;
const url = joinWithSlash(baseUrl, `${version}.yaml`);
const url = joinWithSlashes(baseUrl, `${version}.yaml`);
const resolver = createYamlSpecResolver(url, ContentPageDataSchema);
return resolver(route, state);
};
Expand Down
12 changes: 6 additions & 6 deletions libs/cdk/injectors/src/lib/dispatch/dispatch.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { inject } from '@angular/core';
import type { Any } from '@hra-ui/utils/types';
import { Store } from '@ngxs/store';
import { map, Observable } from 'rxjs';

Expand All @@ -19,7 +19,7 @@ function pipeActionInstance<A>(action: A, obs$: Observable<void>): Observable<A>
* @param boundArgs Initial bound arguments
* @returns A factory function creating a new action on each call
*/
function createActionFactory<A, BoundArgs extends Any[], RestArgs extends Any[]>(
function createActionFactory<A, BoundArgs extends any[], RestArgs extends any[]>(
type: new (...args: [...BoundArgs, ...RestArgs]) => A,
boundArgs: BoundArgs,
): (...args: RestArgs) => A {
Expand All @@ -32,14 +32,14 @@ function createActionFactory<A, BoundArgs extends Any[], RestArgs extends Any[]>
* @param resultHandler Selects the output value from the action and the dispatch observable
* @returns A new dispatch function taking user arguments, dispatches actions, and returns a value
*/
function dispatchImpl<A, R, Args extends Any[]>(
function dispatchImpl<A, R, Args extends any[]>(
actionFactory: (...args: Args) => A,
resultHandler: (action: A, obs$: Observable<void>) => R,
): (...args: Args) => R {
const store = inject(Store);
return (...args) => {
const action = actionFactory(...args);
const obs$ = store.dispatch(action as Any);
const obs$ = store.dispatch(action as any);
return resultHandler(action, obs$);
};
}
Expand All @@ -51,7 +51,7 @@ function dispatchImpl<A, R, Args extends Any[]>(
* @param boundArgs Bound arguments to the action constructor
* @returns A function that dispatches an action on the store each time it is called
*/
export function dispatch<A, BoundArgs extends Any[], DispatchArgs extends Any[]>(
export function dispatch<A, BoundArgs extends any[], DispatchArgs extends any[]>(
type: new (...args: [...BoundArgs, ...DispatchArgs]) => A,
...boundArgs: BoundArgs
): (...args: DispatchArgs) => A {
Expand All @@ -67,7 +67,7 @@ export function dispatch<A, BoundArgs extends Any[], DispatchArgs extends Any[]>
* @param boundArgs Bound arguments to the action constructor
* @returns A function that dispatches an action on the store each time it is called
*/
export function dispatch$<A, BoundArgs extends Any[], DispatchArgs extends Any[]>(
export function dispatch$<A, BoundArgs extends any[], DispatchArgs extends any[]>(
type: new (...args: [...BoundArgs, ...DispatchArgs]) => A,
...boundArgs: BoundArgs
): (...args: DispatchArgs) => Observable<A> {
Expand Down
12 changes: 6 additions & 6 deletions libs/cdk/injectors/src/lib/select/select-snapshot.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import type { Any, AnyFunction } from '@hra-ui/utils/types';
/* eslint-disable @typescript-eslint/no-explicit-any */
import { select$, StateSelector } from './select';
import { SnapshotObserver } from './snapshot-observer';

/** Get remaining arguments after applying bound arguments */
type RestArgs<F extends AnyFunction, BoundArgs extends Any[]> = F extends (
type RestArgs<F extends (...args: any[]) => any, BoundArgs extends any[]> = F extends (
...args: [...BoundArgs, ...infer Rest]
) => Any
) => any
? Rest
: never;

/** Function type returned by {@link selectQuerySnapshot} */
type SelectQuery<F extends AnyFunction, BoundArgs extends Any[]> = <
type SelectQuery<F extends (...args: any[]) => any, BoundArgs extends any[]> = <
Res = ReturnType<F>,
Args extends Any[] = RestArgs<F, BoundArgs>
Args extends any[] = RestArgs<F, BoundArgs>,
>(
...args: Args
) => Res;
Expand Down Expand Up @@ -62,7 +62,7 @@ export function selectSnapshot<T>(selector: StateSelector<T>): () => T {
* @param boundArgs Optional bound query arguments
* @returns A snapshot function taking the same arguments as the query selector (excluding bound arguments)
*/
export function selectQuerySnapshot<F extends (...args: [...BoundArgs, ...Any[]]) => Any, BoundArgs extends Any[]>(
export function selectQuerySnapshot<F extends (...args: [...BoundArgs, ...any[]]) => any, BoundArgs extends any[]>(
selector: StateSelector<F>,
...boundArgs: BoundArgs
): SelectQuery<F, BoundArgs> {
Expand Down
4 changes: 2 additions & 2 deletions libs/cdk/injectors/src/lib/select/select.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { ChangeDetectorRef, inject } from '@angular/core';
import { Any } from '@hra-ui/utils/types';
import { StateToken, Store } from '@ngxs/store';
import { MonoTypeOperatorFunction, Observable, takeUntil, tap } from 'rxjs';
import { injectDestroy$ } from '../on-destroy/on-destroy';

/** Selector type for select style functions */
export type StateSelector<T> = ((...args: Any[]) => T) | StateToken<T>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type StateSelector<T> = ((...args: any[]) => T) | StateToken<T>;

/** `select$` configuration options */
export interface SelectOptions {
Expand Down
1 change: 0 additions & 1 deletion libs/cdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
"@angular/common": "^21.1.4",
"@angular/core": "^21.1.4",
"@ngxs/store": "^21.0.0",
"@hra-ui/utils": "*",
"@angular/cdk": "^21.1.4",
"rxjs": "^7.8.2",
"@hra-ui/common": "1.1.0",
Expand Down
11 changes: 9 additions & 2 deletions libs/cdk/src/lib/link/link.directive.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import { Directive, DoCheck, ElementRef, inject, Injector, Input } from '@angular/core';
import { ActivatedRoute, Params, QueryParamsHandling, UrlCreationOptions } from '@angular/router';
import { dispatch, selectQuerySnapshot } from '@hra-ui/cdk/injectors';
import { EMPTY_LINK, LinkEntry, LinkRegistryActions, LinkRegistrySelectors, LinkType } from '@hra-ui/cdk/state';
import { createExternalUrl, createInternalUrl } from '@hra-ui/utils';
import {
createExternalUrl,
createInternalUrl,
EMPTY_LINK,
LinkEntry,
LinkRegistryActions,
LinkRegistrySelectors,
LinkType,
} from '@hra-ui/cdk/state';

/** Link Directive for routing */
@Directive({
Expand Down
3 changes: 2 additions & 1 deletion libs/cdk/state/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
export { assertUniqueActionType, registerActionType } from './actions/action-type-registry';
export { Action, ActionGroup, ActionConstructor } from './actions/actions';
export { Action, ActionConstructor, ActionGroup } from './actions/actions';
export * from './base-href';
export * from './link-registry';
export * from './link-registry/url/create';
export * from './resource-registry';
export * from './state.module';
export * from './storage';
7 changes: 3 additions & 4 deletions libs/cdk/state/src/link-registry/link-registry.selectors.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { UnionMember } from '@hra-ui/utils/types';
import { Selector } from '@ngxs/store';
import { LinkEntry, LinkId, LinkRegistryModel, LinkType } from './link-registry.model';
import { LinkRegistryQuery, LinkRegistryState } from './link-registry.state';
Expand Down Expand Up @@ -27,9 +26,9 @@ export class LinkRegistrySelectors {
private static getEntry<T extends LinkType | string>(
state: LinkRegistryModel,
id: LinkId,
type?: T
): UnionMember<LinkEntry, 'type', T> | undefined {
const entry = state[id] as UnionMember<LinkEntry, 'type', T>;
type?: T,
): Extract<LinkEntry, { type: T }> | undefined {
const entry = state[id] as Extract<LinkEntry, { type: T }>;
const typeMatches = type === undefined || entry?.type === type;
return typeMatches ? entry : undefined;
}
Expand Down
7 changes: 3 additions & 4 deletions libs/cdk/state/src/link-registry/link-registry.state.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
import { HttpClient } from '@angular/common/http';
import { inject, Injectable, NgZone } from '@angular/core';
import { Router, UrlCreationOptions } from '@angular/router';
import { createExternalUrl } from '@hra-ui/utils';
import { UnionMember } from '@hra-ui/utils/types';
import { createExternalUrl } from './url/create';
import { Action, State } from '@ngxs/store';
import { load } from 'js-yaml';
import { map, Observable } from 'rxjs';
import { Add, AddFromYaml, AddMany, LoadFromYaml, Navigate } from './link-registry.actions';
import {
ExternalLinkEntry,
InternalLinkEntry,
LINK_REGISTRY_SCHEMA,
LinkEntry,
LinkId,
LinkRegistryContext,
LinkRegistryModel,
LinkType,
LINK_REGISTRY_SCHEMA,
} from './link-registry.model';

/** Query function for link entry optionally with type specified */
export type LinkRegistryQuery = <T extends LinkType | string = string>(
id: LinkId,
type?: T,
) => UnionMember<LinkEntry, 'type', T> | undefined;
) => Extract<LinkEntry, { type: T }> | undefined;

/** State for keeping track of links globally */
@State<LinkRegistryModel>({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { LocationStrategy } from '@angular/common';
import { Injector, SecurityContext } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { ActivatedRoute, Params, Router, UrlCreationOptions } from '@angular/router';
import { Any } from '@hra-ui/utils/types';

/**
* Sets parameters with non-nullish values on a URLSearchParams
Expand All @@ -27,7 +26,8 @@ function setQueryParams(dest: URLSearchParams, params: Params | null | undefined
*/
export function createInternalUrl(
injector: Injector,
commands: Any[],
// eslint-disable-next-line @typescript-eslint/no-explicit-any
commands: any[],
extras: UrlCreationOptions,
isResourceUrl: boolean,
): string | undefined {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { UnionMember } from '@hra-ui/utils/types';
import { StateContext } from '@ngxs/store';
import * as z from 'zod';

Expand Down Expand Up @@ -41,7 +40,7 @@ export const RESOURCE_ID = z
// ------------------------------------

/** Extracts the builtin entry with type T */
type ExtractBuiltinEntryType<T> = UnionMember<z.infer<typeof BUILTIN_ENTRY>, 'type', T>;
type ExtractBuiltinEntryType<T> = Extract<z.infer<typeof BUILTIN_ENTRY>, { type: T }>;

/** Maps raw builtin type strings to ResourceType */
type BuiltinTypes<T = typeof RawBuiltinResourceType> = {
Expand Down
10 changes: 5 additions & 5 deletions libs/common/analytics/src/lib/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
makeEnvironmentProviders,
provideAppInitializer,
} from '@angular/core';
import { createFeature, getFeatureProviders, ProviderFeature } from '@hra-ui/common/util/providers';
import { createProviderFeature, getProvidersForFeatures, ProviderFeature } from '@hra-ui/utils/di';
import { AnalyticsPlugin } from 'analytics';
import {
AnalyticsErrorHandler,
Expand All @@ -30,7 +30,7 @@ const enum AnalyticsFeatureKind {
* @returns An analytics feature
*/
export function withErrorHandler(config: AnalyticsErrorHandlerConfig = {}): AnalyticsFeature {
return createFeature(AnalyticsFeatureKind.ErrorHandler, [
return createProviderFeature(AnalyticsFeatureKind.ErrorHandler, [
provideAnalyticsErrorHandlerConfig(config),
{
provide: ErrorHandlerToken,
Expand All @@ -46,7 +46,7 @@ export function withErrorHandler(config: AnalyticsErrorHandlerConfig = {}): Anal
* @returns An analytics feature
*/
export function withPlugins(...plugins: (AnalyticsPlugin | (() => AnalyticsPlugin))[]): AnalyticsFeature {
return createFeature(
return createProviderFeature(
AnalyticsFeatureKind.Plugins,
plugins.map((plugin) => providePlugin(plugin)),
);
Expand All @@ -58,7 +58,7 @@ export function withPlugins(...plugins: (AnalyticsPlugin | (() => AnalyticsPlugi
* @returns An analytics feature
*/
export function withRouterEvents(): AnalyticsFeature {
return createFeature(AnalyticsFeatureKind.RouterEvents, [provideAppInitializer(setupRouterEventListener)]);
return createProviderFeature(AnalyticsFeatureKind.RouterEvents, [provideAppInitializer(setupRouterEventListener)]);
}

/**
Expand All @@ -68,5 +68,5 @@ export function withRouterEvents(): AnalyticsFeature {
* @returns Environment providers
*/
export function provideAnalytics(...features: AnalyticsFeature[]): EnvironmentProviders {
return makeEnvironmentProviders([...features.flatMap(getFeatureProviders)]);
return makeEnvironmentProviders(getProvidersForFeatures(features));
}
3 changes: 2 additions & 1 deletion libs/common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"type-fest": "^5.0.1",
"@angular/forms": "^21.1.4",
"nanoid": "^5.1.5",
"store2": "^2.14.4"
"store2": "^2.14.4",
"@hra-ui/utils": "0.0.1"
},
"sideEffects": false
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Directive, input } from '@angular/core';
import { stripLeadingHash } from '@hra-ui/common/url';
import { stripLeadingHash } from '@hra-ui/utils/paths';
import { injectRouter } from '../injectors';
import { isAuxClick } from '../util/event';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { computed, contentChildren, Directive, effect, inject, input, output } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { IsActiveMatchOptions, NavigationEnd } from '@angular/router';
import { IsActiveMatchOptions, isActive as isUrlTreeActive, NavigationEnd } from '@angular/router';
import { injectWindow } from '@hra-ui/common/injectors';
import { isUrlActive } from '@hra-ui/common/url';
import { isUrlActive } from '@hra-ui/utils/paths';
import { createNotifier } from 'ngxtension/create-notifier';
import { injectRouter } from '../injectors';
import { LinkDirective } from '../link/link.directive';
Expand Down Expand Up @@ -98,7 +98,7 @@ export class LinkActiveDirective {
return false;
}

return router.isActive(urlTree, options);
return isUrlTreeActive(urlTree, router, options)();
});
}
}
5 changes: 3 additions & 2 deletions libs/common/router-ext/src/lib/link/link.directive.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { LocationStrategy } from '@angular/common';
import { booleanAttribute, computed, Directive, inject, input } from '@angular/core';
import { injectAppUrlResolver, isAbsolute, stripTrailingSlash } from '@hra-ui/common/url';
import { injectAppUrlResolver } from '@hra-ui/common/url';
import { isAbsoluteUrl, stripTrailingSlash } from '@hra-ui/utils/paths';
import { injectRouter } from '../injectors';
import { isAuxClick } from '../util/event';

Expand Down Expand Up @@ -30,7 +31,7 @@ export class LinkDirective {
const { router, resolve } = this;
if (router && !this.external()) {
const url = resolve(this.url());
if (!isAbsolute(url)) {
if (!isAbsoluteUrl(url)) {
return router.parseUrl(stripTrailingSlash(url));
}
}
Expand Down
4 changes: 2 additions & 2 deletions libs/common/router-ext/src/lib/providers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { EnvironmentProviders, inject, makeEnvironmentProviders } from '@angular/core';
import { Router } from '@angular/router';
import { getFeatureProviders, ProviderFeature } from '@hra-ui/common/util/providers';
import { getProvidersForFeatures, ProviderFeature } from '@hra-ui/utils/di';
import { provideRouter } from './injectors';

/** Router extension feature */
Expand All @@ -17,5 +17,5 @@ const enum RouterExtFeatureKind {}
* @returns Environment providers
*/
export function provideRouterExt(...features: RouterExtFeature[]): EnvironmentProviders {
return makeEnvironmentProviders([provideRouter(() => inject(Router)), ...features.flatMap(getFeatureProviders)]);
return makeEnvironmentProviders([provideRouter(() => inject(Router)), ...getProvidersForFeatures(features)]);
}
2 changes: 0 additions & 2 deletions libs/common/url/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,4 @@ export { appUrl, AppUrlPipe, injectAppHref, injectAppUrlResolver, provideAppHref
export { assetUrl, AssetUrlPipe, injectAssetHref, injectAssetUrlResolver, provideAssetHref } from './lib/url/asset';
export { cssUrl, CssUrlPipe } from './lib/url/css';
export { injectPageHref, injectPageUrlResolver, pageUrl, PageUrlPipe, providePageHref } from './lib/url/page';
export { isUrlActive } from './lib/util/compare-url';
export { isAbsolute, joinWithSlash, stripLeadingHash, stripTrailingSlash } from './lib/util/path';
export { InjectHrefFn, InjectUrlResolverFn, ProvideHrefFn, UrlResolverFn } from './lib/util/types';
Loading
Loading