Initial project
This commit is contained in:
20
.github/workflows/publish.yml
vendored
Normal file
20
.github/workflows/publish.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
name: Publish to NPM
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [created]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-publish:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: '18'
|
||||||
|
registry-url: 'https://registry.npmjs.org'
|
||||||
|
- run: npm ci
|
||||||
|
- run: npm run build:lib
|
||||||
|
- run: cd dist/ngx-pendo-lite && npm publish
|
||||||
|
env:
|
||||||
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
/.angular
|
||||||
|
/dist
|
||||||
|
/node_modules
|
||||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2025 NinjaPug
|
Copyright (c) 2025 Christopher Koch
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
85
README.md
85
README.md
@@ -1,2 +1,83 @@
|
|||||||
# ngx-pendo-lite
|
# ngx-pendo-lite-workspace
|
||||||
Pendo Angular wrapper
|
|
||||||
|
This workspace contains the Angular library for integrating Pendo.io analytics into Angular applications.
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
### Library
|
||||||
|
|
||||||
|
The main library code is in the `projects/ngx-pendo-lite` directory.
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
Run `npm run build:lib` to build the library. The build artifacts will be stored in the `dist/ngx-pendo-lite` directory.
|
||||||
|
|
||||||
|
### Running unit tests
|
||||||
|
|
||||||
|
Run `npm run test:lib` to execute the unit tests for the library via [Karma](https://karma-runner.github.io).
|
||||||
|
|
||||||
|
### Publishing
|
||||||
|
|
||||||
|
After building the library, you can publish it to npm with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run publish:lib
|
||||||
|
```
|
||||||
|
|
||||||
|
Or do a dry run first:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run publish:lib:dry
|
||||||
|
```
|
||||||
|
|
||||||
|
## Versioning
|
||||||
|
|
||||||
|
The library follows [Semantic Versioning](https://semver.org/).
|
||||||
|
|
||||||
|
To bump the version:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# For patch releases (bug fixes)
|
||||||
|
npm run version:patch
|
||||||
|
|
||||||
|
# For minor releases (new features, backward compatible)
|
||||||
|
npm run version:minor
|
||||||
|
|
||||||
|
# For major releases (breaking changes)
|
||||||
|
npm run version:major
|
||||||
|
```
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Easy integration with Angular's dependency injection
|
||||||
|
- Type-safe wrapper for all Pendo functionality
|
||||||
|
- Server-side rendering (SSR) support
|
||||||
|
- Comprehensive testing
|
||||||
|
|
||||||
|
## Library Usage
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Import in your app module
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
import { PendoModule } from 'ngx-pendo-lite';
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [AppComponent],
|
||||||
|
imports: [
|
||||||
|
BrowserModule,
|
||||||
|
PendoModule.forRoot({
|
||||||
|
apiKey: 'YOUR_PENDO_API_KEY'
|
||||||
|
})
|
||||||
|
],
|
||||||
|
bootstrap: [AppComponent]
|
||||||
|
})
|
||||||
|
export class AppModule { }
|
||||||
|
```
|
||||||
|
|
||||||
|
For more details, see the library's own [README](./projects/ngx-pendo-lite/README.md).
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
||||||
43
angular.json
Normal file
43
angular.json
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||||
|
"version": 1,
|
||||||
|
"newProjectRoot": "projects",
|
||||||
|
"projects": {
|
||||||
|
"ngx-pendo-lite": {
|
||||||
|
"projectType": "library",
|
||||||
|
"root": "projects/ngx-pendo-lite",
|
||||||
|
"sourceRoot": "projects/ngx-pendo-lite/src",
|
||||||
|
"prefix": "lib",
|
||||||
|
"architect": {
|
||||||
|
"build": {
|
||||||
|
"builder": "@angular-devkit/build-angular:ng-packagr",
|
||||||
|
"options": {
|
||||||
|
"project": "projects/ngx-pendo-lite/ng-package.json"
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"tsConfig": "projects/ngx-pendo-lite/tsconfig.lib.prod.json"
|
||||||
|
},
|
||||||
|
"development": {
|
||||||
|
"tsConfig": "projects/ngx-pendo-lite/tsconfig.lib.json"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultConfiguration": "production"
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"builder": "@angular-devkit/build-angular:karma",
|
||||||
|
"options": {
|
||||||
|
"tsConfig": "projects/ngx-pendo-lite/tsconfig.spec.json",
|
||||||
|
"polyfills": [
|
||||||
|
"zone.js",
|
||||||
|
"zone.js/testing"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"cli": {
|
||||||
|
"analytics": false
|
||||||
|
}
|
||||||
|
}
|
||||||
13490
package-lock.json
generated
Normal file
13490
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
47
package.json
Normal file
47
package.json
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"name": "ngx-pendo-lite-workspace",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"scripts": {
|
||||||
|
"ng": "ng",
|
||||||
|
"start": "ng serve",
|
||||||
|
"build": "ng build",
|
||||||
|
"watch": "ng build --watch --configuration development",
|
||||||
|
"test": "ng test",
|
||||||
|
"build:lib": "ng build ngx-pendo-lite",
|
||||||
|
"test:lib": "ng test ngx-pendo-lite",
|
||||||
|
"lint:lib": "ng lint ngx-pendo-lite",
|
||||||
|
"publish:lib": "cd dist/ngx-pendo-lite && npm publish",
|
||||||
|
"publish:lib:dry": "cd dist/ngx-pendo-lite && npm publish --dry-run",
|
||||||
|
"version:patch": "cd projects/ngx-pendo-lite && npm version patch",
|
||||||
|
"version:minor": "cd projects/ngx-pendo-lite && npm version minor",
|
||||||
|
"version:major": "cd projects/ngx-pendo-lite && npm version major"
|
||||||
|
},
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@angular/animations": "^17.1.0",
|
||||||
|
"@angular/common": "^17.1.0",
|
||||||
|
"@angular/compiler": "^17.1.0",
|
||||||
|
"@angular/core": "^17.1.0",
|
||||||
|
"@angular/forms": "^17.1.0",
|
||||||
|
"@angular/platform-browser": "^17.1.0",
|
||||||
|
"@angular/platform-browser-dynamic": "^17.1.0",
|
||||||
|
"@angular/router": "^17.1.0",
|
||||||
|
"rxjs": "~7.8.0",
|
||||||
|
"tslib": "^2.5.0",
|
||||||
|
"zone.js": "~0.14.3"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@angular-devkit/build-angular": "^17.1.0",
|
||||||
|
"@angular/cli": "^17.1.0",
|
||||||
|
"@angular/compiler-cli": "^17.1.0",
|
||||||
|
"ng-packagr": "^17.1.0",
|
||||||
|
"@types/jasmine": "~5.1.0",
|
||||||
|
"jasmine-core": "~5.1.0",
|
||||||
|
"karma": "~6.4.0",
|
||||||
|
"karma-chrome-launcher": "~3.2.0",
|
||||||
|
"karma-coverage": "~2.2.0",
|
||||||
|
"karma-jasmine": "~5.1.0",
|
||||||
|
"karma-jasmine-html-reporter": "~2.1.0",
|
||||||
|
"typescript": "~5.3.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
19
projects/ngx-pendo-lite/LICENSE
Normal file
19
projects/ngx-pendo-lite/LICENSE
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2025 Christopher Koch
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
126
projects/ngx-pendo-lite/README.md
Normal file
126
projects/ngx-pendo-lite/README.md
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
# ngx-pendo-lite
|
||||||
|
|
||||||
|
A lightweight Angular wrapper for Pendo.io analytics integration.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install ngx-pendo-lite --save
|
||||||
|
```
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
### 1. Import the Module
|
||||||
|
|
||||||
|
Import the `PendoModule` in your `AppModule` and configure it with your Pendo API key:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
import { PendoModule } from 'ngx-pendo-lite';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
AppComponent
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
BrowserModule,
|
||||||
|
PendoModule.forRoot({
|
||||||
|
apiKey: 'YOUR_PENDO_API_KEY'
|
||||||
|
})
|
||||||
|
],
|
||||||
|
bootstrap: [AppComponent]
|
||||||
|
})
|
||||||
|
export class AppModule { }
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Identify Users (after login)
|
||||||
|
|
||||||
|
After a user logs in to your application, identify them to Pendo:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { PendoService } from 'ngx-pendo-lite';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-login',
|
||||||
|
template: `...`
|
||||||
|
})
|
||||||
|
export class LoginComponent {
|
||||||
|
constructor(private pendoService: PendoService) {}
|
||||||
|
|
||||||
|
onLoginSuccess(user: any): void {
|
||||||
|
this.pendoService.identify(
|
||||||
|
user.id,
|
||||||
|
user.organizationId,
|
||||||
|
{
|
||||||
|
email: user.email,
|
||||||
|
fullName: user.fullName,
|
||||||
|
role: user.role
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: user.organizationName,
|
||||||
|
tier: user.subscriptionTier
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Track Custom Events
|
||||||
|
|
||||||
|
Track user interactions and custom events:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { PendoService } from 'ngx-pendo-lite';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-feature',
|
||||||
|
template: `...`
|
||||||
|
})
|
||||||
|
export class FeatureComponent {
|
||||||
|
constructor(private pendoService: PendoService) {}
|
||||||
|
|
||||||
|
onFeatureUsed(): void {
|
||||||
|
this.pendoService.track('feature_used', {
|
||||||
|
featureName: 'example-feature',
|
||||||
|
timestamp: new Date().toISOString()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## API Reference
|
||||||
|
|
||||||
|
### PendoService
|
||||||
|
|
||||||
|
#### Methods
|
||||||
|
|
||||||
|
- `initialize(config: PendoConfig): void` - Initialize the Pendo service
|
||||||
|
- `identify(visitorId: string, accountId: string, visitorData?: Record<string, any>, accountData?: Record<string, any>): void` - Identify a user and account
|
||||||
|
- `track(eventName: string, metadata?: Record<string, any>): void` - Track a custom event
|
||||||
|
- `updateVisitor(visitorData: Record<string, any>): void` - Update visitor information
|
||||||
|
- `updateAccount(accountData: Record<string, any>): void` - Update account information
|
||||||
|
- `disable(): void` - Disable Pendo tracking
|
||||||
|
|
||||||
|
#### Interfaces
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface PendoConfig {
|
||||||
|
apiKey: string;
|
||||||
|
visitor?: {
|
||||||
|
id: string;
|
||||||
|
[key: string]: any;
|
||||||
|
};
|
||||||
|
account?: {
|
||||||
|
id: string;
|
||||||
|
[key: string]: any;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
||||||
50
projects/ngx-pendo-lite/karma.conf.js
Normal file
50
projects/ngx-pendo-lite/karma.conf.js
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
// Karma configuration file, see link for more information
|
||||||
|
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||||
|
|
||||||
|
module.exports = function (config) {
|
||||||
|
config.set({
|
||||||
|
basePath: '',
|
||||||
|
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||||
|
plugins: [
|
||||||
|
require('karma-jasmine'),
|
||||||
|
require('karma-chrome-launcher'),
|
||||||
|
require('karma-jasmine-html-reporter'),
|
||||||
|
require('karma-coverage'),
|
||||||
|
require('@angular-devkit/build-angular/plugins/karma')
|
||||||
|
],
|
||||||
|
client: {
|
||||||
|
jasmine: {
|
||||||
|
// you can add configuration options for Jasmine here
|
||||||
|
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
|
||||||
|
// for example, you can disable the random execution with `random: false`
|
||||||
|
// or set a specific seed with `seed: 4321`
|
||||||
|
},
|
||||||
|
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||||
|
},
|
||||||
|
jasmineHtmlReporter: {
|
||||||
|
suppressAll: true // removes the duplicated traces
|
||||||
|
},
|
||||||
|
coverageReporter: {
|
||||||
|
dir: require('path').join(__dirname, '../../coverage/ngx-pendo-lite'),
|
||||||
|
subdir: '.',
|
||||||
|
reporters: [
|
||||||
|
{ type: 'html' },
|
||||||
|
{ type: 'text-summary' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
reporters: ['progress', 'kjhtml'],
|
||||||
|
port: 9876,
|
||||||
|
colors: true,
|
||||||
|
logLevel: config.LOG_INFO,
|
||||||
|
autoWatch: true,
|
||||||
|
browsers: ['Chrome'],
|
||||||
|
customLaunchers: {
|
||||||
|
ChromeHeadlessCI: {
|
||||||
|
base: 'ChromeHeadless',
|
||||||
|
flags: ['--no-sandbox']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
singleRun: false,
|
||||||
|
restartOnFileChange: true
|
||||||
|
});
|
||||||
|
};
|
||||||
7
projects/ngx-pendo-lite/ng-package.json
Normal file
7
projects/ngx-pendo-lite/ng-package.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
|
||||||
|
"dest": "../../dist/ngx-pendo-lite",
|
||||||
|
"lib": {
|
||||||
|
"entryFile": "src/public-api.ts"
|
||||||
|
}
|
||||||
|
}
|
||||||
47
projects/ngx-pendo-lite/package.json
Normal file
47
projects/ngx-pendo-lite/package.json
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"name": "ngx-pendo-lite",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Angular wrapper for Pendo.io analytics integration",
|
||||||
|
"author": "Christopher Koch",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/programmingPug/ngx-pendo-lite"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"angular",
|
||||||
|
"pendo",
|
||||||
|
"analytics",
|
||||||
|
"tracking",
|
||||||
|
"pendo.io"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/programmingPug/ngx-pendo-lite/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/programmingPug/ngx-pendo-lite#readme",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@angular/common": ">=12.0.0",
|
||||||
|
"@angular/core": ">=12.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.5.0"
|
||||||
|
},
|
||||||
|
"sideEffects": false,
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": "./index.d.ts",
|
||||||
|
"esm2022": "./esm2022/ngx-pendo.mjs",
|
||||||
|
"esm": "./esm2022/ngx-pendo.mjs",
|
||||||
|
"default": "./fesm2022/ngx-pendo.mjs"
|
||||||
|
},
|
||||||
|
"./package.json": {
|
||||||
|
"default": "./package.json"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"module": "fesm2022/ngx-pendo.mjs",
|
||||||
|
"typings": "index.d.ts",
|
||||||
|
"type": "module"
|
||||||
|
}
|
||||||
11
projects/ngx-pendo-lite/src/lib/index.ts
Normal file
11
projects/ngx-pendo-lite/src/lib/index.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* Library internal index file that exports all public components, directives,
|
||||||
|
* pipes, services, and other entities from the library
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Export the service
|
||||||
|
export * from './pendo.service';
|
||||||
|
|
||||||
|
// Export the module
|
||||||
|
export * from './pendo.module';
|
||||||
250
projects/ngx-pendo-lite/src/lib/ngx-pendo.service.spec.ts
Normal file
250
projects/ngx-pendo-lite/src/lib/ngx-pendo.service.spec.ts
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
import { PLATFORM_ID } from '@angular/core';
|
||||||
|
import { PendoService, PENDO_CONFIG } from './pendo.service';
|
||||||
|
|
||||||
|
describe('PendoService', () => {
|
||||||
|
let service: PendoService;
|
||||||
|
|
||||||
|
// Mock Pendo instance
|
||||||
|
const mockPendo = {
|
||||||
|
initialize: jasmine.createSpy('initialize'),
|
||||||
|
updateOptions: jasmine.createSpy('updateOptions'),
|
||||||
|
identify: jasmine.createSpy('identify'),
|
||||||
|
track: jasmine.createSpy('track'),
|
||||||
|
disableCookies: jasmine.createSpy('disableCookies'),
|
||||||
|
isReady: jasmine.createSpy('isReady').and.returnValue(true)
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockConfig = {
|
||||||
|
apiKey: 'test-api-key',
|
||||||
|
autoLoad: false
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
// Define mock for window.pendo
|
||||||
|
Object.defineProperty(window, 'pendo', {
|
||||||
|
value: mockPendo,
|
||||||
|
writable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [
|
||||||
|
PendoService,
|
||||||
|
{ provide: PLATFORM_ID, useValue: 'browser' },
|
||||||
|
{ provide: PENDO_CONFIG, useValue: mockConfig }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
service = TestBed.inject(PendoService);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
// Reset all spies
|
||||||
|
mockPendo.initialize.calls.reset();
|
||||||
|
mockPendo.updateOptions.calls.reset();
|
||||||
|
mockPendo.identify.calls.reset();
|
||||||
|
mockPendo.track.calls.reset();
|
||||||
|
mockPendo.disableCookies.calls.reset();
|
||||||
|
mockPendo.isReady.calls.reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('initialize', () => {
|
||||||
|
it('should initialize Pendo with the provided config', async () => {
|
||||||
|
await service.initialize();
|
||||||
|
|
||||||
|
expect(mockPendo.initialize).toHaveBeenCalledWith({
|
||||||
|
apiKey: mockConfig.apiKey,
|
||||||
|
visitor: undefined,
|
||||||
|
account: undefined
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should initialize with visitor and account data when provided', async () => {
|
||||||
|
const visitorData = { id: 'visitor-1', name: 'Test User' };
|
||||||
|
const accountData = { id: 'account-1', name: 'Test Account' };
|
||||||
|
|
||||||
|
await service.initialize({
|
||||||
|
apiKey: 'new-api-key',
|
||||||
|
visitor: visitorData,
|
||||||
|
account: accountData
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockPendo.initialize).toHaveBeenCalledWith({
|
||||||
|
apiKey: 'new-api-key',
|
||||||
|
visitor: visitorData,
|
||||||
|
account: accountData
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('updateVisitor', () => {
|
||||||
|
it('should call updateOptions with visitor data', async () => {
|
||||||
|
await service.initialize();
|
||||||
|
|
||||||
|
const visitorData = { id: 'visitor-1', name: 'Test User' };
|
||||||
|
service.updateVisitor(visitorData);
|
||||||
|
|
||||||
|
expect(mockPendo.updateOptions).toHaveBeenCalledWith({
|
||||||
|
visitor: visitorData
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not call updateOptions if not initialized', () => {
|
||||||
|
const visitorData = { id: 'visitor-1', name: 'Test User' };
|
||||||
|
service.updateVisitor(visitorData);
|
||||||
|
|
||||||
|
expect(mockPendo.updateOptions).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('updateAccount', () => {
|
||||||
|
it('should call updateOptions with account data', async () => {
|
||||||
|
await service.initialize();
|
||||||
|
|
||||||
|
const accountData = { id: 'account-1', name: 'Test Account' };
|
||||||
|
service.updateAccount(accountData);
|
||||||
|
|
||||||
|
expect(mockPendo.updateOptions).toHaveBeenCalledWith({
|
||||||
|
account: accountData
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not call updateOptions if not initialized', () => {
|
||||||
|
const accountData = { id: 'account-1', name: 'Test Account' };
|
||||||
|
service.updateAccount(accountData);
|
||||||
|
|
||||||
|
expect(mockPendo.updateOptions).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('track', () => {
|
||||||
|
it('should call track with event name and metadata', async () => {
|
||||||
|
await service.initialize();
|
||||||
|
|
||||||
|
const eventName = 'test-event';
|
||||||
|
const metadata = { property: 'value' };
|
||||||
|
service.track(eventName, metadata);
|
||||||
|
|
||||||
|
expect(mockPendo.track).toHaveBeenCalledWith(eventName, metadata);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not call track if not initialized', () => {
|
||||||
|
const eventName = 'test-event';
|
||||||
|
service.track(eventName);
|
||||||
|
|
||||||
|
expect(mockPendo.track).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('identify', () => {
|
||||||
|
it('should call identify with visitor and account data', async () => {
|
||||||
|
await service.initialize();
|
||||||
|
|
||||||
|
const visitorId = 'visitor-1';
|
||||||
|
const accountId = 'account-1';
|
||||||
|
const visitorData = { name: 'Test User' };
|
||||||
|
const accountData = { name: 'Test Account' };
|
||||||
|
|
||||||
|
service.identify(visitorId, accountId, visitorData, accountData);
|
||||||
|
|
||||||
|
expect(mockPendo.identify).toHaveBeenCalledWith({
|
||||||
|
visitor: { id: visitorId, ...visitorData },
|
||||||
|
account: { id: accountId, ...accountData }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call identify with minimal data', async () => {
|
||||||
|
await service.initialize();
|
||||||
|
|
||||||
|
const visitorId = 'visitor-1';
|
||||||
|
const accountId = 'account-1';
|
||||||
|
|
||||||
|
service.identify(visitorId, accountId);
|
||||||
|
|
||||||
|
expect(mockPendo.identify).toHaveBeenCalledWith({
|
||||||
|
visitor: { id: visitorId },
|
||||||
|
account: { id: accountId }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not call identify if not initialized', () => {
|
||||||
|
const visitorId = 'visitor-1';
|
||||||
|
const accountId = 'account-1';
|
||||||
|
|
||||||
|
service.identify(visitorId, accountId);
|
||||||
|
|
||||||
|
expect(mockPendo.identify).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('disable', () => {
|
||||||
|
it('should call disableCookies', async () => {
|
||||||
|
await service.initialize();
|
||||||
|
|
||||||
|
service.disable();
|
||||||
|
|
||||||
|
expect(mockPendo.disableCookies).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not call disableCookies if not initialized', () => {
|
||||||
|
service.disable();
|
||||||
|
|
||||||
|
expect(mockPendo.disableCookies).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('isReady', () => {
|
||||||
|
it('should return true when Pendo is ready', async () => {
|
||||||
|
await service.initialize();
|
||||||
|
|
||||||
|
expect(service.isReady()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false when not initialized', () => {
|
||||||
|
expect(service.isReady()).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test for SSR (server-side rendering) environment
|
||||||
|
describe('in SSR environment', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.resetTestingModule();
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [
|
||||||
|
PendoService,
|
||||||
|
{ provide: PLATFORM_ID, useValue: 'server' }, // Simulate server-side rendering
|
||||||
|
{ provide: PENDO_CONFIG, useValue: mockConfig }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
service = TestBed.inject(PendoService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not attempt to initialize Pendo', async () => {
|
||||||
|
await service.initialize();
|
||||||
|
|
||||||
|
expect(mockPendo.initialize).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not call any Pendo methods', () => {
|
||||||
|
service.track('event');
|
||||||
|
service.identify('visitor', 'account');
|
||||||
|
service.updateVisitor({ id: 'visitor' });
|
||||||
|
service.updateAccount({ id: 'account' });
|
||||||
|
service.disable();
|
||||||
|
|
||||||
|
expect(mockPendo.track).not.toHaveBeenCalled();
|
||||||
|
expect(mockPendo.identify).not.toHaveBeenCalled();
|
||||||
|
expect(mockPendo.updateOptions).not.toHaveBeenCalled();
|
||||||
|
expect(mockPendo.disableCookies).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false for isReady', () => {
|
||||||
|
expect(service.isReady()).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
41
projects/ngx-pendo-lite/src/lib/pendo.module.ts
Normal file
41
projects/ngx-pendo-lite/src/lib/pendo.module.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { ModuleWithProviders, NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { PendoConfig, PendoService, PENDO_CONFIG } from './pendo.service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Angular module for Pendo.io integration
|
||||||
|
*/
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule
|
||||||
|
],
|
||||||
|
providers: []
|
||||||
|
})
|
||||||
|
export class PendoModule {
|
||||||
|
/**
|
||||||
|
* Use this method in your root module to provide and configure the PendoService
|
||||||
|
* @param config Configuration for Pendo initialization
|
||||||
|
* @returns ModuleWithProviders configuration for Angular
|
||||||
|
*/
|
||||||
|
static forRoot(config: PendoConfig): ModuleWithProviders<PendoModule> {
|
||||||
|
return {
|
||||||
|
ngModule: PendoModule,
|
||||||
|
providers: [
|
||||||
|
{ provide: PENDO_CONFIG, useValue: config },
|
||||||
|
PendoService
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this method to include the module in feature modules without providing
|
||||||
|
* the service again (it should only be provided once in the app)
|
||||||
|
* @returns ModuleWithProviders configuration for Angular feature modules
|
||||||
|
*/
|
||||||
|
static forChild(): ModuleWithProviders<PendoModule> {
|
||||||
|
return {
|
||||||
|
ngModule: PendoModule,
|
||||||
|
providers: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
318
projects/ngx-pendo-lite/src/lib/pendo.service.ts
Normal file
318
projects/ngx-pendo-lite/src/lib/pendo.service.ts
Normal file
@@ -0,0 +1,318 @@
|
|||||||
|
import { Inject, Injectable, Optional, PLATFORM_ID } from '@angular/core';
|
||||||
|
import { isPlatformBrowser } from '@angular/common';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for visitor data
|
||||||
|
*/
|
||||||
|
export interface PendoVisitor {
|
||||||
|
/** Required unique visitor identifier */
|
||||||
|
id: string;
|
||||||
|
/** Any additional visitor properties */
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for account data
|
||||||
|
*/
|
||||||
|
export interface PendoAccount {
|
||||||
|
/** Required unique account identifier */
|
||||||
|
id: string;
|
||||||
|
/** Any additional account properties */
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pendo initialization configuration options
|
||||||
|
*/
|
||||||
|
export interface PendoConfig {
|
||||||
|
/** Your Pendo API key */
|
||||||
|
apiKey: string;
|
||||||
|
/** Optional visitor data */
|
||||||
|
visitor?: PendoVisitor;
|
||||||
|
/** Optional account data */
|
||||||
|
account?: PendoAccount;
|
||||||
|
/** Optional Pendo script URL. If not provided, uses the default URL with apiKey */
|
||||||
|
scriptUrl?: string;
|
||||||
|
/** Whether to load Pendo script automatically. Default is true */
|
||||||
|
autoLoad?: boolean;
|
||||||
|
/** Whether to disable cookies. Default is false */
|
||||||
|
disableCookies?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type definition for the Pendo global object
|
||||||
|
*/
|
||||||
|
export interface PendoInstance {
|
||||||
|
initialize: (options: {
|
||||||
|
apiKey: string;
|
||||||
|
visitor?: PendoVisitor;
|
||||||
|
account?: PendoAccount;
|
||||||
|
}) => void;
|
||||||
|
updateOptions: (options: {
|
||||||
|
visitor?: PendoVisitor;
|
||||||
|
account?: PendoAccount;
|
||||||
|
}) => void;
|
||||||
|
identify: (visitor: { visitor: PendoVisitor; account: PendoAccount }) => void;
|
||||||
|
track: (eventName: string, metadata?: Record<string, any>) => void;
|
||||||
|
disableCookies: () => void;
|
||||||
|
isReady: () => boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Token for providing Pendo configuration
|
||||||
|
*/
|
||||||
|
export const PENDO_CONFIG = 'PENDO_CONFIG';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Angular service wrapper for Pendo.io analytics
|
||||||
|
*/
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class PendoService {
|
||||||
|
/**
|
||||||
|
* Flag indicating if Pendo has been initialized
|
||||||
|
*/
|
||||||
|
private isInitialized = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reference to the Pendo instance
|
||||||
|
*/
|
||||||
|
private pendoInstance?: PendoInstance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration options
|
||||||
|
*/
|
||||||
|
private config: PendoConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Script loading promise to prevent multiple script loads
|
||||||
|
*/
|
||||||
|
private loadPromise: Promise<void> | null = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param platformId Angular platform ID for SSR detection
|
||||||
|
* @param config Optional injected Pendo configuration
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
@Inject(PLATFORM_ID) private platformId: Object,
|
||||||
|
@Optional() @Inject(PENDO_CONFIG) config?: PendoConfig
|
||||||
|
) {
|
||||||
|
this.config = config || { apiKey: '' };
|
||||||
|
|
||||||
|
// Auto-load the script if running in browser and autoLoad is not explicitly disabled
|
||||||
|
if (
|
||||||
|
isPlatformBrowser(this.platformId) &&
|
||||||
|
config?.apiKey &&
|
||||||
|
(config.autoLoad !== false)
|
||||||
|
) {
|
||||||
|
this.loadPendoScript();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the Pendo script asynchronously
|
||||||
|
* @returns Promise that resolves when the script is loaded
|
||||||
|
*/
|
||||||
|
public loadPendoScript(): Promise<void> {
|
||||||
|
// Don't attempt to load in non-browser environments
|
||||||
|
if (!isPlatformBrowser(this.platformId)) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return existing promise if already loading
|
||||||
|
if (this.loadPromise) {
|
||||||
|
return this.loadPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loadPromise = new Promise<void>((resolve, reject) => {
|
||||||
|
// Check if Pendo is already loaded
|
||||||
|
if (typeof window !== 'undefined' && (window as any).pendo) {
|
||||||
|
this.pendoInstance = (window as any).pendo;
|
||||||
|
resolve();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Create a script element to load Pendo
|
||||||
|
const script = document.createElement('script');
|
||||||
|
script.async = true;
|
||||||
|
script.defer = true;
|
||||||
|
|
||||||
|
// Use custom URL if provided, otherwise construct from API key
|
||||||
|
script.src = this.config.scriptUrl ||
|
||||||
|
`https://cdn.pendo.io/agent/static/${this.config.apiKey}/pendo.js`;
|
||||||
|
|
||||||
|
script.onload = () => {
|
||||||
|
// Make Pendo instance accessible
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
this.pendoInstance = (window as any).pendo;
|
||||||
|
resolve();
|
||||||
|
} else {
|
||||||
|
reject(new Error('Window is not defined after script load'));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
script.onerror = () => {
|
||||||
|
reject(new Error('Failed to load Pendo script'));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Append script to the document head
|
||||||
|
document.head.appendChild(script);
|
||||||
|
} catch (error) {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return this.loadPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize Pendo with configuration
|
||||||
|
* @param config Pendo configuration options
|
||||||
|
* @returns Promise that resolves when initialization is complete
|
||||||
|
*/
|
||||||
|
public async initialize(config?: PendoConfig): Promise<void> {
|
||||||
|
// Don't attempt to initialize in non-browser environments
|
||||||
|
if (!isPlatformBrowser(this.platformId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge provided config with existing config
|
||||||
|
if (config) {
|
||||||
|
this.config = { ...this.config, ...config };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate API key
|
||||||
|
if (!this.config.apiKey) {
|
||||||
|
console.error('Pendo API key is required');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Ensure script is loaded
|
||||||
|
await this.loadPendoScript();
|
||||||
|
|
||||||
|
// Check if Pendo instance is available
|
||||||
|
if (!this.pendoInstance) {
|
||||||
|
throw new Error('Pendo instance not available');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize Pendo
|
||||||
|
this.pendoInstance.initialize({
|
||||||
|
apiKey: this.config.apiKey,
|
||||||
|
visitor: this.config.visitor,
|
||||||
|
account: this.config.account,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set initialized flag
|
||||||
|
this.isInitialized = true;
|
||||||
|
|
||||||
|
// Disable cookies if configured
|
||||||
|
if (this.config.disableCookies) {
|
||||||
|
this.disable();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to initialize Pendo:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates visitor information
|
||||||
|
* @param visitorData Visitor data to update
|
||||||
|
*/
|
||||||
|
public updateVisitor(visitorData: PendoVisitor): void {
|
||||||
|
if (!this.isInitialized || !isPlatformBrowser(this.platformId) || !this.pendoInstance) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.pendoInstance.updateOptions({
|
||||||
|
visitor: visitorData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates account information
|
||||||
|
* @param accountData Account data to update
|
||||||
|
*/
|
||||||
|
public updateAccount(accountData: PendoAccount): void {
|
||||||
|
if (!this.isInitialized || !isPlatformBrowser(this.platformId) || !this.pendoInstance) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.pendoInstance.updateOptions({
|
||||||
|
account: accountData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Track a custom event in Pendo
|
||||||
|
* @param eventName Name of the event to track
|
||||||
|
* @param metadata Optional metadata for the event
|
||||||
|
*/
|
||||||
|
public track(eventName: string, metadata?: Record<string, any>): void {
|
||||||
|
if (!this.isInitialized || !isPlatformBrowser(this.platformId) || !this.pendoInstance) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.pendoInstance.track(eventName, metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identify user and account (or update existing)
|
||||||
|
* @param visitorId Visitor identifier
|
||||||
|
* @param accountId Account identifier
|
||||||
|
* @param visitorData Additional visitor metadata
|
||||||
|
* @param accountData Additional account metadata
|
||||||
|
*/
|
||||||
|
public identify(
|
||||||
|
visitorId: string,
|
||||||
|
accountId: string,
|
||||||
|
visitorData?: Record<string, any>,
|
||||||
|
accountData?: Record<string, any>
|
||||||
|
): void {
|
||||||
|
if (!this.isInitialized || !isPlatformBrowser(this.platformId) || !this.pendoInstance) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const visitor: PendoVisitor = {
|
||||||
|
id: visitorId,
|
||||||
|
...(visitorData || {})
|
||||||
|
};
|
||||||
|
|
||||||
|
const account: PendoAccount = {
|
||||||
|
id: accountId,
|
||||||
|
...(accountData || {})
|
||||||
|
};
|
||||||
|
|
||||||
|
this.pendoInstance.identify({
|
||||||
|
visitor,
|
||||||
|
account
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable Pendo tracking by disabling cookies
|
||||||
|
*/
|
||||||
|
public disable(): void {
|
||||||
|
if (!this.isInitialized || !isPlatformBrowser(this.platformId) || !this.pendoInstance) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.pendoInstance.disableCookies();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if Pendo is ready
|
||||||
|
* @returns boolean indicating if Pendo is ready
|
||||||
|
*/
|
||||||
|
public isReady(): boolean {
|
||||||
|
if (!isPlatformBrowser(this.platformId) || !this.pendoInstance) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return typeof this.pendoInstance.isReady === 'function'
|
||||||
|
? this.pendoInstance.isReady()
|
||||||
|
: this.isInitialized;
|
||||||
|
}
|
||||||
|
}
|
||||||
7
projects/ngx-pendo-lite/src/public-api.ts
Normal file
7
projects/ngx-pendo-lite/src/public-api.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/*
|
||||||
|
* Public API Surface of ngx-pendo-lite
|
||||||
|
* This is the main entry point for the library
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Re-export everything from the lib/index.ts file
|
||||||
|
export * from './lib/index';
|
||||||
15
projects/ngx-pendo-lite/src/test.ts
Normal file
15
projects/ngx-pendo-lite/src/test.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
||||||
|
|
||||||
|
import 'zone.js';
|
||||||
|
import 'zone.js/testing';
|
||||||
|
import { getTestBed } from '@angular/core/testing';
|
||||||
|
import {
|
||||||
|
BrowserDynamicTestingModule,
|
||||||
|
platformBrowserDynamicTesting
|
||||||
|
} from '@angular/platform-browser-dynamic/testing';
|
||||||
|
|
||||||
|
// First, initialize the Angular testing environment.
|
||||||
|
getTestBed().initTestEnvironment(
|
||||||
|
BrowserDynamicTestingModule,
|
||||||
|
platformBrowserDynamicTesting(),
|
||||||
|
);
|
||||||
37
projects/ngx-pendo-lite/tsconfig.json
Normal file
37
projects/ngx-pendo-lite/tsconfig.json
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"compileOnSave": false,
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": "./",
|
||||||
|
"outDir": "./dist/out-tsc",
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"strict": true,
|
||||||
|
"noImplicitOverride": true,
|
||||||
|
"noPropertyAccessFromIndexSignature": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"declaration": false,
|
||||||
|
"downlevelIteration": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"importHelpers": true,
|
||||||
|
"target": "ES2022",
|
||||||
|
"module": "ES2022",
|
||||||
|
"useDefineForClassFields": false,
|
||||||
|
"lib": [
|
||||||
|
"ES2022",
|
||||||
|
"dom"
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"ngx-pendo-lite": [
|
||||||
|
"dist/ngx-pendo-lite"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"enableI18nLegacyMessageIdFormat": false,
|
||||||
|
"strictInjectionParameters": true,
|
||||||
|
"strictInputAccessModifiers": true,
|
||||||
|
"strictTemplates": true
|
||||||
|
}
|
||||||
|
}
|
||||||
31
projects/ngx-pendo-lite/tsconfig.lib.json
Normal file
31
projects/ngx-pendo-lite/tsconfig.lib.json
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../dist/out-tsc/lib",
|
||||||
|
"declaration": true,
|
||||||
|
"declarationMap": true,
|
||||||
|
"inlineSources": true,
|
||||||
|
"types": [],
|
||||||
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"es2022"
|
||||||
|
],
|
||||||
|
"target": "ES2022",
|
||||||
|
"module": "ES2022",
|
||||||
|
"useDefineForClassFields": false
|
||||||
|
},
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"skipTemplateCodegen": true,
|
||||||
|
"strictMetadataEmit": true,
|
||||||
|
"enableResourceInlining": true,
|
||||||
|
"strictInjectionParameters": true,
|
||||||
|
"strictInputAccessModifiers": true,
|
||||||
|
"strictTemplates": true,
|
||||||
|
"compilationMode": "partial"
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"src/test.ts",
|
||||||
|
"**/*.spec.ts",
|
||||||
|
"**/*.test.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
10
projects/ngx-pendo-lite/tsconfig.lib.prod.json
Normal file
10
projects/ngx-pendo-lite/tsconfig.lib.prod.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
{
|
||||||
|
"extends": "./tsconfig.lib.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"declarationMap": false
|
||||||
|
},
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"compilationMode": "full"
|
||||||
|
}
|
||||||
|
}
|
||||||
15
projects/ngx-pendo-lite/tsconfig.spec.json
Normal file
15
projects/ngx-pendo-lite/tsconfig.spec.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
|
||||||
|
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
|
||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../out-tsc/spec",
|
||||||
|
"types": [
|
||||||
|
"jasmine"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"**/*.spec.ts",
|
||||||
|
"**/*.d.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
32
tsconfig.json
Normal file
32
tsconfig.json
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
|
||||||
|
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
|
||||||
|
{
|
||||||
|
"compileOnSave": false,
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "./dist/out-tsc",
|
||||||
|
"strict": true,
|
||||||
|
"noImplicitOverride": true,
|
||||||
|
"noPropertyAccessFromIndexSignature": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"paths": {
|
||||||
|
"ngx-pendo": [
|
||||||
|
"./dist/ngx-pendo"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"importHelpers": true,
|
||||||
|
"target": "ES2022",
|
||||||
|
"module": "ES2022"
|
||||||
|
},
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"enableI18nLegacyMessageIdFormat": false,
|
||||||
|
"strictInjectionParameters": true,
|
||||||
|
"strictInputAccessModifiers": true,
|
||||||
|
"strictTemplates": true
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user