@notix-hub/sdk 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,7 +7,7 @@ JavaScript SDK для **Notix (Нотикс)** — сервиса агрегац
7
7
  ### npm
8
8
 
9
9
  ```bash
10
- npm install @notix/sdk
10
+ npm install @notix-hub/sdk
11
11
  ```
12
12
 
13
13
  ```js
@@ -34,7 +34,7 @@ await notix.notify({
34
34
  Без своего домена — через jsdelivr:
35
35
 
36
36
  ```html
37
- <script src="https://cdn.jsdelivr.net/npm/@notix/sdk/dist/notify.min.js" data-token="ntx_..."></script>
37
+ <script src="https://cdn.jsdelivr.net/npm/@notix-hub/sdk/dist/notify.min.js" data-token="ntx_..."></script>
38
38
  ```
39
39
 
40
40
  ## API
@@ -72,27 +72,51 @@ await notix.notify({
72
72
 
73
73
  ## Автозахват форм
74
74
 
75
- Добавьте `data-notify` к форме, и SDK перехватит `submit`:
75
+ Добавьте `data-notify` к форме, и SDK перехватит `submit`.
76
+
77
+ ### Шаблон (рекомендуется)
76
78
 
77
79
  ```html
78
- <form data-notify data-notify-title="Заявка с лендинга">
79
- <input name="name" data-notify-field="body">
80
- <input name="phone">
80
+ <form data-notify
81
+ data-notify-type="lead"
82
+ data-notify-tag="Сайт"
83
+ data-notify-title="Новая заявка"
84
+ data-notify-template="Имя: {name}\nТелефон: {phone}\nСообщение: {message}">
85
+ <input name="name" placeholder="Ваше имя" required>
86
+ <input name="phone" placeholder="Телефон">
87
+ <textarea name="message" placeholder="Сообщение"></textarea>
81
88
  <button type="submit">Отправить</button>
82
89
  </form>
