Skip to content

Commit

Permalink
feat: add manager provider APIs v2
Browse files Browse the repository at this point in the history
  • Loading branch information
davidlj95 committed Oct 13, 2024
1 parent 479fe2b commit e02ec1d
Show file tree
Hide file tree
Showing 7 changed files with 407 additions and 6 deletions.
63 changes: 63 additions & 0 deletions projects/ngx-meta/api-extractor/ngx-meta.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -417,9 +417,32 @@ export const provideNgxMetaCore: (...features: CoreFeatures) => EnvironmentProvi
// @public
export const provideNgxMetaJsonLd: () => Provider[];

// Warning: (ae-incompatible-release-tags) The symbol "provideNgxMetaManager" is marked as @alpha, but its signature references "_ProvideNgxMetaManagerOptions" which is marked as @internal
//
// @alpha (undocumented)
export const provideNgxMetaManager: <T>(jsonPath: string, setterFactory: MetadataSetterFactory<T>, options?: _ProvideNgxMetaManagerOptions) => FactoryProvider;

// @internal (undocumented)
export type _ProvideNgxMetaManagerOptions = Partial<{
deps: FactoryProvider['deps'];
global: MetadataResolverOptions['global'];
id: NgxMetaMetadataManager['id'];
objectMerge: MetadataResolverOptions['objectMerge'];
}>;

// @public
export const provideNgxMetaMetadataLoader: () => Provider[];

// @internal (undocumented)
export const _provideNgxMetaModuleManager: <Type extends object, Key extends Extract<keyof Type, string>>(key: Key, options?: _ProvideNgxMetaModuleManagerOptions<Type[Key]>) => FactoryProvider;

// @internal (undocumented)
export type _ProvideNgxMetaModuleManagerOptions<T> = Partial<{
scope: ReadonlyArray<string>;
setterFactory: MetadataSetterFactory<T>;
nameAttribute: NgxMetaElementNameAttribute;
}> & _ProvideNgxMetaManagerOptions;

// @public
export const provideNgxMetaOpenGraph: () => Provider[];

Expand Down Expand Up @@ -589,6 +612,46 @@ export const withContentAttribute: {
(content: string | null | undefined, extras?: NgxMetaElementAttributes): NgxMetaElementAttributes | undefined;
};

// Warning: (ae-incompatible-release-tags) The symbol "withManagerDeps" is marked as @alpha, but its signature references "_ProvideNgxMetaManagerOptions" which is marked as @internal
//
// @alpha (undocumented)
export const withManagerDeps: (...deps: Exclude<FactoryProvider['deps'], undefined>) => Partial<_ProvideNgxMetaManagerOptions>;

// Warning: (ae-incompatible-release-tags) The symbol "withManagerGlobal" is marked as @alpha, but its signature references "_ProvideNgxMetaManagerOptions" which is marked as @internal
//
// @alpha (undocumented)
export const withManagerGlobal: (global: string) => Partial<_ProvideNgxMetaManagerOptions>;

// Warning: (ae-incompatible-release-tags) The symbol "withManagerId" is marked as @alpha, but its signature references "_ProvideNgxMetaManagerOptions" which is marked as @internal
//
// @alpha (undocumented)
export const withManagerId: (id: string) => Partial<_ProvideNgxMetaManagerOptions>;

// @alpha (undocumented)
export const withManagerJsonPath: (...jsonPath: MetadataResolverOptions['jsonPath']) => string;

// Warning: (ae-incompatible-release-tags) The symbol "withManagerObjectMerging" is marked as @alpha, but its signature references "_ProvideNgxMetaManagerOptions" which is marked as @internal
//
// @alpha (undocumented)
export const withManagerObjectMerging: () => Partial<_ProvideNgxMetaManagerOptions>;

// Warning: (ae-incompatible-release-tags) The symbol "withManagerOptions" is marked as @alpha, but its signature references "_ProvideNgxMetaManagerOptions" which is marked as @internal
//
// @alpha (undocumented)
export const withManagerOptions: (...options: ReadonlyArray<_ProvideNgxMetaManagerOptions>) => _ProvideNgxMetaManagerOptions;

// @internal (undocumented)
export const _withModuleManagerNameAttribute: <T>(nameAttribute: NgxMetaElementNameAttribute) => _ProvideNgxMetaModuleManagerOptions<T>;

