@c8y/websdk 1024.22.10 → 1025.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,13 +5,13 @@ The @c8y/websdk Angular schematic enables quick scaffolding of custom Cumulocity
5
5
  # How to use
6
6
 
7
7
  ## Install
8
- Install the Angular 16 `@angular/cli` package.
8
+ Install the Angular 22 `@angular/cli` package.
9
9
 
10
10
  ```bash
11
- npm install @angular/cli@v16-lts -g
11
+ npm install @angular/cli@22 -g
12
12
  ```
13
13
 
14
- Generate a new Angular 16 application:
14
+ Generate a new Angular 22 application:
15
15
 
16
16
  ```bash
17
17
  ng new <appName> --interactive=false --routing=true --style=less
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Cumulocity IoT Web Application** — custom web frontend built with the Cumulocity Web SDK. Extends the Cumulocity IoT platform with custom features and integrations.
4
4
 
5
- - **Stack:** Angular 20, TypeScript 5.9.3, RxJS 7.8, Jest 30, Cypress 15, ESLint (airbnb-base + angular-eslint)
5
+ - **Stack:** Angular 22, TypeScript 6.0.3, RxJS 7.8, Jest 30, Cypress 15, ESLint (airbnb-base + angular-eslint)
6
6
  - **Core Libraries:** `@c8y/ngx-components`, `@c8y/client`, `@c8y/toolkit`, `@c8y/devkit`, `@c8y/bootstrap`
7
7
  - **Structure:** Standard Angular CLI application scaffolded with `ng add @c8y/websdk`
8
8
 
@@ -68,7 +68,7 @@ Only after completing Steps 1-2, proceed with planning or implementation.
68
68
  ## Angular Patterns
69
69
 
70
70
  - All new components must be **standalone** (`standalone: true`) — do not create NgModule-based components
71
- - Prefer `ChangeDetectionStrategy.OnPush` for new components (no project-wide enforcement, but scale demands it)
71
+ - OnPush is the default since Angular 22. A component without `changeDetection` re-renders only on new inputs, template or host events, signals read in its template, the `async` pipe or `markForCheck()`, so keep template state in signals: a plain field assigned in a subscription or timer never shows. It also stops refreshing its whole subtree, so a component that renders, directly or through its children, components relying on zone.js (widget and plugin hosts such as `c8y-dynamic-component` or component outlets, or existing `Eager` components that update from subscriptions or timers) declares `ChangeDetectionStrategy.Eager` with a comment saying why. Do not remove `Eager` from existing components as a side change
72
72
  - Constructor injection and `inject()` function are both present; either is acceptable
73
73
  - Manage subscriptions with `async` pipe or `takeUntilDestroyed()` — avoid bare `unsubscribe()` without `ngOnDestroy`
74
74
  - Use signals for local component state
@@ -39,7 +39,7 @@ These are the highest-severity issues — NEVER introduce them:
39
39
  ## Components
40
40
 
41
41
  - All new components must be **standalone** — do not set `standalone: true` explicitly (default since Angular 19+)
42
- - Set `changeDetection: ChangeDetectionStrategy.OnPush` in all `@Component` decorators
42
+ - OnPush is the default since Angular 22: a component without `changeDetection` re-renders only on new inputs, template or host events, signals read in its template, the `async` pipe or `markForCheck()`. Keep template state in signals; a plain field assigned in a subscription, promise or timer does not show. An OnPush component also stops refreshing its whole subtree, so a component that renders, directly or through its children, components relying on zone.js (widget and plugin hosts: `ViewContainerRef.createComponent`, `c8y-dynamic-component`, component outlets; or existing `Eager` components that update from subscriptions or timers) declares `ChangeDetectionStrategy.Eager` with a comment saying why. Do not remove `Eager` from existing components as a side change. `ChangeDetectionStrategy.Default` is deprecated
43
43
  - Keep components small — extract when template exceeds ~150 lines or class exceeds ~200 lines
44
44
  - Components focus on presentation; extract business logic, data mapping, and SDK calls to dedicated services
45
45
  - Use `readonly` for properties that should not change
@@ -55,12 +55,11 @@ These are the highest-severity issues — NEVER introduce them:
55
55
  ### Example
56
56
 
57
57
  ```ts