83
90
  ```
84
91
 
92
+ ### Поля с метками
93
+
94
+ ```html
95
+ <form data-notify data-notify-title="Заявка">
96
+ <input name="name" data-notify-label="Имя">
97
+ <input name="phone" data-notify-label="Телефон">
98
+ <button type="submit">Отправить</button>
99
+ </form>
100
+ ```
101
+
102
+ ### Без шаблона и меток
103
+
104
+ SDK соберёт все поля как `name: value`.
105
+
85
106
  Атрибуты:
86
107
 
87
108
  | Атрибут | Описание |
88
109
  |---------|----------|
89
110
  | `data-notify` | Включает захват формы |
90
111
  | `data-notify-title` | Заголовок уведомления (по умолчанию `document.title`) |
91
- | `data-notify-body` | Статичный текст уведомления |
92
- | `data-notify-type` | Тип уведомления |
93
- | `data-notify-priority` | Приоритет |
94
- | `data-notify-fields` | Имена полей через запятую (какие включить) |
95
- | `data-notify-field` | Пометить поле (собирается как `name: value`) |
112
+ | `data-notify-type` | Тип уведомления (lead, order, message, crm, alert) |
113
+ | `data-notify-tag` | Тег уведомления |
114
+ | `data-notify-priority` | Приоритет (low, normal, high, urgent) |
115
+ | `data-notify-template` | Шаблон тела с `{field_name}` |
116
+ | `data-notify-body` | Статичный текст (если не нужен шаблон) |
117
+ | `data-notify-fields` | Имена полей через запятую |
118
+ | `data-notify-label` | Человекочитаемое название поля |
119
+ | `data-notify-field` | Пометить конкретное поле |
96
120
 
97
121
  ## Яндекс.Метрика
98
122
 
package/dist/index.cjs CHANGED
@@ -12,6 +12,8 @@ function sendWebhook(endpoint, token, payload, timeout = DEFAULT_TIMEOUT) {
12
12
  ...(payload.body !== undefined && { body: payload.body }),
13
13
  ...(payload.type !== undefined && { notification_type: payload.type }),
14
14
  ...(payload.priority !== undefined && { priority: payload.priority }),
15
+ ...(payload.tag !== undefined && { tag: payload.tag }),
16
+ ...(payload.payload !== undefined && { payload: payload.payload }),
15
17
  };
16
18
  const controller = new AbortController();
17
19
  const timer = setTimeout(() => controller.abort(), timeout);
@@ -110,8 +112,10 @@ function destroyFormCapture() {
110
112
  function extractPayload(form) {
111
113
  const title = form.dataset.notifyTitle ?? form.dataset.notify_title ?? document.title;
112
114
  const type = form.dataset.notifyType ?? form.dataset.notify_type;
115
+ const tag = form.dataset.notifyTag ?? form.dataset.notify_tag;
113
116
  const priority = form.dataset.notifyPriority ?? form.dataset.notify_priority;
114
117
  const staticBody = form.dataset.notifyBody ?? form.dataset.notify_body;
118
+ const template = form.dataset.notifyTemplate ?? form.dataset.notify_template;
115
119
  const specifiedFields = (form.dataset.notifyFields ?? form.dataset.notify_fields)
116
120
  ?.split(',')
117
121
  .map((s) => s.trim())
@@ -121,26 +125,44 @@ function extractPayload(form) {
121
125
  title,
122
126
  body: staticBody,
123
127
  ...(type && { type }),
128
+ ...(tag && { tag }),
124
129
  ...(priority && { priority: priority }),
125
130
  };
126
131
  }
127
- const fieldEntries = [];
128
132
  const elements = form.querySelectorAll('input[name], textarea[name], select[name]');
133
+ const fieldMap = new Map();
129
134
  elements.forEach((el) => {
130
135
  if (!el.name)
131
136
  return;
137
+ if (el.type === 'checkbox' || el.type === 'radio') {
138
+ if (!el.checked)
139
+ return;
140
+ }
132
141
  if (specifiedFields && !specifiedFields.includes(el.name))
133
142
  return;
134
143
  const isMarked = el.hasAttribute('data-notify-field');
135
- if (specifiedFields || isMarked) {
136
- fieldEntries.push(`${el.name}: ${el.value || ''}`);
144
+ if (specifiedFields || isMarked || (!specifiedFields && !template)) {
145
+ const label = el.getAttribute('data-notify-label') ?? el.name;
146
+ fieldMap.set(label, el.value || '');
137
147
  }
138
148
  });
139
- const body = fieldEntries.length > 0 ? fieldEntries.join('\n') : undefined;
149
+ let body;
150
+ if (template) {
151
+ body = template.replace(/\{(\w+)\}/g, (_, key) => {
152
+ if (fieldMap.has(key))
153
+ return fieldMap.get(key);
154
+ const el = form.elements.namedItem(key);
155
+ return el?.value || `{${key}}`;
156
+ });
157
+ }
158
+ else if (fieldMap.size > 0) {
159
+ body = Array.from(fieldMap, ([k, v]) => `${k}: ${v}`).join('\n');
160
+ }
140
161
  return {
141
162
  title,
142
163
  ...(body && { body }),
143
164
  ...(type && { type }),
165
+ ...(tag && { tag }),
144
166
  ...(priority && { priority: priority }),
145
167
  };
146
168
  }
@@ -268,14 +290,23 @@ if (typeof document !== 'undefined') {
268
290
  const autoCapture = thisScript.dataset.autoCapture !== 'false';
269
291
  const debug = thisScript.dataset.debug === 'true';
270
292
  const timeout = thisScript.dataset.timeout ? parseInt(thisScript.dataset.timeout, 10) : undefined;
271
- const notix = new Notix({
272
- token,
273
- ...(endpoint && { endpoint }),
274
- autoCapture,
275
- debug,
276
- ...(timeout && { timeout }),
277
- });
278
- window.notix = notix;
293
+ const ready = document.readyState !== 'loading';
294
+ const init = () => {
295
+ const notix = new Notix({
296
+ token,
297
+ ...(endpoint && { endpoint }),
298
+ autoCapture,
299
+ debug,
300
+ ...(timeout && { timeout }),
301
+ });
302
+ window.notix = notix;
303
+ };
304
+ if (ready) {
305
+ init();
306
+ }
307
+ else {
308
+ document.addEventListener('DOMContentLoaded', init);
309
+ }
279
310
  }
280
311
  else if (thisScript.dataset.debug === 'true') {
281
312
  console.warn('[Notix] data-token attribute is required on script tag');
package/dist/index.mjs CHANGED
@@ -10,6 +10,8 @@ function sendWebhook(endpoint, token, payload, timeout = DEFAULT_TIMEOUT) {
10
10
  ...(payload.body !== undefined && { body: payload.body }),
11
11
  ...(payload.type !== undefined && { notification_type: payload.type }),
12
12
  ...(payload.priority !== undefined && { priority: payload.priority }),
13
+ ...(payload.tag !== undefined && { tag: payload.tag }),
14
+ ...(payload.payload !== undefined && { payload: payload.payload }),
13
15
  };
14
16
  const controller = new AbortController();
15
17
  const timer = setTimeout(() => controller.abort(), timeout);
@@ -108,8 +110,10 @@ function destroyFormCapture() {
108
110
  function extractPayload(form) {
109
111
  const title = form.dataset.notifyTitle ?? form.dataset.notify_title ?? document.title;
110
112
  const type = form.dataset.notifyType ?? form.dataset.notify_type;
113
+ const tag = form.dataset.notifyTag ?? form.dataset.notify_tag;
111
114
  const priority = form.dataset.notifyPriority ?? form.dataset.notify_priority;
112
115
  const staticBody = form.dataset.notifyBody ?? form.dataset.notify_body;
116
+ const template = form.dataset.notifyTemplate ?? form.dataset.notify_template;
113
117
  const specifiedFields = (form.dataset.notifyFields ?? form.dataset.notify_fields)
114
118
  ?.split(',')
115
119
  .map((s) => s.trim())
@@ -119,26 +123,44 @@ function extractPayload(form) {
119
123
  title,
120
124
  body: staticBody,
121
125
  ...(type && { type }),
126
+ ...(tag && { tag }),
122
127
  ...(priority && { priority: priority }),
123
128
  };
124
129
  }
125
- const fieldEntries = [];
126
130
  const elements = form.querySelectorAll('input[name], textarea[name], select[name]');
131
+ const fieldMap = new Map();
127
132
  elements.forEach((el) => {
128
133
  if (!el.name)
129
134
  return;
135
+ if (el.type === 'checkbox' || el.type === 'radio') {
136
+ if (!el.checked)
137
+ return;
138
+ }
130
139
  if (specifiedFields && !specifiedFields.includes(el.name))
131
140
  return;
132
141
  const isMarked = el.hasAttribute('data-notify-field');
133
- if (specifiedFields || isMarked) {
134
- fieldEntries.push(`${el.name}: ${el.value || ''}`);
142
+ if (specifiedFields || isMarked || (!specifiedFields && !template)) {
143
+ const label = el.getAttribute('data-notify-label') ?? el.name;
144
+ fieldMap.set(label, el.value || '');
135
145
  }
136
146
  });
137
- const body = fieldEntries.length > 0 ? fieldEntries.join('\n') : undefined;
147
+ let body;
148
+ if (template) {
149
+ body = template.replace(/\{(\w+)\}/g, (_, key) => {
150
+ if (fieldMap.has(key))
151
+ return fieldMap.get(key);
152
+ const el = form.elements.namedItem(key);
153
+ return el?.value || `{${key}}`;
154
+ });
155
+ }
156
+ else if (fieldMap.size > 0) {
157
+ body = Array.from(fieldMap, ([k, v]) => `${k}: ${v}`).join('\n');
158
+ }
138
159
  return {
139
160
  title,
140
161
  ...(body && { body }),
141
162
  ...(type && { type }),
163
+ ...(tag && { tag }),
142
164
  ...(priority && { priority: priority }),
143
165
  };
144
166
  }
@@ -266,14 +288,23 @@ if (typeof document !== 'undefined') {
266
288
  const autoCapture = thisScript.dataset.autoCapture !== 'false';
267
289
  const debug = thisScript.dataset.debug === 'true';
268
290
  const timeout = thisScript.dataset.timeout ? parseInt(thisScript.dataset.timeout, 10) : undefined;
269
- const notix = new Notix({
270
- token,
271
- ...(endpoint && { endpoint }),
272
- autoCapture,
273
- debug,
274
- ...(timeout && { timeout }),
275
- });
276
- window.notix = notix;
291
+ const ready = document.readyState !== 'loading';
292
+ const init = () => {
293
+ const notix = new Notix({
294
+ token,
295
+ ...(endpoint && { endpoint }),
296
+ autoCapture,
297
+ debug,
298
+ ...(timeout && { timeout }),
299
+ });
300
+ window.notix = notix;
301
+ };
302
+ if (ready) {
303
+ init();
304
+ }
305
+ else {
306
+ document.addEventListener('DOMContentLoaded', init);
307
+ }
277
308
  }
278
309
  else if (thisScript.dataset.debug === 'true') {
279
310
  console.warn('[Notix] data-token attribute is required on script tag');
@@ -3,4 +3,4 @@
3
3
  * @version <%= pkg.version %>
4
4
  * @license MIT
5
5
  */
6
- var Notix=function(t){"use strict";function e(t,e,o,i=1e4){const r={title:o.title,...void 0!==o.body&&{body:o.body},...void 0!==o.type&&{notification_type:o.type},...void 0!==o.priority&&{priority:o.priority}},n=new AbortController,a=setTimeout(()=>n.abort(),i);return"undefined"!=typeof fetch?fetch(t,{method:"POST",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(r),signal:n.signal}).then(async t=>{clearTimeout(a);const e=await t.json();if(!t.ok)throw new Error(e.error||e.message||`HTTP ${t.status}`);return e}).catch(t=>{throw clearTimeout(a),t}):function(t,e,o,i){return new Promise((r,n)=>{const a=new XMLHttpRequest;a.open("POST",t,!0),a.setRequestHeader("Authorization",`Bearer ${e}`),a.setRequestHeader("Content-Type","application/json"),a.setRequestHeader("Accept","application/json"),a.timeout=i,a.onload=()=>{try{const t=JSON.parse(a.responseText);a.status>=200&&a.status<300?r(t):n(new Error(t.error||t.message||`HTTP ${a.status}`))}catch{n(new Error("Invalid response"))}},a.onerror=()=>n(new Error("Network error")),a.ontimeout=()=>n(new Error("Request timeout")),a.send(JSON.stringify(o))})}(t,e,r,i)}const o=new WeakMap;function i(t,e,i){e.querySelectorAll("form[data-notify]").forEach(e=>{e.dataset.notixBound||(e.dataset.notixBound="1",e.addEventListener("submit",r=>{const n=Date.now();if(n-(o.get(e)??0)<500)r.preventDefault();else{o.set(e,n);try{const o=function(t){const e=t.dataset.notifyTitle??t.dataset.notify_title??document.title,o=t.dataset.notifyType??t.dataset.notify_type,i=t.dataset.notifyPriority??t.dataset.notify_priority,r=t.dataset.notifyBody??t.dataset.notify_body,n=(t.dataset.notifyFields??t.dataset.notify_fields)?.split(",").map(t=>t.trim()).filter(Boolean);if(r)return{title:e,body:r,...o&&{type:o},...i&&{priority:i}};const a=[],s=t.querySelectorAll("input[name], textarea[name], select[name]");s.forEach(t=>{if(!t.name)return;if(n&&!n.includes(t.name))return;const e=t.hasAttribute("data-notify-field");(n||e)&&a.push(`${t.name}: ${t.value||""}`)});const c=a.length>0?a.join("\n"):void 0;return{title:e,...c&&{body:c},...o&&{type:o},...i&&{priority:i}}}(e);i&&console.log("[Notix] Form captured:",o.title),t(o,{title:o.title,fieldsCount:Object.keys(e.elements).length})}catch(t){i&&console.warn("[Notix] Form capture failed:",t)}}}))})}function r(t){if(!1===t?.enabled)return null;const e="undefined"!=typeof window&&"function"==typeof window.ym;if(!e&&!t?.enabled)return null;let o=t?.counterId;return!o&&e&&(o=function(){for(const t of Object.keys(window))if(t.startsWith("yaCounter")){const e=parseInt(t.replace("yaCounter",""),10);if(!isNaN(e))return e}return}()),o?new n(o,t?.prefix??"notix"):null}class n{constructor(t,e){this.counterId=t,this.prefix=e}trackSent(t){this.reachGoal(`${this.prefix}_sent`,{id:t.id,message:t.message})}trackError(t){this.reachGoal(`${this.prefix}_error`,{error:t.message})}trackFormCaptured(t,e){this.reachGoal(`${this.prefix}_form_captured`,{title:t,fields:e})}trackGoal(t){this.reachGoal(t,{})}reachGoal(t,e){"function"==typeof window.ym&&window.ym(this.counterId,"reachGoal",t,e)}}class a{constructor(t){if(this.captureActive=!1,!t.token||!t.token.startsWith("ntx_"))throw new Error('Notix: token must start with "ntx_"');this.token=t.token,this.endpoint=t.endpoint??"https://notix-hub.ru/api/v1/webhook",this.timeout=t.timeout??1e4,this.debug=t.debug??!1,this.metrika=r(t.metrika),!1!==t.autoCapture&&this.capture()}async notify(t){if(!t.title)throw new Error("Notix: title is required");this.log("Sending notification:",t.title);try{const o=await e(this.endpoint,this.token,t,this.timeout);return this.log("Notification sent:",o.id),this.metrika?.trackSent(o),o}catch(t){const e=t instanceof Error?t:new Error(String(t));throw this.log("Error sending notification:",e.message),this.metrika?.trackError(e),e}}capture(t=document){this.captureActive||(i((t,e)=>{this.notify(t).then(()=>{this.metrika?.trackFormCaptured(e.title??t.title,e.fieldsCount)}).catch(()=>{})},t,this.debug),this.captureActive=!0,this.log("Form capture activated"))}destroy(){document.querySelectorAll("form[data-notix-bound]").forEach(t=>{delete t.dataset.notixBound}),this.captureActive=!1,this.log("Notix destroyed")}log(...t){this.debug&&console.log("[Notix]",...t)}}if("undefined"!=typeof document){const t=document.currentScript;if(t){const e=t.dataset.token;if(e){const o=t.dataset.endpoint,i="false"!==t.dataset.autoCapture,r="true"===t.dataset.debug,n=t.dataset.timeout?parseInt(t.dataset.timeout,10):void 0,s=new a({token:e,...o&&{endpoint:o},autoCapture:i,debug:r,...n&&{timeout:n}});window.notix=s}else"true"===t.dataset.debug&&console.warn("[Notix] data-token attribute is required on script tag")}}return t.Notix=a,t}({});
6
+ var Notix=function(t){"use strict";function e(t,e,o,i=1e4){const n={title:o.title,...void 0!==o.body&&{body:o.body},...void 0!==o.type&&{notification_type:o.type},...void 0!==o.priority&&{priority:o.priority},...void 0!==o.tag&&{tag:o.tag},...void 0!==o.payload&&{payload:o.payload}},r=new AbortController,a=setTimeout(()=>r.abort(),i);return"undefined"!=typeof fetch?fetch(t,{method:"POST",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(n),signal:r.signal}).then(async t=>{clearTimeout(a);const e=await t.json();if(!t.ok)throw new Error(e.error||e.message||`HTTP ${t.status}`);return e}).catch(t=>{throw clearTimeout(a),t}):function(t,e,o,i){return new Promise((n,r)=>{const a=new XMLHttpRequest;a.open("POST",t,!0),a.setRequestHeader("Authorization",`Bearer ${e}`),a.setRequestHeader("Content-Type","application/json"),a.setRequestHeader("Accept","application/json"),a.timeout=i,a.onload=()=>{try{const t=JSON.parse(a.responseText);a.status>=200&&a.status<300?n(t):r(new Error(t.error||t.message||`HTTP ${a.status}`))}catch{r(new Error("Invalid response"))}},a.onerror=()=>r(new Error("Network error")),a.ontimeout=()=>r(new Error("Request timeout")),a.send(JSON.stringify(o))})}(t,e,n,i)}const o=new WeakMap;function i(t,e,i){e.querySelectorAll("form[data-notify]").forEach(e=>{e.dataset.notixBound||(e.dataset.notixBound="1",e.addEventListener("submit",n=>{const r=Date.now();if(r-(o.get(e)??0)<500)n.preventDefault();else{o.set(e,r);try{const o=function(t){const e=t.dataset.notifyTitle??t.dataset.notify_title??document.title,o=t.dataset.notifyType??t.dataset.notify_type,i=t.dataset.notifyTag??t.dataset.notify_tag,n=t.dataset.notifyPriority??t.dataset.notify_priority,r=t.dataset.notifyBody??t.dataset.notify_body,a=t.dataset.notifyTemplate??t.dataset.notify_template,s=(t.dataset.notifyFields??t.dataset.notify_fields)?.split(",").map(t=>t.trim()).filter(Boolean);if(r)return{title:e,body:r,...o&&{type:o},...i&&{tag:i},...n&&{priority:n}};const d=t.querySelectorAll("input[name], textarea[name], select[name]"),c=new Map;let u;d.forEach(t=>{if(!t.name)return;if(("checkbox"===t.type||"radio"===t.type)&&!t.checked)return;if(s&&!s.includes(t.name))return;const e=t.hasAttribute("data-notify-field");if(s||e||!s&&!a){const e=t.getAttribute("data-notify-label")??t.name;c.set(e,t.value||"")}}),a?u=a.replace(/\{(\w+)\}/g,(e,o)=>{if(c.has(o))return c.get(o);const i=t.elements.namedItem(o);return i?.value||`{${o}}`}):c.size>0&&(u=Array.from(c,([t,e])=>`${t}: ${e}`).join("\n"));return{title:e,...u&&{body:u},...o&&{type:o},...i&&{tag:i},...n&&{priority:n}}}(e);i&&console.log("[Notix] Form captured:",o.title),t(o,{title:o.title,fieldsCount:Object.keys(e.elements).length})}catch(t){i&&console.warn("[Notix] Form capture failed:",t)}}}))})}function n(t){if(!1===t?.enabled)return null;const e="undefined"!=typeof window&&"function"==typeof window.ym;if(!e&&!t?.enabled)return null;let o=t?.counterId;return!o&&e&&(o=function(){for(const t of Object.keys(window))if(t.startsWith("yaCounter")){const e=parseInt(t.replace("yaCounter",""),10);if(!isNaN(e))return e}return}()),o?new r(o,t?.prefix??"notix"):null}class r{constructor(t,e){this.counterId=t,this.prefix=e}trackSent(t){this.reachGoal(`${this.prefix}_sent`,{id:t.id,message:t.message})}trackError(t){this.reachGoal(`${this.prefix}_error`,{error:t.message})}trackFormCaptured(t,e){this.reachGoal(`${this.prefix}_form_captured`,{title:t,fields:e})}trackGoal(t){this.reachGoal(t,{})}reachGoal(t,e){"function"==typeof window.ym&&window.ym(this.counterId,"reachGoal",t,e)}}class a{constructor(t){if(this.captureActive=!1,!t.token||!t.token.startsWith("ntx_"))throw new Error('Notix: token must start with "ntx_"');this.token=t.token,this.endpoint=t.endpoint??"https://notix-hub.ru/api/v1/webhook",this.timeout=t.timeout??1e4,this.debug=t.debug??!1,this.metrika=n(t.metrika),!1!==t.autoCapture&&this.capture()}async notify(t){if(!t.title)throw new Error("Notix: title is required");this.log("Sending notification:",t.title);try{const o=await e(this.endpoint,this.token,t,this.timeout);return this.log("Notification sent:",o.id),this.metrika?.trackSent(o),o}catch(t){const e=t instanceof Error?t:new Error(String(t));throw this.log("Error sending notification:",e.message),this.metrika?.trackError(e),e}}capture(t=document){this.captureActive||(i((t,e)=>{this.notify(t).then(()=>{this.metrika?.trackFormCaptured(e.title??t.title,e.fieldsCount)}).catch(()=>{})},t,this.debug),this.captureActive=!0,this.log("Form capture activated"))}destroy(){document.querySelectorAll("form[data-notix-bound]").forEach(t=>{delete t.dataset.notixBound}),this.captureActive=!1,this.log("Notix destroyed")}log(...t){this.debug&&console.log("[Notix]",...t)}}if("undefined"!=typeof document){const t=document.currentScript;if(t){const e=t.dataset.token;if(e){const o=t.dataset.endpoint,i="false"!==t.dataset.autoCapture,n="true"===t.dataset.debug,r=t.dataset.timeout?parseInt(t.dataset.timeout,10):void 0,s=()=>{const t=new a({token:e,...o&&{endpoint:o},autoCapture:i,debug:n,...r&&{timeout:r}});window.notix=t};"loading"!==document.readyState?s():document.addEventListener("DOMContentLoaded",s)}else"true"===t.dataset.debug&&console.warn("[Notix] data-token attribute is required on script tag")}}return t.Notix=a,t}({});
package/dist/types.d.ts CHANGED
@@ -3,11 +3,13 @@ export interface NotifyPayload {
3
3
  title: string;
4
4
  body?: string;
5
5
  type?: string;
6
+ tag?: string;
6
7
  priority?: NotificationPriority;
7
8
  payload?: Record<string, unknown>;
8
9
  }
9
10
  export interface NotifyRequestBody extends NotifyPayload {
10
11
  notification_type?: string;
12
+ tag?: string;
11
13
  }
12
14
  export interface NotixResponse {
13
15
  message: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@notix-hub/sdk",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "JavaScript SDK for Notix (Нотикс) — notification aggregation service",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",