// @internal (undocumented)
export const _withModuleManagerOptions: <T>(...options: ReadonlyArray<_ProvideNgxMetaModuleManagerOptions<T>>) => _ProvideNgxMetaModuleManagerOptions<T>;

// @internal (undocumented)
export const _withModuleManagerScope: <T>(...scope: ReadonlyArray<string>) => _ProvideNgxMetaModuleManagerOptions<T>;

// @internal (undocumented)
export const _withModuleManagerSetterFactory: <T>(setterFactory: MetadataSetterFactory<T>) => _ProvideNgxMetaModuleManagerOptions<T>;

// @public
export const withNameAttribute: (value: string) => readonly ["name", string];

Expand Down
6 changes: 1 addition & 5 deletions projects/ngx-meta/src/core/src/managers/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
export {
makeMetadataManagerProviderFromSetterFactory,
MetadataSetterFactory,
MakeMetadataManagerProviderFromSetterFactoryOptions,
} from './make-metadata-manager-provider-from-setter-factory'
export {
_injectMetadataManagers,
NgxMetaMetadataManager,
MetadataSetter,
MetadataResolverOptions,
} from './ngx-meta-metadata-manager'
export * from './provider'
23 changes: 23 additions & 0 deletions projects/ngx-meta/src/core/src/managers/provider/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
export {
provideNgxMetaManager,
withManagerOptions,
withManagerDeps,
withManagerGlobal,
withManagerId,
withManagerObjectMerging,
withManagerJsonPath,
_ProvideNgxMetaManagerOptions,
} from './provide-ngx-meta-manager'
export {
_provideNgxMetaModuleManager,
_ProvideNgxMetaModuleManagerOptions,
_withModuleManagerNameAttribute,
_withModuleManagerOptions,
_withModuleManagerScope,
_withModuleManagerSetterFactory,
} from './provide-ngx-meta-module-manager'
export {
makeMetadataManagerProviderFromSetterFactory,
MetadataSetterFactory,
MakeMetadataManagerProviderFromSetterFactoryOptions,
} from './make-metadata-manager-provider-from-setter-factory'
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
MetadataResolverOptions,
MetadataSetter,
NgxMetaMetadataManager,
} from './ngx-meta-metadata-manager'
} from '../ngx-meta-metadata-manager'
import { FactoryProvider } from '@angular/core'

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import { injectOneMetadataManager } from '@/ngx-meta/test/inject-one-metadata-manager'
import { FactoryProvider, InjectionToken, Provider } from '@angular/core'
import { TestBed } from '@angular/core/testing'
import { DOCUMENT } from '@angular/common'
import { Router } from '@angular/router'
import { MetadataSetterFactory } from './make-metadata-manager-provider-from-setter-factory'
import { _isDefined } from '../../utils'
import {
provideNgxMetaManager,
withManagerDeps,
withManagerGlobal,
withManagerId,
withManagerObjectMerging,
withManagerOptions,
} from './provide-ngx-meta-manager'

describe('provide manager', () => {
const jsonPathAsArray = ['dummy-scope', 'dummy-key']
const jsonPath = 'dummy-scope.dummy-key'

it('should provide a manager with the given JSON path', () => {
const provider = makeSut({ jsonPath })

const manager = provideAndInject(provider)

expect(manager.resolverOptions.jsonPath).toEqual(jsonPathAsArray)
})

it('should provide a manager with JSON path as id', () => {
const provider = makeSut({ jsonPath })

const manager = provideAndInject(provider)

expect(manager.id).toEqual(jsonPath)
})

it('should provide a manager with the given factory', () => {
const setter = () => {}
const provider = makeSut({ factory: () => setter })

const manager = provideAndInject(provider)

expect(manager.set).toEqual(setter)
})

describe('when dependencies are given', () => {
const deps = [DOCUMENT, Router] satisfies FactoryProvider['deps']

it('should pass them to the factory function', () => {
const factory = jasmine
.createSpy<MetadataSetterFactory<unknown>>()
.and.returnValue(() => {})
const provider = makeSut({ deps, factory })

provideAndInject(provider)

expect(factory).toHaveBeenCalledWith(
...deps.map((dep) => TestBed.inject(dep as InjectionToken<unknown>)),
)
})
})

describe('when global is given', () => {
const global = 'global'

it('should set it in the manager', () => {
const provider = makeSut({ global })

const manager = provideAndInject(provider)

expect(manager.resolverOptions.global).toEqual(global)
})
})

describe('when an id is given', () => {
const id = 'id'

it('should set it in the manager', () => {
const provider = makeSut({ id })

const manager = provideAndInject(provider)

expect(manager.id).toEqual(id)
})
})

describe('when object merging is enabled', () => {
const objectMerge = true

it('should set it in the manager', () => {
const provider = makeSut({ objectMerge })

const manager = provideAndInject(provider)

expect(manager.resolverOptions.objectMerge).toBeTrue()
})
})
})

