@crowdedkingdoms/crowdyjs 7.1.1 → 8.0.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.
Files changed (45) hide show
  1. package/MIGRATION.md +46 -0
  2. package/README.md +51 -14
  3. package/dist/client.d.ts +8 -0
  4. package/dist/client.d.ts.map +1 -1
  5. package/dist/client.js +5 -0
  6. package/dist/crowdy-client.d.ts +7 -0
  7. package/dist/crowdy-client.d.ts.map +1 -1
  8. package/dist/crowdy-client.js +4 -0
  9. package/dist/domains/auth.d.ts +77 -140
  10. package/dist/domains/auth.d.ts.map +1 -1
  11. package/dist/domains/auth.js +81 -178
  12. package/dist/domains/gameModel.d.ts +54 -3
  13. package/dist/domains/gameModel.d.ts.map +1 -1
  14. package/dist/domains/gameModel.js +67 -4
  15. package/dist/domains/host.d.ts +14 -3
  16. package/dist/domains/host.d.ts.map +1 -1
  17. package/dist/domains/host.js +17 -3
  18. package/dist/domains/organizations.d.ts +3 -3
  19. package/dist/domains/organizations.js +3 -3
  20. package/dist/domains/portal.d.ts +43 -1
  21. package/dist/domains/portal.d.ts.map +1 -1
  22. package/dist/domains/portal.js +59 -1
  23. package/dist/domains/quotas.d.ts +1 -1
  24. package/dist/domains/quotas.js +1 -1
  25. package/dist/domains/udp.d.ts +28 -17
  26. package/dist/domains/udp.d.ts.map +1 -1
  27. package/dist/domains/udp.js +28 -17
  28. package/dist/generated/graphql.d.ts +420 -106
  29. package/dist/generated/graphql.d.ts.map +1 -1
  30. package/dist/generated/graphql.js +6 -8
  31. package/dist/index.d.ts +14 -9
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +13 -8
  34. package/dist/lb-cookie-store.d.ts +20 -0
  35. package/dist/lb-cookie-store.d.ts.map +1 -0
  36. package/dist/lb-cookie-store.js +73 -0
  37. package/dist/realtime.d.ts +20 -5
  38. package/dist/realtime.d.ts.map +1 -1
  39. package/dist/realtime.js +38 -0
  40. package/dist/types.d.ts +22 -6
  41. package/dist/types.d.ts.map +1 -1
  42. package/dist/world.d.ts +13 -8
  43. package/dist/world.d.ts.map +1 -1
  44. package/dist/world.js +13 -8
  45. package/package.json +6 -4
package/MIGRATION.md CHANGED
@@ -1,3 +1,49 @@
1
+ # CrowdyJS v8 — Passwordless & federated sign-in (BREAKING)
2
+
3
+ **Crowded Kingdoms is passwordless.** Email + password login is removed. Update
4
+ your sign-in flow to one of:
5
+
6
+ - **Magic link (email):**
7
+ ```ts
8
+ await client.auth.requestLoginLink({ email, redirectUri }); // emails a one-time link
9
+ // on the landing page (token from the URL):
10
+ const { user } = await client.auth.completeLoginLink(tokenFromUrl);
11
+ ```
12
+ - **Social (federated / OIDC):**
13
+ ```ts
14
+ const providers = await client.auth.availableLoginProviders(); // e.g. ['google']
15
+ const { authorizeUrl, state } = await client.auth.socialLoginStart('google', callbackUrl);
16
+ location.assign(authorizeUrl);
17
+ // on the callback page:
18
+ await client.auth.socialLoginComplete({ provider: 'google', code, state });
19
+ ```
20
+ - **Dev bypass (development only):** `await client.auth.devLogin(email)` — works only
21
+ when the server has `DEV_AUTH_BYPASS` enabled.
22
+
23
+ **Removed:** `client.auth.login`, `register`, `confirmEmail`, `requestPasswordReset`,
24
+ `resetPassword`, `resendConfirmationEmail`, `changePassword` (and the
25
+ `LoginUserInput` / `RegisterUserInput` / `ResetPasswordInput` types).
26
+
27
+ **New:** `requestLoginLink`, `completeLoginLink`, `socialLoginStart`,
28
+ `socialLoginComplete`, `devLogin`, `availableLoginProviders`, `myIdentities`,
29
+ `linkIdentity`, `unlinkIdentity`. Each sign-in still returns an identity session
30
+ token, stored on the shared session automatically (account is created on first
31
+ sign-in).
32
+
33
+ **Portal consent + connected apps (new on `client.portal`):** `getConsent(appId)`,
34
+ `authorizeApp(appId)`, `revokeAppAuthorization(appId)`, `myAuthorizedApps()`,
35
+ `setAppClientSettings({ appId, redirectUris, clientType, launchUrl })`.
36
+ `handleAuthorizeRequest` now enforces consent: untrusted apps throw
37
+ `PortalConsentRequiredError` unless you pass `{ grantConsent: true }` (call after
38
+ the user approves on the consent screen). Trusted/first-party apps (the Overworld,
39
+ app 1) skip consent. Browser portal entry now requires the destination app's
40
+ `redirect_uris` to be registered (`setAppClientSettings`).
41
+
42
+ Everything else from v7 (the two-client pattern, `client.portal` minting/PKCE,
43
+ app-scoped tokens) is unchanged.
44
+
45
+ ---
46
+
1
47
  # CrowdyJS v7 — Overworld portals & app-scoped tokens (BREAKING)
