Skip to content

Commit

Permalink
fix: add secondary entry points
Browse files Browse the repository at this point in the history
EmmanuelRoux committed Sep 2, 2023

Verified

This commit was signed with the committer’s verified signature.
EmmanuelRoux Emmanuel Roux
1 parent 84d6b83 commit 89f9344
Showing 57 changed files with 310 additions and 244 deletions.
31 changes: 27 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -28,8 +28,9 @@

<hr>

**Note: this library was previously distributed as `@ngx-matomo/tracker` and `@ngx-matomo/router` packages. Since version 5, it is now distributed as a single package `ngx-matomo-client`.
Follow [instructions below](#migration-from-version--4-ngx-matomotracker-and-ngx-matomorouter) for how to
**Note: this library was previously distributed as `@ngx-matomo/tracker` and `@ngx-matomo/router` packages. Since
version 5, it is now distributed as a single package `ngx-matomo-client`.
Follow [instructions below](#migration-from-ngx-matomotracker-and-ngx-matomorouter-version--4) for how to
easily migrate.**

[![NPM version](https://img.shields.io/npm/v/@ngx-matomo/tracker/latest.svg?logo=npm&logoColor=fff&label=Legacy+NPM+package&color=limegreen)](https://www.npmjs.com/package/@ngx-matomo/tracker)
@@ -65,6 +66,7 @@ easily migrate.**
- [Migration from `@ngx-matomo/tracker` and `@ngx-matomo/router` (version <= 4)](#migration-from-ngx-matomotracker-and-ngx-matomorouter-version--4)
- [Configuration reference](#configuration-reference)
- [FAQ](#faq)
* [How to use `ngx-matomo-client` without `@angular/router`?](#how-to-use-ngx-matomo-client-without-angularrouter)
* [How to set page title?](#how-to-set-page-title)
* [Should I include the tracking code provided by Matomo?](#should-i-include-the-tracking-code-provided-by-matomo)
* [How to disable tracking in some environments?](#how-to-disable-tracking-in-some-environments)
@@ -147,6 +149,12 @@ Take a look at [configuration reference](#configuration-reference) for all avail

</details>

> **Note:** in this documentation, all code examples use imports from `ngx-matomo-client` because this is the most
> common use case.
> **If you don't have `@angular/router` in you application, you must import from `ngx-matomo-client/core` instead.**
>
> See [FAQ](#how-to-use-ngx-matomo-client-without-angularrouter) for more details.
## Usage

### Tracking page views
@@ -630,14 +638,29 @@ To manually migrate your code:
2. In your `package.json`, remove `@ngx-matomo/router` dependency
3. Replace all imports from `@ngx-matomo/tracker` or `@ngx-matomo/router` with imports from `ngx-matomo-client` instead.

Also, feel free to use the new `NgModule`-free way of providing `ngx-matomo-client` using `provideMatomo()` function instead of importing `NgxMatomoModule` and `NgxMatomoRouterModule`.
Also, feel free to use the new `NgModule`-free way of providing `ngx-matomo-client` using `provideMatomo()` function
instead of importing `NgxMatomoModule` and `NgxMatomoRouterModule`.

## Configuration reference

[Find all options and features here](docs/configuration-reference.md)

## FAQ

### How to use `ngx-matomo-client` without `@angular/router`?

If you don't have `@angular/router` in your application, you will encounter errors when declaring imports
from `ngx-matomo-client`.

**Instead, you must use imports from `ngx-matomo-client/core`.**

> This is because `ngx-matomo-client` is composed of two entry points:
>
> - `ngx-matomo-client/core` which contains core features and doesn't depend on `@angular/router`
> - `ngx-matomo-client/router` which brings router features and depends on `@angular/router`
>
> The global entrypoint `ngx-matomo-client` is simply a shorthand that re-exports all of them (thus depending on `@angular/router`).
### How to set page title?

If automatic page view tracking is enabled, then you probably have nothing to do: the page title will be detected and
@@ -803,7 +826,7 @@ import {
)
],
})
export class AppModule { }
export class AppModule {}
```

</td>
4 changes: 2 additions & 2 deletions angular.json
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@
"ngx-matomo-client": {
"projectType": "library",
"root": "projects/ngx-matomo-client",
"sourceRoot": "projects/ngx-matomo-client/src",
"sourceRoot": "projects/ngx-matomo-client",
"prefix": "matomo",
"architect": {
"build": {
@@ -25,7 +25,7 @@
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "projects/ngx-matomo-client/src/test.ts",
"main": "projects/ngx-matomo-client/test.ts",
"tsConfig": "projects/ngx-matomo-client/tsconfig.spec.json",
"karmaConfig": "projects/ngx-matomo-client/karma.conf.js"
}
File renamed without changes.
1 change: 1 addition & 0 deletions projects/ngx-matomo-client/core/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './public-api';
6 changes: 6 additions & 0 deletions projects/ngx-matomo-client/core/ng-package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
"lib": {
"entryFile": "public-api.ts"
}
}
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ import { EnvironmentProviders, ModuleWithProviders, NgModule } from '@angular/co
import { MatomoOptOutFormComponent } from './directives/matomo-opt-out-form.component';
import { MatomoTrackClickDirective } from './directives/matomo-track-click.directive';
import { MatomoTrackerDirective } from './directives/matomo-tracker.directive';
import { MatomoFeature, provideMatomo, withScriptFactory } from './ngx-matomo-providers';
import { MatomoFeature, provideMatomo, withScriptFactory } from './providers';
import { MatomoConfiguration } from './tracker/configuration';
import { MatomoScriptFactory } from './tracker/script-factory';

7 changes: 7 additions & 0 deletions projects/ngx-matomo-client/core/private-api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export { runOnce as ɵrunOnce } from './utils/function';
export { MATOMO_ROUTER_ENABLED as ɵMATOMO_ROUTER_ENABLED } from './tracker/configuration';
export {
createMatomoFeature as ɵcreateMatomoFeature,
MatomoFeatureKind as ɵMatomoFeatureKind,
MatomoFeature as ɵMatomoFeature,
} from './providers';
71 changes: 71 additions & 0 deletions projects/ngx-matomo-client/core/providers.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { ApplicationInitStatus, InjectionToken } from '@angular/core';
import { TestBed, TestModuleMetadata } from '@angular/core/testing';
import { provideMatomo, withScriptFactory } from './providers';
import { MATOMO_CONFIGURATION, MatomoConfiguration } from './tracker/configuration';
import { MatomoInitializerService } from './tracker/matomo-initializer.service';
import { MatomoTracker } from './tracker/matomo-tracker.service';
import { createDefaultMatomoScriptElement } from './tracker/script-factory';

describe('providers', () => {
async function setUp(providers: TestModuleMetadata['providers']): Promise<void> {
TestBed.configureTestingModule({
providers: providers,
});

// https://github.com/angular/angular/issues/24218
await TestBed.inject(ApplicationInitStatus).donePromise;
}

it('should provide basic Matomo providers with static configuration', async () => {
const fakeInitializer = jasmine.createSpyObj<MatomoInitializerService>(['initialize']);
const config: MatomoConfiguration = { trackerUrl: 'my-tracker', siteId: 42 };

await setUp([
{
provide: MatomoInitializerService,
useValue: fakeInitializer,
},
provideMatomo(config),
]);

expect(TestBed.inject(MatomoTracker)).toEqual(jasmine.any(MatomoTracker));
expect(TestBed.inject(MATOMO_CONFIGURATION)).toEqual(config);
expect(fakeInitializer.initialize).toHaveBeenCalledTimes(1);
});

it('should provide basic Matomo providers with configuration factory', async () => {
const fakeInitializer = jasmine.createSpyObj<MatomoInitializerService>(['initialize']);
const trackerUrl = 'my-tracker';
const config: MatomoConfiguration = { trackerUrl, siteId: 42 };
const trackerUrlToken = new InjectionToken<string>('trackerUrl');

await setUp([
{
provide: MatomoInitializerService,
useValue: fakeInitializer,
},
{
provide: trackerUrlToken,
useValue: trackerUrl,
},
provideMatomo(() => ({ trackerUrl: TestBed.inject(trackerUrlToken), siteId: 42 })),
]);

expect(TestBed.inject(MatomoTracker)).toEqual(jasmine.any(MatomoTracker));
expect(TestBed.inject(MATOMO_CONFIGURATION)).toEqual(config);
expect(fakeInitializer.initialize).toHaveBeenCalledTimes(1);
});

it('should provide basic Matomo providers with custom script factory', async () => {
const scriptFactory = jasmine
.createSpy('scriptFactory')
.and.callFake(createDefaultMatomoScriptElement);

await setUp([
provideMatomo({ trackerUrl: 'my-tracker', siteId: 42 }, withScriptFactory(scriptFactory)),
]);

expect(TestBed.inject(MatomoTracker)).toEqual(jasmine.any(MatomoTracker));
expect(scriptFactory).toHaveBeenCalledTimes(1);
});
});
Original file line number Diff line number Diff line change
@@ -4,24 +4,8 @@ import {
inject,
makeEnvironmentProviders,
Provider,
Type,
} from '@angular/core';
import { MATOMO_ROUTER_CONFIGURATION, MatomoRouterConfiguration } from './router/configuration';
import {
MatomoRouterInterceptor,
provideInterceptor,
provideInterceptors,
} from './router/interceptor';
import {
MATOMO_ROUTE_DATA_KEY,
MatomoRouteDataInterceptor,
} from './router/interceptors/route-data-interceptor';
import { MatomoRouter } from './router/matomo-router.service';
import {
MATOMO_CONFIGURATION,
MATOMO_ROUTER_ENABLED,
MatomoConfiguration,
} from './tracker/configuration';
import { MATOMO_CONFIGURATION, MatomoConfiguration } from './tracker/configuration';
import { MatomoInitializerService } from './tracker/matomo-initializer.service';
import { MATOMO_SCRIPT_FACTORY, MatomoScriptFactory } from './tracker/script-factory';

@@ -46,7 +30,7 @@ export interface MatomoFeature {
[PRIVATE_MATOMO_PROVIDERS]: Provider[];
}

function createMatomoFeature(kind: MatomoFeatureKind, providers: Provider[]): MatomoFeature {
export function createMatomoFeature(kind: MatomoFeatureKind, providers: Provider[]): MatomoFeature {
return { kind, [PRIVATE_MATOMO_PROVIDERS]: providers };
}

@@ -137,46 +121,3 @@ export function withScriptFactory(scriptFactory: MatomoScriptFactory): MatomoFea
{ provide: MATOMO_SCRIPT_FACTORY, useValue: scriptFactory },
]);
}

/** Enable automatic page views tracking */
export function withRouter(config?: MatomoRouterConfiguration): MatomoFeature {
const providers = [
{ provide: MATOMO_ROUTER_ENABLED, useValue: true },
{ provide: MATOMO_ROUTER_CONFIGURATION, useValue: config },
{
provide: ENVIRONMENT_INITIALIZER,
multi: true,
useValue() {
inject(MatomoRouter).initialize();
},
},
];

return createMatomoFeature(MatomoFeatureKind.Router, providers);
}

/** Add some matomo router interceptors */
export function withRouterInterceptors(
interceptors: Type<MatomoRouterInterceptor>[]
): MatomoFeature {
return createMatomoFeature(
MatomoFeatureKind.RouterInterceptors,
provideInterceptors(interceptors)
);
}

/**
* Enable retrieval of tracking information from route data
*
* @see MatomoRouteData
* @param key A custom key to get lookup route data - default is 'matomo'
*/
export function withRouteData(key?: string): MatomoFeature {
const providers: Provider[] = [provideInterceptor(MatomoRouteDataInterceptor)];

if (key) {
providers.push({ provide: MATOMO_ROUTE_DATA_KEY, useValue: key });
}

return createMatomoFeature(MatomoFeatureKind.BuiltInRouteDataInterceptor, providers);
}
34 changes: 34 additions & 0 deletions projects/ngx-matomo-client/core/public-api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Public API Surface of tracker
*/

export * from './private-api';

export { NgxMatomoModule, NgxMatomoTrackerModule, MATOMO_DIRECTIVES } from './ngx-matomo.module';
export { provideMatomo, withScriptFactory, MatomoFeatureKind, MatomoFeature } from './providers';
export {
MatomoTracker,
MatomoECommerceItem,
MatomoECommerceView,
MatomoECommerceItemView,
MatomoECommerceCategoryView,
PagePerformanceTimings,
} from './tracker/matomo-tracker.service';
export { MatomoInitializerService } from './tracker/matomo-initializer.service';
export {
MatomoConfiguration,
MATOMO_CONFIGURATION,
AutoMatomoConfiguration,
MatomoInitializationMode,
MatomoConsentMode,
InternalMatomoConfiguration,
INTERNAL_MATOMO_CONFIGURATION,
} from './tracker/configuration';
export {
MATOMO_SCRIPT_FACTORY,
MatomoScriptFactory,
createDefaultMatomoScriptElement,
} from './tracker/script-factory';
export { MatomoTrackerDirective } from './directives/matomo-tracker.directive';
export { MatomoTrackClickDirective } from './directives/matomo-track-click.directive';
export { MatomoOptOutFormComponent } from './directives/matomo-opt-out-form.component';
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { EnvironmentInjector, PLATFORM_ID, Provider } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { MatomoHolder } from '../holder';
import { provideMatomo, withScriptFactory } from '../ngx-matomo-providers';
import { provideMatomo, withScriptFactory } from '../providers';
import {
MATOMO_CONFIGURATION,
MATOMO_ROUTER_ENABLED,
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import { inject, InjectionToken, Type } from '@angular/core';
import {
INTERNAL_MATOMO_CONFIGURATION,
InternalMatomoConfiguration,
} from '../tracker/configuration';
import { INTERNAL_MATOMO_CONFIGURATION, InternalMatomoConfiguration } from 'ngx-matomo-client/core';
import { MatomoRouterInterceptor } from './interceptor';

export const MATOMO_ROUTER_CONFIGURATION = new InjectionToken<MatomoRouterConfiguration>(
File renamed without changes.
1 change: 1 addition & 0 deletions projects/ngx-matomo-client/router/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './public-api';
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ import {
RouterState,
RouterStateSnapshot,
} from '@angular/router';
import { MatomoECommerceItemView, MatomoTracker } from '../../tracker/matomo-tracker.service';
import { MatomoECommerceItemView, MatomoTracker } from 'ngx-matomo-client/core';
import {
DEFAULT_DATA_KEY,
MatomoRouteData,
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { inject, Injectable, InjectionToken } from '@angular/core';
import { ActivatedRouteSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { MatomoECommerceView, MatomoTracker } from '../../tracker/matomo-tracker.service';
import { MatomoECommerceView, MatomoTracker } from 'ngx-matomo-client/core';
import { MatomoRouteInterceptorBase } from './route-interceptor-base';

export const DEFAULT_DATA_KEY = 'matomo';
Original file line number Diff line number Diff line change
@@ -2,8 +2,7 @@ import { Provider } from '@angular/core';
import { fakeAsync, flush, TestBed, tick } from '@angular/core/testing';
import { Event, NavigationEnd, Router } from '@angular/router';
import { of, Subject } from 'rxjs';
import { MATOMO_CONFIGURATION } from '../tracker/configuration';
import { MatomoTracker } from '../tracker/matomo-tracker.service';
import { MATOMO_CONFIGURATION, MatomoTracker } from 'ngx-matomo-client/core';
import {
InternalGlobalConfiguration,
MATOMO_ROUTER_CONFIGURATION,
Original file line number Diff line number Diff line change
@@ -21,8 +21,7 @@ import {
take,
tap,
} from 'rxjs/operators';
import { MatomoTracker } from '../tracker/matomo-tracker.service';
import { runOnce } from '../utils/function';
import { MatomoTracker, ɵrunOnce as runOnce } from 'ngx-matomo-client/core';
import {
ExclusionConfig,
INTERNAL_ROUTER_CONFIGURATION,
6 changes: 6 additions & 0 deletions projects/ngx-matomo-client/router/ng-package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
"lib": {
"entryFile": "public-api.ts"
}
}
Original file line number Diff line number Diff line change
@@ -2,10 +2,10 @@ import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core
import {
MATOMO_ROUTER_CONFIGURATION,
MatomoRouterConfigurationWithInterceptors,
} from './router/configuration';
import { provideInterceptors } from './router/interceptor';
import { MatomoRouter } from './router/matomo-router.service';
import { MATOMO_ROUTER_ENABLED } from './tracker/configuration';
} from './configuration';
import { provideInterceptors } from './interceptor';
import { MatomoRouter } from './matomo-router.service';
import { ɵMATOMO_ROUTER_ENABLED as MATOMO_ROUTER_ENABLED } from 'ngx-matomo-client/core';

@NgModule({
providers: [{ provide: MATOMO_ROUTER_ENABLED, useValue: true }],
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { APP_BASE_HREF, PlatformLocation } from '@angular/common';
import { TestBed } from '@angular/core/testing';
import { NavigationEnd } from '@angular/router';
import { MATOMO_CONFIGURATION, MatomoConfiguration } from '../tracker/configuration';
import { MATOMO_CONFIGURATION, MatomoConfiguration } from 'ngx-matomo-client/core';
import { MATOMO_ROUTER_CONFIGURATION, MatomoRouterConfiguration } from './configuration';
import { MATOMO_PAGE_URL_PROVIDER, PageUrlProvider } from './page-url-provider';

Original file line number Diff line number Diff line change
@@ -1,28 +1,19 @@
import { ApplicationInitStatus, InjectionToken } from '@angular/core';
import { ApplicationInitStatus } from '@angular/core';
import { TestBed, TestModuleMetadata } from '@angular/core/testing';
import {
provideMatomo,
withRouteData,
withRouter,
withRouterInterceptors,
withScriptFactory,
} from './ngx-matomo-providers';
import { MATOMO_ROUTER_CONFIGURATION } from './router/configuration';
import { MATOMO_ROUTER_INTERCEPTORS, MatomoRouterInterceptor } from './router/interceptor';
import { withRouteData, withRouter, withRouterInterceptors } from './providers';
import { MATOMO_ROUTER_CONFIGURATION } from './configuration';
import { MATOMO_ROUTER_INTERCEPTORS, MatomoRouterInterceptor } from './interceptor';
import {
DEFAULT_DATA_KEY,
MATOMO_ROUTE_DATA_KEY,
MatomoRouteDataInterceptor,
} from './router/interceptors/route-data-interceptor';
import { MatomoRouter } from './router/matomo-router.service';
} from './interceptors/route-data-interceptor';
import { MatomoRouter } from './matomo-router.service';
import {
MATOMO_CONFIGURATION,
MATOMO_ROUTER_ENABLED,
MatomoConfiguration,
} from './tracker/configuration';
import { MatomoInitializerService } from './tracker/matomo-initializer.service';
import { MatomoTracker } from './tracker/matomo-tracker.service';
import { createDefaultMatomoScriptElement } from './tracker/script-factory';
MatomoTracker,
provideMatomo,
ɵMATOMO_ROUTER_ENABLED as MATOMO_ROUTER_ENABLED,
} from 'ngx-matomo-client/core';

describe('providers', () => {
async function setUp(providers: TestModuleMetadata['providers']): Promise<void> {
@@ -34,59 +25,6 @@ describe('providers', () => {
await TestBed.inject(ApplicationInitStatus).donePromise;
}

it('should provide basic Matomo providers with static configuration', async () => {
const fakeInitializer = jasmine.createSpyObj<MatomoInitializerService>(['initialize']);
const config: MatomoConfiguration = { trackerUrl: 'my-tracker', siteId: 42 };

await setUp([
{
provide: MatomoInitializerService,
useValue: fakeInitializer,
},
provideMatomo(config),
]);

expect(TestBed.inject(MatomoTracker)).toEqual(jasmine.any(MatomoTracker));
expect(TestBed.inject(MATOMO_CONFIGURATION)).toEqual(config);
expect(fakeInitializer.initialize).toHaveBeenCalledTimes(1);
});

it('should provide basic Matomo providers with configuration factory', async () => {
const fakeInitializer = jasmine.createSpyObj<MatomoInitializerService>(['initialize']);
const trackerUrl = 'my-tracker';
const config: MatomoConfiguration = { trackerUrl, siteId: 42 };
const trackerUrlToken = new InjectionToken<string>('trackerUrl');

await setUp([
{
provide: MatomoInitializerService,
useValue: fakeInitializer,
},
{
provide: trackerUrlToken,
useValue: trackerUrl,
},
provideMatomo(() => ({ trackerUrl: TestBed.inject(trackerUrlToken), siteId: 42 })),
]);

expect(TestBed.inject(MatomoTracker)).toEqual(jasmine.any(MatomoTracker));
expect(TestBed.inject(MATOMO_CONFIGURATION)).toEqual(config);
expect(fakeInitializer.initialize).toHaveBeenCalledTimes(1);
});

it('should provide basic Matomo providers with custom script factory', async () => {
const scriptFactory = jasmine
.createSpy('scriptFactory')
.and.callFake(createDefaultMatomoScriptElement);

await setUp([
provideMatomo({ trackerUrl: 'my-tracker', siteId: 42 }, withScriptFactory(scriptFactory)),
]);

expect(TestBed.inject(MatomoTracker)).toEqual(jasmine.any(MatomoTracker));
expect(scriptFactory).toHaveBeenCalledTimes(1);
});

it('should provide basic Matomo providers with router feature', async () => {
await setUp([
provideMatomo({ trackerUrl: 'my-tracker', siteId: 42 }, withRouter({ delay: 42 })),
57 changes: 57 additions & 0 deletions projects/ngx-matomo-client/router/providers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import {
ɵcreateMatomoFeature as createMatomoFeature,
ɵMATOMO_ROUTER_ENABLED as MATOMO_ROUTER_ENABLED,
ɵMatomoFeature as MatomoFeature,
ɵMatomoFeatureKind as MatomoFeatureKind,
} from 'ngx-matomo-client/core';
import { ENVIRONMENT_INITIALIZER, inject, Provider, Type } from '@angular/core';
import { MATOMO_ROUTER_CONFIGURATION, MatomoRouterConfiguration } from './configuration';
import { MatomoRouter } from './matomo-router.service';
import {
MATOMO_ROUTE_DATA_KEY,
MatomoRouteDataInterceptor,
} from './interceptors/route-data-interceptor';
import { MatomoRouterInterceptor, provideInterceptor, provideInterceptors } from './interceptor';

/** Enable automatic page views tracking */
export function withRouter(config?: MatomoRouterConfiguration): MatomoFeature {
const providers = [
{ provide: MATOMO_ROUTER_ENABLED, useValue: true },
{ provide: MATOMO_ROUTER_CONFIGURATION, useValue: config },
{
provide: ENVIRONMENT_INITIALIZER,
multi: true,
useValue() {
inject(MatomoRouter).initialize();
},
},
];

return createMatomoFeature(MatomoFeatureKind.Router, providers);
}

/** Add some matomo router interceptors */
export function withRouterInterceptors(
interceptors: Type<MatomoRouterInterceptor>[]
): MatomoFeature {
return createMatomoFeature(
MatomoFeatureKind.RouterInterceptors,
provideInterceptors(interceptors)
);
}

/**
* Enable retrieval of tracking information from route data
*
* @see MatomoRouteData
* @param key A custom key to get lookup route data - default is 'matomo'
*/
export function withRouteData(key?: string): MatomoFeature {
const providers: Provider[] = [provideInterceptor(MatomoRouteDataInterceptor)];

if (key) {
providers.push({ provide: MATOMO_ROUTE_DATA_KEY, useValue: key });
}

return createMatomoFeature(MatomoFeatureKind.BuiltInRouteDataInterceptor, providers);
}
26 changes: 26 additions & 0 deletions projects/ngx-matomo-client/router/public-api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Public API Surface of tracker
*/

export { withRouter, withRouterInterceptors, withRouteData } from './providers';
export { NgxMatomoRouterModule } from './ngx-matomo-router.module';
export {
MatomoRouterConfiguration,
MATOMO_ROUTER_CONFIGURATION,
ExclusionConfig,
MatomoRouterConfigurationWithInterceptors,
} from './configuration';
export { PageTitleProvider, MATOMO_PAGE_TITLE_PROVIDER } from './page-title-providers';
export { PageUrlProvider, MATOMO_PAGE_URL_PROVIDER } from './page-url-provider';
export {
MatomoRouterInterceptor,
MATOMO_ROUTER_INTERCEPTORS,
provideInterceptor,
provideInterceptors,
} from './interceptor';
export { MatomoRouteInterceptorBase } from './interceptors/route-interceptor-base';
export {
MatomoRouteData,
MatomoRouteDataInterceptor,
MATOMO_ROUTE_DATA_KEY,
} from './interceptors/route-data-interceptor';
62 changes: 40 additions & 22 deletions projects/ngx-matomo-client/schematics/ng-add/index.ts
Original file line number Diff line number Diff line change
@@ -28,26 +28,17 @@ import {
import { version } from '../version';
import { Schema as Options } from './schema';

/***********************************************************************************/
/* Important note: this schematic depends on non-public API of @schematics/angular */

/***********************************************************************************/

function checkRequiredRouterDependency(host: Tree, context: SchematicContext) {
const ngRouter = getPackageJsonDependency(host, '@angular/router');
function hasAngularRouterDependency(host: Tree): boolean {
return getPackageJsonDependency(host, '@angular/router') != null;
}

if (!ngRouter) {
function checkRequiredRouterDependency(host: Tree) {
if (!hasAngularRouterDependency(host)) {
throw new SchematicsException(
`You chose to automatically track page view, but this requires @angular/router as a dependency.\n` +
`You can run "ng add @angular/router" to add it to your application.`
);
}

if (ngRouter.type !== NodeDependencyType.Default) {
context.logger.warn(
`You chose to automatically track page view, but @angular/router is listed as "${ngRouter.type}" dependency.`
);
}
}

function addPackageJsonDependencies(options: Options) {
@@ -64,7 +55,7 @@ function addPackageJsonDependencies(options: Options) {
}

if (options.router) {
checkRequiredRouterDependency(host, context);
checkRequiredRouterDependency(host);
}

context.addTask(new NodePackageInstallTask());
@@ -118,7 +109,11 @@ function isLegacyImportPath(importPath: string): boolean {
}

function isRelevantImportPath(importPath: string): boolean {
return importPath === 'ngx-matomo-client' || isLegacyImportPath(importPath);
return (
importPath === 'ngx-matomo-client' ||
importPath.startsWith('ngx-matomo-client/') ||
isLegacyImportPath(importPath)
);
}

function findRelevantImports(
@@ -157,6 +152,20 @@ function hasLegacyModuleDeclaration(source: ts.SourceFile): boolean {
.some(el => (el as ts.Identifier).getText().startsWith('NgxMatomo'));
}

function getImportEntryPoints(
host: Tree,
options: Options
): {
core: string;
router: string;
} {
const useSecondaryEntryPoint = !hasAngularRouterDependency(host) && !options.router;
const core = useSecondaryEntryPoint ? 'ngx-matomo-client/core' : 'ngx-matomo-client';
const router = useSecondaryEntryPoint ? 'ngx-matomo-client/router' : 'ngx-matomo-client';

return { core, router };
}

function addImportsToNgModule(options: Options, context: SchematicContext): Rule {
return (host: Tree) => {
const modulePath = options.module;
@@ -168,6 +177,7 @@ function addImportsToNgModule(options: Options, context: SchematicContext): Rule
const changes: Change[] = [];
const source = readIntoSourceFile(host, modulePath);
const trackerConfig = buildTrackerConfig(options, context, modulePath);
const entryPoints = getImportEntryPoints(host, options);

// If some Matomo imports are already present, use the legacy setup using
// NgModule.
@@ -232,7 +242,7 @@ function addImportsToNgModule(options: Options, context: SchematicContext): Rule
);

if (!mainModuleImported) {
changes.push(insertImport(source, modulePath, mainModuleIdentifier, 'ngx-matomo-client'));
changes.push(insertImport(source, modulePath, mainModuleIdentifier, entryPoints.core));
}

changes.push(
@@ -247,7 +257,7 @@ function addImportsToNgModule(options: Options, context: SchematicContext): Rule
if (options.router) {
if (!routerModuleImported) {
changes.push(
insertImport(source, modulePath, routerModuleIdentifier, 'ngx-matomo-client')
insertImport(source, modulePath, routerModuleIdentifier, entryPoints.router)
);
}

@@ -258,10 +268,10 @@ function addImportsToNgModule(options: Options, context: SchematicContext): Rule
} else {
const provideMatomoArgs = [trackerConfig];

changes.push(insertImport(source, modulePath, 'provideMatomo', 'ngx-matomo-client'));
changes.push(insertImport(source, modulePath, 'provideMatomo', entryPoints.core));

if (options.router) {
changes.push(insertImport(source, modulePath, 'withRouter', 'ngx-matomo-client'));
changes.push(insertImport(source, modulePath, 'withRouter', entryPoints.router));

provideMatomoArgs.push(`withRouter()`);
}
@@ -297,6 +307,7 @@ function migrateAllLegacyImports(options: Options, context: SchematicContext): R

if (!options.path || path.startsWith(options.path)) {
const file = readIntoSourceFile(host, path);
const entryPoints = getImportEntryPoints(host, options);
const changes: Change[] = [];

file.forEachChild(node => {
@@ -307,9 +318,16 @@ function migrateAllLegacyImports(options: Options, context: SchematicContext): R
const text = moduleSpecifier.text;
const pos = moduleSpecifier.pos;

if (text?.startsWith('@ngx-matomo/')) {
if (text === '@ngx-matomo/tracker') {
// Be sure to keep any original spacings (contained in getFullText() only)
const newFullText = fullText.replace(text, entryPoints.core);

changes.push(new ReplaceChange(path, pos, fullText, newFullText));
}

if (text === '@ngx-matomo/router') {
// Be sure to keep any original spacings (contained in getFullText() only)
const newFullText = fullText.replace(text, 'ngx-matomo-client');
const newFullText = fullText.replace(text, entryPoints.router);

changes.push(new ReplaceChange(path, pos, fullText, newFullText));
}
1 change: 1 addition & 0 deletions projects/ngx-matomo-client/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './public-api';
63 changes: 2 additions & 61 deletions projects/ngx-matomo-client/src/public-api.ts
Original file line number Diff line number Diff line change
@@ -2,64 +2,5 @@
* Public API Surface of tracker
*/

export {
NgxMatomoModule,
NgxMatomoTrackerModule,
MATOMO_DIRECTIVES,
} from './lib/ngx-matomo.module';
export {
provideMatomo,
withScriptFactory,
withRouter,
withRouterInterceptors,
withRouteData,
MatomoFeatureKind,
MatomoFeature,
} from './lib/ngx-matomo-providers';
export {
MatomoTracker,
MatomoECommerceItem,
MatomoECommerceView,
MatomoECommerceItemView,
MatomoECommerceCategoryView,
PagePerformanceTimings,
} from './lib/tracker/matomo-tracker.service';
export { MatomoInitializerService } from './lib/tracker/matomo-initializer.service';
export {
MatomoConfiguration,
MATOMO_CONFIGURATION,
AutoMatomoConfiguration,
MatomoInitializationMode,
MatomoConsentMode,
InternalMatomoConfiguration,
INTERNAL_MATOMO_CONFIGURATION,
} from './lib/tracker/configuration';
export {
MATOMO_SCRIPT_FACTORY,
MatomoScriptFactory,
createDefaultMatomoScriptElement,
} from './lib/tracker/script-factory';
export { MatomoTrackerDirective } from './lib/directives/matomo-tracker.directive';
export { MatomoTrackClickDirective } from './lib/directives/matomo-track-click.directive';
export { MatomoOptOutFormComponent } from './lib/directives/matomo-opt-out-form.component';
export { NgxMatomoRouterModule } from './lib/ngx-matomo-router.module';
export {
MatomoRouterConfiguration,
MATOMO_ROUTER_CONFIGURATION,
ExclusionConfig,
MatomoRouterConfigurationWithInterceptors,
} from './lib/router/configuration';
export { PageTitleProvider, MATOMO_PAGE_TITLE_PROVIDER } from './lib/router/page-title-providers';
export { PageUrlProvider, MATOMO_PAGE_URL_PROVIDER } from './lib/router/page-url-provider';
export {
MatomoRouterInterceptor,
MATOMO_ROUTER_INTERCEPTORS,
provideInterceptor,
provideInterceptors,
} from './lib/router/interceptor';
export { MatomoRouteInterceptorBase } from './lib/router/interceptors/route-interceptor-base';
export {
MatomoRouteData,
MatomoRouteDataInterceptor,
MATOMO_ROUTE_DATA_KEY,
} from './lib/router/interceptors/route-data-interceptor';
export * from 'ngx-matomo-client/core';
export * from 'ngx-matomo-client/router';
File renamed without changes.
3 changes: 1 addition & 2 deletions projects/ngx-matomo-client/tsconfig.lib.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "../../tsconfig.json",
"compilerOptions": {
@@ -14,5 +13,5 @@
"strictMetadataEmit": true,
"enableResourceInlining": true
},
"exclude": ["src/test.ts", "**/*.spec.ts"]
"exclude": ["test.ts", "**/*.spec.ts"]
}
2 changes: 1 addition & 1 deletion projects/ngx-matomo-client/tsconfig.spec.json
Original file line number Diff line number Diff line change
@@ -5,6 +5,6 @@
"outDir": "../../out-tsc/spec",
"types": ["jasmine"]
},
"files": ["src/test.ts"],
"files": ["test.ts"],
"include": ["**/*.spec.ts", "**/*.d.ts"]
}
2 changes: 1 addition & 1 deletion scripts/detect-missing-api.mjs
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ import * as cheerio from 'cheerio';
import * as fs from 'fs/promises';

const DOCUMENTATION_URL = 'https://developer.matomo.org/api-reference/tracking-javascript';
const TRACKER_FILE_PATH = 'projects/ngx-matomo-client/src/lib/tracker/matomo-tracker.service.ts';
const TRACKER_FILE_PATH = 'projects/ngx-matomo-client/core/tracker/matomo-tracker.service.ts';
const GLOBAL_METHOD_PREFIX = 'Matomo.';
const ACCEPTED_METHOD_PREFIXES = ['matomoTracker.', 'tracker.'];
const EXCLUSIONS = /\//;
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
@@ -18,7 +18,8 @@
"module": "es2020",
"lib": ["es2018", "dom"],
"paths": {
"ngx-matomo-client": ["dist/ngx-matomo-client"]
"ngx-matomo-client": ["dist/ngx-matomo-client"],
"ngx-matomo-client/*": ["dist/ngx-matomo-client/*"]
},
"useDefineForClassFields": false
},

0 comments on commit 89f9344

Please sign in to comment.