Rebuild SCUM plugin data ownership
This commit is contained in:
@@ -245,11 +245,7 @@ describe("PlatformApiClient AI providers", () => {
|
||||
});
|
||||
}
|
||||
if (url.endsWith("/api/v1/server-instances/server-1/scum/players")) return jsonResponse({ items: [{ id: "scum-player-1", gamePlayerId: "steam-1", displayName: "Prisoner One", online: true }], count: 1 });
|
||||
if (url.endsWith("/api/v1/server-instances/server-1/scum/users")) return jsonResponse({ items: [{ id: "scum-user-1", serverInstanceId: server.id, displayName: "Prisoner One", steamId: "steam-1" }], count: 1 });
|
||||
if (url.endsWith("/api/v1/server-instances/server-1/scum/datasets/squads")) return jsonResponse({ items: [{ id: "squad-1", serverInstanceId: server.id, fields: { squadId: "squad-1", name: "Alpha" } }], count: 1 });
|
||||
if (url.endsWith("/api/v1/server-instances/server-1/scum/activity")) return jsonResponse({ items: [{ id: "activity-1", serverInstanceId: server.id, kind: "login" }], count: 1 });
|
||||
if (url.endsWith("/api/v1/server-instances/server-1/scum/gifts")) return jsonResponse({ items: [{ id: "gift-1", serverInstanceId: server.id, name: "Starter" }], count: 1 });
|
||||
if (url.endsWith("/api/v1/server-instances/server-1/scum/map-points")) return jsonResponse({ items: [{ id: "point-1", serverInstanceId: server.id, kind: "base" }], count: 1 });
|
||||
if (url.endsWith("/api/v1/server-instances/server-1/scum/squads")) return jsonResponse({ items: [{ id: "squad-1", squadId: "squad-1", name: "Alpha" }], count: 1 });
|
||||
if (url.endsWith("/api/v1/server-instances/server-1/scum/squad-members")) return jsonResponse({ items: [{ id: "member-1", squadId: "squad-1", gamePlayerId: "steam-1" }], count: 1 });
|
||||
if (url.endsWith("/api/v1/server-instances/server-1/scum/vehicles")) return jsonResponse({ items: [{ id: "vehicle-1", vehicleId: "vehicle-1", label: "SUV" }], count: 1 });
|
||||
if (url.endsWith("/api/v1/server-instances/server-1/scum/flags")) return jsonResponse({ items: [{ id: "flag-1", flagId: "flag-1", ownerSquadId: "squad-1" }], count: 1 });
|
||||
@@ -559,11 +555,7 @@ describe("PlatformApiClient AI providers", () => {
|
||||
await expect(client.getPlatformResourceUsage()).resolves.toMatchObject({ source: "platform-derived", cpuPercent: 28 });
|
||||
await expect(client.listServerMetrics()).resolves.toMatchObject({ count: 1, items: [{ serverInstanceId: server.id, online: true }] });
|
||||
await expect(client.listSCUMPlayers(server.id)).resolves.toMatchObject({ count: 1, items: [{ gamePlayerId: "steam-1" }] });
|
||||
await expect(client.listSCUMUsers(server.id)).resolves.toMatchObject({ count: 1, items: [{ steamId: "steam-1" }] });
|
||||
await expect(client.listSCUMSquads(server.id)).resolves.toMatchObject({ count: 1 });
|
||||
await expect(client.listSCUMActivity(server.id)).resolves.toMatchObject({ count: 1, items: [{ kind: "login" }] });
|
||||
await expect(client.listSCUMGifts(server.id)).resolves.toMatchObject({ count: 1, items: [{ name: "Starter" }] });
|
||||
await expect(client.listSCUMMapPoints(server.id)).resolves.toMatchObject({ count: 1, items: [{ kind: "base" }] });
|
||||
await expect(client.listSCUMSquadMembers(server.id)).resolves.toMatchObject({ count: 1 });
|
||||
await expect(client.listSCUMVehicles(server.id)).resolves.toMatchObject({ count: 1 });
|
||||
await expect(client.listSCUMFlags(server.id)).resolves.toMatchObject({ count: 1 });
|
||||
@@ -632,7 +624,7 @@ describe("PlatformApiClient AI providers", () => {
|
||||
client.invokeAI({ requestId: "ai-1", serverInstanceId: server.id, purpose: "config.suggest", prompt: "Tune PVP safely", currentConfig: "server.name=Example Survival #1\n" })
|
||||
).resolves.toMatchObject({ status: "ok", usage: { mocked: true }, configRecommendation: { diffSummary: "review required" } });
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledTimes(52);
|
||||
expect(fetchMock).toHaveBeenCalledTimes(48);
|
||||
});
|
||||
|
||||
it("calls plugin marketplace endpoints with filter and state contracts", async () => {
|
||||
|
||||
+13
-59
@@ -47,14 +47,6 @@ import type {
|
||||
GameClientBridgeSnapshotListResponse,
|
||||
GameClientBridgeSnapshotQuery,
|
||||
GameClientBridgeStatusResponse,
|
||||
GameGiftCatalogListResponse,
|
||||
GameGiftCatalogRequest,
|
||||
GameGiftCatalogResponse,
|
||||
GameGiftGrantListResponse,
|
||||
GameGiftGrantRequest,
|
||||
GameGiftGrantResponse,
|
||||
GameGiftRevisionListResponse,
|
||||
GameGiftRevisionResponse,
|
||||
GamePluginListResponse,
|
||||
HealthResponse,
|
||||
JobCreateRequest,
|
||||
@@ -110,14 +102,9 @@ import type {
|
||||
RemoteAdapterRequest,
|
||||
RemoteAdapterResponse,
|
||||
SCUMListResponse,
|
||||
SCUMActivityListResponse,
|
||||
SCUMGiftsListResponse,
|
||||
SCUMMapPointsListResponse,
|
||||
SCUMOperationListResponse,
|
||||
SCUMOperationRequest,
|
||||
SCUMOperationResponse,
|
||||
SCUMSquadsListResponse,
|
||||
SCUMUsersListResponse,
|
||||
SCUMWorkflowCreateRequest,
|
||||
SCUMWorkflowListResponse,
|
||||
SCUMWorkflowResponse,
|
||||
@@ -592,6 +579,17 @@ export class PlatformApiClient {
|
||||
return this.request<RemoteAdapterDeclarationListResponse>(`/server-instances/${encodeURIComponent(serverInstanceId)}/remote-adapters`);
|
||||
}
|
||||
|
||||
async listPluginData(serverInstanceId: string, collection: string, key?: string): Promise<{ items: Array<{ key: string; value: Record<string, unknown> }>; count: number }> {
|
||||
const params = new URLSearchParams();
|
||||
if (key) params.set("key", key);
|
||||
const query = params.toString();
|
||||
return this.request(`/server-instances/${encodeURIComponent(serverInstanceId)}/plugin-data/${encodeURIComponent(collection)}${query ? `?${query}` : ""}`);
|
||||
}
|
||||
|
||||
async putPluginData(serverInstanceId: string, collection: string, key: string, value: Record<string, unknown>): Promise<{ key: string; value: Record<string, unknown> }> {
|
||||
return this.request(`/server-instances/${encodeURIComponent(serverInstanceId)}/plugin-data/${encodeURIComponent(collection)}`, { method: "PUT", body: { key, value } });
|
||||
}
|
||||
|
||||
async requestRemoteAdapter(serverInstanceId: string, request: RemoteAdapterRequest): Promise<RemoteAdapterResponse> {
|
||||
return this.request<RemoteAdapterResponse>(`/server-instances/${encodeURIComponent(serverInstanceId)}/remote-adapters`, { method: "POST", body: request });
|
||||
}
|
||||
@@ -600,24 +598,8 @@ export class PlatformApiClient {
|
||||
return this.request<SCUMListResponse>(`/server-instances/${encodeURIComponent(serverInstanceId)}/scum/players`);
|
||||
}
|
||||
|
||||
async listSCUMUsers(serverInstanceId: string): Promise<SCUMUsersListResponse> {
|
||||
return this.request<SCUMUsersListResponse>(`/server-instances/${encodeURIComponent(serverInstanceId)}/scum/users`);
|
||||
}
|
||||
|
||||
async listSCUMSquads(serverInstanceId: string): Promise<SCUMSquadsListResponse> {
|
||||
return this.request<SCUMSquadsListResponse>(`/server-instances/${encodeURIComponent(serverInstanceId)}/scum/datasets/squads`);
|
||||
}
|
||||
|
||||
async listSCUMActivity(serverInstanceId: string): Promise<SCUMActivityListResponse> {
|
||||
return this.request<SCUMActivityListResponse>(`/server-instances/${encodeURIComponent(serverInstanceId)}/scum/activity`);
|
||||
}
|
||||
|
||||
async listSCUMGifts(serverInstanceId: string): Promise<SCUMGiftsListResponse> {
|
||||
return this.request<SCUMGiftsListResponse>(`/server-instances/${encodeURIComponent(serverInstanceId)}/scum/gifts`);
|
||||
}
|
||||
|
||||
async listSCUMMapPoints(serverInstanceId: string): Promise<SCUMMapPointsListResponse> {
|
||||
return this.request<SCUMMapPointsListResponse>(`/server-instances/${encodeURIComponent(serverInstanceId)}/scum/map-points`);
|
||||
async listSCUMSquads(serverInstanceId: string): Promise<SCUMListResponse> {
|
||||
return this.request<SCUMListResponse>(`/server-instances/${encodeURIComponent(serverInstanceId)}/scum/squads`);
|
||||
}
|
||||
|
||||
async listSCUMSquadMembers(serverInstanceId: string): Promise<SCUMListResponse> {
|
||||
@@ -636,34 +618,6 @@ export class PlatformApiClient {
|
||||
return this.request<SCUMListResponse>(`/server-instances/${encodeURIComponent(serverInstanceId)}/scum/positions`);
|
||||
}
|
||||
|
||||
async listGameGiftCatalogs(serverInstanceId: string): Promise<GameGiftCatalogListResponse> {
|
||||
return this.request<GameGiftCatalogListResponse>(`/server-instances/${encodeURIComponent(serverInstanceId)}/game-gifts`);
|
||||
}
|
||||
|
||||
async saveGameGiftCatalog(serverInstanceId: string, request: GameGiftCatalogRequest): Promise<GameGiftCatalogResponse> {
|
||||
return this.request<GameGiftCatalogResponse>(`/server-instances/${encodeURIComponent(serverInstanceId)}/game-gifts`, { method: "POST", body: request });
|
||||
}
|
||||
|
||||
async publishGameGiftCatalog(serverInstanceId: string, catalogId: string): Promise<GameGiftRevisionResponse> {
|
||||
return this.request<GameGiftRevisionResponse>(`/server-instances/${encodeURIComponent(serverInstanceId)}/game-gifts/${encodeURIComponent(catalogId)}/publish`, { method: "POST", body: {} });
|
||||
}
|
||||
|
||||
async listGameGiftRevisions(serverInstanceId: string, catalogId: string): Promise<GameGiftRevisionListResponse> {
|
||||
return this.request<GameGiftRevisionListResponse>(`/server-instances/${encodeURIComponent(serverInstanceId)}/game-gifts/${encodeURIComponent(catalogId)}/revisions`);
|
||||
}
|
||||
|
||||
async listGameGiftGrants(serverInstanceId: string): Promise<GameGiftGrantListResponse> {
|
||||
return this.request<GameGiftGrantListResponse>(`/server-instances/${encodeURIComponent(serverInstanceId)}/game-gift-grants`);
|
||||
}
|
||||
|
||||
async requestGameGiftGrant(serverInstanceId: string, request: GameGiftGrantRequest): Promise<GameGiftGrantResponse> {
|
||||
return this.request<GameGiftGrantResponse>(`/server-instances/${encodeURIComponent(serverInstanceId)}/game-gift-grants`, { method: "POST", body: request });
|
||||
}
|
||||
|
||||
async approveGameGiftGrant(serverInstanceId: string, grantId: string): Promise<GameGiftGrantResponse> {
|
||||
return this.request<GameGiftGrantResponse>(`/server-instances/${encodeURIComponent(serverInstanceId)}/game-gift-grants/${encodeURIComponent(grantId)}/approve`, { method: "POST", body: {} });
|
||||
}
|
||||
|
||||
async listSCUMOperations(serverInstanceId: string): Promise<SCUMOperationListResponse> {
|
||||
return this.request<SCUMOperationListResponse>(`/server-instances/${encodeURIComponent(serverInstanceId)}/scum/operations`);
|
||||
}
|
||||
|
||||
@@ -388,12 +388,9 @@ export interface GamePluginResponse {
|
||||
validationViolations?: string[];
|
||||
runtimeProfiles?: GamePluginRuntimeProfilesResponse;
|
||||
gameClientBridge?: GameClientBridgeManifestResponse;
|
||||
mapTrajectories?: GameMapGeometryResponse;
|
||||
status: GamePluginStatus;
|
||||
}
|
||||
|
||||
export interface GameMapGeometryResponse { mapId: string; mapVersion: string; worldMinX: number; worldMinY: number; worldMaxX: number; worldMaxY: number; imageWidth: number; imageHeight: number; precision: number; sampleDistance: number; sampleIntervalSeconds: number; retentionSeconds: number; }
|
||||
|
||||
export type PluginCreateFieldType = "text" | "number" | "boolean" | "select" | "port";
|
||||
|
||||
export interface PluginCreateFieldResponse {
|
||||
@@ -1378,26 +1375,6 @@ export interface RemoteAdapterResponse {
|
||||
|
||||
export type SCUMJsonRecord = Record<string, unknown>;
|
||||
export interface SCUMListResponse<T = SCUMJsonRecord> { items: T[]; count: number; }
|
||||
export interface SCUMPersistedRecord { id: string; serverInstanceId: string; observedAt?: string; syncedAt?: string; payload?: SCUMJsonRecord; }
|
||||
export interface SCUMUserRecord extends SCUMPersistedRecord { userProfileId?: string; steamId?: string; displayName?: string; famePoints?: number; normalBalance?: number; goldBalance?: number; lastLoginTime?: string; lastLogoutTime?: string; isAlive?: boolean; }
|
||||
export interface SCUMSquadRecord extends SCUMPersistedRecord { squadId?: string; name?: string; message?: string; score?: number; memberLimit?: number; memberCount?: number; }
|
||||
export interface SCUMActivityEventRecord extends SCUMPersistedRecord { eventId?: string; kind?: string; subjectId?: string; subjectName?: string; summary?: string; occurredAt?: string; locationX?: number; locationY?: number; locationZ?: number; }
|
||||
export interface SCUMGiftRecord extends SCUMPersistedRecord { giftId?: string; name?: string; status?: string; recipientUserProfileId?: string; recipientName?: string; availableAt?: string; expiresAt?: string; }
|
||||
export interface SCUMMapPointRecord extends SCUMPersistedRecord { pointId?: string; kind?: string; label?: string; locationX?: number; locationY?: number; locationZ?: number; mapId?: string; }
|
||||
export type SCUMUsersListResponse = SCUMListResponse<SCUMUserRecord>;
|
||||
export type SCUMSquadsListResponse = SCUMListResponse<SCUMSquadRecord>;
|
||||
export type SCUMActivityListResponse = SCUMListResponse<SCUMActivityEventRecord>;
|
||||
export type SCUMGiftsListResponse = SCUMListResponse<SCUMGiftRecord>;
|
||||
export type SCUMMapPointsListResponse = SCUMListResponse<SCUMMapPointRecord>;
|
||||
export interface GameGiftItemResponse { catalogItemKey: string; label: string; quantity: number; }
|
||||
export interface GameGiftCatalogResponse { id: string; name: string; gameVersion: string; draftItems: GameGiftItemResponse[]; latestRevisionId?: string; updatedAt: string; }
|
||||
export interface GameGiftCatalogListResponse { items: GameGiftCatalogResponse[]; }
|
||||
export interface GameGiftRevisionResponse { id: string; catalogId: string; revision: number; gameVersion: string; items: GameGiftItemResponse[]; publishedBy: string; publishedAt: string; }
|
||||
export interface GameGiftRevisionListResponse { items: GameGiftRevisionResponse[]; }
|
||||
export interface GameGiftGrantResponse { id: string; revisionId: string; revisionNumber: number; gameVersion: string; items: GameGiftItemResponse[]; gamePlayerRecordId: string; playerDisplayName: string; notice: string; requesterId: string; approverId?: string; status: string; deliverySummary?: string; notificationSummary?: string; createdAt: string; approvedAt?: string; completedAt?: string; }
|
||||
export interface GameGiftGrantListResponse { items: GameGiftGrantResponse[]; }
|
||||
export interface GameGiftCatalogRequest { id?: string; name: string; gameVersion: string; items: Array<{ catalogItemKey: string; quantity: number }>; }
|
||||
export interface GameGiftGrantRequest { revisionId: string; gamePlayerRecordId: string; notice: string; idempotencyKey: string; }
|
||||
export interface SCUMWorkflowCreateRequest { templateKey: string; idempotencyKey: string; input?: SCUMJsonRecord; }
|
||||
export interface SCUMOperationRequest { templateKey: string; playerId?: string; payload?: SCUMJsonRecord; guard?: SCUMJsonRecord; reason: string; idempotencyKey: string; }
|
||||
export interface SCUMWorkflowResponse { id: string; serverInstanceId: string; pluginId: string; templateKey: string; requestedBy?: string; idempotencyKey?: string; status: string; currentStepKey?: string; input?: SCUMJsonRecord; safeSummary?: SCUMJsonRecord; blockerReason?: string; auditReferences?: string[]; createdAt: string; updatedAt: string; completedAt?: string; }
|
||||
|
||||
Reference in New Issue
Block a user