@matdata/yasr 5.4.0 → 5.6.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@matdata/yasr",
3
3
  "description": "Yet Another SPARQL Resultset GUI",
4
- "version": "5.4.0",
4
+ "version": "5.6.0",
5
5
  "main": "build/yasr.min.js",
6
6
  "types": "build/ts/src/index.d.ts",
7
7
  "license": "MIT",
@@ -122,8 +122,10 @@ class Parser {
122
122
  public getError() {
123
123
  if (!this.errorSummary) {
124
124
  if (this.res && this.res.status >= 400) {
125
+ // Use response content if available, otherwise fall back to statusText
126
+ const errorText = this.res.content || this.res.statusText;
125
127
  this.errorSummary = {
126
- text: this.res.statusText,
128
+ text: errorText,
127
129
  status: this.res.status,
128
130
  statusText: !this.res.ok ? this.res.statusText : undefined,
129
131
  };
@@ -132,8 +134,12 @@ class Parser {
132
134
  this.errorSummary = this.summary.error;
133
135
  }
134
136
  if (this.error) {
137
+ // Check if the error object has status properties attached (from our enhanced error handling)
138
+ const errorWithStatus = this.error as any;
135
139
  this.errorSummary = {
136
140
  text: this.error.message,
141
+ status: errorWithStatus.status,
142
+ statusText: errorWithStatus.statusText,
137
143
  };
138
144
  }
139
145
  }
@@ -53,5 +53,34 @@
53
53
  border: 1px solid #ebccd1;
54
54
  border-radius: 4px;
55
55
  }
56
+ .statusGuidance {
57
+ margin-top: 10px;
58
+ padding: 10px 15px;
59
+ background-color: #d9edf7;
60
+ border: 1px solid #bce8f1;
61
+ border-radius: 4px;
62
+ color: #31708f;
63
+
64
+ h4 {
65
+ margin-top: 0;
66
+ margin-bottom: 8px;
67
+ font-size: 16px;
68
+ font-weight: 600;
69
+ color: #31708f;
70
+ }
71
+
72
+ ul {
73
+ margin: 0;
74
+ padding-left: 20px;
75
+
76
+ li {
77
+ margin-bottom: 5px;
78
+
79
+ &:last-child {
80
+ margin-bottom: 0;
81
+ }
82
+ }
83
+ }
84
+ }
56
85
  }
57
86
  }
@@ -54,6 +54,156 @@ export default class Error implements Plugin<never> {
54
54
  corsEl.appendChild(list);
55
55
  return corsEl;
56
56
  }
