@n8n/composables 1.23.0 → 1.24.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/dist/notification.d.cts +24 -0
- package/dist/notification.d.mts +24 -0
- package/dist/registries/telemetryRegistry.cjs +5 -0
- package/dist/registries/telemetryRegistry.d.cts +2 -0
- package/dist/registries/telemetryRegistry.d.mts +2 -0
- package/dist/registries/telemetryRegistry.mjs +3 -0
- package/dist/telemetryRegistry.cjs +42 -0
- package/dist/telemetryRegistry.cjs.map +1 -0
- package/dist/telemetryRegistry.d.cts +42 -0
- package/dist/telemetryRegistry.d.mts +42 -0
- package/dist/telemetryRegistry.mjs +24 -0
- package/dist/telemetryRegistry.mjs.map +1 -0
- package/dist/types/notification.cjs +0 -0
- package/dist/types/notification.d.cts +2 -0
- package/dist/types/notification.d.mts +2 -0
- package/dist/types/notification.mjs +1 -0
- package/dist/useDeviceSupport.d.cts +2 -2
- package/dist/useDeviceSupport.d.mts +2 -2
- package/dist/useStorage.cjs +13 -0
- package/dist/useStorage.cjs.map +1 -0
- package/dist/useStorage.d.cts +7 -0
- package/dist/useStorage.d.mts +7 -0
- package/dist/useStorage.mjs +12 -0
- package/dist/useStorage.mjs.map +1 -0
- package/dist/useTelemetry.cjs +1 -2
- package/dist/useTelemetry.d.cts +2 -37
- package/dist/useTelemetry.d.mts +2 -37
- package/dist/useTelemetry.mjs +3 -2
- package/dist/useTelemetry2.cjs +5 -31
- package/dist/useTelemetry2.cjs.map +1 -1
- package/dist/useTelemetry2.mjs +6 -20
- package/dist/useTelemetry2.mjs.map +1 -1
- package/dist/useToast.cjs +20 -25
- package/dist/useToast.cjs.map +1 -1
- package/dist/useToast.d.cts +3 -6
- package/dist/useToast.d.mts +3 -6
- package/dist/useToast.mjs +21 -26
- package/dist/useToast.mjs.map +1 -1
- package/package.json +9 -10
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Component, VNode } from "vue";
|
|
2
|
+
|
|
3
|
+
//#region src/types/notification.d.ts
|
|
4
|
+
type NotificationType = '' | 'success' | 'warning' | 'error' | 'info';
|
|
5
|
+
type NotificationPosition = 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';
|
|
6
|
+
interface NotificationOptions {
|
|
7
|
+
message: string | VNode;
|
|
8
|
+
title?: string;
|
|
9
|
+
type?: NotificationType;
|
|
10
|
+
icon?: string | Component;
|
|
11
|
+
customClass?: string;
|
|
12
|
+
duration?: number;
|
|
13
|
+
position?: NotificationPosition;
|
|
14
|
+
showClose?: boolean;
|
|
15
|
+
dangerouslyUseHTMLString?: boolean;
|
|
16
|
+
offset?: number;
|
|
17
|
+
appendTo?: HTMLElement | string;
|
|
18
|
+
zIndex?: number;
|
|
19
|
+
onClick?: () => void;
|
|
20
|
+
onClose?: () => void;
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { NotificationPosition as n, NotificationType as r, NotificationOptions as t };
|
|
24
|
+
//# sourceMappingURL=notification.d.cts.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Component, VNode } from "vue";
|
|
2
|
+
|
|
3
|
+
//#region src/types/notification.d.ts
|
|
4
|
+
type NotificationType = '' | 'success' | 'warning' | 'error' | 'info';
|
|
5
|
+
type NotificationPosition = 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';
|
|
6
|
+
interface NotificationOptions {
|
|
7
|
+
message: string | VNode;
|
|
8
|
+
title?: string;
|
|
9
|
+
type?: NotificationType;
|
|
10
|
+
icon?: string | Component;
|
|
11
|
+
customClass?: string;
|
|
12
|
+
duration?: number;
|
|
13
|
+
position?: NotificationPosition;
|
|
14
|
+
showClose?: boolean;
|
|
15
|
+
dangerouslyUseHTMLString?: boolean;
|
|
16
|
+
offset?: number;
|
|
17
|
+
appendTo?: HTMLElement | string;
|
|
18
|
+
zIndex?: number;
|
|
19
|
+
onClick?: () => void;
|
|
20
|
+
onClose?: () => void;
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { NotificationPosition as n, NotificationType as r, NotificationOptions as t };
|
|
24
|
+
//# sourceMappingURL=notification.d.mts.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
const require_telemetryRegistry = require('../telemetryRegistry.cjs');
|
|
2
|
+
|
|
3
|
+
exports.TelemetryKey = require_telemetryRegistry.TelemetryKey;
|
|
4
|
+
exports.getRegisteredTelemetry = require_telemetryRegistry.getRegisteredTelemetry;
|
|
5
|
+
exports.setTelemetry = require_telemetryRegistry.setTelemetry;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as getRegisteredTelemetry, i as TelemetryNodeParameterChange, n as TelemetryIdentifyOptions, o as setTelemetry, r as TelemetryKey, t as Telemetry } from "../telemetryRegistry.cjs";
|
|
2
|
+
export { Telemetry, TelemetryIdentifyOptions, TelemetryKey, TelemetryNodeParameterChange, getRegisteredTelemetry, setTelemetry };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as getRegisteredTelemetry, i as TelemetryNodeParameterChange, n as TelemetryIdentifyOptions, o as setTelemetry, r as TelemetryKey, t as Telemetry } from "../telemetryRegistry.mjs";
|
|
2
|
+
export { Telemetry, TelemetryIdentifyOptions, TelemetryKey, TelemetryNodeParameterChange, getRegisteredTelemetry, setTelemetry };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/registries/telemetryRegistry.ts
|
|
3
|
+
/**
|
|
4
|
+
* Injection key for the telemetry instance. The application provides it at
|
|
5
|
+
* bootstrap; components may override it (e.g. a pop-out window with its own
|
|
6
|
+
* instance). `useTelemetry` reads it when called inside an injection context.
|
|
7
|
+
*/
|
|
8
|
+
const TelemetryKey = Symbol("Telemetry");
|
|
9
|
+
let registeredTelemetry;
|
|
10
|
+
/**
|
|
11
|
+
* Register the application's telemetry instance. Called once at bootstrap by
|
|
12
|
+
* the editor-ui telemetry plugin so package-side `useTelemetry` can return it
|
|
13
|
+
* from any context, including outside of component setup.
|
|
14
|
+
*/
|
|
15
|
+
function setTelemetry(instance) {
|
|
16
|
+
registeredTelemetry = instance;
|
|
17
|
+
}
|
|
18
|
+
/** The instance registered via {@link setTelemetry}, if bootstrap has run. */
|
|
19
|
+
function getRegisteredTelemetry() {
|
|
20
|
+
return registeredTelemetry;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
Object.defineProperty(exports, 'TelemetryKey', {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () {
|
|
27
|
+
return TelemetryKey;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(exports, 'getRegisteredTelemetry', {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
get: function () {
|
|
33
|
+
return getRegisteredTelemetry;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
Object.defineProperty(exports, 'setTelemetry', {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
get: function () {
|
|
39
|
+
return setTelemetry;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
//# sourceMappingURL=telemetryRegistry.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetryRegistry.cjs","names":["TelemetryKey: InjectionKey<Telemetry>","registeredTelemetry: Telemetry | undefined"],"sources":["../src/registries/telemetryRegistry.ts"],"sourcesContent":["import type { ITelemetrySettings } from '@n8n/api-types';\nimport type { InferTelemetryProps, TelemetryEventDef } from '@n8n/telemetry';\nimport type { IDataObject, ITelemetryTrackProperties, NodeParameterValueType } from 'n8n-workflow';\nimport type { InjectionKey } from 'vue';\nimport type { RouteLocation } from 'vue-router';\n\nexport type TelemetryIdentifyOptions = {\n\tinstanceId: string;\n\tuserId?: string;\n\tprojectId?: string;\n\tversionCli?: string;\n\tuserRole?: string;\n};\n\n/**\n * Shape of a node-parameter change tracked by telemetry. Structurally mirrors\n * editor-ui's `IUpdateInformation`; declared here so the telemetry contract\n * carries no dependency back into the application package.\n */\nexport interface TelemetryNodeParameterChange {\n\tname: string;\n\tkey?: string;\n\tvalue: NodeParameterValueType;\n\tnode?: string;\n\toldValue?: string | number;\n\ttype?: 'optionsOrderChanged';\n}\n\n/**\n * The telemetry contract consumed across the frontend.\n *\n * This package owns the *type* only; the concrete implementation lives in the\n * application (`editor-ui`'s telemetry plugin) and is registered at bootstrap\n * via {@link setTelemetry} / provided through {@link TelemetryKey}. Keeping the\n * contract here lets `useTelemetry` return a fully-typed instance without the\n * package importing application code.\n */\nexport interface Telemetry {\n\tinit(\n\t\ttelemetrySettings: ITelemetrySettings,\n\t\toptions: TelemetryIdentifyOptions & { versionCli: string },\n\t): void;\n\tidentify(options: TelemetryIdentifyOptions): void;\n\ttrack<T extends TelemetryEventDef>(event: T, properties: InferTelemetryProps<T>): void;\n\ttrack(event: string, properties?: ITelemetryTrackProperties): void;\n\tpage(route: RouteLocation): void;\n\treset(): void;\n\tflushPageEvents(): void;\n\ttrackAskAI(event: string, ndvPushRef: string, properties?: IDataObject): void;\n\ttrackAiTransform(event: string, ndvPushRef: string, properties?: IDataObject): void;\n\ttrackNodeParametersValuesChange(nodeType: string, change: TelemetryNodeParameterChange): void;\n}\n\n/**\n * Injection key for the telemetry instance. The application provides it at\n * bootstrap; components may override it (e.g. a pop-out window with its own\n * instance). `useTelemetry` reads it when called inside an injection context.\n */\nexport const TelemetryKey: InjectionKey<Telemetry> = Symbol('Telemetry');\n\nlet registeredTelemetry: Telemetry | undefined;\n\n/**\n * Register the application's telemetry instance. Called once at bootstrap by\n * the editor-ui telemetry plugin so package-side `useTelemetry` can return it\n * from any context, including outside of component setup.\n */\nexport function setTelemetry(instance: Telemetry | undefined): void {\n\tregisteredTelemetry = instance;\n}\n\n/** The instance registered via {@link setTelemetry}, if bootstrap has run. */\nexport function getRegisteredTelemetry(): Telemetry | undefined {\n\treturn registeredTelemetry;\n}\n"],"mappings":";;;;;;;AA0DA,MAAaA,eAAwC,OAAO,YAAY;AAExE,IAAIC;;;;;;AAOJ,SAAgB,aAAa,UAAuC;AACnE,uBAAsB;;;AAIvB,SAAgB,yBAAgD;AAC/D,QAAO"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { InjectionKey } from "vue";
|
|
2
|
+
import { ITelemetrySettings } from "@n8n/api-types";
|
|
3
|
+
import { InferTelemetryProps, TelemetryEventDef } from "@n8n/telemetry";
|
|
4
|
+
import { IDataObject, ITelemetryTrackProperties, NodeParameterValueType } from "n8n-workflow";
|
|
5
|
+
import { RouteLocation } from "vue-router";
|
|
6
|
+
|
|
7
|
+
//#region src/registries/telemetryRegistry.d.ts
|
|
8
|
+
type TelemetryIdentifyOptions = {
|
|
9
|
+
instanceId: string;
|
|
10
|
+
userId?: string;
|
|
11
|
+
projectId?: string;
|
|
12
|
+
versionCli?: string;
|
|
13
|
+
userRole?: string;
|
|
14
|
+
};
|
|
15
|
+
interface TelemetryNodeParameterChange {
|
|
16
|
+
name: string;
|
|
17
|
+
key?: string;
|
|
18
|
+
value: NodeParameterValueType;
|
|
19
|
+
node?: string;
|
|
20
|
+
oldValue?: string | number;
|
|
21
|
+
type?: 'optionsOrderChanged';
|
|
22
|
+
}
|
|
23
|
+
interface Telemetry {
|
|
24
|
+
init(telemetrySettings: ITelemetrySettings, options: TelemetryIdentifyOptions & {
|
|
25
|
+
versionCli: string;
|
|
26
|
+
}): void;
|
|
27
|
+
identify(options: TelemetryIdentifyOptions): void;
|
|
28
|
+
track<T extends TelemetryEventDef>(event: T, properties: InferTelemetryProps<T>): void;
|
|
29
|
+
track(event: string, properties?: ITelemetryTrackProperties): void;
|
|
30
|
+
page(route: RouteLocation): void;
|
|
31
|
+
reset(): void;
|
|
32
|
+
flushPageEvents(): void;
|
|
33
|
+
trackAskAI(event: string, ndvPushRef: string, properties?: IDataObject): void;
|
|
34
|
+
trackAiTransform(event: string, ndvPushRef: string, properties?: IDataObject): void;
|
|
35
|
+
trackNodeParametersValuesChange(nodeType: string, change: TelemetryNodeParameterChange): void;
|
|
36
|
+
}
|
|
37
|
+
declare const TelemetryKey: InjectionKey<Telemetry>;
|
|
38
|
+
declare function setTelemetry(instance: Telemetry | undefined): void;
|
|
39
|
+
declare function getRegisteredTelemetry(): Telemetry | undefined;
|
|
40
|
+
//#endregion
|
|
41
|
+
export { getRegisteredTelemetry as a, TelemetryNodeParameterChange as i, TelemetryIdentifyOptions as n, setTelemetry as o, TelemetryKey as r, Telemetry as t };
|
|
42
|
+
//# sourceMappingURL=telemetryRegistry.d.cts.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { InjectionKey } from "vue";
|
|
2
|
+
import { RouteLocation } from "vue-router";
|
|
3
|
+
import { ITelemetrySettings } from "@n8n/api-types";
|
|
4
|
+
import { InferTelemetryProps, TelemetryEventDef } from "@n8n/telemetry";
|
|
5
|
+
import { IDataObject, ITelemetryTrackProperties, NodeParameterValueType } from "n8n-workflow";
|
|
6
|
+
|
|
7
|
+
//#region src/registries/telemetryRegistry.d.ts
|
|
8
|
+
type TelemetryIdentifyOptions = {
|
|
9
|
+
instanceId: string;
|
|
10
|
+
userId?: string;
|
|
11
|
+
projectId?: string;
|
|
12
|
+
versionCli?: string;
|
|
13
|
+
userRole?: string;
|
|
14
|
+
};
|
|
15
|
+
interface TelemetryNodeParameterChange {
|
|
16
|
+
name: string;
|
|
17
|
+
key?: string;
|
|
18
|
+
value: NodeParameterValueType;
|
|
19
|
+
node?: string;
|
|
20
|
+
oldValue?: string | number;
|
|
21
|
+
type?: 'optionsOrderChanged';
|
|
22
|
+
}
|
|
23
|
+
interface Telemetry {
|
|
24
|
+
init(telemetrySettings: ITelemetrySettings, options: TelemetryIdentifyOptions & {
|
|
25
|
+
versionCli: string;
|
|
26
|
+
}): void;
|
|
27
|
+
identify(options: TelemetryIdentifyOptions): void;
|
|
28
|
+
track<T extends TelemetryEventDef>(event: T, properties: InferTelemetryProps<T>): void;
|
|
29
|
+
track(event: string, properties?: ITelemetryTrackProperties): void;
|
|
30
|
+
page(route: RouteLocation): void;
|
|
31
|
+
reset(): void;
|
|
32
|
+
flushPageEvents(): void;
|
|
33
|
+
trackAskAI(event: string, ndvPushRef: string, properties?: IDataObject): void;
|
|
34
|
+
trackAiTransform(event: string, ndvPushRef: string, properties?: IDataObject): void;
|
|
35
|
+
trackNodeParametersValuesChange(nodeType: string, change: TelemetryNodeParameterChange): void;
|
|
36
|
+
}
|
|
37
|
+
declare const TelemetryKey: InjectionKey<Telemetry>;
|
|
38
|
+
declare function setTelemetry(instance: Telemetry | undefined): void;
|
|
39
|
+
declare function getRegisteredTelemetry(): Telemetry | undefined;
|
|
40
|
+
//#endregion
|
|
41
|
+
export { getRegisteredTelemetry as a, TelemetryNodeParameterChange as i, TelemetryIdentifyOptions as n, setTelemetry as o, TelemetryKey as r, Telemetry as t };
|
|
42
|
+
//# sourceMappingURL=telemetryRegistry.d.mts.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//#region src/registries/telemetryRegistry.ts
|
|
2
|
+
/**
|
|
3
|
+
* Injection key for the telemetry instance. The application provides it at
|
|
4
|
+
* bootstrap; components may override it (e.g. a pop-out window with its own
|
|
5
|
+
* instance). `useTelemetry` reads it when called inside an injection context.
|
|
6
|
+
*/
|
|
7
|
+
const TelemetryKey = Symbol("Telemetry");
|
|
8
|
+
let registeredTelemetry;
|
|
9
|
+
/**
|
|
10
|
+
* Register the application's telemetry instance. Called once at bootstrap by
|
|
11
|
+
* the editor-ui telemetry plugin so package-side `useTelemetry` can return it
|
|
12
|
+
* from any context, including outside of component setup.
|
|
13
|
+
*/
|
|
14
|
+
function setTelemetry(instance) {
|
|
15
|
+
registeredTelemetry = instance;
|
|
16
|
+
}
|
|
17
|
+
/** The instance registered via {@link setTelemetry}, if bootstrap has run. */
|
|
18
|
+
function getRegisteredTelemetry() {
|
|
19
|
+
return registeredTelemetry;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
//#endregion
|
|
23
|
+
export { getRegisteredTelemetry as n, setTelemetry as r, TelemetryKey as t };
|
|
24
|
+
//# sourceMappingURL=telemetryRegistry.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetryRegistry.mjs","names":["TelemetryKey: InjectionKey<Telemetry>","registeredTelemetry: Telemetry | undefined"],"sources":["../src/registries/telemetryRegistry.ts"],"sourcesContent":["import type { ITelemetrySettings } from '@n8n/api-types';\nimport type { InferTelemetryProps, TelemetryEventDef } from '@n8n/telemetry';\nimport type { IDataObject, ITelemetryTrackProperties, NodeParameterValueType } from 'n8n-workflow';\nimport type { InjectionKey } from 'vue';\nimport type { RouteLocation } from 'vue-router';\n\nexport type TelemetryIdentifyOptions = {\n\tinstanceId: string;\n\tuserId?: string;\n\tprojectId?: string;\n\tversionCli?: string;\n\tuserRole?: string;\n};\n\n/**\n * Shape of a node-parameter change tracked by telemetry. Structurally mirrors\n * editor-ui's `IUpdateInformation`; declared here so the telemetry contract\n * carries no dependency back into the application package.\n */\nexport interface TelemetryNodeParameterChange {\n\tname: string;\n\tkey?: string;\n\tvalue: NodeParameterValueType;\n\tnode?: string;\n\toldValue?: string | number;\n\ttype?: 'optionsOrderChanged';\n}\n\n/**\n * The telemetry contract consumed across the frontend.\n *\n * This package owns the *type* only; the concrete implementation lives in the\n * application (`editor-ui`'s telemetry plugin) and is registered at bootstrap\n * via {@link setTelemetry} / provided through {@link TelemetryKey}. Keeping the\n * contract here lets `useTelemetry` return a fully-typed instance without the\n * package importing application code.\n */\nexport interface Telemetry {\n\tinit(\n\t\ttelemetrySettings: ITelemetrySettings,\n\t\toptions: TelemetryIdentifyOptions & { versionCli: string },\n\t): void;\n\tidentify(options: TelemetryIdentifyOptions): void;\n\ttrack<T extends TelemetryEventDef>(event: T, properties: InferTelemetryProps<T>): void;\n\ttrack(event: string, properties?: ITelemetryTrackProperties): void;\n\tpage(route: RouteLocation): void;\n\treset(): void;\n\tflushPageEvents(): void;\n\ttrackAskAI(event: string, ndvPushRef: string, properties?: IDataObject): void;\n\ttrackAiTransform(event: string, ndvPushRef: string, properties?: IDataObject): void;\n\ttrackNodeParametersValuesChange(nodeType: string, change: TelemetryNodeParameterChange): void;\n}\n\n/**\n * Injection key for the telemetry instance. The application provides it at\n * bootstrap; components may override it (e.g. a pop-out window with its own\n * instance). `useTelemetry` reads it when called inside an injection context.\n */\nexport const TelemetryKey: InjectionKey<Telemetry> = Symbol('Telemetry');\n\nlet registeredTelemetry: Telemetry | undefined;\n\n/**\n * Register the application's telemetry instance. Called once at bootstrap by\n * the editor-ui telemetry plugin so package-side `useTelemetry` can return it\n * from any context, including outside of component setup.\n */\nexport function setTelemetry(instance: Telemetry | undefined): void {\n\tregisteredTelemetry = instance;\n}\n\n/** The instance registered via {@link setTelemetry}, if bootstrap has run. */\nexport function getRegisteredTelemetry(): Telemetry | undefined {\n\treturn registeredTelemetry;\n}\n"],"mappings":";;;;;;AA0DA,MAAaA,eAAwC,OAAO,YAAY;AAExE,IAAIC;;;;;;AAOJ,SAAgB,aAAa,UAAuC;AACnE,uBAAsB;;;AAIvB,SAAgB,yBAAgD;AAC/D,QAAO"}
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as vue0 from "vue";
|
|
2
2
|
|
|
3
3
|
//#region src/useDeviceSupport.d.ts
|
|
4
4
|
declare function useDeviceSupport(): {
|
|
@@ -9,7 +9,7 @@ declare function useDeviceSupport(): {
|
|
|
9
9
|
isMacOs: boolean;
|
|
10
10
|
isMobileDevice: boolean;
|
|
11
11
|
controlKeyCode: string;
|
|
12
|
-
controlKeyText:
|
|
12
|
+
controlKeyText: vue0.ComputedRef<"⌘" | "Ctrl">;
|
|
13
13
|
isCtrlKeyPressed: (e: MouseEvent | KeyboardEvent) => boolean;
|
|
14
14
|
};
|
|
15
15
|
//#endregion
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as vue3 from "vue";
|
|
2
2
|
|
|
3
3
|
//#region src/useDeviceSupport.d.ts
|
|
4
4
|
declare function useDeviceSupport(): {
|
|
@@ -9,7 +9,7 @@ declare function useDeviceSupport(): {
|
|
|
9
9
|
isMacOs: boolean;
|
|
10
10
|
isMobileDevice: boolean;
|
|
11
11
|
controlKeyCode: string;
|
|
12
|
-
controlKeyText:
|
|
12
|
+
controlKeyText: vue3.ComputedRef<"⌘" | "Ctrl">;
|
|
13
13
|
isCtrlKeyPressed: (e: MouseEvent | KeyboardEvent) => boolean;
|
|
14
14
|
};
|
|
15
15
|
//#endregion
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const require_useDebounce = require('./useDebounce.cjs');
|
|
2
|
+
let __vueuse_core = require("@vueuse/core");
|
|
3
|
+
|
|
4
|
+
//#region src/useStorage.ts
|
|
5
|
+
function useStorage(key) {
|
|
6
|
+
const data = (0, __vueuse_core.useStorage)(key, null, void 0, { writeDefaults: false });
|
|
7
|
+
if (data.value === "undefined") data.value = null;
|
|
8
|
+
return data;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
//#endregion
|
|
12
|
+
exports.useStorage = useStorage;
|
|
13
|
+
//# sourceMappingURL=useStorage.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useStorage.cjs","names":[],"sources":["../src/useStorage.ts"],"sourcesContent":["import { useStorage as useStorageComposable } from '@vueuse/core';\nimport type { Ref } from 'vue';\n\nexport function useStorage(key: string): Ref<string | null> {\n\tconst data = useStorageComposable(key, null, undefined, { writeDefaults: false });\n\n\t// bug in 1.15.1\n\tif (data.value === 'undefined') {\n\t\tdata.value = null;\n\t}\n\n\treturn data;\n}\n"],"mappings":";;;;AAGA,SAAgB,WAAW,KAAiC;CAC3D,MAAM,qCAA4B,KAAK,MAAM,QAAW,EAAE,eAAe,OAAO,CAAC;AAGjF,KAAI,KAAK,UAAU,YAClB,MAAK,QAAQ;AAGd,QAAO"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { useStorage as useStorage$1 } from "@vueuse/core";
|
|
2
|
+
|
|
3
|
+
//#region src/useStorage.ts
|
|
4
|
+
function useStorage(key) {
|
|
5
|
+
const data = useStorage$1(key, null, void 0, { writeDefaults: false });
|
|
6
|
+
if (data.value === "undefined") data.value = null;
|
|
7
|
+
return data;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
//#endregion
|
|
11
|
+
export { useStorage };
|
|
12
|
+
//# sourceMappingURL=useStorage.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useStorage.mjs","names":["useStorageComposable"],"sources":["../src/useStorage.ts"],"sourcesContent":["import { useStorage as useStorageComposable } from '@vueuse/core';\nimport type { Ref } from 'vue';\n\nexport function useStorage(key: string): Ref<string | null> {\n\tconst data = useStorageComposable(key, null, undefined, { writeDefaults: false });\n\n\t// bug in 1.15.1\n\tif (data.value === 'undefined') {\n\t\tdata.value = null;\n\t}\n\n\treturn data;\n}\n"],"mappings":";;;AAGA,SAAgB,WAAW,KAAiC;CAC3D,MAAM,OAAOA,aAAqB,KAAK,MAAM,QAAW,EAAE,eAAe,OAAO,CAAC;AAGjF,KAAI,KAAK,UAAU,YAClB,MAAK,QAAQ;AAGd,QAAO"}
|
package/dist/useTelemetry.cjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
+
require('./telemetryRegistry.cjs');
|
|
1
2
|
const require_useTelemetry = require('./useTelemetry2.cjs');
|
|
2
3
|
|
|
3
|
-
exports.TelemetryKey = require_useTelemetry.TelemetryKey;
|
|
4
|
-
exports.setTelemetry = require_useTelemetry.setTelemetry;
|
|
5
4
|
exports.useTelemetry = require_useTelemetry.useTelemetry;
|
package/dist/useTelemetry.d.cts
CHANGED
|
@@ -1,42 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ITelemetrySettings } from "@n8n/api-types";
|
|
3
|
-
import { InferTelemetryProps, TelemetryEventDef } from "@n8n/telemetry";
|
|
4
|
-
import { IDataObject, ITelemetryTrackProperties, NodeParameterValueType } from "n8n-workflow";
|
|
5
|
-
import { RouteLocation } from "vue-router";
|
|
1
|
+
import { i as TelemetryNodeParameterChange, n as TelemetryIdentifyOptions, t as Telemetry } from "./telemetryRegistry.cjs";
|
|
6
2
|
|
|
7
3
|
//#region src/useTelemetry.d.ts
|
|
8
|
-
type TelemetryIdentifyOptions = {
|
|
9
|
-
instanceId: string;
|
|
10
|
-
userId?: string;
|
|
11
|
-
projectId?: string;
|
|
12
|
-
versionCli?: string;
|
|
13
|
-
userRole?: string;
|
|
14
|
-
};
|
|
15
|
-
interface TelemetryNodeParameterChange {
|
|
16
|
-
name: string;
|
|
17
|
-
key?: string;
|
|
18
|
-
value: NodeParameterValueType;
|
|
19
|
-
node?: string;
|
|
20
|
-
oldValue?: string | number;
|
|
21
|
-
type?: 'optionsOrderChanged';
|
|
22
|
-
}
|
|
23
|
-
interface Telemetry {
|
|
24
|
-
init(telemetrySettings: ITelemetrySettings, options: TelemetryIdentifyOptions & {
|
|
25
|
-
versionCli: string;
|
|
26
|
-
}): void;
|
|
27
|
-
identify(options: TelemetryIdentifyOptions): void;
|
|
28
|
-
track<T extends TelemetryEventDef>(event: T, properties: InferTelemetryProps<T>): void;
|
|
29
|
-
track(event: string, properties?: ITelemetryTrackProperties): void;
|
|
30
|
-
page(route: RouteLocation): void;
|
|
31
|
-
reset(): void;
|
|
32
|
-
flushPageEvents(): void;
|
|
33
|
-
trackAskAI(event: string, ndvPushRef: string, properties?: IDataObject): void;
|
|
34
|
-
trackAiTransform(event: string, ndvPushRef: string, properties?: IDataObject): void;
|
|
35
|
-
trackNodeParametersValuesChange(nodeType: string, change: TelemetryNodeParameterChange): void;
|
|
36
|
-
}
|
|
37
|
-
declare const TelemetryKey: InjectionKey<Telemetry>;
|
|
38
|
-
declare function setTelemetry(instance: Telemetry | undefined): void;
|
|
39
4
|
declare function useTelemetry(): Telemetry;
|
|
40
5
|
//#endregion
|
|
41
|
-
export { Telemetry, TelemetryIdentifyOptions,
|
|
6
|
+
export { type Telemetry, type TelemetryIdentifyOptions, type TelemetryNodeParameterChange, useTelemetry };
|
|
42
7
|
//# sourceMappingURL=useTelemetry.d.cts.map
|
package/dist/useTelemetry.d.mts
CHANGED
|
@@ -1,42 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { RouteLocation } from "vue-router";
|
|
3
|
-
import { ITelemetrySettings } from "@n8n/api-types";
|
|
4
|
-
import { InferTelemetryProps, TelemetryEventDef } from "@n8n/telemetry";
|
|
5
|
-
import { IDataObject, ITelemetryTrackProperties, NodeParameterValueType } from "n8n-workflow";
|
|
1
|
+
import { i as TelemetryNodeParameterChange, n as TelemetryIdentifyOptions, t as Telemetry } from "./telemetryRegistry.mjs";
|
|
6
2
|
|
|
7
3
|
//#region src/useTelemetry.d.ts
|
|
8
|
-
type TelemetryIdentifyOptions = {
|
|
9
|
-
instanceId: string;
|
|
10
|
-
userId?: string;
|
|
11
|
-
projectId?: string;
|
|
12
|
-
versionCli?: string;
|
|
13
|
-
userRole?: string;
|
|
14
|
-
};
|
|
15
|
-
interface TelemetryNodeParameterChange {
|
|
16
|
-
name: string;
|
|
17
|
-
key?: string;
|
|
18
|
-
value: NodeParameterValueType;
|
|
19
|
-
node?: string;
|
|
20
|
-
oldValue?: string | number;
|
|
21
|
-
type?: 'optionsOrderChanged';
|
|
22
|
-
}
|
|
23
|
-
interface Telemetry {
|
|
24
|
-
init(telemetrySettings: ITelemetrySettings, options: TelemetryIdentifyOptions & {
|
|
25
|
-
versionCli: string;
|
|
26
|
-
}): void;
|
|
27
|
-
identify(options: TelemetryIdentifyOptions): void;
|
|
28
|
-
track<T extends TelemetryEventDef>(event: T, properties: InferTelemetryProps<T>): void;
|
|
29
|
-
track(event: string, properties?: ITelemetryTrackProperties): void;
|
|
30
|
-
page(route: RouteLocation): void;
|
|
31
|
-
reset(): void;
|
|
32
|
-
flushPageEvents(): void;
|
|
33
|
-
trackAskAI(event: string, ndvPushRef: string, properties?: IDataObject): void;
|
|
34
|
-
trackAiTransform(event: string, ndvPushRef: string, properties?: IDataObject): void;
|
|
35
|
-
trackNodeParametersValuesChange(nodeType: string, change: TelemetryNodeParameterChange): void;
|
|
36
|
-
}
|
|
37
|
-
declare const TelemetryKey: InjectionKey<Telemetry>;
|
|
38
|
-
declare function setTelemetry(instance: Telemetry | undefined): void;
|
|
39
4
|
declare function useTelemetry(): Telemetry;
|
|
40
5
|
//#endregion
|
|
41
|
-
export { Telemetry, TelemetryIdentifyOptions,
|
|
6
|
+
export { type Telemetry, type TelemetryIdentifyOptions, type TelemetryNodeParameterChange, useTelemetry };
|
|
42
7
|
//# sourceMappingURL=useTelemetry.d.mts.map
|
package/dist/useTelemetry.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "./telemetryRegistry.mjs";
|
|
2
|
+
import { t as useTelemetry } from "./useTelemetry2.mjs";
|
|
2
3
|
|
|
3
|
-
export {
|
|
4
|
+
export { useTelemetry };
|
package/dist/useTelemetry2.cjs
CHANGED
|
@@ -1,18 +1,13 @@
|
|
|
1
1
|
const require_useDebounce = require('./useDebounce.cjs');
|
|
2
|
+
const require_telemetryRegistry = require('./telemetryRegistry.cjs');
|
|
2
3
|
let vue = require("vue");
|
|
3
4
|
|
|
4
5
|
//#region src/useTelemetry.ts
|
|
5
6
|
/**
|
|
6
|
-
* Injection key for the telemetry instance. The application provides it at
|
|
7
|
-
* bootstrap; components may override it (e.g. a pop-out window with its own
|
|
8
|
-
* instance). `useTelemetry` reads it when called inside an injection context.
|
|
9
|
-
*/
|
|
10
|
-
const TelemetryKey = Symbol("Telemetry");
|
|
11
|
-
/**
|
|
12
7
|
* Null-object telemetry used when no instance has been registered (e.g. in
|
|
13
8
|
* tests that never install the plugin). Telemetry is best-effort and must never
|
|
14
9
|
* throw or break the UI, so every method is a no-op. Any registered instance
|
|
15
|
-
* (via
|
|
10
|
+
* (via `setTelemetry` or `TelemetryKey`) takes precedence.
|
|
16
11
|
*
|
|
17
12
|
* A plain object literal (not a `Proxy`) so method identity is stable, spies
|
|
18
13
|
* attach, `'track' in noopTelemetry` holds, and there is no accidental `then`
|
|
@@ -29,23 +24,14 @@ const noopTelemetry = {
|
|
|
29
24
|
trackAiTransform() {},
|
|
30
25
|
trackNodeParametersValuesChange() {}
|
|
31
26
|
};
|
|
32
|
-
let registeredTelemetry;
|
|
33
27
|
let warnedAboutMissingTelemetry = false;
|
|
34
28
|
/**
|
|
35
|
-
* Register the application's telemetry instance. Called once at bootstrap by
|
|
36
|
-
* the editor-ui telemetry plugin so package-side `useTelemetry` can return it
|
|
37
|
-
* from any context, including outside of component setup.
|
|
38
|
-
*/
|
|
39
|
-
function setTelemetry(instance) {
|
|
40
|
-
registeredTelemetry = instance;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
29
|
* Returns the active telemetry instance. Resolution order: a component-provided
|
|
44
|
-
* instance (via
|
|
45
|
-
*
|
|
30
|
+
* instance (via `TelemetryKey`), then the app-registered singleton (via
|
|
31
|
+
* `setTelemetry`), then a no-op fallback.
|
|
46
32
|
*/
|
|
47
33
|
function useTelemetry() {
|
|
48
|
-
const instance = ((0, vue.hasInjectionContext)() ? (0, vue.inject)(TelemetryKey, null) : null) ??
|
|
34
|
+
const instance = ((0, vue.hasInjectionContext)() ? (0, vue.inject)(require_telemetryRegistry.TelemetryKey, null) : null) ?? require_telemetryRegistry.getRegisteredTelemetry();
|
|
49
35
|
if (instance) return instance;
|
|
50
36
|
if ({}.env.DEV && !warnedAboutMissingTelemetry) {
|
|
51
37
|
warnedAboutMissingTelemetry = true;
|
|
@@ -55,18 +41,6 @@ function useTelemetry() {
|
|
|
55
41
|
}
|
|
56
42
|
|
|
57
43
|
//#endregion
|
|
58
|
-
Object.defineProperty(exports, 'TelemetryKey', {
|
|
59
|
-
enumerable: true,
|
|
60
|
-
get: function () {
|
|
61
|
-
return TelemetryKey;
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
Object.defineProperty(exports, 'setTelemetry', {
|
|
65
|
-
enumerable: true,
|
|
66
|
-
get: function () {
|
|
67
|
-
return setTelemetry;
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
44
|
Object.defineProperty(exports, 'useTelemetry', {
|
|
71
45
|
enumerable: true,
|
|
72
46
|
get: function () {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTelemetry2.cjs","names":["
|
|
1
|
+
{"version":3,"file":"useTelemetry2.cjs","names":["noopTelemetry: Telemetry","TelemetryKey","getRegisteredTelemetry"],"sources":["../src/useTelemetry.ts"],"sourcesContent":["import { hasInjectionContext, inject } from 'vue';\n\nimport {\n\tgetRegisteredTelemetry,\n\tTelemetryKey,\n\ttype Telemetry,\n} from './registries/telemetryRegistry';\n\n// The telemetry *contract* and the *registration* surface deliberately live in\n// `./registries/telemetryRegistry`: this module is `vi.mock`ed in ~100 test\n// files, and a mock factory replaces the whole module. While `setTelemetry`\n// lived here, any partial factory (the common `{ useTelemetry: () => ... }`\n// shape) also starved the telemetry plugin's own bootstrap import of it.\n// Separate modules make that unreachable — the plugin never imports this one.\nexport type {\n\tTelemetry,\n\tTelemetryIdentifyOptions,\n\tTelemetryNodeParameterChange,\n} from './registries/telemetryRegistry';\n\n/**\n * Null-object telemetry used when no instance has been registered (e.g. in\n * tests that never install the plugin). Telemetry is best-effort and must never\n * throw or break the UI, so every method is a no-op. Any registered instance\n * (via `setTelemetry` or `TelemetryKey`) takes precedence.\n *\n * A plain object literal (not a `Proxy`) so method identity is stable, spies\n * attach, `'track' in noopTelemetry` holds, and there is no accidental `then`\n * that would make `await useTelemetry()` hang.\n */\nconst noopTelemetry: Telemetry = {\n\tinit() {},\n\tidentify() {},\n\ttrack() {},\n\tpage() {},\n\treset() {},\n\tflushPageEvents() {},\n\ttrackAskAI() {},\n\ttrackAiTransform() {},\n\ttrackNodeParametersValuesChange() {},\n};\n\nlet warnedAboutMissingTelemetry = false;\n\n/**\n * Returns the active telemetry instance. Resolution order: a component-provided\n * instance (via `TelemetryKey`), then the app-registered singleton (via\n * `setTelemetry`), then a no-op fallback.\n */\nexport function useTelemetry(): Telemetry {\n\tconst injected = hasInjectionContext() ? inject(TelemetryKey, null) : null;\n\tconst instance = injected ?? getRegisteredTelemetry();\n\tif (instance) return instance;\n\n\t// Falling back to the no-op means the plugin has not registered an instance\n\t// yet. That should never happen in the app (bootstrap registers before any\n\t// consumer runs); warn once in dev so an ordering regression stays visible.\n\tif (import.meta.env.DEV && !warnedAboutMissingTelemetry) {\n\t\twarnedAboutMissingTelemetry = true;\n\t\tconsole.warn(\n\t\t\t'[useTelemetry] No telemetry instance registered; using a no-op. Ensure the telemetry plugin is installed at bootstrap.',\n\t\t);\n\t}\n\treturn noopTelemetry;\n}\n"],"mappings":";;;;;;;;;;;;;;;AA8BA,MAAMA,gBAA2B;CAChC,OAAO;CACP,WAAW;CACX,QAAQ;CACR,OAAO;CACP,QAAQ;CACR,kBAAkB;CAClB,aAAa;CACb,mBAAmB;CACnB,kCAAkC;CAClC;AAED,IAAI,8BAA8B;;;;;;AAOlC,SAAgB,eAA0B;CAEzC,MAAM,0CADgC,mBAAUC,wCAAc,KAAK,GAAG,SACzCC,kDAAwB;AACrD,KAAI,SAAU,QAAO;AAKrB,QAAgB,IAAI,OAAO,CAAC,6BAA6B;AACxD,gCAA8B;AAC9B,UAAQ,KACP,yHACA;;AAEF,QAAO"}
|
package/dist/useTelemetry2.mjs
CHANGED
|
@@ -1,17 +1,12 @@
|
|
|
1
|
+
import { n as getRegisteredTelemetry, t as TelemetryKey } from "./telemetryRegistry.mjs";
|
|
1
2
|
import { hasInjectionContext, inject } from "vue";
|
|
2
3
|
|
|
3
4
|
//#region src/useTelemetry.ts
|
|
4
5
|
/**
|
|
5
|
-
* Injection key for the telemetry instance. The application provides it at
|
|
6
|
-
* bootstrap; components may override it (e.g. a pop-out window with its own
|
|
7
|
-
* instance). `useTelemetry` reads it when called inside an injection context.
|
|
8
|
-
*/
|
|
9
|
-
const TelemetryKey = Symbol("Telemetry");
|
|
10
|
-
/**
|
|
11
6
|
* Null-object telemetry used when no instance has been registered (e.g. in
|
|
12
7
|
* tests that never install the plugin). Telemetry is best-effort and must never
|
|
13
8
|
* throw or break the UI, so every method is a no-op. Any registered instance
|
|
14
|
-
* (via
|
|
9
|
+
* (via `setTelemetry` or `TelemetryKey`) takes precedence.
|
|
15
10
|
*
|
|
16
11
|
* A plain object literal (not a `Proxy`) so method identity is stable, spies
|
|
17
12
|
* attach, `'track' in noopTelemetry` holds, and there is no accidental `then`
|
|
@@ -28,23 +23,14 @@ const noopTelemetry = {
|
|
|
28
23
|
trackAiTransform() {},
|
|
29
24
|
trackNodeParametersValuesChange() {}
|
|
30
25
|
};
|
|
31
|
-
let registeredTelemetry;
|
|
32
26
|
let warnedAboutMissingTelemetry = false;
|
|
33
27
|
/**
|
|
34
|
-
* Register the application's telemetry instance. Called once at bootstrap by
|
|
35
|
-
* the editor-ui telemetry plugin so package-side `useTelemetry` can return it
|
|
36
|
-
* from any context, including outside of component setup.
|
|
37
|
-
*/
|
|
38
|
-
function setTelemetry(instance) {
|
|
39
|
-
registeredTelemetry = instance;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
28
|
* Returns the active telemetry instance. Resolution order: a component-provided
|
|
43
|
-
* instance (via
|
|
44
|
-
*
|
|
29
|
+
* instance (via `TelemetryKey`), then the app-registered singleton (via
|
|
30
|
+
* `setTelemetry`), then a no-op fallback.
|
|
45
31
|
*/
|
|
46
32
|
function useTelemetry() {
|
|
47
|
-
const instance = (hasInjectionContext() ? inject(TelemetryKey, null) : null) ??
|
|
33
|
+
const instance = (hasInjectionContext() ? inject(TelemetryKey, null) : null) ?? getRegisteredTelemetry();
|
|
48
34
|
if (instance) return instance;
|
|
49
35
|
if (import.meta.env.DEV && !warnedAboutMissingTelemetry) {
|
|
50
36
|
warnedAboutMissingTelemetry = true;
|
|
@@ -54,5 +40,5 @@ function useTelemetry() {
|
|
|
54
40
|
}
|
|
55
41
|
|
|
56
42
|
//#endregion
|
|
57
|
-
export {
|
|
43
|
+
export { useTelemetry as t };
|
|
58
44
|
//# sourceMappingURL=useTelemetry2.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTelemetry2.mjs","names":["
|
|
1
|
+
{"version":3,"file":"useTelemetry2.mjs","names":["noopTelemetry: Telemetry"],"sources":["../src/useTelemetry.ts"],"sourcesContent":["import { hasInjectionContext, inject } from 'vue';\n\nimport {\n\tgetRegisteredTelemetry,\n\tTelemetryKey,\n\ttype Telemetry,\n} from './registries/telemetryRegistry';\n\n// The telemetry *contract* and the *registration* surface deliberately live in\n// `./registries/telemetryRegistry`: this module is `vi.mock`ed in ~100 test\n// files, and a mock factory replaces the whole module. While `setTelemetry`\n// lived here, any partial factory (the common `{ useTelemetry: () => ... }`\n// shape) also starved the telemetry plugin's own bootstrap import of it.\n// Separate modules make that unreachable — the plugin never imports this one.\nexport type {\n\tTelemetry,\n\tTelemetryIdentifyOptions,\n\tTelemetryNodeParameterChange,\n} from './registries/telemetryRegistry';\n\n/**\n * Null-object telemetry used when no instance has been registered (e.g. in\n * tests that never install the plugin). Telemetry is best-effort and must never\n * throw or break the UI, so every method is a no-op. Any registered instance\n * (via `setTelemetry` or `TelemetryKey`) takes precedence.\n *\n * A plain object literal (not a `Proxy`) so method identity is stable, spies\n * attach, `'track' in noopTelemetry` holds, and there is no accidental `then`\n * that would make `await useTelemetry()` hang.\n */\nconst noopTelemetry: Telemetry = {\n\tinit() {},\n\tidentify() {},\n\ttrack() {},\n\tpage() {},\n\treset() {},\n\tflushPageEvents() {},\n\ttrackAskAI() {},\n\ttrackAiTransform() {},\n\ttrackNodeParametersValuesChange() {},\n};\n\nlet warnedAboutMissingTelemetry = false;\n\n/**\n * Returns the active telemetry instance. Resolution order: a component-provided\n * instance (via `TelemetryKey`), then the app-registered singleton (via\n * `setTelemetry`), then a no-op fallback.\n */\nexport function useTelemetry(): Telemetry {\n\tconst injected = hasInjectionContext() ? inject(TelemetryKey, null) : null;\n\tconst instance = injected ?? getRegisteredTelemetry();\n\tif (instance) return instance;\n\n\t// Falling back to the no-op means the plugin has not registered an instance\n\t// yet. That should never happen in the app (bootstrap registers before any\n\t// consumer runs); warn once in dev so an ordering regression stays visible.\n\tif (import.meta.env.DEV && !warnedAboutMissingTelemetry) {\n\t\twarnedAboutMissingTelemetry = true;\n\t\tconsole.warn(\n\t\t\t'[useTelemetry] No telemetry instance registered; using a no-op. Ensure the telemetry plugin is installed at bootstrap.',\n\t\t);\n\t}\n\treturn noopTelemetry;\n}\n"],"mappings":";;;;;;;;;;;;;;AA8BA,MAAMA,gBAA2B;CAChC,OAAO;CACP,WAAW;CACX,QAAQ;CACR,OAAO;CACP,QAAQ;CACR,kBAAkB;CAClB,aAAa;CACb,mBAAmB;CACnB,kCAAkC;CAClC;AAED,IAAI,8BAA8B;;;;;;AAOlC,SAAgB,eAA0B;CAEzC,MAAM,YADW,qBAAqB,GAAG,OAAO,cAAc,KAAK,GAAG,SACzC,wBAAwB;AACrD,KAAI,SAAU,QAAO;AAKrB,KAAI,OAAO,KAAK,IAAI,OAAO,CAAC,6BAA6B;AACxD,gCAA8B;AAC9B,UAAQ,KACP,yHACA;;AAEF,QAAO"}
|
package/dist/useToast.cjs
CHANGED
|
@@ -1,30 +1,42 @@
|
|
|
1
1
|
const require_useDebounce = require('./useDebounce.cjs');
|
|
2
2
|
const require_useExternalHooks = require('./useExternalHooks2.cjs');
|
|
3
|
+
require('./telemetryRegistry.cjs');
|
|
3
4
|
const require_useTelemetry = require('./useTelemetry2.cjs');
|
|
4
5
|
let vue = require("vue");
|
|
5
6
|
let __n8n_frontend_constants_z_indexes = require("@n8n/frontend-constants/z-indexes");
|
|
6
7
|
let __n8n_frontend_constants_views = require("@n8n/frontend-constants/views");
|
|
7
8
|
let __n8n_frontend_utils_htmlUtils = require("@n8n/frontend-utils/htmlUtils");
|
|
8
9
|
let __n8n_i18n = require("@n8n/i18n");
|
|
9
|
-
let __n8n_stores_notifications_store = require("@n8n/stores/notifications.store");
|
|
10
10
|
let vue_router = require("vue-router");
|
|
11
11
|
|
|
12
12
|
//#region src/useToast.ts
|
|
13
13
|
let registeredNotify;
|
|
14
14
|
/**
|
|
15
15
|
* Register the notification function. Called once at bootstrap by
|
|
16
|
-
* `editor-ui` (passing `ElNotification`
|
|
17
|
-
* can issue notifications without importing element-plus directly —
|
|
18
|
-
* the DTS build lightweight.
|
|
16
|
+
* `editor-ui` (passing a suppression-aware wrapper around `ElNotification`) so
|
|
17
|
+
* `useToast` can issue notifications without importing element-plus directly —
|
|
18
|
+
* keeping the DTS build lightweight.
|
|
19
|
+
*
|
|
20
|
+
* This is the *only* toast dependency the app registers. Whether a notification
|
|
21
|
+
* is actually shown is the notifier's decision, so if you are chasing a toast
|
|
22
|
+
* that never appeared, look at the registration site, not here.
|
|
19
23
|
*/
|
|
20
24
|
function setNotify(fn) {
|
|
21
25
|
registeredNotify = fn;
|
|
22
26
|
}
|
|
23
27
|
const noopHandle = { close() {} };
|
|
24
28
|
const noopNotify = () => noopHandle;
|
|
29
|
+
let warnedAboutMissingNotify = false;
|
|
30
|
+
function resolveNotify() {
|
|
31
|
+
if (registeredNotify) return registeredNotify;
|
|
32
|
+
if ({}.env.DEV && !warnedAboutMissingNotify) {
|
|
33
|
+
warnedAboutMissingNotify = true;
|
|
34
|
+
console.warn("[useToast] No notification function registered; toasts will not render. Call setNotify() at app bootstrap.");
|
|
35
|
+
}
|
|
36
|
+
return noopNotify;
|
|
37
|
+
}
|
|
25
38
|
const stickyNotificationQueue = [];
|
|
26
39
|
function useToast() {
|
|
27
|
-
const notify = registeredNotify ?? noopNotify;
|
|
28
40
|
const telemetry = require_useTelemetry.useTelemetry();
|
|
29
41
|
const route = (0, vue_router.useRoute)();
|
|
30
42
|
const workflowId = (0, vue.computed)(() => {
|
|
@@ -32,7 +44,6 @@ function useToast() {
|
|
|
32
44
|
const id = route?.params?.workflowId;
|
|
33
45
|
return (Array.isArray(id) ? id[0] : id) ?? "";
|
|
34
46
|
});
|
|
35
|
-
const notificationsStore = (0, __n8n_stores_notifications_store.useNotificationsStore)();
|
|
36
47
|
const externalHooks = require_useExternalHooks.useExternalHooks();
|
|
37
48
|
const i18n = (0, __n8n_i18n.useI18n)();
|
|
38
49
|
function causedByCredential(message) {
|
|
@@ -40,9 +51,7 @@ function useToast() {
|
|
|
40
51
|
return message.includes("Credentials for") && message.includes("are not set");
|
|
41
52
|
}
|
|
42
53
|
function showMessage(messageData, track = true) {
|
|
43
|
-
const
|
|
44
|
-
const allowErrors = notificationsStore.allowErrorNotificationsWhenSuppressed;
|
|
45
|
-
if (suppressed && !(allowErrors && messageData.type === "error")) return { close: () => {} };
|
|
54
|
+
const notify = resolveNotify();
|
|
46
55
|
const messageDefaults = {
|
|
47
56
|
dangerouslyUseHTMLString: true,
|
|
48
57
|
position: "bottom-right",
|
|
@@ -58,6 +67,7 @@ function useToast() {
|
|
|
58
67
|
if (typeof message === "string") params.message = (0, __n8n_frontend_utils_htmlUtils.sanitizeHtml)(message);
|
|
59
68
|
if (typeof title === "string") params.title = (0, __n8n_frontend_utils_htmlUtils.sanitizeHtml)(title);
|
|
60
69
|
const notification = notify(params);
|
|
70
|
+
if (!notification) return noopHandle;
|
|
61
71
|
if (params.duration === 0) stickyNotificationQueue.push(notification);
|
|
62
72
|
if (params.type === "error" && track) {
|
|
63
73
|
let messageForTelemetry;
|
|
@@ -146,26 +156,11 @@ function useToast() {
|
|
|
146
156
|
});
|
|
147
157
|
stickyNotificationQueue.length = 0;
|
|
148
158
|
}
|
|
149
|
-
function showNotificationForViews(views) {
|
|
150
|
-
const notifications = [];
|
|
151
|
-
views.forEach((view) => {
|
|
152
|
-
notifications.push(...notificationsStore.pendingNotificationsForViews[view] ?? []);
|
|
153
|
-
});
|
|
154
|
-
if (notifications.length) {
|
|
155
|
-
notifications.forEach((notification) => {
|
|
156
|
-
setTimeout(() => {
|
|
157
|
-
showMessage(notification);
|
|
158
|
-
}, 5);
|
|
159
|
-
});
|
|
160
|
-
notificationsStore.setNotificationsForView(__n8n_frontend_constants_views.VIEWS.WORKFLOW, []);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
159
|
return {
|
|
164
160
|
showMessage,
|
|
165
161
|
showToast,
|
|
166
162
|
showError,
|
|
167
|
-
clearAllStickyNotifications
|
|
168
|
-
showNotificationForViews
|
|
163
|
+
clearAllStickyNotifications
|
|
169
164
|
};
|
|
170
165
|
}
|
|
171
166
|
|
package/dist/useToast.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useToast.cjs","names":["registeredNotify: NotifyFn | undefined","noopHandle: NotificationHandle","noopNotify: NotifyFn","stickyNotificationQueue: NotificationHandle[]","useTelemetry","VIEWS","useExternalHooks","messageDefaults: Partial<Omit<NotificationOptions, 'message'>>","APP_Z_INDEXES","messageForTelemetry: string","notification: NotificationHandle","notifications: NotificationOptions[]"],"sources":["../src/useToast.ts"],"sourcesContent":["import { VIEWS } from '@n8n/frontend-constants/views';\nimport { APP_Z_INDEXES } from '@n8n/frontend-constants/z-indexes';\nimport { sanitizeHtml } from '@n8n/frontend-utils/htmlUtils';\nimport { useI18n } from '@n8n/i18n';\nimport type { NotificationOptions } from '@n8n/stores/notifications.store';\nimport { useNotificationsStore } from '@n8n/stores/notifications.store';\nimport { computed } from 'vue';\nimport { useRoute } from 'vue-router';\n\nimport { useExternalHooks } from './useExternalHooks';\nimport { useTelemetry } from './useTelemetry';\n\n/**\n * Handle returned by the notification function. Declared locally so the DTS\n * build stays free of the full element-plus type graph.\n */\nexport interface NotificationHandle {\n\tclose: () => void;\n}\n\n/** Notification severity — mirrors `MessageBoxState['type']` from element-plus. */\nexport type NotificationType = '' | 'success' | 'warning' | 'info' | 'error';\n\n/**\n * Notification function contract — matches `ElNotification` from element-plus.\n * The application registers the concrete implementation at bootstrap via\n * {@link setNotify}; this package owns only the contract.\n */\ntype NotifyFn = (options: Record<string, unknown>) => NotificationHandle;\n\nlet registeredNotify: NotifyFn | undefined;\n\n/**\n * Register the notification function. Called once at bootstrap by\n * `editor-ui` (passing `ElNotification` from element-plus) so `useToast`\n * can issue notifications without importing element-plus directly — keeping\n * the DTS build lightweight.\n */\nexport function setNotify(fn: NotifyFn): void {\n\tregisteredNotify = fn;\n}\n\nconst noopHandle: NotificationHandle = { close() {} };\nconst noopNotify: NotifyFn = () => noopHandle;\n\nconst stickyNotificationQueue: NotificationHandle[] = [];\n\nexport function useToast() {\n\tconst notify = registeredNotify ?? noopNotify;\n\tconst telemetry = useTelemetry();\n\tconst route = useRoute();\n\tconst workflowId = computed(() => {\n\t\tif (route?.name === VIEWS.DEMO || route?.name === VIEWS.DEMO_DIFF) return 'demo';\n\t\tconst id = route?.params?.workflowId;\n\t\treturn (Array.isArray(id) ? id[0] : id) ?? '';\n\t});\n\tconst notificationsStore = useNotificationsStore();\n\tconst externalHooks = useExternalHooks();\n\tconst i18n = useI18n();\n\n\tfunction causedByCredential(message: string | undefined) {\n\t\tif (!message || typeof message !== 'string') return false;\n\n\t\treturn message.includes('Credentials for') && message.includes('are not set');\n\t}\n\n\tfunction showMessage(messageData: Partial<NotificationOptions>, track = true) {\n\t\tconst suppressed = notificationsStore.areNotificationsSuppressed;\n\t\tconst allowErrors = notificationsStore.allowErrorNotificationsWhenSuppressed;\n\t\tif (suppressed && !(allowErrors && messageData.type === 'error')) {\n\t\t\treturn { close: () => {} } as NotificationHandle;\n\t\t}\n\n\t\tconst messageDefaults: Partial<Omit<NotificationOptions, 'message'>> = {\n\t\t\tdangerouslyUseHTMLString: true,\n\t\t\tposition: 'bottom-right',\n\t\t\t// Layer above NDV and modal overlays, sourced from the shared scale.\n\t\t\tzIndex: APP_Z_INDEXES.TOASTS,\n\t\t\tappendTo: '#n8n-app',\n\t\t\tcustomClass: 'content-toast',\n\t\t};\n\t\tconst { message, title } = messageData;\n\t\tconst params = { ...messageDefaults, ...messageData };\n\n\t\tif (typeof message === 'string') {\n\t\t\tparams.message = sanitizeHtml(message);\n\t\t}\n\n\t\tif (typeof title === 'string') {\n\t\t\tparams.title = sanitizeHtml(title);\n\t\t}\n\n\t\tconst notification = notify(params as unknown as Record<string, unknown>);\n\n\t\tif (params.duration === 0) {\n\t\t\tstickyNotificationQueue.push(notification);\n\t\t}\n\n\t\tif (params.type === 'error' && track) {\n\t\t\t// Extract string message for telemetry - don't send VNode objects as they have circular refs\n\t\t\tlet messageForTelemetry: string;\n\t\t\tif (typeof params.message === 'string') {\n\t\t\t\tmessageForTelemetry = params.message;\n\t\t\t} else if (\n\t\t\t\tparams.message &&\n\t\t\t\ttypeof params.message === 'object' &&\n\t\t\t\t'props' in params.message &&\n\t\t\t\tparams.message.props\n\t\t\t) {\n\t\t\t\t// Extract error message from VNode props (e.g., NodeExecutionErrorMessage component)\n\t\t\t\tconst props = params.message.props;\n\t\t\t\tconst hasErrorMessage =\n\t\t\t\t\ttypeof props === 'object' && props !== null && 'errorMessage' in props;\n\t\t\t\tconst hasMessage = typeof props === 'object' && props !== null && 'message' in props;\n\n\t\t\t\tif (hasErrorMessage) {\n\t\t\t\t\tmessageForTelemetry = String(props.errorMessage);\n\t\t\t\t} else if (hasMessage) {\n\t\t\t\t\tmessageForTelemetry = String(props.message);\n\t\t\t\t} else {\n\t\t\t\t\tmessageForTelemetry = 'Unknown error';\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tmessageForTelemetry = 'Unknown error';\n\t\t\t}\n\n\t\t\ttelemetry.track('Instance FE emitted error', {\n\t\t\t\terror_title: params.title,\n\t\t\t\terror_message: messageForTelemetry,\n\t\t\t\tcaused_by_credential: causedByCredential(messageForTelemetry),\n\t\t\t\tworkflow_id: workflowId.value,\n\t\t\t});\n\t\t}\n\n\t\treturn notification;\n\t}\n\n\tfunction showToast(config: {\n\t\ttitle: string;\n\t\tmessage: NotificationOptions['message'];\n\t\tonClick?: (event?: MouseEvent) => void;\n\t\tonClose?: () => void;\n\t\tduration?: number;\n\t\tcustomClass?: string;\n\t\tcloseOnClick?: boolean;\n\t\ttype?: NotificationType;\n\t}) {\n\t\t// eslint-disable-next-line prefer-const\n\t\tlet notification: NotificationHandle;\n\t\tif (config.closeOnClick) {\n\t\t\tconst originalOnClick = config.onClick;\n\t\t\tconfig.onClick = () => {\n\t\t\t\tif (notification) {\n\t\t\t\t\tnotification.close();\n\t\t\t\t}\n\n\t\t\t\tif (originalOnClick) {\n\t\t\t\t\toriginalOnClick();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\tnotification = showMessage({\n\t\t\ttitle: config.title,\n\t\t\tmessage: config.message,\n\t\t\tonClick: config.onClick,\n\t\t\tonClose: config.onClose,\n\t\t\tduration: config.duration,\n\t\t\tcustomClass: config.customClass,\n\t\t\ttype: config.type,\n\t\t});\n\n\t\treturn notification;\n\t}\n\n\tfunction collapsableDetails(description: string) {\n\t\tconst errorDescription =\n\t\t\tdescription.length > 500 ? `${description.slice(0, 500)}...` : description;\n\n\t\treturn `\n\t\t\t\t<br>\n\t\t\t\t<br>\n\t\t\t\t<details>\n\t\t\t\t\t<summary\n\t\t\t\t\t\tstyle=\"color: #ff6d5a; font-weight: bold; cursor: pointer;\"\n\t\t\t\t\t>\n\t\t\t\t\t\t${i18n.baseText('showMessage.showDetails')}\n\t\t\t\t\t</summary>\n\t\t\t\t\t<p>${errorDescription}</p>\n\t\t\t\t</details>\n\t\t\t`;\n\t}\n\n\tfunction showError(\n\t\te: unknown,\n\t\ttitle: string,\n\t\toptions?: { message?: string; description?: string },\n\t) {\n\t\tconst error = e as Error & { description?: string };\n\t\tconst message = options?.message;\n\t\tconst description = options?.description ?? error.description;\n\t\tconst messageLine = message ? `${message}<br/>` : '';\n\t\tshowMessage(\n\t\t\t{\n\t\t\t\ttitle,\n\t\t\t\tmessage: `\n\t\t\t\t\t${messageLine}\n\t\t\t\t\t<i>${error.message}</i>\n\t\t\t\t\t${description ? collapsableDetails(description) : ''}`,\n\t\t\t\ttype: 'error',\n\t\t\t\tduration: 0,\n\t\t\t},\n\t\t\tfalse,\n\t\t);\n\n\t\tvoid externalHooks.run('showMessage.showError', {\n\t\t\ttitle,\n\t\t\tmessage,\n\t\t\terrorMessage: error.message,\n\t\t});\n\n\t\ttelemetry.track('Instance FE emitted error', {\n\t\t\terror_title: title,\n\t\t\terror_description: message,\n\t\t\terror_message: error.message,\n\t\t\tcaused_by_credential: causedByCredential(error.message),\n\t\t\tworkflow_id: workflowId.value,\n\t\t});\n\t}\n\n\tfunction clearAllStickyNotifications() {\n\t\tstickyNotificationQueue.forEach((notification) => {\n\t\t\tif (notification) {\n\t\t\t\tnotification.close();\n\t\t\t}\n\t\t});\n\n\t\tstickyNotificationQueue.length = 0;\n\t}\n\n\t// Pick up and display notifications for the given list of views\n\tfunction showNotificationForViews(views: VIEWS[]) {\n\t\tconst notifications: NotificationOptions[] = [];\n\t\tviews.forEach((view) => {\n\t\t\tnotifications.push(...(notificationsStore.pendingNotificationsForViews[view] ?? []));\n\t\t});\n\t\tif (notifications.length) {\n\t\t\tnotifications.forEach((notification) => {\n\t\t\t\t// Notifications show on top of each other without this timeout\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tshowMessage(notification);\n\t\t\t\t}, 5);\n\t\t\t});\n\t\t\t// Clear the queue once all notifications are shown\n\t\t\tnotificationsStore.setNotificationsForView(VIEWS.WORKFLOW, []);\n\t\t}\n\t}\n\n\treturn {\n\t\tshowMessage,\n\t\tshowToast,\n\t\tshowError,\n\t\tclearAllStickyNotifications,\n\t\tshowNotificationForViews,\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useToast.cjs","names":["registeredNotify: NotifyFn | undefined","noopHandle: NotificationHandle","noopNotify: NotifyFn","stickyNotificationQueue: NotificationHandle[]","useTelemetry","VIEWS","useExternalHooks","messageDefaults: Partial<Omit<NotificationOptions, 'message'>>","APP_Z_INDEXES","messageForTelemetry: string","notification: NotificationHandle"],"sources":["../src/useToast.ts"],"sourcesContent":["import { VIEWS } from '@n8n/frontend-constants/views';\nimport { APP_Z_INDEXES } from '@n8n/frontend-constants/z-indexes';\nimport { sanitizeHtml } from '@n8n/frontend-utils/htmlUtils';\nimport { useI18n } from '@n8n/i18n';\nimport { computed } from 'vue';\nimport { useRoute } from 'vue-router';\n\nimport type { NotificationOptions, NotificationType } from './types/notification';\nimport { useExternalHooks } from './useExternalHooks';\nimport { useTelemetry } from './useTelemetry';\n\nexport type {\n\tNotificationOptions,\n\tNotificationPosition,\n\tNotificationType,\n} from './types/notification';\n\n/**\n * Handle returned by the notification function. Declared locally so the DTS\n * build stays free of the full element-plus type graph.\n */\nexport interface NotificationHandle {\n\tclose: () => void;\n}\n\n/**\n * Notification function contract — the app's wrapper around `ElNotification`.\n * Registered at bootstrap via {@link setNotify}; this package owns only the\n * contract.\n *\n * Returning `undefined` means the app declined to show this notification — today\n * that is notification suppression, which lives at the registration site rather\n * than here. `showMessage` treats it as \"dropped\": no sticky-queue\n * entry, no error telemetry, and a no-op handle to the caller.\n */\ntype NotifyFn = (options: Record<string, unknown>) => NotificationHandle | undefined;\n\nlet registeredNotify: NotifyFn | undefined;\n\n/**\n * Register the notification function. Called once at bootstrap by\n * `editor-ui` (passing a suppression-aware wrapper around `ElNotification`) so\n * `useToast` can issue notifications without importing element-plus directly —\n * keeping the DTS build lightweight.\n *\n * This is the *only* toast dependency the app registers. Whether a notification\n * is actually shown is the notifier's decision, so if you are chasing a toast\n * that never appeared, look at the registration site, not here.\n */\nexport function setNotify(fn: NotifyFn): void {\n\tregisteredNotify = fn;\n}\n\nconst noopHandle: NotificationHandle = { close() {} };\nconst noopNotify: NotifyFn = () => noopHandle;\n\nlet warnedAboutMissingNotify = false;\n\nfunction resolveNotify(): NotifyFn {\n\tif (registeredNotify) return registeredNotify;\n\n\t// Falling back means bootstrap never registered. The toast is dropped rather\n\t// than shown, so warn once in dev instead of failing silent.\n\tif (import.meta.env.DEV && !warnedAboutMissingNotify) {\n\t\twarnedAboutMissingNotify = true;\n\t\tconsole.warn(\n\t\t\t'[useToast] No notification function registered; toasts will not render. Call setNotify() at app bootstrap.',\n\t\t);\n\t}\n\treturn noopNotify;\n}\n\nconst stickyNotificationQueue: NotificationHandle[] = [];\n\nexport function useToast() {\n\tconst telemetry = useTelemetry();\n\tconst route = useRoute();\n\tconst workflowId = computed(() => {\n\t\tif (route?.name === VIEWS.DEMO || route?.name === VIEWS.DEMO_DIFF) return 'demo';\n\t\tconst id = route?.params?.workflowId;\n\t\treturn (Array.isArray(id) ? id[0] : id) ?? '';\n\t});\n\tconst externalHooks = useExternalHooks();\n\tconst i18n = useI18n();\n\n\tfunction causedByCredential(message: string | undefined) {\n\t\tif (!message || typeof message !== 'string') return false;\n\n\t\treturn message.includes('Credentials for') && message.includes('are not set');\n\t}\n\n\tfunction showMessage(messageData: Partial<NotificationOptions>, track = true) {\n\t\t// Resolved per call, not once per `useToast()`: a composable captured before\n\t\t// bootstrap registers would otherwise stay bound to the no-op for its whole\n\t\t// lifetime, silently dropping toasts.\n\t\tconst notify = resolveNotify();\n\n\t\tconst messageDefaults: Partial<Omit<NotificationOptions, 'message'>> = {\n\t\t\tdangerouslyUseHTMLString: true,\n\t\t\tposition: 'bottom-right',\n\t\t\t// Layer above NDV and modal overlays, sourced from the shared scale.\n\t\t\tzIndex: APP_Z_INDEXES.TOASTS,\n\t\t\tappendTo: '#n8n-app',\n\t\t\tcustomClass: 'content-toast',\n\t\t};\n\t\tconst { message, title } = messageData;\n\t\tconst params = { ...messageDefaults, ...messageData };\n\n\t\tif (typeof message === 'string') {\n\t\t\tparams.message = sanitizeHtml(message);\n\t\t}\n\n\t\tif (typeof title === 'string') {\n\t\t\tparams.title = sanitizeHtml(title);\n\t\t}\n\n\t\tconst notification = notify(params as unknown as Record<string, unknown>);\n\n\t\t// The app declined to show it (suppression). Return before the sticky queue\n\t\t// and before error telemetry, so a dropped toast leaves no trace — exactly\n\t\t// what the removed in-package suppression branch did.\n\t\tif (!notification) return noopHandle;\n\n\t\tif (params.duration === 0) {\n\t\t\tstickyNotificationQueue.push(notification);\n\t\t}\n\n\t\tif (params.type === 'error' && track) {\n\t\t\t// Extract string message for telemetry - don't send VNode objects as they have circular refs\n\t\t\tlet messageForTelemetry: string;\n\t\t\tif (typeof params.message === 'string') {\n\t\t\t\tmessageForTelemetry = params.message;\n\t\t\t} else if (\n\t\t\t\tparams.message &&\n\t\t\t\ttypeof params.message === 'object' &&\n\t\t\t\t'props' in params.message &&\n\t\t\t\tparams.message.props\n\t\t\t) {\n\t\t\t\t// Extract error message from VNode props (e.g., NodeExecutionErrorMessage component)\n\t\t\t\tconst props = params.message.props;\n\t\t\t\tconst hasErrorMessage =\n\t\t\t\t\ttypeof props === 'object' && props !== null && 'errorMessage' in props;\n\t\t\t\tconst hasMessage = typeof props === 'object' && props !== null && 'message' in props;\n\n\t\t\t\tif (hasErrorMessage) {\n\t\t\t\t\tmessageForTelemetry = String(props.errorMessage);\n\t\t\t\t} else if (hasMessage) {\n\t\t\t\t\tmessageForTelemetry = String(props.message);\n\t\t\t\t} else {\n\t\t\t\t\tmessageForTelemetry = 'Unknown error';\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tmessageForTelemetry = 'Unknown error';\n\t\t\t}\n\n\t\t\ttelemetry.track('Instance FE emitted error', {\n\t\t\t\terror_title: params.title,\n\t\t\t\terror_message: messageForTelemetry,\n\t\t\t\tcaused_by_credential: causedByCredential(messageForTelemetry),\n\t\t\t\tworkflow_id: workflowId.value,\n\t\t\t});\n\t\t}\n\n\t\treturn notification;\n\t}\n\n\tfunction showToast(config: {\n\t\ttitle: string;\n\t\tmessage: NotificationOptions['message'];\n\t\tonClick?: (event?: MouseEvent) => void;\n\t\tonClose?: () => void;\n\t\tduration?: number;\n\t\tcustomClass?: string;\n\t\tcloseOnClick?: boolean;\n\t\ttype?: NotificationType;\n\t}) {\n\t\t// eslint-disable-next-line prefer-const\n\t\tlet notification: NotificationHandle;\n\t\tif (config.closeOnClick) {\n\t\t\tconst originalOnClick = config.onClick;\n\t\t\tconfig.onClick = () => {\n\t\t\t\tif (notification) {\n\t\t\t\t\tnotification.close();\n\t\t\t\t}\n\n\t\t\t\tif (originalOnClick) {\n\t\t\t\t\toriginalOnClick();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\tnotification = showMessage({\n\t\t\ttitle: config.title,\n\t\t\tmessage: config.message,\n\t\t\tonClick: config.onClick,\n\t\t\tonClose: config.onClose,\n\t\t\tduration: config.duration,\n\t\t\tcustomClass: config.customClass,\n\t\t\ttype: config.type,\n\t\t});\n\n\t\treturn notification;\n\t}\n\n\tfunction collapsableDetails(description: string) {\n\t\tconst errorDescription =\n\t\t\tdescription.length > 500 ? `${description.slice(0, 500)}...` : description;\n\n\t\treturn `\n\t\t\t\t<br>\n\t\t\t\t<br>\n\t\t\t\t<details>\n\t\t\t\t\t<summary\n\t\t\t\t\t\tstyle=\"color: #ff6d5a; font-weight: bold; cursor: pointer;\"\n\t\t\t\t\t>\n\t\t\t\t\t\t${i18n.baseText('showMessage.showDetails')}\n\t\t\t\t\t</summary>\n\t\t\t\t\t<p>${errorDescription}</p>\n\t\t\t\t</details>\n\t\t\t`;\n\t}\n\n\tfunction showError(\n\t\te: unknown,\n\t\ttitle: string,\n\t\toptions?: { message?: string; description?: string },\n\t) {\n\t\tconst error = e as Error & { description?: string };\n\t\tconst message = options?.message;\n\t\tconst description = options?.description ?? error.description;\n\t\tconst messageLine = message ? `${message}<br/>` : '';\n\t\tshowMessage(\n\t\t\t{\n\t\t\t\ttitle,\n\t\t\t\tmessage: `\n\t\t\t\t\t${messageLine}\n\t\t\t\t\t<i>${error.message}</i>\n\t\t\t\t\t${description ? collapsableDetails(description) : ''}`,\n\t\t\t\ttype: 'error',\n\t\t\t\tduration: 0,\n\t\t\t},\n\t\t\tfalse,\n\t\t);\n\n\t\tvoid externalHooks.run('showMessage.showError', {\n\t\t\ttitle,\n\t\t\tmessage,\n\t\t\terrorMessage: error.message,\n\t\t});\n\n\t\ttelemetry.track('Instance FE emitted error', {\n\t\t\terror_title: title,\n\t\t\terror_description: message,\n\t\t\terror_message: error.message,\n\t\t\tcaused_by_credential: causedByCredential(error.message),\n\t\t\tworkflow_id: workflowId.value,\n\t\t});\n\t}\n\n\tfunction clearAllStickyNotifications() {\n\t\tstickyNotificationQueue.forEach((notification) => {\n\t\t\tif (notification) {\n\t\t\t\tnotification.close();\n\t\t\t}\n\t\t});\n\n\t\tstickyNotificationQueue.length = 0;\n\t}\n\n\treturn {\n\t\tshowMessage,\n\t\tshowToast,\n\t\tshowError,\n\t\tclearAllStickyNotifications,\n\t};\n}\n"],"mappings":"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"}
|
package/dist/useToast.d.cts
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { NotificationOptions } from "@n8n/stores/notifications.store";
|
|
1
|
+
import { n as NotificationPosition, r as NotificationType, t as NotificationOptions } from "./notification.cjs";
|
|
3
2
|
|
|
4
3
|
//#region src/useToast.d.ts
|
|
5
4
|
interface NotificationHandle {
|
|
6
5
|
close: () => void;
|
|
7
6
|
}
|
|
8
|
-
type
|
|
9
|
-
type NotifyFn = (options: Record<string, unknown>) => NotificationHandle;
|
|
7
|
+
type NotifyFn = (options: Record<string, unknown>) => NotificationHandle | undefined;
|
|
10
8
|
declare function setNotify(fn: NotifyFn): void;
|
|
11
9
|
declare function useToast(): {
|
|
12
10
|
showMessage: (messageData: Partial<NotificationOptions>, track?: boolean) => NotificationHandle;
|
|
@@ -25,8 +23,7 @@ declare function useToast(): {
|
|
|
25
23
|
description?: string;
|
|
26
24
|
}) => void;
|
|
27
25
|
clearAllStickyNotifications: () => void;
|
|
28
|
-
showNotificationForViews: (views: VIEWS[]) => void;
|
|
29
26
|
};
|
|
30
27
|
//#endregion
|
|
31
|
-
export { NotificationHandle, NotificationType, setNotify, useToast };
|
|
28
|
+
export { NotificationHandle, type NotificationOptions, type NotificationPosition, type NotificationType, setNotify, useToast };
|
|
32
29
|
//# sourceMappingURL=useToast.d.cts.map
|
package/dist/useToast.d.mts
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { NotificationOptions } from "@n8n/stores/notifications.store";
|
|
1
|
+
import { n as NotificationPosition, r as NotificationType, t as NotificationOptions } from "./notification.mjs";
|
|
3
2
|
|
|
4
3
|
//#region src/useToast.d.ts
|
|
5
4
|
interface NotificationHandle {
|
|
6
5
|
close: () => void;
|
|
7
6
|
}
|
|
8
|
-
type
|
|
9
|
-
type NotifyFn = (options: Record<string, unknown>) => NotificationHandle;
|
|
7
|
+
type NotifyFn = (options: Record<string, unknown>) => NotificationHandle | undefined;
|
|
10
8
|
declare function setNotify(fn: NotifyFn): void;
|
|
11
9
|
declare function useToast(): {
|
|
12
10
|
showMessage: (messageData: Partial<NotificationOptions>, track?: boolean) => NotificationHandle;
|
|
@@ -25,8 +23,7 @@ declare function useToast(): {
|
|
|
25
23
|
description?: string;
|
|
26
24
|
}) => void;
|
|
27
25
|
clearAllStickyNotifications: () => void;
|
|
28
|
-
showNotificationForViews: (views: VIEWS[]) => void;
|
|
29
26
|
};
|
|
30
27
|
//#endregion
|
|
31
|
-
export { NotificationHandle, NotificationType, setNotify, useToast };
|
|
28
|
+
export { NotificationHandle, type NotificationOptions, type NotificationPosition, type NotificationType, setNotify, useToast };
|
|
32
29
|
//# sourceMappingURL=useToast.d.mts.map
|
package/dist/useToast.mjs
CHANGED
|
@@ -1,29 +1,41 @@
|
|
|
1
1
|
import { r as useExternalHooks } from "./useExternalHooks2.mjs";
|
|
2
|
-
import
|
|
2
|
+
import "./telemetryRegistry.mjs";
|
|
3
|
+
import { t as useTelemetry } from "./useTelemetry2.mjs";
|
|
3
4
|
import { computed } from "vue";
|
|
4
5
|
import { APP_Z_INDEXES } from "@n8n/frontend-constants/z-indexes";
|
|
5
6
|
import { VIEWS } from "@n8n/frontend-constants/views";
|
|
6
7
|
import { sanitizeHtml } from "@n8n/frontend-utils/htmlUtils";
|
|
7
8
|
import { useI18n } from "@n8n/i18n";
|
|
8
|
-
import { useNotificationsStore } from "@n8n/stores/notifications.store";
|
|
9
9
|
import { useRoute } from "vue-router";
|
|
10
10
|
|
|
11
11
|
//#region src/useToast.ts
|
|
12
12
|
let registeredNotify;
|
|
13
13
|
/**
|
|
14
14
|
* Register the notification function. Called once at bootstrap by
|
|
15
|
-
* `editor-ui` (passing `ElNotification`
|
|
16
|
-
* can issue notifications without importing element-plus directly —
|
|
17
|
-
* the DTS build lightweight.
|
|
15
|
+
* `editor-ui` (passing a suppression-aware wrapper around `ElNotification`) so
|
|
16
|
+
* `useToast` can issue notifications without importing element-plus directly —
|
|
17
|
+
* keeping the DTS build lightweight.
|
|
18
|
+
*
|
|
19
|
+
* This is the *only* toast dependency the app registers. Whether a notification
|
|
20
|
+
* is actually shown is the notifier's decision, so if you are chasing a toast
|
|
21
|
+
* that never appeared, look at the registration site, not here.
|
|
18
22
|
*/
|
|
19
23
|
function setNotify(fn) {
|
|
20
24
|
registeredNotify = fn;
|
|
21
25
|
}
|
|
22
26
|
const noopHandle = { close() {} };
|
|
23
27
|
const noopNotify = () => noopHandle;
|
|
28
|
+
let warnedAboutMissingNotify = false;
|
|
29
|
+
function resolveNotify() {
|
|
30
|
+
if (registeredNotify) return registeredNotify;
|
|
31
|
+
if (import.meta.env.DEV && !warnedAboutMissingNotify) {
|
|
32
|
+
warnedAboutMissingNotify = true;
|
|
33
|
+
console.warn("[useToast] No notification function registered; toasts will not render. Call setNotify() at app bootstrap.");
|
|
34
|
+
}
|
|
35
|
+
return noopNotify;
|
|
36
|
+
}
|
|
24
37
|
const stickyNotificationQueue = [];
|
|
25
38
|
function useToast() {
|
|
26
|
-
const notify = registeredNotify ?? noopNotify;
|
|
27
39
|
const telemetry = useTelemetry();
|
|
28
40
|
const route = useRoute();
|
|
29
41
|
const workflowId = computed(() => {
|
|
@@ -31,7 +43,6 @@ function useToast() {
|
|
|
31
43
|
const id = route?.params?.workflowId;
|
|
32
44
|
return (Array.isArray(id) ? id[0] : id) ?? "";
|
|
33
45
|
});
|
|
34
|
-
const notificationsStore = useNotificationsStore();
|
|
35
46
|
const externalHooks = useExternalHooks();
|
|
36
47
|
const i18n = useI18n();
|
|
37
48
|
function causedByCredential(message) {
|
|
@@ -39,9 +50,7 @@ function useToast() {
|
|
|
39
50
|
return message.includes("Credentials for") && message.includes("are not set");
|
|
40
51
|
}
|
|
41
52
|
function showMessage(messageData, track = true) {
|
|
42
|
-
const
|
|
43
|
-
const allowErrors = notificationsStore.allowErrorNotificationsWhenSuppressed;
|
|
44
|
-
if (suppressed && !(allowErrors && messageData.type === "error")) return { close: () => {} };
|
|
53
|
+
const notify = resolveNotify();
|
|
45
54
|
const messageDefaults = {
|
|
46
55
|
dangerouslyUseHTMLString: true,
|
|
47
56
|
position: "bottom-right",
|
|
@@ -57,6 +66,7 @@ function useToast() {
|
|
|
57
66
|
if (typeof message === "string") params.message = sanitizeHtml(message);
|
|
58
67
|
if (typeof title === "string") params.title = sanitizeHtml(title);
|
|
59
68
|
const notification = notify(params);
|
|
69
|
+
if (!notification) return noopHandle;
|
|
60
70
|
if (params.duration === 0) stickyNotificationQueue.push(notification);
|
|
61
71
|
if (params.type === "error" && track) {
|
|
62
72
|
let messageForTelemetry;
|
|
@@ -145,26 +155,11 @@ function useToast() {
|
|
|
145
155
|
});
|
|
146
156
|
stickyNotificationQueue.length = 0;
|
|
147
157
|
}
|
|
148
|
-
function showNotificationForViews(views) {
|
|
149
|
-
const notifications = [];
|
|
150
|
-
views.forEach((view) => {
|
|
151
|
-
notifications.push(...notificationsStore.pendingNotificationsForViews[view] ?? []);
|
|
152
|
-
});
|
|
153
|
-
if (notifications.length) {
|
|
154
|
-
notifications.forEach((notification) => {
|
|
155
|
-
setTimeout(() => {
|
|
156
|
-
showMessage(notification);
|
|
157
|
-
}, 5);
|
|
158
|
-
});
|
|
159
|
-
notificationsStore.setNotificationsForView(VIEWS.WORKFLOW, []);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
158
|
return {
|
|
163
159
|
showMessage,
|
|
164
160
|
showToast,
|
|
165
161
|
showError,
|
|
166
|
-
clearAllStickyNotifications
|
|
167
|
-
showNotificationForViews
|
|
162
|
+
clearAllStickyNotifications
|
|
168
163
|
};
|
|
169
164
|
}
|
|
170
165
|
|
package/dist/useToast.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useToast.mjs","names":["registeredNotify: NotifyFn | undefined","noopHandle: NotificationHandle","noopNotify: NotifyFn","stickyNotificationQueue: NotificationHandle[]","messageDefaults: Partial<Omit<NotificationOptions, 'message'>>","messageForTelemetry: string","notification: NotificationHandle","notifications: NotificationOptions[]"],"sources":["../src/useToast.ts"],"sourcesContent":["import { VIEWS } from '@n8n/frontend-constants/views';\nimport { APP_Z_INDEXES } from '@n8n/frontend-constants/z-indexes';\nimport { sanitizeHtml } from '@n8n/frontend-utils/htmlUtils';\nimport { useI18n } from '@n8n/i18n';\nimport type { NotificationOptions } from '@n8n/stores/notifications.store';\nimport { useNotificationsStore } from '@n8n/stores/notifications.store';\nimport { computed } from 'vue';\nimport { useRoute } from 'vue-router';\n\nimport { useExternalHooks } from './useExternalHooks';\nimport { useTelemetry } from './useTelemetry';\n\n/**\n * Handle returned by the notification function. Declared locally so the DTS\n * build stays free of the full element-plus type graph.\n */\nexport interface NotificationHandle {\n\tclose: () => void;\n}\n\n/** Notification severity — mirrors `MessageBoxState['type']` from element-plus. */\nexport type NotificationType = '' | 'success' | 'warning' | 'info' | 'error';\n\n/**\n * Notification function contract — matches `ElNotification` from element-plus.\n * The application registers the concrete implementation at bootstrap via\n * {@link setNotify}; this package owns only the contract.\n */\ntype NotifyFn = (options: Record<string, unknown>) => NotificationHandle;\n\nlet registeredNotify: NotifyFn | undefined;\n\n/**\n * Register the notification function. Called once at bootstrap by\n * `editor-ui` (passing `ElNotification` from element-plus) so `useToast`\n * can issue notifications without importing element-plus directly — keeping\n * the DTS build lightweight.\n */\nexport function setNotify(fn: NotifyFn): void {\n\tregisteredNotify = fn;\n}\n\nconst noopHandle: NotificationHandle = { close() {} };\nconst noopNotify: NotifyFn = () => noopHandle;\n\nconst stickyNotificationQueue: NotificationHandle[] = [];\n\nexport function useToast() {\n\tconst notify = registeredNotify ?? noopNotify;\n\tconst telemetry = useTelemetry();\n\tconst route = useRoute();\n\tconst workflowId = computed(() => {\n\t\tif (route?.name === VIEWS.DEMO || route?.name === VIEWS.DEMO_DIFF) return 'demo';\n\t\tconst id = route?.params?.workflowId;\n\t\treturn (Array.isArray(id) ? id[0] : id) ?? '';\n\t});\n\tconst notificationsStore = useNotificationsStore();\n\tconst externalHooks = useExternalHooks();\n\tconst i18n = useI18n();\n\n\tfunction causedByCredential(message: string | undefined) {\n\t\tif (!message || typeof message !== 'string') return false;\n\n\t\treturn message.includes('Credentials for') && message.includes('are not set');\n\t}\n\n\tfunction showMessage(messageData: Partial<NotificationOptions>, track = true) {\n\t\tconst suppressed = notificationsStore.areNotificationsSuppressed;\n\t\tconst allowErrors = notificationsStore.allowErrorNotificationsWhenSuppressed;\n\t\tif (suppressed && !(allowErrors && messageData.type === 'error')) {\n\t\t\treturn { close: () => {} } as NotificationHandle;\n\t\t}\n\n\t\tconst messageDefaults: Partial<Omit<NotificationOptions, 'message'>> = {\n\t\t\tdangerouslyUseHTMLString: true,\n\t\t\tposition: 'bottom-right',\n\t\t\t// Layer above NDV and modal overlays, sourced from the shared scale.\n\t\t\tzIndex: APP_Z_INDEXES.TOASTS,\n\t\t\tappendTo: '#n8n-app',\n\t\t\tcustomClass: 'content-toast',\n\t\t};\n\t\tconst { message, title } = messageData;\n\t\tconst params = { ...messageDefaults, ...messageData };\n\n\t\tif (typeof message === 'string') {\n\t\t\tparams.message = sanitizeHtml(message);\n\t\t}\n\n\t\tif (typeof title === 'string') {\n\t\t\tparams.title = sanitizeHtml(title);\n\t\t}\n\n\t\tconst notification = notify(params as unknown as Record<string, unknown>);\n\n\t\tif (params.duration === 0) {\n\t\t\tstickyNotificationQueue.push(notification);\n\t\t}\n\n\t\tif (params.type === 'error' && track) {\n\t\t\t// Extract string message for telemetry - don't send VNode objects as they have circular refs\n\t\t\tlet messageForTelemetry: string;\n\t\t\tif (typeof params.message === 'string') {\n\t\t\t\tmessageForTelemetry = params.message;\n\t\t\t} else if (\n\t\t\t\tparams.message &&\n\t\t\t\ttypeof params.message === 'object' &&\n\t\t\t\t'props' in params.message &&\n\t\t\t\tparams.message.props\n\t\t\t) {\n\t\t\t\t// Extract error message from VNode props (e.g., NodeExecutionErrorMessage component)\n\t\t\t\tconst props = params.message.props;\n\t\t\t\tconst hasErrorMessage =\n\t\t\t\t\ttypeof props === 'object' && props !== null && 'errorMessage' in props;\n\t\t\t\tconst hasMessage = typeof props === 'object' && props !== null && 'message' in props;\n\n\t\t\t\tif (hasErrorMessage) {\n\t\t\t\t\tmessageForTelemetry = String(props.errorMessage);\n\t\t\t\t} else if (hasMessage) {\n\t\t\t\t\tmessageForTelemetry = String(props.message);\n\t\t\t\t} else {\n\t\t\t\t\tmessageForTelemetry = 'Unknown error';\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tmessageForTelemetry = 'Unknown error';\n\t\t\t}\n\n\t\t\ttelemetry.track('Instance FE emitted error', {\n\t\t\t\terror_title: params.title,\n\t\t\t\terror_message: messageForTelemetry,\n\t\t\t\tcaused_by_credential: causedByCredential(messageForTelemetry),\n\t\t\t\tworkflow_id: workflowId.value,\n\t\t\t});\n\t\t}\n\n\t\treturn notification;\n\t}\n\n\tfunction showToast(config: {\n\t\ttitle: string;\n\t\tmessage: NotificationOptions['message'];\n\t\tonClick?: (event?: MouseEvent) => void;\n\t\tonClose?: () => void;\n\t\tduration?: number;\n\t\tcustomClass?: string;\n\t\tcloseOnClick?: boolean;\n\t\ttype?: NotificationType;\n\t}) {\n\t\t// eslint-disable-next-line prefer-const\n\t\tlet notification: NotificationHandle;\n\t\tif (config.closeOnClick) {\n\t\t\tconst originalOnClick = config.onClick;\n\t\t\tconfig.onClick = () => {\n\t\t\t\tif (notification) {\n\t\t\t\t\tnotification.close();\n\t\t\t\t}\n\n\t\t\t\tif (originalOnClick) {\n\t\t\t\t\toriginalOnClick();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\tnotification = showMessage({\n\t\t\ttitle: config.title,\n\t\t\tmessage: config.message,\n\t\t\tonClick: config.onClick,\n\t\t\tonClose: config.onClose,\n\t\t\tduration: config.duration,\n\t\t\tcustomClass: config.customClass,\n\t\t\ttype: config.type,\n\t\t});\n\n\t\treturn notification;\n\t}\n\n\tfunction collapsableDetails(description: string) {\n\t\tconst errorDescription =\n\t\t\tdescription.length > 500 ? `${description.slice(0, 500)}...` : description;\n\n\t\treturn `\n\t\t\t\t<br>\n\t\t\t\t<br>\n\t\t\t\t<details>\n\t\t\t\t\t<summary\n\t\t\t\t\t\tstyle=\"color: #ff6d5a; font-weight: bold; cursor: pointer;\"\n\t\t\t\t\t>\n\t\t\t\t\t\t${i18n.baseText('showMessage.showDetails')}\n\t\t\t\t\t</summary>\n\t\t\t\t\t<p>${errorDescription}</p>\n\t\t\t\t</details>\n\t\t\t`;\n\t}\n\n\tfunction showError(\n\t\te: unknown,\n\t\ttitle: string,\n\t\toptions?: { message?: string; description?: string },\n\t) {\n\t\tconst error = e as Error & { description?: string };\n\t\tconst message = options?.message;\n\t\tconst description = options?.description ?? error.description;\n\t\tconst messageLine = message ? `${message}<br/>` : '';\n\t\tshowMessage(\n\t\t\t{\n\t\t\t\ttitle,\n\t\t\t\tmessage: `\n\t\t\t\t\t${messageLine}\n\t\t\t\t\t<i>${error.message}</i>\n\t\t\t\t\t${description ? collapsableDetails(description) : ''}`,\n\t\t\t\ttype: 'error',\n\t\t\t\tduration: 0,\n\t\t\t},\n\t\t\tfalse,\n\t\t);\n\n\t\tvoid externalHooks.run('showMessage.showError', {\n\t\t\ttitle,\n\t\t\tmessage,\n\t\t\terrorMessage: error.message,\n\t\t});\n\n\t\ttelemetry.track('Instance FE emitted error', {\n\t\t\terror_title: title,\n\t\t\terror_description: message,\n\t\t\terror_message: error.message,\n\t\t\tcaused_by_credential: causedByCredential(error.message),\n\t\t\tworkflow_id: workflowId.value,\n\t\t});\n\t}\n\n\tfunction clearAllStickyNotifications() {\n\t\tstickyNotificationQueue.forEach((notification) => {\n\t\t\tif (notification) {\n\t\t\t\tnotification.close();\n\t\t\t}\n\t\t});\n\n\t\tstickyNotificationQueue.length = 0;\n\t}\n\n\t// Pick up and display notifications for the given list of views\n\tfunction showNotificationForViews(views: VIEWS[]) {\n\t\tconst notifications: NotificationOptions[] = [];\n\t\tviews.forEach((view) => {\n\t\t\tnotifications.push(...(notificationsStore.pendingNotificationsForViews[view] ?? []));\n\t\t});\n\t\tif (notifications.length) {\n\t\t\tnotifications.forEach((notification) => {\n\t\t\t\t// Notifications show on top of each other without this timeout\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tshowMessage(notification);\n\t\t\t\t}, 5);\n\t\t\t});\n\t\t\t// Clear the queue once all notifications are shown\n\t\t\tnotificationsStore.setNotificationsForView(VIEWS.WORKFLOW, []);\n\t\t}\n\t}\n\n\treturn {\n\t\tshowMessage,\n\t\tshowToast,\n\t\tshowError,\n\t\tclearAllStickyNotifications,\n\t\tshowNotificationForViews,\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useToast.mjs","names":["registeredNotify: NotifyFn | undefined","noopHandle: NotificationHandle","noopNotify: NotifyFn","stickyNotificationQueue: NotificationHandle[]","messageDefaults: Partial<Omit<NotificationOptions, 'message'>>","messageForTelemetry: string","notification: NotificationHandle"],"sources":["../src/useToast.ts"],"sourcesContent":["import { VIEWS } from '@n8n/frontend-constants/views';\nimport { APP_Z_INDEXES } from '@n8n/frontend-constants/z-indexes';\nimport { sanitizeHtml } from '@n8n/frontend-utils/htmlUtils';\nimport { useI18n } from '@n8n/i18n';\nimport { computed } from 'vue';\nimport { useRoute } from 'vue-router';\n\nimport type { NotificationOptions, NotificationType } from './types/notification';\nimport { useExternalHooks } from './useExternalHooks';\nimport { useTelemetry } from './useTelemetry';\n\nexport type {\n\tNotificationOptions,\n\tNotificationPosition,\n\tNotificationType,\n} from './types/notification';\n\n/**\n * Handle returned by the notification function. Declared locally so the DTS\n * build stays free of the full element-plus type graph.\n */\nexport interface NotificationHandle {\n\tclose: () => void;\n}\n\n/**\n * Notification function contract — the app's wrapper around `ElNotification`.\n * Registered at bootstrap via {@link setNotify}; this package owns only the\n * contract.\n *\n * Returning `undefined` means the app declined to show this notification — today\n * that is notification suppression, which lives at the registration site rather\n * than here. `showMessage` treats it as \"dropped\": no sticky-queue\n * entry, no error telemetry, and a no-op handle to the caller.\n */\ntype NotifyFn = (options: Record<string, unknown>) => NotificationHandle | undefined;\n\nlet registeredNotify: NotifyFn | undefined;\n\n/**\n * Register the notification function. Called once at bootstrap by\n * `editor-ui` (passing a suppression-aware wrapper around `ElNotification`) so\n * `useToast` can issue notifications without importing element-plus directly —\n * keeping the DTS build lightweight.\n *\n * This is the *only* toast dependency the app registers. Whether a notification\n * is actually shown is the notifier's decision, so if you are chasing a toast\n * that never appeared, look at the registration site, not here.\n */\nexport function setNotify(fn: NotifyFn): void {\n\tregisteredNotify = fn;\n}\n\nconst noopHandle: NotificationHandle = { close() {} };\nconst noopNotify: NotifyFn = () => noopHandle;\n\nlet warnedAboutMissingNotify = false;\n\nfunction resolveNotify(): NotifyFn {\n\tif (registeredNotify) return registeredNotify;\n\n\t// Falling back means bootstrap never registered. The toast is dropped rather\n\t// than shown, so warn once in dev instead of failing silent.\n\tif (import.meta.env.DEV && !warnedAboutMissingNotify) {\n\t\twarnedAboutMissingNotify = true;\n\t\tconsole.warn(\n\t\t\t'[useToast] No notification function registered; toasts will not render. Call setNotify() at app bootstrap.',\n\t\t);\n\t}\n\treturn noopNotify;\n}\n\nconst stickyNotificationQueue: NotificationHandle[] = [];\n\nexport function useToast() {\n\tconst telemetry = useTelemetry();\n\tconst route = useRoute();\n\tconst workflowId = computed(() => {\n\t\tif (route?.name === VIEWS.DEMO || route?.name === VIEWS.DEMO_DIFF) return 'demo';\n\t\tconst id = route?.params?.workflowId;\n\t\treturn (Array.isArray(id) ? id[0] : id) ?? '';\n\t});\n\tconst externalHooks = useExternalHooks();\n\tconst i18n = useI18n();\n\n\tfunction causedByCredential(message: string | undefined) {\n\t\tif (!message || typeof message !== 'string') return false;\n\n\t\treturn message.includes('Credentials for') && message.includes('are not set');\n\t}\n\n\tfunction showMessage(messageData: Partial<NotificationOptions>, track = true) {\n\t\t// Resolved per call, not once per `useToast()`: a composable captured before\n\t\t// bootstrap registers would otherwise stay bound to the no-op for its whole\n\t\t// lifetime, silently dropping toasts.\n\t\tconst notify = resolveNotify();\n\n\t\tconst messageDefaults: Partial<Omit<NotificationOptions, 'message'>> = {\n\t\t\tdangerouslyUseHTMLString: true,\n\t\t\tposition: 'bottom-right',\n\t\t\t// Layer above NDV and modal overlays, sourced from the shared scale.\n\t\t\tzIndex: APP_Z_INDEXES.TOASTS,\n\t\t\tappendTo: '#n8n-app',\n\t\t\tcustomClass: 'content-toast',\n\t\t};\n\t\tconst { message, title } = messageData;\n\t\tconst params = { ...messageDefaults, ...messageData };\n\n\t\tif (typeof message === 'string') {\n\t\t\tparams.message = sanitizeHtml(message);\n\t\t}\n\n\t\tif (typeof title === 'string') {\n\t\t\tparams.title = sanitizeHtml(title);\n\t\t}\n\n\t\tconst notification = notify(params as unknown as Record<string, unknown>);\n\n\t\t// The app declined to show it (suppression). Return before the sticky queue\n\t\t// and before error telemetry, so a dropped toast leaves no trace — exactly\n\t\t// what the removed in-package suppression branch did.\n\t\tif (!notification) return noopHandle;\n\n\t\tif (params.duration === 0) {\n\t\t\tstickyNotificationQueue.push(notification);\n\t\t}\n\n\t\tif (params.type === 'error' && track) {\n\t\t\t// Extract string message for telemetry - don't send VNode objects as they have circular refs\n\t\t\tlet messageForTelemetry: string;\n\t\t\tif (typeof params.message === 'string') {\n\t\t\t\tmessageForTelemetry = params.message;\n\t\t\t} else if (\n\t\t\t\tparams.message &&\n\t\t\t\ttypeof params.message === 'object' &&\n\t\t\t\t'props' in params.message &&\n\t\t\t\tparams.message.props\n\t\t\t) {\n\t\t\t\t// Extract error message from VNode props (e.g., NodeExecutionErrorMessage component)\n\t\t\t\tconst props = params.message.props;\n\t\t\t\tconst hasErrorMessage =\n\t\t\t\t\ttypeof props === 'object' && props !== null && 'errorMessage' in props;\n\t\t\t\tconst hasMessage = typeof props === 'object' && props !== null && 'message' in props;\n\n\t\t\t\tif (hasErrorMessage) {\n\t\t\t\t\tmessageForTelemetry = String(props.errorMessage);\n\t\t\t\t} else if (hasMessage) {\n\t\t\t\t\tmessageForTelemetry = String(props.message);\n\t\t\t\t} else {\n\t\t\t\t\tmessageForTelemetry = 'Unknown error';\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tmessageForTelemetry = 'Unknown error';\n\t\t\t}\n\n\t\t\ttelemetry.track('Instance FE emitted error', {\n\t\t\t\terror_title: params.title,\n\t\t\t\terror_message: messageForTelemetry,\n\t\t\t\tcaused_by_credential: causedByCredential(messageForTelemetry),\n\t\t\t\tworkflow_id: workflowId.value,\n\t\t\t});\n\t\t}\n\n\t\treturn notification;\n\t}\n\n\tfunction showToast(config: {\n\t\ttitle: string;\n\t\tmessage: NotificationOptions['message'];\n\t\tonClick?: (event?: MouseEvent) => void;\n\t\tonClose?: () => void;\n\t\tduration?: number;\n\t\tcustomClass?: string;\n\t\tcloseOnClick?: boolean;\n\t\ttype?: NotificationType;\n\t}) {\n\t\t// eslint-disable-next-line prefer-const\n\t\tlet notification: NotificationHandle;\n\t\tif (config.closeOnClick) {\n\t\t\tconst originalOnClick = config.onClick;\n\t\t\tconfig.onClick = () => {\n\t\t\t\tif (notification) {\n\t\t\t\t\tnotification.close();\n\t\t\t\t}\n\n\t\t\t\tif (originalOnClick) {\n\t\t\t\t\toriginalOnClick();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\tnotification = showMessage({\n\t\t\ttitle: config.title,\n\t\t\tmessage: config.message,\n\t\t\tonClick: config.onClick,\n\t\t\tonClose: config.onClose,\n\t\t\tduration: config.duration,\n\t\t\tcustomClass: config.customClass,\n\t\t\ttype: config.type,\n\t\t});\n\n\t\treturn notification;\n\t}\n\n\tfunction collapsableDetails(description: string) {\n\t\tconst errorDescription =\n\t\t\tdescription.length > 500 ? `${description.slice(0, 500)}...` : description;\n\n\t\treturn `\n\t\t\t\t<br>\n\t\t\t\t<br>\n\t\t\t\t<details>\n\t\t\t\t\t<summary\n\t\t\t\t\t\tstyle=\"color: #ff6d5a; font-weight: bold; cursor: pointer;\"\n\t\t\t\t\t>\n\t\t\t\t\t\t${i18n.baseText('showMessage.showDetails')}\n\t\t\t\t\t</summary>\n\t\t\t\t\t<p>${errorDescription}</p>\n\t\t\t\t</details>\n\t\t\t`;\n\t}\n\n\tfunction showError(\n\t\te: unknown,\n\t\ttitle: string,\n\t\toptions?: { message?: string; description?: string },\n\t) {\n\t\tconst error = e as Error & { description?: string };\n\t\tconst message = options?.message;\n\t\tconst description = options?.description ?? error.description;\n\t\tconst messageLine = message ? `${message}<br/>` : '';\n\t\tshowMessage(\n\t\t\t{\n\t\t\t\ttitle,\n\t\t\t\tmessage: `\n\t\t\t\t\t${messageLine}\n\t\t\t\t\t<i>${error.message}</i>\n\t\t\t\t\t${description ? collapsableDetails(description) : ''}`,\n\t\t\t\ttype: 'error',\n\t\t\t\tduration: 0,\n\t\t\t},\n\t\t\tfalse,\n\t\t);\n\n\t\tvoid externalHooks.run('showMessage.showError', {\n\t\t\ttitle,\n\t\t\tmessage,\n\t\t\terrorMessage: error.message,\n\t\t});\n\n\t\ttelemetry.track('Instance FE emitted error', {\n\t\t\terror_title: title,\n\t\t\terror_description: message,\n\t\t\terror_message: error.message,\n\t\t\tcaused_by_credential: causedByCredential(error.message),\n\t\t\tworkflow_id: workflowId.value,\n\t\t});\n\t}\n\n\tfunction clearAllStickyNotifications() {\n\t\tstickyNotificationQueue.forEach((notification) => {\n\t\t\tif (notification) {\n\t\t\t\tnotification.close();\n\t\t\t}\n\t\t});\n\n\t\tstickyNotificationQueue.length = 0;\n\t}\n\n\treturn {\n\t\tshowMessage,\n\t\tshowToast,\n\t\tshowError,\n\t\tclearAllStickyNotifications,\n\t};\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@n8n/composables",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.24.0",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
7
|
-
"
|
|
8
|
-
"
|
|
7
|
+
"LICENSE.md",
|
|
8
|
+
"LICENSE_EE.md"
|
|
9
9
|
],
|
|
10
10
|
"exports": {
|
|
11
11
|
"./*": {
|
|
@@ -19,12 +19,11 @@
|
|
|
19
19
|
"lodash": "4.18.1",
|
|
20
20
|
"vue": "^3.5.13",
|
|
21
21
|
"vue-router": "^4.5.0",
|
|
22
|
-
"@n8n/
|
|
22
|
+
"@n8n/api-types": "1.34.0",
|
|
23
|
+
"@n8n/frontend-constants": "0.3.0",
|
|
23
24
|
"@n8n/frontend-utils": "0.2.0",
|
|
24
|
-
"@n8n/
|
|
25
|
-
"
|
|
26
|
-
"@n8n/stores": "2.33.0",
|
|
27
|
-
"n8n-workflow": "2.33.0"
|
|
25
|
+
"@n8n/i18n": "2.34.0",
|
|
26
|
+
"n8n-workflow": "2.34.0"
|
|
28
27
|
},
|
|
29
28
|
"devDependencies": {
|
|
30
29
|
"@pinia/testing": "^0.1.6",
|
|
@@ -42,9 +41,9 @@
|
|
|
42
41
|
"vitest": "^4.1.9",
|
|
43
42
|
"vue-tsc": "^2.2.8",
|
|
44
43
|
"@n8n/eslint-config": "0.0.1",
|
|
45
|
-
"@n8n/telemetry": "1.1.0",
|
|
46
|
-
"@n8n/vitest-config": "1.19.0",
|
|
47
44
|
"@n8n/playwright-janitor": "0.1.0",
|
|
45
|
+
"@n8n/telemetry": "1.2.0",
|
|
46
|
+
"@n8n/vitest-config": "1.19.0",
|
|
48
47
|
"@n8n/typescript-config": "1.9.0"
|
|
49
48
|
},
|
|
50
49
|
"license": "SEE LICENSE IN LICENSE.md",
|