@ambasada/miniapp 0.5.0 → 0.7.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/index.d.ts +22 -2
- package/dist/index.js +28 -4
- package/dist/miniapp.js +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -142,6 +142,15 @@ export declare const auth: {
|
|
|
142
142
|
token: string;
|
|
143
143
|
expires_at: string;
|
|
144
144
|
}>;
|
|
145
|
+
/**
|
|
146
|
+
* Silent sign-in in one call: gets a shell token and POSTs it to your server (`/api/auth/shell` in the templates,
|
|
147
|
+
* `village.auth.shell(req)` in @ambasada/sdk), which sets your session cookie. Resolves the server's `user`, or
|
|
148
|
+
* null when the shell can't do it (outside the app, an older app, an app that is not verified): then show
|
|
149
|
+
* "Sign in with Ambasada". Rejects when your server refuses the token.
|
|
150
|
+
*/
|
|
151
|
+
signIn<User = unknown>(options?: {
|
|
152
|
+
endpoint?: string;
|
|
153
|
+
}): Promise<User | null>;
|
|
145
154
|
};
|
|
146
155
|
export declare const notifications: {
|
|
147
156
|
/**
|
|
@@ -162,12 +171,14 @@ export declare function on(event: "notification", handler: (n: {
|
|
|
162
171
|
}) => void): () => void;
|
|
163
172
|
/**
|
|
164
173
|
* Local development: pretend to be inside the Ambasada app. Installs a version 3 shell with the given
|
|
165
|
-
* context, records every message in `messages`, answers requests (`getToken` → a fake token, `
|
|
166
|
-
*
|
|
174
|
+
* context, records every message in `messages`, answers requests (`getToken` → a fake token, or with `issuer`
|
|
175
|
+
* (the `ambasada dev` mock URL) a real signed one from `<issuer>/dev/shell-token`; `request()` → enabled)
|
|
176
|
+
* and returns `emit` to fire shell events. The templates call it on `?ambasada_shell=mock` under `ambasada dev`.
|
|
167
177
|
*/
|
|
168
178
|
export declare function mockEnv(overrides?: Partial<ShellContext> & {
|
|
169
179
|
version?: number;
|
|
170
180
|
capabilities?: Capability[];
|
|
181
|
+
issuer?: string;
|
|
171
182
|
answers?: Partial<Record<"auth.getToken" | "notifications.request", unknown | Error>>;
|
|
172
183
|
}): {
|
|
173
184
|
messages: Message[];
|
|
@@ -202,6 +213,15 @@ declare const _default: {
|
|
|
202
213
|
token: string;
|
|
203
214
|
expires_at: string;
|
|
204
215
|
}>;
|
|
216
|
+
/**
|
|
217
|
+
* Silent sign-in in one call: gets a shell token and POSTs it to your server (`/api/auth/shell` in the templates,
|
|
218
|
+
* `village.auth.shell(req)` in @ambasada/sdk), which sets your session cookie. Resolves the server's `user`, or
|
|
219
|
+
* null when the shell can't do it (outside the app, an older app, an app that is not verified): then show
|
|
220
|
+
* "Sign in with Ambasada". Rejects when your server refuses the token.
|
|
221
|
+
*/
|
|
222
|
+
signIn<User = unknown>(options?: {
|
|
223
|
+
endpoint?: string;
|
|
224
|
+
}): Promise<User | null>;
|
|
205
225
|
};
|
|
206
226
|
notifications: {
|
|
207
227
|
/**
|
package/dist/index.js
CHANGED
|
@@ -128,6 +128,25 @@ var auth = {
|
|
|
128
128
|
getToken() {
|
|
129
129
|
if (!has("auth.getToken")) return Promise.reject(new Error(has("ready") ? "silent sign-in is not available for this app" : NOT_IN_AMBASADA));
|
|
130
130
|
return request("auth.getToken");
|
|
131
|
+
},
|
|
132
|
+
/**
|
|
133
|
+
* Silent sign-in in one call: gets a shell token and POSTs it to your server (`/api/auth/shell` in the templates,
|
|
134
|
+
* `village.auth.shell(req)` in @ambasada/sdk), which sets your session cookie. Resolves the server's `user`, or
|
|
135
|
+
* null when the shell can't do it (outside the app, an older app, an app that is not verified): then show
|
|
136
|
+
* "Sign in with Ambasada". Rejects when your server refuses the token.
|
|
137
|
+
*/
|
|
138
|
+
async signIn(options = {}) {
|
|
139
|
+
const w = win();
|
|
140
|
+
if (!w || !has("auth.getToken")) return null;
|
|
141
|
+
let token;
|
|
142
|
+
try {
|
|
143
|
+
token = (await request("auth.getToken")).token;
|
|
144
|
+
} catch {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
const res = await w.fetch(options.endpoint ?? "/api/auth/shell", { method: "POST", credentials: "same-origin", headers: { "content-type": "application/json" }, body: JSON.stringify({ token }) });
|
|
148
|
+
if (!res.ok) throw new Error(`silent sign-in refused (${res.status})`);
|
|
149
|
+
return (await res.json()).user;
|
|
131
150
|
}
|
|
132
151
|
};
|
|
133
152
|
var notifications = {
|
|
@@ -158,7 +177,7 @@ function on(event, handler) {
|
|
|
158
177
|
function mockEnv(overrides = {}) {
|
|
159
178
|
const w = win();
|
|
160
179
|
if (!w) throw new Error("mockEnv needs a window");
|
|
161
|
-
const { version = 3, capabilities: caps, answers = {}, ...ctx } = overrides;
|
|
180
|
+
const { version = 3, capabilities: caps, answers = {}, issuer, ...ctx } = overrides;
|
|
162
181
|
const messages = [];
|
|
163
182
|
w.ambasadaShell = {
|
|
164
183
|
version,
|
|
@@ -178,9 +197,14 @@ function mockEnv(overrides = {}) {
|
|
|
178
197
|
const m = JSON.parse(raw);
|
|
179
198
|
messages.push(m);
|
|
180
199
|
if (m.type === "request") {
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
200
|
+
const reply = (a) => {
|
|
201
|
+
const detail = a instanceof Error ? { id: m.id, error: a.message } : { id: m.id, result: a };
|
|
202
|
+
setTimeout(() => w.dispatchEvent(new CustomEvent("ambasada:reply", { detail })), 0);
|
|
203
|
+
};
|
|
204
|
+
if (m.method in answers) reply(answers[m.method]);
|
|
205
|
+
else if (m.method === "auth.getToken" && issuer) {
|
|
206
|
+
w.fetch(`${issuer.replace(/\/+$/, "")}/dev/shell-token?aud=${encodeURIComponent(w.location.origin)}`).then((r) => r.ok ? r.json() : Promise.reject(new Error(`mock issuer answered ${r.status}`))).then(reply, reply);
|
|
207
|
+
} else reply(m.method === "auth.getToken" ? { token: "fake.jwt.token", expires_at: new Date(Date.now() + 6e4).toISOString() } : { enabled: true });
|
|
184
208
|
}
|
|
185
209
|
}
|
|
186
210
|
};
|
package/dist/miniapp.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var __ambasadaMiniapp=(()=>{var
|
|
1
|
+
"use strict";var __ambasadaMiniapp=(()=>{var x=Object.defineProperty;var O=Object.getOwnPropertyDescriptor;var F=Object.getOwnPropertyNames;var R=Object.prototype.hasOwnProperty;var D=(e,t)=>{for(var n in t)x(e,n,{get:t[n],enumerable:!0})},N=(e,t,n,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of F(t))!R.call(e,s)&&s!==n&&x(e,s,{get:()=>t[s],enumerable:!(a=O(t,s))||a.enumerable});return e};var W=e=>N(x({},"__esModule",{value:!0}),e);var z={};D(z,{applyCssVars:()=>f,auth:()=>M,capabilities:()=>E,close:()=>P,context:()=>v,default:()=>V,haptics:()=>L,isInAmbasada:()=>y,mockEnv:()=>B,notifications:()=>q,on:()=>j,openApp:()=>$,openUrl:()=>C,ready:()=>T,setTitle:()=>_,share:()=>U,shell:()=>c});var H={top:0,bottom:0,left:0,right:0},A="not inside the Ambasada app",i=()=>typeof window>"u"?null:window;function c(){let e=i()?.ambasadaShell;return e&&typeof e.version=="number"&&e.version>=2?e:null}function y(){let e=i();return e?c()!==null||/AmbasadaChat\//.test(e.navigator.userAgent):!1}function v(){let e=c();return{app:e?.app??null,platform:e?.platform??"web",safeArea:{...H,...e?.safeArea??{}},hostBar:e?.hostBar??0,theme:e?.theme??{accent:"#FF002E",scheme:"light"},locale:e?.locale??i()?.navigator.language??"en",user:e?.user??null,location:e?.location??{type:"launcher"}}}function E(){let e=c();return e?e.capabilities?e.capabilities:e.version>=3?["ready","openUrl","openApp","close","share","haptics","title","auth.getToken","notifications"]:["openUrl","close"]:[]}var o=e=>E().includes(e);function r(e){let t=i();if(!t||!y())return!1;if(t.webkit?.messageHandlers?.ambasada)t.webkit.messageHandlers.ambasada.postMessage(e);else if(t.ambasada?.postMessage)t.ambasada.postMessage(JSON.stringify(e));else return!1;return!0}var J=0;function k(e,t=15e3){let n=i();return new Promise((a,s)=>{let l=`${Date.now().toString(36)}-${++J}`,m=setTimeout(()=>{n?.removeEventListener("ambasada:reply",d),s(new Error(`${e}: the Ambasada app did not answer`))},t),d=S=>{let h=S.detail;!h||h.id!==l||(clearTimeout(m),n?.removeEventListener("ambasada:reply",d),h.error?s(new Error(h.error)):a(h.result))};n?.addEventListener("ambasada:reply",d),r({type:"request",id:l,method:e})||(clearTimeout(m),n?.removeEventListener("ambasada:reply",d),s(new Error(A)))})}function f(){let e=i();if(!e)return;let t=e.document.documentElement,n=v();for(let a of["top","bottom","left","right"])t.style.setProperty(`--ambasada-safe-area-${a}`,`${n.safeArea[a]}px`);t.style.setProperty("--ambasada-host-bar",`${n.hostBar}px`),t.classList.toggle("in-ambasada",y())}var b=!1;function T(){f(),!b&&(b=!0,o("ready")?r({type:"ready"}):c()?.version===2&&r({type:"chrome",header:"hidden",tabs:"hidden",back:"none",statusBar:"dark"}))}function C(e){o("openUrl")&&c().version>=3?r({type:"openUrl",url:e}):c()?.version===2?r({type:"open",url:e,mode:"external"}):i()?.open(e,"_blank","noopener")}function $(e,t="/"){o("openApp")?r({type:"openApp",app:e,path:t}):i()?.open(`https://ambasada.id/a/${encodeURIComponent(e)}${t.startsWith("/")?t:`/${t}`}`,"_blank","noopener")}function P(){o("close")?r({type:"close"}):i()?.history.back()}async function U(e={}){if(o("share")){r({type:"share",...e});return}let t=i();t?.navigator.share&&await t.navigator.share({url:e.url??t.location.href,text:e.text}).catch(()=>{})}var L={impact(e="light"){o("haptics")&&r({type:"haptic",kind:"impact",style:e})},notification(e="success"){o("haptics")&&r({type:"haptic",kind:"notification",style:e})},selection(){o("haptics")&&r({type:"haptic",kind:"selection"})}};function _(e){let t=i();t&&(t.document.title=e),o("title")?r({type:"title",title:e}):c()?.version===2&&r({type:"chrome",title:e})}var M={getToken(){return o("auth.getToken")?k("auth.getToken"):Promise.reject(new Error(o("ready")?"silent sign-in is not available for this app":A))},async signIn(e={}){let t=i();if(!t||!o("auth.getToken"))return null;let n;try{n=(await k("auth.getToken")).token}catch{return null}let a=await t.fetch(e.endpoint??"/api/auth/shell",{method:"POST",credentials:"same-origin",headers:{"content-type":"application/json"},body:JSON.stringify({token:n})});if(!a.ok)throw new Error(`silent sign-in refused (${a.status})`);return(await a.json()).user}},q={request(){return o("notifications")?k("notifications.request"):Promise.resolve({enabled:!1})}};function j(e,t){let n=i();if(!n)return()=>{};let a=s=>{let l=s.detail;e==="context"?(l&&typeof l=="object"&&Object.assign(n.ambasadaShell??(n.ambasadaShell={version:3,platform:"web"}),l),f(),t(v())):t(l)};return n.addEventListener(`ambasada:${e}`,a),()=>n.removeEventListener(`ambasada:${e}`,a)}function B(e={}){let t=i();if(!t)throw new Error("mockEnv needs a window");let{version:n=3,capabilities:a,answers:s={},issuer:l,...m}=e,d=[];return t.ambasadaShell={version:n,platform:"ios",safeArea:{top:59,bottom:34,left:0,right:0},hostBar:44,theme:{accent:"#FF002E",scheme:"light"},locale:"ro-RO",app:{id:"my-company",tier:"unlisted"},user:{id:"user_fake",name:"Fake Visitor",avatar:null},location:{type:"launcher"},...a?{capabilities:a}:{},...m},t.ambasada={postMessage(w){let p=JSON.parse(w);if(d.push(p),p.type==="request"){let g=u=>{let I=u instanceof Error?{id:p.id,error:u.message}:{id:p.id,result:u};setTimeout(()=>t.dispatchEvent(new CustomEvent("ambasada:reply",{detail:I})),0)};p.method in s?g(s[p.method]):p.method==="auth.getToken"&&l?t.fetch(`${l.replace(/\/+$/,"")}/dev/shell-token?aud=${encodeURIComponent(t.location.origin)}`).then(u=>u.ok?u.json():Promise.reject(new Error(`mock issuer answered ${u.status}`))).then(g,g):g(p.method==="auth.getToken"?{token:"fake.jwt.token",expires_at:new Date(Date.now()+6e4).toISOString()}:{enabled:!0})}}},b=!1,f(),{messages:d,emit:(w,p)=>t.dispatchEvent(new CustomEvent(`ambasada:${w}`,{detail:p})),uninstall:()=>{delete t.ambasadaShell,delete t.ambasada,b=!1,f()}}}var V={shell:c,isInAmbasada:y,context:v,capabilities:E,applyCssVars:f,ready:T,openUrl:C,openApp:$,close:P,share:U,haptics:L,setTitle:_,auth:M,notifications:q,on:j,mockEnv:B};return W(z);})();
|
|
2
2
|
(function (g) {
|
|
3
3
|
var prev = g.ambasada, api = Object.assign({}, __ambasadaMiniapp.default, __ambasadaMiniapp);
|
|
4
4
|
delete api.default;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ambasada/miniapp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Run your web app inside the Ambasada app as a mini app: ready(), shell context, safe areas, open links, haptics, notifications. Zero dependencies; also a <script> build.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|