@bounded-sh/core 0.0.26 → 0.0.35
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/client/config.d.ts +8 -10
- package/dist/client/live.d.ts +11 -2
- package/dist/client/subscription-v2.d.ts +2 -0
- package/dist/index.js +76 -20
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +76 -20
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -6
package/dist/index.mjs
CHANGED
|
@@ -19,14 +19,10 @@ let clientConfig = {
|
|
|
19
19
|
humanAuthApiUrl: 'https://auth.bounded.sh',
|
|
20
20
|
functionsUrl: 'https://functions.bounded.sh',
|
|
21
21
|
appId: '',
|
|
22
|
-
// No hidden
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
// Bounded explicitly enables it for the issuer. For
|
|
27
|
-
// crypto/onchain wallet login use authMethod:'phantom' (Solana / Phantom), or
|
|
28
|
-
// signInAnonymously() for zero-friction 'guest' accounts. ('wallet' is an
|
|
29
|
-
// unimplemented stub; don't use.)
|
|
22
|
+
// No hidden modal fallback: browser clients start hosted Bounded Auth with
|
|
23
|
+
// loginWithRedirect/loginWithPopup. For crypto/onchain wallet login use
|
|
24
|
+
// authMethod:'phantom' (Solana / Phantom), and use signInAnonymously() for
|
|
25
|
+
// zero-friction guest accounts. ('wallet' is an unimplemented stub; don't use.)
|
|
30
26
|
authMethod: 'none',
|
|
31
27
|
chain: '',
|
|
32
28
|
rpcUrl: '',
|
|
@@ -2806,6 +2802,7 @@ async function genAuthNonce() {
|
|
|
2806
2802
|
// from 'phantom' and couldn't be gated or flagged.
|
|
2807
2803
|
const SIGNATURE_AUTH_METHODS = new Set(['phantom', 'mobile-wallet-adapter', 'guest']);
|
|
2808
2804
|
async function createSessionWithSignature(address, message, signature) {
|
|
2805
|
+
var _a, _b;
|
|
2809
2806
|
const client = await getAxiosAuthClient();
|
|
2810
2807
|
const config = await getConfig();
|
|
2811
2808
|
const appId = config.appId;
|
|
@@ -2815,14 +2812,30 @@ async function createSessionWithSignature(address, message, signature) {
|
|
|
2815
2812
|
// for a signature exchange. This is what makes the server SDK + guest device
|
|
2816
2813
|
// keypair work under the email-default config.
|
|
2817
2814
|
const authMethod = SIGNATURE_AUTH_METHODS.has(config.authMethod) ? config.authMethod : 'phantom';
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2815
|
+
try {
|
|
2816
|
+
const response = await client.post('/session', {
|
|
2817
|
+
appId,
|
|
2818
|
+
address,
|
|
2819
|
+
message,
|
|
2820
|
+
signature,
|
|
2821
|
+
authMethod
|
|
2822
|
+
});
|
|
2823
|
+
return response.data;
|
|
2824
|
+
}
|
|
2825
|
+
catch (err) {
|
|
2826
|
+
// Surface the issuer's actionable message (e.g. "Anonymous auth is not enabled for
|
|
2827
|
+
// this app. Add \"auth\": { \"anonymous\": true } to policy.json and redeploy.")
|
|
2828
|
+
// instead of axios's generic "Request failed with status code 403".
|
|
2829
|
+
const d = (_a = err === null || err === void 0 ? void 0 : err.response) === null || _a === void 0 ? void 0 : _a.data;
|
|
2830
|
+
if (d && (d.message || d.error)) {
|
|
2831
|
+
const e = new Error(String(d.message || d.error));
|
|
2832
|
+
e.code = d.error;
|
|
2833
|
+
e.status = (_b = err === null || err === void 0 ? void 0 : err.response) === null || _b === void 0 ? void 0 : _b.status;
|
|
2834
|
+
e.hint = d.hint;
|
|
2835
|
+
throw e;
|
|
2836
|
+
}
|
|
2837
|
+
throw err;
|
|
2838
|
+
}
|
|
2826
2839
|
}
|
|
2827
2840
|
// Deduplicate concurrent refreshSession calls to prevent multiple code paths
|
|
2828
2841
|
// (WebSocket reconnection, periodic refresh, API 401 retry) from all hitting
|
|
@@ -6542,7 +6555,30 @@ async function wsIntent(appId, roomRoutePath, intent, isServer) {
|
|
|
6542
6555
|
if (!connection || !connection.ws || connection.ws.readyState !== WS_READY_STATE_OPEN || connection.isAuthenticating) {
|
|
6543
6556
|
return false;
|
|
6544
6557
|
}
|
|
6545
|
-
|
|
6558
|
+
// Identity-aware send gate. The server attributes intents to the
|
|
6559
|
+
// CONNECTION's authenticated principal, so the only correct reasons to
|
|
6560
|
+
// refuse the socket are identity ones:
|
|
6561
|
+
// - the socket is anonymous while the user is now authenticated, or
|
|
6562
|
+
// - the current principal DIFFERS from the socket principal.
|
|
6563
|
+
// A mere token rotation for the SAME principal, or a transiently-null
|
|
6564
|
+
// token mid-refresh, must NOT reroute a 30Hz command stream to
|
|
6565
|
+
// per-command HTTP — that collapses delivery rate and unbounds the game's
|
|
6566
|
+
// ack lag (field-debugged: server 500+ commands behind).
|
|
6567
|
+
const currentToken = await getIdToken(isServer).catch(() => null);
|
|
6568
|
+
if (!currentToken) {
|
|
6569
|
+
// Mid-refresh: the socket principal still governs server-side.
|
|
6570
|
+
if (!connection.authTokenFingerprint && !connection.authPrincipal)
|
|
6571
|
+
return false;
|
|
6572
|
+
}
|
|
6573
|
+
else if (!connection.authTokenFingerprint && !connection.authPrincipal) {
|
|
6574
|
+
// Anonymous socket + authenticated user: do not attribute this user's
|
|
6575
|
+
// input to the anon principal. Reauth the socket; caller may fall back.
|
|
6576
|
+
void maybeReauthRoomConnection(connection);
|
|
6577
|
+
return false;
|
|
6578
|
+
}
|
|
6579
|
+
else if (!connectionMatchesAuthToken(connection, currentToken)) {
|
|
6580
|
+
// Different principal (identity switch): never send as the old user.
|
|
6581
|
+
void maybeReauthRoomConnection(connection);
|
|
6546
6582
|
return false;
|
|
6547
6583
|
}
|
|
6548
6584
|
try {
|
|
@@ -6553,6 +6589,26 @@ async function wsIntent(appId, roomRoutePath, intent, isServer) {
|
|
|
6553
6589
|
return false;
|
|
6554
6590
|
}
|
|
6555
6591
|
}
|
|
6592
|
+
// Debounced background reauth: when the client's current token no longer
|
|
6593
|
+
// matches the connection's auth fingerprint (token rotation), refresh the
|
|
6594
|
+
// socket auth ONCE rather than degrading every subsequent send.
|
|
6595
|
+
const reauthInFlight = new WeakSet();
|
|
6596
|
+
async function maybeReauthRoomConnection(connection, isServer) {
|
|
6597
|
+
try {
|
|
6598
|
+
if (reauthInFlight.has(connection))
|
|
6599
|
+
return;
|
|
6600
|
+
reauthInFlight.add(connection);
|
|
6601
|
+
try {
|
|
6602
|
+
await reconnectWithNewAuthV2();
|
|
6603
|
+
}
|
|
6604
|
+
finally {
|
|
6605
|
+
reauthInFlight.delete(connection);
|
|
6606
|
+
}
|
|
6607
|
+
}
|
|
6608
|
+
catch (_a) {
|
|
6609
|
+
// Best-effort: the next send retries; the server still enforces auth.
|
|
6610
|
+
}
|
|
6611
|
+
}
|
|
6556
6612
|
/**
|
|
6557
6613
|
* Send a live-room intent over the EXISTING per-room socket and AWAIT the server
|
|
6558
6614
|
* ack — so a policy/auth denial (401/403/404/503) REJECTS instead of being
|
|
@@ -7120,8 +7176,8 @@ async function status(roomPath, opts = {}) {
|
|
|
7120
7176
|
* claims); pass `opts.userId` to override. Returns the unsubscribe function
|
|
7121
7177
|
* (a Promise<() => Promise<void>>, same as `subscribe`).
|
|
7122
7178
|
*
|
|
7123
|
-
*
|
|
7124
|
-
*
|
|
7179
|
+
* Server/agent consumers: use `WalletClient.live.subscribeView` (it supplies
|
|
7180
|
+
* the wallet session + view id); browser apps just call this directly.
|
|
7125
7181
|
*/
|
|
7126
7182
|
async function subscribeView(roomPath, opts) {
|
|
7127
7183
|
if (!roomPath || typeof roomPath !== 'string') {
|
|
@@ -7151,7 +7207,7 @@ async function subscribeView(roomPath, opts) {
|
|
|
7151
7207
|
// derives the room from the `?path=` the connection carries). Without this the
|
|
7152
7208
|
// subscription lands on the app-level project DO and never sees the room's
|
|
7153
7209
|
// ephemeral view writes.
|
|
7154
|
-
return subscribeV2(viewPath, { onData: opts.onData, onError: opts.onError }, normalizedRoomPath);
|
|
7210
|
+
return subscribeV2(viewPath, { onData: opts.onData, onError: opts.onError, _overrides: opts._overrides }, normalizedRoomPath);
|
|
7155
7211
|
}
|
|
7156
7212
|
/** The `bounded.live` namespace surface. */
|
|
7157
7213
|
const live = { intent, status, subscribeView };
|