58
- import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
58
+ import { Component, signal } from '@angular/core';
59
59
 
60
60
  @Component({
61
61
  selector: 'c8y-example-component',
62
- templateUrl: './example.component.html',
63
- changeDetection: ChangeDetectionStrategy.OnPush
62
+ templateUrl: './example.component.html'
64
63
  })
65
64
  export class ExampleComponent {
66
65
  protected readonly isServerRunning = signal(true);
@@ -63,6 +63,7 @@ describe('ComponentName', () => {
63
63
  ## Common Pitfalls to Avoid
64
64
  - ❌ **Forgetting `async` and `.compileComponents()`**: `beforeEach(() => { ... })` without `async`/`await` leaves components uncompiled
65
65
  - ❌ **Missing `fixture.detectChanges()`**: Component won't initialize without this; properties will be undefined
66
+ - ❌ **Mutating a field of an OnPush component, then `detectChanges()`**: OnPush is the default since Angular 22 and the view does not re-render; set inputs with `fixture.componentRef.setInput()` and keep component state in signals
66
67
  - ❌ **Incomplete service mocks**: Mocking only some methods causes "is not a function" errors on unmocked methods
67
68
  - ❌ **Wrong mock return types**: Returning `[]` when the method returns `{ data: [], paging: {} }` causes destructuring errors
68
69
  - ❌ **Not providing all dependencies**: Missing providers (e.g., `TranslateService`) causes "No provider found" errors
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Cumulocity IoT Web Application** — custom web frontend built with the Cumulocity Web SDK. Extends the Cumulocity IoT platform with custom features and integrations.
4
4
 
5
- - **Stack:** Angular 20, TypeScript 5.9.3, RxJS 7.8, Jest 30, Cypress 15, ESLint (airbnb-base + angular-eslint)
5
+ - **Stack:** Angular 22, TypeScript 6.0.3, RxJS 7.8, Jest 30, Cypress 15, ESLint (airbnb-base + angular-eslint)
6
6
  - **Core Libraries:** `@c8y/ngx-components`, `@c8y/client`, `@c8y/toolkit`, `@c8y/devkit`, `@c8y/bootstrap`
7
7
  - **Structure:** Standard Angular CLI application scaffolded with `ng add @c8y/websdk`
8
8
 
@@ -68,7 +68,7 @@ Only after completing Steps 1-2, proceed with planning or implementation.
68
68
  ## Angular Patterns
69
69
 
70
70
  - All new components must be **standalone** (`standalone: true`) — do not create NgModule-based components
71
- - Prefer `ChangeDetectionStrategy.OnPush` for new components (no project-wide enforcement, but scale demands it)
71
+ - OnPush is the default since Angular 22. A component without `changeDetection` re-renders only on new inputs, template or host events, signals read in its template, the `async` pipe or `markForCheck()`, so keep template state in signals: a plain field assigned in a subscription or timer never shows. It also stops refreshing its whole subtree, so a component that renders, directly or through its children, components relying on zone.js (widget and plugin hosts such as `c8y-dynamic-component` or component outlets, or existing `Eager` components that update from subscriptions or timers) declares `ChangeDetectionStrategy.Eager` with a comment saying why. Do not remove `Eager` from existing components as a side change
72
72
  - Constructor injection and `inject()` function are both present; either is acceptable
73
73
  - Manage subscriptions with `async` pipe or `takeUntilDestroyed()` — avoid bare `unsubscribe()` without `ngOnDestroy`
74
74
  - Use signals for local component state
@@ -39,7 +39,7 @@ These are the highest-severity issues — NEVER introduce them:
39
39
  ## Components
40
40
 
41
41
  - All new components must be **standalone** — do not set `standalone: true` explicitly (default since Angular 19+)
42
- - Set `changeDetection: ChangeDetectionStrategy.OnPush` in all `@Component` decorators
42
+ - OnPush is the default since Angular 22: a component without `changeDetection` re-renders only on new inputs, template or host events, signals read in its template, the `async` pipe or `markForCheck()`. Keep template state in signals; a plain field assigned in a subscription, promise or timer does not show. An OnPush component also stops refreshing its whole subtree, so a component that renders, directly or through its children, components relying on zone.js (widget and plugin hosts: `ViewContainerRef.createComponent`, `c8y-dynamic-component`, component outlets; or existing `Eager` components that update from subscriptions or timers) declares `ChangeDetectionStrategy.Eager` with a comment saying why. Do not remove `Eager` from existing components as a side change. `ChangeDetectionStrategy.Default` is deprecated
43
43
  - Keep components small — extract when template exceeds ~150 lines or class exceeds ~200 lines
44
44
  - Components focus on presentation; extract business logic, data mapping, and SDK calls to dedicated services
45
45
  - Use `readonly` for properties that should not change
@@ -55,12 +55,11 @@ These are the highest-severity issues — NEVER introduce them:
55
55
  ### Example
56
56
 
57
57
  ```ts
58
- import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
58
+ import { Component, signal } from '@angular/core';
59
59
 
60
60
  @Component({
61
61
  selector: 'c8y-example-component',
62
- templateUrl: './example.component.html',
63
- changeDetection: ChangeDetectionStrategy.OnPush
62
+ templateUrl: './example.component.html'
64
63
  })
65
64
  export class ExampleComponent {
66
65
  protected readonly isServerRunning = signal(true);
@@ -63,6 +63,7 @@ describe('ComponentName', () => {
63
63
  ## Common Pitfalls to Avoid
64
64
  - ❌ **Forgetting `async` and `.compileComponents()`**: `beforeEach(() => { ... })` without `async`/`await` leaves components uncompiled
65
65
  - ❌ **Missing `fixture.detectChanges()`**: Component won't initialize without this; properties will be undefined
66
+ - ❌ **Mutating a field of an OnPush component, then `detectChanges()`**: OnPush is the default since Angular 22 and the view does not re-render; set inputs with `fixture.componentRef.setInput()` and keep component state in signals
66
67
  - ❌ **Incomplete service mocks**: Mocking only some methods causes "is not a function" errors on unmocked methods
67
68
  - ❌ **Wrong mock return types**: Returning `[]` when the method returns `{ data: [], paging: {} }` causes destructuring errors
68
69
  - ❌ **Not providing all dependencies**: Missing providers (e.g., `TranslateService`) causes "No provider found" errors
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Cumulocity IoT Web Application** — custom web frontend built with the Cumulocity Web SDK. Extends the Cumulocity IoT platform with custom features and integrations.
4
4
 
5
- - **Stack:** Angular 20, TypeScript 5.9.3, RxJS 7.8, Jest 30, Cypress 15, ESLint (airbnb-base + angular-eslint)
5
+ - **Stack:** Angular 22, TypeScript 6.0.3, RxJS 7.8, Jest 30, Cypress 15, ESLint (airbnb-base + angular-eslint)
6
6
  - **Core Libraries:** `@c8y/ngx-components`, `@c8y/client`, `@c8y/toolkit`, `@c8y/devkit`, `@c8y/bootstrap`
7
7
  - **Structure:** Standard Angular CLI application scaffolded with `ng add @c8y/websdk`
8
8
 
@@ -68,7 +68,7 @@ Only after completing Steps 1-2, proceed with planning or implementation.
68
68
  ## Angular Patterns
69
69
 
70
70
  - All new components must be **standalone** (`standalone: true`) — do not create NgModule-based components
71
- - Prefer `ChangeDetectionStrategy.OnPush` for new components (no project-wide enforcement, but scale demands it)
71
+ - OnPush is the default since Angular 22. A component without `changeDetection` re-renders only on new inputs, template or host events, signals read in its template, the `async` pipe or `markForCheck()`, so keep template state in signals: a plain field assigned in a subscription or timer never shows. It also stops refreshing its whole subtree, so a component that renders, directly or through its children, components relying on zone.js (widget and plugin hosts such as `c8y-dynamic-component` or component outlets, or existing `Eager` components that update from subscriptions or timers) declares `ChangeDetectionStrategy.Eager` with a comment saying why. Do not remove `Eager` from existing components as a side change
72
72
  - Constructor injection and `inject()` function are both present; either is acceptable
73
73
  - Manage subscriptions with `async` pipe or `takeUntilDestroyed()` — avoid bare `unsubscribe()` without `ngOnDestroy`
74
74
  - Use signals for local component state
@@ -35,7 +35,7 @@ These are the highest-severity issues — NEVER introduce them:
35
35
  ## Components
36
36
 
37
37
  - All new components must be **standalone** — do not set `standalone: true` explicitly (default since Angular 19+)
38
- - Set `changeDetection: ChangeDetectionStrategy.OnPush` in all `@Component` decorators
38
+ - OnPush is the default since Angular 22: a component without `changeDetection` re-renders only on new inputs, template or host events, signals read in its template, the `async` pipe or `markForCheck()`. Keep template state in signals; a plain field assigned in a subscription, promise or timer does not show. An OnPush component also stops refreshing its whole subtree, so a component that renders, directly or through its children, components relying on zone.js (widget and plugin hosts: `ViewContainerRef.createComponent`, `c8y-dynamic-component`, component outlets; or existing `Eager` components that update from subscriptions or timers) declares `ChangeDetectionStrategy.Eager` with a comment saying why. Do not remove `Eager` from existing components as a side change. `ChangeDetectionStrategy.Default` is deprecated
39
39
  - Keep components small — extract when template exceeds ~150 lines or class exceeds ~200 lines
40
40
  - Components focus on presentation; extract business logic, data mapping, and SDK calls to dedicated services
41
41
  - Use `readonly` for properties that should not change
@@ -51,12 +51,11 @@ These are the highest-severity issues — NEVER introduce them:
51
51
  ### Example
52
52
 
53
53
  ```ts
54
- import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
54
+ import { Component, signal } from '@angular/core';
55
55
 
56
56
  @Component({
57
57
  selector: 'c8y-example-component',
58
- templateUrl: './example.component.html',
59
- changeDetection: ChangeDetectionStrategy.OnPush
58
+ templateUrl: './example.component.html'
60
59
  })
61
60
  export class ExampleComponent {
62
61
  protected readonly isServerRunning = signal(true);
@@ -57,6 +57,7 @@ describe('ComponentName', () => {
57
57
  ## Common Pitfalls to Avoid
58
58
  - ❌ **Forgetting `async` and `.compileComponents()`**: `beforeEach(() => { ... })` without `async`/`await` leaves components uncompiled
59
59
  - ❌ **Missing `fixture.detectChanges()`**: Component won't initialize without this; properties will be undefined
60
+ - ❌ **Mutating a field of an OnPush component, then `detectChanges()`**: OnPush is the default since Angular 22 and the view does not re-render; set inputs with `fixture.componentRef.setInput()` and keep component state in signals
60
61
  - ❌ **Incomplete service mocks**: Mocking only some methods causes "is not a function" errors on unmocked methods
61
62
  - ❌ **Wrong mock return types**: Returning `[]` when the method returns `{ data: [], paging: {} }` causes destructuring errors
62
63
  - ❌ **Not providing all dependencies**: Missing providers (e.g., `TranslateService`) causes "No provider found" errors
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Cumulocity IoT Web Application** — custom web frontend built with the Cumulocity Web SDK. Extends the Cumulocity IoT platform with custom features and integrations.
4
4
 
5
- - **Stack:** Angular 20, TypeScript 5.9.3, RxJS 7.8, Jest 30, Cypress 15, ESLint (airbnb-base + angular-eslint)
5
+ - **Stack:** Angular 22, TypeScript 6.0.3, RxJS 7.8, Jest 30, Cypress 15, ESLint (airbnb-base + angular-eslint)
6
6
  - **Core Libraries:** `@c8y/ngx-components`, `@c8y/client`, `@c8y/toolkit`, `@c8y/devkit`, `@c8y/bootstrap`
7
7
  - **Structure:** Standard Angular CLI application scaffolded with `ng add @c8y/websdk`
8
8
 
@@ -68,7 +68,7 @@ Only after completing Steps 1-2, proceed with planning or implementation.
68
68
  ## Angular Patterns
69
69
 
70
70
  - All new components must be **standalone** (`standalone: true`) — do not create NgModule-based components
71
- - Prefer `ChangeDetectionStrategy.OnPush` for new components (no project-wide enforcement, but scale demands it)
71
+ - OnPush is the default since Angular 22. A component without `changeDetection` re-renders only on new inputs, template or host events, signals read in its template, the `async` pipe or `markForCheck()`, so keep template state in signals: a plain field assigned in a subscription or timer never shows. It also stops refreshing its whole subtree, so a component that renders, directly or through its children, components relying on zone.js (widget and plugin hosts such as `c8y-dynamic-component` or component outlets, or existing `Eager` components that update from subscriptions or timers) declares `ChangeDetectionStrategy.Eager` with a comment saying why. Do not remove `Eager` from existing components as a side change
72
72
  - Constructor injection and `inject()` function are both present; either is acceptable
73
73
  - Manage subscriptions with `async` pipe or `takeUntilDestroyed()` — avoid bare `unsubscribe()` without `ngOnDestroy`
74
74
  - Use signals for local component state
@@ -39,7 +39,7 @@ These are the highest-severity issues — NEVER introduce them:
39
39
  ## Components
40
40
 
41
41
  - All new components must be **standalone** — do not set `standalone: true` explicitly (default since Angular 19+)
42
- - Set `changeDetection: ChangeDetectionStrategy.OnPush` in all `@Component` decorators
42
+ - OnPush is the default since Angular 22: a component without `changeDetection` re-renders only on new inputs, template or host events, signals read in its template, the `async` pipe or `markForCheck()`. Keep template state in signals; a plain field assigned in a subscription, promise or timer does not show. An OnPush component also stops refreshing its whole subtree, so a component that renders, directly or through its children, components relying on zone.js (widget and plugin hosts: `ViewContainerRef.createComponent`, `c8y-dynamic-component`, component outlets; or existing `Eager` components that update from subscriptions or timers) declares `ChangeDetectionStrategy.Eager` with a comment saying why. Do not remove `Eager` from existing components as a side change. `ChangeDetectionStrategy.Default` is deprecated
43
43
  - Keep components small — extract when template exceeds ~150 lines or class exceeds ~200 lines
44
44
  - Components focus on presentation; extract business logic, data mapping, and SDK calls to dedicated services
45
45
  - Use `readonly` for properties that should not change
@@ -55,12 +55,11 @@ These are the highest-severity issues — NEVER introduce them:
55
55
  ### Example
56
56
 
57
57
  ```ts
58
- import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
58
+ import { Component, signal } from '@angular/core';
59
59
 
60
60
  @Component({
61
61
  selector: 'c8y-example-component',
62
- templateUrl: './example.component.html',
63
- changeDetection: ChangeDetectionStrategy.OnPush
62
+ templateUrl: './example.component.html'
64
63
  })
65
64
  export class ExampleComponent {
66
65
  protected readonly isServerRunning = signal(true);
@@ -63,6 +63,7 @@ describe('ComponentName', () => {
63
63
  ## Common Pitfalls to Avoid
64
64
  - ❌ **Forgetting `async` and `.compileComponents()`**: `beforeEach(() => { ... })` without `async`/`await` leaves components uncompiled
65
65
  - ❌ **Missing `fixture.detectChanges()`**: Component won't initialize without this; properties will be undefined
66
+ - ❌ **Mutating a field of an OnPush component, then `detectChanges()`**: OnPush is the default since Angular 22 and the view does not re-render; set inputs with `fixture.componentRef.setInput()` and keep component state in signals
66
67
  - ❌ **Incomplete service mocks**: Mocking only some methods causes "is not a function" errors on unmocked methods
67
68
  - ❌ **Wrong mock return types**: Returning `[]` when the method returns `{ data: [], paging: {} }` causes destructuring errors
68
69
  - ❌ **Not providing all dependencies**: Missing providers (e.g., `TranslateService`) causes "No provider found" errors
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Cumulocity IoT Web Application** — custom web frontend built with the Cumulocity Web SDK. Extends the Cumulocity IoT platform with custom features and integrations.
4
4
 
5
- - **Stack:** Angular 20, TypeScript 5.9.3, RxJS 7.8, Jest 30, Cypress 15, ESLint (airbnb-base + angular-eslint)
5
+ - **Stack:** Angular 22, TypeScript 6.0.3, RxJS 7.8, Jest 30, Cypress 15, ESLint (airbnb-base + angular-eslint)
6
6
  - **Core Libraries:** `@c8y/ngx-components`, `@c8y/client`, `@c8y/toolkit`, `@c8y/devkit`, `@c8y/bootstrap`
7
7
  - **Structure:** Standard Angular CLI application scaffolded with `ng add @c8y/websdk`
8
8
 
@@ -68,7 +68,7 @@ Only after completing Steps 1-2, proceed with planning or implementation.
68
68
  ## Angular Patterns
69
69
 
70
70
  - All new components must be **standalone** (`standalone: true`) — do not create NgModule-based components
71
- - Prefer `ChangeDetectionStrategy.OnPush` for new components (no project-wide enforcement, but scale demands it)
71
+ - OnPush is the default since Angular 22. A component without `changeDetection` re-renders only on new inputs, template or host events, signals read in its template, the `async` pipe or `markForCheck()`, so keep template state in signals: a plain field assigned in a subscription or timer never shows. It also stops refreshing its whole subtree, so a component that renders, directly or through its children, components relying on zone.js (widget and plugin hosts such as `c8y-dynamic-component` or component outlets, or existing `Eager` components that update from subscriptions or timers) declares `ChangeDetectionStrategy.Eager` with a comment saying why. Do not remove `Eager` from existing components as a side change
72
72
  - Constructor injection and `inject()` function are both present; either is acceptable
73
73
  - Manage subscriptions with `async` pipe or `takeUntilDestroyed()` — avoid bare `unsubscribe()` without `ngOnDestroy`
74
74
  - Use signals for local component state
@@ -35,7 +35,7 @@ These are the highest-severity issues — NEVER introduce them:
35
35
  ## Components
36
36
 
37
37
  - All new components must be **standalone** — do not set `standalone: true` explicitly (default since Angular 19+)
38
- - Set `changeDetection: ChangeDetectionStrategy.OnPush` in all `@Component` decorators
38
+ - OnPush is the default since Angular 22: a component without `changeDetection` re-renders only on new inputs, template or host events, signals read in its template, the `async` pipe or `markForCheck()`. Keep template state in signals; a plain field assigned in a subscription, promise or timer does not show. An OnPush component also stops refreshing its whole subtree, so a component that renders, directly or through its children, components relying on zone.js (widget and plugin hosts: `ViewContainerRef.createComponent`, `c8y-dynamic-component`, component outlets; or existing `Eager` components that update from subscriptions or timers) declares `ChangeDetectionStrategy.Eager` with a comment saying why. Do not remove `Eager` from existing components as a side change. `ChangeDetectionStrategy.Default` is deprecated
39
39
  - Keep components small — extract when template exceeds ~150 lines or class exceeds ~200 lines
40
40
  - Components focus on presentation; extract business logic, data mapping, and SDK calls to dedicated services
41
41
  - Use `readonly` for properties that should not change
@@ -51,12 +51,11 @@ These are the highest-severity issues — NEVER introduce them:
51
51
  ### Example
52
52
 
53
53
  ```ts
54
- import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
54
+ import { Component, signal } from '@angular/core';
55
55
 
56
56
  @Component({
57
57
  selector: 'c8y-example-component',
58
- templateUrl: './example.component.html',
59
- changeDetection: ChangeDetectionStrategy.OnPush
58
+ templateUrl: './example.component.html'
60
59
  })
61
60
  export class ExampleComponent {
62
61
  protected readonly isServerRunning = signal(true);
@@ -57,6 +57,7 @@ describe('ComponentName', () => {
57
57
  ## Common Pitfalls to Avoid
58
58
  - ❌ **Forgetting `async` and `.compileComponents()`**: `beforeEach(() => { ... })` without `async`/`await` leaves components uncompiled
59
59
  - ❌ **Missing `fixture.detectChanges()`**: Component won't initialize without this; properties will be undefined
60
+ - ❌ **Mutating a field of an OnPush component, then `detectChanges()`**: OnPush is the default since Angular 22 and the view does not re-render; set inputs with `fixture.componentRef.setInput()` and keep component state in signals
60
61
  - ❌ **Incomplete service mocks**: Mocking only some methods causes "is not a function" errors on unmocked methods
61
62
  - ❌ **Wrong mock return types**: Returning `[]` when the method returns `{ data: [], paging: {} }` causes destructuring errors
62
63
  - ❌ **Not providing all dependencies**: Missing providers (e.g., `TranslateService`) causes "No provider found" errors
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Cumulocity IoT Web Application** — custom web frontend built with the Cumulocity Web SDK. Extends the Cumulocity IoT platform with custom features and integrations.
4
4
 
5
- - **Stack:** Angular 20, TypeScript 5.9.3, RxJS 7.8, Jest 30, Cypress 15, ESLint (airbnb-base + angular-eslint)
5
+ - **Stack:** Angular 22, TypeScript 6.0.3, RxJS 7.8, Jest 30, Cypress 15, ESLint (airbnb-base + angular-eslint)
6
6
  - **Core Libraries:** `@c8y/ngx-components`, `@c8y/client`, `@c8y/toolkit`, `@c8y/devkit`, `@c8y/bootstrap`
7
7
  - **Structure:** Standard Angular CLI application scaffolded with `ng add @c8y/websdk`
8
8
 
@@ -68,7 +68,7 @@ Only after completing Steps 1-2, proceed with planning or implementation.
68
68
  ## Angular Patterns
69
69
 
70
70
  - All new components must be **standalone** (`standalone: true`) — do not create NgModule-based components
71
- - Prefer `ChangeDetectionStrategy.OnPush` for new components (no project-wide enforcement, but scale demands it)
71
+ - OnPush is the default since Angular 22. A component without `changeDetection` re-renders only on new inputs, template or host events, signals read in its template, the `async` pipe or `markForCheck()`, so keep template state in signals: a plain field assigned in a subscription or timer never shows. It also stops refreshing its whole subtree, so a component that renders, directly or through its children, components relying on zone.js (widget and plugin hosts such as `c8y-dynamic-component` or component outlets, or existing `Eager` components that update from subscriptions or timers) declares `ChangeDetectionStrategy.Eager` with a comment saying why. Do not remove `Eager` from existing components as a side change
72
72
  - Constructor injection and `inject()` function are both present; either is acceptable
73
73
  - Manage subscriptions with `async` pipe or `takeUntilDestroyed()` — avoid bare `unsubscribe()` without `ngOnDestroy`
74
74
  - Use signals for local component state
@@ -39,7 +39,7 @@ These are the highest-severity issues — NEVER introduce them:
39
39
  ## Components
40
40
 
41
41
  - All new components must be **standalone** — do not set `standalone: true` explicitly (default since Angular 19+)
42
- - Set `changeDetection: ChangeDetectionStrategy.OnPush` in all `@Component` decorators
42
+ - OnPush is the default since Angular 22: a component without `changeDetection` re-renders only on new inputs, template or host events, signals read in its template, the `async` pipe or `markForCheck()`. Keep template state in signals; a plain field assigned in a subscription, promise or timer does not show. An OnPush component also stops refreshing its whole subtree, so a component that renders, directly or through its children, components relying on zone.js (widget and plugin hosts: `ViewContainerRef.createComponent`, `c8y-dynamic-component`, component outlets; or existing `Eager` components that update from subscriptions or timers) declares `ChangeDetectionStrategy.Eager` with a comment saying why. Do not remove `Eager` from existing components as a side change. `ChangeDetectionStrategy.Default` is deprecated
43
43
  - Keep components small — extract when template exceeds ~150 lines or class exceeds ~200 lines
44
44
  - Components focus on presentation; extract business logic, data mapping, and SDK calls to dedicated services
45
45
  - Use `readonly` for properties that should not change
@@ -55,12 +55,11 @@ These are the highest-severity issues — NEVER introduce them:
55
55
  ### Example
56
56
 
57
57
  ```ts
58
- import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
58
+ import { Component, signal } from '@angular/core';
59
59
 
60
60
  @Component({
61
61
  selector: 'c8y-example-component',
62
- templateUrl: './example.component.html',
63
- changeDetection: ChangeDetectionStrategy.OnPush
62
+ templateUrl: './example.component.html'
64
63
  })
65
64
  export class ExampleComponent {
66
65
  protected readonly isServerRunning = signal(true);
@@ -63,6 +63,7 @@ describe('ComponentName', () => {
63
63
  ## Common Pitfalls to Avoid
64
64
  - ❌ **Forgetting `async` and `.compileComponents()`**: `beforeEach(() => { ... })` without `async`/`await` leaves components uncompiled
65
65
  - ❌ **Missing `fixture.detectChanges()`**: Component won't initialize without this; properties will be undefined
66
+ - ❌ **Mutating a field of an OnPush component, then `detectChanges()`**: OnPush is the default since Angular 22 and the view does not re-render; set inputs with `fixture.componentRef.setInput()` and keep component state in signals
66
67
  - ❌ **Incomplete service mocks**: Mocking only some methods causes "is not a function" errors on unmocked methods
67
68
  - ❌ **Wrong mock return types**: Returning `[]` when the method returns `{ data: [], paging: {} }` causes destructuring errors
68
69
  - ❌ **Not providing all dependencies**: Missing providers (e.g., `TranslateService`) causes "No provider found" errors
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c8y/websdk",
3
- "version": "1024.22.10",
3
+ "version": "1025.0.0",
4
4
  "description": "Allows to scaffold a Cumulocity IoT application with ng add @c8y/websdk",
5
5
  "license": "Apache-2.0",
6
6
  "scripts": {
@@ -31,7 +31,7 @@
31
31
  "ncp": "2.0.0",
32
32
  "rimraf": "2.6.2",
33
33
  "ts-node": "10.9.2",
34
- "typescript": "5.9.3"
34
+ "typescript": "6.0.3"
35
35
  },
36
36
  "author": "Cumulocity"
37
37
  }