@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 +3 -3
- package/dist/templates/ai-configs/claude/CLAUDE.md +2 -2
- package/dist/templates/ai-configs/claude/rules/frontend.instructions.md +3 -4
- package/dist/templates/ai-configs/claude/rules/unit-tests.instructions.md +1 -0
- package/dist/templates/ai-configs/cursor/cursor.mdc +2 -2
- package/dist/templates/ai-configs/cursor/rules/frontend.instructions.md +3 -4
- package/dist/templates/ai-configs/cursor/rules/unit-tests.instructions.md +1 -0
- package/dist/templates/ai-configs/gemini/GEMINI.md +2 -2
- package/dist/templates/ai-configs/gemini/rules/frontend.instructions.md +3 -4
- package/dist/templates/ai-configs/gemini/rules/unit-tests.instructions.md +1 -0
- package/dist/templates/ai-configs/github/copilot-instructions.md +2 -2
- package/dist/templates/ai-configs/github/instructions/frontend.instructions.md +3 -4
- package/dist/templates/ai-configs/github/instructions/unit-tests.instructions.md +1 -0
- package/dist/templates/ai-configs/jetbrains/guidelines.md +2 -2
- package/dist/templates/ai-configs/jetbrains/rules/frontend.instructions.md +3 -4
- package/dist/templates/ai-configs/jetbrains/rules/unit-tests.instructions.md +1 -0
- package/dist/templates/ai-configs/windsurf/guidelines.md +2 -2
- package/dist/templates/ai-configs/windsurf/rules/frontend.instructions.md +3 -4
- package/dist/templates/ai-configs/windsurf/rules/unit-tests.instructions.md +1 -0
- package/package.json +2 -2
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
|
|
8
|
+
Install the Angular 22 `@angular/cli` package.
|
|
9
9
|
|
|
10
10
|
```bash
|
|
11
|
-
npm install @angular/cli@
|
|
11
|
+
npm install @angular/cli@22 -g
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
Generate a new Angular
|
|
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
|
|
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
|
-
-
|
|
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
|
-
-
|
|
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 {
|
|
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
|
|
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
|
-
-
|
|
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
|
-
-
|
|
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 {
|
|
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
|
|
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
|
-
-
|
|
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
|
-
-
|
|
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 {
|
|
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
|
|
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
|
-
-
|
|
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
|
-
-
|
|
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 {
|
|
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
|
|
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
|
-
-
|
|
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
|
-
-
|
|
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 {
|
|
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
|
|
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
|
-
-
|
|
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
|
-
-
|
|
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 {
|
|
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": "
|
|
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": "
|
|
34
|
+
"typescript": "6.0.3"
|
|
35
35
|
},
|
|
36
36
|
"author": "Cumulocity"
|
|
37
37
|
}
|