Rebuild SCUM plugin data ownership
This commit is contained in:
@@ -617,7 +617,7 @@ describe("plugin manifest validation", () => {
|
||||
expect(manifest.gameClientBridge.pages.find((page) => page.pageKey === "live-map")?.snapshotTypes).toEqual(expect.arrayContaining(["players", "vehicles", "flags"]));
|
||||
});
|
||||
|
||||
it("declares packaged SCUM v57 query templates without browser-provided SQL", () => {
|
||||
it("declares typed SCUM.db query templates without browser-visible SQL", () => {
|
||||
const pluginDir = path.join(pluginsRoot, "examples/scum-server-plugin");
|
||||
const manifest = JSON.parse(fs.readFileSync(path.join(pluginDir, "manifest.json"), "utf8")) as {
|
||||
permissions: string[];
|
||||
@@ -633,10 +633,6 @@ describe("plugin manifest validation", () => {
|
||||
targetKey: string;
|
||||
parameterSchemaRef: string;
|
||||
resultSchemaRef: string;
|
||||
sqlRef: string;
|
||||
targetTable: string;
|
||||
upsertKeys: string[];
|
||||
columnMappings: Record<string, string>;
|
||||
maxRows: number;
|
||||
timeoutSeconds: number;
|
||||
}>;
|
||||
@@ -645,7 +641,7 @@ describe("plugin manifest validation", () => {
|
||||
pages: Array<{ key: string; permissions?: string[]; bridgeActions?: string[] }>;
|
||||
runtimeProfiles?: { transportProfiles?: Array<{ key: string; kind: string; targetKey?: string; capabilities: string[] }> };
|
||||
};
|
||||
const expectedKeys = ["scum.player.profile", "scum.squads", "scum.squad-members", "scum.vehicles", "scum.flags", "scum.positions", "scum.activity", "scum.gifts"];
|
||||
const expectedKeys = ["scum.player.profile", "scum.squads", "scum.squad-members", "scum.vehicles", "scum.flags", "scum.positions"];
|
||||
const templatesByKey = new Map(manifest.gameClientBridge.queryTemplates.map((template) => [template.key, template]));
|
||||
expect([...templatesByKey.keys()]).toEqual(expect.arrayContaining(expectedKeys));
|
||||
expect(manifest.capabilities).toContain("remote.run.db.sqlite.query");
|
||||
@@ -659,14 +655,7 @@ describe("plugin manifest validation", () => {
|
||||
expect(template.engine).toBe("sqlite");
|
||||
expect(template.transportKey).toBe("scum-database");
|
||||
expect(template.targetKey).toBe("scum-database");
|
||||
expect(template.sqlRef).toMatch(/^sql\/scum-db-v57\/.+\.sql$/);
|
||||
expect(template.targetTable).toMatch(/^scum_/);
|
||||
expect(template.upsertKeys.length).toBeGreaterThan(0);
|
||||
expect(Object.keys(template.columnMappings).length).toBeGreaterThan(0);
|
||||
expect(template.upsertKeys.every((key) => key in template.columnMappings)).toBe(true);
|
||||
const sql = fs.readFileSync(path.join(pluginDir, template.sqlRef), "utf8");
|
||||
expect(sql).toMatch(/^SELECT\b/i);
|
||||
expect(sql).not.toMatch(/\b(?:INSERT|UPDATE|DELETE|DROP|ALTER|CREATE|ATTACH|PRAGMA)\b/i);
|
||||
expect(JSON.stringify(template).toLowerCase()).not.toMatch(/select\s|from\s|sqlite:|scum\.db|databasepath|hostpath|dsn/);
|
||||
const parameters = JSON.parse(fs.readFileSync(path.join(pluginDir, template.parameterSchemaRef), "utf8"));
|
||||
const result = JSON.parse(fs.readFileSync(path.join(pluginDir, template.resultSchemaRef), "utf8"));
|
||||
expect(parameters).toMatchObject({ type: "object", additionalProperties: false });
|
||||
@@ -676,7 +665,7 @@ describe("plugin manifest validation", () => {
|
||||
const playersPage = manifest.gameClientBridge.pages.find((page) => page.pageKey === "players");
|
||||
const squadsPage = manifest.gameClientBridge.pages.find((page) => page.pageKey === "squads");
|
||||
const mapPage = manifest.gameClientBridge.pages.find((page) => page.pageKey === "live-map");
|
||||
expect(playersPage?.queryTemplateKeys).toEqual(expect.arrayContaining(["scum.player.profile", "scum.positions", "scum.activity"]));
|
||||
expect(playersPage?.queryTemplateKeys).toEqual(expect.arrayContaining(["scum.player.profile", "scum.positions"]));
|
||||
expect(squadsPage?.queryTemplateKeys).toEqual(expect.arrayContaining(["scum.squads", "scum.squad-members", "scum.flags"]));
|
||||
expect(mapPage?.queryTemplateKeys).toEqual(expect.arrayContaining(["scum.vehicles", "scum.flags", "scum.positions"]));
|
||||
for (const pageKey of ["players", "squads", "live-map"]) {
|
||||
@@ -686,19 +675,6 @@ describe("plugin manifest validation", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("packages SCUM v57 UTF-16LE log and config maps", () => {
|
||||
const pluginDir = path.join(pluginsRoot, "examples/scum-server-plugin");
|
||||
const manifest = JSON.parse(fs.readFileSync(path.join(pluginDir, "manifest.json"), "utf8")) as { gameClientBridge: { dataPacks: Array<{ key: string; databaseUserVersion: number; logParserRefs: string[]; configMapRefs: string[] }> } };
|
||||
const pack = manifest.gameClientBridge.dataPacks.find((candidate) => candidate.key === "scum-db-v57");
|
||||
expect(pack).toMatchObject({ databaseUserVersion: 57 });
|
||||
const logParsers = JSON.parse(fs.readFileSync(path.join(pluginDir, pack!.logParserRefs[0]), "utf8"));
|
||||
const configMaps = JSON.parse(fs.readFileSync(path.join(pluginDir, pack!.configMapRefs[0]), "utf8"));
|
||||
expect(logParsers.encoding).toBe("utf-16le");
|
||||
expect(logParsers.parsers.map((parser: { key: string }) => parser.key)).toEqual(expect.arrayContaining(["login", "logout", "chat", "admin", "vehicle-destruction"]));
|
||||
const serverSettings = configMaps.maps.find((map: { key: string }) => map.key === "server-settings");
|
||||
expect(serverSettings.fields).toMatchObject({ "scum.WelcomeMessage": "welcomeMessage", "scum.MessageOfTheDay": "motd" });
|
||||
});
|
||||
|
||||
it("declares typed SCUM RCON operations without arbitrary command inputs", () => {
|
||||
const pluginDir = path.join(pluginsRoot, "examples/scum-server-plugin");
|
||||
const manifest = JSON.parse(fs.readFileSync(path.join(pluginDir, "manifest.json"), "utf8")) as {
|
||||
@@ -929,20 +905,6 @@ describe("plugin manifest validation", () => {
|
||||
expect(errors.some((error) => error.includes("timeoutSeconds"))).toBe(true);
|
||||
});
|
||||
|
||||
it("rejects inline SQL and incomplete SCUM row declarations", () => {
|
||||
const inlineErrors = validateTemporaryBridgeManifest((manifest) => {
|
||||
Object.assign(manifest.gameClientBridge.queryTemplates![0], { sqlRef: "SELECT * FROM user_profile", targetTable: "scum_users", upsertKeys: ["userProfileId"], columnMappings: { userProfileId: "userProfileId" } });
|
||||
});
|
||||
expect(inlineErrors.some((error) => error.includes("sqlRef"))).toBe(true);
|
||||
|
||||
const incompleteErrors = validateTemporaryBridgeManifest((manifest) => {
|
||||
Object.assign(manifest.gameClientBridge.queryTemplates![0], { sqlRef: "sql/scum-db-v57/users.sql", targetTable: "users", upsertKeys: [], columnMappings: {} });
|
||||
});
|
||||
expect(incompleteErrors.some((error) => error.includes("targetTable"))).toBe(true);
|
||||
expect(incompleteErrors.some((error) => error.includes("upsertKeys"))).toBe(true);
|
||||
expect(incompleteErrors.some((error) => error.includes("columnMappings"))).toBe(true);
|
||||
});
|
||||
|
||||
it("requires query templates to match a declared sqlite transport target and capability", () => {
|
||||
const targetErrors = validateTemporaryBridgeManifest((manifest) => {
|
||||
manifest.gameClientBridge.queryTemplates![0].targetKey = "db/other";
|
||||
|
||||
Reference in New Issue
Block a user