@anweather/game-plugin-ssdk 1.5.0 → 1.6.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/dist-cjs/runtime/conformance.js +94 -0
- package/dist-cjs/runtime/index.js +12 -1
- package/dist-cjs/runtime/registration.js +70 -0
- package/dist-cjs/runtime/servePlugin.js +80 -0
- package/dist-cjs/runtime/version.js +14 -0
- package/dist-cjs/src/models/models_0.js +5 -0
- package/dist-cjs/src/protocols/Aws_restJson1.js +1 -0
- package/dist-cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist-es/runtime/conformance.js +90 -0
- package/dist-es/runtime/index.js +4 -0
- package/dist-es/runtime/registration.js +67 -0
- package/dist-es/runtime/servePlugin.js +75 -0
- package/dist-es/runtime/version.js +10 -0
- package/dist-es/src/models/models_0.js +5 -0
- package/dist-es/src/protocols/Aws_restJson1.js +1 -0
- package/dist-es/tsconfig.es.tsbuildinfo +1 -1
- package/dist-types/runtime/conformance.d.ts +17 -0
- package/dist-types/runtime/index.d.ts +7 -0
- package/dist-types/runtime/registration.d.ts +25 -0
- package/dist-types/runtime/servePlugin.d.ts +65 -0
- package/dist-types/runtime/version.d.ts +9 -0
- package/dist-types/src/models/models_0.d.ts +11 -0
- package/package.json +5 -3
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { GamePluginService } from "../src/server/GamePluginService";
|
|
2
|
+
export interface ConformanceOptions {
|
|
3
|
+
/** Participant ids to seat. Defaults to metadata.minPlayers generated ids. */
|
|
4
|
+
participants?: string[];
|
|
5
|
+
/** InitializeGame config. Defaults to {}. */
|
|
6
|
+
config?: unknown;
|
|
7
|
+
}
|
|
8
|
+
export interface ConformanceReport {
|
|
9
|
+
passed: string[];
|
|
10
|
+
failed: {
|
|
11
|
+
check: string;
|
|
12
|
+
reason: string;
|
|
13
|
+
}[];
|
|
14
|
+
}
|
|
15
|
+
export declare function runConformance<Context>(service: GamePluginService<Context>, context: Context, options?: ConformanceOptions): Promise<ConformanceReport>;
|
|
16
|
+
/** runConformance, throwing one error naming every failed check. */
|
|
17
|
+
export declare function assertConformance<Context>(service: GamePluginService<Context>, context: Context, options?: ConformanceOptions): Promise<ConformanceReport>;
|
|
@@ -1,3 +1,10 @@
|
|
|
1
1
|
export { mountSsdkHandler } from "./express";
|
|
2
2
|
export { createGamePluginService } from "./defaultService";
|
|
3
3
|
export type { RequiredGamePluginService, OptionalGamePluginService } from "./defaultService";
|
|
4
|
+
export { servePlugin, createPluginApp } from "./servePlugin";
|
|
5
|
+
export type { ServePluginOptions, PluginServiceDefinition, PluginApp, RunningPlugin } from "./servePlugin";
|
|
6
|
+
export { createRegistrationLoop } from "./registration";
|
|
7
|
+
export type { RegistrationOptions, RegistrationLoop } from "./registration";
|
|
8
|
+
export { runConformance, assertConformance } from "./conformance";
|
|
9
|
+
export type { ConformanceOptions, ConformanceReport } from "./conformance";
|
|
10
|
+
export { PLUGIN_PROTOCOL_VERSION, runtimeVersion } from "./version";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface RegistrationOptions {
|
|
2
|
+
gameType: string;
|
|
3
|
+
/** The platform's base URL, e.g. http://platform:8080. Absent means
|
|
4
|
+
* "never register" -- the backend runs standalone (local tests, the
|
|
5
|
+
* Jackson-bridge test). */
|
|
6
|
+
platformUrl: string | undefined;
|
|
7
|
+
/** How the platform reaches this backend, e.g. http://chess-remote:8091. */
|
|
8
|
+
backendBaseUrl: string;
|
|
9
|
+
/** The shared secret the platform will send back as X-Plugin-Auth. */
|
|
10
|
+
authToken: string | undefined;
|
|
11
|
+
/** Seconds between attempts while registration keeps failing. */
|
|
12
|
+
retryDelaySeconds?: number;
|
|
13
|
+
fetchImpl?: typeof fetch;
|
|
14
|
+
log?: Pick<Console, "log" | "error">;
|
|
15
|
+
}
|
|
16
|
+
export interface RegistrationLoop {
|
|
17
|
+
/** Start registering (returns immediately; the first attempt is async). */
|
|
18
|
+
start(): void;
|
|
19
|
+
/** Stop renewing and tell the platform this backend is going away. */
|
|
20
|
+
stop(): Promise<void>;
|
|
21
|
+
/** One attempt, resolving to the delay in seconds before the next one.
|
|
22
|
+
* Exposed for tests; start() drives this on a timer. */
|
|
23
|
+
attemptOnce(): Promise<number>;
|
|
24
|
+
}
|
|
25
|
+
export declare function createRegistrationLoop(options: RegistrationOptions): RegistrationLoop;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { type Express, type Request } from "express";
|
|
2
|
+
import type { Server } from "node:http";
|
|
3
|
+
import type { ValidationCustomizer } from "@aws-smithy/server-common";
|
|
4
|
+
import type { GamePluginService, GamePluginServiceOperations } from "../src/server/GamePluginService";
|
|
5
|
+
import type { OptionalGamePluginService, RequiredGamePluginService } from "./defaultService";
|
|
6
|
+
import { type RegistrationLoop } from "./registration";
|
|
7
|
+
/** What a plugin supplies: every operation createGamePluginService requires,
|
|
8
|
+
* except Health, which servePlugin answers itself unless overridden. */
|
|
9
|
+
export type PluginServiceDefinition<Context> = Omit<RequiredGamePluginService<Context>, "Health"> & Partial<Pick<GamePluginService<Context>, "Health">> & OptionalGamePluginService<Context>;
|
|
10
|
+
export interface ServePluginOptions<Context = Record<string, never>> {
|
|
11
|
+
/** The wire GameType id, as GetMetadata reports it. */
|
|
12
|
+
gameType: string;
|
|
13
|
+
service: PluginServiceDefinition<Context>;
|
|
14
|
+
/** Port to listen on when the environment sets no PORT. 0 picks a free one. */
|
|
15
|
+
defaultPort?: number;
|
|
16
|
+
/** Directory served, unauthenticated, under /assets -- the plugin's own
|
|
17
|
+
* frontend bundle. Absent means no /assets route. */
|
|
18
|
+
staticDir?: string;
|
|
19
|
+
/** express.raw body limit. Every RPC carries the whole pluginState, and
|
|
20
|
+
* the platform's own ceiling is the games row (16 MB), so that is the
|
|
21
|
+
* default rather than Express's 100 KB. */
|
|
22
|
+
bodyLimit?: string;
|
|
23
|
+
/** Where PORT, PLUGIN_AUTH_TOKEN, PLATFORM_URL and
|
|
24
|
+
* PLUGIN_BACKEND_BASE_URL are read from. Defaults to process.env. */
|
|
25
|
+
env?: Record<string, string | undefined>;
|
|
26
|
+
/** Per-request context handed to every operation. Defaults to {}. */
|
|
27
|
+
makeContext?: (req: Request) => Context;
|
|
28
|
+
/** Smithy input validation policy. The default is permissive: the rules
|
|
29
|
+
* engine's own validateMove is the real gate for move-shape
|
|
30
|
+
* correctness, and a strict customizer would 400 a Document-typed
|
|
31
|
+
* payload the engine would have rejected with a readable reason. */
|
|
32
|
+
validationCustomizer?: ValidationCustomizer<GamePluginServiceOperations>;
|
|
33
|
+
/** Extra routes or middleware, mounted before the /v1 catch-all and
|
|
34
|
+
* after the auth gate. */
|
|
35
|
+
configure?: (app: Express) => void;
|
|
36
|
+
/** Install SIGTERM/SIGINT handlers that deregister and exit. Defaults
|
|
37
|
+
* to true; tests pass false. */
|
|
38
|
+
handleSignals?: boolean;
|
|
39
|
+
/** Seconds between registration attempts while the platform is
|
|
40
|
+
* unreachable. */
|
|
41
|
+
retryDelaySeconds?: number;
|
|
42
|
+
log?: Pick<Console, "log" | "error">;
|
|
43
|
+
fetchImpl?: typeof fetch;
|
|
44
|
+
}
|
|
45
|
+
export interface PluginApp {
|
|
46
|
+
app: Express;
|
|
47
|
+
registration: RegistrationLoop;
|
|
48
|
+
port: number;
|
|
49
|
+
authToken: string | undefined;
|
|
50
|
+
platformUrl: string | undefined;
|
|
51
|
+
backendBaseUrl: string;
|
|
52
|
+
}
|
|
53
|
+
export interface RunningPlugin extends PluginApp {
|
|
54
|
+
server: Server;
|
|
55
|
+
/** The port actually bound (differs from the configured one only for 0). */
|
|
56
|
+
port: number;
|
|
57
|
+
/** Stop renewing, deregister, close the listener. */
|
|
58
|
+
close(): Promise<void>;
|
|
59
|
+
}
|
|
60
|
+
/** Build the app without listening -- what servePlugin does first, exposed
|
|
61
|
+
* for tests and for a plugin that wants to hand the app to its own server. */
|
|
62
|
+
export declare function createPluginApp<Context = Record<string, never>>(options: ServePluginOptions<Context>): PluginApp;
|
|
63
|
+
/** Listen, register with the platform, and keep the registration alive
|
|
64
|
+
* until close() or SIGTERM. Resolves once the port is bound. */
|
|
65
|
+
export declare function servePlugin<Context = Record<string, never>>(options: ServePluginOptions<Context>): Promise<RunningPlugin>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const PLUGIN_PROTOCOL_VERSION = 1;
|
|
2
|
+
/** The version of this npm package as installed -- what servePlugin()
|
|
3
|
+
* reports as Health.runtimeVersion so the platform can see which SDK
|
|
4
|
+
* release a running plugin was built against. Read from the package's own
|
|
5
|
+
* package.json at runtime (which is why it is not a compile-time constant:
|
|
6
|
+
* the publish workflow stamps the version after the build). "unknown" only
|
|
7
|
+
* when the package layout is not the published one, e.g. a bundler that
|
|
8
|
+
* inlined this module. */
|
|
9
|
+
export declare function runtimeVersion(): string;
|
|
@@ -281,6 +281,17 @@ export interface HealthOutput {
|
|
|
281
281
|
status: string | undefined;
|
|
282
282
|
gameType: string | undefined;
|
|
283
283
|
protocolVersion: number | undefined;
|
|
284
|
+
/**
|
|
285
|
+
* The version of the plugin runtime library this backend was built
|
|
286
|
+
* with (the Kotlin plugin-protocol-kotlin-runtime artifact or the
|
|
287
|
+
* @anweather/game-plugin-ssdk npm package -- both publish on one
|
|
288
|
+
* shared semver, see plugin-protocol/CLAUDE.md). Informational:
|
|
289
|
+
* the platform records it at registration so a plugin on a stale
|
|
290
|
+
* runtime is visible without shelling into its container. Absent
|
|
291
|
+
* from a backend built before this field existed.
|
|
292
|
+
* @public
|
|
293
|
+
*/
|
|
294
|
+
runtimeVersion?: string | undefined;
|
|
284
295
|
}
|
|
285
296
|
export declare namespace HealthOutput {
|
|
286
297
|
/**
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anweather/game-plugin-ssdk",
|
|
3
3
|
"description": "Generated GamePlugin RPC types/server (plugin-protocol/model/game-plugin.smithy) plus a hand-written Express bridge and default-handler wrapper (./runtime) -- see plugin-protocol/CLAUDE.md's \"Publishing for cross-repo plugins\".",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.6.0",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "concurrently 'npm:build:cjs' 'npm:build:es' 'npm:build:types'",
|
|
7
7
|
"build:cjs": "tsc -p tsconfig.cjs.json",
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"build:types": "tsc -p tsconfig.types.json",
|
|
10
10
|
"build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4",
|
|
11
11
|
"clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0",
|
|
12
|
-
"prepack": "npm run clean && npm run build"
|
|
12
|
+
"prepack": "npm run clean && npm run build",
|
|
13
|
+
"test": "tsx --test test/*.test.ts"
|
|
13
14
|
},
|
|
14
15
|
"main": "./dist-cjs/src/index.js",
|
|
15
16
|
"types": "./dist-types/src/index.d.ts",
|
|
@@ -69,7 +70,8 @@
|
|
|
69
70
|
"express": "^4.21.2",
|
|
70
71
|
"rimraf": "^3.0.0",
|
|
71
72
|
"typescript": "~5.8.3",
|
|
72
|
-
"@types/node": "^18.19.69"
|
|
73
|
+
"@types/node": "^18.19.69",
|
|
74
|
+
"tsx": "^4.19.2"
|
|
73
75
|
},
|
|
74
76
|
"engines": {
|
|
75
77
|
"node": ">=18.0.0"
|