2
48
 
3
49
  v7 splits the single app-agnostic game token into two credentials and makes
package/README.md CHANGED
@@ -14,6 +14,37 @@ CrowdyJS v4 targets browsers by default and uses native `fetch`, `WebSocket`, `c
14
14
 
15
15
  > **Server compatibility:** v5.2+ targets environments on release **v0.1.19 or later** (`cks-game-api >= v0.10.3`, `cks-management-api >= v0.1.70`). The destructive mutations send an `idempotencyKey` argument that older servers don't define. v6.1's `client.gameApps.deleteGrid` additionally requires release **v0.1.33+** (`cks-game-api >= v0.12.3`).
16
16
 
17
+ ## Standalone builds and schema refresh
18
+
19
+ CrowdyJS is a standalone public package. A clean external clone must be able to
20
+ run `npm install && npm run build` without sibling CKS API repos checked out.
21
+ For that reason the build uses committed schema artifacts in this repo:
22
+
23
+ - `schema.gql` — merged Management API + Game API SDL.
24
+ - `src/generated/graphql.ts` — generated TypeScript operation types.
25
+
26
+ Schema refresh is explicit:
27
+
28
+ ```bash
29
+ # Refresh from the published production SDLs.
30
+ npm run schema:sync:prod
31
+ npm run codegen
32
+
33
+ # Or, inside the CKS wrapper repo, refresh from local API checkouts.
34
+ npm run schema:sync:local
35
+ npm run codegen
36
+
37
+ # Or use exact file/URL sources.
38
+ npm run schema:sync:paths -- \
39
+ --management ../cks-management-api/schema.gql \
40
+ --game ../cks-game-api/schema.gql
41
+ npm run codegen
42
+ ```
43
+
44
+ Commit `schema.gql` and `src/generated/graphql.ts` together whenever the public
45
+ GraphQL surface changes. Do not make `npm run build` depend on local API repos or
46
+ network access; use `npm run check:schema` in CI/release work to detect drift.
47
+
17
48
  ## Quick start
18
49
 
19
50
  ```ts
