@sylergydigital/issue-pin-sdk 0.6.2 → 0.6.3
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 +48 -0
- package/dist/index.cjs +61 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -1
- package/dist/index.d.ts +13 -1
- package/dist/index.js +59 -3
- package/dist/index.js.map +1 -1
- package/package.json +4 -1
package/dist/index.d.cts
CHANGED
|
@@ -279,4 +279,16 @@ declare const Z: {
|
|
|
279
279
|
readonly flash: 99998;
|
|
280
280
|
};
|
|
281
281
|
|
|
282
|
-
|
|
282
|
+
/** Convert any string user ID to a valid UUID. Already-valid UUIDs pass through unchanged. */
|
|
283
|
+
declare function normalizeUserId(userId: string): string;
|
|
284
|
+
|
|
285
|
+
/** CSP directives required by the IssuePin SDK.
|
|
286
|
+
* Keyed by CSP directive name, values are source expressions to allow.
|
|
287
|
+
* Use wildcards (*.supabase.co) for zero-config — narrow to your project URL in production if preferred. */
|
|
288
|
+
declare const CSP_REQUIREMENTS: {
|
|
289
|
+
readonly "connect-src": readonly ["https://*.supabase.co", "wss://*.supabase.co"];
|
|
290
|
+
readonly "img-src": readonly ["data:", "blob:"];
|
|
291
|
+
readonly "style-src": readonly ["'unsafe-inline'"];
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
export { type AnchorResolution, type AnnotationSurface, CSP_REQUIREMENTS, IssuePin as ElementWhisperer, FeedbackButton, type FeedbackMode, FeedbackOverlay, FeedbackProvider, IssuePin, type LauncherRenderProps, type ModalCaptureRenderProps, type PendingPin, type PendingScreenshotPin, ReviewSurfaceOverlay, ScreenshotFeedback, type ScrollContainerBinding, SdkCommentPopover, type ThreadData, ThreadPins, Z, normalizeUserId, useFeedback, useFeedbackSafe, useIssuePinAnchor };
|
package/dist/index.d.ts
CHANGED
|
@@ -279,4 +279,16 @@ declare const Z: {
|
|
|
279
279
|
readonly flash: 99998;
|
|
280
280
|
};
|
|
281
281
|
|
|
282
|
-
|
|
282
|
+
/** Convert any string user ID to a valid UUID. Already-valid UUIDs pass through unchanged. */
|
|
283
|
+
declare function normalizeUserId(userId: string): string;
|
|
284
|
+
|
|
285
|
+
/** CSP directives required by the IssuePin SDK.
|
|
286
|
+
* Keyed by CSP directive name, values are source expressions to allow.
|
|
287
|
+
* Use wildcards (*.supabase.co) for zero-config — narrow to your project URL in production if preferred. */
|
|
288
|
+
declare const CSP_REQUIREMENTS: {
|
|
289
|
+
readonly "connect-src": readonly ["https://*.supabase.co", "wss://*.supabase.co"];
|
|
290
|
+
readonly "img-src": readonly ["data:", "blob:"];
|
|
291
|
+
readonly "style-src": readonly ["'unsafe-inline'"];
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
export { type AnchorResolution, type AnnotationSurface, CSP_REQUIREMENTS, IssuePin as ElementWhisperer, FeedbackButton, type FeedbackMode, FeedbackOverlay, FeedbackProvider, IssuePin, type LauncherRenderProps, type ModalCaptureRenderProps, type PendingPin, type PendingScreenshotPin, ReviewSurfaceOverlay, ScreenshotFeedback, type ScrollContainerBinding, SdkCommentPopover, type ThreadData, ThreadPins, Z, normalizeUserId, useFeedback, useFeedbackSafe, useIssuePinAnchor };
|
package/dist/index.js
CHANGED
|
@@ -77,6 +77,51 @@ var T = {
|
|
|
77
77
|
ring: "#6366f1"
|
|
78
78
|
};
|
|
79
79
|
|
|
80
|
+
// src/uuid.ts
|
|
81
|
+
import { v5 as uuidv5 } from "uuid";
|
|
82
|
+
var NAMESPACE = "8920e263-ef53-4df0-8108-968cd5d8939e";
|
|
83
|
+
var UUID_SHAPE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
84
|
+
function normalizeUserId(userId) {
|
|
85
|
+
if (UUID_SHAPE.test(userId)) return userId;
|
|
86
|
+
return uuidv5(userId, NAMESPACE);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// src/csp.ts
|
|
90
|
+
var CSP_REQUIREMENTS = {
|
|
91
|
+
"connect-src": ["https://*.supabase.co", "wss://*.supabase.co"],
|
|
92
|
+
"img-src": ["data:", "blob:"],
|
|
93
|
+
"style-src": ["'unsafe-inline'"]
|
|
94
|
+
};
|
|
95
|
+
var warnedDirectives = /* @__PURE__ */ new Set();
|
|
96
|
+
function isIssuePinViolation(event) {
|
|
97
|
+
const blocked = event.blockedURI;
|
|
98
|
+
const directive = event.violatedDirective;
|
|
99
|
+
if (directive.startsWith("connect-src") && blocked.includes("supabase.co")) return true;
|
|
100
|
+
if (directive.startsWith("img-src") && (blocked === "data" || blocked === "blob")) return true;
|
|
101
|
+
if (directive.startsWith("style-src") && (blocked === "inline" || blocked === "'unsafe-inline'")) return true;
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
function handleViolation(event) {
|
|
105
|
+
if (!isIssuePinViolation(event)) return;
|
|
106
|
+
const directive = event.violatedDirective.split(" ")[0];
|
|
107
|
+
if (warnedDirectives.has(directive)) return;
|
|
108
|
+
warnedDirectives.add(directive);
|
|
109
|
+
const sources = CSP_REQUIREMENTS[directive];
|
|
110
|
+
const fix = sources ? sources.join(" ") : event.blockedURI;
|
|
111
|
+
console.warn(
|
|
112
|
+
`[IssuePin] CSP violation: ${directive} blocked "${event.blockedURI}". Add to your Content-Security-Policy: ${directive} ${fix}`
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
function subscribeCspDetection() {
|
|
116
|
+
if (typeof document === "undefined") return () => {
|
|
117
|
+
};
|
|
118
|
+
const handler = (e) => handleViolation(e);
|
|
119
|
+
document.addEventListener("securitypolicyviolation", handler);
|
|
120
|
+
return () => {
|
|
121
|
+
document.removeEventListener("securitypolicyviolation", handler);
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
80
125
|
// src/FeedbackProvider.tsx
|
|
81
126
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
82
127
|
var FeedbackContext = createContext(null);
|
|
@@ -128,11 +173,11 @@ function setThreadsSchemaMode(workspaceId, mode) {
|
|
|
128
173
|
threadsSchemaModeByWorkspace.set(workspaceId, mode);
|
|
129
174
|
}
|
|
130
175
|
function resolveIssuePinActorUserId(opts) {
|
|
131
|
-
if (opts.explicitUserId) return opts.explicitUserId;
|
|
176
|
+
if (opts.explicitUserId) return normalizeUserId(opts.explicitUserId);
|
|
132
177
|
if (opts.hasApiKey && !opts.skipFederation && opts.autoIdentityUserId) {
|
|
133
178
|
return opts.federatedLocalUserId;
|
|
134
179
|
}
|
|
135
|
-
return opts.autoIdentityUserId;
|
|
180
|
+
return opts.autoIdentityUserId ? normalizeUserId(opts.autoIdentityUserId) : opts.autoIdentityUserId;
|
|
136
181
|
}
|
|
137
182
|
function resolveIssuePinActorReady(opts) {
|
|
138
183
|
if (!opts.authReady) return false;
|
|
@@ -369,6 +414,10 @@ function FeedbackProvider({
|
|
|
369
414
|
hasApiKey: !!config.apiKey,
|
|
370
415
|
skipFederation: config.skipFederation
|
|
371
416
|
});
|
|
417
|
+
const rawUserId = config.userId ?? autoIdentity.userId;
|
|
418
|
+
if (config.debug && rawUserId && effectiveUserId && rawUserId !== effectiveUserId) {
|
|
419
|
+
console.log(`[EW SDK] User ID normalized: "${rawUserId}" -> "${effectiveUserId}"`);
|
|
420
|
+
}
|
|
372
421
|
const actorReady = resolveIssuePinActorReady({
|
|
373
422
|
authReady,
|
|
374
423
|
explicitUserId: config.userId,
|
|
@@ -453,12 +502,13 @@ function FeedbackProviderInner({
|
|
|
453
502
|
console.log(`[EW SDK] ${message}`, extra);
|
|
454
503
|
}, [debug]);
|
|
455
504
|
useEffect(() => {
|
|
505
|
+
if (!authReady) return;
|
|
456
506
|
if (!userDisplayName && !userEmail) {
|
|
457
507
|
console.warn(
|
|
458
508
|
'[IssuePin] No user identity provided \u2014 comments will appear as "Unknown". Pass supabaseClient={supabase} for automatic identity, or user={{ email, displayName }} for manual attribution. See https://github.com/sylergydigital/issue-pin/blob/main/sdk/README.md#user-identity-avoiding-unknown-comments'
|
|
459
509
|
);
|
|
460
510
|
}
|
|
461
|
-
}, []);
|
|
511
|
+
}, [authReady, userDisplayName, userEmail]);
|
|
462
512
|
const client = useMemo(() => {
|
|
463
513
|
try {
|
|
464
514
|
return createClient(supabaseUrl, supabaseAnonKey, {
|
|
@@ -565,6 +615,10 @@ function FeedbackProviderInner({
|
|
|
565
615
|
debugLog("FeedbackProvider unmounted", { workspaceId, path: pathname });
|
|
566
616
|
};
|
|
567
617
|
}, [debugLog, workspaceId, pathname]);
|
|
618
|
+
useEffect(() => {
|
|
619
|
+
const unsubscribe = subscribeCspDetection();
|
|
620
|
+
return unsubscribe;
|
|
621
|
+
}, []);
|
|
568
622
|
useEffect(() => {
|
|
569
623
|
debugLog("mode / feedbackActive", { mode, feedbackActive });
|
|
570
624
|
}, [debugLog, mode, feedbackActive]);
|
|
@@ -2434,6 +2488,7 @@ function PinsSlot() {
|
|
|
2434
2488
|
return /* @__PURE__ */ jsx9(ThreadPins, {});
|
|
2435
2489
|
}
|
|
2436
2490
|
export {
|
|
2491
|
+
CSP_REQUIREMENTS,
|
|
2437
2492
|
IssuePin as ElementWhisperer,
|
|
2438
2493
|
FeedbackButton,
|
|
2439
2494
|
FeedbackOverlay,
|
|
@@ -2444,6 +2499,7 @@ export {
|
|
|
2444
2499
|
SdkCommentPopover,
|
|
2445
2500
|
ThreadPins,
|
|
2446
2501
|
Z,
|
|
2502
|
+
normalizeUserId,
|
|
2447
2503
|
useFeedback,
|
|
2448
2504
|
useFeedbackSafe,
|
|
2449
2505
|
useIssuePinAnchor
|