@guidelytech/shared 0.8.0 → 0.9.0
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/chunk-UW6NRYRY.js +809 -0
- package/dist/chunk-UW6NRYRY.js.map +1 -0
- package/dist/index.cjs +189 -60
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +97 -6
- package/dist/index.d.ts +97 -6
- package/dist/index.js +121 -53
- package/dist/index.js.map +1 -1
- package/dist/runtime.cjs +110 -8
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.d.cts +106 -5
- package/dist/runtime.d.ts +106 -5
- package/dist/runtime.js +47 -3
- package/package.json +4 -4
package/dist/runtime.d.cts
CHANGED
|
@@ -78,7 +78,7 @@ declare function isChecklistComplete(config: {
|
|
|
78
78
|
|
|
79
79
|
declare const RULE_OPERATORS: readonly ["equals", "not_equals", "contains", "not_contains", "starts_with", "ends_with", "exists", "not_exists", "gt", "gte", "lt", "lte", "in", "not_in", "regex", "is_true", "is_false", "before", "after"];
|
|
80
80
|
type RuleOperator = (typeof RULE_OPERATORS)[number];
|
|
81
|
-
declare const RULE_FIELDS: readonly ["user.attribute", "account.attribute", "user.role", "user.plan", "url.path", "url.full", "url.query", "device.type", "device.browser", "device.os", "visitor.firstVisit", "visitor.returning", "event.seen", "guide.completed", "guide.dismissed", "guide.seen", "checklist.completed", "audience.member", "datetime.now", "datetime.dayOfWeek", "datetime.hour", "rollout.percentage", "environment", "locale", "app.platform", "app.screen", "app.version"];
|
|
81
|
+
declare const RULE_FIELDS: readonly ["user.attribute", "account.attribute", "user.role", "user.plan", "user.identified", "url.path", "url.full", "url.query", "device.type", "device.browser", "device.os", "visitor.firstVisit", "visitor.returning", "event.seen", "guide.completed", "guide.dismissed", "guide.seen", "checklist.completed", "audience.member", "datetime.now", "datetime.dayOfWeek", "datetime.hour", "rollout.percentage", "environment", "locale", "app.platform", "app.screen", "app.version"];
|
|
82
82
|
type RuleField = (typeof RULE_FIELDS)[number];
|
|
83
83
|
interface Rule {
|
|
84
84
|
id: string;
|
|
@@ -137,6 +137,15 @@ declare function evaluateRule(rule: Rule, ctx: TargetingContext): boolean;
|
|
|
137
137
|
declare function evaluateRules(group: RuleGroup | null | undefined, ctx: TargetingContext): boolean;
|
|
138
138
|
/** Fields whose evaluation requires server-held data. Used by docs/UI to annotate rules. */
|
|
139
139
|
declare const SERVER_ASSISTED_FIELDS: RuleField[];
|
|
140
|
+
/** Who a guide is shown to, before its targeting rules: everyone, only signed-in (identified) users, or only anonymous visitors. */
|
|
141
|
+
declare const GUIDE_VISIBILITIES: readonly ["everyone", "identified", "anonymous"];
|
|
142
|
+
type GuideVisibility = (typeof GUIDE_VISIBILITIES)[number];
|
|
143
|
+
/**
|
|
144
|
+
* Targeting with the visibility folded in as a `user.identified` rule. The server sends guides to SDKs
|
|
145
|
+
* this way, so every SDK applies it through the rules it already evaluates (SDKs that predate the field
|
|
146
|
+
* resolve it as undefined and show the guide to nobody rather than to everyone).
|
|
147
|
+
*/
|
|
148
|
+
declare function withVisibility(targeting: RuleGroup, visibility: GuideVisibility | undefined): RuleGroup;
|
|
140
149
|
declare function describeRule(rule: Rule): string;
|
|
141
150
|
|
|
142
151
|
/** Reserved property names that are stripped from `properties` to avoid collecting sensitive data. */
|
|
@@ -196,6 +205,61 @@ declare const CAPTURE_PARAM = "guidely_capture";
|
|
|
196
205
|
/** Largest screenshot the capture endpoint accepts. */
|
|
197
206
|
declare const CAPTURE_SCREENSHOT_MAX_BYTES: number;
|
|
198
207
|
|
|
208
|
+
/** Complaint types and limits shared by the server and the messenger runtime (zod-free). */
|
|
209
|
+
/** Where a complaint is in its handling; the messenger shows it as Received → In review → Resolved. */
|
|
210
|
+
declare const COMPLAINT_STATUSES: readonly ["open", "in_review", "resolved"];
|
|
211
|
+
type ComplaintStatus = (typeof COMPLAINT_STATUSES)[number];
|
|
212
|
+
/** Events a complaint webhook can fire on. */
|
|
213
|
+
declare const COMPLAINT_EVENTS: readonly ["complaint.filed", "complaint.status_changed", "complaint.replied", "complaint.resolved"];
|
|
214
|
+
type ComplaintEvent = (typeof COMPLAINT_EVENTS)[number];
|
|
215
|
+
/** Extra questions a category asks for. */
|
|
216
|
+
declare const COMPLAINT_FIELD_TYPES: readonly ["text", "choice"];
|
|
217
|
+
type ComplaintFieldType = (typeof COMPLAINT_FIELD_TYPES)[number];
|
|
218
|
+
declare const MAX_COMPLAINT_FIELDS = 8;
|
|
219
|
+
declare const MAX_COMPLAINT_CHOICES = 12;
|
|
220
|
+
declare const MAX_COMPLAINT_LENGTH = 4000;
|
|
221
|
+
declare const MAX_COMPLAINT_ANSWER_LENGTH = 500;
|
|
222
|
+
/** Largest screenshot the messenger may attach (after it scales the image down). */
|
|
223
|
+
declare const MAX_COMPLAINT_ATTACHMENT_BYTES: number;
|
|
224
|
+
interface ComplaintField {
|
|
225
|
+
/** Stable id (`invoice_number`), used as the answer's key in webhook payloads. */
|
|
226
|
+
id: string;
|
|
227
|
+
label: string;
|
|
228
|
+
type: ComplaintFieldType;
|
|
229
|
+
/** Choices for `choice` questions. */
|
|
230
|
+
options?: string[];
|
|
231
|
+
required: boolean;
|
|
232
|
+
}
|
|
233
|
+
/** "CMP-1042" for complaint number 1042. */
|
|
234
|
+
declare const complaintReference: (number: number) => string;
|
|
235
|
+
/** A category as the messenger offers it. */
|
|
236
|
+
interface MessengerComplaintCategory {
|
|
237
|
+
id: string;
|
|
238
|
+
name: string;
|
|
239
|
+
description: string;
|
|
240
|
+
color: string;
|
|
241
|
+
fields: ComplaintField[];
|
|
242
|
+
}
|
|
243
|
+
/** Complaints block of `MessengerConfig`; absent when the project doesn't take complaints. */
|
|
244
|
+
interface MessengerComplaintsConfig {
|
|
245
|
+
categories: MessengerComplaintCategory[];
|
|
246
|
+
/** Visitors the app hasn't identified may file one (with an email address). */
|
|
247
|
+
anonymous: boolean;
|
|
248
|
+
}
|
|
249
|
+
/** A complaint as the person who filed it sees it (on its conversation). */
|
|
250
|
+
interface MessengerComplaint {
|
|
251
|
+
id: string;
|
|
252
|
+
reference: string;
|
|
253
|
+
status: ComplaintStatus;
|
|
254
|
+
categoryName: string;
|
|
255
|
+
createdAt: string;
|
|
256
|
+
}
|
|
257
|
+
/** Scout offered the complaint form in a reply, with this category picked. */
|
|
258
|
+
interface MessengerComplaintOffer {
|
|
259
|
+
categoryId: string;
|
|
260
|
+
name: string;
|
|
261
|
+
}
|
|
262
|
+
|
|
199
263
|
/** rrweb plugin name for network events in recordings (event type 6, `data.plugin`). */
|
|
200
264
|
declare const NETWORK_PLUGIN = "guidely/network@1";
|
|
201
265
|
/** Request kinds, from `fetch`/`XMLHttpRequest` patching or `PerformanceResourceTiming.initiatorType`. */
|
|
@@ -385,8 +449,44 @@ declare function resourceCenterSections<C extends RcCollectionLike, A extends Rc
|
|
|
385
449
|
* it must match. For articles outside a loaded list (e.g. server search results).
|
|
386
450
|
*/
|
|
387
451
|
declare function isArticleListed(collections: readonly RcCollectionLike[], article: RcArticleLike, member?: Membership): boolean;
|
|
452
|
+
/** Who an article is listed for, besides its audiences: everyone, or logged-in (identified) visitors only. */
|
|
453
|
+
declare const ARTICLE_VISIBILITIES: readonly ["everyone", "identified"];
|
|
454
|
+
type ArticleVisibility = (typeof ARTICLE_VISIBILITIES)[number];
|
|
455
|
+
/**
|
|
456
|
+
* Reserved audience every logged-in visitor belongs to. The server folds an article's visibility into
|
|
457
|
+
* the audiences it serves and adds this one to identified visitors' memberships, so every SDK (old ones
|
|
458
|
+
* too) applies "logged-in only" through the audience matching it already does. Anonymous visitors never
|
|
459
|
+
* identify, so their membership is empty and these articles stay hidden.
|
|
460
|
+
*/
|
|
461
|
+
declare const LOGGED_IN_AUDIENCE = "$identified";
|
|
462
|
+
/**
|
|
463
|
+
* The audiences an article is served with. Logged-in only with no audiences becomes the reserved
|
|
464
|
+
* audience; with audiences it is already implied, since audience membership only comes from identify.
|
|
465
|
+
*/
|
|
466
|
+
declare function servedArticleAudiences(audienceIds: readonly string[], visibility: ArticleVisibility | string | null | undefined): string[];
|
|
467
|
+
/** A visitor's memberships as matched against served articles: logged-in visitors are also in `LOGGED_IN_AUDIENCE`. */
|
|
468
|
+
declare function visitorAudiences(audienceIds: readonly string[], identified: boolean): string[];
|
|
388
469
|
/** Ids of the articles a viewer sees (for filtering server search results the same way). */
|
|
389
470
|
declare function visibleArticleIds(collections: readonly RcCollectionLike[], articles: readonly RcArticleLike[], member?: Membership): Set<string>;
|
|
471
|
+
/**
|
|
472
|
+
* A "Show me" prompt in an article body is a plain link, `<p class="gd-show-me"><a href="#guidely-show-me:<guide key>">Show me how</a></p>`,
|
|
473
|
+
* so it survives every sanitizer and reads as a harmless link anywhere else. The widgets turn it into a
|
|
474
|
+
* button that starts the walkthrough (a live flow guide), or hide it when that guide isn't available.
|
|
475
|
+
*/
|
|
476
|
+
declare const SHOW_ME_CLASS = "gd-show-me";
|
|
477
|
+
declare const SHOW_ME_HREF_PREFIX = "#guidely-show-me:";
|
|
478
|
+
declare function showMeHref(guideKey: string): string;
|
|
479
|
+
/** The guide key of a Show me link's `href`, or null. */
|
|
480
|
+
declare function showMeKeyFromHref(href: string | null | undefined): string | null;
|
|
481
|
+
/** Guide keys of the Show me prompts in an article body, in order, without repeats (at most 10). */
|
|
482
|
+
declare function showMeKeys(html: string | null | undefined): string[];
|
|
483
|
+
/** The article body plays a video (uploaded, or embedded from YouTube, Vimeo, Loom or Wistia). */
|
|
484
|
+
declare function hasVideoMedia(html: string | null | undefined): boolean;
|
|
485
|
+
/**
|
|
486
|
+
* Help search on the device: every word of the query starts a word of the text, in any order, or the
|
|
487
|
+
* query appears as typed. "add user" finds "Add a new user" and "Users › Add".
|
|
488
|
+
*/
|
|
489
|
+
declare function matchesHelpQuery(text: string, query: string): boolean;
|
|
390
490
|
|
|
391
491
|
/**
|
|
392
492
|
* Page helpers shared by the SDK (page-aware messenger) and the server (page matching, analytics).
|
|
@@ -395,10 +495,11 @@ declare function visibleArticleIds(collections: readonly RcCollectionLike[], art
|
|
|
395
495
|
/**
|
|
396
496
|
* One path segment that looks like an identifier: digits, a UUID, or a long hex string (hashes,
|
|
397
497
|
* Mongo ids). Written so the same source works as a JS RegExp and a Postgres ARE (`regexp_replace`
|
|
398
|
-
* with flags `gi`), which keeps id folding identical in SQL and in code.
|
|
498
|
+
* with flags `gi`), which keeps id folding identical in SQL and in code. A segment may be followed
|
|
499
|
+
* by the page query parameters a project keeps in its paths (`/contacts/42?tab=notes`).
|
|
399
500
|
*/
|
|
400
|
-
declare const PATH_ID_PATTERN = "/([0-9]+|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|[0-9a-f]{12,})(
|
|
401
|
-
/** `/contacts/42/notes/9f8e…` → `/contacts/:id/notes/:id`. */
|
|
501
|
+
declare const PATH_ID_PATTERN = "/([0-9]+|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|[0-9a-f]{12,})(?=[/?]|$)";
|
|
502
|
+
/** `/contacts/42/notes/9f8e…` → `/contacts/:id/notes/:id`; `/contacts/42?tab=notes` → `/contacts/:id?tab=notes`. */
|
|
402
503
|
declare function foldPathIds(path: string): string;
|
|
403
504
|
/** Words describing a page, from its path (`/settings/billing-plans/42` → `settings billing plans`). */
|
|
404
505
|
declare function pageTerms(path: string): string[];
|
|
@@ -407,4 +508,4 @@ declare function pageLabel(path: string): string | null;
|
|
|
407
508
|
/** The first name in a user's traits (`firstName`, `first_name`, or the first word of `name`), or null. */
|
|
408
509
|
declare function firstNameFromTraits(traits: Record<string, unknown> | null | undefined): string | null;
|
|
409
510
|
|
|
410
|
-
export { CAPTURE_PARAM, CAPTURE_SCREENSHOT_MAX_BYTES, DEFAULT_PLATFORMS, EMBED_IFRAME_ATTRS, type EmbedProvider, type ExceptionProperties, FILE_LINK_CLASS, GUIDELY_ID_ATTRIBUTE, MAX_COLLECTION_DEPTH, MAX_PROPERTY_BYTES, MAX_STACK_FRAMES, MEDIA_FILE_MAX_BYTES, MEDIA_FILE_TYPES, MEDIA_IMAGE_MAX_BYTES, MEDIA_IMAGE_TYPES, MEDIA_MAX_BYTES, MEDIA_VIDEO_MAX_BYTES, MEDIA_VIDEO_TYPES, type MediaContentType, type MediaKind, NETWORK_PLUGIN, type NetworkPluginPayload, type NetworkRequest, type NetworkRequestType, PATH_ID_PATTERN, PDF_BLOCK_CLASS, PDF_MAX_PAGES, PDF_PAGES_CLASS, PLATFORMS, type Platform, RULE_FIELDS, RULE_OPERATORS, type RcArticleLike, type RcCollectionLike, type RcSection, type Rule, type RuleField, type RuleGroup, type RuleOperator, SENSITIVE_HEADER_PATTERN, SENSITIVE_PARAM_PATTERN, SENSITIVE_PROPERTY_PATTERN, SERVER_ASSISTED_FIELDS, SOURCEMAP_MAX_FILES_PER_UPLOAD, SOURCEMAP_MAX_FILE_BYTES, type ShowWhen, type StackFrame, type SurveyAnswer, type SurveyAnswers, type TargetingContext, VIDEO_ATTRS, type VideoEmbed, WS_MAX_MESSAGES_PER_SOCKET, WS_MAX_MESSAGE_BYTES, type WebSocketMessage, clamp, compare, compareVersions, describeRule, emptyRuleGroup, evaluateRule, evaluateRules, fingerprintError, firstNameFromTraits, fnv1a, foldPathIds, getPath, guidePlatforms, guidelyIdFromSelector, isAllowedEmbedSrc, isArticleListed, isChecklistComplete, isFileLink, isMediaContentType, isPlainObject, isQuestionVisible, isRuleGroup, isSafeMediaUrl, isVideoContentType, matchUrlPattern, matchesAudiences, mediaKind, mediaMaxBytes, normalizeErrorMessage, normalizeFrameFile, pageLabel, pageTerms, parseStack, randomId, resourceCenterSections, rolloutBucket, safeRegExp, sanitizeProperties, screenPath, slugify, stripOrigin, supportsPlatform, toEmbedUrl, visibleArticleIds };
|
|
511
|
+
export { ARTICLE_VISIBILITIES, type ArticleVisibility, CAPTURE_PARAM, CAPTURE_SCREENSHOT_MAX_BYTES, COMPLAINT_EVENTS, COMPLAINT_FIELD_TYPES, COMPLAINT_STATUSES, type ComplaintEvent, type ComplaintField, type ComplaintFieldType, type ComplaintStatus, DEFAULT_PLATFORMS, EMBED_IFRAME_ATTRS, type EmbedProvider, type ExceptionProperties, FILE_LINK_CLASS, GUIDELY_ID_ATTRIBUTE, GUIDE_VISIBILITIES, type GuideVisibility, LOGGED_IN_AUDIENCE, MAX_COLLECTION_DEPTH, MAX_COMPLAINT_ANSWER_LENGTH, MAX_COMPLAINT_ATTACHMENT_BYTES, MAX_COMPLAINT_CHOICES, MAX_COMPLAINT_FIELDS, MAX_COMPLAINT_LENGTH, MAX_PROPERTY_BYTES, MAX_STACK_FRAMES, MEDIA_FILE_MAX_BYTES, MEDIA_FILE_TYPES, MEDIA_IMAGE_MAX_BYTES, MEDIA_IMAGE_TYPES, MEDIA_MAX_BYTES, MEDIA_VIDEO_MAX_BYTES, MEDIA_VIDEO_TYPES, type MediaContentType, type MediaKind, type MessengerComplaint, type MessengerComplaintCategory, type MessengerComplaintOffer, type MessengerComplaintsConfig, NETWORK_PLUGIN, type NetworkPluginPayload, type NetworkRequest, type NetworkRequestType, PATH_ID_PATTERN, PDF_BLOCK_CLASS, PDF_MAX_PAGES, PDF_PAGES_CLASS, PLATFORMS, type Platform, RULE_FIELDS, RULE_OPERATORS, type RcArticleLike, type RcCollectionLike, type RcSection, type Rule, type RuleField, type RuleGroup, type RuleOperator, SENSITIVE_HEADER_PATTERN, SENSITIVE_PARAM_PATTERN, SENSITIVE_PROPERTY_PATTERN, SERVER_ASSISTED_FIELDS, SHOW_ME_CLASS, SHOW_ME_HREF_PREFIX, SOURCEMAP_MAX_FILES_PER_UPLOAD, SOURCEMAP_MAX_FILE_BYTES, type ShowWhen, type StackFrame, type SurveyAnswer, type SurveyAnswers, type TargetingContext, VIDEO_ATTRS, type VideoEmbed, WS_MAX_MESSAGES_PER_SOCKET, WS_MAX_MESSAGE_BYTES, type WebSocketMessage, clamp, compare, compareVersions, complaintReference, describeRule, emptyRuleGroup, evaluateRule, evaluateRules, fingerprintError, firstNameFromTraits, fnv1a, foldPathIds, getPath, guidePlatforms, guidelyIdFromSelector, hasVideoMedia, isAllowedEmbedSrc, isArticleListed, isChecklistComplete, isFileLink, isMediaContentType, isPlainObject, isQuestionVisible, isRuleGroup, isSafeMediaUrl, isVideoContentType, matchUrlPattern, matchesAudiences, matchesHelpQuery, mediaKind, mediaMaxBytes, normalizeErrorMessage, normalizeFrameFile, pageLabel, pageTerms, parseStack, randomId, resourceCenterSections, rolloutBucket, safeRegExp, sanitizeProperties, screenPath, servedArticleAudiences, showMeHref, showMeKeyFromHref, showMeKeys, slugify, stripOrigin, supportsPlatform, toEmbedUrl, visibleArticleIds, visitorAudiences, withVisibility };
|
package/dist/runtime.d.ts
CHANGED
|
@@ -78,7 +78,7 @@ declare function isChecklistComplete(config: {
|
|
|
78
78
|
|
|
79
79
|
declare const RULE_OPERATORS: readonly ["equals", "not_equals", "contains", "not_contains", "starts_with", "ends_with", "exists", "not_exists", "gt", "gte", "lt", "lte", "in", "not_in", "regex", "is_true", "is_false", "before", "after"];
|
|
80
80
|
type RuleOperator = (typeof RULE_OPERATORS)[number];
|
|
81
|
-
declare const RULE_FIELDS: readonly ["user.attribute", "account.attribute", "user.role", "user.plan", "url.path", "url.full", "url.query", "device.type", "device.browser", "device.os", "visitor.firstVisit", "visitor.returning", "event.seen", "guide.completed", "guide.dismissed", "guide.seen", "checklist.completed", "audience.member", "datetime.now", "datetime.dayOfWeek", "datetime.hour", "rollout.percentage", "environment", "locale", "app.platform", "app.screen", "app.version"];
|
|
81
|
+
declare const RULE_FIELDS: readonly ["user.attribute", "account.attribute", "user.role", "user.plan", "user.identified", "url.path", "url.full", "url.query", "device.type", "device.browser", "device.os", "visitor.firstVisit", "visitor.returning", "event.seen", "guide.completed", "guide.dismissed", "guide.seen", "checklist.completed", "audience.member", "datetime.now", "datetime.dayOfWeek", "datetime.hour", "rollout.percentage", "environment", "locale", "app.platform", "app.screen", "app.version"];
|
|
82
82
|
type RuleField = (typeof RULE_FIELDS)[number];
|
|
83
83
|
interface Rule {
|
|
84
84
|
id: string;
|
|
@@ -137,6 +137,15 @@ declare function evaluateRule(rule: Rule, ctx: TargetingContext): boolean;
|
|
|
137
137
|
declare function evaluateRules(group: RuleGroup | null | undefined, ctx: TargetingContext): boolean;
|
|
138
138
|
/** Fields whose evaluation requires server-held data. Used by docs/UI to annotate rules. */
|
|
139
139
|
declare const SERVER_ASSISTED_FIELDS: RuleField[];
|
|
140
|
+
/** Who a guide is shown to, before its targeting rules: everyone, only signed-in (identified) users, or only anonymous visitors. */
|
|
141
|
+
declare const GUIDE_VISIBILITIES: readonly ["everyone", "identified", "anonymous"];
|
|
142
|
+
type GuideVisibility = (typeof GUIDE_VISIBILITIES)[number];
|
|
143
|
+
/**
|
|
144
|
+
* Targeting with the visibility folded in as a `user.identified` rule. The server sends guides to SDKs
|
|
145
|
+
* this way, so every SDK applies it through the rules it already evaluates (SDKs that predate the field
|
|
146
|
+
* resolve it as undefined and show the guide to nobody rather than to everyone).
|
|
147
|
+
*/
|
|
148
|
+
declare function withVisibility(targeting: RuleGroup, visibility: GuideVisibility | undefined): RuleGroup;
|
|
140
149
|
declare function describeRule(rule: Rule): string;
|
|
141
150
|
|
|
142
151
|
/** Reserved property names that are stripped from `properties` to avoid collecting sensitive data. */
|
|
@@ -196,6 +205,61 @@ declare const CAPTURE_PARAM = "guidely_capture";
|
|
|
196
205
|
/** Largest screenshot the capture endpoint accepts. */
|
|
197
206
|
declare const CAPTURE_SCREENSHOT_MAX_BYTES: number;
|
|
198
207
|
|
|
208
|
+
/** Complaint types and limits shared by the server and the messenger runtime (zod-free). */
|
|
209
|
+
/** Where a complaint is in its handling; the messenger shows it as Received → In review → Resolved. */
|
|
210
|
+
declare const COMPLAINT_STATUSES: readonly ["open", "in_review", "resolved"];
|
|
211
|
+
type ComplaintStatus = (typeof COMPLAINT_STATUSES)[number];
|
|
212
|
+
/** Events a complaint webhook can fire on. */
|
|
213
|
+
declare const COMPLAINT_EVENTS: readonly ["complaint.filed", "complaint.status_changed", "complaint.replied", "complaint.resolved"];
|
|
214
|
+
type ComplaintEvent = (typeof COMPLAINT_EVENTS)[number];
|
|
215
|
+
/** Extra questions a category asks for. */
|
|
216
|
+
declare const COMPLAINT_FIELD_TYPES: readonly ["text", "choice"];
|
|
217
|
+
type ComplaintFieldType = (typeof COMPLAINT_FIELD_TYPES)[number];
|
|
218
|
+
declare const MAX_COMPLAINT_FIELDS = 8;
|
|
219
|
+
declare const MAX_COMPLAINT_CHOICES = 12;
|
|
220
|
+
declare const MAX_COMPLAINT_LENGTH = 4000;
|
|
221
|
+
declare const MAX_COMPLAINT_ANSWER_LENGTH = 500;
|
|
222
|
+
/** Largest screenshot the messenger may attach (after it scales the image down). */
|
|
223
|
+
declare const MAX_COMPLAINT_ATTACHMENT_BYTES: number;
|
|
224
|
+
interface ComplaintField {
|
|
225
|
+
/** Stable id (`invoice_number`), used as the answer's key in webhook payloads. */
|
|
226
|
+
id: string;
|
|
227
|
+
label: string;
|
|
228
|
+
type: ComplaintFieldType;
|
|
229
|
+
/** Choices for `choice` questions. */
|
|
230
|
+
options?: string[];
|
|
231
|
+
required: boolean;
|
|
232
|
+
}
|
|
233
|
+
/** "CMP-1042" for complaint number 1042. */
|
|
234
|
+
declare const complaintReference: (number: number) => string;
|
|
235
|
+
/** A category as the messenger offers it. */
|
|
236
|
+
interface MessengerComplaintCategory {
|
|
237
|
+
id: string;
|
|
238
|
+
name: string;
|
|
239
|
+
description: string;
|
|
240
|
+
color: string;
|
|
241
|
+
fields: ComplaintField[];
|
|
242
|
+
}
|
|
243
|
+
/** Complaints block of `MessengerConfig`; absent when the project doesn't take complaints. */
|
|
244
|
+
interface MessengerComplaintsConfig {
|
|
245
|
+
categories: MessengerComplaintCategory[];
|
|
246
|
+
/** Visitors the app hasn't identified may file one (with an email address). */
|
|
247
|
+
anonymous: boolean;
|
|
248
|
+
}
|
|
249
|
+
/** A complaint as the person who filed it sees it (on its conversation). */
|
|
250
|
+
interface MessengerComplaint {
|
|
251
|
+
id: string;
|
|
252
|
+
reference: string;
|
|
253
|
+
status: ComplaintStatus;
|
|
254
|
+
categoryName: string;
|
|
255
|
+
createdAt: string;
|
|
256
|
+
}
|
|
257
|
+
/** Scout offered the complaint form in a reply, with this category picked. */
|
|
258
|
+
interface MessengerComplaintOffer {
|
|
259
|
+
categoryId: string;
|
|
260
|
+
name: string;
|
|
261
|
+
}
|
|
262
|
+
|
|
199
263
|
/** rrweb plugin name for network events in recordings (event type 6, `data.plugin`). */
|
|
200
264
|
declare const NETWORK_PLUGIN = "guidely/network@1";
|
|
201
265
|
/** Request kinds, from `fetch`/`XMLHttpRequest` patching or `PerformanceResourceTiming.initiatorType`. */
|
|
@@ -385,8 +449,44 @@ declare function resourceCenterSections<C extends RcCollectionLike, A extends Rc
|
|
|
385
449
|
* it must match. For articles outside a loaded list (e.g. server search results).
|
|
386
450
|
*/
|
|
387
451
|
declare function isArticleListed(collections: readonly RcCollectionLike[], article: RcArticleLike, member?: Membership): boolean;
|
|
452
|
+
/** Who an article is listed for, besides its audiences: everyone, or logged-in (identified) visitors only. */
|
|
453
|
+
declare const ARTICLE_VISIBILITIES: readonly ["everyone", "identified"];
|
|
454
|
+
type ArticleVisibility = (typeof ARTICLE_VISIBILITIES)[number];
|
|
455
|
+
/**
|
|
456
|
+
* Reserved audience every logged-in visitor belongs to. The server folds an article's visibility into
|
|
457
|
+
* the audiences it serves and adds this one to identified visitors' memberships, so every SDK (old ones
|
|
458
|
+
* too) applies "logged-in only" through the audience matching it already does. Anonymous visitors never
|
|
459
|
+
* identify, so their membership is empty and these articles stay hidden.
|
|
460
|
+
*/
|
|
461
|
+
declare const LOGGED_IN_AUDIENCE = "$identified";
|
|
462
|
+
/**
|
|
463
|
+
* The audiences an article is served with. Logged-in only with no audiences becomes the reserved
|
|
464
|
+
* audience; with audiences it is already implied, since audience membership only comes from identify.
|
|
465
|
+
*/
|
|
466
|
+
declare function servedArticleAudiences(audienceIds: readonly string[], visibility: ArticleVisibility | string | null | undefined): string[];
|
|
467
|
+
/** A visitor's memberships as matched against served articles: logged-in visitors are also in `LOGGED_IN_AUDIENCE`. */
|
|
468
|
+
declare function visitorAudiences(audienceIds: readonly string[], identified: boolean): string[];
|
|
388
469
|
/** Ids of the articles a viewer sees (for filtering server search results the same way). */
|
|
389
470
|
declare function visibleArticleIds(collections: readonly RcCollectionLike[], articles: readonly RcArticleLike[], member?: Membership): Set<string>;
|
|
471
|
+
/**
|
|
472
|
+
* A "Show me" prompt in an article body is a plain link, `<p class="gd-show-me"><a href="#guidely-show-me:<guide key>">Show me how</a></p>`,
|
|
473
|
+
* so it survives every sanitizer and reads as a harmless link anywhere else. The widgets turn it into a
|
|
474
|
+
* button that starts the walkthrough (a live flow guide), or hide it when that guide isn't available.
|
|
475
|
+
*/
|
|
476
|
+
declare const SHOW_ME_CLASS = "gd-show-me";
|
|
477
|
+
declare const SHOW_ME_HREF_PREFIX = "#guidely-show-me:";
|
|
478
|
+
declare function showMeHref(guideKey: string): string;
|
|
479
|
+
/** The guide key of a Show me link's `href`, or null. */
|
|
480
|
+
declare function showMeKeyFromHref(href: string | null | undefined): string | null;
|
|
481
|
+
/** Guide keys of the Show me prompts in an article body, in order, without repeats (at most 10). */
|
|
482
|
+
declare function showMeKeys(html: string | null | undefined): string[];
|
|
483
|
+
/** The article body plays a video (uploaded, or embedded from YouTube, Vimeo, Loom or Wistia). */
|
|
484
|
+
declare function hasVideoMedia(html: string | null | undefined): boolean;
|
|
485
|
+
/**
|
|
486
|
+
* Help search on the device: every word of the query starts a word of the text, in any order, or the
|
|
487
|
+
* query appears as typed. "add user" finds "Add a new user" and "Users › Add".
|
|
488
|
+
*/
|
|
489
|
+
declare function matchesHelpQuery(text: string, query: string): boolean;
|
|
390
490
|
|
|
391
491
|
/**
|
|
392
492
|
* Page helpers shared by the SDK (page-aware messenger) and the server (page matching, analytics).
|
|
@@ -395,10 +495,11 @@ declare function visibleArticleIds(collections: readonly RcCollectionLike[], art
|
|
|
395
495
|
/**
|
|
396
496
|
* One path segment that looks like an identifier: digits, a UUID, or a long hex string (hashes,
|
|
397
497
|
* Mongo ids). Written so the same source works as a JS RegExp and a Postgres ARE (`regexp_replace`
|
|
398
|
-
* with flags `gi`), which keeps id folding identical in SQL and in code.
|
|
498
|
+
* with flags `gi`), which keeps id folding identical in SQL and in code. A segment may be followed
|
|
499
|
+
* by the page query parameters a project keeps in its paths (`/contacts/42?tab=notes`).
|
|
399
500
|
*/
|
|
400
|
-
declare const PATH_ID_PATTERN = "/([0-9]+|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|[0-9a-f]{12,})(
|
|
401
|
-
/** `/contacts/42/notes/9f8e…` → `/contacts/:id/notes/:id`. */
|
|
501
|
+
declare const PATH_ID_PATTERN = "/([0-9]+|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|[0-9a-f]{12,})(?=[/?]|$)";
|
|
502
|
+
/** `/contacts/42/notes/9f8e…` → `/contacts/:id/notes/:id`; `/contacts/42?tab=notes` → `/contacts/:id?tab=notes`. */
|
|
402
503
|
declare function foldPathIds(path: string): string;
|
|
403
504
|
/** Words describing a page, from its path (`/settings/billing-plans/42` → `settings billing plans`). */
|
|
404
505
|
declare function pageTerms(path: string): string[];
|
|
@@ -407,4 +508,4 @@ declare function pageLabel(path: string): string | null;
|
|
|
407
508
|
/** The first name in a user's traits (`firstName`, `first_name`, or the first word of `name`), or null. */
|
|
408
509
|
declare function firstNameFromTraits(traits: Record<string, unknown> | null | undefined): string | null;
|
|
409
510
|
|
|
410
|
-
export { CAPTURE_PARAM, CAPTURE_SCREENSHOT_MAX_BYTES, DEFAULT_PLATFORMS, EMBED_IFRAME_ATTRS, type EmbedProvider, type ExceptionProperties, FILE_LINK_CLASS, GUIDELY_ID_ATTRIBUTE, MAX_COLLECTION_DEPTH, MAX_PROPERTY_BYTES, MAX_STACK_FRAMES, MEDIA_FILE_MAX_BYTES, MEDIA_FILE_TYPES, MEDIA_IMAGE_MAX_BYTES, MEDIA_IMAGE_TYPES, MEDIA_MAX_BYTES, MEDIA_VIDEO_MAX_BYTES, MEDIA_VIDEO_TYPES, type MediaContentType, type MediaKind, NETWORK_PLUGIN, type NetworkPluginPayload, type NetworkRequest, type NetworkRequestType, PATH_ID_PATTERN, PDF_BLOCK_CLASS, PDF_MAX_PAGES, PDF_PAGES_CLASS, PLATFORMS, type Platform, RULE_FIELDS, RULE_OPERATORS, type RcArticleLike, type RcCollectionLike, type RcSection, type Rule, type RuleField, type RuleGroup, type RuleOperator, SENSITIVE_HEADER_PATTERN, SENSITIVE_PARAM_PATTERN, SENSITIVE_PROPERTY_PATTERN, SERVER_ASSISTED_FIELDS, SOURCEMAP_MAX_FILES_PER_UPLOAD, SOURCEMAP_MAX_FILE_BYTES, type ShowWhen, type StackFrame, type SurveyAnswer, type SurveyAnswers, type TargetingContext, VIDEO_ATTRS, type VideoEmbed, WS_MAX_MESSAGES_PER_SOCKET, WS_MAX_MESSAGE_BYTES, type WebSocketMessage, clamp, compare, compareVersions, describeRule, emptyRuleGroup, evaluateRule, evaluateRules, fingerprintError, firstNameFromTraits, fnv1a, foldPathIds, getPath, guidePlatforms, guidelyIdFromSelector, isAllowedEmbedSrc, isArticleListed, isChecklistComplete, isFileLink, isMediaContentType, isPlainObject, isQuestionVisible, isRuleGroup, isSafeMediaUrl, isVideoContentType, matchUrlPattern, matchesAudiences, mediaKind, mediaMaxBytes, normalizeErrorMessage, normalizeFrameFile, pageLabel, pageTerms, parseStack, randomId, resourceCenterSections, rolloutBucket, safeRegExp, sanitizeProperties, screenPath, slugify, stripOrigin, supportsPlatform, toEmbedUrl, visibleArticleIds };
|
|
511
|
+
export { ARTICLE_VISIBILITIES, type ArticleVisibility, CAPTURE_PARAM, CAPTURE_SCREENSHOT_MAX_BYTES, COMPLAINT_EVENTS, COMPLAINT_FIELD_TYPES, COMPLAINT_STATUSES, type ComplaintEvent, type ComplaintField, type ComplaintFieldType, type ComplaintStatus, DEFAULT_PLATFORMS, EMBED_IFRAME_ATTRS, type EmbedProvider, type ExceptionProperties, FILE_LINK_CLASS, GUIDELY_ID_ATTRIBUTE, GUIDE_VISIBILITIES, type GuideVisibility, LOGGED_IN_AUDIENCE, MAX_COLLECTION_DEPTH, MAX_COMPLAINT_ANSWER_LENGTH, MAX_COMPLAINT_ATTACHMENT_BYTES, MAX_COMPLAINT_CHOICES, MAX_COMPLAINT_FIELDS, MAX_COMPLAINT_LENGTH, MAX_PROPERTY_BYTES, MAX_STACK_FRAMES, MEDIA_FILE_MAX_BYTES, MEDIA_FILE_TYPES, MEDIA_IMAGE_MAX_BYTES, MEDIA_IMAGE_TYPES, MEDIA_MAX_BYTES, MEDIA_VIDEO_MAX_BYTES, MEDIA_VIDEO_TYPES, type MediaContentType, type MediaKind, type MessengerComplaint, type MessengerComplaintCategory, type MessengerComplaintOffer, type MessengerComplaintsConfig, NETWORK_PLUGIN, type NetworkPluginPayload, type NetworkRequest, type NetworkRequestType, PATH_ID_PATTERN, PDF_BLOCK_CLASS, PDF_MAX_PAGES, PDF_PAGES_CLASS, PLATFORMS, type Platform, RULE_FIELDS, RULE_OPERATORS, type RcArticleLike, type RcCollectionLike, type RcSection, type Rule, type RuleField, type RuleGroup, type RuleOperator, SENSITIVE_HEADER_PATTERN, SENSITIVE_PARAM_PATTERN, SENSITIVE_PROPERTY_PATTERN, SERVER_ASSISTED_FIELDS, SHOW_ME_CLASS, SHOW_ME_HREF_PREFIX, SOURCEMAP_MAX_FILES_PER_UPLOAD, SOURCEMAP_MAX_FILE_BYTES, type ShowWhen, type StackFrame, type SurveyAnswer, type SurveyAnswers, type TargetingContext, VIDEO_ATTRS, type VideoEmbed, WS_MAX_MESSAGES_PER_SOCKET, WS_MAX_MESSAGE_BYTES, type WebSocketMessage, clamp, compare, compareVersions, complaintReference, describeRule, emptyRuleGroup, evaluateRule, evaluateRules, fingerprintError, firstNameFromTraits, fnv1a, foldPathIds, getPath, guidePlatforms, guidelyIdFromSelector, hasVideoMedia, isAllowedEmbedSrc, isArticleListed, isChecklistComplete, isFileLink, isMediaContentType, isPlainObject, isQuestionVisible, isRuleGroup, isSafeMediaUrl, isVideoContentType, matchUrlPattern, matchesAudiences, matchesHelpQuery, mediaKind, mediaMaxBytes, normalizeErrorMessage, normalizeFrameFile, pageLabel, pageTerms, parseStack, randomId, resourceCenterSections, rolloutBucket, safeRegExp, sanitizeProperties, screenPath, servedArticleAudiences, showMeHref, showMeKeyFromHref, showMeKeys, slugify, stripOrigin, supportsPlatform, toEmbedUrl, visibleArticleIds, visitorAudiences, withVisibility };
|
package/dist/runtime.js
CHANGED
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ARTICLE_VISIBILITIES,
|
|
2
3
|
CAPTURE_PARAM,
|
|
3
4
|
CAPTURE_SCREENSHOT_MAX_BYTES,
|
|
5
|
+
COMPLAINT_EVENTS,
|
|
6
|
+
COMPLAINT_FIELD_TYPES,
|
|
7
|
+
COMPLAINT_STATUSES,
|
|
4
8
|
DEFAULT_PLATFORMS,
|
|
5
9
|
EMBED_IFRAME_ATTRS,
|
|
6
10
|
FILE_LINK_CLASS,
|
|
7
11
|
GUIDELY_ID_ATTRIBUTE,
|
|
12
|
+
GUIDE_VISIBILITIES,
|
|
13
|
+
LOGGED_IN_AUDIENCE,
|
|
8
14
|
MAX_COLLECTION_DEPTH,
|
|
15
|
+
MAX_COMPLAINT_ANSWER_LENGTH,
|
|
16
|
+
MAX_COMPLAINT_ATTACHMENT_BYTES,
|
|
17
|
+
MAX_COMPLAINT_CHOICES,
|
|
18
|
+
MAX_COMPLAINT_FIELDS,
|
|
19
|
+
MAX_COMPLAINT_LENGTH,
|
|
9
20
|
MAX_PROPERTY_BYTES,
|
|
10
21
|
MAX_STACK_FRAMES,
|
|
11
22
|
MEDIA_FILE_MAX_BYTES,
|
|
@@ -27,6 +38,8 @@ import {
|
|
|
27
38
|
SENSITIVE_PARAM_PATTERN,
|
|
28
39
|
SENSITIVE_PROPERTY_PATTERN,
|
|
29
40
|
SERVER_ASSISTED_FIELDS,
|
|
41
|
+
SHOW_ME_CLASS,
|
|
42
|
+
SHOW_ME_HREF_PREFIX,
|
|
30
43
|
SOURCEMAP_MAX_FILES_PER_UPLOAD,
|
|
31
44
|
SOURCEMAP_MAX_FILE_BYTES,
|
|
32
45
|
VIDEO_ATTRS,
|
|
@@ -35,6 +48,7 @@ import {
|
|
|
35
48
|
clamp,
|
|
36
49
|
compare,
|
|
37
50
|
compareVersions,
|
|
51
|
+
complaintReference,
|
|
38
52
|
describeRule,
|
|
39
53
|
emptyRuleGroup,
|
|
40
54
|
evaluateRule,
|
|
@@ -46,6 +60,7 @@ import {
|
|
|
46
60
|
getPath,
|
|
47
61
|
guidePlatforms,
|
|
48
62
|
guidelyIdFromSelector,
|
|
63
|
+
hasVideoMedia,
|
|
49
64
|
isAllowedEmbedSrc,
|
|
50
65
|
isArticleListed,
|
|
51
66
|
isChecklistComplete,
|
|
@@ -58,6 +73,7 @@ import {
|
|
|
58
73
|
isVideoContentType,
|
|
59
74
|
matchUrlPattern,
|
|
60
75
|
matchesAudiences,
|
|
76
|
+
matchesHelpQuery,
|
|
61
77
|
mediaKind,
|
|
62
78
|
mediaMaxBytes,
|
|
63
79
|
normalizeErrorMessage,
|
|
@@ -71,20 +87,37 @@ import {
|
|
|
71
87
|
safeRegExp,
|
|
72
88
|
sanitizeProperties,
|
|
73
89
|
screenPath,
|
|
90
|
+
servedArticleAudiences,
|
|
91
|
+
showMeHref,
|
|
92
|
+
showMeKeyFromHref,
|
|
93
|
+
showMeKeys,
|
|
74
94
|
slugify,
|
|
75
95
|
stripOrigin,
|
|
76
96
|
supportsPlatform,
|
|
77
97
|
toEmbedUrl,
|
|
78
|
-
visibleArticleIds
|
|
79
|
-
|
|
98
|
+
visibleArticleIds,
|
|
99
|
+
visitorAudiences,
|
|
100
|
+
withVisibility
|
|
101
|
+
} from "./chunk-UW6NRYRY.js";
|
|
80
102
|
export {
|
|
103
|
+
ARTICLE_VISIBILITIES,
|
|
81
104
|
CAPTURE_PARAM,
|
|
82
105
|
CAPTURE_SCREENSHOT_MAX_BYTES,
|
|
106
|
+
COMPLAINT_EVENTS,
|
|
107
|
+
COMPLAINT_FIELD_TYPES,
|
|
108
|
+
COMPLAINT_STATUSES,
|
|
83
109
|
DEFAULT_PLATFORMS,
|
|
84
110
|
EMBED_IFRAME_ATTRS,
|
|
85
111
|
FILE_LINK_CLASS,
|
|
86
112
|
GUIDELY_ID_ATTRIBUTE,
|
|
113
|
+
GUIDE_VISIBILITIES,
|
|
114
|
+
LOGGED_IN_AUDIENCE,
|
|
87
115
|
MAX_COLLECTION_DEPTH,
|
|
116
|
+
MAX_COMPLAINT_ANSWER_LENGTH,
|
|
117
|
+
MAX_COMPLAINT_ATTACHMENT_BYTES,
|
|
118
|
+
MAX_COMPLAINT_CHOICES,
|
|
119
|
+
MAX_COMPLAINT_FIELDS,
|
|
120
|
+
MAX_COMPLAINT_LENGTH,
|
|
88
121
|
MAX_PROPERTY_BYTES,
|
|
89
122
|
MAX_STACK_FRAMES,
|
|
90
123
|
MEDIA_FILE_MAX_BYTES,
|
|
@@ -106,6 +139,8 @@ export {
|
|
|
106
139
|
SENSITIVE_PARAM_PATTERN,
|
|
107
140
|
SENSITIVE_PROPERTY_PATTERN,
|
|
108
141
|
SERVER_ASSISTED_FIELDS,
|
|
142
|
+
SHOW_ME_CLASS,
|
|
143
|
+
SHOW_ME_HREF_PREFIX,
|
|
109
144
|
SOURCEMAP_MAX_FILES_PER_UPLOAD,
|
|
110
145
|
SOURCEMAP_MAX_FILE_BYTES,
|
|
111
146
|
VIDEO_ATTRS,
|
|
@@ -114,6 +149,7 @@ export {
|
|
|
114
149
|
clamp,
|
|
115
150
|
compare,
|
|
116
151
|
compareVersions,
|
|
152
|
+
complaintReference,
|
|
117
153
|
describeRule,
|
|
118
154
|
emptyRuleGroup,
|
|
119
155
|
evaluateRule,
|
|
@@ -125,6 +161,7 @@ export {
|
|
|
125
161
|
getPath,
|
|
126
162
|
guidePlatforms,
|
|
127
163
|
guidelyIdFromSelector,
|
|
164
|
+
hasVideoMedia,
|
|
128
165
|
isAllowedEmbedSrc,
|
|
129
166
|
isArticleListed,
|
|
130
167
|
isChecklistComplete,
|
|
@@ -137,6 +174,7 @@ export {
|
|
|
137
174
|
isVideoContentType,
|
|
138
175
|
matchUrlPattern,
|
|
139
176
|
matchesAudiences,
|
|
177
|
+
matchesHelpQuery,
|
|
140
178
|
mediaKind,
|
|
141
179
|
mediaMaxBytes,
|
|
142
180
|
normalizeErrorMessage,
|
|
@@ -150,10 +188,16 @@ export {
|
|
|
150
188
|
safeRegExp,
|
|
151
189
|
sanitizeProperties,
|
|
152
190
|
screenPath,
|
|
191
|
+
servedArticleAudiences,
|
|
192
|
+
showMeHref,
|
|
193
|
+
showMeKeyFromHref,
|
|
194
|
+
showMeKeys,
|
|
153
195
|
slugify,
|
|
154
196
|
stripOrigin,
|
|
155
197
|
supportsPlatform,
|
|
156
198
|
toEmbedUrl,
|
|
157
|
-
visibleArticleIds
|
|
199
|
+
visibleArticleIds,
|
|
200
|
+
visitorAudiences,
|
|
201
|
+
withVisibility
|
|
158
202
|
};
|
|
159
203
|
//# sourceMappingURL=runtime.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@guidelytech/shared",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Shared schemas, types and pure utilities for Guidely",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -40,12 +40,12 @@
|
|
|
40
40
|
},
|
|
41
41
|
"repository": {
|
|
42
42
|
"type": "git",
|
|
43
|
-
"url": "git+https://github.com/
|
|
43
|
+
"url": "git+https://github.com/GuidelyTech/Guidely.git",
|
|
44
44
|
"directory": "packages/shared"
|
|
45
45
|
},
|
|
46
|
-
"homepage": "https://github.com/
|
|
46
|
+
"homepage": "https://github.com/GuidelyTech/Guidely/tree/main/packages/shared#readme",
|
|
47
47
|
"bugs": {
|
|
48
|
-
"url": "https://github.com/
|
|
48
|
+
"url": "https://github.com/GuidelyTech/Guidely/issues"
|
|
49
49
|
},
|
|
50
50
|
"keywords": [
|
|
51
51
|
"guidely",
|