feat: deliver module database ABI by manifest
CI / verify (pull_request) Successful in 1m0s
CI / infrastructure-smoke (pull_request) Successful in 36s
CI / migration-smoke (pull_request) Successful in 1m53s
CI / image-build (pull_request) Successful in 23s
CI / deploy-smoke (same-origin) (pull_request) Successful in 50s
CI / deploy-smoke (split) (pull_request) Successful in 1m30s
CI / verify (pull_request) Successful in 1m0s
CI / infrastructure-smoke (pull_request) Successful in 36s
CI / migration-smoke (pull_request) Successful in 1m53s
CI / image-build (pull_request) Successful in 23s
CI / deploy-smoke (same-origin) (pull_request) Successful in 50s
CI / deploy-smoke (split) (pull_request) Successful in 1m30s
This commit is contained in:
@@ -16,7 +16,7 @@ import {
|
||||
|
||||
function validManifest(): Record<string, unknown> {
|
||||
return {
|
||||
manifestVersion: 7,
|
||||
manifestVersion: 8,
|
||||
id: "calendar",
|
||||
name: "Calendar",
|
||||
version: "0.1.0",
|
||||
@@ -42,6 +42,24 @@ function validManifest(): Record<string, unknown> {
|
||||
}
|
||||
|
||||
describe("module manifest contract", () => {
|
||||
it("accepts both manifest-v8 database modes", () => {
|
||||
expect(parseModuleManifest(validManifest()).database).toBeUndefined();
|
||||
expect(parseModuleManifest({ ...validManifest(), database: { abi: 1 } }).database).toEqual({
|
||||
abi: 1,
|
||||
});
|
||||
});
|
||||
|
||||
it("rejects manifest v7, unsupported ABIs, malformed declarations, and unknown database fields", () => {
|
||||
expect(safeParseModuleManifest({ ...validManifest(), manifestVersion: 7 }).success).toBe(false);
|
||||
expect(safeParseModuleManifest({ ...validManifest(), database: { abi: 2 } }).success).toBe(
|
||||
false,
|
||||
);
|
||||
expect(safeParseModuleManifest({ ...validManifest(), database: "abi-v1" }).success).toBe(false);
|
||||
expect(
|
||||
safeParseModuleManifest({ ...validManifest(), database: { abi: 1, driver: "drizzle" } })
|
||||
.success,
|
||||
).toBe(false);
|
||||
});
|
||||
it("normalizes a valid manifest with safe defaults", () => {
|
||||
const manifest = parseModuleManifest(validManifest());
|
||||
|
||||
@@ -232,15 +250,15 @@ describe("module manifest contract", () => {
|
||||
expect(safeParseModuleManifest(version5Manifest).success).toBe(false);
|
||||
});
|
||||
|
||||
it("rejects a version 6 manifest rather than silently interpreting it as version 7", () => {
|
||||
it("rejects a version 6 manifest rather than silently interpreting it as version 8", () => {
|
||||
const version6Manifest = { ...validManifest(), manifestVersion: 6 };
|
||||
|
||||
expect(safeParseModuleManifest(version6Manifest).success).toBe(false);
|
||||
});
|
||||
|
||||
it("accepts exactly one manifest version, so no document can be read as two versions", () => {
|
||||
expect(MODULE_MANIFEST_VERSION).toBe(7);
|
||||
for (const manifestVersion of [1, 2, 3, 4, 5, 6, 8, "7", 7.5, null]) {
|
||||
expect(MODULE_MANIFEST_VERSION).toBe(8);
|
||||
for (const manifestVersion of [1, 2, 3, 4, 5, 6, 7, 9, "8", 8.5, null]) {
|
||||
expect(safeParseModuleManifest({ ...validManifest(), manifestVersion }).success).toBe(false);
|
||||
}
|
||||
expect(
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { parseModuleSchemaMetadataDefinition } from "../src/index.js";
|
||||
|
||||
describe("module schema metadata contract", () => {
|
||||
it("accepts and freezes plain ABI-v1 metadata", () => {
|
||||
const definition = parseModuleSchemaMetadataDefinition({
|
||||
moduleId: "calendar",
|
||||
tables: [
|
||||
{ name: "calendar_events" },
|
||||
{ name: "calendar_attendees", foreignKeys: [{ table: "calendar_events" }] },
|
||||
],
|
||||
});
|
||||
|
||||
expect(definition).toEqual({
|
||||
moduleId: "calendar",
|
||||
tables: [
|
||||
{ name: "calendar_events", foreignKeys: [] },
|
||||
{ name: "calendar_attendees", foreignKeys: [{ table: "calendar_events" }] },
|
||||
],
|
||||
});
|
||||
expect(Object.isFrozen(definition)).toBe(true);
|
||||
expect(Object.isFrozen(definition.tables)).toBe(true);
|
||||
expect(Object.isFrozen(definition.tables[1]?.foreignKeys)).toBe(true);
|
||||
});
|
||||
|
||||
it("strictly rejects malformed, executable, and class-backed metadata", () => {
|
||||
class Metadata {
|
||||
moduleId = "calendar";
|
||||
tables = [{ name: "calendar_events" }];
|
||||
}
|
||||
|
||||
for (const value of [
|
||||
{ moduleId: "calendar", tables: [] },
|
||||
{ moduleId: "calendar", tables: [{ name: "calendar_events", unknown: true }] },
|
||||
{ moduleId: "calendar", tables: [{ name: "calendar_events", foreignKeys: [{}] }] },
|
||||
{ moduleId: "calendar", tables: [{ name: "calendar_events", inspect: () => undefined }] },
|
||||
new Metadata(),
|
||||
]) {
|
||||
expect(() => parseModuleSchemaMetadataDefinition(value)).toThrow(
|
||||
"Invalid Ekklesia module schema metadata definition.",
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user