@freeappstore/sdk 0.2.0 → 0.3.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/dist/auth.d.ts +7 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +35 -15
- package/dist/auth.js.map +1 -1
- package/dist/auth.test.js +74 -72
- package/dist/auth.test.js.map +1 -1
- package/dist/index.d.ts +8 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/kv.d.ts +5 -1
- package/dist/kv.d.ts.map +1 -1
- package/dist/kv.js +49 -10
- package/dist/kv.js.map +1 -1
- package/dist/proxy.d.ts +2 -2
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js +13 -8
- package/dist/proxy.js.map +1 -1
- package/dist/proxy.test.js +40 -40
- package/dist/proxy.test.js.map +1 -1
- package/package.json +1 -1
package/dist/auth.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Unsubscribe, User } from "./types.js";
|
|
2
2
|
export declare class Auth {
|
|
3
3
|
private readonly appId;
|
|
4
4
|
private readonly apiBase;
|
|
@@ -18,6 +18,12 @@ export declare class Auth {
|
|
|
18
18
|
*/
|
|
19
19
|
signIn(): void;
|
|
20
20
|
signOut(): void;
|
|
21
|
+
/**
|
|
22
|
+
* Called internally by Kv and ApiProxy when an API response returns 401.
|
|
23
|
+
* Clears the stale session so the UI reacts (shows sign-in) instead of
|
|
24
|
+
* every subsequent call throwing "Not signed in" from a cached dead token.
|
|
25
|
+
*/
|
|
26
|
+
handleUnauthorized(): void;
|
|
21
27
|
/**
|
|
22
28
|
* Call this once at app start, before rendering anything that depends on
|
|
23
29
|
* auth state. If the page was loaded via an auth callback (e.g. after
|
package/dist/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAapD,qBAAa,IAAI;IAKb,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAL1B,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,SAAS,CAA0C;gBAGxC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM;IAKlC,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,CAEtB;IAED,IAAI,KAAK,IAAI,MAAM,GAAG,IAAI,CAEzB;IAED,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,KAAK,IAAI,GAAG,WAAW;IAM5D;;;;;;;OAOG;IACH,MAAM,IAAI,IAAI;IASd,OAAO,IAAI,IAAI;IAMf;;;;OAIG;IACH,kBAAkB,IAAI,IAAI;IAI1B;;;;;;;;;;;;OAYG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YA8Bb,SAAS;IAQvB,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,IAAI;CAGb"}
|
package/dist/auth.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Shared across all FAS apps on the same origin — this is intentional SSO.
|
|
3
|
+
* A user signed in on one FAS app is signed in on all of them.
|
|
4
|
+
*/
|
|
5
|
+
const STORAGE_KEY = "fas:session";
|
|
2
6
|
export class Auth {
|
|
3
7
|
appId;
|
|
4
8
|
apiBase;
|
|
@@ -17,6 +21,7 @@ export class Auth {
|
|
|
17
21
|
}
|
|
18
22
|
onChange(listener) {
|
|
19
23
|
this.listeners.add(listener);
|
|
24
|
+
listener(this.user);
|
|
20
25
|
return () => this.listeners.delete(listener);
|
|
21
26
|
}
|
|
22
27
|
/**
|
|
@@ -29,10 +34,10 @@ export class Auth {
|
|
|
29
34
|
*/
|
|
30
35
|
signIn() {
|
|
31
36
|
const here = new URL(window.location.href);
|
|
32
|
-
here.hash =
|
|
33
|
-
const url = new URL(
|
|
34
|
-
url.searchParams.set(
|
|
35
|
-
url.searchParams.set(
|
|
37
|
+
here.hash = "";
|
|
38
|
+
const url = new URL("/v1/auth/github/start", this.apiBase);
|
|
39
|
+
url.searchParams.set("app_id", this.appId);
|
|
40
|
+
url.searchParams.set("return_to", here.toString());
|
|
36
41
|
window.location.assign(url.toString());
|
|
37
42
|
}
|
|
38
43
|
signOut() {
|
|
@@ -40,6 +45,15 @@ export class Auth {
|
|
|
40
45
|
window.localStorage.removeItem(STORAGE_KEY);
|
|
41
46
|
this.emit();
|
|
42
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Called internally by Kv and ApiProxy when an API response returns 401.
|
|
50
|
+
* Clears the stale session so the UI reacts (shows sign-in) instead of
|
|
51
|
+
* every subsequent call throwing "Not signed in" from a cached dead token.
|
|
52
|
+
*/
|
|
53
|
+
handleUnauthorized() {
|
|
54
|
+
if (this.session)
|
|
55
|
+
this.signOut();
|
|
56
|
+
}
|
|
43
57
|
/**
|
|
44
58
|
* Call this once at app start, before rendering anything that depends on
|
|
45
59
|
* auth state. If the page was loaded via an auth callback (e.g. after
|
|
@@ -54,18 +68,18 @@ export class Auth {
|
|
|
54
68
|
* render();
|
|
55
69
|
*/
|
|
56
70
|
async init() {
|
|
57
|
-
if (typeof window ===
|
|
71
|
+
if (typeof window === "undefined")
|
|
58
72
|
return;
|
|
59
73
|
const hash = window.location.hash;
|
|
60
|
-
if (!hash.startsWith(
|
|
74
|
+
if (!hash.startsWith("#fas_session="))
|
|
61
75
|
return;
|
|
62
76
|
// Always clear the hash before doing anything else — even on failure.
|
|
63
77
|
// Otherwise a bad token gets re-tried on every reload and the user is
|
|
64
78
|
// permanently stuck on a "broken" URL.
|
|
65
|
-
history.replaceState(null,
|
|
79
|
+
history.replaceState(null, "", window.location.pathname + window.location.search);
|
|
66
80
|
let token;
|
|
67
81
|
try {
|
|
68
|
-
token = decodeURIComponent(hash.slice(
|
|
82
|
+
token = decodeURIComponent(hash.slice("#fas_session=".length));
|
|
69
83
|
}
|
|
70
84
|
catch {
|
|
71
85
|
// Malformed hash (% with nothing after, etc.). Hash already cleared.
|
|
@@ -73,13 +87,19 @@ export class Auth {
|
|
|
73
87
|
}
|
|
74
88
|
if (!token)
|
|
75
89
|
return;
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
90
|
+
try {
|
|
91
|
+
const user = await this.fetchUser(token);
|
|
92
|
+
this.session = { token, user };
|
|
93
|
+
this.writeStorage(this.session);
|
|
94
|
+
this.emit();
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
// Token was invalid or network failed. Hash already cleared so the user
|
|
98
|
+
// won't get stuck in a retry loop. Silently remain signed out.
|
|
99
|
+
}
|
|
80
100
|
}
|
|
81
101
|
async fetchUser(token) {
|
|
82
|
-
const res = await fetch(new URL(
|
|
102
|
+
const res = await fetch(new URL("/v1/auth/me", this.apiBase), {
|
|
83
103
|
headers: { Authorization: `Bearer ${token}` },
|
|
84
104
|
});
|
|
85
105
|
if (!res.ok)
|
|
@@ -87,7 +107,7 @@ export class Auth {
|
|
|
87
107
|
return (await res.json());
|
|
88
108
|
}
|
|
89
109
|
readStorage() {
|
|
90
|
-
if (typeof window ===
|
|
110
|
+
if (typeof window === "undefined")
|
|
91
111
|
return null;
|
|
92
112
|
const raw = window.localStorage.getItem(STORAGE_KEY);
|
|
93
113
|
if (!raw)
|
package/dist/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,GAAG,aAAa,CAAC;AAOlC,MAAM,OAAO,IAAI;IAKI;IACA;IALX,OAAO,GAAmB,IAAI,CAAC;IAC/B,SAAS,GAAG,IAAI,GAAG,EAA+B,CAAC;IAE3D,YACmB,KAAa,EACb,OAAe;QADf,UAAK,GAAL,KAAK,CAAQ;QACb,YAAO,GAAP,OAAO,CAAQ;QAEhC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACpC,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,OAAO,EAAE,IAAI,IAAI,IAAI,CAAC;IACpC,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,OAAO,EAAE,KAAK,IAAI,IAAI,CAAC;IACrC,CAAC;IAED,QAAQ,CAAC,QAAqC;QAC5C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAED;;;;;;;OAOG;IACH,MAAM;QACJ,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC;QACf,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,uBAAuB,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3D,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3C,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QACnD,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,OAAO;QACL,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,IAAI;QACR,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO;QAC1C,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;QAClC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC;YAAE,OAAO;QAE9C,sEAAsE;QACtE,sEAAsE;QACtE,uCAAuC;QACvC,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAElF,IAAI,KAAa,CAAC;QAClB,IAAI,CAAC;YACH,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC;QACjE,CAAC;QAAC,MAAM,CAAC;YACP,qEAAqE;YACrE,OAAO;QACT,CAAC;QACD,IAAI,CAAC,KAAK;YAAE,OAAO;QAEnB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,WAAW,GAAG,aAAa,CAAC;AAOlC,MAAM,OAAO,IAAI;IAKI;IACA;IALX,OAAO,GAAmB,IAAI,CAAC;IAC/B,SAAS,GAAG,IAAI,GAAG,EAA+B,CAAC;IAE3D,YACmB,KAAa,EACb,OAAe;QADf,UAAK,GAAL,KAAK,CAAQ;QACb,YAAO,GAAP,OAAO,CAAQ;QAEhC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACpC,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,OAAO,EAAE,IAAI,IAAI,IAAI,CAAC;IACpC,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,OAAO,EAAE,KAAK,IAAI,IAAI,CAAC;IACrC,CAAC;IAED,QAAQ,CAAC,QAAqC;QAC5C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpB,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAED;;;;;;;OAOG;IACH,MAAM;QACJ,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC;QACf,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,uBAAuB,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3D,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3C,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QACnD,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,OAAO;QACL,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAED;;;;OAIG;IACH,kBAAkB;QAChB,IAAI,IAAI,CAAC,OAAO;YAAE,IAAI,CAAC,OAAO,EAAE,CAAC;IACnC,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,IAAI;QACR,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO;QAC1C,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;QAClC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC;YAAE,OAAO;QAE9C,sEAAsE;QACtE,sEAAsE;QACtE,uCAAuC;QACvC,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAElF,IAAI,KAAa,CAAC;QAClB,IAAI,CAAC;YACH,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC;QACjE,CAAC;QAAC,MAAM,CAAC;YACP,qEAAqE;YACrE,OAAO;QACT,CAAC;QACD,IAAI,CAAC,KAAK;YAAE,OAAO;QAEnB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YACzC,IAAI,CAAC,OAAO,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;YAC/B,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAChC,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,wEAAwE;YACxE,+DAA+D;QACjE,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,SAAS,CAAC,KAAa;QACnC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE;YAC5D,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE;SAC9C,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QAC3D,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAS,CAAC;IACpC,CAAC;IAEO,WAAW;QACjB,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO,IAAI,CAAC;QAC/C,MAAM,GAAG,GAAG,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QACrD,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACtB,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAC;QACpC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAEO,YAAY,CAAC,OAAgB;QACnC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IACpE,CAAC;IAEO,IAAI;QACV,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS;YAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7D,CAAC;CACF"}
|
package/dist/auth.test.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Auth } from
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { Auth } from "./auth.js";
|
|
3
3
|
function makeWindow(initial) {
|
|
4
4
|
const url = new URL(initial.href);
|
|
5
5
|
if (initial.hash)
|
|
@@ -32,117 +32,119 @@ function makeWindow(initial) {
|
|
|
32
32
|
}
|
|
33
33
|
beforeEach(() => {
|
|
34
34
|
// happy-dom-style globals; we install per-test
|
|
35
|
-
delete globalThis[
|
|
36
|
-
delete globalThis[
|
|
37
|
-
delete globalThis[
|
|
35
|
+
delete globalThis["window"];
|
|
36
|
+
delete globalThis["history"];
|
|
37
|
+
delete globalThis["fetch"];
|
|
38
38
|
});
|
|
39
39
|
afterEach(() => {
|
|
40
|
-
delete globalThis[
|
|
41
|
-
delete globalThis[
|
|
42
|
-
delete globalThis[
|
|
40
|
+
delete globalThis["window"];
|
|
41
|
+
delete globalThis["history"];
|
|
42
|
+
delete globalThis["fetch"];
|
|
43
43
|
});
|
|
44
|
-
describe(
|
|
45
|
-
it(
|
|
44
|
+
describe("Auth.signIn", () => {
|
|
45
|
+
it("strips the hash from return_to so the OAuth callback does not clobber app router state", () => {
|
|
46
46
|
const { window, assigns } = makeWindow({
|
|
47
|
-
href:
|
|
47
|
+
href: "https://app.freeappstore.online/dashboard?team=42#/settings/profile",
|
|
48
48
|
});
|
|
49
|
-
globalThis[
|
|
50
|
-
const auth = new Auth(
|
|
49
|
+
globalThis["window"] = window;
|
|
50
|
+
const auth = new Auth("demo", "https://api.freeappstore.online");
|
|
51
51
|
auth.signIn();
|
|
52
52
|
expect(assigns).toHaveLength(1);
|
|
53
53
|
const target = new URL(assigns[0]);
|
|
54
|
-
const returnTo = target.searchParams.get(
|
|
55
|
-
expect(returnTo).toBe(
|
|
54
|
+
const returnTo = target.searchParams.get("return_to");
|
|
55
|
+
expect(returnTo).toBe("https://app.freeappstore.online/dashboard?team=42");
|
|
56
56
|
// No #/settings/profile carried into return_to.
|
|
57
|
-
expect(returnTo).not.toContain(
|
|
57
|
+
expect(returnTo).not.toContain("#");
|
|
58
58
|
});
|
|
59
|
-
it(
|
|
60
|
-
const { window, assigns } = makeWindow({ href:
|
|
61
|
-
globalThis[
|
|
62
|
-
const auth = new Auth(
|
|
59
|
+
it("still preserves pathname + querystring", () => {
|
|
60
|
+
const { window, assigns } = makeWindow({ href: "https://app.example/page?x=1" });
|
|
61
|
+
globalThis["window"] = window;
|
|
62
|
+
const auth = new Auth("demo", "https://api.example");
|
|
63
63
|
auth.signIn();
|
|
64
|
-
const returnTo = new URL(assigns[0]).searchParams.get(
|
|
65
|
-
expect(returnTo).toBe(
|
|
64
|
+
const returnTo = new URL(assigns[0]).searchParams.get("return_to");
|
|
65
|
+
expect(returnTo).toBe("https://app.example/page?x=1");
|
|
66
66
|
});
|
|
67
67
|
});
|
|
68
|
-
describe(
|
|
69
|
-
it(
|
|
68
|
+
describe("Auth.init — hash handling", () => {
|
|
69
|
+
it("clears the hash and stays signed out when the auth fetch fails (no crash, no stuck state)", async () => {
|
|
70
70
|
const { window, replaces } = makeWindow({
|
|
71
|
-
href:
|
|
72
|
-
hash:
|
|
71
|
+
href: "https://app.example/",
|
|
72
|
+
hash: "#fas_session=bad-token",
|
|
73
73
|
});
|
|
74
|
-
globalThis[
|
|
75
|
-
globalThis[
|
|
76
|
-
globalThis.fetch = vi.fn().mockResolvedValue(new Response(
|
|
77
|
-
const auth = new Auth(
|
|
78
|
-
|
|
74
|
+
globalThis["window"] = window;
|
|
75
|
+
globalThis["history"] = window.history;
|
|
76
|
+
globalThis.fetch = vi.fn().mockResolvedValue(new Response("", { status: 401 }));
|
|
77
|
+
const auth = new Auth("demo", "https://api.example");
|
|
78
|
+
// init() no longer throws — it silently remains signed out.
|
|
79
|
+
await auth.init();
|
|
79
80
|
// The hash was cleared before the fetch, so reload won't retry.
|
|
80
81
|
expect(replaces).toHaveLength(1);
|
|
81
|
-
expect(replaces[0]).toBe(
|
|
82
|
+
expect(replaces[0]).toBe("/");
|
|
82
83
|
expect(auth.user).toBeNull();
|
|
83
84
|
});
|
|
84
|
-
it(
|
|
85
|
+
it("captures session and clears hash on successful auth callback", async () => {
|
|
85
86
|
const { window, replaces } = makeWindow({
|
|
86
|
-
href:
|
|
87
|
-
hash:
|
|
87
|
+
href: "https://app.example/dashboard",
|
|
88
|
+
hash: "#fas_session=good-token",
|
|
88
89
|
});
|
|
89
|
-
globalThis[
|
|
90
|
-
globalThis[
|
|
91
|
-
globalThis.fetch = vi.fn().mockResolvedValue(new Response(JSON.stringify({ id:
|
|
90
|
+
globalThis["window"] = window;
|
|
91
|
+
globalThis["history"] = window.history;
|
|
92
|
+
globalThis.fetch = vi.fn().mockResolvedValue(new Response(JSON.stringify({ id: "gh:1", login: "alice", avatarUrl: null }), {
|
|
92
93
|
status: 200,
|
|
93
94
|
}));
|
|
94
|
-
const auth = new Auth(
|
|
95
|
+
const auth = new Auth("demo", "https://api.example");
|
|
95
96
|
await auth.init();
|
|
96
|
-
expect(auth.user?.login).toBe(
|
|
97
|
-
expect(auth.token).toBe(
|
|
98
|
-
expect(window.localStorage.store.get(
|
|
99
|
-
expect(replaces[0]).toBe(
|
|
97
|
+
expect(auth.user?.login).toBe("alice");
|
|
98
|
+
expect(auth.token).toBe("good-token");
|
|
99
|
+
expect(window.localStorage.store.get("fas:session")).toContain("good-token");
|
|
100
|
+
expect(replaces[0]).toBe("/dashboard");
|
|
100
101
|
});
|
|
101
|
-
it(
|
|
102
|
-
const { window, replaces } = makeWindow({ href:
|
|
103
|
-
globalThis[
|
|
104
|
-
globalThis[
|
|
102
|
+
it("is a no-op when no fas_session hash is present", async () => {
|
|
103
|
+
const { window, replaces } = makeWindow({ href: "https://app.example/" });
|
|
104
|
+
globalThis["window"] = window;
|
|
105
|
+
globalThis["history"] = window.history;
|
|
105
106
|
const fetchSpy = vi.fn();
|
|
106
107
|
globalThis.fetch = fetchSpy;
|
|
107
|
-
const auth = new Auth(
|
|
108
|
+
const auth = new Auth("demo", "https://api.example");
|
|
108
109
|
await auth.init();
|
|
109
110
|
expect(fetchSpy).not.toHaveBeenCalled();
|
|
110
111
|
expect(replaces).toHaveLength(0);
|
|
111
112
|
expect(auth.user).toBeNull();
|
|
112
113
|
});
|
|
113
114
|
});
|
|
114
|
-
describe(
|
|
115
|
-
it(
|
|
116
|
-
const { window } = makeWindow({ href:
|
|
117
|
-
window.localStorage.store.set(
|
|
118
|
-
token:
|
|
119
|
-
user: { id:
|
|
115
|
+
describe("Auth — storage round-trip", () => {
|
|
116
|
+
it("reads cached session from localStorage in the constructor", () => {
|
|
117
|
+
const { window } = makeWindow({ href: "https://app.example/" });
|
|
118
|
+
window.localStorage.store.set("fas:session", JSON.stringify({
|
|
119
|
+
token: "cached",
|
|
120
|
+
user: { id: "gh:7", login: "returning-user", avatarUrl: null },
|
|
120
121
|
}));
|
|
121
|
-
globalThis[
|
|
122
|
-
const auth = new Auth(
|
|
123
|
-
expect(auth.user?.login).toBe(
|
|
124
|
-
expect(auth.token).toBe(
|
|
122
|
+
globalThis["window"] = window;
|
|
123
|
+
const auth = new Auth("demo", "https://api.example");
|
|
124
|
+
expect(auth.user?.login).toBe("returning-user");
|
|
125
|
+
expect(auth.token).toBe("cached");
|
|
125
126
|
});
|
|
126
|
-
it(
|
|
127
|
-
const { window } = makeWindow({ href:
|
|
128
|
-
window.localStorage.store.set(
|
|
129
|
-
token:
|
|
130
|
-
user: { id:
|
|
127
|
+
it("signOut clears storage and notifies listeners", () => {
|
|
128
|
+
const { window } = makeWindow({ href: "https://app.example/" });
|
|
129
|
+
window.localStorage.store.set("fas:session", JSON.stringify({
|
|
130
|
+
token: "cached",
|
|
131
|
+
user: { id: "gh:7", login: "u", avatarUrl: null },
|
|
131
132
|
}));
|
|
132
|
-
globalThis[
|
|
133
|
-
const auth = new Auth(
|
|
133
|
+
globalThis["window"] = window;
|
|
134
|
+
const auth = new Auth("demo", "https://api.example");
|
|
134
135
|
const seen = [];
|
|
135
136
|
auth.onChange((u) => seen.push(u));
|
|
136
137
|
auth.signOut();
|
|
137
138
|
expect(auth.user).toBeNull();
|
|
138
|
-
expect(window.localStorage.store.has(
|
|
139
|
-
|
|
139
|
+
expect(window.localStorage.store.has("fas:session")).toBe(false);
|
|
140
|
+
// onChange fires immediately with current user on subscribe, then null on signOut
|
|
141
|
+
expect(seen).toEqual([{ id: "gh:7", login: "u", avatarUrl: null }, null]);
|
|
140
142
|
});
|
|
141
|
-
it(
|
|
142
|
-
const { window } = makeWindow({ href:
|
|
143
|
-
window.localStorage.store.set(
|
|
144
|
-
globalThis[
|
|
145
|
-
const auth = new Auth(
|
|
143
|
+
it("returns null when localStorage has corrupt JSON (does not crash)", () => {
|
|
144
|
+
const { window } = makeWindow({ href: "https://app.example/" });
|
|
145
|
+
window.localStorage.store.set("fas:session", "{ not: json");
|
|
146
|
+
globalThis["window"] = window;
|
|
147
|
+
const auth = new Auth("demo", "https://api.example");
|
|
146
148
|
expect(auth.user).toBeNull();
|
|
147
149
|
});
|
|
148
150
|
});
|
package/dist/auth.test.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.test.js","sourceRoot":"","sources":["../src/auth.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"auth.test.js","sourceRoot":"","sources":["../src/auth.test.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { Auth } from
|
|
2
|
-
import { Kv } from
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import type { FasInitOptions } from
|
|
6
|
-
export type {
|
|
7
|
-
export type {
|
|
1
|
+
import { Auth } from "./auth.js";
|
|
2
|
+
import { Kv } from "./kv.js";
|
|
3
|
+
import { ApiProxy } from "./proxy.js";
|
|
4
|
+
import { Rooms } from "./rooms.js";
|
|
5
|
+
import type { FasInitOptions } from "./types.js";
|
|
6
|
+
export type { ConnectionState, Room, RoomMessage, RoomPeer } from "./rooms.js";
|
|
7
|
+
export type { FasInitOptions, Unsubscribe, User } from "./types.js";
|
|
8
8
|
export declare class FreeAppStore {
|
|
9
9
|
readonly auth: Auth;
|
|
10
10
|
readonly kv: Kv;
|
|
11
11
|
readonly rooms: Rooms;
|
|
12
|
-
readonly proxy:
|
|
12
|
+
readonly proxy: ApiProxy;
|
|
13
13
|
constructor(opts: FasInitOptions);
|
|
14
14
|
}
|
|
15
15
|
export declare function initApp(opts: FasInitOptions): FreeAppStore;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,YAAY,EAAE,eAAe,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC/E,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEpE,qBAAa,YAAY;IACvB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC;IAChB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;gBAEb,IAAI,EAAE,cAAc;CAOjC;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,YAAY,CAE1D"}
|
package/dist/index.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { Auth } from
|
|
2
|
-
import { Kv } from
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { Auth } from "./auth.js";
|
|
2
|
+
import { Kv } from "./kv.js";
|
|
3
|
+
import { ApiProxy } from "./proxy.js";
|
|
4
|
+
import { Rooms } from "./rooms.js";
|
|
5
5
|
export class FreeAppStore {
|
|
6
6
|
auth;
|
|
7
7
|
kv;
|
|
8
8
|
rooms;
|
|
9
9
|
proxy;
|
|
10
10
|
constructor(opts) {
|
|
11
|
-
const apiBase = opts.apiBase ??
|
|
11
|
+
const apiBase = opts.apiBase ?? "https://api.freeappstore.online";
|
|
12
12
|
this.auth = new Auth(opts.appId, apiBase);
|
|
13
13
|
this.kv = new Kv(opts.appId, apiBase, this.auth);
|
|
14
14
|
this.rooms = new Rooms(opts.appId, apiBase, this.auth);
|
|
15
|
-
this.proxy = new
|
|
15
|
+
this.proxy = new ApiProxy(opts.appId, apiBase, this.auth);
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
export function initApp(opts) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAMnC,MAAM,OAAO,YAAY;IACd,IAAI,CAAO;IACX,EAAE,CAAK;IACP,KAAK,CAAQ;IACb,KAAK,CAAW;IAEzB,YAAY,IAAoB;QAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,iCAAiC,CAAC;QAClE,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC1C,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACvD,IAAI,CAAC,KAAK,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5D,CAAC;CACF;AAED,MAAM,UAAU,OAAO,CAAC,IAAoB;IAC1C,OAAO,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC"}
|
package/dist/kv.d.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import type { Auth } from
|
|
1
|
+
import type { Auth } from "./auth.js";
|
|
2
2
|
export declare class Kv {
|
|
3
3
|
private readonly appId;
|
|
4
4
|
private readonly apiBase;
|
|
5
5
|
private readonly auth;
|
|
6
6
|
constructor(appId: string, apiBase: string, auth: Auth);
|
|
7
|
+
list(opts?: {
|
|
8
|
+
prefix?: string;
|
|
9
|
+
}): Promise<string[]>;
|
|
10
|
+
getMany<T = unknown>(keys: string[]): Promise<Map<string, T>>;
|
|
7
11
|
get<T = unknown>(key: string): Promise<T | null>;
|
|
8
12
|
set<T = unknown>(key: string, value: T): Promise<void>;
|
|
9
13
|
delete(key: string): Promise<void>;
|
package/dist/kv.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kv.d.ts","sourceRoot":"","sources":["../src/kv.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAyBtC,qBAAa,EAAE;IAEX,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAFJ,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,IAAI;IAGvB,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAQhD,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IActD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"kv.d.ts","sourceRoot":"","sources":["../src/kv.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAyBtC,qBAAa,EAAE;IAEX,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAFJ,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,IAAI;IAGvB,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAgBnD,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAW7D,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAQhD,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IActD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAQ1B,OAAO;CAYtB"}
|
package/dist/kv.js
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
*/
|
|
13
13
|
const MAX_KEY_LENGTH = 128;
|
|
14
14
|
function assertValidKey(key) {
|
|
15
|
-
if (typeof key !==
|
|
16
|
-
throw new Error(
|
|
15
|
+
if (typeof key !== "string" || key.length === 0) {
|
|
16
|
+
throw new Error("kv key must be a non-empty string.");
|
|
17
17
|
}
|
|
18
18
|
if (key.length > MAX_KEY_LENGTH) {
|
|
19
19
|
throw new Error(`kv key exceeds ${MAX_KEY_LENGTH} chars.`);
|
|
@@ -28,9 +28,43 @@ export class Kv {
|
|
|
28
28
|
this.apiBase = apiBase;
|
|
29
29
|
this.auth = auth;
|
|
30
30
|
}
|
|
31
|
+
async list(opts) {
|
|
32
|
+
const token = this.auth.token;
|
|
33
|
+
if (!token)
|
|
34
|
+
throw new Error("Not signed in.");
|
|
35
|
+
const url = new URL(`/v1/apps/${encodeURIComponent(this.appId)}/kv`, this.apiBase);
|
|
36
|
+
if (opts?.prefix)
|
|
37
|
+
url.searchParams.set("prefix", opts.prefix);
|
|
38
|
+
const res = await fetch(url, {
|
|
39
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
40
|
+
});
|
|
41
|
+
if (res.status === 401) {
|
|
42
|
+
this.auth.handleUnauthorized();
|
|
43
|
+
throw new Error("Not signed in.");
|
|
44
|
+
}
|
|
45
|
+
if (!res.ok)
|
|
46
|
+
throw new Error(`kv.list failed: ${res.status}`);
|
|
47
|
+
let keys = (await res.json());
|
|
48
|
+
// Client-side prefix filter as fallback if server doesn't support it yet
|
|
49
|
+
if (opts?.prefix)
|
|
50
|
+
keys = keys.filter(k => k.startsWith(opts.prefix));
|
|
51
|
+
return keys;
|
|
52
|
+
}
|
|
53
|
+
async getMany(keys) {
|
|
54
|
+
for (const key of keys)
|
|
55
|
+
assertValidKey(key);
|
|
56
|
+
const results = new Map();
|
|
57
|
+
const fetches = keys.map(async (key) => {
|
|
58
|
+
const val = await this.get(key);
|
|
59
|
+
if (val !== null)
|
|
60
|
+
results.set(key, val);
|
|
61
|
+
});
|
|
62
|
+
await Promise.all(fetches);
|
|
63
|
+
return results;
|
|
64
|
+
}
|
|
31
65
|
async get(key) {
|
|
32
66
|
assertValidKey(key);
|
|
33
|
-
const res = await this.request(
|
|
67
|
+
const res = await this.request("GET", key);
|
|
34
68
|
if (res.status === 404)
|
|
35
69
|
return null;
|
|
36
70
|
if (!res.ok)
|
|
@@ -42,9 +76,9 @@ export class Kv {
|
|
|
42
76
|
// JSON.stringify(undefined) returns undefined, which would store an empty
|
|
43
77
|
// body and break later get() calls. Reject up front instead.
|
|
44
78
|
if (value === undefined) {
|
|
45
|
-
throw new Error(
|
|
79
|
+
throw new Error("kv.set: value is undefined. Use kv.delete(key) to remove a key.");
|
|
46
80
|
}
|
|
47
|
-
const res = await this.request(
|
|
81
|
+
const res = await this.request("PUT", key, JSON.stringify(value));
|
|
48
82
|
if (!res.ok) {
|
|
49
83
|
const text = await res.text();
|
|
50
84
|
throw new Error(`kv.set failed (${res.status}): ${text}`);
|
|
@@ -52,23 +86,28 @@ export class Kv {
|
|
|
52
86
|
}
|
|
53
87
|
async delete(key) {
|
|
54
88
|
assertValidKey(key);
|
|
55
|
-
const res = await this.request(
|
|
89
|
+
const res = await this.request("DELETE", key);
|
|
56
90
|
if (!res.ok && res.status !== 404) {
|
|
57
91
|
throw new Error(`kv.delete failed: ${res.status}`);
|
|
58
92
|
}
|
|
59
93
|
}
|
|
60
|
-
request(method, key, body) {
|
|
94
|
+
async request(method, key, body) {
|
|
61
95
|
const token = this.auth.token;
|
|
62
96
|
if (!token)
|
|
63
|
-
throw new Error(
|
|
97
|
+
throw new Error("Not signed in.");
|
|
64
98
|
const url = new URL(`/v1/apps/${encodeURIComponent(this.appId)}/kv/${encodeURIComponent(key)}`, this.apiBase);
|
|
65
99
|
const headers = { Authorization: `Bearer ${token}` };
|
|
66
100
|
if (body !== undefined)
|
|
67
|
-
headers[
|
|
101
|
+
headers["Content-Type"] = "application/json";
|
|
68
102
|
const init = { method, headers };
|
|
69
103
|
if (body !== undefined)
|
|
70
104
|
init.body = body;
|
|
71
|
-
|
|
105
|
+
const res = await fetch(url, init);
|
|
106
|
+
if (res.status === 401) {
|
|
107
|
+
this.auth.handleUnauthorized();
|
|
108
|
+
throw new Error("Not signed in.");
|
|
109
|
+
}
|
|
110
|
+
return res;
|
|
72
111
|
}
|
|
73
112
|
}
|
|
74
113
|
//# sourceMappingURL=kv.js.map
|
package/dist/kv.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kv.js","sourceRoot":"","sources":["../src/kv.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,MAAM,cAAc,GAAG,GAAG,CAAC;AAE3B,SAAS,cAAc,CAAC,GAAW;IACjC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,GAAG,cAAc,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,kBAAkB,cAAc,SAAS,CAAC,CAAC;IAC7D,CAAC;AACH,CAAC;AAED,MAAM,OAAO,EAAE;IAEM;IACA;IACA;IAHnB,YACmB,KAAa,EACb,OAAe,EACf,IAAU;QAFV,UAAK,GAAL,KAAK,CAAQ;QACb,YAAO,GAAP,OAAO,CAAQ;QACf,SAAI,GAAJ,IAAI,CAAM;IAC1B,CAAC;IAEJ,KAAK,CAAC,GAAG,CAAc,GAAW;QAChC,cAAc,CAAC,GAAG,CAAC,CAAC;QACpB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC3C,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QACpC,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QAC7D,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAM,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,GAAG,CAAc,GAAW,EAAE,KAAQ;QAC1C,cAAc,CAAC,GAAG,CAAC,CAAC;QACpB,0EAA0E;QAC1E,6DAA6D;QAC7D,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC;QACrF,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QAClE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,kBAAkB,GAAG,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,cAAc,CAAC,GAAG,CAAC,CAAC;QACpB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QAC9C,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,qBAAqB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IAEO,OAAO,CAAC,MAAc,EAAE,GAAW,EAAE,IAAa;
|
|
1
|
+
{"version":3,"file":"kv.js","sourceRoot":"","sources":["../src/kv.ts"],"names":[],"mappings":"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"}
|
package/dist/proxy.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Auth } from
|
|
1
|
+
import type { Auth } from "./auth.js";
|
|
2
2
|
/**
|
|
3
3
|
* Browser-side wrapper around the platform's per-app secret-injecting proxy.
|
|
4
4
|
*
|
|
@@ -15,7 +15,7 @@ import type { Auth } from './auth.js';
|
|
|
15
15
|
*
|
|
16
16
|
* The developer's secret never touches the browser.
|
|
17
17
|
*/
|
|
18
|
-
export declare class
|
|
18
|
+
export declare class ApiProxy {
|
|
19
19
|
private readonly appId;
|
|
20
20
|
private readonly apiBase;
|
|
21
21
|
private readonly auth;
|
package/dist/proxy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,
|
|
1
|
+
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,QAAQ;IAEjB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAFJ,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,IAAI;IAG7B;;;;OAIG;IACG,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC;CAWnE;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAWtD"}
|
package/dist/proxy.js
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*
|
|
15
15
|
* The developer's secret never touches the browser.
|
|
16
16
|
*/
|
|
17
|
-
export class
|
|
17
|
+
export class ApiProxy {
|
|
18
18
|
appId;
|
|
19
19
|
apiBase;
|
|
20
20
|
auth;
|
|
@@ -30,12 +30,17 @@ export class Proxy {
|
|
|
30
30
|
*/
|
|
31
31
|
async fetch(target, init) {
|
|
32
32
|
if (!this.auth.token) {
|
|
33
|
-
throw new Error(
|
|
33
|
+
throw new Error("proxy.fetch: not signed in. Call fas.auth.signIn() first.");
|
|
34
34
|
}
|
|
35
|
-
const url = `${this.apiBase}/v1/apps/${this.appId}/proxy/${normalizeTarget(target)}`;
|
|
35
|
+
const url = `${this.apiBase}/v1/apps/${encodeURIComponent(this.appId)}/proxy/${normalizeTarget(target)}`;
|
|
36
36
|
const headers = new Headers(init?.headers);
|
|
37
|
-
headers.set(
|
|
38
|
-
|
|
37
|
+
headers.set("Authorization", `Bearer ${this.auth.token}`);
|
|
38
|
+
const res = await fetch(url, { ...init, headers });
|
|
39
|
+
if (res.status === 401) {
|
|
40
|
+
this.auth.handleUnauthorized();
|
|
41
|
+
throw new Error("proxy.fetch: session expired. User has been signed out.");
|
|
42
|
+
}
|
|
43
|
+
return res;
|
|
39
44
|
}
|
|
40
45
|
}
|
|
41
46
|
/**
|
|
@@ -51,12 +56,12 @@ export function normalizeTarget(target) {
|
|
|
51
56
|
const schemeMatch = /^([a-z][a-z0-9+.-]*):\/\//i.exec(target);
|
|
52
57
|
if (schemeMatch) {
|
|
53
58
|
const scheme = schemeMatch[1].toLowerCase();
|
|
54
|
-
if (scheme ===
|
|
59
|
+
if (scheme === "http" || scheme === "https") {
|
|
55
60
|
return target.slice(schemeMatch[0].length);
|
|
56
61
|
}
|
|
57
|
-
throw new Error(
|
|
62
|
+
throw new Error("proxy.fetch: only http(s) targets are supported");
|
|
58
63
|
}
|
|
59
64
|
// Already in "host/path" form.
|
|
60
|
-
return target.replace(/^\/+/,
|
|
65
|
+
return target.replace(/^\/+/, "");
|
|
61
66
|
}
|
|
62
67
|
//# sourceMappingURL=proxy.js.map
|
package/dist/proxy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,OAAO,
|
|
1
|
+
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,OAAO,QAAQ;IAEA;IACA;IACA;IAHnB,YACmB,KAAa,EACb,OAAe,EACf,IAAU;QAFV,UAAK,GAAL,KAAK,CAAQ;QACb,YAAO,GAAP,OAAO,CAAQ;QACf,SAAI,GAAJ,IAAI,CAAM;IAC1B,CAAC;IAEJ;;;;OAIG;IACH,KAAK,CAAC,KAAK,CAAC,MAAc,EAAE,IAAkB;QAC5C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;QAC/E,CAAC;QACD,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,YAAY,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC;QACzG,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QAC1D,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QACnD,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAAC,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;QAAC,CAAC;QACvI,OAAO,GAAG,CAAC;IACb,CAAC;CACF;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,MAAM,WAAW,GAAG,4BAA4B,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC9D,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,CAAC;QAC7C,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;YAC5C,OAAO,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QAC7C,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,CAAC;IACD,+BAA+B;IAC/B,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACpC,CAAC"}
|
package/dist/proxy.test.js
CHANGED
|
@@ -1,73 +1,73 @@
|
|
|
1
|
-
import { describe,
|
|
2
|
-
import {
|
|
3
|
-
describe(
|
|
4
|
-
it(
|
|
5
|
-
expect(normalizeTarget(
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { normalizeTarget, ApiProxy } from "./proxy.js";
|
|
3
|
+
describe("normalizeTarget", () => {
|
|
4
|
+
it("passes through bare host/path form", () => {
|
|
5
|
+
expect(normalizeTarget("api.example.com/v1/x")).toBe("api.example.com/v1/x");
|
|
6
6
|
});
|
|
7
|
-
it(
|
|
8
|
-
expect(normalizeTarget(
|
|
9
|
-
expect(normalizeTarget(
|
|
7
|
+
it("strips https:// and http:// prefixes", () => {
|
|
8
|
+
expect(normalizeTarget("https://api.example.com/v1/x")).toBe("api.example.com/v1/x");
|
|
9
|
+
expect(normalizeTarget("http://api.example.com/v1/x")).toBe("api.example.com/v1/x");
|
|
10
10
|
});
|
|
11
|
-
it(
|
|
12
|
-
expect(normalizeTarget(
|
|
13
|
-
expect(normalizeTarget(
|
|
11
|
+
it("matches the scheme case-insensitively", () => {
|
|
12
|
+
expect(normalizeTarget("HTTPS://api.example.com/v1/x")).toBe("api.example.com/v1/x");
|
|
13
|
+
expect(normalizeTarget("Http://api.example.com/v1/x")).toBe("api.example.com/v1/x");
|
|
14
14
|
});
|
|
15
|
-
it(
|
|
16
|
-
expect(normalizeTarget(
|
|
15
|
+
it("strips leading slashes from bare form", () => {
|
|
16
|
+
expect(normalizeTarget("//api.example.com/v1")).toBe("api.example.com/v1");
|
|
17
17
|
});
|
|
18
|
-
it(
|
|
19
|
-
expect(normalizeTarget(
|
|
18
|
+
it("preserves query strings", () => {
|
|
19
|
+
expect(normalizeTarget("api.example.com/x?a=1&b=2")).toBe("api.example.com/x?a=1&b=2");
|
|
20
20
|
});
|
|
21
|
-
it(
|
|
22
|
-
expect(() => normalizeTarget(
|
|
23
|
-
expect(() => normalizeTarget(
|
|
21
|
+
it("rejects non-http(s) schemes", () => {
|
|
22
|
+
expect(() => normalizeTarget("ftp://api.example.com/x")).toThrow(/http\(s\)/);
|
|
23
|
+
expect(() => normalizeTarget("javascript://x")).toThrow(/http\(s\)/);
|
|
24
24
|
});
|
|
25
25
|
});
|
|
26
|
-
describe(
|
|
27
|
-
it(
|
|
26
|
+
describe("Proxy.fetch", () => {
|
|
27
|
+
it("throws when not signed in", async () => {
|
|
28
28
|
const auth = { token: null };
|
|
29
|
-
const proxy = new
|
|
30
|
-
await expect(proxy.fetch(
|
|
29
|
+
const proxy = new ApiProxy("weather", "https://api.example.com", auth);
|
|
30
|
+
await expect(proxy.fetch("api.openweathermap.org/data/2.5/weather")).rejects.toThrow(/not signed in/);
|
|
31
31
|
});
|
|
32
|
-
it(
|
|
33
|
-
const auth = { token:
|
|
34
|
-
const proxy = new
|
|
32
|
+
it("builds the right URL and forwards Bearer auth", async () => {
|
|
33
|
+
const auth = { token: "tok-123" };
|
|
34
|
+
const proxy = new ApiProxy("weather", "https://api.example.com", auth);
|
|
35
35
|
const captured = {};
|
|
36
36
|
const origFetch = globalThis.fetch;
|
|
37
37
|
globalThis.fetch = vi.fn(async (url, init) => {
|
|
38
38
|
captured.url = String(url);
|
|
39
39
|
captured.init = init;
|
|
40
|
-
return new Response(
|
|
40
|
+
return new Response("ok");
|
|
41
41
|
});
|
|
42
42
|
try {
|
|
43
|
-
await proxy.fetch(
|
|
44
|
-
expect(captured.url).toBe(
|
|
43
|
+
await proxy.fetch("api.openweathermap.org/data/2.5/weather?q=London");
|
|
44
|
+
expect(captured.url).toBe("https://api.example.com/v1/apps/weather/proxy/api.openweathermap.org/data/2.5/weather?q=London");
|
|
45
45
|
const h = new Headers(captured.init?.headers);
|
|
46
|
-
expect(h.get(
|
|
46
|
+
expect(h.get("authorization")).toBe("Bearer tok-123");
|
|
47
47
|
}
|
|
48
48
|
finally {
|
|
49
49
|
globalThis.fetch = origFetch;
|
|
50
50
|
}
|
|
51
51
|
});
|
|
52
|
-
it(
|
|
53
|
-
const auth = { token:
|
|
54
|
-
const proxy = new
|
|
52
|
+
it("preserves caller-supplied headers and method", async () => {
|
|
53
|
+
const auth = { token: "tok" };
|
|
54
|
+
const proxy = new ApiProxy("weather", "https://api.example.com", auth);
|
|
55
55
|
const captured = {};
|
|
56
56
|
const origFetch = globalThis.fetch;
|
|
57
57
|
globalThis.fetch = vi.fn(async (_url, init) => {
|
|
58
58
|
captured.init = init;
|
|
59
|
-
return new Response(
|
|
59
|
+
return new Response("ok");
|
|
60
60
|
});
|
|
61
61
|
try {
|
|
62
|
-
await proxy.fetch(
|
|
63
|
-
method:
|
|
64
|
-
headers: {
|
|
65
|
-
body:
|
|
62
|
+
await proxy.fetch("api.example.com/v1/x", {
|
|
63
|
+
method: "POST",
|
|
64
|
+
headers: { "Content-Type": "application/json" },
|
|
65
|
+
body: "{}",
|
|
66
66
|
});
|
|
67
|
-
expect(captured.init?.method).toBe(
|
|
67
|
+
expect(captured.init?.method).toBe("POST");
|
|
68
68
|
const h = new Headers(captured.init?.headers);
|
|
69
|
-
expect(h.get(
|
|
70
|
-
expect(h.get(
|
|
69
|
+
expect(h.get("content-type")).toBe("application/json");
|
|
70
|
+
expect(h.get("authorization")).toBe("Bearer tok");
|
|
71
71
|
}
|
|
72
72
|
finally {
|
|
73
73
|
globalThis.fetch = origFetch;
|
package/dist/proxy.test.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.test.js","sourceRoot":"","sources":["../src/proxy.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"proxy.test.js","sourceRoot":"","sources":["../src/proxy.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@freeappstore/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Browser SDK for free apps on freeappstore.online — auth, per-user KV, light realtime rooms, secret-injecting proxy for third-party APIs.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|