@@ -26,7 +57,7 @@ const client = createCrowdyClient({
26
57
  // Game API (world data + UDP proxy)
27
58
  httpUrl: 'https://game.example.com',
28
59
  wsUrl: 'wss://game.example.com',
29
- // Management API (login, register, profile)
60
+ // Management API (passwordless sign-in, profile)
30
61
  managementUrl: 'https://management.example.com',
31
62
  tokenStore: new BrowserLocalStorageTokenStore(),
32
63
  realtime: {
@@ -35,19 +66,23 @@ const client = createCrowdyClient({
35
66
  },
36
67
  });
37
68
 
38
- // Restore a previous session if there is one, otherwise log in.
69
+ // Restore a previous session if there is one, otherwise sign in (passwordless).
39
70
  await client.session.restore();
40
71
  if (!client.session.getToken()) {
41
- await client.auth.login({ email: 'player@example.com', password: 'secret' });
72
+ // Magic link: email a one-time link, then complete with the token from it.
73
+ await client.auth.requestLoginLink({ email: 'player@example.com', redirectUri });
74
+ await client.auth.completeLoginLink(tokenFromLink);
75
+ // Or social/OIDC: socialLoginStart('google', redirectUri) -> socialLoginComplete({ provider, code, state })
76
+ // Or dev/test only (server has DEV_AUTH_BYPASS): client.auth.devLogin('player@example.com')
42
77
  }
43
78
 
44
- // `client.auth.login()` returns an identity SESSION token (Management API only).
45
- // Identity reads run on it:
79
+ // Passwordless sign-in returns an identity SESSION token (Management API only);
80
+ // the account is created on first sign-in. Identity reads run on it:
46
81
  const me = await client.users.me();
47
82
  console.log(me.email);
48
83
  ```
49
84
 
50
- **Gameplay needs an app-scoped token, not the login token.** Mint one per app and
85
+ **Gameplay needs an app-scoped token, not the session token.** Mint one per app and
51
86
  drive the Game API world/UDP surface (including `gameClientBootstrap`) from a
52
87
  per-game client — see [Overworld portals & app-scoped tokens (v7)](#overworld-portals--app-scoped-tokens-v7).
53
88
 
@@ -59,12 +94,12 @@ If `managementUrl` is omitted, the SDK falls back to `httpUrl` for backwards-com
59
94
 
60
95
  | Sub-client | What it does |
61
96
  |---|---|
62
- | `client.auth` | Register, log in, log out, password reset, email confirmation. |
97
+ | `client.auth` | Passwordless sign-in (magic link, social/OIDC, dev bypass), log out, and linked identities (`myIdentities`, `linkIdentity`/`unlinkIdentity`). |
63
98
  | `client.users` | `me`, `updateGamertag`, profile reads. |
64
99
  | `client.session` | Token store, `restore()`, `getToken()`, manual `setToken()`. |
65
100
  | `client.serverStatus` | `gameClientBootstrap(appId)` — per-app version info, UDP status, spatial limits. |
66
101
  | `client.chunks`, `client.voxels`, `client.actors`, `client.avatars`, `client.state` | World data reads + writes. |
67
- | `client.host` | Game-host election + actor liveness `heartbeat`. |
102
+ | `client.host` | Game-host election (`get`, `amIHost`) + actor liveness `heartbeat`. `amIHost` is UI convenience only — authoritative host gating uses `gameModelInvoke`'s `is_host` policy. |
68
103
  | `client.teleport` | Teleport requests. |
69
104
  | `client.channels`, `client.teams` | Messaging channels and app-scoped player teams (membership + roles). |
70
105
  | `client.gameModel` | Abstract game model: containers, properties, functions (incl. model-driven `notify_*` effects), sessions, and **automations / NPCs** (`upsertAutomation`, `runAutomation`, `automationRuns`, `automationStats`, …). |
@@ -97,7 +132,7 @@ Auth, user reads, and the studio-admin / operator surfaces target `managementUrl
97
132
 
98
133
  ## Game-loop lifecycle
99
134
 
100
- 1. Authenticate on the identity client with `client.auth.login()` (or `client.session.restore()`) this yields the **session token**.
135
+ 1. Sign in (passwordless) on the identity client with `client.auth` — `requestLoginLink`/`completeLoginLink` (magic link), `socialLoginStart`/`socialLoginComplete` (social/OIDC), or `devLogin` (dev/test only) — or `client.session.restore()`. This yields the **session token** (Management API only).
101
136
  2. Mint an **app-scoped token** for the app (`identity.portal.mintAppToken(appId)`, or the PKCE portal flow across origins) and build a per-game client holding it (`game.setToken(token)`). The gameplay steps below run on that **game** client.
102
137
  3. Subscribe to UDP proxy notifications with `game.udp.subscribe(handlers, appId)` — `appId` is **required** (the SDK opens the realtime socket on demand and scopes it to that app).
103
138
  4. Join a chunk by sending an initial actor update.
@@ -269,10 +304,10 @@ The key parameter is optional and trailing, so it's safe to omit. Requires a ser
269
304
 
270
305
  ## Overworld portals & app-scoped tokens (v7)
271
306
 
272
- As of v7 gameplay requires an **app-scoped token**, not the login token. Login
273
- returns an **identity session token** (Management API only — account, studio
274
- admin, and minting); each game is entered with a short-lived token confined to
275
- that one app, so a game stack never receives the player's full session.
307
+ As of v7 gameplay requires an **app-scoped token**, not the session token.
308
+ Passwordless sign-in returns an **identity session token** (Management API only —
309
+ account, studio admin, and minting); each game is entered with a short-lived token
310
+ confined to that one app, so a game stack never receives the player's full session.
276
311
 
277
312
  Use two clients: an Overworld/identity client (session token) and a per-game
278
313
  client (app token), sharing only the Management URL.
@@ -280,7 +315,9 @@ client (app token), sharing only the Management URL.
280
315
  ```ts
281
316
  // Overworld/identity client
282
317
  const overworld = createCrowdyClient({ managementUrl, tokenStore: new BrowserLocalStorageTokenStore('crowdyjs:session') });
283
- await overworld.auth.login({ email, password });
318
+ // Passwordless sign-in (magic link, social/OIDC, or dev bypass) yields the session token.
319
+ await overworld.auth.requestLoginLink({ email, redirectUri });
320
+ await overworld.auth.completeLoginLink(tokenFromLink);
284
321
 
285
322
  // Native / same-origin: mint directly, then build a game client.
286
323
  const t = await overworld.portal.mintAppToken(appId);
package/dist/client.d.ts CHANGED
@@ -9,6 +9,7 @@
9
9
  import type { TypedDocumentNode } from '@graphql-typed-document-node/core';
10
10
  import type { SessionStore } from './session.js';
11
11
  import type { CrowdyLogger } from './logger.js';
12
+ import type { LbCookieStore } from './lb-cookie-store.js';
12
13
  /**
13
14
  * Configuration for {@link GraphQLClient}, the low-level HTTP transport. You
14
15
  * normally don't build this yourself — `CrowdyClient` constructs the transport
@@ -38,6 +39,12 @@ export interface GraphQLClientConfig {
38
39
  * that discards all output.
39
40
  */
40
41
  logger?: CrowdyLogger;
42
+ /**
43
+ * Optional sticky-LB cookie jar for game-api requests. When set, the
44
+ * client forwards `cks_ga` on HTTP and ingests `Set-Cookie` from responses
45
+ * so mutations stay pinned to the same upstream as the WS subscription.
46
+ */
47
+ lbCookieStore?: LbCookieStore;
41
48
  }
42
49
  /**
43
50
  * Low-level HTTP transport for GraphQL operations against the game or
@@ -65,6 +72,7 @@ export declare class GraphQLClient {
65
72
  private readonly timeout;
66
73
  private readonly session;
67
74
  private readonly logger;
75
+ private readonly lbCookieStore?;
68
76
  /**
69
77
  * @param config - Endpoint, timeout, and logger options; see
70
78
  * {@link GraphQLClientConfig}.
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAWhD;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IAEtC;;;;;;OAMG;gBACS,MAAM,EAAE,mBAAmB,YAAK,EAAE,OAAO,EAAE,YAAY;IAUnE;;;;OAIG;IACH,WAAW,IAAI,MAAM;IAIrB;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,OAAO,CAAC,OAAO,EAAE,UAAU,EAC/B,QAAQ,EAAE,iBAAiB,CAAC,OAAO,EAAE,UAAU,CAAC,EAChD,SAAS,CAAC,EAAE,UAAU,EACtB,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAO,GACrC,OAAO,CAAC,OAAO,CAAC;IASnB;;;;;;;;;;;;;;;;;;;OAmBG;IACG,KAAK,CAAC,CAAC,GAAG,GAAG,EACjB,KAAK,EAAE,MAAM,EACb,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACvC,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAO,GACrC,OAAO,CAAC,CAAC,CAAC;CA+Cd;AAED;;;GAGG;AACH,OAAO,EAAE,aAAa,IAAI,gBAAgB,EAAE,CAAC"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAUhD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB;;;;OAIG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAgB;IAE/C;;;;;;OAMG;gBACS,MAAM,EAAE,mBAAmB,YAAK,EAAE,OAAO,EAAE,YAAY;IAWnE;;;;OAIG;IACH,WAAW,IAAI,MAAM;IAIrB;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,OAAO,CAAC,OAAO,EAAE,UAAU,EAC/B,QAAQ,EAAE,iBAAiB,CAAC,OAAO,EAAE,UAAU,CAAC,EAChD,SAAS,CAAC,EAAE,UAAU,EACtB,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAO,GACrC,OAAO,CAAC,OAAO,CAAC;IASnB;;;;;;;;;;;;;;;;;;;OAmBG;IACG,KAAK,CAAC,CAAC,GAAG,GAAG,EACjB,KAAK,EAAE,MAAM,EACb,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACvC,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAO,GACrC,OAAO,CAAC,CAAC,CAAC;CAmDd;AAED;;;GAGG;AACH,OAAO,EAAE,aAAa,IAAI,gBAAgB,EAAE,CAAC"}
package/dist/client.js CHANGED
@@ -46,6 +46,7 @@ export class GraphQLClient {
46
46
  this.timeout = config.timeout || 60000;
47
47
  this.session = session;
48
48
  this.logger = config.logger ?? silentLogger;
49
+ this.lbCookieStore = config.lbCookieStore;
49
50
  }
50
51
  /**
51
52
  * The resolved GraphQL endpoint URL this client POSTs to.
@@ -105,6 +106,7 @@ export class GraphQLClient {
105
106
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
106
107
  const token = this.session.getToken();
107
108
  const signal = options.signal ?? controller.signal;
109
+ const lbCookie = this.lbCookieStore?.headerValue();
108
110
  try {
109
111
  const requestBody = { query, variables };
110
112
  const response = await fetch(this.graphqlEndpoint, {
@@ -112,11 +114,14 @@ export class GraphQLClient {
112
114
  headers: {
113
115
  'Content-Type': 'application/json',
114
116
  ...(token ? { Authorization: `Bearer ${token}` } : {}),
117
+ ...(lbCookie ? { Cookie: lbCookie } : {}),
115
118
  },
116
119
  body: JSON.stringify(requestBody),
120
+ credentials: this.lbCookieStore ? 'include' : 'same-origin',
117
121
  signal,
118
122
  });
119
123
  clearTimeout(timeoutId);
124
+ this.lbCookieStore?.ingestSetCookie(response.headers);
120
125
  if (!response.ok) {
121
126
  const errorText = await response.text();
122
127
  throw new CrowdyHttpError(response.status, errorText);
@@ -22,6 +22,7 @@
22
22
  */
23
23
  import { AuthState } from './auth-state.js';
24
24
  import { GraphQLClient } from './client.js';
25
+ import { LbCookieStore } from './lb-cookie-store.js';
25
26
  import { SubscriptionManager } from './subscriptions.js';
26
27
  import type { CrowdyLogger } from './logger.js';
27
28
  import type { TokenStore } from './session.js';
@@ -101,6 +102,12 @@ export interface CrowdyClientConfig {
101
102
  /** Default timeout for `...AndWait` round-trips that await a matching echo. */
102
103
  waitTimeoutMs?: number;
103
104
  };
105
+ /**
106
+ * Optional sticky-LB cookie jar shared with the game-api HTTP client. Node
107
+ * runtimes must forward `cks_ga` on the WebSocket upgrade; browsers send it
108
+ * automatically once HTTP has stored the cookie via `credentials: 'include'`.
109
+ */
110
+ lbCookieStore?: LbCookieStore;
104
111
  }
105
112
  export declare class CrowdyClient {
106
113
  /** Shared token state for both game-api and management-api requests. */
@@ -1 +1 @@
1
- {"version":3,"file":"crowdy-client.d.ts","sourceRoot":"","sources":["../src/crowdy-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD,MAAM,WAAW,kBAAkB;IAEjC,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wBAAwB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mEAAmE;IACnE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC;IAGpB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+EAA+E;IAC/E,yBAAyB,CAAC,EAAE,MAAM,CAAC;IAGnC,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,wEAAwE;IACxE,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,mFAAmF;IACnF,QAAQ,CAAC,EAAE;QACT,4EAA4E;QAC5E,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,iDAAiD;QACjD,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,8EAA8E;QAC9E,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,+EAA+E;QAC/E,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;CACH;AAED,qBAAa,YAAY;IACvB,wEAAwE;IACxE,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAC5B,4BAA4B;IAC5B,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,+CAA+C;IAC/C,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACvC,iEAAiE;IACjE,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC;IAGnC,qEAAqE;IACrE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,+DAA+D;IAC/D,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,6EAA6E;IAC7E,QAAQ,CAAC,aAAa,EAAE,gBAAgB,CAAC;IACzC,gEAAgE;IAChE,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IACjC,yDAAyD;IACzD,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,wDAAwD;IACxD,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,gFAAgF;IAChF,QAAQ,CAAC,YAAY,EAAE,eAAe,CAAC;IACvC,4DAA4D;IAC5D,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,kFAAkF;IAClF,QAAQ,CAAC,iBAAiB,EAAE,oBAAoB,CAAC;IACjD,iEAAiE;IACjE,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IAGzB,wEAAwE;IACxE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,uEAAuE;IACvE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,yEAAyE;IACzE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,4DAA4D;IAC5D,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,8CAA8C;IAC9C,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,4EAA4E;IAC5E,QAAQ,CAAC,YAAY,EAAE,eAAe,CAAC;IACvC,+DAA+D;IAC/D,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,gFAAgF;IAChF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IACjC,kEAAkE;IAClE,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,qDAAqD;IACrD,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;gBAEnB,MAAM,GAAE,kBAAuB;IAoF3C,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAIpC,0DAA0D;IAC1D,QAAQ,IAAI,MAAM,GAAG,IAAI;IAIzB;;;;;;;OAOG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW;IAIjC,gEAAgE;IAChE,KAAK,IAAI,IAAI;CAId;AAED,wBAAgB,kBAAkB,CAChC,MAAM,GAAE,kBAAuB,GAC9B,YAAY,CAEd"}
1
+ {"version":3,"file":"crowdy-client.d.ts","sourceRoot":"","sources":["../src/crowdy-client.ts"],"names":[],"mappings":"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"}
@@ -22,6 +22,7 @@
22
22
  */
23
23
  import { AuthState } from './auth-state.js';
24
24
  import { GraphQLClient } from './client.js';
25
+ import { LbCookieStore } from './lb-cookie-store.js';
25
26
  import { SubscriptionManager } from './subscriptions.js';
26
27
  import { WorldClient } from './world.js';
27
28
  import { AuthAPI } from './domains/auth.js';
@@ -55,16 +56,19 @@ import { GameModelAPI } from './domains/gameModel.js';
55
56
  export class CrowdyClient {
56
57
  constructor(config = {}) {
57
58
  this.session = new AuthState(config.tokenStore);
59
+ const lbCookieStore = config.lbCookieStore ?? new LbCookieStore();
58
60
  this.graphql = new GraphQLClient({
59
61
  httpUrl: config.httpUrl,
60
62
  graphqlEndpoint: config.graphqlEndpoint ?? toGraphqlEndpoint(config.httpUrl, 'graphql'),
61
63
  timeout: config.timeout,
62
64
  logger: config.logger,
65
+ lbCookieStore,
63
66
  }, this.session);
64
67
  this.realtime = new SubscriptionManager({
65
68
  wsUrl: config.wsUrl,
66
69
  wsEndpoint: config.wsEndpoint ?? toGraphqlEndpoint(config.wsUrl, 'graphql'),
67
70
  logger: config.logger,
71
+ lbCookieStore,
68
72
  ...config.realtime,
69
73
  }, this.session);
70
74
  const managementGraphqlEndpoint = config.managementGraphqlEndpoint ??
@@ -1,163 +1,100 @@
1
1
  import type { GraphQLClient } from '../client.js';
2
2
  import type { AuthState } from '../auth-state.js';
3
- import { type LoginMutation, type LoginUserInput, type RegisterMutation, type RegisterUserInput, type ResetPasswordInput } from '../generated/graphql.js';
4
3
  /**
5
- * Authentication and account-lifecycle flows — exposed as `client.auth`.
4
+ * Authentication and account lifecycle — exposed as `client.auth`.
6
5
  *
7
- * Targets the **management-api**: every call routes to `managementUrl` (falling
8
- * back to the game-api endpoint only in legacy single-endpoint mode). The
9
- * management API owns the `game_tokens` table that backs every login / register
10
- * / password / email-confirmation flow; the `token` it returns is a
11
- * `game_tokens` row that game-api validates against the same shared Postgres.
6
+ * Crowded Kingdoms is **passwordless**. There is no email+password login: a user
7
+ * authenticates with an emailed magic link, a federated social provider (OIDC),
8
+ * or in development only — the dev bypass. Every path returns an identity
9
+ * SESSION token (management-plane), which is stored on the shared session state
10
+ * automatically. Gameplay tokens are minted separately via `client.portal`.
12
11
  *
13
- * {@link login} and {@link register} mint that session token **and** store it on
14
- * the shared session state automatically, so every later call on *either*
15
- * endpoint (auth, users, apps, actors, chunks, udp, ...) is authenticated
16
- * without you threading the token through by hand. Use {@link setToken} to
17
- * rehydrate a saved token and {@link getToken} to read the current one. `BigInt`
18
- * ids on the returned user (e.g. `userId`, `orgId`) are decimal strings.
12
+ * Targets the **management-api** (`managementUrl`).
19
13
  *
20
- * **Public no session required:** {@link login}, {@link register},
21
- * {@link confirmEmail}, {@link requestPasswordReset}, {@link resetPassword}, and
22
- * {@link resendConfirmationEmail}. **Require a valid session:** {@link logout},
23
- * {@link logoutAllDevices}, and {@link changePassword}, which otherwise throw
24
- * {@link CrowdyGraphQLError} with `UNAUTHENTICATED` when the bearer token is
25
- * missing, expired, or revoked.
14
+ * **Public (no session):** {@link requestLoginLink}, {@link completeLoginLink},
15
+ * {@link socialLoginStart}, {@link socialLoginComplete}, {@link devLogin},
16
+ * {@link availableLoginProviders}. **Require a session:** {@link logout},
17
+ * {@link logoutAllDevices}, {@link myIdentities}, {@link linkIdentity},
18
+ * {@link unlinkIdentity}.
26
19
  */
20
+ export interface AuthUser {
21
+ userId: string;
22
+ email?: string | null;
23
+ gamertag?: string | null;
24
+ }
25
+ export interface AuthResponse {
26
+ /** Identity session token; stored on the session state automatically. */
27
+ token: string;
28
+ gameTokenId: string;
29
+ user: AuthUser;
30
+ }
31
+ export interface UserIdentity {
32
+ identityId: string;
33
+ provider: string;
34
+ subject: string;
35
+ email: string | null;
36
+ emailVerified: boolean;
37
+ createdAt: string;
38
+ lastLoginAt: string | null;
39
+ }
27
40
  export declare class AuthAPI {
28
41
  private readonly graphql;
29
42
  private readonly session;
30
43
  constructor(graphql: GraphQLClient, session: AuthState);
44
+ /** The federated sign-in providers currently enabled (e.g. `['google']`). */
45
+ availableLoginProviders(): Promise<string[]>;
31
46
  /**
32
- * Authenticate with email + password and start a new session. **Public** — no
33
- * existing session required.
34
- *
35
- * On success the returned `token` is minted **and** stored on the shared
36
- * session state, so subsequent calls on any sub-client (management-api or
37
- * game-api) carry it automatically — no need to call {@link setToken}.
38
- *
39
- * @param input - Credentials ({@link LoginUserInput}): `email` and `password`
40
- * (min 8 characters).
41
- * @returns An {@link AuthResponse}: the opaque session `token` (sent as
42
- * `Authorization: Bearer <token>`), `gameTokenId` (the session row id, a
43
- * string), and the authenticated `user`.
44
- * @throws {CrowdyGraphQLError} `UNAUTHENTICATED` on invalid credentials, or
45
- * `BAD_USER_INPUT` on malformed input.
46
- * @example
47
- * ```ts
48
- * const { user } = await client.auth.login({ email, password });
49
- * // the session token is now stored; later calls are authenticated for you
50
- * await client.users.me();
51
- * ```
47
+ * Passwordless: email the address a one-time magic sign-in link (creating the
48
+ * account on first sign-in). Always resolves `sent: true` (no enumeration). In
49
+ * development (`DEV_AUTH_BYPASS`) the response also carries `devToken`, the
50
+ * token to pass straight to {@link completeLoginLink} without an inbox.
52
51
  */
53
- login(input: LoginUserInput): Promise<LoginMutation['login']>;
52
+ requestLoginLink(input: {
53
+ email: string;
54
+ redirectUri?: string;
55
+ }): Promise<{
56
+ sent: boolean;
57
+ devToken: string | null;
58
+ }>;
59
+ /** Complete a magic-link sign-in; stores the session token on success. */
60
+ completeLoginLink(token: string): Promise<AuthResponse>;
54
61
  /**
55
- * Create a new (initially unconfirmed) account, send a confirmation email, and
56
- * return a session for immediate login. **Public** no existing session
57
- * required. Same token-persistence behaviour as {@link login}: the new `token`
58
- * is stored on the shared session state automatically.
59
- *
60
- * @param input - New-account details ({@link RegisterUserInput}): `email`
61
- * (where the confirmation email is sent), `password` (min 8 characters), and
62
- * an optional initial `gamertag` (min 3 characters; can also be set later via
63
- * `client.users.updateGamertag`).
64
- * @returns An {@link AuthResponse} (session `token`, `gameTokenId`, and the new
65
- * `user`).
66
- * @throws {CrowdyGraphQLError} `BAD_USER_INPUT` if the email already exists or
67
- * the input is invalid.
62
+ * Begin a federated (social) sign-in. Returns an `authorizeUrl` to redirect the
63
+ * user to and an opaque `state` to round-trip back to {@link socialLoginComplete}.
68
64
  */
69
- register(input: RegisterUserInput): Promise<RegisterMutation['register']>;
65
+ socialLoginStart(provider: string, redirectUri: string): Promise<{
66
+ authorizeUrl: string;
67
+ state: string;
68
+ }>;
69
+ /** Complete a federated sign-in from the provider callback; stores the token. */
70
+ socialLoginComplete(input: {
71
+ provider: string;
72
+ code: string;
73
+ state: string;
74
+ }): Promise<AuthResponse>;
70
75
  /**
71
- * Single-device logout: revoke the `game_tokens` row that authenticated this
72
- * request; other devices/tokens are unaffected. After a successful server-side
73
- * revoke the in-memory token is cleared from the shared session state so the
74
- * other sub-clients stop using it. Requires a valid session.
75
- *
76
- * @returns `true` if a token was revoked, or `false` if the request carried no
77
- * game token.
78
- * @throws {CrowdyGraphQLError} `UNAUTHENTICATED` if the session is invalid.
76
+ * DEV ONLY bypass sign-in (active only when the server has `DEV_AUTH_BYPASS`).
77
+ * Returns a session for `email` without email/social verification; stores it.
78
+ * Throws `FORBIDDEN` when the bypass is disabled (e.g. production).
79
79
  */
80
+ devLogin(email: string): Promise<AuthResponse>;
81
+ /** The signed-in user's linked sign-in identities. Requires a session. */
82
+ myIdentities(): Promise<UserIdentity[]>;
83
+ /** Link an additional federated identity (from a social callback). */
84
+ linkIdentity(input: {
85
+ provider: string;
86
+ code: string;
87
+ state: string;
88
+ }): Promise<UserIdentity>;
89
+ /** Unlink a federated identity (cannot remove the last sign-in method). */
90
+ unlinkIdentity(identityId: string): Promise<boolean>;
91
+ /** Single-device logout; clears the in-memory token on success. */
80
92
  logout(): Promise<boolean>;
81
- /**
82
- * Revoke **every** active session for the authenticated user (deletes all
83
- * their `game_tokens` rows and records revocations). Requires a valid session;
84
- * use {@link logout} to end only the current one.
85
- *
86
- * Note: unlike {@link logout}, this does not clear the SDK's in-memory token —
87
- * call {@link setToken}`(null)` afterwards if you also want to drop it locally.
88
- *
89
- * @returns `true` on success.
90
- * @throws {CrowdyGraphQLError} `UNAUTHENTICATED` if the session is invalid.
91
- */
93
+ /** Revoke every active session for the user. Requires a session. */
92
94
  logoutAllDevices(): Promise<boolean>;
93
- /**
94
- * Confirm a user's email address using the token from the confirmation email.
95
- * **Public** — the token itself authorizes the call.
96
- *
97
- * @param token - The confirmation token from the emailed link.
98
- * @returns `true` on success, or `false` if the token is invalid or expired.
99
- * @throws {CrowdyGraphQLError} on transport/validation failures (invalid or
100
- * expired tokens resolve to `false` rather than throwing).
101
- */
102
- confirmEmail(token: string): Promise<boolean>;
103
- /**
104
- * Start the password-reset flow by emailing a reset link to the address.
105
- * **Public**. Always returns `true` regardless of whether the email exists or
106
- * is confirmed, to prevent account enumeration.
107
- *
108
- * @param email - Email address to send the password-reset link to.
109
- * @returns `true` (always, even when no such account exists).
110
- * @throws {CrowdyGraphQLError} on transport/validation failures.
111
- */
112
- requestPasswordReset(email: string): Promise<boolean>;
113
- /**
114
- * Complete a password reset using the reset token and a new password.
115
- * **Public** — the reset token authorizes the call. Existing sessions are
116
- * **not** revoked.
117
- *
118
- * @param input - {@link ResetPasswordInput}: the `token` from the emailed reset
119
- * link and the `newPassword` to set (min 8 characters).
120
- * @returns `true` on success.
121
- * @throws {CrowdyGraphQLError} `BAD_USER_INPUT` if the token is invalid or
122
- * expired.
123
- */
124
- resetPassword(input: ResetPasswordInput): Promise<boolean>;
125
- /**
126
- * Re-send the email-confirmation link. **Public**. Always returns `true`
127
- * regardless of whether the account exists or is already confirmed (prevents
128
- * enumeration); the email is only actually sent for existing unconfirmed
129
- * accounts.
130
- *
131
- * @param email - Email address of the account to re-send confirmation to.
132
- * @returns `true` (always).
133
- * @throws {CrowdyGraphQLError} on transport/validation failures.
134
- */
135
- resendConfirmationEmail(email: string): Promise<boolean>;
136
- /**
137
- * Change the authenticated user's password after verifying the current one.
138
- * Requires a valid session. Existing sessions are **not** revoked.
139
- *
140
- * @param currentPassword - The user's current password, for verification.
141
- * @param newPassword - The new password to set (min 8 characters).
142
- * @returns `true` on success.
143
- * @throws {CrowdyGraphQLError} `UNAUTHENTICATED` without a valid session, or
144
- * `BAD_USER_INPUT` if the current password is wrong.
145
- */
146
- changePassword(currentPassword: string, newPassword: string): Promise<boolean>;
147
- /**
148
- * Imperatively replace the in-memory bearer token on the shared session state
149
- * (e.g. to rehydrate a token persisted to disk). Affects every sub-client.
150
- * Local only — performs no network call. Pass `null` to clear it.
151
- *
152
- * @param token - The bearer token to use, or `null` to clear the session.
153
- */
95
+ /** Imperatively set the in-memory bearer token (e.g. rehydrate). */
154
96
  setToken(token: string | null): void;
155
- /**
156
- * Read the current in-memory bearer token from the shared session state. Local
157
- * only — performs no network call.
158
- *
159
- * @returns The current bearer token, or `null` if none is set.
160
- */
97
+ /** Read the current in-memory bearer token. */
161
98
  getToken(): string | null;
162
99
  }
163
100
  //# sourceMappingURL=auth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/domains/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAUL,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACxB,MAAM,yBAAyB,CAAC;AAEjC;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,OAAO;IAEhB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBADP,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,SAAS;IAGrC;;;;;;;;;;;;;;;;;;;;;OAqBG;IACG,KAAK,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAQnE;;;;;;;;;;;;;;OAcG;IACG,QAAQ,CACZ,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAQxC;;;;;;;;;OASG;IACG,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAMhC;;;;;;;;;;OAUG;IACG,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC;IAK1C;;;;;;;;OAQG;IACG,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKnD;;;;;;;;OAQG;IACG,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAO3D;;;;;;;;;;OAUG;IACG,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC;IAOhE;;;;;;;;;OASG;IACG,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAO9D;;;;;;;;;OASG;IACG,cAAc,CAClB,eAAe,EAAE,MAAM,EACvB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,OAAO,CAAC;IAQnB;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAIpC;;;;;OAKG;IACH,QAAQ,IAAI,MAAM,GAAG,IAAI;CAG1B"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/domains/auth.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAGlD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,yEAAyE;IACzE,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AA+DD,qBAAa,OAAO;IAEhB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBADP,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,SAAS;IAGrC,6EAA6E;IACvE,uBAAuB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAKlD;;;;;OAKG;IACG,gBAAgB,CAAC,KAAK,EAAE;QAC5B,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAKvD,0EAA0E;IACpE,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAS7D;;;OAGG;IACG,gBAAgB,CACpB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAOnD,iFAAiF;IAC3E,mBAAmB,CAAC,KAAK,EAAE;QAC/B,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;KACf,GAAG,OAAO,CAAC,YAAY,CAAC;IASzB;;;;OAIG;IACG,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAQpD,0EAA0E;IACpE,YAAY,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IAK7C,sEAAsE;IAChE,YAAY,CAAC,KAAK,EAAE;QACxB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;KACf,GAAG,OAAO,CAAC,YAAY,CAAC;IAKzB,2EAA2E;IACrE,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAO1D,mEAAmE;IAC7D,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAMhC,oEAAoE;IAC9D,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC;IAK1C,oEAAoE;IACpE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAIpC,+CAA+C;IAC/C,QAAQ,IAAI,MAAM,GAAG,IAAI;CAG1B"}