const makeSut = (
opts: {
jsonPath?: string
factory?: MetadataSetterFactory<unknown>
deps?: FactoryProvider['deps']
global?: string
id?: string
objectMerge?: true
} = {},
) =>
provideNgxMetaManager(
opts.jsonPath ?? 'dummy-scope.dummy-key',
opts.factory ?? (() => () => {}),
withManagerOptions(
...[
opts.deps ? withManagerDeps(...opts.deps) : undefined,
opts.global ? withManagerGlobal(opts.global) : undefined,
opts.id ? withManagerId(opts.id) : undefined,
opts.objectMerge ? withManagerObjectMerging() : undefined,
].filter(_isDefined),
),
)

const provideAndInject = (provider: Provider) => {
TestBed.configureTestingModule({ providers: [provider] })
return injectOneMetadataManager()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { MetadataSetterFactory } from './make-metadata-manager-provider-from-setter-factory'
import { FactoryProvider } from '@angular/core'
import {
MetadataResolverOptions,
NgxMetaMetadataManager,
} from '../ngx-meta-metadata-manager'

/**
* @param jsonPath -
* @param setterFactory -
* @param options -
*
* @alpha
*/
export const provideNgxMetaManager = <T>(
jsonPath: string,
setterFactory: MetadataSetterFactory<T>,
options: _ProvideNgxMetaManagerOptions = {},
): FactoryProvider => ({
provide: NgxMetaMetadataManager,
multi: true,
useFactory: (...deps: ReadonlyArray<unknown>) =>
({
id: options.id ?? jsonPath,
set: setterFactory(...deps),
resolverOptions: {
jsonPath: jsonPath.split('.'),
global: options.global,
objectMerge: options.objectMerge,
},
}) satisfies NgxMetaMetadataManager<T>,
deps: options.deps,
})

/**
* @internal
*/
export type _ProvideNgxMetaManagerOptions = Partial<{
deps: FactoryProvider['deps']
global: MetadataResolverOptions['global']
id: NgxMetaMetadataManager['id']
objectMerge: MetadataResolverOptions['objectMerge']
}>

/**
*
* @param options -
*
* @alpha
*/
export const withManagerOptions = (
...options: ReadonlyArray<_ProvideNgxMetaManagerOptions>
): _ProvideNgxMetaManagerOptions =>
options.reduce<Partial<_ProvideNgxMetaManagerOptions>>(
(acc, curr) => ({ ...acc, ...curr }),
{},
)

/**
*
* @param deps -
*
* @alpha
*/
export const withManagerDeps = (
...deps: Exclude<FactoryProvider['deps'], undefined>
): Partial<_ProvideNgxMetaManagerOptions> => ({
deps,
})

/**
*
* @param global -
*
* @alpha
*/
export const withManagerGlobal = (
global: string,
): Partial<_ProvideNgxMetaManagerOptions> => ({ global })

/**
*
* @param id -
*
* @alpha
*/
export const withManagerId = (
id: string,
): Partial<_ProvideNgxMetaManagerOptions> => ({ id })

/**
* @alpha
*/
export const withManagerObjectMerging =
(): Partial<_ProvideNgxMetaManagerOptions> => ({ objectMerge: true })

/**
*
* @param jsonPath -
*
* @alpha
*/
export const withManagerJsonPath = (
...jsonPath: MetadataResolverOptions['jsonPath']
): string => jsonPath.join('.')

Check warning on line 105 in projects/ngx-meta/src/core/src/managers/provider/provide-ngx-meta-manager.ts

View check run for this annotation

Codecov / codecov/patch

projects/ngx-meta/src/core/src/managers/provider/provide-ngx-meta-manager.ts#L105

Added line #L105 was not covered by tests
Loading

0 comments on commit e02ec1d

Please sign in to comment.