@feedlog-ai/webcomponents 0.0.30 → 0.0.32
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/cjs/feedlog-issues-client.cjs.entry.js +7 -2
- package/dist/collection/components/feedlog-issues-client/feedlog-issues-client.js +7 -2
- package/dist/components/feedlog-issues-client.js +1 -1
- package/dist/esm/feedlog-issues-client.entry.js +7 -2
- package/dist/feedlog-toolkit/feedlog-toolkit.esm.js +1 -1
- package/dist/feedlog-toolkit/{p-c3e9b94b.entry.js → p-b51c95a6.entry.js} +1 -1
- package/dist/types/components/feedlog-issues-client/feedlog-issues-client.d.ts +1 -1
- package/hydrate/index.js +7 -2
- package/hydrate/index.mjs +7 -2
- package/package.json +2 -2
|
@@ -413,7 +413,12 @@ const FeedlogIssuesClient = class {
|
|
|
413
413
|
this.previousLimit = this.limit;
|
|
414
414
|
this.previousSortBy = this.sortBy;
|
|
415
415
|
this.initializeSDK();
|
|
416
|
-
|
|
416
|
+
// Return the promise so SSR waits for the fetch before serializing HTML.
|
|
417
|
+
// During client hydration, skip fetch if we already have server-rendered data.
|
|
418
|
+
if (this.issues.length > 0 && !this.loading) {
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
return this.fetchIssues();
|
|
417
422
|
}
|
|
418
423
|
disconnectedCallback() {
|
|
419
424
|
// Prevent any pending async operations from updating state
|
|
@@ -559,7 +564,7 @@ const FeedlogIssuesClient = class {
|
|
|
559
564
|
const style = hostBg
|
|
560
565
|
? { '--feedlog-background': hostBg }
|
|
561
566
|
: undefined;
|
|
562
|
-
return (index.h("feedlog-issues", { key: '
|
|
567
|
+
return (index.h("feedlog-issues", { key: '0528f8bbb5f1e735c3b50a4325221ee8bfdfadda', style: style, issues: this.issues, limit: this.limit, maxWidth: this.maxWidth, theme: this.theme, heading: this.heading, subtitle: this.subtitle, emptyStateTitle: this.emptyStateTitle, emptyStateMessage: this.emptyStateMessage, getIssueUrl: this.getIssueUrl, loading: this.loading, error: this.error, hasMore: this.hasMore, isLoadingMore: this.isLoadingMore, onFeedlogUpvote: this.handleUpvote, onFeedlogLoadMore: async () => this.loadMore() }));
|
|
563
568
|
}
|
|
564
569
|
get el() { return index.getElement(this); }
|
|
565
570
|
};
|
|
@@ -73,7 +73,12 @@ export class FeedlogIssuesClient {
|
|
|
73
73
|
this.previousLimit = this.limit;
|
|
74
74
|
this.previousSortBy = this.sortBy;
|
|
75
75
|
this.initializeSDK();
|
|
76
|
-
|
|
76
|
+
// Return the promise so SSR waits for the fetch before serializing HTML.
|
|
77
|
+
// During client hydration, skip fetch if we already have server-rendered data.
|
|
78
|
+
if (this.issues.length > 0 && !this.loading) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
return this.fetchIssues();
|
|
77
82
|
}
|
|
78
83
|
disconnectedCallback() {
|
|
79
84
|
// Prevent any pending async operations from updating state
|
|
@@ -219,7 +224,7 @@ export class FeedlogIssuesClient {
|
|
|
219
224
|
const style = hostBg
|
|
220
225
|
? { '--feedlog-background': hostBg }
|
|
221
226
|
: undefined;
|
|
222
|
-
return (h("feedlog-issues", { key: '
|
|
227
|
+
return (h("feedlog-issues", { key: '0528f8bbb5f1e735c3b50a4325221ee8bfdfadda', style: style, issues: this.issues, limit: this.limit, maxWidth: this.maxWidth, theme: this.theme, heading: this.heading, subtitle: this.subtitle, emptyStateTitle: this.emptyStateTitle, emptyStateMessage: this.emptyStateMessage, getIssueUrl: this.getIssueUrl, loading: this.loading, error: this.error, hasMore: this.hasMore, isLoadingMore: this.isLoadingMore, onFeedlogUpvote: this.handleUpvote, onFeedlogLoadMore: async () => this.loadMore() }));
|
|
223
228
|
}
|
|
224
229
|
static get is() { return "feedlog-issues-client"; }
|
|
225
230
|
static get encapsulation() { return "shadow"; }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t,p as e,H as s,c as i,h as o}from"./index.js";import{d as r}from"./p-DzATWlAC.js";import{d as n}from"./p-DMdb-G26.js";import{d as h}from"./p-BRjVS8bz.js";import{d as a}from"./p-BBbiSGNf.js";import{d as u}from"./p-CuFKEckF.js";function l(t){if("string"!=typeof t)return"";let e=t.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,"");return e=e.replace(/\s*on\w+\s*=\s*["'][^"']*["']/gi,""),e=e.replace(/\s*on\w+\s*=\s*[^\s>]*/gi,""),e=e.replace(/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi,""),e=e.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi,""),e=e.replace(/<(embed|object)\b[^<]*>/gi,""),e=e.replace(/javascript:/gi,""),e=e.replace(/data:(?!image\/(?:png|jpg|jpeg|gif|webp);)/gi,""),e}class d extends Error{constructor(t,e,s){super(t),this.statusCode=e,this.originalError=s,this.name="FeedlogError",Object.setPrototypeOf(this,d.prototype)}}class c extends d{constructor(t){super(t),this.name="FeedlogValidationError",Object.setPrototypeOf(this,c.prototype)}}class p extends d{constructor(t,e,s){super(t,e,s),this.name="FeedlogNetworkError",Object.setPrototypeOf(this,p.prototype)}}class f extends d{constructor(t="Request timed out"){super(t),this.name="FeedlogTimeoutError",Object.setPrototypeOf(this,f.prototype)}}class g{constructor(t){if(this.config={credentials:"include",...t},this.apiKey=this.config.apiKey,!this.apiKey)throw new c("apiKey is required in FeedlogSDKConfig");this.endpoint=this.config.endpoint||"https://api.feedlog.app",this.timeout=this.config.timeout||3e4,this.endpoint=this.endpoint.replace(/\/$/,"")}async fetchIssues(t={}){try{const e=this.buildIssuesUrl(t),s=await this.fetchWithTimeout(e,{method:"GET",headers:this.getAuthHeaders(),credentials:this.config.credentials||"include"});if(!s.ok)throw new p("Failed to fetch issues: "+s.statusText,s.status);const i=await s.json();return this.validateIssuesResponse(i)}catch(t){if(t instanceof d)throw t;if(t instanceof TypeError&&t.message.includes("fetch"))throw new p("Network error: Unable to reach API",void 0,t);throw new d("Failed to fetch issues: "+(t instanceof Error?t.message:"Unknown error"),void 0,t)}}async toggleUpvote(t){if(!t||"string"!=typeof t)throw new c("Issue ID is required");try{const e=`${this.endpoint}/api/issues/${encodeURIComponent(t)}/upvote`,s=await this.fetchWithTimeout(e,{method:"POST",headers:this.getAuthHeaders(),credentials:this.config.credentials||"include",body:JSON.stringify({})});if(404===s.status)throw new p("Issue not found",404);if(401===s.status)throw new p("Unauthorized",401);if(403===s.status)throw new p("Forbidden: Domain not allowed for this repository",403);if(!s.ok)throw new p("Failed to toggle upvote: "+s.statusText,s.status);const i=await s.json();return this.validateUpvoteResponse(i)}catch(t){if(t instanceof d)throw t;if(t instanceof TypeError&&t.message.includes("fetch"))throw new p("Network error: Unable to reach API",void 0,t);throw new d("Failed to toggle upvote: "+(t instanceof Error?t.message:"Unknown error"),void 0,t)}}buildIssuesUrl(t){const e=new URL(this.endpoint+"/api/issues");if(t.repositoryIds){const s=Array.isArray(t.repositoryIds)?t.repositoryIds:[t.repositoryIds];for(const t of s)e.searchParams.append("repositoryIds",t)}return t.type&&e.searchParams.set("type",t.type),t.sortBy&&e.searchParams.set("sortBy",t.sortBy),t.cursor&&e.searchParams.set("cursor",t.cursor),void 0!==t.limit&&e.searchParams.set("limit",""+t.limit),""+e}getAuthHeaders(){const t={"Content-Type":"application/json"};return this.apiKey&&(t["x-api-key"]=this.apiKey),t}async fetchWithTimeout(t,e){const s=new AbortController,i=setTimeout((()=>s.abort()),this.timeout);try{const o=await fetch(t,{...e,signal:s.signal});return clearTimeout(i),o}catch(t){if(clearTimeout(i),t instanceof Error&&"AbortError"===t.name)throw new f(`Request timed out after ${this.timeout}ms`);throw t}}validateIssuesResponse(t){if(!t||"object"!=typeof t)throw new c("Invalid API response: expected object");const e=t;if(!Array.isArray(e.issues))throw new c("Invalid API response: issues must be an array");if(!e.pagination||"object"!=typeof e.pagination)throw new c("Invalid API response: pagination is required");return{issues:e.issues.map((t=>this.validateIssue(t))),pagination:{cursor:e.pagination.cursor,hasMore:!!e.pagination.hasMore}}}validateIssue(t){if(!t||"object"!=typeof t)throw new c("Invalid issue: expected object");const e=t;if("string"!=typeof e.id)throw new c("Invalid issue: id is required and must be a string");if(!["bug","enhancement"].includes(e.type+""))throw new c('Invalid issue: type must be "bug" or "enhancement"');if(!["open","in_progress","closed"].includes(e.status+""))throw new c('Invalid issue: status must be "open", "in_progress", or "closed"');if(!e.repository||"object"!=typeof e.repository)throw new c("Invalid issue: repository is required");const s=e.repository;if("string"!=typeof s.id)throw new c("Invalid issue: repository must have id");const i=null!==e.githubIssueLink&&"string"==typeof e.githubIssueLink?e.githubIssueLink+"":null,o=e.title,r=null!=o&&""!==o?l(o+""):null,n=e.body,h=null!=n&&""!==n?l(n+""):null,a=s.name,u=null!=a&&""!==a?a+"":null,d=s.description,p=null!=d&&""!==d?l(d+""):null;return{id:e.id+"",githubIssueLink:i,type:e.type||"bug",status:e.status||"open",pinnedAt:e.pinnedAt?e.pinnedAt+"":null,revision:Number(e.revision)||1,title:r,body:h,repository:{id:s.id+"",name:u,description:p},updatedAt:e.updatedAt+""||(new Date).toISOString(),createdAt:e.createdAt+""||(new Date).toISOString(),upvoteCount:Number(e.upvoteCount)||0,hasUpvoted:!!e.hasUpvoted}}validateUpvoteResponse(t){if(!t||"object"!=typeof t)throw new c("Invalid upvote response: expected object");const e=t;if("boolean"!=typeof e.upvoted)throw new c("Invalid upvote response: upvoted must be a boolean");if("number"!=typeof e.upvoteCount)throw new c("Invalid upvote response: upvoteCount must be a number");if("string"!=typeof e.anonymousUserId)throw new c("Invalid upvote response: anonymousUserId must be a string");return{upvoted:e.upvoted,upvoteCount:e.upvoteCount,anonymousUserId:e.anonymousUserId}}getEndpoint(){return this.endpoint}getTimeout(){return this.timeout}}const m=e(class extends s{constructor(t){super(),!1!==t&&this.__registerHost(),this.__attachShadow(),this.feedlogUpvote=i(this,"feedlogUpvote"),this.feedlogError=i(this,"feedlogError"),this.maxWidth="42rem",this.theme="light",this.issues=[],this.loading=!0,this.error=null,this.cursor=null,this.hasMore=!1,this.isLoadingMore=!1,this.sdk=null,this.fetchRequestId=0,this.isDisconnected=!1,this.upvoteRequestIds=new Map,this.handleUpvote=async t=>{if(!this.sdk||this.isDisconnected)return;const{issueId:e,currentUpvoted:s,currentCount:i}=t.detail,o=(this.upvoteRequestIds.get(e)||0)+1;this.upvoteRequestIds.set(e,o),this.issues=this.issues.map((t=>t.id===e?Object.assign(Object.assign({},t),{hasUpvoted:!s,upvoteCount:s?i-1:i+1}):t));try{const t=await this.sdk.toggleUpvote(e);if(this.isDisconnected||this.upvoteRequestIds.get(e)!==o)return;this.issues=this.issues.map((s=>s.id===e?Object.assign(Object.assign({},s),{hasUpvoted:t.upvoted,upvoteCount:t.upvoteCount}):s)),this.feedlogUpvote.emit({issueId:e,upvoted:t.upvoted,upvoteCount:t.upvoteCount})}catch(t){if(this.isDisconnected||this.upvoteRequestIds.get(e)!==o)return;this.issues=this.issues.map((t=>t.id===e?Object.assign(Object.assign({},t),{hasUpvoted:s,upvoteCount:i}):t)),this.feedlogError.emit({error:t instanceof Error?t.message:"Failed to toggle upvote"})}}}componentWillLoad(){this.previousType=this.type,this.previousLimit=this.limit,this.previousSortBy=this.sortBy,this.initializeSDK(),this.fetchIssues()}disconnectedCallback(){this.isDisconnected=!0,this.fetchRequestId++}componentDidUpdate(){(this.previousType!==this.type||this.previousLimit!==this.limit||this.previousSortBy!==this.sortBy)&&(this.fetchRequestId++,this.cursor=null,this.hasMore=!1,this.issues=[],this.fetchIssues(),this.previousType=this.type,this.previousLimit=this.limit,this.previousSortBy=this.sortBy)}initializeSDK(){try{if(!this.apiKey)throw Error("API key is required for the Feedlog SDK");this.sdk=new g(Object.assign({apiKey:this.apiKey},this.endpoint&&{endpoint:this.endpoint})),this.error=null}catch(t){const e=t instanceof Error?t.message:"Failed to initialize SDK";this.error=e,this.feedlogError.emit({error:e})}}async fetchIssues(){if(!this.sdk)return;const t=this.fetchRequestId;try{this.loading=!0,this.error=null;const e={};this.type&&(e.type=this.type),this.sortBy&&(e.sortBy=this.sortBy),this.limit&&(e.limit=this.limit),this.cursor&&(e.cursor=this.cursor);const s=await this.sdk.fetchIssues(e);if(this.isDisconnected||t!==this.fetchRequestId)return;this.issues=s.issues,this.cursor=s.pagination.cursor,this.hasMore=s.pagination.hasMore}catch(e){if(this.isDisconnected||t!==this.fetchRequestId)return;const s=e instanceof Error?e.message:"Couldn't load updates";this.error=s,this.issues=[],this.feedlogError.emit({error:s,code:null==e?void 0:e.statusCode})}finally{this.isDisconnected||t!==this.fetchRequestId||(this.loading=!1,this.isLoadingMore=!1)}}async loadMore(){if(!this.sdk||!this.hasMore||this.isLoadingMore||this.loading)return;const t=this.fetchRequestId;this.isLoadingMore=!0;try{const e={};this.type&&(e.type=this.type),this.sortBy&&(e.sortBy=this.sortBy),this.limit&&(e.limit=this.limit),this.cursor&&(e.cursor=this.cursor);const s=await this.sdk.fetchIssues(e);if(this.isDisconnected||t!==this.fetchRequestId)return;this.issues=[...this.issues,...s.issues],this.cursor=s.pagination.cursor,this.hasMore=s.pagination.hasMore}catch(e){if(this.isDisconnected||t!==this.fetchRequestId)return;this.feedlogError.emit({error:e instanceof Error?e.message:"Failed to load more issues",code:null==e?void 0:e.statusCode})}finally{this.isDisconnected||t!==this.fetchRequestId||(this.isLoadingMore=!1)}}render(){var t,e;const s=null===(e=null===(t=this.el)||void 0===t?void 0:t.style)||void 0===e?void 0:e.getPropertyValue("--feedlog-background");return o("feedlog-issues",{key:"15ae96d7d7b51964026f873f8b97e10530ed02b4",style:s?{"--feedlog-background":s}:void 0,issues:this.issues,limit:this.limit,maxWidth:this.maxWidth,theme:this.theme,heading:this.heading,subtitle:this.subtitle,emptyStateTitle:this.emptyStateTitle,emptyStateMessage:this.emptyStateMessage,getIssueUrl:this.getIssueUrl,loading:this.loading,error:this.error,hasMore:this.hasMore,isLoadingMore:this.isLoadingMore,onFeedlogUpvote:this.handleUpvote,onFeedlogLoadMore:async()=>this.loadMore()})}get el(){return this}},[1,"feedlog-issues-client",{apiKey:[1,"api-key"],type:[1],limit:[2],sortBy:[1,"sort-by"],endpoint:[1],maxWidth:[1,"max-width"],theme:[1],heading:[1],subtitle:[1],emptyStateTitle:[1,"empty-state-title"],emptyStateMessage:[1,"empty-state-message"],getIssueUrl:[16],issues:[32],loading:[32],error:[32],cursor:[32],hasMore:[32],isLoadingMore:[32]}]);function w(){"undefined"!=typeof customElements&&["feedlog-issues-client","feedlog-badge","feedlog-button","feedlog-issue","feedlog-issues","feedlog-issues-list"].forEach((e=>{switch(e){case"feedlog-issues-client":customElements.get(t(e))||customElements.define(t(e),m);break;case"feedlog-badge":customElements.get(t(e))||r();break;case"feedlog-button":customElements.get(t(e))||n();break;case"feedlog-issue":customElements.get(t(e))||h();break;case"feedlog-issues":customElements.get(t(e))||a();break;case"feedlog-issues-list":customElements.get(t(e))||u()}}))}w();const b=m,y=w;export{b as FeedlogIssuesClient,y as defineCustomElement}
|
|
1
|
+
import{t,p as e,H as s,c as i,h as o}from"./index.js";import{d as r}from"./p-DzATWlAC.js";import{d as n}from"./p-DMdb-G26.js";import{d as h}from"./p-BRjVS8bz.js";import{d as a}from"./p-BBbiSGNf.js";import{d as u}from"./p-CuFKEckF.js";function l(t){if("string"!=typeof t)return"";let e=t.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,"");return e=e.replace(/\s*on\w+\s*=\s*["'][^"']*["']/gi,""),e=e.replace(/\s*on\w+\s*=\s*[^\s>]*/gi,""),e=e.replace(/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi,""),e=e.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi,""),e=e.replace(/<(embed|object)\b[^<]*>/gi,""),e=e.replace(/javascript:/gi,""),e=e.replace(/data:(?!image\/(?:png|jpg|jpeg|gif|webp);)/gi,""),e}class c extends Error{constructor(t,e,s){super(t),this.statusCode=e,this.originalError=s,this.name="FeedlogError",Object.setPrototypeOf(this,c.prototype)}}class d extends c{constructor(t){super(t),this.name="FeedlogValidationError",Object.setPrototypeOf(this,d.prototype)}}class p extends c{constructor(t,e,s){super(t,e,s),this.name="FeedlogNetworkError",Object.setPrototypeOf(this,p.prototype)}}class f extends c{constructor(t="Request timed out"){super(t),this.name="FeedlogTimeoutError",Object.setPrototypeOf(this,f.prototype)}}class g{constructor(t){if(this.config={credentials:"include",...t},this.apiKey=this.config.apiKey,!this.apiKey)throw new d("apiKey is required in FeedlogSDKConfig");this.endpoint=this.config.endpoint||"https://api.feedlog.app",this.timeout=this.config.timeout||3e4,this.endpoint=this.endpoint.replace(/\/$/,"")}async fetchIssues(t={}){try{const e=this.buildIssuesUrl(t),s=await this.fetchWithTimeout(e,{method:"GET",headers:this.getAuthHeaders(),credentials:this.config.credentials||"include"});if(!s.ok)throw new p("Failed to fetch issues: "+s.statusText,s.status);const i=await s.json();return this.validateIssuesResponse(i)}catch(t){if(t instanceof c)throw t;if(t instanceof TypeError&&t.message.includes("fetch"))throw new p("Network error: Unable to reach API",void 0,t);throw new c("Failed to fetch issues: "+(t instanceof Error?t.message:"Unknown error"),void 0,t)}}async toggleUpvote(t){if(!t||"string"!=typeof t)throw new d("Issue ID is required");try{const e=`${this.endpoint}/api/issues/${encodeURIComponent(t)}/upvote`,s=await this.fetchWithTimeout(e,{method:"POST",headers:this.getAuthHeaders(),credentials:this.config.credentials||"include",body:JSON.stringify({})});if(404===s.status)throw new p("Issue not found",404);if(401===s.status)throw new p("Unauthorized",401);if(403===s.status)throw new p("Forbidden: Domain not allowed for this repository",403);if(!s.ok)throw new p("Failed to toggle upvote: "+s.statusText,s.status);const i=await s.json();return this.validateUpvoteResponse(i)}catch(t){if(t instanceof c)throw t;if(t instanceof TypeError&&t.message.includes("fetch"))throw new p("Network error: Unable to reach API",void 0,t);throw new c("Failed to toggle upvote: "+(t instanceof Error?t.message:"Unknown error"),void 0,t)}}buildIssuesUrl(t){const e=new URL(this.endpoint+"/api/issues");if(t.repositoryIds){const s=Array.isArray(t.repositoryIds)?t.repositoryIds:[t.repositoryIds];for(const t of s)e.searchParams.append("repositoryIds",t)}return t.type&&e.searchParams.set("type",t.type),t.sortBy&&e.searchParams.set("sortBy",t.sortBy),t.cursor&&e.searchParams.set("cursor",t.cursor),void 0!==t.limit&&e.searchParams.set("limit",""+t.limit),""+e}getAuthHeaders(){const t={"Content-Type":"application/json"};return this.apiKey&&(t["x-api-key"]=this.apiKey),t}async fetchWithTimeout(t,e){const s=new AbortController,i=setTimeout((()=>s.abort()),this.timeout);try{const o=await fetch(t,{...e,signal:s.signal});return clearTimeout(i),o}catch(t){if(clearTimeout(i),t instanceof Error&&"AbortError"===t.name)throw new f(`Request timed out after ${this.timeout}ms`);throw t}}validateIssuesResponse(t){if(!t||"object"!=typeof t)throw new d("Invalid API response: expected object");const e=t;if(!Array.isArray(e.issues))throw new d("Invalid API response: issues must be an array");if(!e.pagination||"object"!=typeof e.pagination)throw new d("Invalid API response: pagination is required");return{issues:e.issues.map((t=>this.validateIssue(t))),pagination:{cursor:e.pagination.cursor,hasMore:!!e.pagination.hasMore}}}validateIssue(t){if(!t||"object"!=typeof t)throw new d("Invalid issue: expected object");const e=t;if("string"!=typeof e.id)throw new d("Invalid issue: id is required and must be a string");if(!["bug","enhancement"].includes(e.type+""))throw new d('Invalid issue: type must be "bug" or "enhancement"');if(!["open","in_progress","closed"].includes(e.status+""))throw new d('Invalid issue: status must be "open", "in_progress", or "closed"');if(!e.repository||"object"!=typeof e.repository)throw new d("Invalid issue: repository is required");const s=e.repository;if("string"!=typeof s.id)throw new d("Invalid issue: repository must have id");const i=null!==e.githubIssueLink&&"string"==typeof e.githubIssueLink?e.githubIssueLink+"":null,o=e.title,r=null!=o&&""!==o?l(o+""):null,n=e.body,h=null!=n&&""!==n?l(n+""):null,a=s.name,u=null!=a&&""!==a?a+"":null,c=s.description,p=null!=c&&""!==c?l(c+""):null;return{id:e.id+"",githubIssueLink:i,type:e.type||"bug",status:e.status||"open",pinnedAt:e.pinnedAt?e.pinnedAt+"":null,revision:Number(e.revision)||1,title:r,body:h,repository:{id:s.id+"",name:u,description:p},updatedAt:e.updatedAt+""||(new Date).toISOString(),createdAt:e.createdAt+""||(new Date).toISOString(),upvoteCount:Number(e.upvoteCount)||0,hasUpvoted:!!e.hasUpvoted}}validateUpvoteResponse(t){if(!t||"object"!=typeof t)throw new d("Invalid upvote response: expected object");const e=t;if("boolean"!=typeof e.upvoted)throw new d("Invalid upvote response: upvoted must be a boolean");if("number"!=typeof e.upvoteCount)throw new d("Invalid upvote response: upvoteCount must be a number");if("string"!=typeof e.anonymousUserId)throw new d("Invalid upvote response: anonymousUserId must be a string");return{upvoted:e.upvoted,upvoteCount:e.upvoteCount,anonymousUserId:e.anonymousUserId}}getEndpoint(){return this.endpoint}getTimeout(){return this.timeout}}const m=e(class extends s{constructor(t){super(),!1!==t&&this.__registerHost(),this.__attachShadow(),this.feedlogUpvote=i(this,"feedlogUpvote"),this.feedlogError=i(this,"feedlogError"),this.maxWidth="42rem",this.theme="light",this.issues=[],this.loading=!0,this.error=null,this.cursor=null,this.hasMore=!1,this.isLoadingMore=!1,this.sdk=null,this.fetchRequestId=0,this.isDisconnected=!1,this.upvoteRequestIds=new Map,this.handleUpvote=async t=>{if(!this.sdk||this.isDisconnected)return;const{issueId:e,currentUpvoted:s,currentCount:i}=t.detail,o=(this.upvoteRequestIds.get(e)||0)+1;this.upvoteRequestIds.set(e,o),this.issues=this.issues.map((t=>t.id===e?Object.assign(Object.assign({},t),{hasUpvoted:!s,upvoteCount:s?i-1:i+1}):t));try{const t=await this.sdk.toggleUpvote(e);if(this.isDisconnected||this.upvoteRequestIds.get(e)!==o)return;this.issues=this.issues.map((s=>s.id===e?Object.assign(Object.assign({},s),{hasUpvoted:t.upvoted,upvoteCount:t.upvoteCount}):s)),this.feedlogUpvote.emit({issueId:e,upvoted:t.upvoted,upvoteCount:t.upvoteCount})}catch(t){if(this.isDisconnected||this.upvoteRequestIds.get(e)!==o)return;this.issues=this.issues.map((t=>t.id===e?Object.assign(Object.assign({},t),{hasUpvoted:s,upvoteCount:i}):t)),this.feedlogError.emit({error:t instanceof Error?t.message:"Failed to toggle upvote"})}}}componentWillLoad(){if(this.previousType=this.type,this.previousLimit=this.limit,this.previousSortBy=this.sortBy,this.initializeSDK(),!(this.issues.length>0)||this.loading)return this.fetchIssues()}disconnectedCallback(){this.isDisconnected=!0,this.fetchRequestId++}componentDidUpdate(){(this.previousType!==this.type||this.previousLimit!==this.limit||this.previousSortBy!==this.sortBy)&&(this.fetchRequestId++,this.cursor=null,this.hasMore=!1,this.issues=[],this.fetchIssues(),this.previousType=this.type,this.previousLimit=this.limit,this.previousSortBy=this.sortBy)}initializeSDK(){try{if(!this.apiKey)throw Error("API key is required for the Feedlog SDK");this.sdk=new g(Object.assign({apiKey:this.apiKey},this.endpoint&&{endpoint:this.endpoint})),this.error=null}catch(t){const e=t instanceof Error?t.message:"Failed to initialize SDK";this.error=e,this.feedlogError.emit({error:e})}}async fetchIssues(){if(!this.sdk)return;const t=this.fetchRequestId;try{this.loading=!0,this.error=null;const e={};this.type&&(e.type=this.type),this.sortBy&&(e.sortBy=this.sortBy),this.limit&&(e.limit=this.limit),this.cursor&&(e.cursor=this.cursor);const s=await this.sdk.fetchIssues(e);if(this.isDisconnected||t!==this.fetchRequestId)return;this.issues=s.issues,this.cursor=s.pagination.cursor,this.hasMore=s.pagination.hasMore}catch(e){if(this.isDisconnected||t!==this.fetchRequestId)return;const s=e instanceof Error?e.message:"Couldn't load updates";this.error=s,this.issues=[],this.feedlogError.emit({error:s,code:null==e?void 0:e.statusCode})}finally{this.isDisconnected||t!==this.fetchRequestId||(this.loading=!1,this.isLoadingMore=!1)}}async loadMore(){if(!this.sdk||!this.hasMore||this.isLoadingMore||this.loading)return;const t=this.fetchRequestId;this.isLoadingMore=!0;try{const e={};this.type&&(e.type=this.type),this.sortBy&&(e.sortBy=this.sortBy),this.limit&&(e.limit=this.limit),this.cursor&&(e.cursor=this.cursor);const s=await this.sdk.fetchIssues(e);if(this.isDisconnected||t!==this.fetchRequestId)return;this.issues=[...this.issues,...s.issues],this.cursor=s.pagination.cursor,this.hasMore=s.pagination.hasMore}catch(e){if(this.isDisconnected||t!==this.fetchRequestId)return;this.feedlogError.emit({error:e instanceof Error?e.message:"Failed to load more issues",code:null==e?void 0:e.statusCode})}finally{this.isDisconnected||t!==this.fetchRequestId||(this.isLoadingMore=!1)}}render(){var t,e;const s=null===(e=null===(t=this.el)||void 0===t?void 0:t.style)||void 0===e?void 0:e.getPropertyValue("--feedlog-background");return o("feedlog-issues",{key:"0528f8bbb5f1e735c3b50a4325221ee8bfdfadda",style:s?{"--feedlog-background":s}:void 0,issues:this.issues,limit:this.limit,maxWidth:this.maxWidth,theme:this.theme,heading:this.heading,subtitle:this.subtitle,emptyStateTitle:this.emptyStateTitle,emptyStateMessage:this.emptyStateMessage,getIssueUrl:this.getIssueUrl,loading:this.loading,error:this.error,hasMore:this.hasMore,isLoadingMore:this.isLoadingMore,onFeedlogUpvote:this.handleUpvote,onFeedlogLoadMore:async()=>this.loadMore()})}get el(){return this}},[1,"feedlog-issues-client",{apiKey:[1,"api-key"],type:[1],limit:[2],sortBy:[1,"sort-by"],endpoint:[1],maxWidth:[1,"max-width"],theme:[1],heading:[1],subtitle:[1],emptyStateTitle:[1,"empty-state-title"],emptyStateMessage:[1,"empty-state-message"],getIssueUrl:[16],issues:[32],loading:[32],error:[32],cursor:[32],hasMore:[32],isLoadingMore:[32]}]);function w(){"undefined"!=typeof customElements&&["feedlog-issues-client","feedlog-badge","feedlog-button","feedlog-issue","feedlog-issues","feedlog-issues-list"].forEach((e=>{switch(e){case"feedlog-issues-client":customElements.get(t(e))||customElements.define(t(e),m);break;case"feedlog-badge":customElements.get(t(e))||r();break;case"feedlog-button":customElements.get(t(e))||n();break;case"feedlog-issue":customElements.get(t(e))||h();break;case"feedlog-issues":customElements.get(t(e))||a();break;case"feedlog-issues-list":customElements.get(t(e))||u()}}))}w();const b=m,y=w;export{b as FeedlogIssuesClient,y as defineCustomElement}
|
|
@@ -411,7 +411,12 @@ const FeedlogIssuesClient = class {
|
|
|
411
411
|
this.previousLimit = this.limit;
|
|
412
412
|
this.previousSortBy = this.sortBy;
|
|
413
413
|
this.initializeSDK();
|
|
414
|
-
|
|
414
|
+
// Return the promise so SSR waits for the fetch before serializing HTML.
|
|
415
|
+
// During client hydration, skip fetch if we already have server-rendered data.
|
|
416
|
+
if (this.issues.length > 0 && !this.loading) {
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
return this.fetchIssues();
|
|
415
420
|
}
|
|
416
421
|
disconnectedCallback() {
|
|
417
422
|
// Prevent any pending async operations from updating state
|
|
@@ -557,7 +562,7 @@ const FeedlogIssuesClient = class {
|
|
|
557
562
|
const style = hostBg
|
|
558
563
|
? { '--feedlog-background': hostBg }
|
|
559
564
|
: undefined;
|
|
560
|
-
return (h("feedlog-issues", { key: '
|
|
565
|
+
return (h("feedlog-issues", { key: '0528f8bbb5f1e735c3b50a4325221ee8bfdfadda', style: style, issues: this.issues, limit: this.limit, maxWidth: this.maxWidth, theme: this.theme, heading: this.heading, subtitle: this.subtitle, emptyStateTitle: this.emptyStateTitle, emptyStateMessage: this.emptyStateMessage, getIssueUrl: this.getIssueUrl, loading: this.loading, error: this.error, hasMore: this.hasMore, isLoadingMore: this.isLoadingMore, onFeedlogUpvote: this.handleUpvote, onFeedlogLoadMore: async () => this.loadMore() }));
|
|
561
566
|
}
|
|
562
567
|
get el() { return getElement(this); }
|
|
563
568
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{p as e,g as t,b as a}from"./p-CgNWSmzU.js";export{s as setNonce}from"./p-CgNWSmzU.js";(()=>{const t=import.meta.url,s={};return""!==t&&(s.resourcesUrl=new URL(".",t).href),e(s)})().then((async e=>(await t(),a([["p-32663f65",[[257,"feedlog-card"]]],["p-da0268a8",[[257,"feedlog-badge",{variant:[1]}]]],["p-891c349f",[[1,"feedlog-issues-list",{issues:[16],limit:[2],theme:[1],getIssueUrl:[16],emptyStateTitle:[1,"empty-state-title"],emptyStateMessage:[1,"empty-state-message"],currentPage:[32]},null,{issues:[{resetPage:0}],limit:[{resetPage:0}]}],[257,"feedlog-button",{variant:[1],size:[1],disabled:[4],type:[1]}],[257,"feedlog-issue",{issue:[16],issueUrl:[1,"issue-url"],theme:[1]}]]],["p-f22117ae",[[1,"feedlog-issues",{issues:[16],maxWidth:[1,"max-width"],limit:[2],theme:[1025],heading:[1],subtitle:[1],emptyStateTitle:[1,"empty-state-title"],emptyStateMessage:[1,"empty-state-message"],loading:[4],error:[1],hasMore:[4,"has-more"],isLoadingMore:[4,"is-loading-more"],getIssueUrl:[16],currentTheme:[32]}]]],["p-
|
|
1
|
+
import{p as e,g as t,b as a}from"./p-CgNWSmzU.js";export{s as setNonce}from"./p-CgNWSmzU.js";(()=>{const t=import.meta.url,s={};return""!==t&&(s.resourcesUrl=new URL(".",t).href),e(s)})().then((async e=>(await t(),a([["p-32663f65",[[257,"feedlog-card"]]],["p-da0268a8",[[257,"feedlog-badge",{variant:[1]}]]],["p-891c349f",[[1,"feedlog-issues-list",{issues:[16],limit:[2],theme:[1],getIssueUrl:[16],emptyStateTitle:[1,"empty-state-title"],emptyStateMessage:[1,"empty-state-message"],currentPage:[32]},null,{issues:[{resetPage:0}],limit:[{resetPage:0}]}],[257,"feedlog-button",{variant:[1],size:[1],disabled:[4],type:[1]}],[257,"feedlog-issue",{issue:[16],issueUrl:[1,"issue-url"],theme:[1]}]]],["p-f22117ae",[[1,"feedlog-issues",{issues:[16],maxWidth:[1,"max-width"],limit:[2],theme:[1025],heading:[1],subtitle:[1],emptyStateTitle:[1,"empty-state-title"],emptyStateMessage:[1,"empty-state-message"],loading:[4],error:[1],hasMore:[4,"has-more"],isLoadingMore:[4,"is-loading-more"],getIssueUrl:[16],currentTheme:[32]}]]],["p-b51c95a6",[[1,"feedlog-issues-client",{apiKey:[1,"api-key"],type:[1],limit:[2],sortBy:[1,"sort-by"],endpoint:[1],maxWidth:[1,"max-width"],theme:[1],heading:[1],subtitle:[1],emptyStateTitle:[1,"empty-state-title"],emptyStateMessage:[1,"empty-state-message"],getIssueUrl:[16],issues:[32],loading:[32],error:[32],cursor:[32],hasMore:[32],isLoadingMore:[32]}]]]],e))));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as t,c as s,h as e,a as i}from"./p-CgNWSmzU.js";function o(t){if("string"!=typeof t)return"";let s=t.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,"");return s=s.replace(/\s*on\w+\s*=\s*["'][^"']*["']/gi,""),s=s.replace(/\s*on\w+\s*=\s*[^\s>]*/gi,""),s=s.replace(/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi,""),s=s.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi,""),s=s.replace(/<(embed|object)\b[^<]*>/gi,""),s=s.replace(/javascript:/gi,""),s=s.replace(/data:(?!image\/(?:png|jpg|jpeg|gif|webp);)/gi,""),s}class r extends Error{constructor(t,s,e){super(t),this.statusCode=s,this.originalError=e,this.name="FeedlogError",Object.setPrototypeOf(this,r.prototype)}}class n extends r{constructor(t){super(t),this.name="FeedlogValidationError",Object.setPrototypeOf(this,n.prototype)}}class h extends r{constructor(t,s,e){super(t,s,e),this.name="FeedlogNetworkError",Object.setPrototypeOf(this,h.prototype)}}class a extends r{constructor(t="Request timed out"){super(t),this.name="FeedlogTimeoutError",Object.setPrototypeOf(this,a.prototype)}}class u{constructor(t){if(this.config={credentials:"include",...t},this.apiKey=this.config.apiKey,!this.apiKey)throw new n("apiKey is required in FeedlogSDKConfig");this.endpoint=this.config.endpoint||"https://api.feedlog.app",this.timeout=this.config.timeout||3e4,this.endpoint=this.endpoint.replace(/\/$/,"")}async fetchIssues(t={}){try{const s=this.buildIssuesUrl(t),e=await this.fetchWithTimeout(s,{method:"GET",headers:this.getAuthHeaders(),credentials:this.config.credentials||"include"});if(!e.ok)throw new h(`Failed to fetch issues: ${e.statusText}`,e.status);const i=await e.json();return this.validateIssuesResponse(i)}catch(t){if(t instanceof r)throw t;if(t instanceof TypeError&&t.message.includes("fetch"))throw new h("Network error: Unable to reach API",void 0,t);throw new r(`Failed to fetch issues: ${t instanceof Error?t.message:"Unknown error"}`,void 0,t)}}async toggleUpvote(t){if(!t||"string"!=typeof t)throw new n("Issue ID is required");try{const s=`${this.endpoint}/api/issues/${encodeURIComponent(t)}/upvote`,e=await this.fetchWithTimeout(s,{method:"POST",headers:this.getAuthHeaders(),credentials:this.config.credentials||"include",body:JSON.stringify({})});if(404===e.status)throw new h("Issue not found",404);if(401===e.status)throw new h("Unauthorized",401);if(403===e.status)throw new h("Forbidden: Domain not allowed for this repository",403);if(!e.ok)throw new h(`Failed to toggle upvote: ${e.statusText}`,e.status);const i=await e.json();return this.validateUpvoteResponse(i)}catch(t){if(t instanceof r)throw t;if(t instanceof TypeError&&t.message.includes("fetch"))throw new h("Network error: Unable to reach API",void 0,t);throw new r(`Failed to toggle upvote: ${t instanceof Error?t.message:"Unknown error"}`,void 0,t)}}buildIssuesUrl(t){const s=new URL(`${this.endpoint}/api/issues`);if(t.repositoryIds){const e=Array.isArray(t.repositoryIds)?t.repositoryIds:[t.repositoryIds];for(const t of e)s.searchParams.append("repositoryIds",t)}return t.type&&s.searchParams.set("type",t.type),t.sortBy&&s.searchParams.set("sortBy",t.sortBy),t.cursor&&s.searchParams.set("cursor",t.cursor),void 0!==t.limit&&s.searchParams.set("limit",t.limit.toString()),s.toString()}getAuthHeaders(){const t={"Content-Type":"application/json"};return this.apiKey&&(t["x-api-key"]=this.apiKey),t}async fetchWithTimeout(t,s){const e=new AbortController,i=setTimeout((()=>e.abort()),this.timeout);try{const o=await fetch(t,{...s,signal:e.signal});return clearTimeout(i),o}catch(t){if(clearTimeout(i),t instanceof Error&&"AbortError"===t.name)throw new a(`Request timed out after ${this.timeout}ms`);throw t}}validateIssuesResponse(t){if(!t||"object"!=typeof t)throw new n("Invalid API response: expected object");const s=t;if(!Array.isArray(s.issues))throw new n("Invalid API response: issues must be an array");if(!s.pagination||"object"!=typeof s.pagination)throw new n("Invalid API response: pagination is required");return{issues:s.issues.map((t=>this.validateIssue(t))),pagination:{cursor:s.pagination.cursor,hasMore:Boolean(s.pagination.hasMore)}}}validateIssue(t){if(!t||"object"!=typeof t)throw new n("Invalid issue: expected object");const s=t;if("string"!=typeof s.id)throw new n("Invalid issue: id is required and must be a string");if(!["bug","enhancement"].includes(String(s.type)))throw new n('Invalid issue: type must be "bug" or "enhancement"');if(!["open","in_progress","closed"].includes(String(s.status)))throw new n('Invalid issue: status must be "open", "in_progress", or "closed"');if(!s.repository||"object"!=typeof s.repository)throw new n("Invalid issue: repository is required");const e=s.repository;if("string"!=typeof e.id)throw new n("Invalid issue: repository must have id");const i=null!==s.githubIssueLink&&"string"==typeof s.githubIssueLink?String(s.githubIssueLink):null,r=s.title,h=null!=r&&""!==r?o(String(r)):null,a=s.body,u=null!=a&&""!==a?o(String(a)):null,c=e.name,l=null!=c&&""!==c?String(c):null,d=e.description,p=null!=d&&""!==d?o(String(d)):null;return{id:String(s.id),githubIssueLink:i,type:s.type||"bug",status:s.status||"open",pinnedAt:s.pinnedAt?String(s.pinnedAt):null,revision:Number(s.revision)||1,title:h,body:u,repository:{id:String(e.id),name:l,description:p},updatedAt:String(s.updatedAt)||(new Date).toISOString(),createdAt:String(s.createdAt)||(new Date).toISOString(),upvoteCount:Number(s.upvoteCount)||0,hasUpvoted:Boolean(s.hasUpvoted)}}validateUpvoteResponse(t){if(!t||"object"!=typeof t)throw new n("Invalid upvote response: expected object");const s=t;if("boolean"!=typeof s.upvoted)throw new n("Invalid upvote response: upvoted must be a boolean");if("number"!=typeof s.upvoteCount)throw new n("Invalid upvote response: upvoteCount must be a number");if("string"!=typeof s.anonymousUserId)throw new n("Invalid upvote response: anonymousUserId must be a string");return{upvoted:s.upvoted,upvoteCount:s.upvoteCount,anonymousUserId:s.anonymousUserId}}getEndpoint(){return this.endpoint}getTimeout(){return this.timeout}}const c=class{constructor(e){t(this,e),this.feedlogUpvote=s(this,"feedlogUpvote"),this.feedlogError=s(this,"feedlogError"),this.maxWidth="42rem",this.theme="light",this.issues=[],this.loading=!0,this.error=null,this.cursor=null,this.hasMore=!1,this.isLoadingMore=!1,this.sdk=null,this.fetchRequestId=0,this.isDisconnected=!1,this.upvoteRequestIds=new Map,this.handleUpvote=async t=>{if(!this.sdk||this.isDisconnected)return;const{issueId:s,currentUpvoted:e,currentCount:i}=t.detail,o=(this.upvoteRequestIds.get(s)||0)+1;this.upvoteRequestIds.set(s,o),this.issues=this.issues.map((t=>t.id===s?Object.assign(Object.assign({},t),{hasUpvoted:!e,upvoteCount:e?i-1:i+1}):t));try{const t=await this.sdk.toggleUpvote(s);if(this.isDisconnected||this.upvoteRequestIds.get(s)!==o)return;this.issues=this.issues.map((e=>e.id===s?Object.assign(Object.assign({},e),{hasUpvoted:t.upvoted,upvoteCount:t.upvoteCount}):e)),this.feedlogUpvote.emit({issueId:s,upvoted:t.upvoted,upvoteCount:t.upvoteCount})}catch(t){if(this.isDisconnected||this.upvoteRequestIds.get(s)!==o)return;this.issues=this.issues.map((t=>t.id===s?Object.assign(Object.assign({},t),{hasUpvoted:e,upvoteCount:i}):t));const r=t instanceof Error?t.message:"Failed to toggle upvote";this.feedlogError.emit({error:r})}}}componentWillLoad(){this.previousType=this.type,this.previousLimit=this.limit,this.previousSortBy=this.sortBy,this.initializeSDK(),this.fetchIssues()}disconnectedCallback(){this.isDisconnected=!0,this.fetchRequestId++}componentDidUpdate(){(this.previousType!==this.type||this.previousLimit!==this.limit||this.previousSortBy!==this.sortBy)&&(this.fetchRequestId++,this.cursor=null,this.hasMore=!1,this.issues=[],this.fetchIssues(),this.previousType=this.type,this.previousLimit=this.limit,this.previousSortBy=this.sortBy)}initializeSDK(){try{if(!this.apiKey)throw new Error("API key is required for the Feedlog SDK");this.sdk=new u(Object.assign({apiKey:this.apiKey},this.endpoint&&{endpoint:this.endpoint})),this.error=null}catch(t){const s=t instanceof Error?t.message:"Failed to initialize SDK";this.error=s,this.feedlogError.emit({error:s})}}async fetchIssues(){if(!this.sdk)return;const t=this.fetchRequestId;try{this.loading=!0,this.error=null;const s={};this.type&&(s.type=this.type),this.sortBy&&(s.sortBy=this.sortBy),this.limit&&(s.limit=this.limit),this.cursor&&(s.cursor=this.cursor);const e=await this.sdk.fetchIssues(s);if(this.isDisconnected||t!==this.fetchRequestId)return;this.issues=e.issues,this.cursor=e.pagination.cursor,this.hasMore=e.pagination.hasMore}catch(s){if(this.isDisconnected||t!==this.fetchRequestId)return;const e=s instanceof Error?s.message:"Couldn't load updates";this.error=e,this.issues=[],this.feedlogError.emit({error:e,code:null==s?void 0:s.statusCode})}finally{this.isDisconnected||t!==this.fetchRequestId||(this.loading=!1,this.isLoadingMore=!1)}}async loadMore(){if(!this.sdk||!this.hasMore||this.isLoadingMore||this.loading)return;const t=this.fetchRequestId;this.isLoadingMore=!0;try{const s={};this.type&&(s.type=this.type),this.sortBy&&(s.sortBy=this.sortBy),this.limit&&(s.limit=this.limit),this.cursor&&(s.cursor=this.cursor);const e=await this.sdk.fetchIssues(s);if(this.isDisconnected||t!==this.fetchRequestId)return;this.issues=[...this.issues,...e.issues],this.cursor=e.pagination.cursor,this.hasMore=e.pagination.hasMore}catch(s){if(this.isDisconnected||t!==this.fetchRequestId)return;const e=s instanceof Error?s.message:"Failed to load more issues";this.feedlogError.emit({error:e,code:null==s?void 0:s.statusCode})}finally{this.isDisconnected||t!==this.fetchRequestId||(this.isLoadingMore=!1)}}render(){var t,s;const i=null===(s=null===(t=this.el)||void 0===t?void 0:t.style)||void 0===s?void 0:s.getPropertyValue("--feedlog-background");return e("feedlog-issues",{key:"15ae96d7d7b51964026f873f8b97e10530ed02b4",style:i?{"--feedlog-background":i}:void 0,issues:this.issues,limit:this.limit,maxWidth:this.maxWidth,theme:this.theme,heading:this.heading,subtitle:this.subtitle,emptyStateTitle:this.emptyStateTitle,emptyStateMessage:this.emptyStateMessage,getIssueUrl:this.getIssueUrl,loading:this.loading,error:this.error,hasMore:this.hasMore,isLoadingMore:this.isLoadingMore,onFeedlogUpvote:this.handleUpvote,onFeedlogLoadMore:async()=>this.loadMore()})}get el(){return i(this)}};export{c as feedlog_issues_client}
|
|
1
|
+
import{r as t,c as s,h as e,a as i}from"./p-CgNWSmzU.js";function o(t){if("string"!=typeof t)return"";let s=t.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,"");return s=s.replace(/\s*on\w+\s*=\s*["'][^"']*["']/gi,""),s=s.replace(/\s*on\w+\s*=\s*[^\s>]*/gi,""),s=s.replace(/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi,""),s=s.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi,""),s=s.replace(/<(embed|object)\b[^<]*>/gi,""),s=s.replace(/javascript:/gi,""),s=s.replace(/data:(?!image\/(?:png|jpg|jpeg|gif|webp);)/gi,""),s}class r extends Error{constructor(t,s,e){super(t),this.statusCode=s,this.originalError=e,this.name="FeedlogError",Object.setPrototypeOf(this,r.prototype)}}class n extends r{constructor(t){super(t),this.name="FeedlogValidationError",Object.setPrototypeOf(this,n.prototype)}}class h extends r{constructor(t,s,e){super(t,s,e),this.name="FeedlogNetworkError",Object.setPrototypeOf(this,h.prototype)}}class a extends r{constructor(t="Request timed out"){super(t),this.name="FeedlogTimeoutError",Object.setPrototypeOf(this,a.prototype)}}class u{constructor(t){if(this.config={credentials:"include",...t},this.apiKey=this.config.apiKey,!this.apiKey)throw new n("apiKey is required in FeedlogSDKConfig");this.endpoint=this.config.endpoint||"https://api.feedlog.app",this.timeout=this.config.timeout||3e4,this.endpoint=this.endpoint.replace(/\/$/,"")}async fetchIssues(t={}){try{const s=this.buildIssuesUrl(t),e=await this.fetchWithTimeout(s,{method:"GET",headers:this.getAuthHeaders(),credentials:this.config.credentials||"include"});if(!e.ok)throw new h(`Failed to fetch issues: ${e.statusText}`,e.status);const i=await e.json();return this.validateIssuesResponse(i)}catch(t){if(t instanceof r)throw t;if(t instanceof TypeError&&t.message.includes("fetch"))throw new h("Network error: Unable to reach API",void 0,t);throw new r(`Failed to fetch issues: ${t instanceof Error?t.message:"Unknown error"}`,void 0,t)}}async toggleUpvote(t){if(!t||"string"!=typeof t)throw new n("Issue ID is required");try{const s=`${this.endpoint}/api/issues/${encodeURIComponent(t)}/upvote`,e=await this.fetchWithTimeout(s,{method:"POST",headers:this.getAuthHeaders(),credentials:this.config.credentials||"include",body:JSON.stringify({})});if(404===e.status)throw new h("Issue not found",404);if(401===e.status)throw new h("Unauthorized",401);if(403===e.status)throw new h("Forbidden: Domain not allowed for this repository",403);if(!e.ok)throw new h(`Failed to toggle upvote: ${e.statusText}`,e.status);const i=await e.json();return this.validateUpvoteResponse(i)}catch(t){if(t instanceof r)throw t;if(t instanceof TypeError&&t.message.includes("fetch"))throw new h("Network error: Unable to reach API",void 0,t);throw new r(`Failed to toggle upvote: ${t instanceof Error?t.message:"Unknown error"}`,void 0,t)}}buildIssuesUrl(t){const s=new URL(`${this.endpoint}/api/issues`);if(t.repositoryIds){const e=Array.isArray(t.repositoryIds)?t.repositoryIds:[t.repositoryIds];for(const t of e)s.searchParams.append("repositoryIds",t)}return t.type&&s.searchParams.set("type",t.type),t.sortBy&&s.searchParams.set("sortBy",t.sortBy),t.cursor&&s.searchParams.set("cursor",t.cursor),void 0!==t.limit&&s.searchParams.set("limit",t.limit.toString()),s.toString()}getAuthHeaders(){const t={"Content-Type":"application/json"};return this.apiKey&&(t["x-api-key"]=this.apiKey),t}async fetchWithTimeout(t,s){const e=new AbortController,i=setTimeout((()=>e.abort()),this.timeout);try{const o=await fetch(t,{...s,signal:e.signal});return clearTimeout(i),o}catch(t){if(clearTimeout(i),t instanceof Error&&"AbortError"===t.name)throw new a(`Request timed out after ${this.timeout}ms`);throw t}}validateIssuesResponse(t){if(!t||"object"!=typeof t)throw new n("Invalid API response: expected object");const s=t;if(!Array.isArray(s.issues))throw new n("Invalid API response: issues must be an array");if(!s.pagination||"object"!=typeof s.pagination)throw new n("Invalid API response: pagination is required");return{issues:s.issues.map((t=>this.validateIssue(t))),pagination:{cursor:s.pagination.cursor,hasMore:Boolean(s.pagination.hasMore)}}}validateIssue(t){if(!t||"object"!=typeof t)throw new n("Invalid issue: expected object");const s=t;if("string"!=typeof s.id)throw new n("Invalid issue: id is required and must be a string");if(!["bug","enhancement"].includes(String(s.type)))throw new n('Invalid issue: type must be "bug" or "enhancement"');if(!["open","in_progress","closed"].includes(String(s.status)))throw new n('Invalid issue: status must be "open", "in_progress", or "closed"');if(!s.repository||"object"!=typeof s.repository)throw new n("Invalid issue: repository is required");const e=s.repository;if("string"!=typeof e.id)throw new n("Invalid issue: repository must have id");const i=null!==s.githubIssueLink&&"string"==typeof s.githubIssueLink?String(s.githubIssueLink):null,r=s.title,h=null!=r&&""!==r?o(String(r)):null,a=s.body,u=null!=a&&""!==a?o(String(a)):null,c=e.name,l=null!=c&&""!==c?String(c):null,d=e.description,p=null!=d&&""!==d?o(String(d)):null;return{id:String(s.id),githubIssueLink:i,type:s.type||"bug",status:s.status||"open",pinnedAt:s.pinnedAt?String(s.pinnedAt):null,revision:Number(s.revision)||1,title:h,body:u,repository:{id:String(e.id),name:l,description:p},updatedAt:String(s.updatedAt)||(new Date).toISOString(),createdAt:String(s.createdAt)||(new Date).toISOString(),upvoteCount:Number(s.upvoteCount)||0,hasUpvoted:Boolean(s.hasUpvoted)}}validateUpvoteResponse(t){if(!t||"object"!=typeof t)throw new n("Invalid upvote response: expected object");const s=t;if("boolean"!=typeof s.upvoted)throw new n("Invalid upvote response: upvoted must be a boolean");if("number"!=typeof s.upvoteCount)throw new n("Invalid upvote response: upvoteCount must be a number");if("string"!=typeof s.anonymousUserId)throw new n("Invalid upvote response: anonymousUserId must be a string");return{upvoted:s.upvoted,upvoteCount:s.upvoteCount,anonymousUserId:s.anonymousUserId}}getEndpoint(){return this.endpoint}getTimeout(){return this.timeout}}const c=class{constructor(e){t(this,e),this.feedlogUpvote=s(this,"feedlogUpvote"),this.feedlogError=s(this,"feedlogError"),this.maxWidth="42rem",this.theme="light",this.issues=[],this.loading=!0,this.error=null,this.cursor=null,this.hasMore=!1,this.isLoadingMore=!1,this.sdk=null,this.fetchRequestId=0,this.isDisconnected=!1,this.upvoteRequestIds=new Map,this.handleUpvote=async t=>{if(!this.sdk||this.isDisconnected)return;const{issueId:s,currentUpvoted:e,currentCount:i}=t.detail,o=(this.upvoteRequestIds.get(s)||0)+1;this.upvoteRequestIds.set(s,o),this.issues=this.issues.map((t=>t.id===s?Object.assign(Object.assign({},t),{hasUpvoted:!e,upvoteCount:e?i-1:i+1}):t));try{const t=await this.sdk.toggleUpvote(s);if(this.isDisconnected||this.upvoteRequestIds.get(s)!==o)return;this.issues=this.issues.map((e=>e.id===s?Object.assign(Object.assign({},e),{hasUpvoted:t.upvoted,upvoteCount:t.upvoteCount}):e)),this.feedlogUpvote.emit({issueId:s,upvoted:t.upvoted,upvoteCount:t.upvoteCount})}catch(t){if(this.isDisconnected||this.upvoteRequestIds.get(s)!==o)return;this.issues=this.issues.map((t=>t.id===s?Object.assign(Object.assign({},t),{hasUpvoted:e,upvoteCount:i}):t));const r=t instanceof Error?t.message:"Failed to toggle upvote";this.feedlogError.emit({error:r})}}}componentWillLoad(){if(this.previousType=this.type,this.previousLimit=this.limit,this.previousSortBy=this.sortBy,this.initializeSDK(),!(this.issues.length>0)||this.loading)return this.fetchIssues()}disconnectedCallback(){this.isDisconnected=!0,this.fetchRequestId++}componentDidUpdate(){(this.previousType!==this.type||this.previousLimit!==this.limit||this.previousSortBy!==this.sortBy)&&(this.fetchRequestId++,this.cursor=null,this.hasMore=!1,this.issues=[],this.fetchIssues(),this.previousType=this.type,this.previousLimit=this.limit,this.previousSortBy=this.sortBy)}initializeSDK(){try{if(!this.apiKey)throw new Error("API key is required for the Feedlog SDK");this.sdk=new u(Object.assign({apiKey:this.apiKey},this.endpoint&&{endpoint:this.endpoint})),this.error=null}catch(t){const s=t instanceof Error?t.message:"Failed to initialize SDK";this.error=s,this.feedlogError.emit({error:s})}}async fetchIssues(){if(!this.sdk)return;const t=this.fetchRequestId;try{this.loading=!0,this.error=null;const s={};this.type&&(s.type=this.type),this.sortBy&&(s.sortBy=this.sortBy),this.limit&&(s.limit=this.limit),this.cursor&&(s.cursor=this.cursor);const e=await this.sdk.fetchIssues(s);if(this.isDisconnected||t!==this.fetchRequestId)return;this.issues=e.issues,this.cursor=e.pagination.cursor,this.hasMore=e.pagination.hasMore}catch(s){if(this.isDisconnected||t!==this.fetchRequestId)return;const e=s instanceof Error?s.message:"Couldn't load updates";this.error=e,this.issues=[],this.feedlogError.emit({error:e,code:null==s?void 0:s.statusCode})}finally{this.isDisconnected||t!==this.fetchRequestId||(this.loading=!1,this.isLoadingMore=!1)}}async loadMore(){if(!this.sdk||!this.hasMore||this.isLoadingMore||this.loading)return;const t=this.fetchRequestId;this.isLoadingMore=!0;try{const s={};this.type&&(s.type=this.type),this.sortBy&&(s.sortBy=this.sortBy),this.limit&&(s.limit=this.limit),this.cursor&&(s.cursor=this.cursor);const e=await this.sdk.fetchIssues(s);if(this.isDisconnected||t!==this.fetchRequestId)return;this.issues=[...this.issues,...e.issues],this.cursor=e.pagination.cursor,this.hasMore=e.pagination.hasMore}catch(s){if(this.isDisconnected||t!==this.fetchRequestId)return;const e=s instanceof Error?s.message:"Failed to load more issues";this.feedlogError.emit({error:e,code:null==s?void 0:s.statusCode})}finally{this.isDisconnected||t!==this.fetchRequestId||(this.isLoadingMore=!1)}}render(){var t,s;const i=null===(s=null===(t=this.el)||void 0===t?void 0:t.style)||void 0===s?void 0:s.getPropertyValue("--feedlog-background");return e("feedlog-issues",{key:"0528f8bbb5f1e735c3b50a4325221ee8bfdfadda",style:i?{"--feedlog-background":i}:void 0,issues:this.issues,limit:this.limit,maxWidth:this.maxWidth,theme:this.theme,heading:this.heading,subtitle:this.subtitle,emptyStateTitle:this.emptyStateTitle,emptyStateMessage:this.emptyStateMessage,getIssueUrl:this.getIssueUrl,loading:this.loading,error:this.error,hasMore:this.hasMore,isLoadingMore:this.isLoadingMore,onFeedlogUpvote:this.handleUpvote,onFeedlogLoadMore:async()=>this.loadMore()})}get el(){return i(this)}};export{c as feedlog_issues_client}
|
|
@@ -89,7 +89,7 @@ export declare class FeedlogIssuesClient {
|
|
|
89
89
|
private isDisconnected;
|
|
90
90
|
/** Map to track the latest upvote request ID for each issue to handle race conditions */
|
|
91
91
|
private upvoteRequestIds;
|
|
92
|
-
componentWillLoad(): void;
|
|
92
|
+
componentWillLoad(): Promise<void> | undefined;
|
|
93
93
|
disconnectedCallback(): void;
|
|
94
94
|
componentDidUpdate(): void;
|
|
95
95
|
private initializeSDK;
|
package/hydrate/index.js
CHANGED
|
@@ -7240,7 +7240,12 @@ class FeedlogIssuesClient {
|
|
|
7240
7240
|
this.previousLimit = this.limit;
|
|
7241
7241
|
this.previousSortBy = this.sortBy;
|
|
7242
7242
|
this.initializeSDK();
|
|
7243
|
-
|
|
7243
|
+
// Return the promise so SSR waits for the fetch before serializing HTML.
|
|
7244
|
+
// During client hydration, skip fetch if we already have server-rendered data.
|
|
7245
|
+
if (this.issues.length > 0 && !this.loading) {
|
|
7246
|
+
return;
|
|
7247
|
+
}
|
|
7248
|
+
return this.fetchIssues();
|
|
7244
7249
|
}
|
|
7245
7250
|
disconnectedCallback() {
|
|
7246
7251
|
// Prevent any pending async operations from updating state
|
|
@@ -7386,7 +7391,7 @@ class FeedlogIssuesClient {
|
|
|
7386
7391
|
const style = hostBg
|
|
7387
7392
|
? { '--feedlog-background': hostBg }
|
|
7388
7393
|
: undefined;
|
|
7389
|
-
return (hAsync("feedlog-issues", { key: '
|
|
7394
|
+
return (hAsync("feedlog-issues", { key: '0528f8bbb5f1e735c3b50a4325221ee8bfdfadda', style: style, issues: this.issues, limit: this.limit, maxWidth: this.maxWidth, theme: this.theme, heading: this.heading, subtitle: this.subtitle, emptyStateTitle: this.emptyStateTitle, emptyStateMessage: this.emptyStateMessage, getIssueUrl: this.getIssueUrl, loading: this.loading, error: this.error, hasMore: this.hasMore, isLoadingMore: this.isLoadingMore, onFeedlogUpvote: this.handleUpvote, onFeedlogLoadMore: async () => this.loadMore() }));
|
|
7390
7395
|
}
|
|
7391
7396
|
get el() { return getElement(this); }
|
|
7392
7397
|
static get cmpMeta() { return {
|
package/hydrate/index.mjs
CHANGED
|
@@ -7238,7 +7238,12 @@ class FeedlogIssuesClient {
|
|
|
7238
7238
|
this.previousLimit = this.limit;
|
|
7239
7239
|
this.previousSortBy = this.sortBy;
|
|
7240
7240
|
this.initializeSDK();
|
|
7241
|
-
|
|
7241
|
+
// Return the promise so SSR waits for the fetch before serializing HTML.
|
|
7242
|
+
// During client hydration, skip fetch if we already have server-rendered data.
|
|
7243
|
+
if (this.issues.length > 0 && !this.loading) {
|
|
7244
|
+
return;
|
|
7245
|
+
}
|
|
7246
|
+
return this.fetchIssues();
|
|
7242
7247
|
}
|
|
7243
7248
|
disconnectedCallback() {
|
|
7244
7249
|
// Prevent any pending async operations from updating state
|
|
@@ -7384,7 +7389,7 @@ class FeedlogIssuesClient {
|
|
|
7384
7389
|
const style = hostBg
|
|
7385
7390
|
? { '--feedlog-background': hostBg }
|
|
7386
7391
|
: undefined;
|
|
7387
|
-
return (hAsync("feedlog-issues", { key: '
|
|
7392
|
+
return (hAsync("feedlog-issues", { key: '0528f8bbb5f1e735c3b50a4325221ee8bfdfadda', style: style, issues: this.issues, limit: this.limit, maxWidth: this.maxWidth, theme: this.theme, heading: this.heading, subtitle: this.subtitle, emptyStateTitle: this.emptyStateTitle, emptyStateMessage: this.emptyStateMessage, getIssueUrl: this.getIssueUrl, loading: this.loading, error: this.error, hasMore: this.hasMore, isLoadingMore: this.isLoadingMore, onFeedlogUpvote: this.handleUpvote, onFeedlogLoadMore: async () => this.loadMore() }));
|
|
7388
7393
|
}
|
|
7389
7394
|
get el() { return getElement(this); }
|
|
7390
7395
|
static get cmpMeta() { return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@feedlog-ai/webcomponents",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.32",
|
|
4
4
|
"description": "Stencil web components for Feedlog Toolkit - Data visualization components",
|
|
5
5
|
"main": "./dist/index.cjs.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"clean": "rm -rf dist loader"
|
|
67
67
|
},
|
|
68
68
|
"dependencies": {
|
|
69
|
-
"@feedlog-ai/core": "^0.0.
|
|
69
|
+
"@feedlog-ai/core": "^0.0.32",
|
|
70
70
|
"dompurify": "^3.3.1",
|
|
71
71
|
"marked": "^17.0.2"
|
|
72
72
|
},
|