@siteping/widget 0.9.9 → 0.9.11

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/schema.d.ts CHANGED
@@ -9,35 +9,70 @@
9
9
  * This is a TS representation, NOT a .prisma file.
10
10
  * The CLI generates the actual Prisma schema from this definition.
11
11
  */
12
- /** Definition of a single field in a Siteping database model. */
12
+ /** Prisma scalar types supported by Siteping field definitions. */
13
+ export type PrismaScalarType = "String" | "Boolean" | "Int" | "BigInt" | "Float" | "Decimal" | "DateTime" | "Json" | "Bytes";
14
+ /** Prisma native column hints applied via `@db.<NativeType>`. */
15
+ export type PrismaNativeType = "Text" | "VarChar" | "Char" | "MediumText" | "LongText" | (string & {});
16
+ /** Relation cardinality between two Siteping models. */
17
+ export type RelationKind = "1-to-many" | "many-to-1";
18
+ /** Prisma `onDelete` referential action. */
19
+ export type RelationOnDelete = "Cascade" | "Restrict" | "NoAction" | "SetNull" | "SetDefault";
20
+ /**
21
+ * Relation metadata attached to a {@link FieldDef}.
22
+ *
23
+ * - `1-to-many` fields point at the related model and require no inverse
24
+ * column on this side (`fields`/`references` are inferred by Prisma).
25
+ * - `many-to-1` fields own the foreign key — Prisma needs `fields` and
26
+ * `references` to wire it up.
27
+ */
28
+ export interface RelationDef {
29
+ kind: RelationKind;
30
+ model: string;
31
+ fields?: readonly string[];
32
+ references?: readonly string[];
33
+ onDelete?: RelationOnDelete;
34
+ }
35
+ /**
36
+ * Definition of a single field in a Siteping database model.
37
+ *
38
+ * The interface intentionally keeps a wide structural shape so it stays
39
+ * easy to extend, but consumers can narrow via {@link isRelationField} /
40
+ * {@link isScalarField} when relation vs. scalar logic diverges.
41
+ */
13
42
  export interface FieldDef {
14
- type: string;
43
+ /** Prisma type (e.g. "String", "Int") for scalars, model name for relations. */
44
+ type: PrismaScalarType | (string & {});
45
+ /** Default literal (`"open"`) or function call (`now()`, `cuid()`). */
15
46
  default?: string;
47
+ /** Whether the column is nullable. */
16
48
  optional?: boolean;
17
- relation?: {
18
- kind: "1-to-many" | "many-to-1";
19
- model: string;
20
- fields?: string[];
21
- references?: string[];
22
- onDelete?: string;
23
- };
49
+ /** Set on relation fields — absent on scalars. */
50
+ relation?: RelationDef;
24
51
  isId?: boolean;
25
52
  isUnique?: boolean;
26
53
  /** Prisma native type attribute (e.g. "Text" for @db.Text) — used for MySQL compatibility on long strings */
27
- nativeType?: string;
54
+ nativeType?: PrismaNativeType;
28
55
  /** Prisma @updatedAt attribute */
29
56
  isUpdatedAt?: boolean;
30
57
  }
58
+ /** Narrowing predicate: returns `true` when `field` declares a Prisma relation. */
59
+ export declare function isRelationField(field: FieldDef): field is FieldDef & {
60
+ relation: RelationDef;
61
+ };
62
+ /** Narrowing predicate: returns `true` when `field` is a Prisma scalar (no relation metadata). */
63
+ export declare function isScalarField(field: FieldDef): field is FieldDef & {
64
+ relation?: undefined;
65
+ };
31
66
  /** Definition of a composite index on a Siteping database model. */
32
67
  export interface IndexDef {
33
- fields: string[];
68
+ fields: readonly string[];
34
69
  }
35
70
  /** Definition of a single Siteping database model (fields + indexes). */
36
71
  export interface ModelDef {
37
72
  fields: Record<string, FieldDef>;
38
- indexes?: IndexDef[];
73
+ indexes?: readonly IndexDef[];
39
74
  }
