@crowdedkingdoms/crowdyjs 18.10.0 → 18.12.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 +69 -0
- package/README.md +91 -30
- package/dist/crowdy-client.d.ts +11 -3
- package/dist/crowdy-client.d.ts.map +1 -1
- package/dist/crowdy-client.js +25 -4
- 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/exec.d.ts +6 -0
- package/dist/domains/exec.d.ts.map +1 -1
- package/dist/domains/exec.js +28 -2
- package/dist/generated/graphql-schema.d.ts +1 -1
- package/dist/generated/graphql-schema.d.ts.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/kit/index.d.ts +22 -2
- package/dist/kit/index.d.ts.map +1 -1
- package/dist/kit/index.js +22 -2
- package/dist/kit/kit.d.ts +141 -7
- package/dist/kit/kit.d.ts.map +1 -1
- package/dist/kit/kit.js +138 -4
- package/dist/kit/mirror.d.ts +111 -0
- package/dist/kit/mirror.d.ts.map +1 -0
- package/dist/kit/mirror.js +295 -0
- package/dist/kit/modules/arenas.d.ts +87 -0
- package/dist/kit/modules/arenas.d.ts.map +1 -0
- package/dist/kit/modules/arenas.js +66 -0
- package/dist/kit/modules/encounters.d.ts +75 -0
- package/dist/kit/modules/encounters.d.ts.map +1 -0
- package/dist/kit/modules/encounters.js +57 -0
- package/dist/kit/modules/instances.d.ts +78 -0
- package/dist/kit/modules/instances.d.ts.map +1 -0
- package/dist/kit/modules/instances.js +72 -0
- package/dist/kit/modules/leaderboards.d.ts +79 -0
- package/dist/kit/modules/leaderboards.d.ts.map +1 -0
- package/dist/kit/modules/leaderboards.js +69 -0
- package/dist/kit/modules/matchmaking.d.ts +107 -0
- package/dist/kit/modules/matchmaking.d.ts.map +1 -0
- package/dist/kit/modules/matchmaking.js +109 -0
- package/dist/kit/modules/minigames.d.ts +59 -0
- package/dist/kit/modules/minigames.d.ts.map +1 -0
- package/dist/kit/modules/minigames.js +55 -0
- package/dist/kit/modules/npcs.d.ts +80 -0
- package/dist/kit/modules/npcs.d.ts.map +1 -0
- package/dist/kit/modules/npcs.js +102 -0
- package/dist/kit/modules/presence.d.ts +81 -0
- package/dist/kit/modules/presence.d.ts.map +1 -0
- package/dist/kit/modules/presence.js +99 -0
- package/dist/kit/modules/racing.d.ts +131 -0
- package/dist/kit/modules/racing.d.ts.map +1 -0
- package/dist/kit/modules/racing.js +113 -0
- package/dist/kit/modules/sessions.d.ts +91 -0
- package/dist/kit/modules/sessions.d.ts.map +1 -0
- package/dist/kit/modules/sessions.js +84 -0
- package/dist/kit/modules/tables.d.ts +76 -0
- package/dist/kit/modules/tables.d.ts.map +1 -0
- package/dist/kit/modules/tables.js +73 -0
- package/dist/kit/modules/tactics.d.ts +79 -0
- package/dist/kit/modules/tactics.d.ts.map +1 -0
- package/dist/kit/modules/tactics.js +67 -0
- package/dist/kit/modules/territory.d.ts +92 -0
- package/dist/kit/modules/territory.d.ts.map +1 -0
- package/dist/kit/modules/territory.js +84 -0
- package/dist/kit/modules/world.d.ts +69 -0
- package/dist/kit/modules/world.d.ts.map +1 -0
- package/dist/kit/modules/world.js +35 -0
- package/dist/kit/protocol.d.ts +128 -0
- package/dist/kit/protocol.d.ts.map +1 -0
- package/dist/kit/protocol.js +171 -0
- package/dist/kit/realtime.d.ts +72 -0
- package/dist/kit/realtime.d.ts.map +1 -0
- package/dist/kit/realtime.js +108 -0
- package/dist/kit/runtime.d.ts +90 -0
- package/dist/kit/runtime.d.ts.map +1 -0
- package/dist/kit/runtime.js +194 -0
- package/dist/kit/store.d.ts +20 -0
- package/dist/kit/store.d.ts.map +1 -0
- package/dist/kit/store.js +25 -0
- package/dist/kit/topology.d.ts +69 -0
- package/dist/kit/topology.d.ts.map +1 -0
- package/dist/kit/topology.js +156 -0
- package/dist/kit/wire.d.ts +45 -5
- package/dist/kit/wire.d.ts.map +1 -1
- package/dist/kit/wire.js +51 -5
- package/dist/live-coding/assets/browser-authoring-index.json +1 -1
- package/dist/live-coding/assets/manifest.json +1 -1
- package/dist/live-coding/browser-authoring-index.generated.d.ts.map +1 -1
- package/dist/live-coding/browser-authoring-index.generated.js +5092 -45
- package/package.json +1 -1
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What kit hubs show players near them through the realtime tier (UDP), decoded for World
|
|
3
|
+
* Stores: server-driven actors (mobs, NPCs, pets, a ball) and server events.
|
|
4
|
+
*
|
|
5
|
+
* A server-driven actor's state is {@link KitActorState} as MessagePack (`ckx_sdk::kit::wire`
|
|
6
|
+
* `ActorState`). A server event is an `eventType` from the registry in `wire.ts` with a JSON
|
|
7
|
+
* body; `ServerEventNotification.state` is that body, base64.
|
|
8
|
+
*/
|
|
9
|
+
import { type StateCodec } from '../stores/codec.js';
|
|
10
|
+
/** A server-driven actor as a kit hub shows it. */
|
|
11
|
+
export interface KitActorState {
|
|
12
|
+
/** What it is: `mob`, `npc`, `pet`, `ball`, `ghost`, or a game's own word. */
|
|
13
|
+
kind: string;
|
|
14
|
+
/** Its id within the hub that shows it. */
|
|
15
|
+
id: number;
|
|
16
|
+
/** Where it is, in chunks. */
|
|
17
|
+
x: number;
|
|
18
|
+
y: number;
|
|
19
|
+
z: number;
|
|
20
|
+
hp: number | null;
|
|
21
|
+
max_hp?: number;
|
|
22
|
+
mode?: string;
|
|
23
|
+
/** The player it belongs to (a pet, a summon). */
|
|
24
|
+
owner?: number;
|
|
25
|
+
yaw?: number;
|
|
26
|
+
name?: string;
|
|
27
|
+
}
|
|
28
|
+
/** Whether a decoded value is a kit actor's state. */
|
|
29
|
+
export declare function isKitActorState(value: unknown): value is KitActorState;
|
|
30
|
+
/** A kit actor's state from its MessagePack bytes, or null when they are not one. */
|
|
31
|
+
export declare function decodeKitActorState(bytes: Uint8Array): KitActorState | null;
|
|
32
|
+
/**
|
|
33
|
+
* A {@link StateCodec} for the actors kit hubs show, for `createWorldSession`'s `actors`
|
|
34
|
+
* config. A state that is not a kit actor's decodes to null (a player's, say).
|
|
35
|
+
*/
|
|
36
|
+
export declare const kitActorCodec: StateCodec<KitActorState | null>;
|
|
37
|
+
/** A player's actor in a world with kit hubs, with the game's own state. */
|
|
38
|
+
export interface KitPlayerActor<P> {
|
|
39
|
+
kind: 'player';
|
|
40
|
+
player: P;
|
|
41
|
+
}
|
|
42
|
+
/** A remote actor in a world with kit hubs: a player's, or a server-driven one. */
|
|
43
|
+
export type KitWorldActor<P> = KitPlayerActor<P> | KitActorState;
|
|
44
|
+
/** Whether a remote actor is a player's (rather than one a hub shows). */
|
|
45
|
+
export declare function isKitPlayerActor<P>(actor: KitWorldActor<P>): actor is KitPlayerActor<P>;
|
|
46
|
+
/**
|
|
47
|
+
* One codec for a world where players and kit hubs both show actors: a kit actor's state
|
|
48
|
+
* decodes as itself, anything else through `playerCodec` as `{ kind: 'player', player }`.
|
|
49
|
+
* A game's own player state must not be a MessagePack map with `kind`, `id`, `x` and `z`.
|
|
50
|
+
*/
|
|
51
|
+
export declare function withKitActors<P>(playerCodec: StateCodec<P>): StateCodec<KitWorldActor<P>>;
|
|
52
|
+
/**
|
|
53
|
+
* Lane predicates for `createWorldSession`'s `actors.lanes` with {@link withKitActors}:
|
|
54
|
+
* `players`, `mobs`, `npcs`, `pets`, and `others` for any other kind a hub shows.
|
|
55
|
+
*/
|
|
56
|
+
export declare function kitActorLanes<P>(): Record<'players' | 'mobs' | 'npcs' | 'pets' | 'others', (a: KitWorldActor<P>) => boolean>;
|
|
57
|
+
/** The event types of the kit's registry, each with the JSON codec its body takes. */
|
|
58
|
+
export declare const KIT_EVENT_TYPES: readonly number[];
|
|
59
|
+
/** Codecs for World Stores' `EventRouter`, one per kit event type: the bodies are JSON. */
|
|
60
|
+
export declare function kitEventCodecs(): Map<number, StateCodec<Record<string, unknown>>>;
|
|
61
|
+
/**
|
|
62
|
+
* A server event a kit hub sent, from its notification (`eventType` and the base64 `state`),
|
|
63
|
+
* or null when the body is not JSON.
|
|
64
|
+
*/
|
|
65
|
+
export declare function parseKitServerEvent(notification: {
|
|
66
|
+
eventType: number;
|
|
67
|
+
state: string;
|
|
68
|
+
}): {
|
|
69
|
+
eventType: number;
|
|
70
|
+
body: Record<string, unknown>;
|
|
71
|
+
} | null;
|
|
72
|
+
//# sourceMappingURL=realtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realtime.d.ts","sourceRoot":"","sources":["../../src/kit/realtime.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAa,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAkBhE,mDAAmD;AACnD,MAAM,WAAW,aAAa;IAC5B,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,EAAE,EAAE,MAAM,CAAC;IACX,8BAA8B;IAC9B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,sDAAsD;AACtD,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAItE;AAED,qFAAqF;AACrF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG,aAAa,GAAG,IAAI,CAQ3E;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,UAAU,CAAC,aAAa,GAAG,IAAI,CAG1D,CAAC;AAEF,4EAA4E;AAC5E,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,CAAC,CAAC;CACX;AAED,mFAAmF;AACnF,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC;AAEjE,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,cAAc,CAAC,CAAC,CAAC,CAEvF;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAQzF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,KAAK,MAAM,CAAC,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,EAAE,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAS5H;AAED,sFAAsF;AACtF,eAAO,MAAM,eAAe,EAAE,SAAS,MAAM,EAc5C,CAAC;AAEF,2FAA2F;AAC3F,wBAAgB,cAAc,IAAI,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAGjF;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAAG,IAAI,CAS9D"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What kit hubs show players near them through the realtime tier (UDP), decoded for World
|
|
3
|
+
* Stores: server-driven actors (mobs, NPCs, pets, a ball) and server events.
|
|
4
|
+
*
|
|
5
|
+
* A server-driven actor's state is {@link KitActorState} as MessagePack (`ckx_sdk::kit::wire`
|
|
6
|
+
* `ActorState`). A server event is an `eventType` from the registry in `wire.ts` with a JSON
|
|
7
|
+
* body; `ServerEventNotification.state` is that body, base64.
|
|
8
|
+
*/
|
|
9
|
+
import { decode, encode } from '@msgpack/msgpack';
|
|
10
|
+
import { jsonCodec } from '../stores/codec.js';
|
|
11
|
+
import { decodeBase64, encodeBase64 } from '../utils.js';
|
|
12
|
+
import { EVENT_ABILITY, EVENT_CONTACT_DAMAGE, EVENT_CONTROL_POINT, EVENT_EMOTE, EVENT_ENCOUNTER, EVENT_MOVEMENT_VIOLATION, EVENT_POSSESSION, EVENT_PROPOSAL, EVENT_RACE_TIMING, EVENT_SCORE, EVENT_TURN, EVENT_WEATHER, EVENT_ZONE_CHANGE, } from './wire.js';
|
|
13
|
+
/** Whether a decoded value is a kit actor's state. */
|
|
14
|
+
export function isKitActorState(value) {
|
|
15
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
16
|
+
return false;
|
|
17
|
+
const v = value;
|
|
18
|
+
return typeof v.kind === 'string' && typeof v.id === 'number' && typeof v.x === 'number' && typeof v.z === 'number';
|
|
19
|
+
}
|
|
20
|
+
/** A kit actor's state from its MessagePack bytes, or null when they are not one. */
|
|
21
|
+
export function decodeKitActorState(bytes) {
|
|
22
|
+
try {
|
|
23
|
+
const v = decode(bytes);
|
|
24
|
+
if (!isKitActorState(v))
|
|
25
|
+
return null;
|
|
26
|
+
return { ...v, y: typeof v.y === 'number' ? v.y : 0, hp: typeof v.hp === 'number' ? v.hp : null };
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* A {@link StateCodec} for the actors kit hubs show, for `createWorldSession`'s `actors`
|
|
34
|
+
* config. A state that is not a kit actor's decodes to null (a player's, say).
|
|
35
|
+
*/
|
|
36
|
+
export const kitActorCodec = {
|
|
37
|
+
encode: (state) => encodeBase64(state ? encode(state) : new Uint8Array()),
|
|
38
|
+
decode: (data) => (data ? decodeKitActorState(decodeBase64(data)) : null),
|
|
39
|
+
};
|
|
40
|
+
/** Whether a remote actor is a player's (rather than one a hub shows). */
|
|
41
|
+
export function isKitPlayerActor(actor) {
|
|
42
|
+
return actor.kind === 'player' && 'player' in actor;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* One codec for a world where players and kit hubs both show actors: a kit actor's state
|
|
46
|
+
* decodes as itself, anything else through `playerCodec` as `{ kind: 'player', player }`.
|
|
47
|
+
* A game's own player state must not be a MessagePack map with `kind`, `id`, `x` and `z`.
|
|
48
|
+
*/
|
|
49
|
+
export function withKitActors(playerCodec) {
|
|
50
|
+
return {
|
|
51
|
+
encode: (actor) => (isKitPlayerActor(actor) ? playerCodec.encode(actor.player) : kitActorCodec.encode(actor)),
|
|
52
|
+
decode: (data) => {
|
|
53
|
+
const kit = data ? decodeKitActorState(decodeBase64(data)) : null;
|
|
54
|
+
return kit ?? { kind: 'player', player: playerCodec.decode(data) };
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Lane predicates for `createWorldSession`'s `actors.lanes` with {@link withKitActors}:
|
|
60
|
+
* `players`, `mobs`, `npcs`, `pets`, and `others` for any other kind a hub shows.
|
|
61
|
+
*/
|
|
62
|
+
export function kitActorLanes() {
|
|
63
|
+
const known = new Set(['player', 'mob', 'npc', 'pet']);
|
|
64
|
+
return {
|
|
65
|
+
players: (a) => a.kind === 'player',
|
|
66
|
+
mobs: (a) => a.kind === 'mob',
|
|
67
|
+
npcs: (a) => a.kind === 'npc',
|
|
68
|
+
pets: (a) => a.kind === 'pet',
|
|
69
|
+
others: (a) => !known.has(a.kind),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/** The event types of the kit's registry, each with the JSON codec its body takes. */
|
|
73
|
+
export const KIT_EVENT_TYPES = [
|
|
74
|
+
EVENT_CONTACT_DAMAGE,
|
|
75
|
+
EVENT_WEATHER,
|
|
76
|
+
EVENT_TURN,
|
|
77
|
+
EVENT_SCORE,
|
|
78
|
+
EVENT_PROPOSAL,
|
|
79
|
+
EVENT_ABILITY,
|
|
80
|
+
EVENT_MOVEMENT_VIOLATION,
|
|
81
|
+
EVENT_CONTROL_POINT,
|
|
82
|
+
EVENT_RACE_TIMING,
|
|
83
|
+
EVENT_ZONE_CHANGE,
|
|
84
|
+
EVENT_ENCOUNTER,
|
|
85
|
+
EVENT_POSSESSION,
|
|
86
|
+
EVENT_EMOTE,
|
|
87
|
+
];
|
|
88
|
+
/** Codecs for World Stores' `EventRouter`, one per kit event type: the bodies are JSON. */
|
|
89
|
+
export function kitEventCodecs() {
|
|
90
|
+
const codec = jsonCodec();
|
|
91
|
+
return new Map(KIT_EVENT_TYPES.map((t) => [t, codec]));
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* A server event a kit hub sent, from its notification (`eventType` and the base64 `state`),
|
|
95
|
+
* or null when the body is not JSON.
|
|
96
|
+
*/
|
|
97
|
+
export function parseKitServerEvent(notification) {
|
|
98
|
+
try {
|
|
99
|
+
const text = new TextDecoder().decode(decodeBase64(notification.state));
|
|
100
|
+
const body = text ? JSON.parse(text) : {};
|
|
101
|
+
if (!body || typeof body !== 'object' || Array.isArray(body))
|
|
102
|
+
return null;
|
|
103
|
+
return { eventType: notification.eventType, body: body };
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { type ExecAPI, type ExecConnectOptions, type ExecConnection, type ExecPushHandler } from '../domains/exec.js';
|
|
2
|
+
/** Subscriptions one connection holds at most (the gateway refuses the next). */
|
|
3
|
+
export declare const KIT_SUBSCRIPTIONS_MAX = 256;
|
|
4
|
+
/** How a {@link KitRuntime} reaches the app's hubs. */
|
|
5
|
+
export interface KitRuntimeOptions {
|
|
6
|
+
/** Use this connection rather than opening one. The kit does not close it. */
|
|
7
|
+
connection?: ExecConnection;
|
|
8
|
+
/** How the kit opens its connection: affinity (`nodeType`, `key`), timeouts, a WebSocket. */
|
|
9
|
+
connect?: ExecConnectOptions;
|
|
10
|
+
/**
|
|
11
|
+
* Connect as one of the app's developers (`exec.connectAsDeveloper`, the org's
|
|
12
|
+
* `manage_compute`, an identity session rather than an app token): what admin endpoints
|
|
13
|
+
* (`configure`, `schedule`, ...) need.
|
|
14
|
+
*/
|
|
15
|
+
developer?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Calls, subscriptions and unsubscriptions the kit sends in one window at most. The gateway
|
|
18
|
+
* takes 120 per 10 s from a player and refuses the rest `Busy`; the default, 100, keeps the
|
|
19
|
+
* kit under it with room for the game's own calls.
|
|
20
|
+
*/
|
|
21
|
+
callBudget?: number;
|
|
22
|
+
/** The budget's window, in milliseconds. Default 10 000. */
|
|
23
|
+
budgetWindowMs?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Times a call is sent again when it did not run (`Busy`, `RateLimited`), or, when it
|
|
26
|
+
* carries an action id, after an unknown outcome (`DeadlineExceeded`, `Unavailable`,
|
|
27
|
+
* `Moved`). Default 2.
|
|
28
|
+
*/
|
|
29
|
+
retries?: number;
|
|
30
|
+
/** The player's id, to match `changed` messages; asked of `users.me` when absent. */
|
|
31
|
+
playerId?: string | number;
|
|
32
|
+
}
|
|
33
|
+
/** Per call: the action id, and the reply timeout. */
|
|
34
|
+
export interface KitCallOptions {
|
|
35
|
+
/**
|
|
36
|
+
* Send an `action_id` so a resend is answered once: `true` for a fresh one, or the id to
|
|
37
|
+
* use (for a deliberate retry of an earlier attempt).
|
|
38
|
+
*/
|
|
39
|
+
action?: boolean | string;
|
|
40
|
+
/** How long to wait for the reply, in milliseconds (the connection's default otherwise). */
|
|
41
|
+
timeoutMs?: number;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The kit's way to the app's hubs: one {@link ExecConnection} shared by every kit module,
|
|
45
|
+
* opened when first needed. It paces what it sends to a budget below the gateway's limit,
|
|
46
|
+
* sends a call again when that is safe (it did not run, or it carries an action id the hub
|
|
47
|
+
* answers once), counts subscriptions under the gateway's cap, and turns a hub's coded
|
|
48
|
+
* refusal into a {@link KitError}.
|
|
49
|
+
*/
|
|
50
|
+
export declare class KitRuntime {
|
|
51
|
+
readonly appId: string;
|
|
52
|
+
private readonly exec;
|
|
53
|
+
private readonly options;
|
|
54
|
+
private readonly whoAmI?;
|
|
55
|
+
private conn;
|
|
56
|
+
private connecting;
|
|
57
|
+
private ended;
|
|
58
|
+
private readonly budget;
|
|
59
|
+
private readonly retries;
|
|
60
|
+
private readonly subs;
|
|
61
|
+
private readonly reconnectListeners;
|
|
62
|
+
private readonly endedListeners;
|
|
63
|
+
private me;
|
|
64
|
+
constructor(appId: string, exec: ExecAPI | undefined, options?: KitRuntimeOptions, whoAmI?: (() => Promise<string | null>) | undefined);
|
|
65
|
+
/** The connection, opened on first use. */
|
|
66
|
+
connection(): Promise<ExecConnection>;
|
|
67
|
+
private open;
|
|
68
|
+
/** The player's id, from the options or `users.me`; null when neither knows it. */
|
|
69
|
+
playerId(): Promise<string | null>;
|
|
70
|
+
/**
|
|
71
|
+
* Calls a hub's endpoint, `args` as MessagePack, and returns the decoded reply.
|
|
72
|
+
* @throws {KitError} for a hub's coded refusal; {@link CrowdyExecError} for the platform's.
|
|
73
|
+
*/
|
|
74
|
+
call<T = unknown>(nodeType: string, key: string, method: string, args?: unknown, options?: KitCallOptions): Promise<T>;
|
|
75
|
+
/**
|
|
76
|
+
* Receives what a hub publishes on `topic`. Returns the function that stops this handler
|
|
77
|
+
* (and the subscription with the last one).
|
|
78
|
+
* @throws {KitError} `limit` past {@link KIT_SUBSCRIPTIONS_MAX} subscriptions.
|
|
79
|
+
*/
|
|
80
|
+
subscribe<T = unknown>(nodeType: string, key: string, topic: string, onPush: ExecPushHandler<T>): Promise<() => Promise<void>>;
|
|
81
|
+
/** How many distinct topics the kit subscribes to. */
|
|
82
|
+
get subscriptions(): number;
|
|
83
|
+
/** Called with the new host after the connection reconnects; kit mirrors resync then. */
|
|
84
|
+
onReconnect(listener: (host: string) => void): () => void;
|
|
85
|
+
/** Called once when the player's access ended (close code 4403); nothing reconnects. */
|
|
86
|
+
onAccessEnded(listener: (reason: string) => void): () => void;
|
|
87
|
+
/** Closes the connection the kit opened (not one it was given). */
|
|
88
|
+
close(): void;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/kit/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,OAAO,EACZ,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,eAAe,EACrB,MAAM,oBAAoB,CAAC;AAG5B,iFAAiF;AACjF,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC,uDAAuD;AACvD,MAAM,WAAW,iBAAiB;IAChC,8EAA8E;IAC9E,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,6FAA6F;IAC7F,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qFAAqF;IACrF,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5B;AAED,sDAAsD;AACtD,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC1B,4FAA4F;IAC5F,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA8CD;;;;;;GAMG;AACH,qBAAa,UAAU;IAYnB,QAAQ,CAAC,KAAK,EAAE,MAAM;IACtB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IAd1B,OAAO,CAAC,IAAI,CAA+B;IAC3C,OAAO,CAAC,UAAU,CAAwC;IAC1D,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA6B;IAClD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAqC;IACxE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAuC;IACtE,OAAO,CAAC,EAAE,CAAuC;gBAGtC,KAAK,EAAE,MAAM,EACL,IAAI,EAAE,OAAO,GAAG,SAAS,EACzB,OAAO,GAAE,iBAAsB,EAC/B,MAAM,CAAC,GAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,aAAA;IAMxD,2CAA2C;IACrC,UAAU,IAAI,OAAO,CAAC,cAAc,CAAC;YAY7B,IAAI;IAmBlB,mFAAmF;IAC7E,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAQxC;;;OAGG;IACG,IAAI,CAAC,CAAC,GAAG,OAAO,EACpB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,OAAO,EACd,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,CAAC,CAAC;IA2Bb;;;;OAIG;IACG,SAAS,CAAC,CAAC,GAAG,OAAO,EACzB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,GACzB,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IA2B/B,sDAAsD;IACtD,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED,yFAAyF;IACzF,WAAW,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI;IAKzD,wFAAwF;IACxF,aAAa,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI;IAK7D,mEAAmE;IACnE,KAAK,IAAI,IAAI;CAMd"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { CrowdyExecError, } from '../domains/exec.js';
|
|
2
|
+
import { KitError, newActionId, withActionId } from './protocol.js';
|
|
3
|
+
/** Subscriptions one connection holds at most (the gateway refuses the next). */
|
|
4
|
+
export const KIT_SUBSCRIPTIONS_MAX = 256;
|
|
5
|
+
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
6
|
+
/** A token bucket: `capacity` tokens a window, refilled continuously. */
|
|
7
|
+
class Budget {
|
|
8
|
+
constructor(capacity, windowMs) {
|
|
9
|
+
this.capacity = capacity;
|
|
10
|
+
this.windowMs = windowMs;
|
|
11
|
+
this.last = Date.now();
|
|
12
|
+
this.blockedUntil = 0;
|
|
13
|
+
this.tokens = capacity;
|
|
14
|
+
}
|
|
15
|
+
refill() {
|
|
16
|
+
const now = Date.now();
|
|
17
|
+
this.tokens = Math.min(this.capacity, this.tokens + ((now - this.last) * this.capacity) / this.windowMs);
|
|
18
|
+
this.last = now;
|
|
19
|
+
}
|
|
20
|
+
async take() {
|
|
21
|
+
for (;;) {
|
|
22
|
+
const wait = this.blockedUntil - Date.now();
|
|
23
|
+
if (wait > 0) {
|
|
24
|
+
await sleep(wait);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
this.refill();
|
|
28
|
+
if (this.tokens >= 1) {
|
|
29
|
+
this.tokens -= 1;
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
await sleep(Math.ceil(((1 - this.tokens) * this.windowMs) / this.capacity));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/** The gateway said to wait: nothing is sent until `ms` from now. */
|
|
36
|
+
hold(ms) {
|
|
37
|
+
this.blockedUntil = Math.max(this.blockedUntil, Date.now() + ms);
|
|
38
|
+
this.tokens = 0;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The kit's way to the app's hubs: one {@link ExecConnection} shared by every kit module,
|
|
43
|
+
* opened when first needed. It paces what it sends to a budget below the gateway's limit,
|
|
44
|
+
* sends a call again when that is safe (it did not run, or it carries an action id the hub
|
|
45
|
+
* answers once), counts subscriptions under the gateway's cap, and turns a hub's coded
|
|
46
|
+
* refusal into a {@link KitError}.
|
|
47
|
+
*/
|
|
48
|
+
export class KitRuntime {
|
|
49
|
+
constructor(appId, exec, options = {}, whoAmI) {
|
|
50
|
+
this.appId = appId;
|
|
51
|
+
this.exec = exec;
|
|
52
|
+
this.options = options;
|
|
53
|
+
this.whoAmI = whoAmI;
|
|
54
|
+
this.conn = null;
|
|
55
|
+
this.connecting = null;
|
|
56
|
+
this.ended = null;
|
|
57
|
+
this.subs = new Map();
|
|
58
|
+
this.reconnectListeners = new Set();
|
|
59
|
+
this.endedListeners = new Set();
|
|
60
|
+
this.me = null;
|
|
61
|
+
this.budget = new Budget(Math.max(1, options.callBudget ?? 100), Math.max(1, options.budgetWindowMs ?? 10000));
|
|
62
|
+
this.retries = Math.max(0, options.retries ?? 2);
|
|
63
|
+
}
|
|
64
|
+
/** The connection, opened on first use. */
|
|
65
|
+
async connection() {
|
|
66
|
+
if (this.ended !== null)
|
|
67
|
+
throw new CrowdyExecError('Denied', `access ended: ${this.ended}`);
|
|
68
|
+
if (this.conn)
|
|
69
|
+
return this.conn;
|
|
70
|
+
if (!this.connecting) {
|
|
71
|
+
this.connecting = this.open().catch((e) => {
|
|
72
|
+
this.connecting = null;
|
|
73
|
+
throw e;
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
return this.connecting;
|
|
77
|
+
}
|
|
78
|
+
async open() {
|
|
79
|
+
let c = this.options.connection;
|
|
80
|
+
if (!c) {
|
|
81
|
+
if (!this.exec)
|
|
82
|
+
throw new CrowdyExecError('Unavailable', 'the kit has no exec client to connect with');
|
|
83
|
+
c = this.options.developer
|
|
84
|
+
? await this.exec.connectAsDeveloper(this.appId, this.options.connect)
|
|
85
|
+
: await this.exec.connect(this.appId, this.options.connect);
|
|
86
|
+
}
|
|
87
|
+
c.onReconnect((host) => {
|
|
88
|
+
for (const l of [...this.reconnectListeners])
|
|
89
|
+
l(host);
|
|
90
|
+
});
|
|
91
|
+
c.onAccessEnded((reason) => {
|
|
92
|
+
this.ended = reason;
|
|
93
|
+
for (const l of [...this.endedListeners])
|
|
94
|
+
l(reason);
|
|
95
|
+
});
|
|
96
|
+
this.conn = c;
|
|
97
|
+
return c;
|
|
98
|
+
}
|
|
99
|
+
/** The player's id, from the options or `users.me`; null when neither knows it. */
|
|
100
|
+
async playerId() {
|
|
101
|
+
if (this.options.playerId !== undefined)
|
|
102
|
+
return String(this.options.playerId);
|
|
103
|
+
if (!this.me) {
|
|
104
|
+
this.me = this.whoAmI ? this.whoAmI().catch(() => null) : Promise.resolve(null);
|
|
105
|
+
}
|
|
106
|
+
return this.me;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Calls a hub's endpoint, `args` as MessagePack, and returns the decoded reply.
|
|
110
|
+
* @throws {KitError} for a hub's coded refusal; {@link CrowdyExecError} for the platform's.
|
|
111
|
+
*/
|
|
112
|
+
async call(nodeType, key, method, args, options = {}) {
|
|
113
|
+
const actionId = options.action === true ? newActionId() : typeof options.action === 'string' ? options.action : undefined;
|
|
114
|
+
const sent = actionId ? withActionId(args, actionId) : args;
|
|
115
|
+
for (let attempt = 0;; attempt++) {
|
|
116
|
+
await this.budget.take();
|
|
117
|
+
const conn = await this.connection();
|
|
118
|
+
try {
|
|
119
|
+
return await conn.call(nodeType, key, method, sent, { timeoutMs: options.timeoutMs });
|
|
120
|
+
}
|
|
121
|
+
catch (e) {
|
|
122
|
+
const err = KitError.from(e);
|
|
123
|
+
if (attempt < this.retries && err instanceof CrowdyExecError && !(err instanceof KitError)) {
|
|
124
|
+
if (err.status === 'Busy' && err.rateLimited) {
|
|
125
|
+
this.budget.hold(err.retryAfterMs ?? 1000);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
const didNotRun = err.status === 'Busy' || err.status === 'RateLimited';
|
|
129
|
+
const unknown = err.status === 'DeadlineExceeded' || err.status === 'Unavailable' || err.status === 'Moved';
|
|
130
|
+
if (didNotRun || (actionId && unknown)) {
|
|
131
|
+
await sleep(Math.min(2000, 200 * 2 ** attempt) * (0.5 + Math.random() / 2));
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
throw err;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Receives what a hub publishes on `topic`. Returns the function that stops this handler
|
|
141
|
+
* (and the subscription with the last one).
|
|
142
|
+
* @throws {KitError} `limit` past {@link KIT_SUBSCRIPTIONS_MAX} subscriptions.
|
|
143
|
+
*/
|
|
144
|
+
async subscribe(nodeType, key, topic, onPush) {
|
|
145
|
+
const k = `${nodeType}\u0000${key}\u0000${topic}`;
|
|
146
|
+
const held = this.subs.get(k) ?? 0;
|
|
147
|
+
if (held === 0) {
|
|
148
|
+
if (this.subs.size >= KIT_SUBSCRIPTIONS_MAX) {
|
|
149
|
+
throw new KitError('limit', `a connection holds at most ${KIT_SUBSCRIPTIONS_MAX} subscriptions`);
|
|
150
|
+
}
|
|
151
|
+
await this.budget.take();
|
|
152
|
+
}
|
|
153
|
+
const conn = await this.connection();
|
|
154
|
+
const stop = await conn.subscribe(nodeType, key, topic, onPush);
|
|
155
|
+
this.subs.set(k, (this.subs.get(k) ?? 0) + 1);
|
|
156
|
+
let stopped = false;
|
|
157
|
+
return async () => {
|
|
158
|
+
if (stopped)
|
|
159
|
+
return;
|
|
160
|
+
stopped = true;
|
|
161
|
+
const left = (this.subs.get(k) ?? 1) - 1;
|
|
162
|
+
if (left > 0) {
|
|
163
|
+
this.subs.set(k, left);
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
this.subs.delete(k);
|
|
167
|
+
await this.budget.take();
|
|
168
|
+
}
|
|
169
|
+
await stop();
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
/** How many distinct topics the kit subscribes to. */
|
|
173
|
+
get subscriptions() {
|
|
174
|
+
return this.subs.size;
|
|
175
|
+
}
|
|
176
|
+
/** Called with the new host after the connection reconnects; kit mirrors resync then. */
|
|
177
|
+
onReconnect(listener) {
|
|
178
|
+
this.reconnectListeners.add(listener);
|
|
179
|
+
return () => this.reconnectListeners.delete(listener);
|
|
180
|
+
}
|
|
181
|
+
/** Called once when the player's access ended (close code 4403); nothing reconnects. */
|
|
182
|
+
onAccessEnded(listener) {
|
|
183
|
+
this.endedListeners.add(listener);
|
|
184
|
+
return () => this.endedListeners.delete(listener);
|
|
185
|
+
}
|
|
186
|
+
/** Closes the connection the kit opened (not one it was given). */
|
|
187
|
+
close() {
|
|
188
|
+
if (this.conn && !this.options.connection)
|
|
189
|
+
this.conn.close();
|
|
190
|
+
this.conn = null;
|
|
191
|
+
this.connecting = null;
|
|
192
|
+
this.subs.clear();
|
|
193
|
+
}
|
|
194
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The kit's observable value: `get` the current value, `subscribe` to hear each new one. The
|
|
3
|
+
* shape React's `useSyncExternalStore(store.subscribe, store.get)` takes, and that any other
|
|
4
|
+
* framework wraps in a line.
|
|
5
|
+
*/
|
|
6
|
+
export interface KitStore<T> {
|
|
7
|
+
get(): T;
|
|
8
|
+
/** Calls `listener` with every new value; returns the function that stops it. */
|
|
9
|
+
subscribe(listener: (value: T) => void): () => void;
|
|
10
|
+
}
|
|
11
|
+
/** A {@link KitStore} its owner sets. */
|
|
12
|
+
export declare class WritableKitStore<T> implements KitStore<T> {
|
|
13
|
+
private value;
|
|
14
|
+
private readonly listeners;
|
|
15
|
+
constructor(initial: T);
|
|
16
|
+
get(): T;
|
|
17
|
+
subscribe(listener: (value: T) => void): () => void;
|
|
18
|
+
set(value: T): void;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/kit/store.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,QAAQ,CAAC,CAAC;IACzB,GAAG,IAAI,CAAC,CAAC;IACT,iFAAiF;IACjF,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CACrD;AAED,yCAAyC;AACzC,qBAAa,gBAAgB,CAAC,CAAC,CAAE,YAAW,QAAQ,CAAC,CAAC,CAAC;IACrD,OAAO,CAAC,KAAK,CAAI;IACjB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiC;gBAE/C,OAAO,EAAE,CAAC;IAItB,GAAG,IAAI,CAAC;IAIR,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI;IAKnD,GAAG,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI;CAUpB"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** A {@link KitStore} its owner sets. */
|
|
2
|
+
export class WritableKitStore {
|
|
3
|
+
constructor(initial) {
|
|
4
|
+
this.listeners = new Set();
|
|
5
|
+
this.value = initial;
|
|
6
|
+
}
|
|
7
|
+
get() {
|
|
8
|
+
return this.value;
|
|
9
|
+
}
|
|
10
|
+
subscribe(listener) {
|
|
11
|
+
this.listeners.add(listener);
|
|
12
|
+
return () => this.listeners.delete(listener);
|
|
13
|
+
}
|
|
14
|
+
set(value) {
|
|
15
|
+
this.value = value;
|
|
16
|
+
for (const l of [...this.listeners]) {
|
|
17
|
+
try {
|
|
18
|
+
l(value);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
/* a listener's exception is its own */
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { ExecAPI, ExecBuild, ExecManifestType, ExecNodeTypeInput, ExecStarterPack } from '../domains/exec.js';
|
|
2
|
+
/** The crates one build takes at most (the game API's `execBuild`). */
|
|
3
|
+
export declare const KIT_BUILD_MAX_CRATES = 16;
|
|
4
|
+
/** The node API scopes a manifest may declare (ck-exec `bounds::NODE_API_SCOPES`). */
|
|
5
|
+
export declare const KIT_NODE_API_SCOPES: readonly string[];
|
|
6
|
+
/** A manifest as the kit composes it: the root hub and each node type. */
|
|
7
|
+
export interface KitManifest {
|
|
8
|
+
root: string;
|
|
9
|
+
types: Record<string, ExecNodeTypeInput | ExecManifestType>;
|
|
10
|
+
}
|
|
11
|
+
/** What {@link KitTopology.plan} composes: a manifest, and the starter crates it builds. */
|
|
12
|
+
export interface KitTopologyPlan {
|
|
13
|
+
root: string;
|
|
14
|
+
types: Record<string, ExecNodeTypeInput>;
|
|
15
|
+
/** The starter crates the types name, each built once. */
|
|
16
|
+
crates: string[];
|
|
17
|
+
}
|
|
18
|
+
/** Changes to a planned type: a seed, limits, replicas, scopes, `client`, ... */
|
|
19
|
+
export interface KitPlanOptions {
|
|
20
|
+
overrides?: Record<string, Partial<ExecNodeTypeInput>>;
|
|
21
|
+
}
|
|
22
|
+
/** How {@link KitTopology.deploy} waits for its build. */
|
|
23
|
+
export interface KitDeployOptions {
|
|
24
|
+
/** Default 10 minutes. */
|
|
25
|
+
timeoutMs?: number;
|
|
26
|
+
/** Called with the build once it is done. */
|
|
27
|
+
onBuild?: (build: ExecBuild) => void;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* What the execution manager would refuse in `manifest`, in its words (ck-exec
|
|
31
|
+
* `Manifest::problems`, less the digests, which the build fills in): the root is a hub
|
|
32
|
+
* without a parent, every other type has a defined parent, `calls` name defined types or `*`,
|
|
33
|
+
* replicas are for spokes, scopes are known. Empty when it deploys.
|
|
34
|
+
*/
|
|
35
|
+
export declare function kitManifestProblems(manifest: KitManifest): string[];
|
|
36
|
+
/**
|
|
37
|
+
* An app's tree of kit hubs, composed from the starter packs (`exec.starters`): pick the node
|
|
38
|
+
* types a game uses, and {@link plan} adds the hubs they hang under and the ones they call,
|
|
39
|
+
* checks the tree, and {@link deploy} builds the crates on the platform and deploys them.
|
|
40
|
+
* For the app's developers (the org's `manage_compute`), from an identity session.
|
|
41
|
+
*/
|
|
42
|
+
export declare class KitTopology {
|
|
43
|
+
private readonly appId;
|
|
44
|
+
private readonly exec;
|
|
45
|
+
private packed;
|
|
46
|
+
constructor(appId: string, exec: ExecAPI | undefined);
|
|
47
|
+
private api;
|
|
48
|
+
/** The starter packs this tier's toolchain carries (fetched once). */
|
|
49
|
+
pack(): Promise<ExecStarterPack>;
|
|
50
|
+
/** The node types the packs offer. */
|
|
51
|
+
types(): Promise<string[]>;
|
|
52
|
+
/**
|
|
53
|
+
* A manifest with the types in `select`, the types they hang under up to the root, and the
|
|
54
|
+
* types they call (by name, not `*`), from the packs' manifest.
|
|
55
|
+
* @throws {CrowdyError} for a type the packs do not have, a tree the manager would refuse,
|
|
56
|
+
* or more crates than one build takes.
|
|
57
|
+
*/
|
|
58
|
+
plan(select: readonly string[], options?: KitPlanOptions): Promise<KitTopologyPlan>;
|
|
59
|
+
/**
|
|
60
|
+
* Builds the plan's crates on the platform, waits, and deploys the manifest with the build.
|
|
61
|
+
* Resolves with the deployed version and the build id.
|
|
62
|
+
* @throws {CrowdyError} when the build fails (its log in the message).
|
|
63
|
+
*/
|
|
64
|
+
deploy(plan: KitTopologyPlan, options?: KitDeployOptions): Promise<{
|
|
65
|
+
version: number;
|
|
66
|
+
buildId: string;
|
|
67
|
+
}>;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=topology.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"topology.d.ts","sourceRoot":"","sources":["../../src/kit/topology.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,OAAO,EACP,SAAS,EAET,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EAChB,MAAM,oBAAoB,CAAC;AAE5B,uEAAuE;AACvE,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAEvC,sFAAsF;AACtF,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAUhD,CAAC;AAEF,0EAA0E;AAC1E,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,GAAG,gBAAgB,CAAC,CAAC;CAC7D;AAED,4FAA4F;AAC5F,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IACzC,0DAA0D;IAC1D,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,iFAAiF;AACjF,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC;CACxD;AAED,0DAA0D;AAC1D,MAAM,WAAW,gBAAgB;IAC/B,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;CACtC;AAID;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,EAAE,CA0BnE;AAED;;;;;GAKG;AACH,qBAAa,WAAW;IAIpB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAJvB,OAAO,CAAC,MAAM,CAAyC;gBAGpC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,OAAO,GAAG,SAAS;IAG5C,OAAO,CAAC,GAAG;IAKX,sEAAsE;IACtE,IAAI,IAAI,OAAO,CAAC,eAAe,CAAC;IAYhC,sCAAsC;IAChC,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAIhC;;;;;OAKG;IACG,IAAI,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,eAAe,CAAC;IA8B7F;;;;OAIG;IACG,MAAM,CAAC,IAAI,EAAE,eAAe,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAiBnH"}
|