@gandalan/weblibs 2.0.1 → 2.0.4

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.
@@ -1,7 +1,31 @@
1
1
  /**
2
2
  * @typedef {import('../fluentApi.js').FluentApi} FluentApi
3
- * @typedef {Object & { AnpassungGuid?: string, anpassungGuid?: string }} AnpassungDTO
4
- * @typedef {Object & { AnpassungVorlageGuid?: string, anpassungVorlageGuid?: string }} AnpassungVorlageDTO
3
+ */
4
+
5
+ /**
6
+ * @typedef {Object} AnpassungDTO
7
+ * @property {string} AnpassungGuid
8
+ * @property {string} Art
9
+ * @property {boolean} GiltFuerBesitzer
10
+ * @property {boolean} GiltFuerAlleUntermandanten
11
+ * @property {boolean} GiltFuerZielMandant
12
+ * @property {string} ZielMandantGuid
13
+ * @property {string} Content
14
+ * @property {string} WarengruppeGuid
15
+ * @property {string} ArtikelGuid
16
+ * @property {number} Version
17
+ * @property {string} ChangedDate - ISO date string
18
+ */
19
+
20
+ /**
21
+ * @typedef {Object} AnpassungVorlageDTO
22
+ * @property {string} AnpassungVorlageGuid
23
+ * @property {string} Art
24
+ * @property {string} Name
25
+ * @property {string} Beschreibung
26
+ * @property {string} Content
27
+ * @property {number} Version
28
+ * @property {string} ChangedDate - ISO date string
5
29
  */
6
30
 
7
31
  /**
@@ -6,8 +6,7 @@
6
6
  * @typedef {import('../dtos/produktion.js').ProduktionsDatenDTO} ProduktionsDatenDTO
7
7
  * @typedef {import('../dtos/index.js').AVReserviertItemDTO} AVReserviertItemDTO
8
8
  * @typedef {import('../dtos/belege.js').CalculationInfoDTO} CalculationInfoDTO
9
- * @typedef {Object} AvReportVorgangRequestDto
10
- * @typedef {Object} AvReportVorgangDto
9
+ * @typedef {import('../dtos/index.js').BeleganschriftDTO} BeleganschriftDTO
11
10
  * @typedef {import('../dtos/produktion.js').SaegeDatenHistorieDTO} SaegeDatenHistorieDTO
12
11
  * @typedef {import('../dtos/produktion.js').SaegeDatenResultDTO} SaegeDatenResultDTO
13
12
  * @typedef {import('../dtos/index.js').MaterialBearbeitungsMethodeDTO} MaterialBearbeitungsMethodeDTO
@@ -16,6 +15,41 @@
16
15
  * @typedef {import('../dtos/av.js').SerienMaterialEditDTO} SerienMaterialEditDTO
17
16
  */
18
17
 
18
+ /**
19
+ * @typedef {Object} AvReportVorgangRequestDto
20
+ * @property {Array<string>} VorgangGuids
21
+ */
22
+
23
+ /**
24
+ * Minimalistic DTO for Vorgang in AV reports.
25
+ * @typedef {Object} AvReportVorgangDto
26
+ * @property {string} VorgangGuid
27
+ * @property {number} VorgangsNummer
28
+ * @property {string} Kommission
29
+ * @property {string} Kommission2
30
+ * @property {Array<AvReportBelegDto>} Belege
31
+ * @property {AvReportKontaktDto} Kunde
32
+ */
33
+
34
+ /**
35
+ * Minimalistic DTO for Beleg in AV reports.
36
+ * @typedef {Object} AvReportBelegDto
37
+ * @property {string} BelegGuid
38
+ * @property {BeleganschriftDTO} BelegAdresse
39
+ * @property {BeleganschriftDTO} VersandAdresse
40
+ * @property {boolean} VersandAdresseGleichBelegAdresse
41
+ * @property {string} BelegArt
42
+ * @property {string} Terminwunsch
43
+ * @property {boolean} IstSelbstabholer
44
+ */
45
+
46
+ /**
47
+ * Minimalistic DTO for Kontakt information in AvReportVorgangDto.
48
+ * @typedef {Object} AvReportKontaktDto
49
+ * @property {string} KundenNummer
50
+ * @property {string} Land
51
+ */
52
+
19
53
  /**
20
54
  * AV API - Arbeitsvorbereitung (work preparation) management
21
55
  * @param {FluentApi} fluentApi
@@ -1,6 +1,15 @@
1
1
  /**
2
2
  * @typedef {import('../fluentApi.js').FluentApi} FluentApi
3
+ */
4
+
5
+ /**
3
6
  * @typedef {Object} FileInfoDTO
7
+ * @property {string} FileName
8
+ * @property {number} FileSize
9
+ * @property {string} Modified - ISO date string
10
+ * @property {string} Created - ISO date string
11
+ * @property {string | null} GueltigBis - ISO date string
12
+ * @property {string | null} MandantGuid
4
13
  */
