fix: align bound query keys with invalidation prefixes

This commit is contained in:
DongHyeonka
2026-08-01 22:11:04 +09:00
parent 92c3d438ab
commit 853c2e3f30
4 changed files with 207 additions and 8 deletions
@@ -1,6 +1,80 @@
import { describe, expect, it } from "vitest";
import { indexInvalidationRegistry } from "../../src/contracts/query-invalidation.ts";
import {
createBoundQueryKey,
createQueryInvalidationPrefix,
defineQueryNamespaceIdentity,
queryNamespaceIdentityKey,
} from "../../src/contracts/query-keys.ts";
describe("query namespace identity", () => {
it("uses a canonical JSON tuple as the namespace identity key", () => {
const namespace = defineQueryNamespaceIdentity("reference-resource", 1);
expect(queryNamespaceIdentityKey(namespace)).toBe(
'["reference-resource",1]',
);
});
it("creates one namespace-first prefix for invalidation and bound keys", () => {
const namespace = defineQueryNamespaceIdentity("reference-resource", 1);
const prefix = createQueryInvalidationPrefix(namespace);
const key = createBoundQueryKey(
namespace,
"scope-fingerprint-0001",
3,
"identity-token-0001",
);
expect(prefix).toEqual(["query", 2, "reference-resource", 1]);
expect(key).toEqual([
"query",
2,
"reference-resource",
1,
"scope-fingerprint-0001",
3,
"identity-token-0001",
]);
expect(key.slice(0, 4)).toEqual(prefix);
expect(Object.isFrozen(prefix)).toBe(true);
expect(Object.isFrozen(key)).toBe(true);
});
it.each([
["empty", ""],
["C0 control", "orders\u0000private"],
["DEL control", "orders\u007fprivate"],
["81 UTF-8 bytes", "가".repeat(27)],
])("rejects a $0 namespace ID", (_label, namespaceId) => {
expect(() => defineQueryNamespaceIdentity(namespaceId, 1)).toThrow(
/namespace identity is invalid/u,
);
});
it.each([0, -1, 1.5, Number.MAX_SAFE_INTEGER + 1])(
"rejects the non-positive-safe namespace version %s",
(namespaceVersion) => {
expect(() =>
defineQueryNamespaceIdentity("reference-resource", namespaceVersion),
).toThrow(/namespace identity is invalid/u);
},
);
it("rejects a non-positive definition version before creating a bound key", () => {
const namespace = defineQueryNamespaceIdentity("reference-resource", 1);
expect(() =>
createBoundQueryKey(
namespace,
"scope-fingerprint-0001",
0,
"identity-token-0001",
),
).toThrow(/definition version is invalid/u);
});
});
describe("query invalidation registry", () => {
it.each([