40
- export declare const SITEPING_MODELS: Readonly<{
75
+ declare const _SITEPING_MODELS: {
41
76
  readonly SitepingFeedback: {
42
77
  readonly fields: {
43
78
  readonly id: {
@@ -111,12 +146,12 @@ export declare const SITEPING_MODELS: Readonly<{
111
146
  };
112
147
  };
113
148
  };
114
- readonly indexes: [{
115
- readonly fields: ["projectName"];
149
+ readonly indexes: readonly [{
150
+ readonly fields: readonly ["projectName"];
116
151
  }, {
117
- readonly fields: ["projectName", "status", "createdAt"];
152
+ readonly fields: readonly ["projectName", "status", "createdAt"];
118
153
  }, {
119
- readonly fields: ["projectName", "url"];
154
+ readonly fields: readonly ["projectName", "url"];
120
155
  }];
121
156
  };
122
157
  readonly SitepingAnnotation: {
@@ -134,8 +169,8 @@ export declare const SITEPING_MODELS: Readonly<{
134
169
  readonly relation: {
135
170
  readonly kind: "many-to-1";
136
171
  readonly model: "SitepingFeedback";
137
- readonly fields: ["feedbackId"];
138
- readonly references: ["id"];
172
+ readonly fields: readonly ["feedbackId"];
173
+ readonly references: readonly ["id"];
139
174
  readonly onDelete: "Cascade";
140
175
  };
141
176
  };
@@ -210,8 +245,15 @@ export declare const SITEPING_MODELS: Readonly<{
210
245
  readonly default: "now()";
211
246
  };
212
247
  };
213
- readonly indexes: [{
214
- readonly fields: ["feedbackId"];
248
+ readonly indexes: readonly [{
249
+ readonly fields: readonly ["feedbackId"];
215
250
  }];
216
251
  };
217
- }>;
252
+ };
253
+ /** Map of Siteping models keyed by model name — frozen at runtime. */
254
+ export declare const SITEPING_MODELS: typeof _SITEPING_MODELS;
255
+ /** Union of every Siteping model name as a string literal. */
256
+ export type SitepingModelName = keyof typeof SITEPING_MODELS;
257
+ /** Field names declared on a specific Siteping model. */
258
+ export type SitepingModelFieldName<M extends SitepingModelName> = keyof (typeof SITEPING_MODELS)[M]["fields"];
259
+ export {};
@@ -1,8 +1,11 @@
1
+ export type { SitepingErrorCode } from "./errors.js";
1
2
  export { SitepingAuthError, SitepingError, SitepingNetworkError, SitepingValidationError } from "./errors.js";
2
3
  export type { FilterResult } from "./filters.js";
3
4
  export { applyFeedbackFilters } from "./filters.js";
4
- export type { FieldDef, IndexDef, ModelDef } from "./schema.js";
5
- export { SITEPING_MODELS } from "./schema.js";
5
+ export type { FieldDef, IndexDef, ModelDef, PrismaNativeType, PrismaScalarType, RelationDef, RelationKind, RelationOnDelete, SitepingModelFieldName, SitepingModelName, } from "./schema.js";
6
+ export { isRelationField, isScalarField, SITEPING_MODELS } from "./schema.js";
6
7
  export type { ScreenshotStorage } from "./screenshot-storage.js";
7
- export type { AnchorData, AnnotationCreateInput, AnnotationPayload, AnnotationRecord, AnnotationResponse, ConsoleDiagnosticEntry, DiagnosticsSnapshot, FeedbackCreateInput, FeedbackPayload, FeedbackQuery, FeedbackRecord, FeedbackResponse, FeedbackStatus, FeedbackType, FeedbackUpdateInput, NetworkDiagnosticEntry, PageScope, RectData, SitepingConfig, SitepingInstance, SitepingPublicEvents, SitepingStore, } from "./types.js";
8
- export { FEEDBACK_STATUSES, FEEDBACK_TYPES, flattenAnnotation, isStoreDuplicate, isStoreNotFound, StoreDuplicateError, StoreNotFoundError, } from "./types.js";
8
+ export type { AssertEqual, Brand, DeepReadonly, IfEquals, KeysOfType, NonEmptyArray, Prettify, Replace, RequiredNonNull, } from "./type-utils.js";
9
+ export { hasOwn, isRecord } from "./type-utils.js";
10
+ export type { AnchorData, AnnotationCreateInput, AnnotationPayload, AnnotationRecord, AnnotationResponse, BuiltinLocale, ConsoleDiagnosticEntry, ConsoleDiagnosticLevel, DiagnosticsCaptureOptions, DiagnosticsSnapshot, FeedbackCreateInput, FeedbackPage, FeedbackPayload, FeedbackQuery, FeedbackRecord, FeedbackResponse, FeedbackResponseList, FeedbackStatus, FeedbackType, FeedbackUpdateInput, NetworkDiagnosticEntry, PageScope, RectData, SitepingConfig, SitepingDeepLinkOptions, SitepingIdentity, SitepingInstance, SitepingLocale, SitepingPosition, SitepingPublicEventListener, SitepingPublicEvents, SitepingSkipReason, SitepingStore, SitepingTheme, SitepingUnsubscribe, } from "./types.js";
11
+ export { BUILTIN_LOCALES, FEEDBACK_STATUSES, FEEDBACK_TYPES, flattenAnnotation, isStoreDuplicate, isStoreNotFound, StoreDuplicateError, StoreNotFoundError, } from "./types.js";
package/dist/types.d.ts CHANGED
@@ -1,3 +1,36 @@
1
+ import { type Prettify } from "./type-utils.js";
2
+ /** FAB anchor — bottom-corner placement supported by the widget. */
3
+ export type SitepingPosition = "bottom-right" | "bottom-left";
4
+ /** Visual theme — `auto` resolves to `light` or `dark` via system preference. */
5
+ export type SitepingTheme = "light" | "dark" | "auto";
6
+ /** Built-in UI locales shipped with the widget. */
7
+ export declare const BUILTIN_LOCALES: readonly ["en", "fr", "de", "es", "it", "pt", "ru"];
8
+ export type BuiltinLocale = (typeof BUILTIN_LOCALES)[number];
9
+ /**
10
+ * Locale identifier accepted by the widget. Built-in locales are kept as
11
+ * literal strings so editors auto-complete them, but arbitrary BCP-47 tags
12
+ * are also accepted (custom dictionaries registered via `registerLocale`).
13
+ */
14
+ export type SitepingLocale = BuiltinLocale | (string & {});
15
+ /** Reasons reported through `SitepingConfig.onSkip`. */
16
+ export type SitepingSkipReason = "production" | "mobile";
17
+ /** Per-channel + per-buffer-size diagnostics configuration. */
18
+ export interface DiagnosticsCaptureOptions {
19
+ console?: boolean;
20
+ network?: boolean;
21
+ maxConsoleEntries?: number;
22
+ maxNetworkEntries?: number;
23
+ }
24
+ /** Identity payload supplied by the host application — bypasses the modal. */
25
+ export interface SitepingIdentity {
26
+ name: string;
27
+ email: string;
28
+ }
29
+ /** Deep-link configuration — controls how a feedback id is read from the URL. */
30
+ export interface SitepingDeepLinkOptions {
31
+ /** Query parameter name carrying the feedback id. Defaults to `"siteping"`. */
32
+ param?: string;
33
+ }
1
34
  /** Configuration options for the Siteping widget. */
2
35
  export interface SitepingConfig {
3
36
  /** HTTP endpoint that receives feedbacks (e.g. '/api/siteping'). Required unless `store` is provided. */
@@ -7,7 +40,7 @@ export interface SitepingConfig {
7
40
  /** Direct store for client-side mode. When set, bypasses HTTP and uses the store directly in the browser. */
8
41
  store?: SitepingStore | undefined;
9
42
  /** FAB position — defaults to 'bottom-right' */
10
- position?: "bottom-right" | "bottom-left";
43
+ position?: SitepingPosition;
11
44
  /** Accent color for the widget UI — defaults to '#0066ff' */
12
45
  accentColor?: string;
13
46
  /** Show the widget even in production — defaults to false */
@@ -15,9 +48,9 @@ export interface SitepingConfig {
15
48
  /** Enable debug logging of lifecycle events — defaults to false */
16
49
  debug?: boolean;
17
50
  /** Color theme — defaults to 'light' */
18
- theme?: "light" | "dark" | "auto";
51
+ theme?: SitepingTheme;
19
52
  /** UI locale — defaults to 'en'. Built-in: en, fr, de, es, it, pt (Brazilian), ru. Any other string falls back to English. */
20
- locale?: "en" | "fr" | "de" | "es" | "it" | "pt" | "ru" | (string & {}) | undefined;
53
+ locale?: SitepingLocale | undefined;
21
54
  /**
22
55
  * Returns the current page scope for annotations and panel filtering.
23
56
  * Called on initial markers load and on `instance.refresh()`.
@@ -74,14 +107,33 @@ export interface SitepingConfig {
74
107
  * URL (with query string) but never the response body. Inform end users
75
108
  * before enabling in environments where they might log sensitive values.
76
109
  */
77
- captureDiagnostics?: boolean | {
78
- console?: boolean;
79
- network?: boolean;
80
- maxConsoleEntries?: number;
81
- maxNetworkEntries?: number;
82
- } | undefined;
110
+ captureDiagnostics?: boolean | DiagnosticsCaptureOptions | undefined;
83
111
  /** Called when the widget is skipped (production mode, mobile viewport) */
84
- onSkip?: (reason: "production" | "mobile") => void;
112
+ onSkip?: (reason: SitepingSkipReason) => void;
113
+ /**
114
+ * Auto-focus a specific annotation when its ID appears in the URL query
115
+ * string. Lets hosts deeplink directly into a feedback from external
116
+ * systems (Zammad tickets, Slack notifications, dashboard rows).
117
+ *
118
+ * When enabled, the widget reads the configured query parameter from
119
+ * `window.location.search` right after the initial markers load. If the
120
+ * value matches a visible feedback ID, the widget scrolls the annotation
121
+ * into view, pins its highlight, and pulses the marker — the same visual
122
+ * affordance a marker click produces.
123
+ *
124
+ * - `false` / `undefined` (default): no URL parsing. Existing behavior
125
+ * unchanged, no host URL inspection.
126
+ * - `true`: enabled with default query parameter name `siteping`.
127
+ * - object: enabled with a custom parameter name. Use this to avoid
128
+ * clashes with host-app query keys.
129
+ *
130
+ * Only the initial load triggers focus. Subsequent URL changes (SPA
131
+ * navigation, `history.pushState`, hash updates) are ignored —
132
+ * deliberate, to avoid surprising re-scrolls during normal browsing.
133
+ * Hosts that need re-focus on route change can call
134
+ * `instance.focusFeedback(id)` explicitly.
135
+ */
136
+ deepLink?: boolean | SitepingDeepLinkOptions | undefined;
85
137
  /**
86
138
  * Pre-fill author identity from the host application — typically the
87
139
  * currently signed-in user. When set, the widget uses these values
@@ -101,10 +153,7 @@ export interface SitepingConfig {
101
153
  * https://github.com/NeosiaNexus/SitePing/issues/85 for tracking a
102
154
  * future enhancement that propagates identity updates without a remount.
103
155
  */
104
- identity?: {
105
- name: string;
106
- email: string;
107
- } | undefined;
156
+ identity?: SitepingIdentity | undefined;
108
157
  /** Called when the feedback panel is opened. */
109
158
  onOpen?: () => void;
110
159
  /** Called when the feedback panel is closed. */
@@ -137,15 +186,30 @@ export interface SitepingInstance {
137
186
  close: () => void;
138
187
  /** Reload feedbacks from server */
139
188
  refresh: () => void;
189
+ /**
190
+ * Scroll the matching annotation into view, pin its highlight, and
191
+ * pulse its marker. Returns `true` when a visible feedback matched the
192
+ * given ID, `false` otherwise (unknown ID, feedback on another URL when
193
+ * `scopeAnnotationsByUrl` filtered it out, or markers not yet loaded).
194
+ *
195
+ * Counterpart to the `deepLink` config option for hosts that prefer to
196
+ * drive focus from JS (e.g., a notification click handler) instead of a
197
+ * URL query parameter.
198
+ */
199
+ focusFeedback: (feedbackId: string) => boolean;
140
200
  /** Subscribe to a public widget event */
141
- on: <K extends keyof SitepingPublicEvents>(event: K, listener: (...args: SitepingPublicEvents[K]) => void) => () => void;
201
+ on: <K extends keyof SitepingPublicEvents>(event: K, listener: SitepingPublicEventListener<K>) => SitepingUnsubscribe;
142
202
  /** Unsubscribe from a public widget event */
143
- off: <K extends keyof SitepingPublicEvents>(event: K, listener: (...args: SitepingPublicEvents[K]) => void) => void;
203
+ off: <K extends keyof SitepingPublicEvents>(event: K, listener: SitepingPublicEventListener<K>) => void;
144
204
  }
205
+ /** Listener signature for a single `SitepingPublicEvents` key. */
206
+ export type SitepingPublicEventListener<K extends keyof SitepingPublicEvents> = (...args: SitepingPublicEvents[K]) => void;
207
+ /** Disposer returned by `SitepingInstance.on` — call once to detach the listener. */
208
+ export type SitepingUnsubscribe = () => void;
145
209
  /** Events exposed to consumers via SitepingInstance.on / .off */
146
210
  export interface SitepingPublicEvents {
147
211
  "feedback:sent": [FeedbackResponse];
148
- "feedback:deleted": [string];
212
+ "feedback:deleted": [FeedbackResponse["id"]];
149
213
  "panel:open": [];
150
214
  "panel:close": [];
151
215
  }
@@ -340,12 +404,21 @@ export declare class StoreDuplicateError extends Error {
340
404
  readonly code: "STORE_DUPLICATE";
341
405
  constructor(message?: string);
342
406
  }
407
+ /** Shape of any ORM error that carries a Prisma-style `code` field. */
408
+ type CodedError<C extends string = string> = {
409
+ code: C;
410
+ };
343
411
  /** Type guard — works for `StoreNotFoundError` and ORM-specific equivalents (e.g. Prisma P2025). */
344
- export declare function isStoreNotFound(error: unknown): boolean;
412
+ export declare function isStoreNotFound(error: unknown): error is StoreNotFoundError | CodedError<"P2025">;
345
413
  /** Type guard — works for `StoreDuplicateError` and ORM-specific equivalents (e.g. Prisma P2002). */
346
- export declare function isStoreDuplicate(error: unknown): boolean;
414
+ export declare function isStoreDuplicate(error: unknown): error is StoreDuplicateError | CodedError<"P2002">;
347
415
  /** Flatten a widget `AnnotationPayload` (nested anchor + rect) into a flat `AnnotationCreateInput`. */
348
- export declare function flattenAnnotation(ann: AnnotationPayload): AnnotationCreateInput;
416
+ export declare function flattenAnnotation(ann: AnnotationPayload): Prettify<AnnotationCreateInput>;
417
+ /** Paginated result returned by `SitepingStore.getFeedbacks`. */
418
+ export interface FeedbackPage {
419
+ feedbacks: FeedbackRecord[];
420
+ total: number;
421
+ }
349
422
  /**
350
423
  * Abstract storage interface for Siteping.
351
424
  *
@@ -366,10 +439,7 @@ export interface SitepingStore {
366
439
  /** Create a feedback with its annotations. Idempotent on `clientId` — return existing record on duplicate, or throw `StoreDuplicateError`. */
367
440
  createFeedback(data: FeedbackCreateInput): Promise<FeedbackRecord>;
368
441
  /** Paginated query with optional filters. Returns empty array (not error) when no results. */
369
- getFeedbacks(query: FeedbackQuery): Promise<{
370
- feedbacks: FeedbackRecord[];
371
- total: number;
372
- }>;
442
+ getFeedbacks(query: FeedbackQuery): Promise<FeedbackPage>;
373
443
  /** Lookup by client-generated UUID. Returns `null` (not error) when not found. */
374
444
  findByClientId(clientId: string): Promise<FeedbackRecord | null>;
375
445
  /** Update status/resolvedAt. Throws `StoreNotFoundError` if `id` does not exist. */
@@ -409,9 +479,11 @@ export interface FeedbackPayload {
409
479
  */
410
480
  diagnostics?: DiagnosticsSnapshot | null | undefined;
411
481
  }
482
+ /** Severity levels persisted in `ConsoleDiagnosticEntry`. */
483
+ export type ConsoleDiagnosticLevel = "log" | "info" | "warn" | "error";
412
484
  /** A single console entry captured by `ConsoleBuffer`. */
413
485
  export interface ConsoleDiagnosticEntry {
414
- level: "log" | "info" | "warn" | "error";
486
+ level: ConsoleDiagnosticLevel;
415
487
  /** ISO 8601 timestamp captured at log time. */
416
488
  timestamp: string;
417
489
  /** Best-effort string representation of the original console args. */
@@ -537,3 +609,9 @@ export interface AnnotationResponse {
537
609
  devicePixelRatio: number;
538
610
  createdAt: string;
539
611
  }
612
+ /** Paginated `FeedbackResponse` shape returned by the API. */
613
+ export interface FeedbackResponseList {
614
+ feedbacks: FeedbackResponse[];
615
+ total: number;
616
+ }
617
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@siteping/widget",
3
- "version": "0.9.9",
3
+ "version": "0.9.11",
4
4
  "description": "Feedback widget for client review during development — annotations, bugs, questions directly on the site",
5
5
  "type": "module",
6
6
  "sideEffects": false,