5
14
 
6
15
  /**
@@ -3,11 +3,24 @@
3
3
  * @typedef {import('../dtos/index.js').ChangeDTO} ChangeDTO
4
4
  * @typedef {import('../dtos/index.js').TagInfoDTO} TagInfoDTO
5
5
  * @typedef {import('../dtos/index.js').TagVorlageDTO} TagVorlageDTO
6
- * @typedef {Object} FilterItemDTO
7
6
  * @typedef {import('../dtos/index.js').ChangeInfoDTO} ChangeInfoDTO
8
7
  * @typedef {import('../dtos/index.js').UpdateInfoDTO} UpdateInfoDTO
9
8
  */
10
9
 
10
+ /**
11
+ * @typedef {Object} FilterItemDTO
12
+ * @property {string} FilterGuid
13
+ * @property {string} MandantGuid
14
+ * @property {string} BenutzerGuid
15
+ * @property {string} Title
16
+ * @property {string} Context
17
+ * @property {string} SerializedFilterSetting
18
+ * @property {number} Version
19
+ * @property {string} ChangedDate - ISO date string
20
+ * @property {boolean} IsDeleted
21
+ * @property {number} Reihenfolge
22
+ */
23
+
11
24
  /**
12
25
  * System API - System administration and configuration
13
26
  * @param {FluentApi} fluentApi
@@ -5,7 +5,7 @@
5
5
  * @typedef {import('../dtos/index.js').UIEingabeFeldInfoDTO} UIEingabeFeldInfoDTO
6
6
  * @typedef {import('../dtos/index.js').TagInfoDTO} TagInfoDTO
7
7
  * @typedef {import('../dtos/index.js').TagVorlageDTO} TagVorlageDTO
8
- * @typedef {Object} FilterItemDTO
8
+ * @typedef {import('./systemApi.js').FilterItemDTO} FilterItemDTO
9
9
  */
10
10
 
