@n8n/frontend-module-sdk 0.7.1 → 0.8.1

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
@@ -14,3 +14,12 @@ only public entry point.
14
14
  ```ts
15
15
  import { modalRegistry, registerResource, type FrontendModuleDescription } from '@n8n/frontend-module-sdk';
16
16
  ```
17
+
18
+ ## Push handlers
19
+
20
+ A module owns a push message type when it declares it in `pushHandlers`. The
21
+ shell dispatches these at app scope, so a handler runs in every layout. The shell
22
+ skips its own built-in handler for a type a module owns.
23
+
24
+ **Contract:** a handler must not depend on the built-in handling of the same
25
+ event. The two run on separate listeners, so their order is not defined.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@n8n/frontend-module-sdk",
4
- "version": "0.7.1",
4
+ "version": "0.8.1",
5
5
  "main": "src/index.ts",
6
6
  "import": "src/index.ts",
7
7
  "exports": {
@@ -10,8 +10,8 @@
10
10
  "dependencies": {
11
11
  "vue": "^3.5.13",
12
12
  "vue-router": "^4.5.0",
13
- "@n8n/api-types": "1.37.1",
14
- "@n8n/design-system": "2.36.1"
13
+ "@n8n/api-types": "1.38.1",
14
+ "@n8n/design-system": "2.37.1"
15
15
  },
16
16
  "devDependencies": {
17
17
  "typescript": "6.0.2",
@@ -20,7 +20,7 @@
20
20
  "vitest": "^4.1.9",
21
21
  "vue-tsc": "^2.2.8",
22
22
  "@n8n/eslint-config": "0.0.1",
23
- "@n8n/typescript-config": "1.10.0",
23
+ "@n8n/typescript-config": "1.11.0",
24
24
  "@n8n/vitest-config": "1.21.0"
25
25
  },
26
26
  "license": "SEE LICENSE IN LICENSE.md",
@@ -68,6 +68,25 @@ describe('commandRegistry', () => {
68
68
  expect(listener).toHaveBeenLastCalledWith([]);
69
69
  });
70
70
 
71
+ it('should give each subscriber its own array', () => {
72
+ const received: CommandBarEntry[][] = [];
73
+ commandRegistry.subscribe((commands) => {
74
+ commands.reverse();
75
+ received.push(commands);
76
+ });
77
+ commandRegistry.subscribe((commands) => {
78
+ received.push(commands);
79
+ });
80
+
81
+ commandRegistry.register(commandA);
82
+ commandRegistry.register(commandB);
83
+
84
+ const [firstMutated, secondUnaffected] = received.slice(-2);
85
+ expect(firstMutated).toEqual([commandB, commandA]);
86
+ expect(secondUnaffected).toEqual([commandA, commandB]);
87
+ expect(commandRegistry.getAll()).toEqual([commandA, commandB]);
88
+ });
89
+
71
90
  it('should return an unsubscribe function that stops notifications', () => {
72
91
  const listener = vi.fn();
73
92
  const unsubscribe = commandRegistry.subscribe(listener);
@@ -8,8 +8,8 @@ export function getAll(): CommandBarEntry[] {
8
8
  }
9
9
 
10
10
  function notifyListeners(): void {
11
- const snapshot = getAll();
12
- listeners.forEach((listener) => listener(snapshot));
11
+ // One array per listener: `sort`, `reverse` and `splice` mutate in place.
12
+ listeners.forEach((listener) => listener(getAll()));
13
13
  }
14
14
 
15
15
  export function register(command: CommandBarEntry): void {
@@ -42,7 +42,7 @@ export type FrontendModuleDescription = {
42
42
 
43
43
  /** Per-module i18n messages, merged into the active locale by the shell. */
44
44
  locales?: ModuleLocaleMessages;
45
- /** Push-message handlers, keyed by message type. */
45
+ /** Push-message handlers, keyed by message type. See `ModulePushHandlers`. */
46
46
  pushHandlers?: ModulePushHandlers;
47
47
  /** Command-bar contributions. */
48
48
  commands?: CommandBarEntry[];
package/src/types/push.ts CHANGED
@@ -21,6 +21,13 @@ export type ModulePushHandler<Ctx extends ModulePushHandlerContext = ModulePushH
21
21
  /**
22
22
  * A module's push-message contributions, keyed by message type. Each handler
23
23
  * receives the event already narrowed to its type.
24
+ *
25
+ * The shell dispatches these at app scope, on a listener of its own. The order
26
+ * against the built-in handling of the same type is not defined.
27
+ *
28
+ * **Contract:** a handler must not depend on the built-in handling of the same
29
+ * event. Registration makes the module the owner of a type, and the shell then
30
+ * skips its own handler for it.
24
31
  */
25
32
  export type ModulePushHandlers = {
26
33
  [T in PushType]?: (