57
+
58
+ private getStatusSpecificGuidance(status: number): HTMLElement | null {
59
+ const guidanceEl = document.createElement("div");
60
+ guidanceEl.className = "statusGuidance";
61
+
62
+ const title = document.createElement("h4");
63
+ const suggestions = document.createElement("ul");
64
+
65
+ switch (status) {
66
+ case 401:
67
+ title.textContent = "Authentication Required";
68
+ guidanceEl.appendChild(title);
69
+
70
+ const auth1 = document.createElement("li");
71
+ auth1.textContent = "The endpoint requires authentication credentials";
72
+ suggestions.appendChild(auth1);
73
+
74
+ const auth2 = document.createElement("li");
75
+ auth2.textContent = "Check if you need to provide an API key, username/password, or bearer token";
76
+ suggestions.appendChild(auth2);
77
+
78
+ const auth3 = document.createElement("li");
79
+ auth3.textContent = "Verify your credentials are correct and not expired";
80
+ suggestions.appendChild(auth3);
81
+
82
+ guidanceEl.appendChild(suggestions);
83
+ return guidanceEl;
84
+
85
+ case 403:
86
+ title.textContent = "Access Forbidden";
87
+ guidanceEl.appendChild(title);
88
+
89
+ const forbidden1 = document.createElement("li");
90
+ forbidden1.textContent = "You don't have permission to access this endpoint";
91
+ suggestions.appendChild(forbidden1);
92
+
93
+ const forbidden2 = document.createElement("li");
94
+ forbidden2.textContent = "Your credentials may be valid but lack sufficient privileges";
95
+ suggestions.appendChild(forbidden2);
96
+
97
+ const forbidden3 = document.createElement("li");
98
+ forbidden3.textContent = "Contact the endpoint administrator to request access";
99
+ suggestions.appendChild(forbidden3);
100
+
101
+ guidanceEl.appendChild(suggestions);
102
+ return guidanceEl;
103
+
104
+ case 404:
105
+ title.textContent = "Endpoint Not Found";
106
+ guidanceEl.appendChild(title);
107
+
108
+ const notFound1 = document.createElement("li");
109
+ notFound1.textContent = "The endpoint URL may be incorrect or has changed";
110
+ suggestions.appendChild(notFound1);
111
+
112
+ const notFound2 = document.createElement("li");
113
+ notFound2.textContent = "Check for typos in the endpoint address";
114
+ suggestions.appendChild(notFound2);
115
+
116
+ const notFound3 = document.createElement("li");
117
+ notFound3.textContent = "Verify the endpoint is still active and hasn't been moved";
118
+ suggestions.appendChild(notFound3);
119
+
120
+ guidanceEl.appendChild(suggestions);
121
+ return guidanceEl;
122
+
123
+ case 429:
124
+ title.textContent = "Too Many Requests";
125
+ guidanceEl.appendChild(title);
126
+
127
+ const rateLimit1 = document.createElement("li");
128
+ rateLimit1.textContent = "You've exceeded the rate limit for this endpoint";
129
+ suggestions.appendChild(rateLimit1);
130
+
131
+ const rateLimit2 = document.createElement("li");
132
+ rateLimit2.textContent = "Wait a few moments before trying again";
133
+ suggestions.appendChild(rateLimit2);
134
+
135
+ const rateLimit3 = document.createElement("li");
136
+ rateLimit3.textContent =
137
+ "Consider reducing query frequency or contacting the endpoint provider for higher limits";
138
+ suggestions.appendChild(rateLimit3);
139
+
140
+ guidanceEl.appendChild(suggestions);
141
+ return guidanceEl;
142
+
143
+ case 500:
144
+ title.textContent = "Internal Server Error";
145
+ guidanceEl.appendChild(title);
146
+
147
+ const server1 = document.createElement("li");
148
+ server1.textContent = "The SPARQL endpoint encountered an error while processing your query";
149
+ suggestions.appendChild(server1);
150
+
151
+ const server2 = document.createElement("li");
152
+ server2.textContent = "Try simplifying your query or reducing the result limit";
153
+ suggestions.appendChild(server2);
154
+
155
+ const server3 = document.createElement("li");
156
+ server3.textContent = "Check the error message below for specific details";
157
+ suggestions.appendChild(server3);
158
+
159
+ const server4 = document.createElement("li");
160
+ server4.textContent = "If the problem persists, contact the endpoint administrator";
161
+ suggestions.appendChild(server4);
162
+
163
+ guidanceEl.appendChild(suggestions);
164
+ return guidanceEl;
165
+
166
+ case 502:
167
+ case 503:
168
+ case 504:
169
+ title.textContent = status === 502 ? "Bad Gateway" : status === 503 ? "Service Unavailable" : "Gateway Timeout";
170
+ guidanceEl.appendChild(title);
171
+
172
+ const gateway1 = document.createElement("li");
173
+ gateway1.textContent = "The endpoint is temporarily unavailable or overloaded";
174
+ suggestions.appendChild(gateway1);
175
+
176
+ const gateway2 = document.createElement("li");
177
+ gateway2.textContent = "Try again in a few moments";
178
+ suggestions.appendChild(gateway2);
179
+
180
+ const gateway3 = document.createElement("li");
181
+ gateway3.textContent = "The service may be undergoing maintenance";
182
+ suggestions.appendChild(gateway3);
183
+
184
+ guidanceEl.appendChild(suggestions);
185
+ return guidanceEl;
186
+
187
+ default:
188
+ // For other 4xx errors
189
+ if (status >= 400 && status < 500) {
190
+ title.textContent = "Client Error";
191
+ guidanceEl.appendChild(title);
192
+
193
+ const client1 = document.createElement("li");
194
+ client1.textContent = "There's an issue with the request";
195
+ suggestions.appendChild(client1);
196
+
197
+ const client2 = document.createElement("li");
198
+ client2.textContent = "Check the error message below for details";
199
+ suggestions.appendChild(client2);
200
+
201
+ guidanceEl.appendChild(suggestions);
202
+ return guidanceEl;
203
+ }
204
+ return null;
205
+ }
206
+ }
57
207
  async draw() {
58
208
  const el = document.createElement("div");
59
209
  el.className = "errorResult";
@@ -93,6 +243,12 @@ export default class Error implements Plugin<never> {
93
243
  if (link) header.appendChild(this.getTryBtn(link));
94
244
  }
95
245
 
246
+ // Add status-specific guidance
247
+ const guidance = this.getStatusSpecificGuidance(error.status);
248
+ if (guidance) {
249
+ el.appendChild(guidance);
250
+ }
251
+
96
252
  if (error.text) {
97
253
  const textContainer = document.createElement("div");
98
254
  addClass(textContainer, "errorMessageContainer");
@@ -107,7 +263,16 @@ export default class Error implements Plugin<never> {
107
263
  const link = this.yasr.config.getPlainQueryLinkToEndpoint();
108
264
  if (link) header.appendChild(this.getTryBtn(link));
109
265
  }
110
- if (!error.text || error.text.indexOf("Request has been terminated") >= 0) {
266
+ // Only show CORS message for network failures (not for HTTP errors with status codes)
267
+ // Common network error indicators: terminated requests, fetch failures, no error text
268
+ const isNetworkError =
269
+ !error.text ||
270
+ error.text.indexOf("Request has been terminated") >= 0 ||
271
+ error.text.indexOf("Failed to fetch") >= 0 ||
272
+ error.text.indexOf("NetworkError") >= 0 ||
273
+ error.text.indexOf("Network request failed") >= 0;
274
+
275
+ if (isNetworkError) {
111
276
  el.appendChild(this.getCorsMessage());
112
277
  } else {
113
278
  const errTextEl = document.createElement("pre");