@crowdedkingdoms/crowdyjs 17.1.0-test.1 → 17.2.0-dev.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/MIGRATION.md +29 -0
- package/README.md +46 -0
- package/dist/crowdy-client.d.ts +20 -0
- package/dist/crowdy-client.d.ts.map +1 -1
- package/dist/crowdy-client.js +9 -1
- package/dist/default-origin.d.ts +6 -6
- package/dist/default-origin.d.ts.map +1 -1
- package/dist/default-origin.js +6 -6
- package/dist/domains/embedded-host.d.ts +126 -0
- package/dist/domains/embedded-host.d.ts.map +1 -0
- package/dist/domains/embedded-host.js +175 -0
- package/dist/domains/hosting.d.ts +75 -0
- package/dist/domains/hosting.d.ts.map +1 -0
- package/dist/domains/hosting.js +136 -0
- package/dist/domains/portal.d.ts +23 -2
- package/dist/domains/portal.d.ts.map +1 -1
- package/dist/domains/portal.js +28 -4
- package/dist/generated/graphql.d.ts +512 -0
- package/dist/generated/graphql.d.ts.map +1 -1
- package/dist/generated/graphql.js +30 -0
- package/dist/hosting/index.d.ts +8 -0
- package/dist/hosting/index.d.ts.map +1 -0
- package/dist/hosting/index.js +6 -0
- package/dist/hosting/publish-directory.d.ts +33 -0
- package/dist/hosting/publish-directory.d.ts.map +1 -0
- package/dist/hosting/publish-directory.js +65 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/kit/npcs.d.ts.map +1 -1
- package/dist/kit/social.d.ts.map +1 -1
- package/package.json +5 -1
package/MIGRATION.md
CHANGED
|
@@ -1,3 +1,32 @@
|
|
|
1
|
+
# CrowdyJS v17.2 — publish to Crowdy Games; sign-in under the shell
|
|
2
|
+
|
|
3
|
+
**Additive.** `17.2.0` (2026-09-14). Tracks ck-api `v2.1.0` (third-party game
|
|
4
|
+
hosting). Nothing existing changes shape; two things are new.
|
|
5
|
+
|
|
6
|
+
- **`client.hosting`** wraps the hosting surface: `claim({ appId, slug? })`,
|
|
7
|
+
`beginPublish({ slug, files })`, `completePublish(slug, publishId)`,
|
|
8
|
+
`abandonPublish`, `setEnabled`, `publishes`, `mine`; public `game(slug)` and
|
|
9
|
+
`listed()`; operator `all()`, `setListing`, `takeDown`. Every mutation needs an
|
|
10
|
+
identity session with `manage_apps` (a game's own app token is refused, so a
|
|
11
|
+
bundle can never publish a replacement for itself). The new subpath
|
|
12
|
+
`@crowdedkingdoms/crowdyjs/hosting` exports `publishDirectory(client, { dir,
|
|
13
|
+
slug })` and `manifestForDirectory(dir)` for Node; the root exports
|
|
14
|
+
`uploadPublishFiles` for a browser tool.
|
|
15
|
+
- **`EmbeddedHost`** (`client.embeddedHost`, `CrowdyClientConfig.embeddedHost`):
|
|
16
|
+
when a game published to Crowdy Games runs inside the first-party shell's
|
|
17
|
+
iframe, `portal.signIn` learns the shell's return URL and Studio origin from a
|
|
18
|
+
`crowdyjs:host-hello`, uses the shell's page as `redirect_uri`, and asks the
|
|
19
|
+
shell to navigate (`crowdyjs:navigate`) instead of `location.assign`. The PKCE
|
|
20
|
+
verifier stays in the game origin; `handleSignInCallback` is unchanged because
|
|
21
|
+
the shell relays `?code=&state=` into the iframe's `src`. Detection is a bounded
|
|
22
|
+
hello (1.5 s) and falls back to the ordinary flow, so a self-hosted or
|
|
23
|
+
top-level game behaves exactly as before. `SignInParams.embedded: false` or
|
|
24
|
+
`createCrowdyClient({ embeddedHost: false })` opts out. `portal.embeddedHostInfo()`
|
|
25
|
+
tells a game whether it is under a shell.
|
|
26
|
+
|
|
27
|
+
No removals. Error codes added: `CONTENT_HOSTING_DISABLED`,
|
|
28
|
+
`HOSTED_SLUG_UNAVAILABLE`, `HOSTED_MANIFEST_INVALID`, `HOSTED_PUBLISH_INCOMPLETE`,
|
|
29
|
+
`HOSTED_GAME_TAKEN_DOWN`.
|
|
1
30
|
# CrowdyJS v17.1 — binary-relay sends are bundled
|
|
2
31
|
|
|
3
32
|
**Nothing removed.** `17.1.0` (2026-09-13). On the binary relay
|
package/README.md
CHANGED
|
@@ -98,6 +98,19 @@ sign-in mutations are refused from a non-first-party browser origin with
|
|
|
98
98
|
customer's domain that collects it is indistinguishable, to the platform and to
|
|
99
99
|
the player, from a phishing page.
|
|
100
100
|
|
|
101
|
+
**A game published to Crowdy Games takes the first row too, with one twist the SDK
|
|
102
|
+
handles for you** (17.2.0). Such a game is reached at `https://<games host>/<slug>/`,
|
|
103
|
+
which is a first-party *shell* page, and runs inside that page's iframe on its own
|
|
104
|
+
origin, `https://<slug>.<content host>`. The iframe cannot navigate the tab and
|
|
105
|
+
Studio refuses to be framed, so `portal.signIn` asks the shell to navigate
|
|
106
|
+
(`crowdyjs:navigate`; the shell honours exactly the tier's Studio `/authorize`) and
|
|
107
|
+
uses the shell's page as the `redirect_uri` -- the shell then hands the returned
|
|
108
|
+
`?code=&state=` into the iframe, where `portal.handleSignInCallback` runs exactly as
|
|
109
|
+
it does self-hosted. Nothing changes in your code: the bridge (`client.embeddedHost`,
|
|
110
|
+
`EmbeddedHost`) detects the shell with a bounded hello and falls back to the
|
|
111
|
+
top-level flow when nobody answers. Pass `embeddedHost: false` to `createCrowdyClient`
|
|
112
|
+
to never consult a framing page.
|
|
113
|
+
|
|
101
114
|
**Hosted sign-in** (browser game, own domain) is OAuth2 Authorization Code +
|
|
102
115
|
PKCE; the verifier never leaves your origin and your page never sees a
|
|
103
116
|
credential:
|
|
@@ -208,6 +221,7 @@ never told about, so a native refresh without it is a re-placement.
|
|
|
208
221
|
| `client.users` | `me`, `updateGamertag`, profile reads. |
|
|
209
222
|
| `client.session` | Token store, `restore()`, `getToken()`, manual `setToken()`. |
|
|
210
223
|
| `client.portal` | App-scoped token minting (`mintAppToken`) and the cross-origin PKCE entry flow (`beginEntry` / `handleAuthorizeRequest` / `completeEntry` / `refresh`). |
|
|
224
|
+
| `client.hosting` | Third-party hosting on Crowdy Games (17.2.0): `claim` a slug for an app, `beginPublish` / `completePublish` / `abandonPublish` a built bundle, `setEnabled`; public `game(slug)` / `listed()`; operator `all` / `setListing` / `takeDown`. Mutations need an identity session with `manage_apps`. `@crowdedkingdoms/crowdyjs/hosting` exports `publishDirectory(client, { dir, slug })`, the Node helper that does the whole publish for a `dist/`. |
|
|
211
225
|
| `client.platform` | Public platform configuration (`config()`). |
|
|
212
226
|
| `client.serverStatus` | `gameClientBootstrap(appId)` — per-app version info, UDP status, spatial limits. |
|
|
213
227
|
| `client.chunks`, `client.voxels`, `client.actors`, `client.avatars`, `client.state` | World data reads + writes: terrain/LODs, voxel edit + history/rollback, durable actors, avatars, per-user app state blobs. |
|
|
@@ -634,6 +648,38 @@ See the docs guides [Modeling game concepts](https://docs.crowdedkingdoms.com/ga
|
|
|
634
648
|
(the SDK surface + the simulation-tier / notify-to-pull / timer / hidden-info
|
|
635
649
|
/ anti-cheat patterns).
|
|
636
650
|
|
|
651
|
+
## Hosting a game on Crowdy Games
|
|
652
|
+
|
|
653
|
+
Since 17.2.0 (ck-api v2.1) a developer can publish a built static bundle to the
|
|
654
|
+
platform instead of hosting it: players reach it at
|
|
655
|
+
`https://<games host>/<slug>/` and it executes on an origin of its own,
|
|
656
|
+
`https://<slug>.<content host>`, behind the same security headers `the-construct`'s
|
|
657
|
+
`docs/HOSTING.md` asks a self-hoster to serve. The API returns both URLs
|
|
658
|
+
(`HostedGame.launchUrl`, `.contentOrigin`); nothing in your code names a host.
|
|
659
|
+
|
|
660
|
+
From Node, with an identity session (never from a browser page, by design):
|
|
661
|
+
|
|
662
|
+
```ts
|
|
663
|
+
import { createCrowdyClient } from '@crowdedkingdoms/crowdyjs';
|
|
664
|
+
import { publishDirectory } from '@crowdedkingdoms/crowdyjs/hosting';
|
|
665
|
+
|
|
666
|
+
const client = createCrowdyClient();
|
|
667
|
+
await client.auth.login({ email, password }); // identity session, Node only
|
|
668
|
+
const game = await client.hosting.claim({ appId, slug: 'my-game' }); // once; idempotent
|
|
669
|
+
const result = await publishDirectory(client, { dir: 'dist', slug: game.slug });
|
|
670
|
+
console.log(result.game.launchUrl); // https://.../my-game/
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
`claim` registers the shell page and the game origin as the app's redirect URIs
|
|
674
|
+
and sets `launch_url`; `publishDirectory` hashes `dist/`, declares the manifest
|
|
675
|
+
(`beginGamePublish` validates it as a whole and returns one presigned PUT per file),
|
|
676
|
+
uploads with the exact signed headers, and `completeGamePublish` verifies every
|
|
677
|
+
object, promotes it and invalidates the CDN. The slug is a DNS label, global on the
|
|
678
|
+
tier, and first-party names are reserved (`HOSTED_SLUG_UNAVAILABLE`); a tier without
|
|
679
|
+
a content CDN answers `CONTENT_HOSTING_DISABLED`. Being *listed* in the lobby is an
|
|
680
|
+
operator decision (`setListing`); publishing is self-serve. `the-construct`'s
|
|
681
|
+
`npm run publish` is this section as a command.
|
|
682
|
+
|
|
637
683
|
## Crowdy Studio
|
|
638
684
|
|
|
639
685
|
Crowdy Studio is the in-game SERVER/CLIENT Rust authoring surface for player
|
package/dist/crowdy-client.d.ts
CHANGED
|
@@ -32,6 +32,8 @@ import { GameKitClient, type GameKitOptions } from './kit/index.js';
|
|
|
32
32
|
import { AuthAPI } from './domains/auth.js';
|
|
33
33
|
import { UsersAPI } from './domains/users.js';
|
|
34
34
|
import { AppsAPI } from './domains/apps.js';
|
|
35
|
+
import { EmbeddedHost } from './domains/embedded-host.js';
|
|
36
|
+
import { HostingAPI } from './domains/hosting.js';
|
|
35
37
|
import { PortalAPI, type AppTokenResponse, type PkceStore } from './domains/portal.js';
|
|
36
38
|
import { PlatformAPI } from './domains/platform.js';
|
|
37
39
|
import { OrganizationsAPI } from './domains/organizations.js';
|
|
@@ -99,6 +101,15 @@ export interface CrowdyClientConfig {
|
|
|
99
101
|
* or tests where sessionStorage is unavailable.
|
|
100
102
|
*/
|
|
101
103
|
pkceStore?: PkceStore;
|
|
104
|
+
/**
|
|
105
|
+
* The Crowdy Games shell bridge (third-party hosting, 2026-09-13). When a game
|
|
106
|
+
* published to Crowdy Games runs inside the first-party shell's iframe,
|
|
107
|
+
* `portal.signIn` must ask the shell to navigate to Studio and must use the shell's
|
|
108
|
+
* page as the redirect URI; this bridge is how it learns both. Default: detect in a
|
|
109
|
+
* browser (`new EmbeddedHost()`), nothing in Node. Pass `false` to never consult a
|
|
110
|
+
* framing page, or your own instance to control timeouts.
|
|
111
|
+
*/
|
|
112
|
+
embeddedHost?: EmbeddedHost | false;
|
|
102
113
|
/** Realtime (WebSocket) tuning for reconnect backoff and `...AndWait` timeouts. */
|
|
103
114
|
realtime?: {
|
|
104
115
|
/** Max reconnect attempts before giving up (default tuned for browsers). */
|
|
@@ -203,6 +214,15 @@ export declare class CrowdyClient {
|
|
|
203
214
|
* app token.
|
|
204
215
|
*/
|
|
205
216
|
readonly portal: PortalAPI;
|
|
217
|
+
/**
|
|
218
|
+
* Third-party game hosting on Crowdy Games: claim a slug, publish a bundle, list
|
|
219
|
+
* hosted games. Mutations need an identity session with manage_apps; the reads a
|
|
220
|
+
* page needs are public. `@crowdedkingdoms/crowdyjs/hosting` has the Node helper
|
|
221
|
+
* that publishes a directory.
|
|
222
|
+
*/
|
|
223
|
+
readonly hosting: HostingAPI;
|
|
224
|
+
/** The Crowdy Games shell bridge (see `CrowdyClientConfig.embeddedHost`); null in Node or when opted out. */
|
|
225
|
+
readonly embeddedHost: EmbeddedHost | null;
|
|
206
226
|
/**
|
|
207
227
|
* Where each app lives. Unauthenticated, and meant to be called BEFORE login against
|
|
208
228
|
* the shared origin, so the session and the app token are both written in the app's
|
|
@@ -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;AAK5C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,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;AAE/C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEpE,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,EACL,SAAS,EACT,KAAK,gBAAgB,EACrB,KAAK,SAAS,EACf,MAAM,qBAAqB,CAAC;AAC7B,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,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;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAC;AAClF,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,MAAM,WAAW,kBAAkB;IAEjC;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mDAAmD;IACnD,UAAU,CAAC,EAAE,MAAM,CAAC;IAGpB,gDAAgD;IAChD,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;QACvB;;;WAGG;QACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;QAC5B;;;;;;;WAOG;QACH,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B;;;WAGG;QACH,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB;;;;;;;;;;;;;;;;;;;;WAoBG;QACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,OAAO,CAAC;YAC7C,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;YACxB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;SACvB,GAAG,IAAI,CAAC,CAAC;QACV;;;;;;;;;WASG;QACH,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,iEAAiE;QACjE,uBAAuB,CAAC,EAAE,MAAM,CAAC;KAClC,CAAC;IACF;;;;OAIG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,oBAAoB,CAA0C;IAEtE,8DAA8D;IAC9D,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAC5B,+BAA+B;IAC/B,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,+CAA+C;IAC/C,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACvC;;;;;;;OAOG;IACH,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAGlC,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;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC,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,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,8EAA8E;IAC9E,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,aAAa,EAAE,gBAAgB,CAAC;IACzC,wEAAwE;IACxE,QAAQ,CAAC,YAAY,EAAE,eAAe,CAAC;IACvC,iHAAiH;IACjH,QAAQ,CAAC,kBAAkB,EAAE,2BAA2B,CAAC;IAEzD,0EAA0E;IAC1E,QAAQ,CAAC,WAAW,EAAE,cAAc,CAAC;IACrC,+EAA+E;IAC/E,QAAQ,CAAC,YAAY,EAAE,eAAe,CAAC;IACvC,sEAAsE;IACtE,QAAQ,CAAC,WAAW,EAAE,cAAc,CAAC;IACrC,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;
|
|
1
|
+
{"version":3,"file":"crowdy-client.d.ts","sourceRoot":"","sources":["../src/crowdy-client.ts"],"names":[],"mappings":"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"}
|
package/dist/crowdy-client.js
CHANGED
|
@@ -33,6 +33,8 @@ import { GameKitClient } from './kit/index.js';
|
|
|
33
33
|
import { AuthAPI } from './domains/auth.js';
|
|
34
34
|
import { UsersAPI } from './domains/users.js';
|
|
35
35
|
import { AppsAPI } from './domains/apps.js';
|
|
36
|
+
import { EmbeddedHost } from './domains/embedded-host.js';
|
|
37
|
+
import { HostingAPI } from './domains/hosting.js';
|
|
36
38
|
import { PortalAPI, } from './domains/portal.js';
|
|
37
39
|
import { PlatformAPI } from './domains/platform.js';
|
|
38
40
|
import { OrganizationsAPI } from './domains/organizations.js';
|
|
@@ -184,7 +186,12 @@ export class CrowdyClient {
|
|
|
184
186
|
this.auth = new AuthAPI(this.graphql, this.session);
|
|
185
187
|
this.users = new UsersAPI(this.graphql);
|
|
186
188
|
this.apps = new AppsAPI(this.graphql);
|
|
187
|
-
this.
|
|
189
|
+
this.embeddedHost =
|
|
190
|
+
config.embeddedHost === false
|
|
191
|
+
? null
|
|
192
|
+
: config.embeddedHost ?? (typeof globalThis.window !== 'undefined' ? new EmbeddedHost() : null);
|
|
193
|
+
this.portal = new PortalAPI(this.graphql, this.session, config.pkceStore, this.embeddedHost);
|
|
194
|
+
this.hosting = new HostingAPI(this.graphql);
|
|
188
195
|
this.discovery = new DiscoveryDomain(this.graphql);
|
|
189
196
|
this.platform = new PlatformAPI(this.graphql);
|
|
190
197
|
this.organizations = new OrganizationsAPI(this.graphql);
|
|
@@ -343,6 +350,7 @@ export class CrowdyClient {
|
|
|
343
350
|
close() {
|
|
344
351
|
this.realtime.close();
|
|
345
352
|
this.session.setToken(null);
|
|
353
|
+
this.embeddedHost?.close();
|
|
346
354
|
}
|
|
347
355
|
/** The configured or discovered GraphQL endpoint URL. */
|
|
348
356
|
get graphqlEndpoint() {
|
package/dist/default-origin.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* GENERATED — do not edit. The operator tooling's
|
|
3
|
-
* `sync-client-origins.mjs --write --tier
|
|
3
|
+
* `sync-client-origins.mjs --write --tier dev` writes this file, and
|
|
4
4
|
* `check-sdk-default-origin.mjs` refuses it when it names the wrong tier or a
|
|
5
5
|
* host that declaration does not carry. Regenerate; never hand-edit.
|
|
6
6
|
*
|
|
@@ -10,14 +10,14 @@
|
|
|
10
10
|
* than no default at all. Every fallback this SDK ever removed named a host that
|
|
11
11
|
* was already dead. A generated file plus a gate is what makes this one different.
|
|
12
12
|
*
|
|
13
|
-
* Source: the operator's per-tier public CK API origin declaration, tier '
|
|
13
|
+
* Source: the operator's per-tier public CK API origin declaration, tier 'dev'
|
|
14
14
|
*/
|
|
15
15
|
/** The tier this build of the SDK is published for. */
|
|
16
|
-
export declare const CROWDY_DEFAULT_TIER = "
|
|
16
|
+
export declare const CROWDY_DEFAULT_TIER = "dev";
|
|
17
17
|
/** The public CK API origin for that tier. */
|
|
18
|
-
export declare const CROWDY_DEFAULT_HTTP_ORIGIN = "https://ck.
|
|
18
|
+
export declare const CROWDY_DEFAULT_HTTP_ORIGIN = "https://ck.dev.crowdedkingdoms.com";
|
|
19
19
|
/** The same host over WebSocket. A scheme is composed; a hostname is looked up. */
|
|
20
|
-
export declare const CROWDY_DEFAULT_WS_ORIGIN = "wss://ck.
|
|
20
|
+
export declare const CROWDY_DEFAULT_WS_ORIGIN = "wss://ck.dev.crowdedkingdoms.com";
|
|
21
21
|
/** The bare hostname, for callers that need to compare rather than dial. */
|
|
22
|
-
export declare const CROWDY_DEFAULT_HOST = "ck.
|
|
22
|
+
export declare const CROWDY_DEFAULT_HOST = "ck.dev.crowdedkingdoms.com";
|
|
23
23
|
//# sourceMappingURL=default-origin.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"default-origin.d.ts","sourceRoot":"","sources":["../src/default-origin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,uDAAuD;AACvD,eAAO,MAAM,mBAAmB,
|
|
1
|
+
{"version":3,"file":"default-origin.d.ts","sourceRoot":"","sources":["../src/default-origin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,uDAAuD;AACvD,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AAEzC,8CAA8C;AAC9C,eAAO,MAAM,0BAA0B,uCAAuC,CAAC;AAE/E,mFAAmF;AACnF,eAAO,MAAM,wBAAwB,qCAAqC,CAAC;AAE3E,4EAA4E;AAC5E,eAAO,MAAM,mBAAmB,+BAA+B,CAAC"}
|
package/dist/default-origin.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* GENERATED — do not edit. The operator tooling's
|
|
3
|
-
* `sync-client-origins.mjs --write --tier
|
|
3
|
+
* `sync-client-origins.mjs --write --tier dev` writes this file, and
|
|
4
4
|
* `check-sdk-default-origin.mjs` refuses it when it names the wrong tier or a
|
|
5
5
|
* host that declaration does not carry. Regenerate; never hand-edit.
|
|
6
6
|
*
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
* than no default at all. Every fallback this SDK ever removed named a host that
|
|
11
11
|
* was already dead. A generated file plus a gate is what makes this one different.
|
|
12
12
|
*
|
|
13
|
-
* Source: the operator's per-tier public CK API origin declaration, tier '
|
|
13
|
+
* Source: the operator's per-tier public CK API origin declaration, tier 'dev'
|
|
14
14
|
*/
|
|
15
15
|
/** The tier this build of the SDK is published for. */
|
|
16
|
-
export const CROWDY_DEFAULT_TIER = '
|
|
16
|
+
export const CROWDY_DEFAULT_TIER = 'dev';
|
|
17
17
|
/** The public CK API origin for that tier. */
|
|
18
|
-
export const CROWDY_DEFAULT_HTTP_ORIGIN = 'https://ck.
|
|
18
|
+
export const CROWDY_DEFAULT_HTTP_ORIGIN = 'https://ck.dev.crowdedkingdoms.com';
|
|
19
19
|
/** The same host over WebSocket. A scheme is composed; a hostname is looked up. */
|
|
20
|
-
export const CROWDY_DEFAULT_WS_ORIGIN = 'wss://ck.
|
|
20
|
+
export const CROWDY_DEFAULT_WS_ORIGIN = 'wss://ck.dev.crowdedkingdoms.com';
|
|
21
21
|
/** The bare hostname, for callers that need to compare rather than dial. */
|
|
22
|
-
export const CROWDY_DEFAULT_HOST = 'ck.
|
|
22
|
+
export const CROWDY_DEFAULT_HOST = 'ck.dev.crowdedkingdoms.com';
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The embedded-host bridge: how a game framed by the Crowdy Games SHELL signs in.
|
|
3
|
+
*
|
|
4
|
+
* A game published to Crowdy Games (`client.hosting`, the-construct's `npm run
|
|
5
|
+
* publish`) is reached at `https://<games host>/<slug>/`, which is a first-party
|
|
6
|
+
* shell page, and executes inside that page's iframe on its own origin,
|
|
7
|
+
* `https://<slug>.<content host>`. Two things about that arrangement change hosted
|
|
8
|
+
* sign-in, and this module is the whole of the change:
|
|
9
|
+
*
|
|
10
|
+
* 1. The game cannot navigate the tab. Its iframe has no `allow-top-navigation`
|
|
11
|
+
* (a game that could send the player to a lookalike sign-in page would have the
|
|
12
|
+
* phishing surface the shell exists to remove), and Studio refuses to be framed.
|
|
13
|
+
* So `portal.signIn` asks the SHELL to navigate -- `crowdyjs:navigate` -- and
|
|
14
|
+
* the shell honours exactly one destination: the tier's Studio `/authorize`.
|
|
15
|
+
*
|
|
16
|
+
* 2. The redirect URI is the SHELL's page, not the iframe's. Studio sends the code
|
|
17
|
+
* back to `https://<games host>/<slug>/` (the app's registered redirect URI, which
|
|
18
|
+
* `claimGameHosting` registered); the shell moves `?code=&state=` onto the iframe's
|
|
19
|
+
* `src` and strips it from its own address bar; the game's
|
|
20
|
+
* `handleSignInCallback()` then reads its own `location.search` exactly as it does
|
|
21
|
+
* when self-hosted. The shell tells the game which return URL to use in
|
|
22
|
+
* `crowdyjs:host-hello`.
|
|
23
|
+
*
|
|
24
|
+
* WHAT DOES NOT CHANGE. The PKCE pair is generated here, in the game's origin, and the
|
|
25
|
+
* verifier stays in the game origin's sessionStorage. The shell relays a code it cannot
|
|
26
|
+
* spend. The app token is exchanged and stored by the game as before.
|
|
27
|
+
*
|
|
28
|
+
* WHY TRUSTING THE PARENT IS SAFE. The bridge accepts `crowdyjs:host-hello` only from
|
|
29
|
+
* `window.parent`. When the game is served by the Crowdy Games content edge, its
|
|
30
|
+
* `frame-ancestors` names the tier's games host and nothing else, so the parent IS the
|
|
31
|
+
* shell. A self-hosted game framed by a hostile page could be told a hostile
|
|
32
|
+
* `returnUrl` -- and Studio would refuse it, because it is not one of the app's
|
|
33
|
+
* registered redirect URIs; and even a code delivered to a registered-but-wrong page
|
|
34
|
+
* is useless without the verifier in this origin. The bridge also refuses a
|
|
35
|
+
* `returnUrl` whose origin is not https (or the parent's own origin, for a local dev
|
|
36
|
+
* shell), so the failure is loud rather than a silent detour.
|
|
37
|
+
*
|
|
38
|
+
* The message shapes mirror Crowdy-Games `shell/src/protocol.ts` (version 1).
|
|
39
|
+
*/
|
|
40
|
+
export declare const EMBEDDED_HOST_PROTOCOL_VERSION = 1;
|
|
41
|
+
export interface HostHelloMessage {
|
|
42
|
+
type: 'crowdyjs:host-hello';
|
|
43
|
+
version: number;
|
|
44
|
+
/** The URL hosted sign-in must return to: the shell's page for this game. */
|
|
45
|
+
returnUrl: string;
|
|
46
|
+
/** The Studio origin the shell will navigate to for `/authorize`. */
|
|
47
|
+
authorizeOrigin: string;
|
|
48
|
+
/** The slug the shell is showing. */
|
|
49
|
+
slug: string;
|
|
50
|
+
}
|
|
51
|
+
export interface HostHelloRequestMessage {
|
|
52
|
+
type: 'crowdyjs:host-hello-request';
|
|
53
|
+
version: number;
|
|
54
|
+
}
|
|
55
|
+
export interface NavigateMessage {
|
|
56
|
+
type: 'crowdyjs:navigate';
|
|
57
|
+
version: number;
|
|
58
|
+
url: string;
|
|
59
|
+
}
|
|
60
|
+
/** What the game learned from the shell. */
|
|
61
|
+
export interface EmbeddedHostInfo {
|
|
62
|
+
/** The shell's origin (`event.origin` of the hello) -- the only target navigate posts to. */
|
|
63
|
+
hostOrigin: string;
|
|
64
|
+
returnUrl: string;
|
|
65
|
+
authorizeOrigin: string;
|
|
66
|
+
slug: string;
|
|
67
|
+
}
|
|
68
|
+
/** The DOM surface the bridge needs, narrow so tests can hand it a fake. */
|
|
69
|
+
export interface EmbeddedWindow {
|
|
70
|
+
parent: unknown;
|
|
71
|
+
addEventListener(type: 'message', listener: (event: EmbeddedMessageEvent) => void): void;
|
|
72
|
+
removeEventListener(type: 'message', listener: (event: EmbeddedMessageEvent) => void): void;
|
|
73
|
+
location?: {
|
|
74
|
+
origin?: string;
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
export interface EmbeddedMessageEvent {
|
|
78
|
+
data: unknown;
|
|
79
|
+
origin: string;
|
|
80
|
+
source: unknown;
|
|
81
|
+
}
|
|
82
|
+
export interface ParentWindow {
|
|
83
|
+
postMessage(message: unknown, targetOrigin: string): void;
|
|
84
|
+
}
|
|
85
|
+
export interface EmbeddedHostOptions {
|
|
86
|
+
/** How long `hello()` waits for the shell before deciding the game is not framed by one. */
|
|
87
|
+
helloTimeoutMs?: number;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Detects and talks to a Crowdy Games shell framing this page. Constructed once by
|
|
91
|
+
* `createCrowdyClient` (see `CrowdyClientConfig.embeddedHost`); `portal.signIn`
|
|
92
|
+
* consults it.
|
|
93
|
+
*/
|
|
94
|
+
export declare class EmbeddedHost {
|
|
95
|
+
private readonly win;
|
|
96
|
+
private info;
|
|
97
|
+
private pending;
|
|
98
|
+
private readonly listener;
|
|
99
|
+
private readonly helloTimeoutMs;
|
|
100
|
+
constructor(win?: EmbeddedWindow | null, options?: EmbeddedHostOptions);
|
|
101
|
+
/** True when this page is inside another (any) frame. Not the same as "framed by a shell". */
|
|
102
|
+
isFramed(): boolean;
|
|
103
|
+
/** The shell's facts, once a hello has arrived; null before that or when not framed. */
|
|
104
|
+
current(): EmbeddedHostInfo | null;
|
|
105
|
+
/**
|
|
106
|
+
* Ask the parent to identify itself and wait (bounded) for a hello. Resolves null
|
|
107
|
+
* when this page is not framed, or the parent never answers -- which is how a game
|
|
108
|
+
* that is simply embedded in somebody's blog behaves like a top-level page.
|
|
109
|
+
*/
|
|
110
|
+
hello(timeoutMs?: number): Promise<EmbeddedHostInfo | null>;
|
|
111
|
+
/**
|
|
112
|
+
* Ask the shell to take the tab to `url`. The shell honours only its tier's Studio
|
|
113
|
+
* `/authorize` with a redirect_uri of its own page; anything else is dropped there.
|
|
114
|
+
*/
|
|
115
|
+
navigate(url: string): void;
|
|
116
|
+
close(): void;
|
|
117
|
+
private onHello;
|
|
118
|
+
private onMessage;
|
|
119
|
+
/**
|
|
120
|
+
* The return URL must be a page ON THE SHELL'S OWN ORIGIN: the shell is the page
|
|
121
|
+
* that will receive the code, so a hello naming anywhere else is malformed (or
|
|
122
|
+
* hostile) and is ignored rather than acted on.
|
|
123
|
+
*/
|
|
124
|
+
private acceptableReturnUrl;
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=embedded-host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedded-host.d.ts","sourceRoot":"","sources":["../../src/domains/embedded-host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,eAAO,MAAM,8BAA8B,IAAI,CAAC;AAEhD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,qBAAqB,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,SAAS,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,eAAe,EAAE,MAAM,CAAC;IACxB,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,6BAA6B,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,mBAAmB,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,4CAA4C;AAC5C,MAAM,WAAW,gBAAgB;IAC/B,6FAA6F;IAC7F,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,4EAA4E;AAC5E,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,OAAO,CAAC;IAChB,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,GAAG,IAAI,CAAC;IACzF,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,GAAG,IAAI,CAAC;IAC5F,QAAQ,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAChC;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3D;AAED,MAAM,WAAW,mBAAmB;IAClC,4FAA4F;IAC5F,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAeD;;;;GAIG;AACH,qBAAa,YAAY;IAOrB,OAAO,CAAC,QAAQ,CAAC,GAAG;IANtB,OAAO,CAAC,IAAI,CAAiC;IAC7C,OAAO,CAAC,OAAO,CAAiD;IAChE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwC;IACjE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;gBAGrB,GAAG,GAAE,cAAc,GAAG,IAAsB,EAC7D,OAAO,GAAE,mBAAwB;IASnC,8FAA8F;IAC9F,QAAQ,IAAI,OAAO;IAUnB,wFAAwF;IACxF,OAAO,IAAI,gBAAgB,GAAG,IAAI;IAIlC;;;;OAIG;IACH,KAAK,CAAC,SAAS,SAAsB,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IA2BxE;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAU3B,KAAK,IAAI,IAAI;IAIb,OAAO,CAAC,OAAO,CAA6B;IAE5C,OAAO,CAAC,SAAS;IAmBjB;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;CAQ5B"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The embedded-host bridge: how a game framed by the Crowdy Games SHELL signs in.
|
|
3
|
+
*
|
|
4
|
+
* A game published to Crowdy Games (`client.hosting`, the-construct's `npm run
|
|
5
|
+
* publish`) is reached at `https://<games host>/<slug>/`, which is a first-party
|
|
6
|
+
* shell page, and executes inside that page's iframe on its own origin,
|
|
7
|
+
* `https://<slug>.<content host>`. Two things about that arrangement change hosted
|
|
8
|
+
* sign-in, and this module is the whole of the change:
|
|
9
|
+
*
|
|
10
|
+
* 1. The game cannot navigate the tab. Its iframe has no `allow-top-navigation`
|
|
11
|
+
* (a game that could send the player to a lookalike sign-in page would have the
|
|
12
|
+
* phishing surface the shell exists to remove), and Studio refuses to be framed.
|
|
13
|
+
* So `portal.signIn` asks the SHELL to navigate -- `crowdyjs:navigate` -- and
|
|
14
|
+
* the shell honours exactly one destination: the tier's Studio `/authorize`.
|
|
15
|
+
*
|
|
16
|
+
* 2. The redirect URI is the SHELL's page, not the iframe's. Studio sends the code
|
|
17
|
+
* back to `https://<games host>/<slug>/` (the app's registered redirect URI, which
|
|
18
|
+
* `claimGameHosting` registered); the shell moves `?code=&state=` onto the iframe's
|
|
19
|
+
* `src` and strips it from its own address bar; the game's
|
|
20
|
+
* `handleSignInCallback()` then reads its own `location.search` exactly as it does
|
|
21
|
+
* when self-hosted. The shell tells the game which return URL to use in
|
|
22
|
+
* `crowdyjs:host-hello`.
|
|
23
|
+
*
|
|
24
|
+
* WHAT DOES NOT CHANGE. The PKCE pair is generated here, in the game's origin, and the
|
|
25
|
+
* verifier stays in the game origin's sessionStorage. The shell relays a code it cannot
|
|
26
|
+
* spend. The app token is exchanged and stored by the game as before.
|
|
27
|
+
*
|
|
28
|
+
* WHY TRUSTING THE PARENT IS SAFE. The bridge accepts `crowdyjs:host-hello` only from
|
|
29
|
+
* `window.parent`. When the game is served by the Crowdy Games content edge, its
|
|
30
|
+
* `frame-ancestors` names the tier's games host and nothing else, so the parent IS the
|
|
31
|
+
* shell. A self-hosted game framed by a hostile page could be told a hostile
|
|
32
|
+
* `returnUrl` -- and Studio would refuse it, because it is not one of the app's
|
|
33
|
+
* registered redirect URIs; and even a code delivered to a registered-but-wrong page
|
|
34
|
+
* is useless without the verifier in this origin. The bridge also refuses a
|
|
35
|
+
* `returnUrl` whose origin is not https (or the parent's own origin, for a local dev
|
|
36
|
+
* shell), so the failure is loud rather than a silent detour.
|
|
37
|
+
*
|
|
38
|
+
* The message shapes mirror Crowdy-Games `shell/src/protocol.ts` (version 1).
|
|
39
|
+
*/
|
|
40
|
+
export const EMBEDDED_HOST_PROTOCOL_VERSION = 1;
|
|
41
|
+
const DEFAULT_HELLO_TIMEOUT_MS = 1500;
|
|
42
|
+
function isHostHello(data) {
|
|
43
|
+
if (typeof data !== 'object' || data === null)
|
|
44
|
+
return false;
|
|
45
|
+
const d = data;
|
|
46
|
+
return (d.type === 'crowdyjs:host-hello' &&
|
|
47
|
+
typeof d.returnUrl === 'string' &&
|
|
48
|
+
typeof d.authorizeOrigin === 'string' &&
|
|
49
|
+
typeof d.slug === 'string');
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Detects and talks to a Crowdy Games shell framing this page. Constructed once by
|
|
53
|
+
* `createCrowdyClient` (see `CrowdyClientConfig.embeddedHost`); `portal.signIn`
|
|
54
|
+
* consults it.
|
|
55
|
+
*/
|
|
56
|
+
export class EmbeddedHost {
|
|
57
|
+
constructor(win = defaultWindow(), options = {}) {
|
|
58
|
+
this.win = win;
|
|
59
|
+
this.info = null;
|
|
60
|
+
this.pending = null;
|
|
61
|
+
this.onHello = null;
|
|
62
|
+
this.helloTimeoutMs = options.helloTimeoutMs ?? DEFAULT_HELLO_TIMEOUT_MS;
|
|
63
|
+
this.listener = (event) => this.onMessage(event);
|
|
64
|
+
if (this.isFramed()) {
|
|
65
|
+
this.win.addEventListener('message', this.listener);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** True when this page is inside another (any) frame. Not the same as "framed by a shell". */
|
|
69
|
+
isFramed() {
|
|
70
|
+
const w = this.win;
|
|
71
|
+
if (!w)
|
|
72
|
+
return false;
|
|
73
|
+
try {
|
|
74
|
+
return w.parent !== null && w.parent !== undefined && w.parent !== w;
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/** The shell's facts, once a hello has arrived; null before that or when not framed. */
|
|
81
|
+
current() {
|
|
82
|
+
return this.info;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Ask the parent to identify itself and wait (bounded) for a hello. Resolves null
|
|
86
|
+
* when this page is not framed, or the parent never answers -- which is how a game
|
|
87
|
+
* that is simply embedded in somebody's blog behaves like a top-level page.
|
|
88
|
+
*/
|
|
89
|
+
hello(timeoutMs = this.helloTimeoutMs) {
|
|
90
|
+
if (!this.isFramed())
|
|
91
|
+
return Promise.resolve(null);
|
|
92
|
+
if (this.info)
|
|
93
|
+
return Promise.resolve(this.info);
|
|
94
|
+
if (this.pending)
|
|
95
|
+
return this.pending;
|
|
96
|
+
this.pending = new Promise((resolve) => {
|
|
97
|
+
const timer = setTimeout(() => {
|
|
98
|
+
this.pending = null;
|
|
99
|
+
resolve(this.info);
|
|
100
|
+
}, timeoutMs);
|
|
101
|
+
const check = () => {
|
|
102
|
+
if (this.info) {
|
|
103
|
+
clearTimeout(timer);
|
|
104
|
+
this.pending = null;
|
|
105
|
+
resolve(this.info);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
this.onHello = check;
|
|
109
|
+
const request = {
|
|
110
|
+
type: 'crowdyjs:host-hello-request',
|
|
111
|
+
version: EMBEDDED_HOST_PROTOCOL_VERSION,
|
|
112
|
+
};
|
|
113
|
+
// '*': the request carries nothing and the parent's origin is not yet known.
|
|
114
|
+
this.win.parent.postMessage(request, '*');
|
|
115
|
+
});
|
|
116
|
+
return this.pending;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Ask the shell to take the tab to `url`. The shell honours only its tier's Studio
|
|
120
|
+
* `/authorize` with a redirect_uri of its own page; anything else is dropped there.
|
|
121
|
+
*/
|
|
122
|
+
navigate(url) {
|
|
123
|
+
if (!this.info)
|
|
124
|
+
throw new Error('embedded host: no shell has said hello; call hello() first');
|
|
125
|
+
const message = {
|
|
126
|
+
type: 'crowdyjs:navigate',
|
|
127
|
+
version: EMBEDDED_HOST_PROTOCOL_VERSION,
|
|
128
|
+
url,
|
|
129
|
+
};
|
|
130
|
+
this.win.parent.postMessage(message, this.info.hostOrigin);
|
|
131
|
+
}
|
|
132
|
+
close() {
|
|
133
|
+
this.win?.removeEventListener('message', this.listener);
|
|
134
|
+
}
|
|
135
|
+
onMessage(event) {
|
|
136
|
+
if (!this.win || event.source !== this.win.parent)
|
|
137
|
+
return;
|
|
138
|
+
if (!isHostHello(event.data))
|
|
139
|
+
return;
|
|
140
|
+
if (!this.acceptableReturnUrl(event.data.returnUrl, event.origin))
|
|
141
|
+
return;
|
|
142
|
+
let authorizeOrigin;
|
|
143
|
+
try {
|
|
144
|
+
authorizeOrigin = new URL(event.data.authorizeOrigin).origin;
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
this.info = {
|
|
150
|
+
hostOrigin: event.origin,
|
|
151
|
+
returnUrl: event.data.returnUrl,
|
|
152
|
+
authorizeOrigin,
|
|
153
|
+
slug: event.data.slug,
|
|
154
|
+
};
|
|
155
|
+
this.onHello?.();
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* The return URL must be a page ON THE SHELL'S OWN ORIGIN: the shell is the page
|
|
159
|
+
* that will receive the code, so a hello naming anywhere else is malformed (or
|
|
160
|
+
* hostile) and is ignored rather than acted on.
|
|
161
|
+
*/
|
|
162
|
+
acceptableReturnUrl(returnUrl, hostOrigin) {
|
|
163
|
+
try {
|
|
164
|
+
const u = new URL(returnUrl);
|
|
165
|
+
return u.origin === hostOrigin && (u.protocol === 'https:' || u.hostname === 'localhost' || u.hostname === '127.0.0.1');
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
function defaultWindow() {
|
|
173
|
+
const g = globalThis;
|
|
174
|
+
return g.window ?? null;
|
|
175
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { GraphQLClient } from '../client.js';
|
|
2
|
+
import { type BeginGamePublishMutation, type CompleteGamePublishMutation, type HostedGameFieldsFragment, type HostedGamePublishFieldsFragment, type PublishFileInput } from '../generated/graphql.js';
|
|
3
|
+
export type HostedGame = HostedGameFieldsFragment;
|
|
4
|
+
export type HostedGamePublish = HostedGamePublishFieldsFragment;
|
|
5
|
+
export type BeginGamePublishResult = BeginGamePublishMutation['beginGamePublish'];
|
|
6
|
+
export type HostedGameUpload = BeginGamePublishResult['uploads'][number];
|
|
7
|
+
export type CompleteGamePublishResult = CompleteGamePublishMutation['completeGamePublish'];
|
|
8
|
+
export type { PublishFileInput };
|
|
9
|
+
/**
|
|
10
|
+
* Third-party game hosting on Crowdy Games (ck-api v2.1, 2026-09-13).
|
|
11
|
+
*
|
|
12
|
+
* A developer publishes a built static bundle to the platform; players reach it at
|
|
13
|
+
* `https://<games host>/<slug>/` (a first-party shell page) while it executes on
|
|
14
|
+
* `https://<slug>.<content host>`, an origin of its own. The API returns both URLs
|
|
15
|
+
* (`launchUrl`, `contentOrigin`); nothing here spells a hostname.
|
|
16
|
+
*
|
|
17
|
+
* WHICH TOKEN. Every mutation here needs an IDENTITY SESSION (`client.auth.login`
|
|
18
|
+
* from Node, or a Studio session) with `manage_apps` on the app -- never an app
|
|
19
|
+
* token. A game's own bundle can therefore never publish a replacement for itself.
|
|
20
|
+
* The two reads a page needs (`game`, `listed`) are public.
|
|
21
|
+
*
|
|
22
|
+
* THE FLOW: `claim` once per app -> build -> `beginPublish` with the manifest ->
|
|
23
|
+
* PUT every file to its presigned URL with exactly the returned headers ->
|
|
24
|
+
* `completePublish`. `@crowdedkingdoms/crowdyjs/hosting`'s `publishDirectory` does
|
|
25
|
+
* the last three steps for a `dist/` directory in Node.
|
|
26
|
+
*/
|
|
27
|
+
export declare class HostingAPI {
|
|
28
|
+
private readonly api;
|
|
29
|
+
constructor(api: GraphQLClient);
|
|
30
|
+
/** Public: a hosted game by slug, or null. The shell's question. */
|
|
31
|
+
game(slug: string): Promise<HostedGame | null>;
|
|
32
|
+
/** Public: the LIVE, LISTED hosted games -- the lobby's list. */
|
|
33
|
+
listed(): Promise<HostedGame[]>;
|
|
34
|
+
/** Operator: every hosted game on the tier. */
|
|
35
|
+
all(): Promise<HostedGame[]>;
|
|
36
|
+
/** The hosted games the caller can manage. Session token. */
|
|
37
|
+
mine(): Promise<HostedGame[]>;
|
|
38
|
+
/** Publish history for a game, newest first. Session token + manage_apps. */
|
|
39
|
+
publishes(slug: string, limit?: number): Promise<HostedGamePublish[]>;
|
|
40
|
+
/**
|
|
41
|
+
* Claim (or re-assert) the hosting slug for an app. Idempotent; a different slug
|
|
42
|
+
* MOVES the game. Registers the shell page and the game origin as redirect URIs
|
|
43
|
+
* and sets `launch_url`. Refuses reserved, taken or malformed slugs
|
|
44
|
+
* (`HOSTED_SLUG_UNAVAILABLE`) and a tier without hosting (`CONTENT_HOSTING_DISABLED`).
|
|
45
|
+
*/
|
|
46
|
+
claim(params: {
|
|
47
|
+
appId: string;
|
|
48
|
+
slug?: string;
|
|
49
|
+
}): Promise<HostedGame>;
|
|
50
|
+
/** Declare a publish; returns one presigned PUT per file. */
|
|
51
|
+
beginPublish(params: {
|
|
52
|
+
slug: string;
|
|
53
|
+
files: PublishFileInput[];
|
|
54
|
+
}): Promise<BeginGamePublishResult>;
|
|
55
|
+
/** Verify, promote, record LIVE, invalidate. */
|
|
56
|
+
completePublish(slug: string, publishId: string): Promise<CompleteGamePublishResult>;
|
|
57
|
+
abandonPublish(slug: string, publishId: string): Promise<HostedGamePublish>;
|
|
58
|
+
/** Developer switch: off (DISABLED) or on (LIVE). */
|
|
59
|
+
setEnabled(slug: string, enabled: boolean): Promise<HostedGame>;
|
|
60
|
+
/** Operator: list or unlist in the lobby and the management UI. */
|
|
61
|
+
setListing(slug: string, listed: boolean): Promise<HostedGame>;
|
|
62
|
+
/** Operator: take down (or restore with `false`). */
|
|
63
|
+
takeDown(slug: string, takenDown?: boolean): Promise<HostedGame>;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Upload every file of a publish to its presigned URL, with bounded concurrency and
|
|
67
|
+
* a retry per file. Works in Node 20+ and in a browser (`fetch`, `Blob`/`Uint8Array`
|
|
68
|
+
* bodies). `read(path)` returns the bytes for a manifest path.
|
|
69
|
+
*/
|
|
70
|
+
export declare function uploadPublishFiles(uploads: HostedGameUpload[], read: (path: string) => Promise<Uint8Array | Blob>, options?: {
|
|
71
|
+
concurrency?: number;
|
|
72
|
+
retries?: number;
|
|
73
|
+
onFile?: (path: string, ok: boolean) => void;
|
|
74
|
+
}): Promise<void>;
|
|
75
|
+
//# sourceMappingURL=hosting.d.ts.map
|