@clearly-hub/browser 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/clearly-hub.js +2 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +21 -4
- package/package.json +9 -3
package/README.md
CHANGED
|
@@ -43,7 +43,8 @@ Hono, Bun or Deno. Mount it at `/clearly-hub/*`.
|
|
|
43
43
|
**3. Add the script and a button:**
|
|
44
44
|
|
|
45
45
|
```html
|
|
46
|
-
|
|
46
|
+
<!-- @0.1: follows 0.1.x fixes, not a breaking 0.2 -->
|
|
47
|
+
<script src="https://cdn.jsdelivr.net/npm/@clearly-hub/browser@0.1/dist/clearly-hub.js"></script>
|
|
47
48
|
|
|
48
49
|
<clearly-hub-button action="sign-in"></clearly-hub-button>
|
|
49
50
|
<clearly-hub-button action="DATA_PICKER"></clearly-hub-button>
|
package/dist/clearly-hub.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";(()=>{var
|
|
1
|
+
"use strict";(()=>{var C=Object.defineProperty;var x=(r,e,t)=>e in r?C(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var l=(r,e,t)=>x(r,typeof e!="symbol"?e+"":e,t);var T=["SELECT_SUBSCRIPTION","DATA_PICKER","REGISTER_RESOURCE","SELECT_HUB"];function E(r){return T.includes(r)}function S(r,e){if(r!=="REGISTER_RESOURCE")return;let{url:t,format:s}=e??{};if(typeof t!="string"||!t||typeof s!="string"||!s)return'REGISTER_RESOURCE needs data with a url and a format, for example { url, format: "geojson" }';if(!t.startsWith("https://"))return"REGISTER_RESOURCE needs a public https url: Clearly.HUB refuses other addresses"}var b="/clearly-hub";var u={signIn:"/sign-in",callback:"/callback",signOut:"/sign-out",session:"/session",open:"/open",answer:"/answer",result:"/result"},g="clearly-hub-answers";var p="clearly-hub-answer",y=480,f=class{constructor(e={}){l(this,"basePath",b);l(this,"display","popup");l(this,"redirectResult");this.configure(e)}configure(e){return e.basePath&&(this.basePath=e.basePath.replace(/\/+$/,"")),e.display&&(this.display=e.display),this}async session(){let e=await fetch(this.url(u.session),{credentials:"same-origin"});if(!e.ok)throw new Error(`Clearly.HUB session failed (${e.status})`);return e.json()}signIn({returnTo:e=A()}={}){window.location.assign(this.url(u.signIn,{returnTo:e}))}signOut(){window.location.assign(this.url(u.signOut))}open(e,t={}){let s=S(e,t.data);if(s)return Promise.reject(new Error(`Clearly.HUB: ${s}`));let o=crypto.randomUUID(),n=t.display??this.display,i={action:e,ref:o,returnTo:t.returnTo??A(),data:t.data?JSON.stringify(t.data):void 0};if(n==="popup"){let c=window.open(this.url(u.open,{...i,display:"popup"}),"clearly-hub-screen",`width=${y},height=${screen.availHeight},left=${screen.availWidth-y}`);if(c)return this.waitForPopup(c,o,e)}return window.location.assign(this.url(u.open,{...i,display:"redirect"})),new Promise(()=>{})}result(){return this.redirectResult??(this.redirectResult=fetch(this.url(u.result),{credentials:"same-origin"}).then(e=>e.ok?e.json():null).then(e=>e?.result??null).catch(()=>null)),this.redirectResult}waitForPopup(e,t,s){return new Promise(o=>{let n=new BroadcastChannel(g),i=!1,c=a=>{i||(i=!0,n.close(),window.clearInterval(d),window.dispatchEvent(new CustomEvent(p,{detail:a})),o(a))};n.onmessage=a=>{a.data?.ref===t&&c(a.data.result)};let d=window.setInterval(()=>{e.closed&&(window.clearInterval(d),window.setTimeout(()=>c({action:s,result:"CANCELLED"}),500))},400)})}url(e,t={}){let s=new URLSearchParams;for(let[n,i]of Object.entries(t))i!==void 0&&s.set(n,i);let o=s.toString();return`${this.basePath}${e}${o?`?${o}`:""}`}};function A(){return`${window.location.pathname}${window.location.search}${window.location.hash}`}var R={"sign-in":"Sign in with Clearly.HUB","sign-out":"Sign out",SELECT_SUBSCRIPTION:"Choose a plan in Clearly.HUB",DATA_PICKER:"Pick data from Clearly.HUB",REGISTER_RESOURCE:"Save to Clearly.HUB",SELECT_HUB:"Choose a hub"},v=`
|
|
2
2
|
:host { display: inline-block; }
|
|
3
3
|
button {
|
|
4
4
|
--color: var(--clearly-hub-color, #1fa69d);
|
|
@@ -20,4 +20,4 @@
|
|
|
20
20
|
button:focus-visible { outline: 2px solid var(--color); outline-offset: 2px; }
|
|
21
21
|
button:disabled { opacity: 0.6; cursor: default; }
|
|
22
22
|
svg { width: 1.25em; height: 1.25em; flex: none; fill: currentColor; }
|
|
23
|
-
`,
|
|
23
|
+
`,U='<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M21 6.5c-1.66 0-3 1.34-3 3 0 .07 0 .14.01.21l-2.03.68c-.64-1.21-1.82-2.09-3.22-2.32V5.91C14.04 5.57 15 4.4 15 3c0-1.66-1.34-3-3-3S9 1.34 9 3c0 1.4.96 2.57 2.25 2.91v2.16c-1.4.23-2.58 1.11-3.22 2.32l-2.04-.68C6 9.64 6 9.57 6 9.5c0-1.66-1.34-3-3-3s-3 1.34-3 3 1.34 3 3 3c1.06 0 1.98-.55 2.52-1.37l2.03.68c-.2 1.29.17 2.66 1.09 3.69l-1.41 1.77Q6.66 17 6 17c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3c0-.68-.22-1.3-.6-1.8l1.41-1.77c1.36.76 3.02.75 4.37 0l1.41 1.77c-.37.5-.59 1.12-.59 1.8 0 1.66 1.34 3 3 3s3-1.34 3-3-1.34-3-3-3c-.44 0-.85.09-1.23.26l-1.41-1.77c.93-1.04 1.29-2.4 1.09-3.69l2.03-.68c.53.82 1.46 1.37 2.52 1.37 1.66 0 3-1.34 3-3S22.66 6.5 21 6.5m-18 4c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1M6 21c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1m5-18c0-.55.45-1 1-1s1 .45 1 1-.45 1-1 1-1-.45-1-1m1 12c-1.38 0-2.5-1.12-2.5-2.5S10.62 10 12 10s2.5 1.12 2.5 2.5S13.38 15 12 15m6 4c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1m3-8.5c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1"/></svg>';function m(r,e="clearly-hub-button"){if(typeof customElements>"u"||customElements.get(e))return;class t extends HTMLElement{constructor(){super();l(this,"button");let n=this.attachShadow({mode:"open"});n.innerHTML=`<style>${v}</style><button part="button" type="button"></button>`,this.button=n.querySelector("button"),this.button.addEventListener("click",()=>this.run())}connectedCallback(){this.render()}attributeChangedCallback(){this.render()}get action(){let n=this.getAttribute("action")??"sign-in";return n in R?n:"sign-in"}render(){let n=this.getAttribute("label")??R[this.action];this.button.innerHTML=`${U}<span></span>`,this.button.querySelector("span").textContent=n}async run(){let n=this.action;if(n==="sign-in")return r.signIn();if(n==="sign-out")return r.signOut();if(!E(n))return;let i=this.getAttribute("data"),c=this.getAttribute("display")==="redirect"?"redirect":void 0;this.button.disabled=!0;let d;try{d=await r.open(n,{display:c,data:i?JSON.parse(i):void 0})}catch(a){console.error(a),d={action:n,result:"FAILURE",error:a.message}}finally{this.button.disabled=!1}this.dispatchEvent(new CustomEvent(p,{detail:d,bubbles:!0,composed:!0}))}}l(t,"observedAttributes",["action","label"]),customElements.define(e,t)}var h=new f;m(h);typeof window<"u"&&queueMicrotask(()=>{h.result().then(r=>{r&&window.dispatchEvent(new CustomEvent(p,{detail:r}))})});var w=document.currentScript;h.configure({basePath:w?.dataset.basePath,display:w?.dataset.display==="redirect"?"redirect":void 0});window.clearlyHub=h;})();
|
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ interface ScreenData {
|
|
|
8
8
|
format: string;
|
|
9
9
|
};
|
|
10
10
|
}
|
|
11
|
+
declare function checkScreenData(action: ScreenAction, data: unknown): string | undefined;
|
|
11
12
|
interface HubRef {
|
|
12
13
|
_id: string;
|
|
13
14
|
name: string;
|
|
@@ -135,5 +136,5 @@ declare function defineButton(client: ClearlyHubClient, tagName?: string): void;
|
|
|
135
136
|
|
|
136
137
|
declare const clearlyHub: ClearlyHubClient;
|
|
137
138
|
|
|
138
|
-
export { ANSWER_CHANNEL, ANSWER_EVENT, ClearlyHubClient, DEFAULT_AUTH_URL, DEFAULT_BASE_PATH, DEFAULT_HUB_URL, DEFAULT_ISSUER, ROUTES, SCREEN_ACTIONS, clearlyHub, defineButton, isScreenAction };
|
|
139
|
+
export { ANSWER_CHANNEL, ANSWER_EVENT, ClearlyHubClient, DEFAULT_AUTH_URL, DEFAULT_BASE_PATH, DEFAULT_HUB_URL, DEFAULT_ISSUER, ROUTES, SCREEN_ACTIONS, checkScreenData, clearlyHub, defineButton, isScreenAction };
|
|
139
140
|
export type { AnswerMessage, ClientOptions, HubRef, HubSubscription, OpenOptions, PickedResource, ScreenAction, ScreenAnswers, ScreenData, ScreenDisplay, ScreenResult, Session, SessionUser };
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,17 @@ var SCREEN_ACTIONS = [
|
|
|
12
12
|
function isScreenAction(value) {
|
|
13
13
|
return SCREEN_ACTIONS.includes(value);
|
|
14
14
|
}
|
|
15
|
+
function checkScreenData(action, data) {
|
|
16
|
+
if (action !== "REGISTER_RESOURCE") return void 0;
|
|
17
|
+
const { url, format } = data ?? {};
|
|
18
|
+
if (typeof url !== "string" || !url || typeof format !== "string" || !format) {
|
|
19
|
+
return 'REGISTER_RESOURCE needs data with a url and a format, for example { url, format: "geojson" }';
|
|
20
|
+
}
|
|
21
|
+
if (!url.startsWith("https://")) {
|
|
22
|
+
return "REGISTER_RESOURCE needs a public https url: Clearly.HUB refuses other addresses";
|
|
23
|
+
}
|
|
24
|
+
return void 0;
|
|
25
|
+
}
|
|
15
26
|
|
|
16
27
|
// ../shared/src/protocol.ts
|
|
17
28
|
var DEFAULT_BASE_PATH = "/clearly-hub";
|
|
@@ -57,6 +68,8 @@ var ClearlyHubClient = class {
|
|
|
57
68
|
// click handler: browsers only allow popups there. A blocked popup falls
|
|
58
69
|
// back to a redirect.
|
|
59
70
|
open(action, options = {}) {
|
|
71
|
+
const dataProblem = checkScreenData(action, options.data);
|
|
72
|
+
if (dataProblem) return Promise.reject(new Error(`Clearly.HUB: ${dataProblem}`));
|
|
60
73
|
const ref = crypto.randomUUID();
|
|
61
74
|
const display = options.display ?? this.display;
|
|
62
75
|
const query = {
|
|
@@ -185,17 +198,21 @@ function defineButton(client, tagName = "clearly-hub-button") {
|
|
|
185
198
|
const data = this.getAttribute("data");
|
|
186
199
|
const display = this.getAttribute("display") === "redirect" ? "redirect" : void 0;
|
|
187
200
|
this.button.disabled = true;
|
|
201
|
+
let result;
|
|
188
202
|
try {
|
|
189
|
-
|
|
203
|
+
result = await client.open(action, {
|
|
190
204
|
display,
|
|
191
205
|
data: data ? JSON.parse(data) : void 0
|
|
192
206
|
});
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
207
|
+
} catch (error) {
|
|
208
|
+
console.error(error);
|
|
209
|
+
result = { action, result: "FAILURE", error: error.message };
|
|
196
210
|
} finally {
|
|
197
211
|
this.button.disabled = false;
|
|
198
212
|
}
|
|
213
|
+
this.dispatchEvent(
|
|
214
|
+
new CustomEvent(ANSWER_EVENT, { detail: result, bubbles: true, composed: true })
|
|
215
|
+
);
|
|
199
216
|
}
|
|
200
217
|
}
|
|
201
218
|
__publicField(ClearlyHubButton, "observedAttributes", ["action", "label"]);
|
package/package.json
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clearly-hub/browser",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Clearly.HUB in the browser: sign-in, hosted screens and the session, talking to @clearly-hub/node",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"author": "Future Insight Group BV",
|
|
7
|
-
"keywords": [
|
|
7
|
+
"keywords": [
|
|
8
|
+
"clearly-hub",
|
|
9
|
+
"oup",
|
|
10
|
+
"open-urban-platform",
|
|
11
|
+
"web-component",
|
|
12
|
+
"sdk"
|
|
13
|
+
],
|
|
8
14
|
"type": "module",
|
|
9
15
|
"module": "./dist/index.js",
|
|
10
16
|
"types": "./dist/index.d.ts",
|
|
@@ -31,6 +37,6 @@
|
|
|
31
37
|
"prepack": "node ../../scripts/copy-license.mjs && npm run build"
|
|
32
38
|
},
|
|
33
39
|
"devDependencies": {
|
|
34
|
-
"@clearly-hub/shared": "
|
|
40
|
+
"@clearly-hub/shared": "*"
|
|
35
41
|
}
|
|
36
42
|
}
|