@useinsider/guido 1.0.3-beta.618f482 → 1.0.3-beta.6204034

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
@@ -597,6 +597,12 @@ Create a `.env` file with the following variables: (You can get env variables fr
597
597
  VITE_STRIPO_PLUGIN_ID=your_plugin_id
598
598
  VITE_STRIPO_SECRET_KEY=your_secret_key
599
599
  VITE_STRIPO_ROLE=your_role
600
+
601
+ # Sentry Configuration (optional - for error tracking)
602
+ VITE_SENTRY_DSN=https://your-sentry-dsn@sentry.io/project-id
603
+ VITE_SENTRY_ENVIRONMENT=production
604
+ VITE_SENTRY_RELEASE=1.0.3
605
+ VITE_SENTRY_ENABLED=true
600
606
  ```
601
607
 
602
608
  ### Project Structure
@@ -12,7 +12,7 @@ var t = function() {
12
12
  n,
13
13
  !1,
14
14
  null,
15
- "3c910a93"
15
+ "b2d31329"
16
16
  );
17
17
  const v = s.exports;
18
18
  export {
@@ -1,23 +1,24 @@
1
- import { defineComponent as R, defineAsyncComponent as I, ref as x, computed as U, watch as M, onMounted as z, onUnmounted as B } from "vue";
2
- import { provideGuidoActions as K } from "../composables/useGuidoActions.js";
3
- import { usePartner as O } from "../composables/usePartner.js";
4
- import { useStripo as j } from "../composables/useStripo.js";
5
- import { migrate as W } from "../config/migrator/index.js";
6
- import { DefaultUsername as q, DefaultMessageType as J, DefaultGuidoConfig as Q } from "../enums/defaults.js";
7
- import V from "./organisms/base/Toaster.vue.js";
8
- import X from "./organisms/extensions/recommendation/FilterSelectionDrawer.vue.js";
9
- import Y from "./organisms/header/HeaderWrapper.vue.js";
10
- import Z from "./organisms/LoadingWrapper.vue.js";
11
- import $ from "./organisms/save-as-template/SaveAsTemplateDrawer.vue.js";
12
- import ee from "./organisms/unsubscribe/UnsubscribeWrapper.vue.js";
13
- import { useStripoApi as oe } from "../services/stripoApi.js";
14
- import { useConfigStore as te } from "../stores/config.js";
15
- import { useDynamicContentStore as ne } from "../stores/dynamic-content.js";
16
- import { useEditorStore as re } from "../stores/editor.js";
1
+ import x, { defineComponent as M, defineAsyncComponent as U, ref as z, computed as W, watch as B, onMounted as K, onUnmounted as O } from "vue";
2
+ import { provideGuidoActions as V } from "../composables/useGuidoActions.js";
3
+ import { usePartner as j } from "../composables/usePartner.js";
4
+ import { useStripo as q } from "../composables/useStripo.js";
5
+ import { migrate as _ } from "../config/migrator/index.js";
6
+ import { DefaultUsername as J, DefaultMessageType as Q, DefaultGuidoConfig as X } from "../enums/defaults.js";
7
+ import Y from "./organisms/base/Toaster.vue.js";
8
+ import Z from "./organisms/extensions/recommendation/FilterSelectionDrawer.vue.js";
9
+ import $ from "./organisms/header/HeaderWrapper.vue.js";
10
+ import ee from "./organisms/LoadingWrapper.vue.js";
11
+ import oe from "./organisms/save-as-template/SaveAsTemplateDrawer.vue.js";
12
+ import te from "./organisms/unsubscribe/UnsubscribeWrapper.vue.js";
13
+ import { useStripoApi as ne } from "../services/stripoApi.js";
14
+ import { useConfigStore as re } from "../stores/config.js";
15
+ import { useDynamicContentStore as ie } from "../stores/dynamic-content.js";
16
+ import { useEditorStore as se } from "../stores/editor.js";
17
17
  import { usePreviewStore as ae } from "../stores/preview.js";
18
- import { useUnsubscribeStore as ie } from "../stores/unsubscribe.js";
19
- import se from "../node_modules/lodash-es/merge.js";
20
- const Ge = /* @__PURE__ */ R({
18
+ import { useUnsubscribeStore as ce } from "../stores/unsubscribe.js";
19
+ import { initSentry as me, createSentryConfig as de } from "../utils/sentry.js";
20
+ import ue from "../node_modules/lodash-es/merge.js";
21
+ const Le = /* @__PURE__ */ M({
21
22
  __name: "Guido",
22
23
  props: {
23
24
  templateId: null,
@@ -32,97 +33,99 @@ const Ge = /* @__PURE__ */ R({
32
33
  templateConfig: null
33
34
  },
34
35
  emits: ["dynamic-content:open", "back", "save:start", "save:complete", "on-change", "ready", "onboarding:finished"],
35
- setup(_, { expose: L, emit: t }) {
36
- const u = _, k = I(
36
+ setup(L, { expose: k, emit: n }) {
37
+ const l = L, A = U(
37
38
  () => import("./organisms/email-preview/PreviewContainer.vue.js")
38
- ), A = I(
39
+ ), N = U(
39
40
  () => import("./organisms/onboarding/OnboardingWrapper.vue.js")
40
- ), l = x(), a = ne(), p = ie(), g = te(), i = re(), N = ae(), n = U(() => i.hasChanges), { getPartnerName: f, getProductType: y, isTestPartner: F } = O(), v = () => {
41
+ ), p = z(), s = ie(), f = ce(), g = re(), a = se(), F = ae(), r = W(() => a.hasChanges), { getPartnerName: y, getProductType: v, isTestPartner: H } = j(), C = () => {
41
42
  var e;
42
- return (e = l.value) == null ? void 0 : e.handleSave(!0);
43
+ return (e = p.value) == null ? void 0 : e.handleSave(!0);
43
44
  }, {
44
- templateId: s,
45
+ templateId: c,
45
46
  userId: b,
46
- guidoConfig: C,
47
- templateConfig: o,
48
- html: r = "",
47
+ guidoConfig: S,
48
+ templateConfig: t,
49
+ html: i = "",
49
50
  css: h = "",
50
- partnerName: c = f(),
51
- productType: d = y(),
52
- messageType: S = J,
53
- username: w = q
54
- } = u, m = (o == null ? void 0 : o.preselectedDynamicContentList) || [];
55
- i.templateId = s, window.GuidoConfig = se(Q, C), window.GuidoConfig.partner = {
56
- partnerName: c,
51
+ partnerName: m = y(),
52
+ productType: d = v(),
53
+ messageType: w = Q,
54
+ username: D = J
55
+ } = l, u = (t == null ? void 0 : t.preselectedDynamicContentList) || [];
56
+ a.templateId = c, window.GuidoConfig = ue(X, S), window.GuidoConfig.partner = {
57
+ partnerName: m,
57
58
  productType: d,
58
- messageType: S
59
- }, g.templateConfig = o;
60
- const { initPlugin: D } = j({
61
- emailId: s,
59
+ messageType: w
60
+ }, g.templateConfig = t;
61
+ const { initPlugin: T } = q({
62
+ emailId: c,
62
63
  userId: b,
63
- username: w,
64
- partnerName: c,
64
+ username: D,
65
+ partnerName: m,
65
66
  productType: d,
66
- preselectedDynamicContentList: m,
67
+ preselectedDynamicContentList: u,
67
68
  onReady: () => {
68
- console.debug("guido:ready"), t("ready");
69
+ console.debug("guido:ready"), n("ready");
69
70
  }
70
- }), { getDefaultTemplate: T } = oe(), H = U(() => {
71
+ }), { getDefaultTemplate: E } = ne(), R = W(() => {
71
72
  var e;
72
73
  return !((e = window.GuidoConfig) != null && e.useHeader);
73
74
  });
74
- K({
75
+ V({
75
76
  onBack: () => {
76
- console.debug("guido:back"), t("back");
77
+ console.debug("guido:back"), n("back");
77
78
  },
78
79
  onSaveStart: () => {
79
- console.debug("guido:save:start"), t("save:start");
80
+ console.debug("guido:save:start"), n("save:start");
80
81
  },
81
82
  onSaveComplete: (e) => {
82
- console.debug("guido:save:complete", e), t("save:complete", e);
83
+ console.debug("guido:save:complete", e), n("save:complete", e);
83
84
  }
84
85
  });
85
- const E = (e) => {
86
- console.debug("dynamic-content:close", e), a.setSelectedDynamicContent(e), document.dispatchEvent(new CustomEvent("dynamic-content:close", { detail: e }));
87
- }, P = () => {
86
+ const P = (e) => {
87
+ console.debug("dynamic-content:close", e), s.setSelectedDynamicContent(e), document.dispatchEvent(new CustomEvent("dynamic-content:close", { detail: e }));
88
+ }, G = () => {
88
89
  console.debug("dynamic-content:close", "Without Data"), document.dispatchEvent(new CustomEvent("dynamic-content:close", { detail: { text: "", value: "" } }));
89
90
  };
90
- return M(() => n.value, () => {
91
- t("on-change", n.value);
92
- }), z(async () => {
91
+ return B(() => r.value, () => {
92
+ n("on-change", r.value);
93
+ }), K(async () => {
93
94
  console.debug("Guido says happy coding 🎉"), console.debug("🚗 Ka-Chow");
95
+ const e = de();
96
+ e && me(x, e);
94
97
  try {
95
- p.selectedUnsubscribePages = (o == null ? void 0 : o.selectedUnsubscribePages) || [];
96
- let e = {
97
- html: r && await W(r),
98
+ f.selectedUnsubscribePages = (t == null ? void 0 : t.selectedUnsubscribePages) || [];
99
+ let o = {
100
+ html: i && await _(i),
98
101
  css: h,
99
102
  forceRecreate: !0
100
103
  // TODO: It should be false for old templates. We will communicate with Stripo
101
104
  };
102
- e.html || (e = await T(), e.html = await W(e.html)), await D(e), a.selectedDynamicContentList = m;
103
- } catch (e) {
104
- console.error("Failed to initialize Stripo editor:", e);
105
+ o.html || (o = await E(), o.html = await _(o.html)), await T(o), s.selectedDynamicContentList = u;
106
+ } catch (o) {
107
+ console.error("Failed to initialize Stripo editor:", o);
105
108
  }
106
- document.addEventListener("dynamic-content:open", (e) => {
107
- const G = e;
108
- console.debug("dynamic-content:open", G.detail), t("dynamic-content:open", G.detail);
109
+ document.addEventListener("dynamic-content:open", (o) => {
110
+ const I = o;
111
+ console.debug("dynamic-content:open", I.detail), n("dynamic-content:open", I.detail);
109
112
  });
110
- }), B(() => {
113
+ }), O(() => {
111
114
  try {
112
115
  window.UIEditor.removeEditor();
113
116
  } catch {
114
117
  console.debug("Failed to remove Stripo editor: No editor found");
115
118
  }
116
- }), L({
119
+ }), k({
117
120
  dynamicContent: {
118
- insert: E,
119
- close: P
121
+ insert: P,
122
+ close: G
120
123
  },
121
- hasChanges: n,
122
- saveSilent: v
123
- }), { __sfc: !0, PreviewContainer: k, OnboardingWrapper: A, headerWrapperRef: l, dynamicContentStore: a, unsubscribeStore: p, props: u, configStore: g, editorStore: i, previewStore: N, hasChanges: n, getPartnerName: f, getProductType: y, isTestPartner: F, saveSilent: v, templateId: s, userId: b, guidoConfig: C, templateConfig: o, html: r, css: h, partnerName: c, productType: d, messageType: S, username: w, preselectedDynamicContentList: m, emit: t, initPlugin: D, getDefaultTemplate: T, noHeader: H, insertDynamicContent: E, closeDynamicContent: P, Toaster: V, FilterSelectionDrawer: X, HeaderWrapper: Y, LoadingWrapper: Z, SaveAsTemplateDrawer: $, UnsubscribeWrapper: ee };
124
+ hasChanges: r,
125
+ saveSilent: C
126
+ }), { __sfc: !0, PreviewContainer: A, OnboardingWrapper: N, headerWrapperRef: p, dynamicContentStore: s, unsubscribeStore: f, props: l, configStore: g, editorStore: a, previewStore: F, hasChanges: r, getPartnerName: y, getProductType: v, isTestPartner: H, saveSilent: C, templateId: c, userId: b, guidoConfig: S, templateConfig: t, html: i, css: h, partnerName: m, productType: d, messageType: w, username: D, preselectedDynamicContentList: u, emit: n, initPlugin: T, getDefaultTemplate: E, noHeader: R, insertDynamicContent: P, closeDynamicContent: G, Toaster: Y, FilterSelectionDrawer: Z, HeaderWrapper: $, LoadingWrapper: ee, SaveAsTemplateDrawer: oe, UnsubscribeWrapper: te };
124
127
  }
125
128
  });
126
129
  export {
127
- Ge as default
130
+ Le as default
128
131
  };
package/dist/guido.css CHANGED
@@ -1 +1 @@
1
- .gap-16[data-v-6562e38c],.gap-16[data-v-1ccb6d4a]{gap:16px}[data-v-0502bceb] .in-button-v2__wrapper{line-height:0}[data-v-b5997368] .in-segments-wrapper .in-tooltip-wrapper__box{text-align:left}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history-wrapper[data-v-52a77eec]{gap:8px}.view-options-wrapper[data-v-d405ca59]{position:relative;display:inline-block}.new-tag[data-v-d405ca59]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-d405ca59] .guido__verion-history-view-option-selection-desktop svg,[data-v-d405ca59] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-d405ca59] .in-segments-wrapper__button_selected,[data-v-d405ca59] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-d405ca59] .in-tooltip-wrapper__icon{cursor:pointer}.view-options-wrapper[data-v-195ab6d4]{position:relative;display:inline-block}.new-tag[data-v-195ab6d4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-195ab6d4] .guido__view-option-selection-desktop svg,[data-v-195ab6d4] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-195ab6d4] .in-segments-wrapper__button_selected,[data-v-195ab6d4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-195ab6d4] .in-tooltip-wrapper__icon{cursor:pointer}.guido-loading__wrapper[data-v-dced5582]{height:100%;top:75px}.guido-editor__wrapper[data-v-3c910a93],.guido-editor__container[data-v-3c910a93]{width:100%;height:calc(100vh - 128px)}.guido-editor__no-header[data-v-3c910a93]{height:calc(100vh - 75px)}[data-v-70835920] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-a86fc486]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-a86fc486]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-a86fc486]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-a86fc486]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-a86fc486]{object-fit:cover;transform:scale(1)}[data-v-dd57102d] .guido__verion-history-view-option-selection-desktop svg,[data-v-dd57102d] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-dd57102d] .in-segments-wrapper__button_selected,[data-v-dd57102d] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-7a09985c]{gap:16px}[data-v-c2adc57d] .in-progress-wrapper__progress p span:last-child{display:none!important}.desktop-preview-container[data-v-2dd60b0c],[data-v-2dd60b0c] .desktop-preview-container .in-container{min-height:720px!important;height:100%}.cropped-text[data-v-f20b3a9b]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}[data-v-d3c52b44] .vueperslides__bullets,[data-v-a408dcea] .vueperslides__bullets{pointer-events:none!important}[data-v-a408dcea] .vueperslides__parallax-wrapper{height:110px!important}
1
+ .gap-16[data-v-6562e38c],.gap-16[data-v-1ccb6d4a]{gap:16px}[data-v-0502bceb] .in-button-v2__wrapper{line-height:0}[data-v-b5997368] .in-segments-wrapper .in-tooltip-wrapper__box{text-align:left}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history-wrapper[data-v-52a77eec]{gap:8px}.view-options-wrapper[data-v-d405ca59]{position:relative;display:inline-block}.new-tag[data-v-d405ca59]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-d405ca59] .guido__verion-history-view-option-selection-desktop svg,[data-v-d405ca59] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-d405ca59] .in-segments-wrapper__button_selected,[data-v-d405ca59] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-d405ca59] .in-tooltip-wrapper__icon{cursor:pointer}.view-options-wrapper[data-v-195ab6d4]{position:relative;display:inline-block}.new-tag[data-v-195ab6d4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-195ab6d4] .guido__view-option-selection-desktop svg,[data-v-195ab6d4] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-195ab6d4] .in-segments-wrapper__button_selected,[data-v-195ab6d4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-195ab6d4] .in-tooltip-wrapper__icon{cursor:pointer}.guido-loading__wrapper[data-v-dced5582]{height:100%;top:75px}.guido-editor__wrapper[data-v-b2d31329],.guido-editor__container[data-v-b2d31329]{width:100%;height:calc(100vh - 128px)}.guido-editor__no-header[data-v-b2d31329]{height:calc(100vh - 75px)}[data-v-70835920] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-a86fc486]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-a86fc486]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-a86fc486]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-a86fc486]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-a86fc486]{object-fit:cover;transform:scale(1)}[data-v-dd57102d] .guido__verion-history-view-option-selection-desktop svg,[data-v-dd57102d] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-dd57102d] .in-segments-wrapper__button_selected,[data-v-dd57102d] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-7a09985c]{gap:16px}[data-v-c2adc57d] .in-progress-wrapper__progress p span:last-child{display:none!important}.desktop-preview-container[data-v-2dd60b0c],[data-v-2dd60b0c] .desktop-preview-container .in-container{min-height:720px!important;height:100%}.cropped-text[data-v-f20b3a9b]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}[data-v-d3c52b44] .vueperslides__bullets,[data-v-a408dcea] .vueperslides__bullets{pointer-events:none!important}[data-v-a408dcea] .vueperslides__parallax-wrapper{height:110px!important}
@@ -1,4 +1,5 @@
1
1
  import type { CompilerRule } from './html-compiler';
2
+ import type { ErrorEvent, EventHint } from '@sentry/types';
2
3
  type Extensions = {
3
4
  unsubscribe?: boolean;
4
5
  };
@@ -13,6 +14,18 @@ type Partner = {
13
14
  productType: number;
14
15
  messageType: number;
15
16
  };
17
+ export type SentryConfig = {
18
+ environment?: string;
19
+ release?: string;
20
+ enabled?: boolean;
21
+ userId?: string;
22
+ userEmail?: string;
23
+ tags?: Record<string, string>;
24
+ whitelistUrls?: (string | RegExp)[];
25
+ ignoreErrors?: string[];
26
+ shouldSendCallback?: () => boolean;
27
+ beforeSend?: (event: ErrorEvent, hint: EventHint) => ErrorEvent | null;
28
+ };
16
29
  export type GuidoBlockType = 'amp-accordion' | 'amp-carousel' | 'amp-form-controls' | 'banner-block' | 'button-block' | 'html-block' | 'image-block' | 'menu-block' | 'social-block' | 'spacer-block' | 'text-block' | 'timer-block' | 'video-block';
17
30
  export type GuidoCustomBlockType = 'dynamic-content' | 'checkbox-block' | 'radio-button-block' | 'recommendation-block' | 'unsubscribe-block' | 'coupon-block' | 'items-block';
18
31
  type BlocksConfig = {
@@ -31,6 +44,12 @@ export type GuidoConfig = {
31
44
  features?: Features;
32
45
  blocks?: BlocksConfig;
33
46
  backButtonLabel?: string;
47
+ /**
48
+ * @deprecated Sentry configuration is now bundled at build time
49
+ * This field is ignored - Sentry is completely internal to Guido
50
+ * Configure via VITE_SENTRY_DSN environment variable when building Guido
51
+ */
52
+ sentry?: SentryConfig;
34
53
  };
35
54
  export type TemplateConfig = {
36
55
  preselectedDynamicContentList?: DynamicContent[];
@@ -84,6 +84,40 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"config", S
84
84
  includeCustoms?: import("@@/Types/generic").GuidoCustomBlockType[] | undefined;
85
85
  } | undefined;
86
86
  backButtonLabel?: string | undefined;
87
+ sentry?: {
88
+ environment?: string | undefined;
89
+ release?: string | undefined;
90
+ enabled?: boolean | undefined;
91
+ userId?: string | undefined;
92
+ userEmail?: string | undefined;
93
+ tags?: Record<string, string> | undefined;
94
+ whitelistUrls?: (string | {
95
+ exec: (string: string) => RegExpExecArray | null;
96
+ test: (string: string) => boolean;
97
+ readonly source: string;
98
+ readonly global: boolean;
99
+ readonly ignoreCase: boolean;
100
+ readonly multiline: boolean;
101
+ lastIndex: number;
102
+ compile: (pattern: string, flags?: string) => RegExp;
103
+ readonly flags: string;
104
+ readonly sticky: boolean;
105
+ readonly unicode: boolean;
106
+ readonly dotAll: boolean;
107
+ readonly hasIndices: boolean;
108
+ [Symbol.match]: (string: string) => RegExpMatchArray | null;
109
+ [Symbol.replace]: {
110
+ (string: string, replaceValue: string): string;
111
+ (string: string, replacer: (substring: string, ...args: any[]) => string): string;
112
+ };
113
+ [Symbol.search]: (string: string) => number;
114
+ [Symbol.split]: (string: string, limit?: number) => string[];
115
+ [Symbol.matchAll]: (str: string) => IterableIterator<RegExpMatchArray>;
116
+ })[] | undefined;
117
+ ignoreErrors?: string[] | undefined;
118
+ shouldSendCallback?: (() => boolean) | undefined;
119
+ beforeSend?: ((event: import("@sentry/types").ErrorEvent, hint: import("@sentry/types").EventHint) => import("@sentry/types").ErrorEvent | null) | undefined;
120
+ } | undefined;
87
121
  };
88
122
  templateConfig?: {
89
123
  preselectedDynamicContentList?: {
@@ -0,0 +1,28 @@
1
+ import type { SentryConfig } from '@@/Types/generic';
2
+ import type Vue from 'vue';
3
+ /**
4
+ * Internal SentryConfig with DSN (DSN is bundled at build time)
5
+ */
6
+ type InternalSentryConfig = SentryConfig & {
7
+ dsn: string;
8
+ };
9
+ /**
10
+ * Initializes Sentry for Guido with complete isolation from parent app's Sentry
11
+ * This ensures errors only go to Guido's Sentry project, not the parent app's
12
+ *
13
+ * Key isolation features:
14
+ * - Uses Guido's own DSN (separate from parent app)
15
+ * - beforeSend filter ensures only Guido/Stripo errors are captured
16
+ * - Error path matching includes npm package paths (@useinsider/guido)
17
+ * - Tags identify errors as coming from Guido package
18
+ *
19
+ * This should be called once when the Guido component is mounted
20
+ */
21
+ export declare function initSentry(VueInstance: typeof Vue, config: InternalSentryConfig): void;
22
+ /**
23
+ * Creates SentryConfig from build-time environment variables
24
+ * All Sentry configuration is bundled with Guido at build time
25
+ * Parent apps don't need to provide any Sentry config - it's completely internal
26
+ */
27
+ export declare function createSentryConfig(): InternalSentryConfig | null;
28
+ export {};
@@ -0,0 +1,168 @@
1
+ import { browserTracingIntegration as h, httpClientIntegration as C, moduleMetadataIntegration as S, init as x, setTags as E, getCurrentHub as y } from "@sentry/vue";
2
+ function j(e) {
3
+ var s, a, d, c, t;
4
+ const o = (c = (d = (a = (s = e == null ? void 0 : e.exception) == null ? void 0 : s.values) == null ? void 0 : a[0]) == null ? void 0 : d.stacktrace) == null ? void 0 : c.frames, i = [
5
+ "/client-injected",
6
+ "/s/fs.js",
7
+ "/webpack",
8
+ "/ins.js"
9
+ ], r = e, n = ((t = r == null ? void 0 : r.metadata) == null ? void 0 : t.filename) || "";
10
+ return n && i.some((u) => n.includes(u)) ? !0 : !o || o.length === 0 ? !1 : o.some((u) => i.some((l) => {
11
+ var p;
12
+ return (p = u.filename) == null ? void 0 : p.includes(l);
13
+ }));
14
+ }
15
+ function N(e, o) {
16
+ var a, d, c;
17
+ const i = ((c = (d = (a = e == null ? void 0 : e.exception) == null ? void 0 : a.values) == null ? void 0 : d[0]) == null ? void 0 : c.value) || "", r = o == null ? void 0 : o.originalException, n = r && typeof r == "object" && "message" in r ? String(r.message) : "";
18
+ return [
19
+ "Non-Error exception captured",
20
+ "Object captured as exception with keys",
21
+ "Object captured as promise rejection with keys",
22
+ "Cannot read properties of null (reading 'cmd')",
23
+ // cspell:ignore zalo
24
+ "Can't find variable: zaloJSV2",
25
+ "ResizeObserver loop completed with undelivered notifications"
26
+ ].some((t) => i.includes(t) || n.includes(t));
27
+ }
28
+ function k(e) {
29
+ var r, n, s, a, d;
30
+ const o = (a = (s = (n = (r = e == null ? void 0 : e.exception) == null ? void 0 : r.values) == null ? void 0 : n[0]) == null ? void 0 : s.stacktrace) == null ? void 0 : a.frames;
31
+ if (!o || o.length === 0) {
32
+ const c = (e == null ? void 0 : e.message) || "", t = e, u = ((d = t == null ? void 0 : t.metadata) == null ? void 0 : d.filename) || "", l = `${c}${u}`.toLowerCase();
33
+ return l.includes("guido") || l.includes("stripo") || l.includes("uieditor");
34
+ }
35
+ const i = [
36
+ // Source patterns
37
+ "guido",
38
+ "Guido.vue",
39
+ "composables",
40
+ "extensions",
41
+ "stores",
42
+ "services",
43
+ "utils/sentry",
44
+ "components/Guido",
45
+ // Built/dist patterns (when installed as npm package)
46
+ "@useinsider/guido",
47
+ "useinsider/guido",
48
+ "guido/dist",
49
+ "guido/library",
50
+ // Stripo patterns - since Guido wraps Stripo, these errors are relevant
51
+ "stripo",
52
+ // cspell:ignore uieditor
53
+ "uieditor",
54
+ "UIEditor",
55
+ "/stripo/"
56
+ ];
57
+ return o.some((c) => {
58
+ const t = c.filename || "", u = c.abs_path || "", l = `${t}${u}`.toLowerCase();
59
+ return i.some((p) => l.includes(p.toLowerCase()));
60
+ });
61
+ }
62
+ function $(e) {
63
+ var d, c, t, u, l;
64
+ const o = (u = (t = (c = (d = e == null ? void 0 : e.exception) == null ? void 0 : d.values) == null ? void 0 : c[0]) == null ? void 0 : t.stacktrace) == null ? void 0 : u.frames, i = (e == null ? void 0 : e.message) || "", r = e, n = ((l = r == null ? void 0 : r.metadata) == null ? void 0 : l.filename) || "", s = `${i}${n}`.toLowerCase();
65
+ if (s.includes("stripo") || s.includes("uieditor"))
66
+ return !0;
67
+ if (!o || o.length === 0)
68
+ return !1;
69
+ const a = ["stripo", "uieditor", "UIEditor"];
70
+ return o.some((p) => {
71
+ const f = p.filename || "", w = p.abs_path || "", g = `${f}${w}`.toLowerCase();
72
+ return a.some((b) => g.includes(b.toLowerCase()));
73
+ });
74
+ }
75
+ function I() {
76
+ return !0;
77
+ }
78
+ function m() {
79
+ var i, r;
80
+ if (typeof window > "u")
81
+ return;
82
+ const e = window;
83
+ if ((r = (i = e.GuidoConfig) == null ? void 0 : i.partner) != null && r.partnerName)
84
+ return e.GuidoConfig.partner.partnerName;
85
+ try {
86
+ const { hostname: n } = window.location;
87
+ if (n) {
88
+ const s = n.split(".");
89
+ return s.length > 2 ? s[0] : n;
90
+ }
91
+ } catch {
92
+ }
93
+ const o = window;
94
+ if (o.projectName)
95
+ return o.projectName;
96
+ if (o.appName)
97
+ return o.appName;
98
+ }
99
+ function L(e, o) {
100
+ if (typeof window < "u" && window.isSessionExpired || !k(e) || j(e) || N(e, o))
101
+ return null;
102
+ const i = $(e), r = m();
103
+ return e.tags = {
104
+ ...e.tags,
105
+ source: "guido",
106
+ errorSource: i ? "stripo" : "guido"
107
+ }, r && (e.tags.parentApp = r, e.contexts = {
108
+ ...e.contexts,
109
+ parentApp: {
110
+ name: r,
111
+ url: typeof window < "u" ? window.location.href : void 0
112
+ }
113
+ }), e;
114
+ }
115
+ function A(e, o) {
116
+ if (!(!o.enabled || !o.dsn))
117
+ try {
118
+ const i = {
119
+ Vue: e,
120
+ dsn: o.dsn,
121
+ // Guido's DSN - errors will only go here, not to parent app's Sentry
122
+ release: o.release,
123
+ environment: o.environment || "production",
124
+ ignoreErrors: o.ignoreErrors || [
125
+ "ResizeObserver loop completed with undelivered notifications",
126
+ "Non-Error exception captured",
127
+ "Non-Error promise rejection captured",
128
+ "Cannot read properties of null (reading 'cmd')",
129
+ // cspell:ignore zalo
130
+ "Can't find variable: zaloJSV2"
131
+ ],
132
+ shouldSendCallback: o.shouldSendCallback || I,
133
+ allowUrls: o.whitelistUrls || [],
134
+ integrations: [
135
+ h(),
136
+ // No router needed for Guido
137
+ C(),
138
+ S()
139
+ ],
140
+ beforeSend: o.beforeSend || L
141
+ // Ensure we only capture errors from Guido/Stripo, never from parent app
142
+ // This is critical for npm package usage
143
+ };
144
+ x(i);
145
+ const r = m(), n = {
146
+ package: "@useinsider/guido",
147
+ ...r ? { parentApp: r } : {},
148
+ ...o.tags
149
+ };
150
+ if (E(n), r && typeof window < "u") {
151
+ const a = y().getScope();
152
+ a && a.setContext("parentApp", {
153
+ name: r,
154
+ url: window.location.href,
155
+ hostname: window.location.hostname
156
+ });
157
+ }
158
+ } catch (i) {
159
+ console.warn("Failed to initialize Sentry:", i);
160
+ }
161
+ }
162
+ function G() {
163
+ return null;
164
+ }
165
+ export {
166
+ G as createSentryConfig,
167
+ A as initSentry
168
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@useinsider/guido",
3
- "version": "1.0.3-beta.618f482",
3
+ "version": "1.0.3-beta.6204034",
4
4
  "description": "Guido is a Vue + TypeScript wrapper for Email Plugin. Easily embed the email editor in your Vue applications.",
5
5
  "main": "./dist/guido.umd.cjs",
6
6
  "module": "./dist/library.js",
@@ -31,6 +31,7 @@
31
31
  "author": "",
32
32
  "license": "ISC",
33
33
  "dependencies": {
34
+ "@sentry/vue": "7.120.4",
34
35
  "@stripoinc/ui-editor-extensions": "3.1.0",
35
36
  "@useinsider/design-system-vue": "0.14.20",
36
37
  "@vueuse/core": "11.3.0",