@crowdedkingdoms/crowdyjs 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/MIGRATION.md +247 -0
- package/README.md +303 -0
- package/dist/auth-state.d.ts +11 -0
- package/dist/auth-state.d.ts.map +1 -0
- package/dist/auth-state.js +13 -0
- package/dist/client.d.ts +135 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +150 -0
- package/dist/crowdy-client.d.ts +182 -0
- package/dist/crowdy-client.d.ts.map +1 -0
- package/dist/crowdy-client.js +146 -0
- package/dist/domains/actors.d.ts +117 -0
- package/dist/domains/actors.d.ts.map +1 -0
- package/dist/domains/actors.js +140 -0
- package/dist/domains/admin.d.ts +61 -0
- package/dist/domains/admin.d.ts.map +1 -0
- package/dist/domains/admin.js +33 -0
- package/dist/domains/appAccess.d.ts +141 -0
- package/dist/domains/appAccess.d.ts.map +1 -0
- package/dist/domains/appAccess.js +198 -0
- package/dist/domains/apps.d.ts +192 -0
- package/dist/domains/apps.d.ts.map +1 -0
- package/dist/domains/apps.js +217 -0
- package/dist/domains/auth.d.ts +163 -0
- package/dist/domains/auth.d.ts.map +1 -0
- package/dist/domains/auth.js +208 -0
- package/dist/domains/avatars.d.ts +94 -0
- package/dist/domains/avatars.d.ts.map +1 -0
- package/dist/domains/avatars.js +137 -0
- package/dist/domains/billing.d.ts +97 -0
- package/dist/domains/billing.d.ts.map +1 -0
- package/dist/domains/billing.js +131 -0
- package/dist/domains/channels.d.ts +293 -0
- package/dist/domains/channels.d.ts.map +1 -0
- package/dist/domains/channels.js +353 -0
- package/dist/domains/chunks.d.ts +133 -0
- package/dist/domains/chunks.d.ts.map +1 -0
- package/dist/domains/chunks.js +153 -0
- package/dist/domains/controlPlane.d.ts +174 -0
- package/dist/domains/controlPlane.d.ts.map +1 -0
- package/dist/domains/controlPlane.js +252 -0
- package/dist/domains/environments.d.ts +155 -0
- package/dist/domains/environments.d.ts.map +1 -0
- package/dist/domains/environments.js +223 -0
- package/dist/domains/gameApps.d.ts +114 -0
- package/dist/domains/gameApps.d.ts.map +1 -0
- package/dist/domains/gameApps.js +169 -0
- package/dist/domains/gameModel.d.ts +668 -0
- package/dist/domains/gameModel.d.ts.map +1 -0
- package/dist/domains/gameModel.js +816 -0
- package/dist/domains/host.d.ts +35 -0
- package/dist/domains/host.d.ts.map +1 -0
- package/dist/domains/host.js +40 -0
- package/dist/domains/organizations.d.ts +179 -0
- package/dist/domains/organizations.d.ts.map +1 -0
- package/dist/domains/organizations.js +269 -0
- package/dist/domains/payments.d.ts +104 -0
- package/dist/domains/payments.d.ts.map +1 -0
- package/dist/domains/payments.js +129 -0
- package/dist/domains/platform.d.ts +49 -0
- package/dist/domains/platform.d.ts.map +1 -0
- package/dist/domains/platform.js +50 -0
- package/dist/domains/quotas.d.ts +62 -0
- package/dist/domains/quotas.d.ts.map +1 -0
- package/dist/domains/quotas.js +79 -0
- package/dist/domains/serverStatus.d.ts +90 -0
- package/dist/domains/serverStatus.d.ts.map +1 -0
- package/dist/domains/serverStatus.js +104 -0
- package/dist/domains/sharedEnvironment.d.ts +133 -0
- package/dist/domains/sharedEnvironment.d.ts.map +1 -0
- package/dist/domains/sharedEnvironment.js +179 -0
- package/dist/domains/state.d.ts +64 -0
- package/dist/domains/state.d.ts.map +1 -0
- package/dist/domains/state.js +75 -0
- package/dist/domains/teams.d.ts +292 -0
- package/dist/domains/teams.d.ts.map +1 -0
- package/dist/domains/teams.js +352 -0
- package/dist/domains/teleport.d.ts +41 -0
- package/dist/domains/teleport.d.ts.map +1 -0
- package/dist/domains/teleport.js +43 -0
- package/dist/domains/udp.d.ts +405 -0
- package/dist/domains/udp.d.ts.map +1 -0
- package/dist/domains/udp.js +457 -0
- package/dist/domains/usage.d.ts +76 -0
- package/dist/domains/usage.d.ts.map +1 -0
- package/dist/domains/usage.js +110 -0
- package/dist/domains/users.d.ts +147 -0
- package/dist/domains/users.d.ts.map +1 -0
- package/dist/domains/users.js +195 -0
- package/dist/domains/voxels.d.ts +136 -0
- package/dist/domains/voxels.d.ts.map +1 -0
- package/dist/domains/voxels.js +153 -0
- package/dist/errors.d.ts +158 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +142 -0
- package/dist/generated/graphql.d.ts +12206 -0
- package/dist/generated/graphql.d.ts.map +1 -0
- package/dist/generated/graphql.js +474 -0
- package/dist/index.d.ts +84 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +85 -0
- package/dist/logger.d.ts +8 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +1 -0
- package/dist/realtime.d.ts +319 -0
- package/dist/realtime.d.ts.map +1 -0
- package/dist/realtime.js +390 -0
- package/dist/session.d.ts +73 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +96 -0
- package/dist/subscriptions.d.ts +2 -0
- package/dist/subscriptions.d.ts.map +1 -0
- package/dist/subscriptions.js +1 -0
- package/dist/types.d.ts +658 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +61 -0
- package/dist/utils.d.ts +98 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +136 -0
- package/dist/world.d.ts +236 -0
- package/dist/world.d.ts.map +1 -0
- package/dist/world.js +275 -0
- package/package.json +73 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { AppAccessTiersDocument, MyAppAccessDocument, AppUserAccessByAppDocument, AppUserAccessConnectionDocument, RuntimePermissionsDocument, AppGrantMemberCandidatesDocument, ClaimFreeAppAccessDocument, GrantMyAppAccessDocument, CreateAccessTierDocument, UpdateAccessTierDocument, ArchiveAccessTierDocument, GrantAppAccessDocument, RevokeAppAccessDocument, } from '../generated/graphql.js';
|
|
2
|
+
/**
|
|
3
|
+
* App access tiers + per-user access grants — exposed as `client.appAccess`
|
|
4
|
+
* (and grouped under `client.admin`).
|
|
5
|
+
*
|
|
6
|
+
* Targets the **management-api**. Tiers define the runtime-permission bundles
|
|
7
|
+
* (`access`, `teleport`, `update_voxel_data`, `use_voice_chat`, ...) a player
|
|
8
|
+
* gets; grants attach a user to a tier. New apps auto-provision an open default
|
|
9
|
+
* tier, so most players need no explicit grant.
|
|
10
|
+
*
|
|
11
|
+
* Reads of the tier catalog ({@link tiers}) are public; {@link myAccess} needs
|
|
12
|
+
* a session; tier admin and grant/revoke require the `manage_access_tiers` app
|
|
13
|
+
* permission. `BigInt` ids are decimal strings.
|
|
14
|
+
*
|
|
15
|
+
* @throws {CrowdyGraphQLError} `UNAUTHENTICATED` / `FORBIDDEN` / `SCOPE_MISSING`
|
|
16
|
+
* per the permission notes above.
|
|
17
|
+
*/
|
|
18
|
+
export class AppAccessAPI {
|
|
19
|
+
constructor(management) {
|
|
20
|
+
this.management = management;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* List the access tiers defined for an app. **Public.**
|
|
24
|
+
*
|
|
25
|
+
* @param appId - Numeric app id (`BigInt` as a decimal string).
|
|
26
|
+
* @returns The app's tiers, ordered.
|
|
27
|
+
*/
|
|
28
|
+
async tiers(appId) {
|
|
29
|
+
const data = await this.management.request(AppAccessTiersDocument, {
|
|
30
|
+
appId,
|
|
31
|
+
});
|
|
32
|
+
return data.appAccessTiers;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Return the authenticated caller's access record for an app (which tier they
|
|
36
|
+
* hold and its status), or `null` if they have none.
|
|
37
|
+
*
|
|
38
|
+
* @param appId - Numeric app id.
|
|
39
|
+
* @returns The caller's {@link AppUserAccess}, or `null`.
|
|
40
|
+
*/
|
|
41
|
+
async myAccess(appId) {
|
|
42
|
+
const data = await this.management.request(MyAppAccessDocument, { appId });
|
|
43
|
+
return data.myAppAccess;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* List the users who hold access to an app (paginated). Requires the
|
|
47
|
+
* `manage_access_tiers` app permission.
|
|
48
|
+
*
|
|
49
|
+
* @param appId - Numeric app id.
|
|
50
|
+
* @param opts - Optional `status` filter and `limit` / `offset` (default
|
|
51
|
+
* limit 50).
|
|
52
|
+
* @returns The matching access records.
|
|
53
|
+
*/
|
|
54
|
+
async usersByApp(appId, opts = {}) {
|
|
55
|
+
const data = await this.management.request(AppUserAccessByAppDocument, {
|
|
56
|
+
appId,
|
|
57
|
+
status: opts.status,
|
|
58
|
+
limit: opts.limit,
|
|
59
|
+
offset: opts.offset,
|
|
60
|
+
});
|
|
61
|
+
return data.appUserAccessByApp;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Relay-style cursor pagination over an app's access grants — the preferred
|
|
65
|
+
* alternative to {@link usersByApp}. Page with `first` plus the previous
|
|
66
|
+
* page's `pageInfo.endCursor` as `after`; optional `status` filter. Requires
|
|
67
|
+
* the `manage_access_tiers` app permission. See
|
|
68
|
+
* https://docs.crowdedkingdoms.com/overview/pagination.
|
|
69
|
+
*
|
|
70
|
+
* @param args - `appId` plus optional `status`, `first`, and `after`.
|
|
71
|
+
* @returns An {@link AppUserAccessConnection}.
|
|
72
|
+
*/
|
|
73
|
+
async usersByAppConnection(args) {
|
|
74
|
+
const data = await this.management.request(AppUserAccessConnectionDocument, args);
|
|
75
|
+
return data.appUserAccessConnection;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* List every valid runtime permission key (e.g. `access`, `teleport`,
|
|
79
|
+
* `update_voxel_data`, `use_voice_chat`) that a tier or grid grant can
|
|
80
|
+
* reference. **Public.**
|
|
81
|
+
*
|
|
82
|
+
* @returns The runtime permission keys.
|
|
83
|
+
*/
|
|
84
|
+
async runtimePermissions() {
|
|
85
|
+
const data = await this.management.request(RuntimePermissionsDocument);
|
|
86
|
+
return data.runtimePermissions;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* List org members eligible for a manual app-access grant (those without an
|
|
90
|
+
* active grant yet). Requires the `manage_access_tiers` app permission. Pair
|
|
91
|
+
* with {@link grant} to grant the chosen candidate.
|
|
92
|
+
*
|
|
93
|
+
* @param appId - Numeric app id.
|
|
94
|
+
* @returns The candidate users (id + email/gamertag where known).
|
|
95
|
+
*/
|
|
96
|
+
async grantMemberCandidates(appId) {
|
|
97
|
+
const data = await this.management.request(AppGrantMemberCandidatesDocument, { appId });
|
|
98
|
+
return data.appGrantMemberCandidates;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Self-service: claim the app's free/default tier for the authenticated
|
|
102
|
+
* caller (no admin permission required). Use when an app exposes a free tier
|
|
103
|
+
* a player can opt into themselves.
|
|
104
|
+
*
|
|
105
|
+
* @param appId - Numeric app id.
|
|
106
|
+
* @returns The caller's new {@link AppUserAccess} record.
|
|
107
|
+
*/
|
|
108
|
+
async claimFree(appId) {
|
|
109
|
+
const data = await this.management.request(ClaimFreeAppAccessDocument, {
|
|
110
|
+
appId,
|
|
111
|
+
});
|
|
112
|
+
return data.claimFreeAppAccess;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Self-grant access to an app via its default tier for the authenticated
|
|
116
|
+
* caller, when the caller is an org member of the app's owning org.
|
|
117
|
+
*
|
|
118
|
+
* @param appId - Numeric app id.
|
|
119
|
+
* @returns The caller's new {@link AppUserAccess} record.
|
|
120
|
+
*/
|
|
121
|
+
async grantMine(appId) {
|
|
122
|
+
const data = await this.management.request(GrantMyAppAccessDocument, {
|
|
123
|
+
appId,
|
|
124
|
+
});
|
|
125
|
+
return data.grantMyAppAccess;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Create a new access tier for an app. Requires the `manage_access_tiers` app
|
|
129
|
+
* permission.
|
|
130
|
+
*
|
|
131
|
+
* @param input - {@link CreateAccessTierInput}: `appId`, `name`, runtime
|
|
132
|
+
* `permissions`, pricing/free flags.
|
|
133
|
+
* @returns The created tier.
|
|
134
|
+
*/
|
|
135
|
+
async createTier(input) {
|
|
136
|
+
const data = await this.management.request(CreateAccessTierDocument, {
|
|
137
|
+
input,
|
|
138
|
+
});
|
|
139
|
+
return data.createAccessTier;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Update an existing access tier. Requires the `manage_access_tiers` app
|
|
143
|
+
* permission.
|
|
144
|
+
*
|
|
145
|
+
* @param tierId - Numeric tier id.
|
|
146
|
+
* @param input - {@link UpdateAccessTierInput} fields to change.
|
|
147
|
+
* @returns The updated tier.
|
|
148
|
+
*/
|
|
149
|
+
async updateTier(tierId, input) {
|
|
150
|
+
const data = await this.management.request(UpdateAccessTierDocument, {
|
|
151
|
+
tierId,
|
|
152
|
+
input,
|
|
153
|
+
});
|
|
154
|
+
return data.updateAccessTier;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Archive (soft-delete) an access tier so it can no longer be granted.
|
|
158
|
+
* Requires the `manage_access_tiers` app permission.
|
|
159
|
+
*
|
|
160
|
+
* @param tierId - Numeric tier id.
|
|
161
|
+
* @returns The archived tier's new status.
|
|
162
|
+
*/
|
|
163
|
+
async archiveTier(tierId) {
|
|
164
|
+
const data = await this.management.request(ArchiveAccessTierDocument, {
|
|
165
|
+
tierId,
|
|
166
|
+
});
|
|
167
|
+
return data.archiveAccessTier;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Grant a user access to an app at a given tier. Requires the
|
|
171
|
+
* `manage_access_tiers` app permission. Triggers replica-sync so the grant
|
|
172
|
+
* (and its grid permissions) reaches the game DB / Buddy.
|
|
173
|
+
*
|
|
174
|
+
* @param input - {@link GrantAppAccessInput}: `appId`, `userId`, `tierId`.
|
|
175
|
+
* @returns The created/updated access record.
|
|
176
|
+
*/
|
|
177
|
+
async grant(input) {
|
|
178
|
+
const data = await this.management.request(GrantAppAccessDocument, {
|
|
179
|
+
input,
|
|
180
|
+
});
|
|
181
|
+
return data.grantAppAccess;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Revoke a user's access to an app. Requires the `manage_access_tiers` app
|
|
185
|
+
* permission.
|
|
186
|
+
*
|
|
187
|
+
* @param appId - Numeric app id.
|
|
188
|
+
* @param userId - Numeric id of the user whose access is revoked.
|
|
189
|
+
* @returns `true` on success.
|
|
190
|
+
*/
|
|
191
|
+
async revoke(appId, userId) {
|
|
192
|
+
const data = await this.management.request(RevokeAppAccessDocument, {
|
|
193
|
+
appId,
|
|
194
|
+
userId,
|
|
195
|
+
});
|
|
196
|
+
return data.revokeAppAccess;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import type { GraphQLClient } from '../client.js';
|
|
2
|
+
import { type AppQuery, type AppBySlugQuery, type MyAppsQuery, type AppsForOrgQuery, type MarketplaceAppsQuery, type MarketplaceAppsQueryVariables, type AppsConnectionQuery, type AppsConnectionQueryVariables, type CreateAppMutation, type UpdateAppMutation, type ArchiveAppMutation, type SetAppVisibilityMutation, type CreateAppInput, type UpdateAppInput, type AppVisibility } from '../generated/graphql.js';
|
|
3
|
+
/**
|
|
4
|
+
* The minimal routing tuple the SDK derives from an `App` row: just enough to
|
|
5
|
+
* decide which game-api endpoint should serve a given app. Returned by
|
|
6
|
+
* {@link AppsAPI.routeFor}.
|
|
7
|
+
*/
|
|
8
|
+
export interface AppRoute {
|
|
9
|
+
/** Numeric id of the app (`BigInt` as a decimal string). */
|
|
10
|
+
appId: string;
|
|
11
|
+
/**
|
|
12
|
+
* `true` when the app's runtime data lives in a dedicated per-tenant game-api
|
|
13
|
+
* database rather than the shared game-api. Used together with `gameApiUrl` to
|
|
14
|
+
* route gameplay calls.
|
|
15
|
+
*/
|
|
16
|
+
splitMode: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Where the app runs: `'none'` (draft / not deployed), `'shared'` (the shared
|
|
19
|
+
* game-api), or `'dedicated'` (a provisioned per-tenant environment). `null`
|
|
20
|
+
* until the schema/codegen expose it.
|
|
21
|
+
*/
|
|
22
|
+
deploymentTarget: string | null;
|
|
23
|
+
/**
|
|
24
|
+
* The game-api base URL to route gameplay to. Set for BOTH dedicated
|
|
25
|
+
* (split-mode) and shared-environment apps. When non-null, build a game-api
|
|
26
|
+
* client against it; when `null`, fall back to the constructor `httpUrl`.
|
|
27
|
+
*/
|
|
28
|
+
gameApiUrl: string | null;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* App discovery & game-api routing — exposed as `client.apps`.
|
|
32
|
+
*
|
|
33
|
+
* Targets the **management-api** (every call routes to `managementUrl`), where
|
|
34
|
+
* the apps catalog lives. After the database split an app may be served by its
|
|
35
|
+
* own per-tenant cks-game-api; the catalog returns each app's `gameApiUrl` so
|
|
36
|
+
* you can build a per-app `CrowdyClient` against the correct endpoint (see
|
|
37
|
+
* {@link routeFor} / {@link AppRoute}).
|
|
38
|
+
*
|
|
39
|
+
* Auth: {@link appBySlug} is **public** (no session; resolves unlisted or draft
|
|
40
|
+
* apps when the exact slugs are known). {@link app}, {@link myApps}, and
|
|
41
|
+
* {@link routeFor} require authentication (any signed-in user) and otherwise
|
|
42
|
+
* throw {@link CrowdyGraphQLError} with `UNAUTHENTICATED`; note {@link app} does
|
|
43
|
+
* not enforce org/app permissions. `BigInt` ids such as `appId` and `orgId` are
|
|
44
|
+
* decimal strings.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* const base = createCrowdyClient({
|
|
49
|
+
* managementUrl: 'https://api.example.com',
|
|
50
|
+
* httpUrl: 'https://legacy-game-api.example.com', // pre-split fallback
|
|
51
|
+
* });
|
|
52
|
+
* await base.auth.login({ email, password });
|
|
53
|
+
*
|
|
54
|
+
* const route = await base.apps.routeFor(appId);
|
|
55
|
+
* if (route.gameApiUrl) {
|
|
56
|
+
* // route gameplay to the app's resolved game-api endpoint
|
|
57
|
+
* const perAppClient = createCrowdyClient({
|
|
58
|
+
* managementUrl: 'https://api.example.com',
|
|
59
|
+
* httpUrl: route.gameApiUrl,
|
|
60
|
+
* wsUrl: route.gameApiUrl.replace(/^http/, 'ws'),
|
|
61
|
+
* tokenStore: base.session.tokenStore,
|
|
62
|
+
* });
|
|
63
|
+
* }
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export declare class AppsAPI {
|
|
67
|
+
private readonly management;
|
|
68
|
+
constructor(management: GraphQLClient);
|
|
69
|
+
/**
|
|
70
|
+
* Fetch a single app by its numeric id. Requires authentication (any signed-in
|
|
71
|
+
* user); does **not** enforce org/app permissions, so it can read apps the
|
|
72
|
+
* caller does not own, of any visibility/status. Prefer {@link appBySlug} for
|
|
73
|
+
* slug-based marketplace lookups.
|
|
74
|
+
*
|
|
75
|
+
* @param appId - Numeric id of the app (`BigInt` as a decimal string).
|
|
76
|
+
* @returns The {@link App}, or `null` if the id does not exist.
|
|
77
|
+
* @throws {CrowdyGraphQLError} `UNAUTHENTICATED` if the caller is not signed in.
|
|
78
|
+
*/
|
|
79
|
+
app(appId: string): Promise<AppQuery['app']>;
|
|
80
|
+
/**
|
|
81
|
+
* Look up a single app by its org slug + app slug (the marketplace URL path).
|
|
82
|
+
* **Public**: no authentication required, and not filtered by visibility or
|
|
83
|
+
* status — it can resolve unlisted or draft apps when the exact slugs are
|
|
84
|
+
* known.
|
|
85
|
+
*
|
|
86
|
+
* @param orgSlug - URL slug of the owning organization (e.g. `"acme"` in the
|
|
87
|
+
* path `/acme/my-game`).
|
|
88
|
+
* @param appSlug - URL slug of the app within the org (e.g. `"my-game"`);
|
|
89
|
+
* unique per org.
|
|
90
|
+
* @returns The {@link App}, or `null` if no matching app exists.
|
|
91
|
+
* @throws {CrowdyGraphQLError} on transport/validation failures.
|
|
92
|
+
*/
|
|
93
|
+
appBySlug(orgSlug: string, appSlug: string): Promise<AppBySlugQuery['appBySlug']>;
|
|
94
|
+
/**
|
|
95
|
+
* List the apps the authenticated caller can see in their account: those owned
|
|
96
|
+
* by an org they are an active member of, OR those where they hold an active
|
|
97
|
+
* access grant. Includes apps of any visibility/status (e.g. accessible
|
|
98
|
+
* drafts), ordered newest-first. Requires authentication.
|
|
99
|
+
*
|
|
100
|
+
* @returns The caller's accessible {@link App}s (an empty array if none).
|
|
101
|
+
* @throws {CrowdyGraphQLError} `UNAUTHENTICATED` if the caller is not signed in.
|
|
102
|
+
*/
|
|
103
|
+
myApps(): Promise<MyAppsQuery['myApps']>;
|
|
104
|
+
/**
|
|
105
|
+
* Convenience wrapper over {@link app} that returns just the {@link AppRoute}
|
|
106
|
+
* routing tuple for an app — i.e. which game-api endpoint should serve it. If
|
|
107
|
+
* the app row is missing or the API does not expose the split-mode fields yet,
|
|
108
|
+
* returns a safe default (`{ appId, splitMode: false, deploymentTarget: null,
|
|
109
|
+
* gameApiUrl: null }`) so the caller keeps using the legacy single-endpoint
|
|
110
|
+
* deployment.
|
|
111
|
+
*
|
|
112
|
+
* @param appId - Numeric id of the app (`BigInt` as a decimal string).
|
|
113
|
+
* @returns The {@link AppRoute}; route gameplay to `gameApiUrl` when non-null,
|
|
114
|
+
* otherwise fall back to the constructor `httpUrl`.
|
|
115
|
+
* @throws {CrowdyGraphQLError} `UNAUTHENTICATED` (it calls {@link app} under
|
|
116
|
+
* the hood).
|
|
117
|
+
*/
|
|
118
|
+
routeFor(appId: string): Promise<AppRoute>;
|
|
119
|
+
/**
|
|
120
|
+
* List the apps owned by an organization (by org slug). Studio-admin read —
|
|
121
|
+
* requires the caller to be a member of the org.
|
|
122
|
+
*
|
|
123
|
+
* @param orgSlug - URL slug of the owning organization.
|
|
124
|
+
* @returns The org's {@link App}s.
|
|
125
|
+
* @throws {CrowdyGraphQLError} `UNAUTHENTICATED` / `FORBIDDEN`.
|
|
126
|
+
*/
|
|
127
|
+
forOrg(orgSlug: string): Promise<AppsForOrgQuery['appsForOrg']>;
|
|
128
|
+
/**
|
|
129
|
+
* List the public marketplace apps (LIVE + PUBLIC only) with offset
|
|
130
|
+
* pagination. **Public** — no session required.
|
|
131
|
+
*
|
|
132
|
+
* @param opts - Optional {@link AppMarketplaceFilterInput} `filter` and
|
|
133
|
+
* `limit` / `offset`.
|
|
134
|
+
* @returns A page of marketplace apps.
|
|
135
|
+
* @remarks Prefer {@link marketplaceConnection} (Relay cursor pagination) for
|
|
136
|
+
* large catalogs; the offset args here are deprecated server-side.
|
|
137
|
+
*/
|
|
138
|
+
marketplace(opts?: {
|
|
139
|
+
filter?: MarketplaceAppsQueryVariables['filter'];
|
|
140
|
+
limit?: MarketplaceAppsQueryVariables['limit'];
|
|
141
|
+
offset?: MarketplaceAppsQueryVariables['offset'];
|
|
142
|
+
}): Promise<MarketplaceAppsQuery['apps']>;
|
|
143
|
+
/**
|
|
144
|
+
* Relay-style cursor pagination over the public marketplace — the preferred
|
|
145
|
+
* alternative to {@link marketplace}. **Public.** See
|
|
146
|
+
* https://docs.crowdedkingdoms.com/overview/pagination.
|
|
147
|
+
*
|
|
148
|
+
* @param args - Optional `first`, `after`, and {@link AppMarketplaceFilterInput}.
|
|
149
|
+
* @returns An apps connection.
|
|
150
|
+
*/
|
|
151
|
+
marketplaceConnection(args?: AppsConnectionQueryVariables): Promise<AppsConnectionQuery['appsConnection']>;
|
|
152
|
+
/**
|
|
153
|
+
* Create a new app under an organization. Requires the `manage_apps` org
|
|
154
|
+
* permission. The new app auto-provisions an open-by-default access tier.
|
|
155
|
+
*
|
|
156
|
+
* @param input - {@link CreateAppInput}: `orgId`, `name`, `slug`, optional
|
|
157
|
+
* `description`/`visibility`/`metadata`.
|
|
158
|
+
* @returns The created {@link App}.
|
|
159
|
+
* @throws {CrowdyGraphQLError} `FORBIDDEN`/`SCOPE_MISSING` without
|
|
160
|
+
* `manage_apps`, or `BAD_USER_INPUT` (e.g. duplicate slug).
|
|
161
|
+
*/
|
|
162
|
+
create(input: CreateAppInput): Promise<CreateAppMutation['createApp']>;
|
|
163
|
+
/**
|
|
164
|
+
* Update an app's mutable fields. Requires the `manage_apps` app permission.
|
|
165
|
+
*
|
|
166
|
+
* @param appId - Numeric app id.
|
|
167
|
+
* @param input - {@link UpdateAppInput} fields to change.
|
|
168
|
+
* @returns The updated {@link App}.
|
|
169
|
+
* @throws {CrowdyGraphQLError} `FORBIDDEN`/`SCOPE_MISSING` without
|
|
170
|
+
* `manage_apps`.
|
|
171
|
+
*/
|
|
172
|
+
update(appId: string, input: UpdateAppInput): Promise<UpdateAppMutation['updateApp']>;
|
|
173
|
+
/**
|
|
174
|
+
* Archive (soft-delete) an app. Requires the `manage_apps` app permission.
|
|
175
|
+
*
|
|
176
|
+
* @param appId - Numeric app id.
|
|
177
|
+
* @returns The archived app's new status.
|
|
178
|
+
* @throws {CrowdyGraphQLError} `FORBIDDEN`/`SCOPE_MISSING` without
|
|
179
|
+
* `manage_apps`.
|
|
180
|
+
*/
|
|
181
|
+
archive(appId: string): Promise<ArchiveAppMutation['archiveApp']>;
|
|
182
|
+
/**
|
|
183
|
+
* Override an app's marketplace visibility. **Super-admin only.**
|
|
184
|
+
*
|
|
185
|
+
* @param appId - Numeric app id.
|
|
186
|
+
* @param visibility - The new {@link AppVisibility}.
|
|
187
|
+
* @returns The app's updated visibility.
|
|
188
|
+
* @throws {CrowdyGraphQLError} `FORBIDDEN` for non-super-admins.
|
|
189
|
+
*/
|
|
190
|
+
setVisibility(appId: string, visibility: AppVisibility): Promise<SetAppVisibilityMutation['setAppVisibility']>;
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=apps.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apps.d.ts","sourceRoot":"","sources":["../../src/domains/apps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAWL,KAAK,QAAQ,EAEb,KAAK,cAAc,EAEnB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,6BAA6B,EAClC,KAAK,mBAAmB,EACxB,KAAK,4BAA4B,EACjC,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC7B,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,yBAAyB,CAAC;AAEjC;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,4DAA4D;IAC5D,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC;;;;OAIG;IACH,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAgBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,qBAAa,OAAO;IACN,OAAO,CAAC,QAAQ,CAAC,UAAU;gBAAV,UAAU,EAAE,aAAa;IAEtD;;;;;;;;;OASG;IACG,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAQlD;;;;;;;;;;;;OAYG;IACG,SAAS,CACb,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;IAQvC;;;;;;;;OAQG;IACG,MAAM,IAAI,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IAQ9C;;;;;;;;;;;;;OAaG;IACG,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAYhD;;;;;;;OAOG;IACG,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;IAKrE;;;;;;;;;OASG;IACG,WAAW,CACf,IAAI,GAAE;QACJ,MAAM,CAAC,EAAE,6BAA6B,CAAC,QAAQ,CAAC,CAAC;QACjD,KAAK,CAAC,EAAE,6BAA6B,CAAC,OAAO,CAAC,CAAC;QAC/C,MAAM,CAAC,EAAE,6BAA6B,CAAC,QAAQ,CAAC,CAAC;KAC7C,GACL,OAAO,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAKxC;;;;;;;OAOG;IACG,qBAAqB,CACzB,IAAI,GAAE,4BAAiC,GACtC,OAAO,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,CAAC;IAKjD;;;;;;;;;OASG;IACG,MAAM,CACV,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAK1C;;;;;;;;OAQG;IACG,MAAM,CACV,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAQ1C;;;;;;;OAOG;IACG,OAAO,CACX,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC;IAK5C;;;;;;;OAOG;IACG,aAAa,CACjB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,aAAa,GACxB,OAAO,CAAC,wBAAwB,CAAC,kBAAkB,CAAC,CAAC;CAOzD"}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { AppDocument, AppBySlugDocument, MyAppsDocument, AppsForOrgDocument, MarketplaceAppsDocument, AppsConnectionDocument, CreateAppDocument, UpdateAppDocument, ArchiveAppDocument, SetAppVisibilityDocument, } from '../generated/graphql.js';
|
|
2
|
+
function appRouteFromAppRow(row) {
|
|
3
|
+
if (!row || typeof row !== 'object')
|
|
4
|
+
return null;
|
|
5
|
+
const r = row;
|
|
6
|
+
if (typeof r.appId !== 'string')
|
|
7
|
+
return null;
|
|
8
|
+
return {
|
|
9
|
+
appId: r.appId,
|
|
10
|
+
splitMode: typeof r.splitMode === 'boolean' ? r.splitMode : false,
|
|
11
|
+
deploymentTarget: typeof r.deploymentTarget === 'string' ? r.deploymentTarget : null,
|
|
12
|
+
gameApiUrl: typeof r.gameApiUrl === 'string' && r.gameApiUrl ? r.gameApiUrl : null,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* App discovery & game-api routing — exposed as `client.apps`.
|
|
17
|
+
*
|
|
18
|
+
* Targets the **management-api** (every call routes to `managementUrl`), where
|
|
19
|
+
* the apps catalog lives. After the database split an app may be served by its
|
|
20
|
+
* own per-tenant cks-game-api; the catalog returns each app's `gameApiUrl` so
|
|
21
|
+
* you can build a per-app `CrowdyClient` against the correct endpoint (see
|
|
22
|
+
* {@link routeFor} / {@link AppRoute}).
|
|
23
|
+
*
|
|
24
|
+
* Auth: {@link appBySlug} is **public** (no session; resolves unlisted or draft
|
|
25
|
+
* apps when the exact slugs are known). {@link app}, {@link myApps}, and
|
|
26
|
+
* {@link routeFor} require authentication (any signed-in user) and otherwise
|
|
27
|
+
* throw {@link CrowdyGraphQLError} with `UNAUTHENTICATED`; note {@link app} does
|
|
28
|
+
* not enforce org/app permissions. `BigInt` ids such as `appId` and `orgId` are
|
|
29
|
+
* decimal strings.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* const base = createCrowdyClient({
|
|
34
|
+
* managementUrl: 'https://api.example.com',
|
|
35
|
+
* httpUrl: 'https://legacy-game-api.example.com', // pre-split fallback
|
|
36
|
+
* });
|
|
37
|
+
* await base.auth.login({ email, password });
|
|
38
|
+
*
|
|
39
|
+
* const route = await base.apps.routeFor(appId);
|
|
40
|
+
* if (route.gameApiUrl) {
|
|
41
|
+
* // route gameplay to the app's resolved game-api endpoint
|
|
42
|
+
* const perAppClient = createCrowdyClient({
|
|
43
|
+
* managementUrl: 'https://api.example.com',
|
|
44
|
+
* httpUrl: route.gameApiUrl,
|
|
45
|
+
* wsUrl: route.gameApiUrl.replace(/^http/, 'ws'),
|
|
46
|
+
* tokenStore: base.session.tokenStore,
|
|
47
|
+
* });
|
|
48
|
+
* }
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export class AppsAPI {
|
|
52
|
+
constructor(management) {
|
|
53
|
+
this.management = management;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Fetch a single app by its numeric id. Requires authentication (any signed-in
|
|
57
|
+
* user); does **not** enforce org/app permissions, so it can read apps the
|
|
58
|
+
* caller does not own, of any visibility/status. Prefer {@link appBySlug} for
|
|
59
|
+
* slug-based marketplace lookups.
|
|
60
|
+
*
|
|
61
|
+
* @param appId - Numeric id of the app (`BigInt` as a decimal string).
|
|
62
|
+
* @returns The {@link App}, or `null` if the id does not exist.
|
|
63
|
+
* @throws {CrowdyGraphQLError} `UNAUTHENTICATED` if the caller is not signed in.
|
|
64
|
+
*/
|
|
65
|
+
async app(appId) {
|
|
66
|
+
const data = await this.management.request(AppDocument, { appId });
|
|
67
|
+
return data.app;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Look up a single app by its org slug + app slug (the marketplace URL path).
|
|
71
|
+
* **Public**: no authentication required, and not filtered by visibility or
|
|
72
|
+
* status — it can resolve unlisted or draft apps when the exact slugs are
|
|
73
|
+
* known.
|
|
74
|
+
*
|
|
75
|
+
* @param orgSlug - URL slug of the owning organization (e.g. `"acme"` in the
|
|
76
|
+
* path `/acme/my-game`).
|
|
77
|
+
* @param appSlug - URL slug of the app within the org (e.g. `"my-game"`);
|
|
78
|
+
* unique per org.
|
|
79
|
+
* @returns The {@link App}, or `null` if no matching app exists.
|
|
80
|
+
* @throws {CrowdyGraphQLError} on transport/validation failures.
|
|
81
|
+
*/
|
|
82
|
+
async appBySlug(orgSlug, appSlug) {
|
|
83
|
+
const data = await this.management.request(AppBySlugDocument, { orgSlug, appSlug });
|
|
84
|
+
return data.appBySlug;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* List the apps the authenticated caller can see in their account: those owned
|
|
88
|
+
* by an org they are an active member of, OR those where they hold an active
|
|
89
|
+
* access grant. Includes apps of any visibility/status (e.g. accessible
|
|
90
|
+
* drafts), ordered newest-first. Requires authentication.
|
|
91
|
+
*
|
|
92
|
+
* @returns The caller's accessible {@link App}s (an empty array if none).
|
|
93
|
+
* @throws {CrowdyGraphQLError} `UNAUTHENTICATED` if the caller is not signed in.
|
|
94
|
+
*/
|
|
95
|
+
async myApps() {
|
|
96
|
+
const data = await this.management.request(MyAppsDocument, {});
|
|
97
|
+
return data.myApps;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Convenience wrapper over {@link app} that returns just the {@link AppRoute}
|
|
101
|
+
* routing tuple for an app — i.e. which game-api endpoint should serve it. If
|
|
102
|
+
* the app row is missing or the API does not expose the split-mode fields yet,
|
|
103
|
+
* returns a safe default (`{ appId, splitMode: false, deploymentTarget: null,
|
|
104
|
+
* gameApiUrl: null }`) so the caller keeps using the legacy single-endpoint
|
|
105
|
+
* deployment.
|
|
106
|
+
*
|
|
107
|
+
* @param appId - Numeric id of the app (`BigInt` as a decimal string).
|
|
108
|
+
* @returns The {@link AppRoute}; route gameplay to `gameApiUrl` when non-null,
|
|
109
|
+
* otherwise fall back to the constructor `httpUrl`.
|
|
110
|
+
* @throws {CrowdyGraphQLError} `UNAUTHENTICATED` (it calls {@link app} under
|
|
111
|
+
* the hood).
|
|
112
|
+
*/
|
|
113
|
+
async routeFor(appId) {
|
|
114
|
+
const row = await this.app(appId);
|
|
115
|
+
return (appRouteFromAppRow(row) ?? {
|
|
116
|
+
appId,
|
|
117
|
+
splitMode: false,
|
|
118
|
+
deploymentTarget: null,
|
|
119
|
+
gameApiUrl: null,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* List the apps owned by an organization (by org slug). Studio-admin read —
|
|
124
|
+
* requires the caller to be a member of the org.
|
|
125
|
+
*
|
|
126
|
+
* @param orgSlug - URL slug of the owning organization.
|
|
127
|
+
* @returns The org's {@link App}s.
|
|
128
|
+
* @throws {CrowdyGraphQLError} `UNAUTHENTICATED` / `FORBIDDEN`.
|
|
129
|
+
*/
|
|
130
|
+
async forOrg(orgSlug) {
|
|
131
|
+
const data = await this.management.request(AppsForOrgDocument, { orgSlug });
|
|
132
|
+
return data.appsForOrg;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* List the public marketplace apps (LIVE + PUBLIC only) with offset
|
|
136
|
+
* pagination. **Public** — no session required.
|
|
137
|
+
*
|
|
138
|
+
* @param opts - Optional {@link AppMarketplaceFilterInput} `filter` and
|
|
139
|
+
* `limit` / `offset`.
|
|
140
|
+
* @returns A page of marketplace apps.
|
|
141
|
+
* @remarks Prefer {@link marketplaceConnection} (Relay cursor pagination) for
|
|
142
|
+
* large catalogs; the offset args here are deprecated server-side.
|
|
143
|
+
*/
|
|
144
|
+
async marketplace(opts = {}) {
|
|
145
|
+
const data = await this.management.request(MarketplaceAppsDocument, opts);
|
|
146
|
+
return data.apps;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Relay-style cursor pagination over the public marketplace — the preferred
|
|
150
|
+
* alternative to {@link marketplace}. **Public.** See
|
|
151
|
+
* https://docs.crowdedkingdoms.com/overview/pagination.
|
|
152
|
+
*
|
|
153
|
+
* @param args - Optional `first`, `after`, and {@link AppMarketplaceFilterInput}.
|
|
154
|
+
* @returns An apps connection.
|
|
155
|
+
*/
|
|
156
|
+
async marketplaceConnection(args = {}) {
|
|
157
|
+
const data = await this.management.request(AppsConnectionDocument, args);
|
|
158
|
+
return data.appsConnection;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Create a new app under an organization. Requires the `manage_apps` org
|
|
162
|
+
* permission. The new app auto-provisions an open-by-default access tier.
|
|
163
|
+
*
|
|
164
|
+
* @param input - {@link CreateAppInput}: `orgId`, `name`, `slug`, optional
|
|
165
|
+
* `description`/`visibility`/`metadata`.
|
|
166
|
+
* @returns The created {@link App}.
|
|
167
|
+
* @throws {CrowdyGraphQLError} `FORBIDDEN`/`SCOPE_MISSING` without
|
|
168
|
+
* `manage_apps`, or `BAD_USER_INPUT` (e.g. duplicate slug).
|
|
169
|
+
*/
|
|
170
|
+
async create(input) {
|
|
171
|
+
const data = await this.management.request(CreateAppDocument, { input });
|
|
172
|
+
return data.createApp;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Update an app's mutable fields. Requires the `manage_apps` app permission.
|
|
176
|
+
*
|
|
177
|
+
* @param appId - Numeric app id.
|
|
178
|
+
* @param input - {@link UpdateAppInput} fields to change.
|
|
179
|
+
* @returns The updated {@link App}.
|
|
180
|
+
* @throws {CrowdyGraphQLError} `FORBIDDEN`/`SCOPE_MISSING` without
|
|
181
|
+
* `manage_apps`.
|
|
182
|
+
*/
|
|
183
|
+
async update(appId, input) {
|
|
184
|
+
const data = await this.management.request(UpdateAppDocument, {
|
|
185
|
+
appId,
|
|
186
|
+
input,
|
|
187
|
+
});
|
|
188
|
+
return data.updateApp;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Archive (soft-delete) an app. Requires the `manage_apps` app permission.
|
|
192
|
+
*
|
|
193
|
+
* @param appId - Numeric app id.
|
|
194
|
+
* @returns The archived app's new status.
|
|
195
|
+
* @throws {CrowdyGraphQLError} `FORBIDDEN`/`SCOPE_MISSING` without
|
|
196
|
+
* `manage_apps`.
|
|
197
|
+
*/
|
|
198
|
+
async archive(appId) {
|
|
199
|
+
const data = await this.management.request(ArchiveAppDocument, { appId });
|
|
200
|
+
return data.archiveApp;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Override an app's marketplace visibility. **Super-admin only.**
|
|
204
|
+
*
|
|
205
|
+
* @param appId - Numeric app id.
|
|
206
|
+
* @param visibility - The new {@link AppVisibility}.
|
|
207
|
+
* @returns The app's updated visibility.
|
|
208
|
+
* @throws {CrowdyGraphQLError} `FORBIDDEN` for non-super-admins.
|
|
209
|
+
*/
|
|
210
|
+
async setVisibility(appId, visibility) {
|
|
211
|
+
const data = await this.management.request(SetAppVisibilityDocument, {
|
|
212
|
+
appId,
|
|
213
|
+
visibility,
|
|
214
|
+
});
|
|
215
|
+
return data.setAppVisibility;
|
|
216
|
+
}
|
|
217
|
+
}
|