11
11
  /**
package/api/fluentApi.js CHANGED
@@ -73,44 +73,47 @@ export function createApi() {
73
73
  },
74
74
 
75
75
  /**
76
- * Sends a GET request, ensuring authentication if needed.
77
- *
78
- * @async
79
- * @param {string} [url=""]
80
- * @param {boolean} [auth=true]
81
- * @returns {Promise<Object>}
82
- */
83
- async get(url = "", auth = true) {
76
+ * Sends a GET request, ensuring authentication if needed.
77
+ *
78
+ * @async
79
+ * @param {string} [url=""]
80
+ * @param {boolean} [auth=true]
81
+ * @param {boolean} [skipResponseParsing=false]
82
+ * @returns {Promise<Object>}
83
+ */
84
+ async get(url = "", auth = true, skipResponseParsing = false) {
84
85
  await this.preCheck(auth);
85
- return await this.createRestClient().get(url);
86
+ return await this.createRestClient().get(url, auth, skipResponseParsing);
86
87
  },
87
88
 
88
89
  /**
89
- * Sends a PUT request with a payload, ensuring authentication if needed.
90
- *
91
- * @async
92
- * @param {string} [url=""]
93
- * @param {Object} [payload={}]
94
- * @param {boolean} [auth=true]
95
- * @returns {Promise<Object>}
96
- */
97
- async put(url = "", payload = {}, auth = true) {
90
+ * Sends a PUT request with a payload, ensuring authentication if needed.
91
+ *
92
+ * @async
93
+ * @param {string} [url=""]
94
+ * @param {Object} [payload={}]
95
+ * @param {boolean} [auth=true]
96
+ * @param {boolean} [skipResponseParsing=false]
97
+ * @returns {Promise<Object>}
98
+ */
99
+ async put(url = "", payload = {}, auth = true, skipResponseParsing = false) {
98
100
  await this.preCheck(auth);
99
- return await this.createRestClient().put(url, payload);
101
+ return await this.createRestClient().put(url, payload, skipResponseParsing);
100
102
  },
101
103
 
102
104
  /**
103
- * Sends a POST request with a payload, ensuring authentication if needed.
104
- *
105
- * @async
106
- * @param {string} [url=""]
107
- * @param {Object} [payload={}]
108
- * @param {boolean} [auth=true]
109
- * @returns {Promise<Object>}
110
- */
111
- async post(url = "", payload = {}, auth = true) {
105
+ * Sends a POST request with a payload, ensuring authentication if needed.
106
+ *
107
+ * @async
108
+ * @param {string} [url=""]
109
+ * @param {Object} [payload={}]
110
+ * @param {boolean} [auth=true]
111
+ * @param {boolean} [skipResponseParsing=false]
112
+ * @returns {Promise<Object>}
113
+ */
114
+ async post(url = "", payload = {}, auth = true, skipResponseParsing = false) {
112
115
  await this.preCheck(auth);
113
- return await this.createRestClient().post(url, payload);
116
+ return await this.createRestClient().post(url, payload, skipResponseParsing);
114
117
  },
115
118
 
116
119
  /**
@@ -118,12 +121,14 @@ export function createApi() {
118
121
  *
119
122
  * @async
120
123
  * @param {string} [url=""]
124
+ * @param {Object|FormData} [payload=null]
121
125
  * @param {boolean} [auth=true]
126
+ * @param {boolean} [skipResponseParsing=false]
122
127
  * @returns {Promise<Object>}
123
128
  */
124
- async delete(url = "", payload = null, auth = true) {
129
+ async delete(url = "", payload = null, auth = true, skipResponseParsing = false) {
125
130
  await this.preCheck(auth);
126
- return await this.createRestClient().delete(url, payload);
131
+ return await this.createRestClient().delete(url, payload, skipResponseParsing);
127
132
  },
128
133
 
129
134
  /**
@@ -60,14 +60,15 @@ export function restClient() {
60
60
  * @async
61
61
  * @param {string} [url=""]
62
62
  * @param {boolean} [auth=true]
63
+ * @param {boolean} [skipResponseParsing=false]
63
64
  * @returns {Promise<any>}
64
65
  */
65
- async get(url = "", auth = true) {
66
+ async get(url = "", auth = true, skipResponseParsing = false) {
66
67
  const finalUrl = `${this.baseUrl}${url}`;
67
68
  const headers = this._createHeaders();
68
69
  const res = await fetch(finalUrl, { method: "GET", headers });
69
70
  if (res.ok) {
70
- return await this._parseReponse(res);
71
+ return skipResponseParsing ? res : await this._parseReponse(res);
71
72
  }
72
73
 
73
74
  throw new Error(`GET ${finalUrl} failed: ${res.status} ${res.statusText}`);
@@ -79,14 +80,15 @@ export function restClient() {
79
80
  * @async
80
81
  * @param {string} [url=""]
81
82
  * @param {Object} [payload={}]
83
+ * @param {boolean} [skipResponseParsing=false]
82
84
  * @returns {Promise<any>}
83
85
  */
84
- async put(url = "", payload = {}) {
86
+ async put(url = "", payload = {}, skipResponseParsing = false) {
85
87
  const finalUrl = `${this.baseUrl}${url}`;
86
88
  const headers = this._createHeaders("application/json");
87
89
  const res = await fetch(finalUrl, { method: "PUT", body: JSON.stringify(payload), headers });
88
90
  if (res.ok) {
89
- return await this._parseReponse(res);
91
+ return skipResponseParsing ? res : await this._parseReponse(res);
90
92
  }
91
93
 
92
94
  throw new Error(`PUT ${finalUrl} failed: ${res.status} ${res.statusText}`);
@@ -98,9 +100,10 @@ export function restClient() {
98
100
  * @async
99
101
  * @param {string} [url=""]
100
102
  * @param {Object|FormData} [payload={}]
103
+ * @param {boolean} [skipResponseParsing=false]
101
104
  * @returns {Promise<any>}
102
105
  */
103
- async post(url = "", payload = {}) {
106
+ async post(url = "", payload = {}, skipResponseParsing = false) {
104
107
  const finalUrl = `${this.baseUrl}${url}`;
105
108
  let headers;
106
109
 
@@ -116,7 +119,7 @@ export function restClient() {
116
119
 
117
120
  const res = await fetch(finalUrl, { method: "POST", body, headers });
118
121
  if (res.ok) {
119
- return await this._parseReponse(res);
122
+ return skipResponseParsing ? res : await this._parseReponse(res);
120
123
  }
121
124
 
122
125
  throw new Error(`POST ${finalUrl} failed: ${res.status} ${res.statusText}`);
@@ -127,9 +130,11 @@ export function restClient() {
127
130
  *
128
131
  * @async
129
132
  * @param {string} [url=""]
133
+ * @param {Object|FormData} [payload=null]
134
+ * @param {boolean} [skipResponseParsing=false]
130
135
  * @returns {Promise<any>}
131
136
  */
132
- async delete(url = "", payload = null) {
137
+ async delete(url = "", payload = null, skipResponseParsing = false) {
133
138
  const finalUrl = `${this.baseUrl}${url}`;
134
139
  const hasBody = payload !== null && payload !== undefined;
135
140
  const isFormData = payload instanceof FormData;
@@ -137,7 +142,7 @@ export function restClient() {
137
142
  const body = !hasBody ? undefined : isFormData ? payload : JSON.stringify(payload);
138
143
  const res = await fetch(finalUrl, { method: "DELETE", headers, body });
139
144
  if (res.ok) {
140
- return await this._parseReponse(res);
145
+ return skipResponseParsing ? res : await this._parseReponse(res);
141
146
  }
142
147
 
143
148
  throw new Error(`DELETE ${finalUrl} failed: ${res.status} ${res.statusText}`);
@@ -96,6 +96,74 @@
96
96
  * @property {NeherApp3ErfassungCache} erfassung
97
97
  */
98
98
 
99
+ /**
100
+ * A single message envelope delivered to handlers.
101
+ * @typedef {Object} NeherMessage
102
+ * @property {string} id - Unique message id (`crypto.randomUUID`).
103
+ * @property {string} type - Message kind, e.g. `"artikel.selected"`.
104
+ * @property {string | null} to - Target module name (directed) or `null` (broadcast).
105
+ * @property {string | null} from - Sender module name (stamped by the endpoint) or `null`.
106
+ * @property {any} payload - Arbitrary payload.
107
+ * @property {number} ts - Timestamp (`Date.now`).
108
+ */
109
+
110
+ /**
111
+ * Handler invoked with the full message envelope.
112
+ * @callback MessageHandler
113
+ * @param {NeherMessage} message
114
+ * @returns {void}
115
+ */
116
+
117
+ /**
118
+ * Subscription type pattern: exact (`"a.b"`), prefix glob (`"a.*"`), all (`"*"`)
119
+ * or a list of patterns.
120
+ * @typedef {string | string[]} TypePattern
121
+ */
122
+
123
+ /**
124
+ * Options for `send`/`broadcast`.
125
+ * @typedef {Object} SendOptions
126
+ * @property {string} [from] - Sender module name (bus-level `send`/`broadcast` only; set automatically via an endpoint).
127
+ * @property {boolean} [retain] - Keep this `(to, type)` as a last value; subscribers that register later receive it immediately. Default `false`.
128
+ * @property {boolean} [requireRecipient] - If nobody received it, call `onUndeliverable` instead of silently dropping. Default `false`.
129
+ * @property {boolean} [deliverWhenAvailable] - If nobody is listening, buffer the directed message and deliver it when the target registers. Default `false`.
130
+ * @property {boolean} [echo] - For broadcast: also deliver to the sender itself. Default `false`.
131
+ * @property {number} [ttlMs] - Lifetime for buffered messages. Default `30000`.
132
+ * @property {(message: NeherMessage) => void} [onUndeliverable] - Callback invoked with the envelope when `requireRecipient` and no recipient.
133
+ */
134
+
135
+ /**
136
+ * Delivery information returned by `send`/`broadcast` — never the result of a handler.
137
+ * @typedef {Object} Delivery
138
+ * @property {boolean} delivered - At least one recipient was reached.
139
+ * @property {number} recipients - Number of distinct modules delivered to.
140
+ * @property {boolean} queued - Buffered for a later recipient.
141
+ */
142
+
143
+ /**
144
+ * A registered endpoint, returned by `messages.register`. `register` is
145
+ * idempotent; each handle's `dispose` only removes subscriptions made through it.
146
+ * @typedef {Object} Endpoint
147
+ * @property {string} name - The module name of this endpoint.
148
+ * @property {(type: TypePattern, handler: MessageHandler) => (() => void)} on - Subscribe; returns an unsubscribe function.
149
+ * @property {(to: string, type: string, payload?: any, options?: SendOptions) => Delivery} send - Directed message (`from` is stamped automatically).
150
+ * @property {(type: string, payload?: any, options?: SendOptions) => Delivery} broadcast - Broadcast (`from` is stamped automatically).
151
+ * @property {() => void} dispose - Remove all subscriptions created through this handle.
152
+ */
153
+
154
+ /**
155
+ * In-realm message bus for module-to-module communication, exposed at
156
+ * `neherapp3.messages`. Messaging, not RPC: `send`/`broadcast` return delivery
157
+ * information, never a handler's result.
158
+ * @typedef {Object} NeherApp3Messages
159
+ * @property {(moduleName: string) => Endpoint} register - Register a module as a reachable endpoint.
160
+ * @property {(to: string, type: string, payload?: any, options?: SendOptions) => Delivery} send - Directed message (`from` via `options.from`).
161
+ * @property {(type: string, payload?: any, options?: SendOptions) => Delivery} broadcast - Broadcast to all subscribers (`from` via `options.from`).
162
+ * @property {(moduleName: string) => boolean} isReachable - Does the module have at least one live handler?
163
+ * @property {(moduleName: string) => boolean} isKnown - Is the module registered (loaded via `addApp`)?
164
+ * @property {string[]} reachable - Reactive list of all currently reachable module names.
165
+ */
166
+
99
167
  /**
100
168
  * @typedef {Object} NeherApp3
101
169
  * @property {(menuItem: NeherApp3MenuItem) => void} addMenuItem - Adds a menu item. If an item with the same `id` already exists it is replaced.
@@ -105,6 +173,7 @@
105
173
  * @property {(message: string, type?: NeherApp3NotifyType, cb?: function) => void} notify - Shows a notification. Type defaults to 0 (info). Callback is optional.
106
174
  * @property {NeherApp3ApiCollection} api
107
175
  * @property {NeherApp3CacheCollection} cache
176
+ * @property {NeherApp3Messages} messages - In-realm message bus for module-to-module communication.
108
177
  * @property {boolean} isEmbedded - Indicates if the app is embedded inside i3
109
178
  */
110
179
 
package/index.d.ts CHANGED
@@ -93,6 +93,30 @@ export type AnpassungApi = {
93
93
  vorlage: { getAll: () => Promise<AnpassungVorlageDTO[]>; get: (guid: string) => Promise<AnpassungVorlageDTO>; save: (dto: AnpassungVorlageDTO) => Promise<void>; delete: (guid: string) => Promise<void> };
94
94
  };
95
95
 
96
+ export type AnpassungDTO = {
97
+ AnpassungGuid: string;
98
+ Art: string;
99
+ GiltFuerBesitzer: boolean;
100
+ GiltFuerAlleUntermandanten: boolean;
101
+ GiltFuerZielMandant: boolean;
102
+ ZielMandantGuid: string;
103
+ Content: string;
104
+ WarengruppeGuid: string;
105
+ ArtikelGuid: string;
106
+ Version: number;
107
+ ChangedDate: string;
108
+ };
109
+
110
+ export type AnpassungVorlageDTO = {
111
+ AnpassungVorlageGuid: string;
112
+ Art: string;
113
+ Name: string;
114
+ Beschreibung: string;
115
+ Content: string;
116
+ Version: number;
117
+ ChangedDate: string;
118
+ };
119
+
96
120
  export type ApiVersionDTO = {
97
121
  Version: string;
98
122
  Environment: string;
@@ -212,6 +236,34 @@ export type AvApi = {
212
236
  material: { serieBerechnen: (serieGuid: string) => Promise<void>; getForSerie: (serieGuid: string) => Promise<MaterialbedarfDTO[]>; getOffenerBedarfV2: (serieGuid: string, filterCsvExportedMaterial?: boolean) => Promise<MaterialbedarfDTO[]>; getOffenerBedarf: (serieGuid: string) => Promise<MaterialbedarfDTO[]>; resetForSerie: (serieGuid: string) => Promise<void>; berechnenForFunction: (serieGuid: string, mandantId: number) => Promise<string[]>; resetFromAvPosForFunction: (avPosGuid: string, mandantId: number) => Promise<string[]>; addOrUpdate: (dto: MaterialbedarfDTO) => Promise<SerienMaterialEditDTO>; delete: (materialbedarfGuid: string) => Promise<void> };
213
237
  };
214
238
 
239
+ export type AvReportBelegDto = {
240
+ BelegGuid: string;
241
+ BelegAdresse: BeleganschriftDTO;
242
+ VersandAdresse: BeleganschriftDTO;
243
+ VersandAdresseGleichBelegAdresse: boolean;
244
+ BelegArt: string;
245
+ Terminwunsch: string;
246
+ IstSelbstabholer: boolean;
247
+ };
248
+
249
+ export type AvReportKontaktDto = {
250
+ KundenNummer: string;
251
+ Land: string;
252
+ };
253
+
254
+ export type AvReportVorgangDto = {
255
+ VorgangGuid: string;
256
+ VorgangsNummer: number;
257
+ Kommission: string;
258
+ Kommission2: string;
259
+ Belege: Array<AvReportBelegDto>;
260
+ Kunde: AvReportKontaktDto;
261
+ };
262
+
263
+ export type AvReportVorgangRequestDto = {
264
+ VorgangGuids: Array<string>;
265
+ };
266
+
215
267
  export type AVReserviertItemDTO = {
216
268
  Variante: string;
217
269
  ArtikelNummer: string;
@@ -853,6 +905,12 @@ export type CsvExportCombinationDTO = {
853
905
  ExportFarbArten: ExportFarbArt[];
854
906
  };
855
907
 
908
+ export type Delivery = {
909
+ delivered: boolean;
910
+ recipients: number;
911
+ queued: boolean;
912
+ };
913
+
856
914
  export type DevOpsStatusDTO = {
857
915
  Env: string;
858
916
  DbInfo: string;
@@ -860,6 +918,14 @@ export type DevOpsStatusDTO = {
860
918
  PendingMigrations: string[];
861
919
  };
862
920
 
921
+ export type Endpoint = {
922
+ name: string;
923
+ on: (type: TypePattern, handler: MessageHandler) => (() => void);
924
+ send: (to: string, type: string, payload?: any, options?: SendOptions) => Delivery;
925
+ broadcast: (type: string, payload?: any, options?: SendOptions) => Delivery;
926
+ dispose: () => void;
927
+ };
928
+
863
929
  export type EnvironmentConfig = {
864
930
  name: string;
865
931
  version: string;
@@ -1018,6 +1084,28 @@ export type FileApi = {
1018
1084
  data: { get: (filename: string) => Promise<Uint8Array>; getList: (directory?: string) => Promise<FileInfoDTO[]>; save: (fileName: string, data: Uint8Array) => Promise<void>; delete: (filename: string) => Promise<void> };
1019
1085
  };
1020
1086
 
1087
+ export type FileInfoDTO = {
1088
+ FileName: string;
1089
+ FileSize: number;
1090
+ Modified: string;
1091
+ Created: string;
1092
+ GueltigBis: string | null;
1093
+ MandantGuid: string | null;
1094
+ };
1095
+
1096
+ export type FilterItemDTO = {
1097
+ FilterGuid: string;
1098
+ MandantGuid: string;
1099
+ BenutzerGuid: string;
1100
+ Title: string;
1101
+ Context: string;
1102
+ SerializedFilterSetting: string;
1103
+ Version: number;
1104
+ ChangedDate: string;
1105
+ IsDeleted: boolean;
1106
+ Reihenfolge: number;
1107
+ };
1108
+
1021
1109
  export type FluentApi = {
1022
1110
  baseUrl: string;
1023
1111
  authManager: FluentAuthManager|null;
@@ -1841,7 +1929,7 @@ export type MaterialBearbeitungsMethodeDTO = {
1841
1929
  ChangedDate: string;
1842
1930
  };
1843
1931
 
1844
- export type MaterialbedarfCutOptimization = object.<string, any>;
1932
+ export type MaterialbedarfCutOptimization = Record<string, any>;
1845
1933
 
1846
1934
  export type MaterialbedarfDTO = {
1847
1935
  MaterialBedarfGuid: string;
@@ -1942,6 +2030,8 @@ export type MaterialDTO = {
1942
2030
  MoeglicheBearbeitungsMethoden: Array<string>;
1943
2031
  };
1944
2032
 
2033
+ export type MessageHandler = (message: NeherMessage) => void;
2034
+
1945
2035
  export type NachrichtenDTO = {
1946
2036
  NachrichtGuid: string;
1947
2037
  MandantGuid: string;
@@ -1961,6 +2051,7 @@ export type NeherApp3 = {
1961
2051
  notify: (message: string, type?: NeherApp3NotifyType, cb?: Function) => void;
1962
2052
  api: NeherApp3ApiCollection;
1963
2053
  cache: NeherApp3CacheCollection;
2054
+ messages: NeherApp3Messages;
1964
2055
  isEmbedded: boolean;
1965
2056
  };
1966
2057
 
@@ -2001,6 +2092,15 @@ export type NeherApp3MenuItem = {
2001
2092
  separator?: boolean;
2002
2093
  };
2003
2094
 
2095
+ export type NeherApp3Messages = {
2096
+ register: (moduleName: string) => Endpoint;
2097
+ send: (to: string, type: string, payload?: any, options?: SendOptions) => Delivery;
2098
+ broadcast: (type: string, payload?: any, options?: SendOptions) => Delivery;
2099
+ isReachable: (moduleName: string) => boolean;
2100
+ isKnown: (moduleName: string) => boolean;
2101
+ reachable: string[];
2102
+ };
2103
+
2004
2104
  export type NeherApp3Module = {
2005
2105
  moduleName: string;
2006
2106
  setup?: (context: NeherApp3SetupContext) => void | Promise<void>;
@@ -2021,6 +2121,15 @@ export type NeherApp3Props = {
2021
2121
 
2022
2122
  export type NeherApp3SetupContext = NeherApp3Props & { neherapp3: NeherApp3 };
2023
2123
 
2124
+ export type NeherMessage = {
2125
+ id: string;
2126
+ type: string;
2127
+ to: string | null;
2128
+ from: string | null;
2129
+ payload: any;
2130
+ ts: number;
2131
+ };
2132
+
2024
2133
  export type OberflaecheDTO = {
2025
2134
  OberflaecheGuid: string;
2026
2135
  Bezeichnung: string;
@@ -2095,11 +2204,11 @@ export type PreisermittlungsEinstellungenDTO = {
2095
2204
  EndpreisRundungsModus: string;
2096
2205
  SonderfarbZuschlaege: string;
2097
2206
  BruttoPreisErmitteln: boolean;
2098
- AufpreisAnpassungen: object.<string, AufpreisAnpassungDTO[]>;
2099
- PreisfaktorAnpassungen: object.<string, number>;
2100
- ZuschnittpreisfaktorAnpassungen: object.<string, number>;
2101
- AufpreisfaktorAnpassungen: object.<string, number>;
2102
- GrenzfreigabeAnpassungen: object.<string, boolean>;
2207
+ AufpreisAnpassungen: Record<string, AufpreisAnpassungDTO[]>;
2208
+ PreisfaktorAnpassungen: Record<string, number>;
2209
+ ZuschnittpreisfaktorAnpassungen: Record<string, number>;
2210
+ AufpreisfaktorAnpassungen: Record<string, number>;
2211
+ GrenzfreigabeAnpassungen: Record<string, boolean>;
2103
2212
  MbAufpreis: number;
2104
2213
  Mb_v_Fix_Aufpreis: number|null;
2105
2214
  Mb_Klebeband_Aufpreis: number|null;
@@ -2548,6 +2657,16 @@ export type SchnittKonturOperationDTO = {
2548
2657
 
2549
2658
  export type SchnittoptimierungsOptionen = ('Keine'|'Lieferdatum'|'Serie'|'FarbeOberflaeche');
2550
2659
 
2660
+ export type SendOptions = {
2661
+ from?: string;
2662
+ retain?: boolean;
2663
+ requireRecipient?: boolean;
2664
+ deliverWhenAvailable?: boolean;
2665
+ echo?: boolean;
2666
+ ttlMs?: number;
2667
+ onUndeliverable?: (message: NeherMessage) => void;
2668
+ };
2669
+
2551
2670
  export type SerieAuslastungDTO = {
2552
2671
  IstSumme: boolean;
2553
2672
  Produktfamilie: string;
@@ -2727,6 +2846,8 @@ export type TemplateDTO = {
2727
2846
  Benutzer: string;
2728
2847
  };
2729
2848
 
2849
+ export type TypePattern = string | string[];
2850
+
2730
2851
  export type UiApi = {
2731
2852
  getAllUiDefinitions: () => Promise<UIDefinitionDTO[]>;
2732
2853
  getUiDefinition: (guid: string) => Promise<UIDefinitionDTO>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gandalan/weblibs",
3
- "version": "2.0.1",
3
+ "version": "2.0.4",
4
4
  "description": "WebLibs for Gandalan JS/TS projects",
5
5
  "keywords": [
6
6
  "gandalan"
@@ -23,14 +23,14 @@
23
23
  "dependencies": {
24
24
  "@mdi/js": "^7.4.47",
25
25
  "jwt-decode": "^4.0.0",
26
- "validator": "^13.12.0"
26
+ "validator": "^13.15.35"
27
27
  },
28
28
  "devDependencies": {
29
- "@babel/core": "^7.26.9",
30
- "@babel/eslint-parser": "^7.26.8",
31
- "@eslint/js": "^9.21.0",
32
- "eslint": "^9.21.0",
33
- "globals": "^15.15.0"
29
+ "@babel/core": "^8.0.1",
30
+ "@babel/eslint-parser": "^8.0.1",
31
+ "@eslint/js": "^10.0.1",
32
+ "eslint": "^10.5.0",
33
+ "globals": "^17.7.0"
34
34
  },
35
35
  "publishConfig": {
36
36
  "access": "public",
@@ -429,7 +429,7 @@ function parseObjectLiteralProperties(objectSource, scopeTypeMap) {
429
429
 
430
430
  index = skipWhitespaceAndComments(objectSource, index);
431
431
 
432
- let typeExpression = "any";
432
+ let typeExpression;
433
433
  let optional = false;
434
434
 
435
435
  if (objectSource[index] === ":") {
@@ -858,35 +858,56 @@ function isSimpleImportAlias(typeExpression) {
858
858
  return simpleImportTypePattern.test(typeExpression.replace(/\s+/g, ""));
859
859
  }
860
860
 
861
+ function splitBlockByTagBoundaries(normalizedBlock) {
862
+ const tagPattern = /@(?:typedef|callback)\b/g;
863
+ const startIndices = [];
864
+ let match;
865
+
866
+ while ((match = tagPattern.exec(normalizedBlock)) !== null) {
867
+ startIndices.push(match.index);
868
+ }
869
+
870
+ if (startIndices.length <= 1) {
871
+ return [normalizedBlock];
872
+ }
873
+
874
+ return startIndices.map((startIndex, position) => {
875
+ const endIndex = position + 1 < startIndices.length ? startIndices[position + 1] : normalizedBlock.length;
876
+ return normalizedBlock.slice(startIndex, endIndex);
877
+ });
878
+ }
879
+
861
880
  function extractPublicTypeEntries(source, filePath) {
862
881
  const entries = [];
863
882
 
864
883
  for (const block of getJSDocBlocks(source).map(normalizeJSDocBlock)) {
865
- const typedefEntry = extractTypedefEntry(block);
884
+ for (const segment of splitBlockByTagBoundaries(block)) {
885
+ const typedefEntry = extractTypedefEntry(segment);
866
886
 
867
- if (typedefEntry) {
868
- const inferredCreateApiName = typedefEntry.typeExpression.match(returnTypeOfCreateApiPattern)?.[1] ?? null;
887
+ if (typedefEntry) {
888
+ const inferredCreateApiName = typedefEntry.typeExpression.match(returnTypeOfCreateApiPattern)?.[1] ?? null;
869
889
 
870
- if (inferredCreateApiName) {
871
- const inferredObjectEntry = inferReturnTypeObjectEntry(source, filePath, typedefEntry.name, inferredCreateApiName);
890
+ if (inferredCreateApiName) {
891
+ const inferredObjectEntry = inferReturnTypeObjectEntry(source, filePath, typedefEntry.name, inferredCreateApiName);
872
892
 
873
- if (inferredObjectEntry) {
874
- entries.push(inferredObjectEntry);
875
- continue;
893
+ if (inferredObjectEntry) {
894
+ entries.push(inferredObjectEntry);
895
+ continue;
896
+ }
876
897
  }
877
- }
878
898
 
879
- if (!isSimpleImportAlias(typedefEntry.typeExpression)) {
880
- entries.push({ ...typedefEntry, filePath });
881
- }
899
+ if (!isSimpleImportAlias(typedefEntry.typeExpression)) {
900
+ entries.push({ ...typedefEntry, filePath });
901
+ }
882
902
 
883
- continue;
884
- }
903
+ continue;
904
+ }
885
905
 
886
- const callbackEntry = extractCallbackEntry(block);
906
+ const callbackEntry = extractCallbackEntry(segment);
887
907
 
888
- if (callbackEntry) {
889
- entries.push({ ...callbackEntry, filePath });
908
+ if (callbackEntry) {
909
+ entries.push({ ...callbackEntry, filePath });
910
+ }
890
911
  }
891
912
  }
892
913
 
@@ -940,15 +961,20 @@ function replaceObjectGenerics(typeExpression, transformTypeExpression) {
940
961
  let result = "";
941
962
 
942
963
  for (let index = 0; index < typeExpression.length; index += 1) {
943
- if (!typeExpression.startsWith("Object<", index)) {
964
+ // Support both the TypeScript form (Object<...>) and the dotted JSDoc form (Object.<...>).
965
+ const isDottedForm = typeExpression.startsWith("Object.<", index);
966
+ const isPlainForm = typeExpression.startsWith("Object<", index);
967
+
968
+ if (!isDottedForm && !isPlainForm) {
944
969
  result += typeExpression[index];
945
970
  continue;
946
971
  }
947
972
 
973
+ const openAngleIndex = index + (isDottedForm ? "Object.".length : "Object".length);
948
974
  let angleDepth = 0;
949
975
  let closingIndex = -1;
950
976
 
951
- for (let cursor = index + "Object".length; cursor < typeExpression.length; cursor += 1) {
977
+ for (let cursor = openAngleIndex; cursor < typeExpression.length; cursor += 1) {
952
978
  const character = typeExpression[cursor];
953
979
 
954
980
  if (character === "<") {
@@ -968,7 +994,7 @@ function replaceObjectGenerics(typeExpression, transformTypeExpression) {
968
994
  continue;
969
995
  }
970
996
 
971
- const genericContent = typeExpression.slice(index + "Object<".length, closingIndex);
997
+ const genericContent = typeExpression.slice(openAngleIndex + 1, closingIndex);
972
998
  const genericParts = splitTopLevel(genericContent, ",");
973
999
 
974
1000
  if (genericParts.length === 2) {