From 4fb9bb4ca99c357223d9d6bbbff2c03e925fdf9a Mon Sep 17 00:00:00 2001 From: Alex Olivier Date: Thu, 5 Mar 2026 11:30:12 +0000 Subject: [PATCH 1/9] feat(prisma): add support for string concatenation and hierarchy operators Add support for the `add` operator (string/numeric concatenation) with algebraic solving, and hierarchy functions (`overlaps`, `ancestorOf`, `descendentOf`) for segment-wise prefix comparisons. Closes #155, closes #156 Signed-off-by: Alex Olivier --- policies/resource.yaml | 54 +++ prisma/README.md | 11 + prisma/src/index.test.ts | 810 +++++++++++++++++++++++++++++++++++++++ prisma/src/index.ts | 436 ++++++++++++++++++++- 4 files changed, 1303 insertions(+), 8 deletions(-) diff --git a/policies/resource.yaml b/policies/resource.yaml index 7c54bbbd..1bc5c22d 100644 --- a/policies/resource.yaml +++ b/policies/resource.yaml @@ -639,3 +639,57 @@ resourcePolicy: match: expr: > !(request.resource.attr.categories.exists(cat, cat.subCategories.exists(sub, sub.name == "finance"))) + + - actions: + - "string-concat" + effect: EFFECT_ALLOW + roles: + - USER + condition: + match: + expr: > + request.resource.attr.aString == "prefix:" + request.resource.attr.id + + - actions: + - "string-concat-principal" + effect: EFFECT_ALLOW + roles: + - USER + condition: + match: + any: + of: + - expr: P.attr.context == "projects" + - expr: P.attr.context == "projects:" + request.resource.attr.id + + - actions: + - "hierarchy-overlaps" + effect: EFFECT_ALLOW + roles: + - USER + condition: + match: + expr: > + hierarchy(P.attr.context, ":").overlaps(hierarchy(["projects", R.id])) + + - actions: + - "hierarchy-ancestor-of" + effect: EFFECT_ALLOW + roles: + - USER + condition: + match: + expr: > + hierarchy(P.attr.scope).ancestorOf(hierarchy(R.attr.scope)) + + - actions: + - "hierarchy-descendent-of" + effect: EFFECT_ALLOW + roles: + - USER + condition: + match: + expr: > + hierarchy(R.attr.scope).descendentOf(hierarchy(P.attr.scope)) + + diff --git a/prisma/README.md b/prisma/README.md index 59f72db5..bd558e3e 100644 --- a/prisma/README.md +++ b/prisma/README.md @@ -19,6 +19,17 @@ An adapter library that takes a [Cerbos](https://cerbos.dev) Query Plan ([PlanRe - Collection operators: `exists`, `exists_one`, `all`, `filter`, `except` - Set operations: `hasIntersection` +#### String Concatenation + +- `add` operator for string/numeric concatenation in conditions +- Algebraic solving: `P.attr.context == "projects:" + R.attr.id` → `{ id: { equals: "123" } }` + +#### Hierarchy Operators + +- `hierarchy(string)`, `hierarchy(string, delimiter)`, `hierarchy([segments])` +- `overlaps`: segment-wise prefix comparison between two hierarchies +- `ancestorOf` / `descendentOf`: strict prefix relationship between hierarchies + #### Advanced Features - Deep nested relations support diff --git a/prisma/src/index.test.ts b/prisma/src/index.test.ts index 179d9e2a..a27fd6aa 100644 --- a/prisma/src/index.test.ts +++ b/prisma/src/index.test.ts @@ -5513,3 +5513,813 @@ describe("Return Types", () => { expect(conditional.kind).toBe(PlanKind.CONDITIONAL); }); }); + +// Issue #156: add operator (string concatenation) +describe("Add Operator", () => { + test("add with two values (constant folding)", () => { + // #given eq(field, add("prefix:", "suffix")) + const plan = createConditionalPlan({ + operator: "eq", + operands: [ + { name: "request.resource.attr.aString" }, + { + operator: "add", + operands: [{ value: "prefix:" }, { value: "suffix" }], + }, + ], + }); + + // #when + const result = queryPlanToPrisma({ + queryPlan: plan, + mapper: { + "request.resource.attr.aString": { field: "aString" }, + }, + }); + + // #then constant fold: "prefix:" + "suffix" = "prefix:suffix" + expect(result).toEqual({ + kind: PlanKind.CONDITIONAL, + filters: { aString: { equals: "prefix:suffix" } }, + }); + }); + + test("add with value prefix and field reference in eq", () => { + // #given eq("projects:123", add("projects:", R.attr.id)) + // This is the exact plan Cerbos produces for: + // P.attr.context == "projects:" + request.resource.attr.id + const plan = createConditionalPlan({ + operator: "eq", + operands: [ + { value: "projects:123" }, + { + operator: "add", + operands: [ + { value: "projects:" }, + { name: "request.resource.attr.id" }, + ], + }, + ], + }); + + // #when + const result = queryPlanToPrisma({ + queryPlan: plan, + mapper: { + "request.resource.attr.id": { field: "id" }, + }, + }); + + // #then solve: "projects:123" == "projects:" + id → id == "123" + expect(result).toEqual({ + kind: PlanKind.CONDITIONAL, + filters: { id: { equals: "123" } }, + }); + }); + + test("add with field reference and value suffix in eq", () => { + // #given eq("hello_world", add(R.attr.aString, "_world")) + const plan = createConditionalPlan({ + operator: "eq", + operands: [ + { value: "hello_world" }, + { + operator: "add", + operands: [ + { name: "request.resource.attr.aString" }, + { value: "_world" }, + ], + }, + ], + }); + + // #when + const result = queryPlanToPrisma({ + queryPlan: plan, + mapper: { + "request.resource.attr.aString": { field: "aString" }, + }, + }); + + // #then solve: "hello_world" == aString + "_world" → aString == "hello" + expect(result).toEqual({ + kind: PlanKind.CONDITIONAL, + filters: { aString: { equals: "hello" } }, + }); + }); + + test("add with value prefix and field reference in ne", () => { + // #given ne("projects:123", add("projects:", R.attr.id)) + const plan = createConditionalPlan({ + operator: "ne", + operands: [ + { value: "projects:123" }, + { + operator: "add", + operands: [ + { value: "projects:" }, + { name: "request.resource.attr.id" }, + ], + }, + ], + }); + + // #when + const result = queryPlanToPrisma({ + queryPlan: plan, + mapper: { + "request.resource.attr.id": { field: "id" }, + }, + }); + + // #then solve: "projects:123" != "projects:" + id → id != "123" + expect(result).toEqual({ + kind: PlanKind.CONDITIONAL, + filters: { id: { not: "123" } }, + }); + }); + + test("add with prefix mismatch yields impossible filter", () => { + // #given eq("other:123", add("projects:", R.attr.id)) + // "other:123" doesn't start with "projects:", so no value of id can match + const plan = createConditionalPlan({ + operator: "eq", + operands: [ + { value: "other:123" }, + { + operator: "add", + operands: [ + { value: "projects:" }, + { name: "request.resource.attr.id" }, + ], + }, + ], + }); + + // #when + const result = queryPlanToPrisma({ + queryPlan: plan, + mapper: { + "request.resource.attr.id": { field: "id" }, + }, + }); + + // #then impossible: produces a filter that matches nothing + // Use an impossible equality that Prisma won't match + expect(result).toEqual({ + kind: PlanKind.CONDITIONAL, + filters: { + AND: [{ id: { equals: null } }, { id: { not: null } }], + }, + }); + }); + + test("add with relation mapping", () => { + // #given eq("projects:123", add("projects:", R.attr.nested.id)) + const plan = createConditionalPlan({ + operator: "eq", + operands: [ + { value: "projects:123" }, + { + operator: "add", + operands: [ + { value: "projects:" }, + { name: "request.resource.attr.nested.id" }, + ], + }, + ], + }); + + // #when + const result = queryPlanToPrisma({ + queryPlan: plan, + mapper: { + "request.resource.attr.nested": { + relation: { + name: "nested", + type: "one", + field: "id", + }, + }, + }, + }); + + // #then + expect(result).toEqual({ + kind: PlanKind.CONDITIONAL, + filters: { nested: { is: { id: { equals: "123" } } } }, + }); + }); + + test("add via cerbos integration", async () => { + const queryPlan = await cerbos.planResources({ + principal: { + id: "user1", + roles: ["USER"], + attr: { context: "projects:123" }, + }, + resource: { kind: "resource" }, + action: "string-concat-principal", + }); + + expect(queryPlan.kind).toBe(PlanKind.CONDITIONAL); + + const result = queryPlanToPrisma({ + queryPlan, + mapper: { + "request.resource.attr.id": { field: "id" }, + }, + }); + + expect(result).toEqual({ + kind: PlanKind.CONDITIONAL, + filters: { id: { equals: "123" } }, + }); + }); + + test("add with numeric values", () => { + // #given add with numbers: eq(10, add(3, R.attr.aNumber)) + const plan = createConditionalPlan({ + operator: "eq", + operands: [ + { value: 10 }, + { + operator: "add", + operands: [ + { value: 3 }, + { name: "request.resource.attr.aNumber" }, + ], + }, + ], + }); + + // #when + const result = queryPlanToPrisma({ + queryPlan: plan, + mapper: { + "request.resource.attr.aNumber": { field: "aNumber" }, + }, + }); + + // #then solve: 10 == 3 + aNumber → aNumber == 7 + expect(result).toEqual({ + kind: PlanKind.CONDITIONAL, + filters: { aNumber: { equals: 7 } }, + }); + }); +}); + +// Issue #155: hierarchy overlaps operator +// overlaps = one hierarchy is a prefix of the other (segment-wise comparison) +describe("Hierarchy Overlaps", () => { + test("overlaps - equal length hierarchies, field must match", () => { + // #given hierarchy("projects:123", ":").overlaps(hierarchy(["projects", R.id])) + // Left segments: ["projects", "123"], Right segments: ["projects", R.id] + // Same length: prefix check both directions requires all segments match + // segments[0]: "projects" == "projects" ✓ + // segments[1]: "123" == R.id → R.id == "123" + const plan = createConditionalPlan({ + operator: "overlaps", + operands: [ + { + operator: "hierarchy", + operands: [{ value: "projects:123" }, { value: ":" }], + }, + { + operator: "hierarchy", + operands: [ + { + operator: "list", + operands: [ + { value: "projects" }, + { name: "request.resource.id" }, + ], + }, + ], + }, + ], + }); + + // #when + const result = queryPlanToPrisma({ + queryPlan: plan, + mapper: { + "request.resource.id": { field: "id" }, + }, + }); + + // #then + expect(result).toEqual({ + kind: PlanKind.CONDITIONAL, + filters: { id: { equals: "123" } }, + }); + }); + + test("overlaps - left shorter than right, left is always prefix", () => { + // #given hierarchy("admin", ":").overlaps(hierarchy(["admin", R.attr.scope])) + // Left segments: ["admin"] (length 1), Right segments: ["admin", R.attr.scope] (length 2) + // Left prefix of right: "admin" == "admin" ✓ → always true + const plan = createConditionalPlan({ + operator: "overlaps", + operands: [ + { + operator: "hierarchy", + operands: [{ value: "admin" }, { value: ":" }], + }, + { + operator: "hierarchy", + operands: [ + { + operator: "list", + operands: [ + { value: "admin" }, + { name: "request.resource.attr.scope" }, + ], + }, + ], + }, + ], + }); + + // #when + const result = queryPlanToPrisma({ + queryPlan: plan, + mapper: { + "request.resource.attr.scope": { field: "scope" }, + }, + }); + + // #then always true + expect(result).toEqual({ + kind: PlanKind.CONDITIONAL, + filters: {}, + }); + }); + + test("overlaps - left longer, right is prefix when field matches", () => { + // #given hierarchy("dept:engineering:frontend", ":").overlaps(hierarchy(["dept", R.attr.department])) + // Left segments: ["dept", "engineering", "frontend"] (3) + // Right segments: ["dept", R.attr.department] (2) + // Left prefix of right: len 3 > len 2 → impossible + // Right prefix of left: "dept" == "dept" ✓, R.attr.department == "engineering" + const plan = createConditionalPlan({ + operator: "overlaps", + operands: [ + { + operator: "hierarchy", + operands: [ + { value: "dept:engineering:frontend" }, + { value: ":" }, + ], + }, + { + operator: "hierarchy", + operands: [ + { + operator: "list", + operands: [ + { value: "dept" }, + { name: "request.resource.attr.department" }, + ], + }, + ], + }, + ], + }); + + // #when + const result = queryPlanToPrisma({ + queryPlan: plan, + mapper: { + "request.resource.attr.department": { field: "department" }, + }, + }); + + // #then + expect(result).toEqual({ + kind: PlanKind.CONDITIONAL, + filters: { department: { equals: "engineering" } }, + }); + }); + + test("overlaps - different roots, impossible", () => { + // #given hierarchy("org:acme:team1", ":").overlaps(hierarchy(["company", R.attr.team])) + // Left: ["org", "acme", "team1"], Right: ["company", R.attr.team] + // Both directions fail at segment[0]: "org" ≠ "company" + const plan = createConditionalPlan({ + operator: "overlaps", + operands: [ + { + operator: "hierarchy", + operands: [{ value: "org:acme:team1" }, { value: ":" }], + }, + { + operator: "hierarchy", + operands: [ + { + operator: "list", + operands: [ + { value: "company" }, + { name: "request.resource.attr.team" }, + ], + }, + ], + }, + ], + }); + + // #when + const result = queryPlanToPrisma({ + queryPlan: plan, + mapper: { + "request.resource.attr.team": { field: "team" }, + }, + }); + + // #then impossible + expect(result).toEqual({ + kind: PlanKind.CONDITIONAL, + filters: { + AND: [ + { team: { equals: null } }, + { team: { not: null } }, + ], + }, + }); + }); + + test("overlaps - equal length with field in middle, field must match", () => { + // #given hierarchy("region:us:west", ":").overlaps(hierarchy(["region", "us", R.attr.zone])) + // Left: ["region", "us", "west"], Right: ["region", "us", R.attr.zone] + // Same length, prefix check: "region"=="region" ✓, "us"=="us" ✓, "west"==R.attr.zone + const plan = createConditionalPlan({ + operator: "overlaps", + operands: [ + { + operator: "hierarchy", + operands: [{ value: "region:us:west" }, { value: ":" }], + }, + { + operator: "hierarchy", + operands: [ + { + operator: "list", + operands: [ + { value: "region" }, + { value: "us" }, + { name: "request.resource.attr.zone" }, + ], + }, + ], + }, + ], + }); + + // #when + const result = queryPlanToPrisma({ + queryPlan: plan, + mapper: { + "request.resource.attr.zone": { field: "zone" }, + }, + }); + + // #then + expect(result).toEqual({ + kind: PlanKind.CONDITIONAL, + filters: { zone: { equals: "west" } }, + }); + }); + + test("overlaps - single-field right hierarchy as prefix of left", () => { + // #given hierarchy("team:alpha", ":").overlaps(hierarchy([R.attr.group])) + // Left: ["team", "alpha"] (2), Right: [R.attr.group] (1) + // Left prefix of right: len 2 > len 1 → impossible + // Right prefix of left: R.attr.group == "team" (first segment) + const plan = createConditionalPlan({ + operator: "overlaps", + operands: [ + { + operator: "hierarchy", + operands: [{ value: "team:alpha" }, { value: ":" }], + }, + { + operator: "hierarchy", + operands: [ + { + operator: "list", + operands: [{ name: "request.resource.attr.group" }], + }, + ], + }, + ], + }); + + // #when + const result = queryPlanToPrisma({ + queryPlan: plan, + mapper: { + "request.resource.attr.group": { field: "group" }, + }, + }); + + // #then + expect(result).toEqual({ + kind: PlanKind.CONDITIONAL, + filters: { group: { equals: "team" } }, + }); + }); + + test("overlaps - hierarchy(dotted string) without delimiter", () => { + // #given hierarchy("a.b.c").overlaps(hierarchy(["a", "b", R.attr.zone])) + // hierarchy("a.b.c") uses default "." delimiter → ["a", "b", "c"] + const plan = createConditionalPlan({ + operator: "overlaps", + operands: [ + { + operator: "hierarchy", + operands: [{ value: "a.b.c" }], + }, + { + operator: "hierarchy", + operands: [ + { + operator: "list", + operands: [ + { value: "a" }, + { value: "b" }, + { name: "request.resource.attr.zone" }, + ], + }, + ], + }, + ], + }); + + // #when + const result = queryPlanToPrisma({ + queryPlan: plan, + mapper: { "request.resource.attr.zone": { field: "zone" } }, + }); + + // #then + expect(result).toEqual({ + kind: PlanKind.CONDITIONAL, + filters: { zone: { equals: "c" } }, + }); + }); + + test("overlaps via cerbos integration", async () => { + const queryPlan = await cerbos.planResources({ + principal: { + id: "user1", + roles: ["USER"], + attr: { context: "projects:123" }, + }, + resource: { kind: "resource" }, + action: "hierarchy-overlaps", + }); + + expect(queryPlan.kind).toBe(PlanKind.CONDITIONAL); + + const result = queryPlanToPrisma({ + queryPlan, + mapper: { + "request.resource.id": { field: "id" }, + }, + }); + + // hierarchy("projects:123", ":") segments = ["projects", "123"] + // hierarchy(["projects", R.id]) segments = ["projects", R.id] + // Same length, segments[1]: "123" == R.id → R.id == "123" + expect(result).toEqual({ + kind: PlanKind.CONDITIONAL, + filters: { id: { equals: "123" } }, + }); + }); +}); + +const hierarchyMapper = { + "request.resource.attr.scope": { field: "scope" }, + "request.resource.attr.path": { field: "path" }, +}; + +// ancestorOf = first hierarchy is a strict prefix of second +// hierarchy("a.b").ancestorOf(hierarchy("a.b.c.d")) == true +describe("Hierarchy ancestorOf", () => { + test("ancestorOf - constant is ancestor, field is descendant", () => { + // #given hierarchy("a.b.c").ancestorOf(hierarchy(R.attr.scope)) + const plan = createConditionalPlan({ + operator: "ancestorOf", + operands: [ + { + operator: "hierarchy", + operands: [{ value: "a.b.c" }], + }, + { + operator: "hierarchy", + operands: [{ name: "request.resource.attr.scope" }], + }, + ], + }); + + // #when + const result = queryPlanToPrisma({ queryPlan: plan, mapper: hierarchyMapper }); + + // #then - R.attr.scope must start with "a.b.c." (ancestor means strict prefix) + expect(result).toEqual({ + kind: PlanKind.CONDITIONAL, + filters: { scope: { startsWith: "a.b.c." } }, + }); + }); + + test("ancestorOf - field is ancestor of constant", () => { + // #given hierarchy(R.attr.scope).ancestorOf(hierarchy("a.b.c.d")) + // R.attr.scope must be a prefix of "a.b.c.d" + // Possible prefixes: "a", "a.b", "a.b.c" + const plan = createConditionalPlan({ + operator: "ancestorOf", + operands: [ + { + operator: "hierarchy", + operands: [{ name: "request.resource.attr.scope" }], + }, + { + operator: "hierarchy", + operands: [{ value: "a.b.c.d" }], + }, + ], + }); + + // #when + const result = queryPlanToPrisma({ queryPlan: plan, mapper: hierarchyMapper }); + + // #then - scope must be one of the strict prefixes of "a.b.c.d" + expect(result).toEqual({ + kind: PlanKind.CONDITIONAL, + filters: { scope: { in: ["a", "a.b", "a.b.c"] } }, + }); + }); + + test("ancestorOf - single segment constant ancestor", () => { + // #given hierarchy("root").ancestorOf(hierarchy(R.attr.scope)) + const plan = createConditionalPlan({ + operator: "ancestorOf", + operands: [ + { + operator: "hierarchy", + operands: [{ value: "root" }], + }, + { + operator: "hierarchy", + operands: [{ name: "request.resource.attr.scope" }], + }, + ], + }); + + // #when + const result = queryPlanToPrisma({ queryPlan: plan, mapper: hierarchyMapper }); + + // #then + expect(result).toEqual({ + kind: PlanKind.CONDITIONAL, + filters: { scope: { startsWith: "root." } }, + }); + }); + + test("ancestorOf - with custom delimiter", () => { + // #given hierarchy(P.attr.scope, ":").ancestorOf(hierarchy(R.attr.path, ":")) + // P.attr.scope is resolved at plan time → constant "org:team" + const plan = createConditionalPlan({ + operator: "ancestorOf", + operands: [ + { + operator: "hierarchy", + operands: [{ value: "org:team" }, { value: ":" }], + }, + { + operator: "hierarchy", + operands: [{ name: "request.resource.attr.path" }, { value: ":" }], + }, + ], + }); + + // #when + const result = queryPlanToPrisma({ queryPlan: plan, mapper: hierarchyMapper }); + + // #then - R.attr.path must start with "org:team:" (using the ":" delimiter) + expect(result).toEqual({ + kind: PlanKind.CONDITIONAL, + filters: { path: { startsWith: "org:team:" } }, + }); + }); + + test("ancestorOf via cerbos integration", async () => { + const plan = await cerbos.planResources({ + principal: { + id: "user1", + roles: ["USER"], + attr: { scope: "a.b.c" }, + }, + resource: { kind: "resource" }, + action: "hierarchy-ancestor-of", + }); + + const result = queryPlanToPrisma({ + queryPlan: plan, + mapper: { + "request.resource.attr.scope": { field: "scope" }, + }, + }); + + // hierarchy("a.b.c").ancestorOf(hierarchy(R.attr.scope)) + // "a.b.c" is ancestor of R.attr.scope → R.attr.scope starts with "a.b.c." + expect(result).toEqual({ + kind: PlanKind.CONDITIONAL, + filters: { scope: { startsWith: "a.b.c." } }, + }); + }); +}); + +// descendentOf = mirror of ancestorOf +// hierarchy("a.b.c.d").descendentOf(hierarchy("a.b")) == true +describe("Hierarchy descendentOf", () => { + test("descendentOf - field is descendant of constant", () => { + // #given hierarchy(R.attr.scope).descendentOf(hierarchy("a.b")) + // R.attr.scope must be a descendant of "a.b" → "a.b" is a prefix of R.attr.scope + const plan = createConditionalPlan({ + operator: "descendentOf", + operands: [ + { + operator: "hierarchy", + operands: [{ name: "request.resource.attr.scope" }], + }, + { + operator: "hierarchy", + operands: [{ value: "a.b" }], + }, + ], + }); + + // #when + const result = queryPlanToPrisma({ queryPlan: plan, mapper: hierarchyMapper }); + + // #then - scope must start with "a.b." (descendant = strict, must be longer) + expect(result).toEqual({ + kind: PlanKind.CONDITIONAL, + filters: { scope: { startsWith: "a.b." } }, + }); + }); + + test("descendentOf - constant is descendant of field", () => { + // #given hierarchy("a.b.c.d").descendentOf(hierarchy(R.attr.scope)) + // "a.b.c.d" descends from R.attr.scope → R.attr.scope is a prefix of "a.b.c.d" + const plan = createConditionalPlan({ + operator: "descendentOf", + operands: [ + { + operator: "hierarchy", + operands: [{ value: "a.b.c.d" }], + }, + { + operator: "hierarchy", + operands: [{ name: "request.resource.attr.scope" }], + }, + ], + }); + + // #when + const result = queryPlanToPrisma({ queryPlan: plan, mapper: hierarchyMapper }); + + // #then - scope must be one of the strict prefixes of "a.b.c.d" + expect(result).toEqual({ + kind: PlanKind.CONDITIONAL, + filters: { scope: { in: ["a", "a.b", "a.b.c"] } }, + }); + }); + + test("descendentOf via cerbos integration", async () => { + const plan = await cerbos.planResources({ + principal: { + id: "user1", + roles: ["USER"], + attr: { scope: "a.b.c" }, + }, + resource: { kind: "resource" }, + action: "hierarchy-descendent-of", + }); + + const result = queryPlanToPrisma({ + queryPlan: plan, + mapper: { + "request.resource.attr.scope": { field: "scope" }, + }, + }); + + // hierarchy(R.attr.scope).descendentOf(hierarchy("a.b.c")) + // R.attr.scope descends from "a.b.c" → R.attr.scope starts with "a.b.c." + expect(result).toEqual({ + kind: PlanKind.CONDITIONAL, + filters: { scope: { startsWith: "a.b.c." } }, + }); + }); +}); diff --git a/prisma/src/index.ts b/prisma/src/index.ts index 0d68e3ab..07f1ce33 100644 --- a/prisma/src/index.ts +++ b/prisma/src/index.ts @@ -7,6 +7,15 @@ import { export { PlanKind }; +const CERBOS_TO_PRISMA_OPERATOR: Record = { + eq: "equals", + ne: "not", + lt: "lt", + le: "lte", + gt: "gt", + ge: "gte", +}; + // Type Definitions export type PrismaFilter = Record; @@ -302,12 +311,35 @@ function resolveOperand( } else if (isValueOperand(operand)) { return { value: operand.value }; } else if (isOperatorOperand(operand)) { + const folded = tryFoldValueExpression(operand, mapper); + if (folded !== null) return { value: folded }; const nestedResult = buildPrismaFilterFromCerbosExpression(operand, mapper); return { value: nestedResult }; } throw new Error("Operand must have name, value, or be an expression"); } +function tryFoldValueExpression( + expr: OperatorOperand, + mapper: Mapper +): Value | null { + if (expr.operator !== "add") return null; + const leftOp = expr.operands[0]; + const rightOp = expr.operands[1]; + if (!leftOp || !rightOp) return null; + + const left = resolveOperand(leftOp, mapper); + const right = resolveOperand(rightOp, mapper); + + if (!isResolvedValue(left) || !isResolvedValue(right)) return null; + + try { + return foldAdd(left.value, right.value); + } catch { + return null; + } +} + /** * Creates a scoped mapper for collection operations */ @@ -475,6 +507,18 @@ function buildPrismaFilterFromCerbosExpression( return handleMapOperator(operands, mapper); } + case "overlaps": { + return handleOverlapsOperator(operands, mapper); + } + + case "ancestorOf": { + return handleAncestorDescendantOperator(operands, mapper, "ancestor"); + } + + case "descendentOf": { + return handleAncestorDescendantOperator(operands, mapper, "descendant"); + } + default: throw new Error(`Unsupported operator: ${operator}`); } @@ -542,14 +586,7 @@ function handleRelationalOperator( operands: PlanExpressionOperand[], mapper: Mapper ): PrismaFilter { - const prismaOperator = { - eq: "equals", - ne: "not", - lt: "lt", - le: "lte", - gt: "gt", - ge: "gte", - }[operator]; + const prismaOperator = CERBOS_TO_PRISMA_OPERATOR[operator]; if (!prismaOperator) { throw new Error(`Unsupported operator: ${operator}`); @@ -567,6 +604,16 @@ function handleRelationalOperator( return handleSizeComparison(operator, leftOperand, rightOperand, mapper); } + const addOperand = [leftOperand, rightOperand].find( + (o): o is OperatorOperand => + isOperatorOperand(o) && o.operator === "add" + ); + if (addOperand) { + const otherOperand = + addOperand === leftOperand ? rightOperand : leftOperand; + return handleAddComparison(operator, addOperand, otherOperand, mapper); + } + const left = resolveOperand(leftOperand, mapper); const right = resolveOperand(rightOperand, mapper); @@ -1035,3 +1082,376 @@ function handleMapOperator( }, }); } + +function buildImpossibleFilter(fieldRef: ResolvedFieldReference): PrismaFilter { + const fieldName = getLeafField(fieldRef.path); + return { + AND: [ + { [fieldName]: { equals: null } }, + { [fieldName]: { not: null } }, + ], + }; +} + +function handleAddComparison( + operator: string, + addExpr: OperatorOperand, + otherOperand: PlanExpressionOperand, + mapper: Mapper +): PrismaFilter { + const addLeftOp = assertDefined( + addExpr.operands[0], + "add operator requires a left operand" + ); + const addRightOp = assertDefined( + addExpr.operands[1], + "add operator requires a right operand" + ); + + const addLeft = resolveOperand(addLeftOp, mapper); + const addRight = resolveOperand(addRightOp, mapper); + const other = resolveOperand(otherOperand, mapper); + + if (isResolvedValue(addLeft) && isResolvedValue(addRight)) { + const folded = foldAdd(addLeft.value, addRight.value); + const prismaOp = CERBOS_TO_PRISMA_OPERATOR[operator]; + if (!prismaOp) throw new Error(`Unsupported operator: ${operator}`); + + if (isResolvedFieldReference(other)) { + return buildFieldFilter(other, prismaOp, folded); + } + throw new Error("add with two values requires a field reference on the other side"); + } + + if (!isResolvedValue(other)) { + throw new Error( + "add operator with field references requires a value on the other side of the comparison" + ); + } + + let fieldRef: ResolvedFieldReference; + let addValue: Value; + let fieldIsLeft: boolean; + + if (isResolvedFieldReference(addLeft) && isResolvedValue(addRight)) { + fieldRef = addLeft; + addValue = addRight.value; + fieldIsLeft = true; + } else if (isResolvedValue(addLeft) && isResolvedFieldReference(addRight)) { + fieldRef = addRight; + addValue = addLeft.value; + fieldIsLeft = false; + } else { + throw new Error( + "add operator requires exactly one field reference and one value, or two values" + ); + } + + if (operator !== "eq" && operator !== "ne") { + throw new Error( + `Operator ${operator} is not supported with add and field references` + ); + } + + const solvedValue = solveAdd(other.value, addValue, fieldIsLeft); + if (solvedValue === null) { + if (operator === "eq") return buildImpossibleFilter(fieldRef); + return {}; + } + + const prismaOp = operator === "eq" ? "equals" : "not"; + return buildFieldFilter(fieldRef, prismaOp, solvedValue); +} + +function foldAdd(left: Value, right: Value): Value { + if (typeof left === "string" || typeof right === "string") { + return String(left) + String(right); + } + if (typeof left === "number" && typeof right === "number") { + return left + right; + } + throw new Error("add operator requires string or number operands"); +} + +function solveAdd( + comparisonValue: Value, + addConstant: Value, + fieldIsLeft: boolean +): Value | null { + if (typeof comparisonValue === "string" && typeof addConstant === "string") { + if (fieldIsLeft) { + if (!comparisonValue.endsWith(addConstant)) return null; + return comparisonValue.slice( + 0, + comparisonValue.length - addConstant.length + ); + } + if (!comparisonValue.startsWith(addConstant)) return null; + return comparisonValue.slice(addConstant.length); + } + if (typeof comparisonValue === "number" && typeof addConstant === "number") { + return comparisonValue - addConstant; + } + throw new Error("Type mismatch in add comparison"); +} + +type ConstantSegment = { type: "constant"; value: string }; +type FieldSegment = { type: "field"; fieldRef: ResolvedFieldReference }; +type HierarchySegment = ConstantSegment | FieldSegment; + +type ConstantHierarchy = { + type: "constant"; + segments: string[]; + raw: string; + delimiter: string; +}; + +type FieldHierarchy = { + type: "field"; + fieldRef: ResolvedFieldReference; + delimiter: string; +}; + +type SegmentedHierarchy = { + type: "segmented"; + segments: HierarchySegment[]; +}; + +type ResolvedHierarchy = ConstantHierarchy | FieldHierarchy | SegmentedHierarchy; + +function resolveHierarchy( + expr: OperatorOperand, + mapper: Mapper +): ResolvedHierarchy { + const operands = expr.operands; + + if (operands.length === 2) { + const strOperand = assertDefined(operands[0], "hierarchy requires operands"); + const delimOperand = assertDefined( + operands[1], + "hierarchy requires a delimiter" + ); + if (!isValueOperand(delimOperand)) { + throw new Error("hierarchy delimiter must be a value"); + } + const delimiter = String(delimOperand.value); + + if (isValueOperand(strOperand)) { + const raw = String(strOperand.value); + return { type: "constant", segments: raw.split(delimiter), raw, delimiter }; + } + if (isNamedOperand(strOperand)) { + return { + type: "field", + fieldRef: resolveFieldReference(strOperand.name, mapper), + delimiter, + }; + } + throw new Error("hierarchy(string, delimiter) requires a value or field operand"); + } + + if (operands.length === 1) { + const inner = assertDefined(operands[0], "hierarchy requires an operand"); + + if (isValueOperand(inner)) { + const raw = String(inner.value); + return { type: "constant", segments: raw.split("."), raw, delimiter: "." }; + } + + if (isNamedOperand(inner)) { + return { + type: "field", + fieldRef: resolveFieldReference(inner.name, mapper), + delimiter: ".", + }; + } + + if (isOperatorOperand(inner) && inner.operator === "list") { + const segments = inner.operands.map((op): HierarchySegment => { + const resolved = resolveOperand(op, mapper); + if (isResolvedValue(resolved)) { + return { type: "constant", value: String(resolved.value) }; + } + return { type: "field", fieldRef: resolved }; + }); + return { type: "segmented", segments }; + } + + throw new Error("hierarchy requires a value, field, or list operand"); + } + + throw new Error("hierarchy requires 1 or 2 operands"); +} + +function toSegments(resolved: ResolvedHierarchy): HierarchySegment[] { + switch (resolved.type) { + case "constant": + return resolved.segments.map((s) => ({ type: "constant" as const, value: s })); + case "segmented": + return resolved.segments; + case "field": + throw new Error( + "Cannot get segments from a field-reference hierarchy" + ); + } +} + +function checkPrefixConditions( + shorter: HierarchySegment[], + longer: HierarchySegment[] +): PrismaFilter | null { + if (shorter.length > longer.length) return null; + + const conditions: PrismaFilter[] = []; + + for (let i = 0; i < shorter.length; i++) { + const s = shorter[i]!; + const l = longer[i]!; + + if (s.type === "constant" && l.type === "constant") { + if (s.value !== l.value) return null; + } else if (s.type === "field" && l.type === "constant") { + conditions.push(buildFieldFilter(s.fieldRef, "equals", l.value)); + } else if (s.type === "constant" && l.type === "field") { + conditions.push(buildFieldFilter(l.fieldRef, "equals", s.value)); + } else { + throw new Error( + "Cannot compare two field references in hierarchy overlap" + ); + } + } + + if (conditions.length === 0) return {}; + if (conditions.length === 1) return conditions[0]!; + return { AND: conditions }; +} + +function handleOverlapsOperator( + operands: PlanExpressionOperand[], + mapper: Mapper +): PrismaFilter { + const [left, right] = extractHierarchyOperands("overlaps", operands, mapper); + + const leftSegs = toSegments(left); + const rightSegs = toSegments(right); + + const leftPrefixOfRight = checkPrefixConditions(leftSegs, rightSegs); + const rightPrefixOfLeft = checkPrefixConditions(rightSegs, leftSegs); + + const validConditions = [leftPrefixOfRight, rightPrefixOfLeft].filter( + (c): c is PrismaFilter => c !== null + ); + + if (validConditions.length === 0) { + const allSegs = [...leftSegs, ...rightSegs]; + const fieldSeg = allSegs.find( + (s): s is FieldSegment => s.type === "field" + ); + if (fieldSeg) return buildImpossibleFilter(fieldSeg.fieldRef); + throw new Error("Cannot determine overlap: no field references found"); + } + + if (validConditions.some((c) => Object.keys(c).length === 0)) return {}; + + // When both directions are valid (equal-length hierarchies), they produce + // identical conditions since the same segment pairs are compared in both. + return validConditions[0]!; +} + +function extractHierarchyOperands( + operatorName: string, + operands: PlanExpressionOperand[], + mapper: Mapper +): [ResolvedHierarchy, ResolvedHierarchy] { + if (operands.length !== 2) { + throw new Error(`${operatorName} requires exactly two operands`); + } + const leftOp = assertDefined(operands[0], `${operatorName} requires a left operand`); + const rightOp = assertDefined(operands[1], `${operatorName} requires a right operand`); + + if ( + !isOperatorOperand(leftOp) || leftOp.operator !== "hierarchy" || + !isOperatorOperand(rightOp) || rightOp.operator !== "hierarchy" + ) { + throw new Error(`${operatorName} requires two hierarchy operands`); + } + + return [resolveHierarchy(leftOp, mapper), resolveHierarchy(rightOp, mapper)]; +} + +function getStrictPrefixes(segments: string[], delimiter: string): string[] { + if (segments.length <= 1) return []; + const prefixes: string[] = []; + let current = segments[0]!; + prefixes.push(current); + for (let i = 1; i < segments.length - 1; i++) { + current = current + delimiter + segments[i]!; + prefixes.push(current); + } + return prefixes; +} + +function handleAncestorDescendantOperator( + operands: PlanExpressionOperand[], + mapper: Mapper, + direction: "ancestor" | "descendant" +): PrismaFilter { + const [left, right] = extractHierarchyOperands( + direction === "ancestor" ? "ancestorOf" : "descendentOf", + operands, + mapper + ); + + // ancestorOf(A, B) = A is strict prefix of B + // descendentOf(A, B) = B is strict prefix of A + const ancestor = direction === "ancestor" ? left : right; + const descendant = direction === "ancestor" ? right : left; + + if (ancestor.type === "constant" && descendant.type === "field") { + const prefix = ancestor.raw + descendant.delimiter; + return buildFieldFilter(descendant.fieldRef, "startsWith", prefix); + } + + if (ancestor.type === "field" && descendant.type === "constant") { + const prefixes = getStrictPrefixes(descendant.segments, descendant.delimiter); + if (prefixes.length === 0) { + return buildImpossibleFilter(ancestor.fieldRef); + } + if (prefixes.length === 1) { + return buildFieldFilter(ancestor.fieldRef, "equals", prefixes[0]!); + } + return buildFieldFilter(ancestor.fieldRef, "in", prefixes); + } + + if (ancestor.type === "constant" && descendant.type === "constant") { + const ancestorStr = ancestor.raw + ancestor.delimiter; + if (descendant.raw.startsWith(ancestorStr)) return {}; + return buildImpossibleFilterFromHierarchies(ancestor, descendant); + } + + throw new Error( + `${direction === "ancestor" ? "ancestorOf" : "descendentOf"}: unsupported hierarchy type combination` + ); +} + +function buildImpossibleFilterFromHierarchies( + a: ResolvedHierarchy, + b: ResolvedHierarchy +): PrismaFilter { + if (a.type === "field") return buildImpossibleFilter(a.fieldRef); + if (b.type === "field") return buildImpossibleFilter(b.fieldRef); + throw new Error("Cannot build impossible filter: no field references found"); +} + +function buildFieldFilter( + fieldRef: ResolvedFieldReference, + prismaOp: string, + value: Value +): PrismaFilter { + const fieldName = getLeafField(fieldRef.path); + const fieldFilter = { [fieldName]: { [prismaOp]: value } }; + if (fieldRef.relations && fieldRef.relations.length > 0) { + return buildNestedRelationFilter(fieldRef.relations, fieldFilter); + } + return fieldFilter; +} From f3973fbb5bf1e7ac2fe1dc168086efaebf2856de Mon Sep 17 00:00:00 2001 From: Alex Olivier Date: Thu, 5 Mar 2026 11:53:42 +0000 Subject: [PATCH 2/9] fix(prisma): preserve relation nesting in impossible filters and use segment-based hierarchy prefixes - buildImpossibleFilter now wraps contradiction in buildNestedRelationFilter when the field reference has relations, preventing Prisma validation errors - Hierarchy prefix construction uses segments re-joined with the target delimiter instead of raw strings, fixing false negatives with mismatched delimiters - Constant/constant ancestor check compares segment arrays directly Signed-off-by: Alex Olivier --- prisma/src/index.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/prisma/src/index.ts b/prisma/src/index.ts index 07f1ce33..3ded9041 100644 --- a/prisma/src/index.ts +++ b/prisma/src/index.ts @@ -1085,12 +1085,16 @@ function handleMapOperator( function buildImpossibleFilter(fieldRef: ResolvedFieldReference): PrismaFilter { const fieldName = getLeafField(fieldRef.path); - return { + const contradiction = { AND: [ { [fieldName]: { equals: null } }, { [fieldName]: { not: null } }, ], }; + if (fieldRef.relations && fieldRef.relations.length > 0) { + return buildNestedRelationFilter(fieldRef.relations, contradiction); + } + return contradiction; } function handleAddComparison( @@ -1408,7 +1412,7 @@ function handleAncestorDescendantOperator( const descendant = direction === "ancestor" ? right : left; if (ancestor.type === "constant" && descendant.type === "field") { - const prefix = ancestor.raw + descendant.delimiter; + const prefix = ancestor.segments.join(descendant.delimiter) + descendant.delimiter; return buildFieldFilter(descendant.fieldRef, "startsWith", prefix); } @@ -1424,8 +1428,14 @@ function handleAncestorDescendantOperator( } if (ancestor.type === "constant" && descendant.type === "constant") { - const ancestorStr = ancestor.raw + ancestor.delimiter; - if (descendant.raw.startsWith(ancestorStr)) return {}; + const ancestorSegs = ancestor.segments; + const descendantSegs = descendant.segments; + if ( + descendantSegs.length > ancestorSegs.length && + ancestorSegs.every((seg, i) => seg === descendantSegs[i]) + ) { + return {}; + } return buildImpossibleFilterFromHierarchies(ancestor, descendant); } From aa551a7fc7aef1a11c339944cbc245099d74f474 Mon Sep 17 00:00:00 2001 From: Alex Olivier Date: Thu, 5 Mar 2026 12:04:37 +0000 Subject: [PATCH 3/9] fix(prisma): handle field hierarchies in overlaps and segmented in ancestor/descendant - buildImpossibleFilter delegates each condition to buildFieldFilter so relation field aliases are handled correctly per-condition - handleOverlapsOperator supports field-type hierarchies by combining prefix/equality/startsWith checks - normalizeHierarchy converts all-constant segmented hierarchies to constant type for ancestor/descendant and overlaps operators Signed-off-by: Alex Olivier --- prisma/src/index.ts | 75 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 64 insertions(+), 11 deletions(-) diff --git a/prisma/src/index.ts b/prisma/src/index.ts index 3ded9041..04e83fd3 100644 --- a/prisma/src/index.ts +++ b/prisma/src/index.ts @@ -1084,17 +1084,12 @@ function handleMapOperator( } function buildImpossibleFilter(fieldRef: ResolvedFieldReference): PrismaFilter { - const fieldName = getLeafField(fieldRef.path); - const contradiction = { + return { AND: [ - { [fieldName]: { equals: null } }, - { [fieldName]: { not: null } }, + buildFieldFilter(fieldRef, "equals", null), + buildFieldFilter(fieldRef, "not", null), ], }; - if (fieldRef.relations && fieldRef.relations.length > 0) { - return buildNestedRelationFilter(fieldRef.relations, contradiction); - } - return contradiction; } function handleAddComparison( @@ -1300,6 +1295,24 @@ function toSegments(resolved: ResolvedHierarchy): HierarchySegment[] { } } +function normalizeHierarchy( + h: ResolvedHierarchy, + defaultDelimiter = "." +): ResolvedHierarchy { + if (h.type !== "segmented") return h; + const allConstant = h.segments.every( + (s): s is ConstantSegment => s.type === "constant" + ); + if (!allConstant) return h; + const segments = (h.segments as ConstantSegment[]).map((s) => s.value); + return { + type: "constant", + segments, + raw: segments.join(defaultDelimiter), + delimiter: defaultDelimiter, + }; +} + function checkPrefixConditions( shorter: HierarchySegment[], longer: HierarchySegment[] @@ -1334,7 +1347,13 @@ function handleOverlapsOperator( operands: PlanExpressionOperand[], mapper: Mapper ): PrismaFilter { - const [left, right] = extractHierarchyOperands("overlaps", operands, mapper); + const [rawLeft, rawRight] = extractHierarchyOperands("overlaps", operands, mapper); + const left = normalizeHierarchy(rawLeft); + const right = normalizeHierarchy(rawRight); + + if (left.type === "field" || right.type === "field") { + return handleFieldOverlaps(left, right); + } const leftSegs = toSegments(left); const rightSegs = toSegments(right); @@ -1362,6 +1381,40 @@ function handleOverlapsOperator( return validConditions[0]!; } +function handleFieldOverlaps( + left: ResolvedHierarchy, + right: ResolvedHierarchy +): PrismaFilter { + const [field, other] = left.type === "field" ? [left, right] : [right as FieldHierarchy, left]; + + if (other.type === "field") { + throw new Error("overlaps: cannot compare two field-reference hierarchies"); + } + + const delimiter = field.delimiter; + const otherSegments = other.type === "constant" ? other.segments : undefined; + if (!otherSegments) { + throw new Error("overlaps: segmented hierarchies with field hierarchies are not supported"); + } + + const otherRaw = otherSegments.join(delimiter); + const allPrefixes = [otherSegments[0]!]; + for (let i = 1; i < otherSegments.length; i++) { + allPrefixes.push(allPrefixes[allPrefixes.length - 1]! + delimiter + otherSegments[i]!); + } + + // field is ancestor of other OR field equals other OR other is ancestor of field + const conditions: PrismaFilter[] = []; + if (allPrefixes.length > 1) { + conditions.push(buildFieldFilter(field.fieldRef, "in", allPrefixes.slice(0, -1))); + } + conditions.push(buildFieldFilter(field.fieldRef, "equals", otherRaw)); + conditions.push(buildFieldFilter(field.fieldRef, "startsWith", otherRaw + delimiter)); + + if (conditions.length === 1) return conditions[0]!; + return { OR: conditions }; +} + function extractHierarchyOperands( operatorName: string, operands: PlanExpressionOperand[], @@ -1408,8 +1461,8 @@ function handleAncestorDescendantOperator( // ancestorOf(A, B) = A is strict prefix of B // descendentOf(A, B) = B is strict prefix of A - const ancestor = direction === "ancestor" ? left : right; - const descendant = direction === "ancestor" ? right : left; + const ancestor = normalizeHierarchy(direction === "ancestor" ? left : right); + const descendant = normalizeHierarchy(direction === "ancestor" ? right : left); if (ancestor.type === "constant" && descendant.type === "field") { const prefix = ancestor.segments.join(descendant.delimiter) + descendant.delimiter; From 4b71fa9457b4a2de8273c4da7f804f0e012ac20c Mon Sep 17 00:00:00 2001 From: Alex Olivier Date: Thu, 5 Mar 2026 12:08:46 +0000 Subject: [PATCH 4/9] refactor(prisma): simplify hierarchy and add operator code - Reuse getStrictPrefixes in handleFieldOverlaps instead of manual loop - Fix unsafe type cast in handleFieldOverlaps with proper narrowing - Move normalizeHierarchy into extractHierarchyOperands - Use CERBOS_TO_PRISMA_OPERATOR map instead of manual ternary - Remove unreachable buildImpossibleFilterFromHierarchies - Short-circuit tryFoldValueExpression on non-value left operand - Deduplicate descendentOf operator name string Signed-off-by: Alex Olivier --- prisma/src/index.ts | 66 +++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 42 deletions(-) diff --git a/prisma/src/index.ts b/prisma/src/index.ts index 04e83fd3..e486d5dc 100644 --- a/prisma/src/index.ts +++ b/prisma/src/index.ts @@ -329,9 +329,9 @@ function tryFoldValueExpression( if (!leftOp || !rightOp) return null; const left = resolveOperand(leftOp, mapper); + if (!isResolvedValue(left)) return null; const right = resolveOperand(rightOp, mapper); - - if (!isResolvedValue(left) || !isResolvedValue(right)) return null; + if (!isResolvedValue(right)) return null; try { return foldAdd(left.value, right.value); @@ -1158,8 +1158,7 @@ function handleAddComparison( return {}; } - const prismaOp = operator === "eq" ? "equals" : "not"; - return buildFieldFilter(fieldRef, prismaOp, solvedValue); + return buildFieldFilter(fieldRef, CERBOS_TO_PRISMA_OPERATOR[operator]!, solvedValue); } function foldAdd(left: Value, right: Value): Value { @@ -1347,9 +1346,7 @@ function handleOverlapsOperator( operands: PlanExpressionOperand[], mapper: Mapper ): PrismaFilter { - const [rawLeft, rawRight] = extractHierarchyOperands("overlaps", operands, mapper); - const left = normalizeHierarchy(rawLeft); - const right = normalizeHierarchy(rawRight); + const [left, right] = extractHierarchyOperands("overlaps", operands, mapper); if (left.type === "field" || right.type === "field") { return handleFieldOverlaps(left, right); @@ -1385,28 +1382,24 @@ function handleFieldOverlaps( left: ResolvedHierarchy, right: ResolvedHierarchy ): PrismaFilter { - const [field, other] = left.type === "field" ? [left, right] : [right as FieldHierarchy, left]; - - if (other.type === "field") { + if (left.type === "field" && right.type === "field") { throw new Error("overlaps: cannot compare two field-reference hierarchies"); } - const delimiter = field.delimiter; - const otherSegments = other.type === "constant" ? other.segments : undefined; - if (!otherSegments) { + const field = (left.type === "field" ? left : right) as FieldHierarchy; + const other = left.type === "field" ? right : left; + + if (other.type !== "constant") { throw new Error("overlaps: segmented hierarchies with field hierarchies are not supported"); } - const otherRaw = otherSegments.join(delimiter); - const allPrefixes = [otherSegments[0]!]; - for (let i = 1; i < otherSegments.length; i++) { - allPrefixes.push(allPrefixes[allPrefixes.length - 1]! + delimiter + otherSegments[i]!); - } + const delimiter = field.delimiter; + const otherRaw = other.segments.join(delimiter); + const strictPrefixes = getStrictPrefixes(other.segments, delimiter); - // field is ancestor of other OR field equals other OR other is ancestor of field const conditions: PrismaFilter[] = []; - if (allPrefixes.length > 1) { - conditions.push(buildFieldFilter(field.fieldRef, "in", allPrefixes.slice(0, -1))); + if (strictPrefixes.length > 0) { + conditions.push(buildFieldFilter(field.fieldRef, "in", strictPrefixes)); } conditions.push(buildFieldFilter(field.fieldRef, "equals", otherRaw)); conditions.push(buildFieldFilter(field.fieldRef, "startsWith", otherRaw + delimiter)); @@ -1433,7 +1426,10 @@ function extractHierarchyOperands( throw new Error(`${operatorName} requires two hierarchy operands`); } - return [resolveHierarchy(leftOp, mapper), resolveHierarchy(rightOp, mapper)]; + return [ + normalizeHierarchy(resolveHierarchy(leftOp, mapper)), + normalizeHierarchy(resolveHierarchy(rightOp, mapper)), + ]; } function getStrictPrefixes(segments: string[], delimiter: string): string[] { @@ -1453,16 +1449,13 @@ function handleAncestorDescendantOperator( mapper: Mapper, direction: "ancestor" | "descendant" ): PrismaFilter { - const [left, right] = extractHierarchyOperands( - direction === "ancestor" ? "ancestorOf" : "descendentOf", - operands, - mapper - ); + const operatorName = direction === "ancestor" ? "ancestorOf" : "descendentOf"; + const [left, right] = extractHierarchyOperands(operatorName, operands, mapper); // ancestorOf(A, B) = A is strict prefix of B // descendentOf(A, B) = B is strict prefix of A - const ancestor = normalizeHierarchy(direction === "ancestor" ? left : right); - const descendant = normalizeHierarchy(direction === "ancestor" ? right : left); + const ancestor = direction === "ancestor" ? left : right; + const descendant = direction === "ancestor" ? right : left; if (ancestor.type === "constant" && descendant.type === "field") { const prefix = ancestor.segments.join(descendant.delimiter) + descendant.delimiter; @@ -1489,21 +1482,10 @@ function handleAncestorDescendantOperator( ) { return {}; } - return buildImpossibleFilterFromHierarchies(ancestor, descendant); + throw new Error(`${operatorName}: constants do not satisfy ${direction} relationship`); } - throw new Error( - `${direction === "ancestor" ? "ancestorOf" : "descendentOf"}: unsupported hierarchy type combination` - ); -} - -function buildImpossibleFilterFromHierarchies( - a: ResolvedHierarchy, - b: ResolvedHierarchy -): PrismaFilter { - if (a.type === "field") return buildImpossibleFilter(a.fieldRef); - if (b.type === "field") return buildImpossibleFilter(b.fieldRef); - throw new Error("Cannot build impossible filter: no field references found"); + throw new Error(`${operatorName}: unsupported hierarchy type combination`); } function buildFieldFilter( From 2a1823b71578279417a9f7be77fdcfce065682eb Mon Sep 17 00:00:00 2001 From: Alex Olivier Date: Thu, 5 Mar 2026 12:15:38 +0000 Subject: [PATCH 5/9] fix(prisma): wrap impossible filter in single relation scope and use field delimiter for prefixes - buildImpossibleFilter now builds the AND contradiction as a single unit wrapped in one relation traversal, ensuring to-many relations can't satisfy each condition with different rows - Use ancestor field's delimiter when building prefixes from constant descendant segments, fixing mismatch when segmented hierarchies are normalized with default delimiter Signed-off-by: Alex Olivier --- prisma/src/index.ts | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/prisma/src/index.ts b/prisma/src/index.ts index e486d5dc..ae214e07 100644 --- a/prisma/src/index.ts +++ b/prisma/src/index.ts @@ -1084,12 +1084,23 @@ function handleMapOperator( } function buildImpossibleFilter(fieldRef: ResolvedFieldReference): PrismaFilter { - return { + const fieldName = getLeafField(fieldRef.path); + const contradiction: PrismaFilter = { AND: [ - buildFieldFilter(fieldRef, "equals", null), - buildFieldFilter(fieldRef, "not", null), + { [fieldName]: { equals: null } }, + { [fieldName]: { not: null } }, ], }; + if (!fieldRef.relations || fieldRef.relations.length === 0) { + return contradiction; + } + let filter: PrismaFilter = contradiction; + for (let i = fieldRef.relations.length - 1; i >= 0; i--) { + const relation = fieldRef.relations[i]!; + const op = relation.type === "one" ? "is" : "some"; + filter = { [relation.name]: { [op]: filter } }; + } + return filter; } function handleAddComparison( @@ -1463,7 +1474,8 @@ function handleAncestorDescendantOperator( } if (ancestor.type === "field" && descendant.type === "constant") { - const prefixes = getStrictPrefixes(descendant.segments, descendant.delimiter); + const delimiter = ancestor.delimiter; + const prefixes = getStrictPrefixes(descendant.segments, delimiter); if (prefixes.length === 0) { return buildImpossibleFilter(ancestor.fieldRef); } From 5f0d0c05497bdd12c3503aae4df9f46ffd5a60f9 Mon Sep 17 00:00:00 2001 From: Alex Olivier Date: Thu, 5 Mar 2026 12:21:30 +0000 Subject: [PATCH 6/9] fix(prisma): apply relation field alias in impossible filters buildImpossibleFilter now uses the deepest relation's field alias when constructing the contradiction, matching the remapping behavior in buildNestedRelationFilter. Signed-off-by: Alex Olivier --- prisma/src/index.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/prisma/src/index.ts b/prisma/src/index.ts index ae214e07..6191ebcd 100644 --- a/prisma/src/index.ts +++ b/prisma/src/index.ts @@ -1084,7 +1084,13 @@ function handleMapOperator( } function buildImpossibleFilter(fieldRef: ResolvedFieldReference): PrismaFilter { - const fieldName = getLeafField(fieldRef.path); + let fieldName = getLeafField(fieldRef.path); + if (fieldRef.relations && fieldRef.relations.length > 0) { + const deepest = fieldRef.relations[fieldRef.relations.length - 1]!; + if (deepest.field) { + fieldName = deepest.field; + } + } const contradiction: PrismaFilter = { AND: [ { [fieldName]: { equals: null } }, From 9ff898c0459bea8b6287f18f598ca3ad39fd6eb2 Mon Sep 17 00:00:00 2001 From: Alex Olivier Date: Thu, 5 Mar 2026 12:34:11 +0000 Subject: [PATCH 7/9] fix(prisma): use empty in-list for impossible filters Replace null-based contradiction (equals: null / not: null) with { in: [] } which works for all field types including non-nullable required fields. Also simplifies buildImpossibleFilter to a single buildFieldFilter call. Signed-off-by: Alex Olivier --- prisma/src/index.test.ts | 7 ++----- prisma/src/index.ts | 24 +----------------------- 2 files changed, 3 insertions(+), 28 deletions(-) diff --git a/prisma/src/index.test.ts b/prisma/src/index.test.ts index a27fd6aa..a3819a33 100644 --- a/prisma/src/index.test.ts +++ b/prisma/src/index.test.ts @@ -5669,7 +5669,7 @@ describe("Add Operator", () => { expect(result).toEqual({ kind: PlanKind.CONDITIONAL, filters: { - AND: [{ id: { equals: null } }, { id: { not: null } }], + id: { in: [] }, }, }); }); @@ -5940,10 +5940,7 @@ describe("Hierarchy Overlaps", () => { expect(result).toEqual({ kind: PlanKind.CONDITIONAL, filters: { - AND: [ - { team: { equals: null } }, - { team: { not: null } }, - ], + team: { in: [] }, }, }); }); diff --git a/prisma/src/index.ts b/prisma/src/index.ts index 6191ebcd..2a4efe91 100644 --- a/prisma/src/index.ts +++ b/prisma/src/index.ts @@ -1084,29 +1084,7 @@ function handleMapOperator( } function buildImpossibleFilter(fieldRef: ResolvedFieldReference): PrismaFilter { - let fieldName = getLeafField(fieldRef.path); - if (fieldRef.relations && fieldRef.relations.length > 0) { - const deepest = fieldRef.relations[fieldRef.relations.length - 1]!; - if (deepest.field) { - fieldName = deepest.field; - } - } - const contradiction: PrismaFilter = { - AND: [ - { [fieldName]: { equals: null } }, - { [fieldName]: { not: null } }, - ], - }; - if (!fieldRef.relations || fieldRef.relations.length === 0) { - return contradiction; - } - let filter: PrismaFilter = contradiction; - for (let i = fieldRef.relations.length - 1; i >= 0; i--) { - const relation = fieldRef.relations[i]!; - const op = relation.type === "one" ? "is" : "some"; - filter = { [relation.name]: { [op]: filter } }; - } - return filter; + return buildFieldFilter(fieldRef, "in", []); } function handleAddComparison( From 8f153baee5c6497b4d95fd449c0c476b5e68e744 Mon Sep 17 00:00:00 2001 From: Alex Olivier Date: Thu, 5 Mar 2026 13:31:54 +0000 Subject: [PATCH 8/9] refactor(prisma): improve filter builder readability Signed-off-by: Alex Olivier --- prisma/src/index.ts | 242 ++++++++++++++++++++++---------------------- 1 file changed, 122 insertions(+), 120 deletions(-) diff --git a/prisma/src/index.ts b/prisma/src/index.ts index 2a4efe91..b62d8415 100644 --- a/prisma/src/index.ts +++ b/prisma/src/index.ts @@ -136,6 +136,78 @@ function isResolvedValue(operand: ResolvedOperand): operand is ResolvedValue { return "value" in operand; } +function getNamedOperand( + operands: PlanExpressionOperand[], + message: string +): NamedOperand { + const operand = operands.find(isNamedOperand); + if (!operand) { + throw new Error(message); + } + return operand; +} + +function getValueOperand( + operands: PlanExpressionOperand[], + message: string +): ValueOperand { + const operand = operands.find(isValueOperand); + if (!operand) { + throw new Error(message); + } + return operand; +} + +function requireResolvedFieldReference( + operand: ResolvedOperand, + message: string +): ResolvedFieldReference { + if (!isResolvedFieldReference(operand)) { + throw new Error(message); + } + return operand; +} + +function requireResolvedValue( + operand: ResolvedOperand, + message: string +): ResolvedValue { + if (!isResolvedValue(operand)) { + throw new Error(message); + } + return operand; +} + +function wrapRelations( + relations: RelationConfig[] | undefined, + filter: PrismaFilter +): PrismaFilter { + if (!relations || relations.length === 0) { + return filter; + } + return buildNestedRelationFilter(relations, filter); +} + +function buildFieldEqualsFilter( + fieldRef: ResolvedFieldReference, + value: Value +): PrismaFilter { + const fieldName = getLeafField(fieldRef.path); + return wrapRelations(fieldRef.relations, { [fieldName]: { equals: value } }); +} + +function buildFieldDirectOrInFilter( + fieldRef: ResolvedFieldReference, + values: Value[] +): PrismaFilter { + const fieldName = getLeafField(fieldRef.path); + const baseFilter = + values.length === 1 + ? { [fieldName]: values[0] } + : { [fieldName]: { in: values } }; + return wrapRelations(fieldRef.relations, baseFilter); +} + /** * Converts a Cerbos query plan to a Prisma filter. */ @@ -413,13 +485,8 @@ function buildPrismaFilterFromCerbosExpression( ): PrismaFilter { // A bare named operand represents a boolean field reference (e.g. `R.attr.booleanAttr`) if (isNamedOperand(expression)) { - const { path, relations } = resolveFieldReference(expression.name, mapper); - const fieldName = getLeafField(path); - const fieldFilter = { [fieldName]: { equals: true } }; - if (relations && relations.length > 0) { - return buildNestedRelationFilter(relations, fieldFilter); - } - return fieldFilter; + const fieldRef = resolveFieldReference(expression.name, mapper); + return buildFieldEqualsFilter(fieldRef, true); } if (!isOperatorOperand(expression)) { @@ -450,13 +517,12 @@ function buildPrismaFilterFromCerbosExpression( throw new Error("not operator requires an operand"); } if (isNamedOperand(operand)) { - const { path, relations } = resolveFieldReference( + const { relations, ...fieldRef } = resolveFieldReference( operand.name, mapper ); if (!relations || relations.length === 0) { - const fieldName = getLeafField(path); - return { [fieldName]: { equals: false } }; + return buildFieldEqualsFilter(fieldRef, false); } } return { @@ -615,28 +681,13 @@ function handleRelationalOperator( } const left = resolveOperand(leftOperand, mapper); - const right = resolveOperand(rightOperand, mapper); + const right = requireResolvedValue( + resolveOperand(rightOperand, mapper), + "Right operand must be a value" + ); if (isResolvedFieldReference(left)) { - const { path, relations } = left; - - if (!isResolvedValue(right)) { - throw new Error("Right operand must be a value"); - } - - const filterValue = { [prismaOperator]: right.value }; - const fieldName = getLeafField(path); - const fieldFilter = { [fieldName]: filterValue }; - - if (relations && relations.length > 0) { - return buildNestedRelationFilter(relations, fieldFilter); - } - - return fieldFilter; - } - - if (!isResolvedValue(right)) { - throw new Error("Right operand must be a value"); + return buildFieldFilter(left, prismaOperator, right.value); } return { [prismaOperator]: right.value }; @@ -649,39 +700,18 @@ function handleInOperator( operands: PlanExpressionOperand[], mapper: Mapper ): PrismaFilter { - const nameOperand = operands.find(isNamedOperand); - if (!nameOperand) throw new Error("Name operand is undefined"); - - const valueOperand = operands.find(isValueOperand); - if (!valueOperand) throw new Error("Value operand is undefined"); - - const resolved = resolveOperand(nameOperand, mapper); - if (!isResolvedFieldReference(resolved)) { - throw new Error("Name operand must resolve to a field reference"); - } - - const { path, relations } = resolved; - const resolvedValue = resolveOperand(valueOperand, mapper); - - if (!isResolvedValue(resolvedValue)) { - throw new Error("Value operand must resolve to a value"); - } - - const { value } = resolvedValue; + const nameOperand = getNamedOperand(operands, "Name operand is undefined"); + const valueOperand = getValueOperand(operands, "Value operand is undefined"); + const fieldRef = requireResolvedFieldReference( + resolveOperand(nameOperand, mapper), + "Name operand must resolve to a field reference" + ); + const { value } = requireResolvedValue( + resolveOperand(valueOperand, mapper), + "Value operand must resolve to a value" + ); const values = Array.isArray(value) ? value : [value]; - const fieldName = getLeafField(path); - - if (relations && relations.length > 0) { - const fieldFilter = - values.length === 1 - ? { [fieldName]: values[0] } - : { [fieldName]: { in: values } }; - return buildNestedRelationFilter(relations, fieldFilter); - } - - return values.length === 1 - ? { [fieldName]: values[0] } - : { [fieldName]: { in: values } }; + return buildFieldDirectOrInFilter(fieldRef, values); } /** @@ -692,37 +722,24 @@ function handleStringOperator( operands: PlanExpressionOperand[], mapper: Mapper ): PrismaFilter { - const nameOperand = operands.find(isNamedOperand); - if (!nameOperand) throw new Error("Name operand is undefined"); - - const resolved = resolveOperand(nameOperand, mapper); - if (!isResolvedFieldReference(resolved)) { - throw new Error("Name operand must resolve to a field reference"); - } - - const { path, relations } = resolved; - - const valueOperand = operands.find(isValueOperand); - if (!valueOperand) throw new Error("Value operand is undefined"); - - const resolvedValue = resolveOperand(valueOperand, mapper); - if (!isResolvedValue(resolvedValue)) { - throw new Error("Value operand must resolve to a value"); - } - - const { value } = resolvedValue; + const nameOperand = getNamedOperand(operands, "Name operand is undefined"); + const valueOperand = getValueOperand(operands, "Value operand is undefined"); + const fieldRef = requireResolvedFieldReference( + resolveOperand(nameOperand, mapper), + "Name operand must resolve to a field reference" + ); + const { value } = requireResolvedValue( + resolveOperand(valueOperand, mapper), + "Value operand must resolve to a value" + ); if (typeof value !== "string") { throw new Error(`${operator} operator requires string value`); } - const fieldName = getLeafField(path); - const fieldFilter = { [fieldName]: { [operator]: value } }; - - if (relations && relations.length > 0) { - return buildNestedRelationFilter(relations, fieldFilter); - } - - return fieldFilter; + const fieldName = getLeafField(fieldRef.path); + return wrapRelations(fieldRef.relations, { + [fieldName]: { [operator]: value }, + }); } /** @@ -732,34 +749,21 @@ function handleIsSetOperator( operands: PlanExpressionOperand[], mapper: Mapper ): PrismaFilter { - const nameOperand = operands.find(isNamedOperand); - if (!nameOperand) throw new Error("Name operand is undefined"); - - const resolved = resolveOperand(nameOperand, mapper); - if (!isResolvedFieldReference(resolved)) { - throw new Error("Name operand must resolve to a field reference"); - } - - const { path, relations } = resolved; - - const valueOperand = operands.find(isValueOperand); - if (!valueOperand) throw new Error("Value operand is undefined"); - - const resolvedValue = resolveOperand(valueOperand, mapper); - if (!isResolvedValue(resolvedValue)) { - throw new Error("Value operand must resolve to a value"); - } + const nameOperand = getNamedOperand(operands, "Name operand is undefined"); + const valueOperand = getValueOperand(operands, "Value operand is undefined"); + const fieldRef = requireResolvedFieldReference( + resolveOperand(nameOperand, mapper), + "Name operand must resolve to a field reference" + ); + const resolvedValue = requireResolvedValue( + resolveOperand(valueOperand, mapper), + "Value operand must resolve to a value" + ); - const fieldName = getLeafField(path); - const fieldFilter = { + const fieldName = getLeafField(fieldRef.path); + return wrapRelations(fieldRef.relations, { [fieldName]: resolvedValue.value ? { not: null } : { equals: null }, - }; - - if (relations && relations.length > 0) { - return buildNestedRelationFilter(relations, fieldFilter); - } - - return fieldFilter; + }); } /** @@ -1490,9 +1494,7 @@ function buildFieldFilter( value: Value ): PrismaFilter { const fieldName = getLeafField(fieldRef.path); - const fieldFilter = { [fieldName]: { [prismaOp]: value } }; - if (fieldRef.relations && fieldRef.relations.length > 0) { - return buildNestedRelationFilter(fieldRef.relations, fieldFilter); - } - return fieldFilter; + return wrapRelations(fieldRef.relations, { + [fieldName]: { [prismaOp]: value }, + }); } From ded93efea5e6d67027b8984186ee635aeea8b108 Mon Sep 17 00:00:00 2001 From: Alex Olivier Date: Thu, 26 Mar 2026 15:18:11 +0000 Subject: [PATCH 9/9] deps Signed-off-by: Alex Olivier --- prisma/package-lock.json | 1426 +++++++++++++++++--------------------- 1 file changed, 626 insertions(+), 800 deletions(-) diff --git a/prisma/package-lock.json b/prisma/package-lock.json index 5b30e34c..4812d459 100644 --- a/prisma/package-lock.json +++ b/prisma/package-lock.json @@ -37,13 +37,13 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" }, @@ -52,9 +52,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", - "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", "dev": true, "license": "MIT", "engines": { @@ -62,21 +62,22 @@ } }, "node_modules/@babel/core": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", - "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.5", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helpers": "^7.28.4", - "@babel/parser": "^7.28.5", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.5", - "@babel/types": "^7.28.5", + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -93,14 +94,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", - "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.5", - "@babel/types": "^7.28.5", + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -110,13 +111,13 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.27.2", + "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", @@ -137,29 +138,29 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", - "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.28.3" + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -169,9 +170,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", - "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", "dev": true, "license": "MIT", "engines": { @@ -209,27 +210,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", - "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4" + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", - "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.28.5" + "@babel/types": "^7.29.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -294,13 +295,13 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", - "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", + "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -336,13 +337,13 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", - "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz", + "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -462,13 +463,13 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", - "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz", + "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -478,33 +479,33 @@ } }, "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", - "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.5", + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.5", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.5", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", "debug": "^4.3.1" }, "engines": { @@ -512,9 +513,9 @@ } }, "node_modules/@babel/types": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", - "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", "dev": true, "license": "MIT", "dependencies": { @@ -530,20 +531,21 @@ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@bufbuild/protobuf": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.11.0.tgz", "integrity": "sha512-sBXGT13cpmPR5BMgHE6UEEfEaShh5Ror6rfN3yEK5si7QVrtZg8LEPQb0VVhiLRUslD2yLnXtnRzG035J/mZXQ==", - "license": "(Apache-2.0 AND BSD-3-Clause)" + "license": "(Apache-2.0 AND BSD-3-Clause)", + "peer": true }, "node_modules/@cerbos/api": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/@cerbos/api/-/api-0.6.0.tgz", "integrity": "sha512-NgJlJPCyhKSN9pVWE6TPnbQNTbCINFFo4YQcDOsr5BqnxybsLDsh+BdDLbA7gpsYgWrhIu2tegEpJsctDvWbHg==", "license": "Apache-2.0", + "peer": true, "dependencies": { "@bufbuild/protobuf": "^2.11.0" }, @@ -650,7 +652,8 @@ "resolved": "https://registry.npmjs.org/@electric-sql/pglite/-/pglite-0.3.15.tgz", "integrity": "sha512-Cj++n1Mekf9ETfdc16TlDi+cDDQF0W7EcbyRHYOAeZdsAe8M/FJg18itDTSwyHfar2WIezawM9o0EKaRGVKygQ==", "dev": true, - "license": "Apache-2.0" + "license": "Apache-2.0", + "peer": true }, "node_modules/@electric-sql/pglite-socket": { "version": "0.0.20", @@ -676,38 +679,35 @@ } }, "node_modules/@emnapi/core": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz", - "integrity": "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.1.tgz", + "integrity": "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA==", "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { - "@emnapi/wasi-threads": "1.1.0", + "@emnapi/wasi-threads": "1.2.0", "tslib": "^2.4.0" } }, "node_modules/@emnapi/runtime": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz", - "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.1.tgz", + "integrity": "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==", "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "tslib": "^2.4.0" } }, "node_modules/@emnapi/wasi-threads": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", - "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.0.tgz", + "integrity": "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==", "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "tslib": "^2.4.0" } @@ -762,7 +762,6 @@ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -803,18 +802,17 @@ } }, "node_modules/@jest/console": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.2.0.tgz", - "integrity": "sha512-+O1ifRjkvYIkBqASKWgLxrpEhQAAE7hY77ALLUufSk5717KfOShg6IbqLmdsLMPdUiFvA2kTs0R7YZy+l0IzZQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.3.0.tgz", + "integrity": "sha512-PAwCvFJ4696XP2qZj+LAn1BWjZaJ6RjG6c7/lkMaUJnkyMS34ucuIsfqYvfskVNvUI27R/u4P1HMYFnlVXG/Ww==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", - "jest-message-util": "30.2.0", - "jest-util": "30.2.0", + "jest-message-util": "30.3.0", + "jest-util": "30.3.0", "slash": "^3.0.0" }, "engines": { @@ -822,40 +820,38 @@ } }, "node_modules/@jest/core": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.2.0.tgz", - "integrity": "sha512-03W6IhuhjqTlpzh/ojut/pDB2LPRygyWX8ExpgHtQA8H/3K7+1vKmcINx5UzeOX1se6YEsBsOHQ1CRzf3fOwTQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.3.0.tgz", + "integrity": "sha512-U5mVPsBxLSO6xYbf+tgkymLx+iAhvZX43/xI1+ej2ZOPnPdkdO1CzDmFKh2mZBn2s4XZixszHeQnzp1gm/DIxw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@jest/console": "30.2.0", + "@jest/console": "30.3.0", "@jest/pattern": "30.0.1", - "@jest/reporters": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", + "@jest/reporters": "30.3.0", + "@jest/test-result": "30.3.0", + "@jest/transform": "30.3.0", + "@jest/types": "30.3.0", "@types/node": "*", "ansi-escapes": "^4.3.2", "chalk": "^4.1.2", "ci-info": "^4.2.0", "exit-x": "^0.2.2", "graceful-fs": "^4.2.11", - "jest-changed-files": "30.2.0", - "jest-config": "30.2.0", - "jest-haste-map": "30.2.0", - "jest-message-util": "30.2.0", + "jest-changed-files": "30.3.0", + "jest-config": "30.3.0", + "jest-haste-map": "30.3.0", + "jest-message-util": "30.3.0", "jest-regex-util": "30.0.1", - "jest-resolve": "30.2.0", - "jest-resolve-dependencies": "30.2.0", - "jest-runner": "30.2.0", - "jest-runtime": "30.2.0", - "jest-snapshot": "30.2.0", - "jest-util": "30.2.0", - "jest-validate": "30.2.0", - "jest-watcher": "30.2.0", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", + "jest-resolve": "30.3.0", + "jest-resolve-dependencies": "30.3.0", + "jest-runner": "30.3.0", + "jest-runtime": "30.3.0", + "jest-snapshot": "30.3.0", + "jest-util": "30.3.0", + "jest-validate": "30.3.0", + "jest-watcher": "30.3.0", + "pretty-format": "30.3.0", "slash": "^3.0.0" }, "engines": { @@ -871,9 +867,9 @@ } }, "node_modules/@jest/diff-sequences": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz", - "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.3.0.tgz", + "integrity": "sha512-cG51MVnLq1ecVUaQ3fr6YuuAOitHK1S4WUJHnsPFE/quQr33ADUx1FfrTCpMCRxvy0Yr9BThKpDjSlcTi91tMA==", "dev": true, "license": "MIT", "engines": { @@ -881,39 +877,39 @@ } }, "node_modules/@jest/environment": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.2.0.tgz", - "integrity": "sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.3.0.tgz", + "integrity": "sha512-SlLSF4Be735yQXyh2+mctBOzNDx5s5uLv88/j8Qn1wH679PDcwy67+YdADn8NJnGjzlXtN62asGH/T4vWOkfaw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/fake-timers": "30.2.0", - "@jest/types": "30.2.0", + "@jest/fake-timers": "30.3.0", + "@jest/types": "30.3.0", "@types/node": "*", - "jest-mock": "30.2.0" + "jest-mock": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/expect": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.2.0.tgz", - "integrity": "sha512-V9yxQK5erfzx99Sf+7LbhBwNWEZ9eZay8qQ9+JSC0TrMR1pMDHLMY+BnVPacWU6Jamrh252/IKo4F1Xn/zfiqA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.3.0.tgz", + "integrity": "sha512-76Nlh4xJxk2D/9URCn3wFi98d2hb19uWE1idLsTt2ywhvdOldbw3S570hBgn25P4ICUZ/cBjybrBex2g17IDbg==", "dev": true, "license": "MIT", "dependencies": { - "expect": "30.2.0", - "jest-snapshot": "30.2.0" + "expect": "30.3.0", + "jest-snapshot": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/expect-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz", - "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.3.0.tgz", + "integrity": "sha512-j0+W5iQQ8hBh7tHZkTQv3q2Fh/M7Je72cIsYqC4OaktgtO7v1So9UTjp6uPBHIaB6beoF/RRsCgMJKvti0wADA==", "dev": true, "license": "MIT", "dependencies": { @@ -924,18 +920,18 @@ } }, "node_modules/@jest/fake-timers": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.2.0.tgz", - "integrity": "sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.3.0.tgz", + "integrity": "sha512-WUQDs8SOP9URStX1DzhD425CqbN/HxUYCTwVrT8sTVBfMvFqYt/s61EK5T05qnHu0po6RitXIvP9otZxYDzTGQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", - "@sinonjs/fake-timers": "^13.0.0", + "@jest/types": "30.3.0", + "@sinonjs/fake-timers": "^15.0.0", "@types/node": "*", - "jest-message-util": "30.2.0", - "jest-mock": "30.2.0", - "jest-util": "30.2.0" + "jest-message-util": "30.3.0", + "jest-mock": "30.3.0", + "jest-util": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -952,16 +948,16 @@ } }, "node_modules/@jest/globals": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.2.0.tgz", - "integrity": "sha512-b63wmnKPaK+6ZZfpYhz9K61oybvbI1aMcIs80++JI1O1rR1vaxHUCNqo3ITu6NU0d4V34yZFoHMn/uoKr/Rwfw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.3.0.tgz", + "integrity": "sha512-+owLCBBdfpgL3HU+BD5etr1SvbXpSitJK0is1kiYjJxAAJggYMRQz5hSdd5pq1sSggfxPbw2ld71pt4x5wwViA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.2.0", - "@jest/expect": "30.2.0", - "@jest/types": "30.2.0", - "jest-mock": "30.2.0" + "@jest/environment": "30.3.0", + "@jest/expect": "30.3.0", + "@jest/types": "30.3.0", + "jest-mock": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -982,33 +978,32 @@ } }, "node_modules/@jest/reporters": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.2.0.tgz", - "integrity": "sha512-DRyW6baWPqKMa9CzeiBjHwjd8XeAyco2Vt8XbcLFjiwCOEKOvy82GJ8QQnJE9ofsxCMPjH4MfH8fCWIHHDKpAQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.3.0.tgz", + "integrity": "sha512-a09z89S+PkQnL055bVj8+pe2Caed2PBOaczHcXCykW5ngxX9EWx/1uAwncxc/HiU0oZqfwseMjyhxgRjS49qPw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", + "@jest/console": "30.3.0", + "@jest/test-result": "30.3.0", + "@jest/transform": "30.3.0", + "@jest/types": "30.3.0", "@jridgewell/trace-mapping": "^0.3.25", "@types/node": "*", "chalk": "^4.1.2", "collect-v8-coverage": "^1.0.2", "exit-x": "^0.2.2", - "glob": "^10.3.10", + "glob": "^10.5.0", "graceful-fs": "^4.2.11", "istanbul-lib-coverage": "^3.0.0", "istanbul-lib-instrument": "^6.0.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^5.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "30.2.0", - "jest-util": "30.2.0", - "jest-worker": "30.2.0", + "jest-message-util": "30.3.0", + "jest-util": "30.3.0", + "jest-worker": "30.3.0", "slash": "^3.0.0", "string-length": "^4.0.2", "v8-to-istanbul": "^9.0.1" @@ -1039,13 +1034,13 @@ } }, "node_modules/@jest/snapshot-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.2.0.tgz", - "integrity": "sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.3.0.tgz", + "integrity": "sha512-ORbRN9sf5PP82v3FXNSwmO1OTDR2vzR2YTaR+E3VkSBZ8zadQE6IqYdYEeFH1NIkeB2HIGdF02dapb6K0Mj05g==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", "natural-compare": "^1.4.0" @@ -1060,7 +1055,6 @@ "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "callsites": "^3.1.0", @@ -1071,15 +1065,14 @@ } }, "node_modules/@jest/test-result": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.2.0.tgz", - "integrity": "sha512-RF+Z+0CCHkARz5HT9mcQCBulb1wgCP3FBvl9VFokMX27acKphwyQsNuWH3c+ojd1LeWBLoTYoxF0zm6S/66mjg==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.3.0.tgz", + "integrity": "sha512-e/52nJGuD74AKTSe0P4y5wFRlaXP0qmrS17rqOMHeSwm278VyNyXE3gFO/4DTGF9w+65ra3lo3VKj0LBrzmgdQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@jest/console": "30.2.0", - "@jest/types": "30.2.0", + "@jest/console": "30.3.0", + "@jest/types": "30.3.0", "@types/istanbul-lib-coverage": "^2.0.6", "collect-v8-coverage": "^1.0.2" }, @@ -1088,16 +1081,15 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.2.0.tgz", - "integrity": "sha512-wXKgU/lk8fKXMu/l5Hog1R61bL4q5GCdT6OJvdAFz1P+QrpoFuLU68eoKuVc4RbrTtNnTL5FByhWdLgOPSph+Q==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.3.0.tgz", + "integrity": "sha512-dgbWy9b8QDlQeRZcv7LNF+/jFiiYHTKho1xirauZ7kVwY7avjFF6uTT0RqlgudB5OuIPagFdVtfFMosjVbk1eA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@jest/test-result": "30.2.0", + "@jest/test-result": "30.3.0", "graceful-fs": "^4.2.11", - "jest-haste-map": "30.2.0", + "jest-haste-map": "30.3.0", "slash": "^3.0.0" }, "engines": { @@ -1105,24 +1097,23 @@ } }, "node_modules/@jest/transform": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.2.0.tgz", - "integrity": "sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.3.0.tgz", + "integrity": "sha512-TLKY33fSLVd/lKB2YI1pH69ijyUblO/BQvCj566YvnwuzoTNr648iE0j22vRvVNk2HsPwByPxATg3MleS3gf5A==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.27.4", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@jridgewell/trace-mapping": "^0.3.25", "babel-plugin-istanbul": "^7.0.1", "chalk": "^4.1.2", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.11", - "jest-haste-map": "30.2.0", + "jest-haste-map": "30.3.0", "jest-regex-util": "30.0.1", - "jest-util": "30.2.0", - "micromatch": "^4.0.8", + "jest-util": "30.3.0", "pirates": "^4.0.7", "slash": "^3.0.0", "write-file-atomic": "^5.0.1" @@ -1132,9 +1123,9 @@ } }, "node_modules/@jest/types": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz", - "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.3.0.tgz", + "integrity": "sha512-JHm87k7bA33hpBngtU8h6UBub/fqqA9uXfw+21j5Hmk7ooPHlboRNxHq0JcMtC+n8VJGP1mcfnD3Mk+XKe1oSw==", "dev": true, "license": "MIT", "dependencies": { @@ -1231,7 +1222,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", @@ -1245,7 +1235,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "engines": { "node": ">=14" } @@ -1264,24 +1253,24 @@ } }, "node_modules/@prisma/adapter-better-sqlite3": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@prisma/adapter-better-sqlite3/-/adapter-better-sqlite3-7.4.2.tgz", - "integrity": "sha512-FkhPMbEieT/oCz2VYqn3LqZf0N1yBrFsAe4ZMkS/ZplBfwXLZclUxFrWjg50tTjqdEjWewTFN4xxYfxap7UW+g==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@prisma/adapter-better-sqlite3/-/adapter-better-sqlite3-7.5.0.tgz", + "integrity": "sha512-ThP6y1cAZW/BdHuuTKzO+j8vzEzXDMZaDPmboJyrkdbJvO9LRiHdnG5LNKAht8YYwjHgQoq7G7NtKbaW7NebVQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@prisma/driver-adapter-utils": "7.4.2", + "@prisma/driver-adapter-utils": "7.5.0", "better-sqlite3": "^12.6.0" } }, "node_modules/@prisma/client": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-7.4.2.tgz", - "integrity": "sha512-ts2mu+cQHriAhSxngO3StcYubBGTWDtu/4juZhXCUKOwgh26l+s4KD3vT2kMUzFyrYnll9u/3qWrtzRv9CGWzA==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-7.5.0.tgz", + "integrity": "sha512-h4hF9ctp+kSRs7ENHGsFQmHAgHcfkOCxbYt6Ti9Xi8x7D+kP4tTi9x51UKmiTH/OqdyJAO+8V+r+JA5AWdav7w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@prisma/client-runtime-utils": "7.4.2" + "@prisma/client-runtime-utils": "7.5.0" }, "engines": { "node": "^20.19 || ^22.12 || >=24.0" @@ -1300,9 +1289,9 @@ } }, "node_modules/@prisma/client-runtime-utils": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@prisma/client-runtime-utils/-/client-runtime-utils-7.4.2.tgz", - "integrity": "sha512-cID+rzOEb38VyMsx5LwJMEY4NGIrWCNpKu/0ImbeooQ2Px7TI+kOt7cm0NelxUzF2V41UVVXAmYjANZQtCu1/Q==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@prisma/client-runtime-utils/-/client-runtime-utils-7.5.0.tgz", + "integrity": "sha512-KnJ2b4Si/pcWEtK68uM+h0h1oh80CZt2suhLTVuLaSKg4n58Q9jBF/A42Kw6Ma+aThy1yAhfDeTC0JvEmeZnFQ==", "dev": true, "license": "Apache-2.0" }, @@ -1331,9 +1320,9 @@ } }, "node_modules/@prisma/config": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@prisma/config/-/config-7.4.2.tgz", - "integrity": "sha512-CftBjWxav99lzY1Z4oDgomdb1gh9BJFAOmWF6P2v1xRfXqQb56DfBub+QKcERRdNoAzCb3HXy3Zii8Vb4AsXhg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@prisma/config/-/config-7.5.0.tgz", + "integrity": "sha512-1J/9YEX7A889xM46PYg9e8VAuSL1IUmXJW3tEhMv7XQHDWlfC9YSkIw9sTYRaq5GswGlxZ+GnnyiNsUZ9JJhSQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1344,9 +1333,9 @@ } }, "node_modules/@prisma/debug": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-7.4.2.tgz", - "integrity": "sha512-aP7qzu+g/JnbF6U69LMwHoUkELiserKmWsE2shYuEpNUJ4GrtxBCvZwCyCBHFSH2kLTF2l1goBlBh4wuvRq62w==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-7.5.0.tgz", + "integrity": "sha512-163+nffny0JoPEkDhfNco0vcuT3ymIJc9+WX7MHSQhfkeKUmKe9/wqvGk5SjppT93DtBjVwr5HPJYlXbzm6qtg==", "dev": true, "license": "Apache-2.0" }, @@ -1377,66 +1366,66 @@ } }, "node_modules/@prisma/driver-adapter-utils": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@prisma/driver-adapter-utils/-/driver-adapter-utils-7.4.2.tgz", - "integrity": "sha512-REdjFpT/ye9KdDs+CXAXPIbMQkVLhne9G5Pe97sNY4Ovx4r2DAbWM9hOFvvB1Oq8H8bOCdu0Ri3AoGALquQqVw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@prisma/driver-adapter-utils/-/driver-adapter-utils-7.5.0.tgz", + "integrity": "sha512-B79N/amgV677mFesFDBAdrW0OIaqawap9E0sjgLBtzIz2R3hIMS1QB8mLZuUEiS4q5Y8Oh3I25Kw4SLxMypk9Q==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "7.4.2" + "@prisma/debug": "7.5.0" } }, "node_modules/@prisma/engines": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-7.4.2.tgz", - "integrity": "sha512-B+ZZhI4rXlzjVqRw/93AothEKOU5/x4oVyJFGo9RpHPnBwaPwk4Pi0Q4iGXipKxeXPs/dqljgNBjK0m8nocOJA==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-7.5.0.tgz", + "integrity": "sha512-ondGRhzoaVpRWvFaQ5wH5zS1BIbhzbKqczKjCn6j3L0Zfe/LInjcEg8+xtB49AuZBX30qyx1ZtGoootUohz2pw==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "7.4.2", - "@prisma/engines-version": "7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919", - "@prisma/fetch-engine": "7.4.2", - "@prisma/get-platform": "7.4.2" + "@prisma/debug": "7.5.0", + "@prisma/engines-version": "7.5.0-15.280c870be64f457428992c43c1f6d557fab6e29e", + "@prisma/fetch-engine": "7.5.0", + "@prisma/get-platform": "7.5.0" } }, "node_modules/@prisma/engines-version": { - "version": "7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919.tgz", - "integrity": "sha512-5FIKY3KoYQlBuZC2yc16EXfVRQ8HY+fLqgxkYfWCtKhRb3ajCRzP/rPeoSx11+NueJDANdh4hjY36mdmrTcGSg==", + "version": "7.5.0-15.280c870be64f457428992c43c1f6d557fab6e29e", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-7.5.0-15.280c870be64f457428992c43c1f6d557fab6e29e.tgz", + "integrity": "sha512-E+iRV/vbJLl8iGjVr6g/TEWokA+gjkV/doZkaQN1i/ULVdDwGnPJDfLUIFGS3BVwlG/m6L8T4x1x5isl8hGMxA==", "dev": true, "license": "Apache-2.0" }, "node_modules/@prisma/engines/node_modules/@prisma/get-platform": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.4.2.tgz", - "integrity": "sha512-UTnChXRwiauzl/8wT4hhe7Xmixja9WE28oCnGpBtRejaHhvekx5kudr3R4Y9mLSA0kqGnAMeyTiKwDVMjaEVsw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.5.0.tgz", + "integrity": "sha512-7I+2y1nu/gkEKSiHHbcZ1HPe/euGdEqJZxEEMT0246q4De1+hla0ZzlTgvaT9dHcVCgLSuCG8v39db5qUUWNgw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "7.4.2" + "@prisma/debug": "7.5.0" } }, "node_modules/@prisma/fetch-engine": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-7.4.2.tgz", - "integrity": "sha512-f/c/MwYpdJO7taLETU8rahEstLeXfYgQGlz5fycG7Fbmva3iPdzGmjiSWHeSWIgNnlXnelUdCJqyZnFocurZuA==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-7.5.0.tgz", + "integrity": "sha512-kZCl2FV54qnyrVdnII8MI6qvt7HfU6Cbiz8dZ8PXz4f4lbSw45jEB9/gEMK2SGdiNhBKyk/Wv95uthoLhGMLYA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "7.4.2", - "@prisma/engines-version": "7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919", - "@prisma/get-platform": "7.4.2" + "@prisma/debug": "7.5.0", + "@prisma/engines-version": "7.5.0-15.280c870be64f457428992c43c1f6d557fab6e29e", + "@prisma/get-platform": "7.5.0" } }, "node_modules/@prisma/fetch-engine/node_modules/@prisma/get-platform": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.4.2.tgz", - "integrity": "sha512-UTnChXRwiauzl/8wT4hhe7Xmixja9WE28oCnGpBtRejaHhvekx5kudr3R4Y9mLSA0kqGnAMeyTiKwDVMjaEVsw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.5.0.tgz", + "integrity": "sha512-7I+2y1nu/gkEKSiHHbcZ1HPe/euGdEqJZxEEMT0246q4De1+hla0ZzlTgvaT9dHcVCgLSuCG8v39db5qUUWNgw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "7.4.2" + "@prisma/debug": "7.5.0" } }, "node_modules/@prisma/get-platform": { @@ -1464,11 +1453,15 @@ "license": "Apache-2.0" }, "node_modules/@prisma/studio-core": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/@prisma/studio-core/-/studio-core-0.13.1.tgz", - "integrity": "sha512-agdqaPEePRHcQ7CexEfkX1RvSH9uWDb6pXrZnhCRykhDFAV0/0P3d07WtfiY8hZWb7oRU4v+NkT4cGFHkQJIPg==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@prisma/studio-core/-/studio-core-0.21.1.tgz", + "integrity": "sha512-bOGqG/eMQtKC0XVvcVLRmhWWzm/I+0QUWqAEhEBtetpuS3k3V4IWqKGUONkAIT223DNXJMxMtZp36b1FmcdPeg==", "dev": true, "license": "Apache-2.0", + "engines": { + "node": "^20.19 || ^22.12 || ^24.0", + "pnpm": "8" + }, "peerDependencies": { "@types/react": "^18.0.0 || ^19.0.0", "react": "^18.0.0 || ^19.0.0", @@ -1540,9 +1533,9 @@ "license": "BSD-3-Clause" }, "node_modules/@sinclair/typebox": { - "version": "0.34.41", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.41.tgz", - "integrity": "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==", + "version": "0.34.48", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.48.tgz", + "integrity": "sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA==", "dev": true, "license": "MIT" }, @@ -1557,9 +1550,9 @@ } }, "node_modules/@sinonjs/fake-timers": { - "version": "13.0.5", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", - "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-15.1.1.tgz", + "integrity": "sha512-cO5W33JgAPbOh07tvZjUOJ7oWhtaqGHiZw+11DPbyqh2kHTBc3eF/CjJDeQ4205RLQsX6rxCuYOroFQwl7JDRw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -1622,7 +1615,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "tslib": "^2.4.0" } @@ -1633,7 +1625,6 @@ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", @@ -1648,7 +1639,6 @@ "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/types": "^7.0.0" } @@ -1659,7 +1649,6 @@ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" @@ -1671,7 +1660,6 @@ "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/types": "^7.28.2" } @@ -1715,18 +1703,19 @@ } }, "node_modules/@types/node": { - "version": "24.11.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.11.0.tgz", - "integrity": "sha512-fPxQqz4VTgPI/IQ+lj9r0h+fDR66bzoeMGHp8ASee+32OSGIkeASsoZuJixsQoVef1QJbeubcPBxKk22QVoWdw==", + "version": "24.12.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.0.tgz", + "integrity": "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==", "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.16.0" } }, "node_modules/@types/react": { - "version": "19.2.8", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.8.tgz", - "integrity": "sha512-3MbSL37jEchWZz2p2mjntRZtPt837ij10ApxKfgmXCTuHWagYg7iA5bqPw6C8BMPfwidlvfPI/fxOc42HLhcyg==", + "version": "19.2.14", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", + "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", "dev": true, "license": "MIT", "peer": true, @@ -1777,8 +1766,7 @@ "optional": true, "os": [ "android" - ], - "peer": true + ] }, "node_modules/@unrs/resolver-binding-android-arm64": { "version": "1.11.1", @@ -1792,8 +1780,7 @@ "optional": true, "os": [ "android" - ], - "peer": true + ] }, "node_modules/@unrs/resolver-binding-darwin-arm64": { "version": "1.11.1", @@ -1807,8 +1794,7 @@ "optional": true, "os": [ "darwin" - ], - "peer": true + ] }, "node_modules/@unrs/resolver-binding-darwin-x64": { "version": "1.11.1", @@ -1822,8 +1808,7 @@ "optional": true, "os": [ "darwin" - ], - "peer": true + ] }, "node_modules/@unrs/resolver-binding-freebsd-x64": { "version": "1.11.1", @@ -1837,8 +1822,7 @@ "optional": true, "os": [ "freebsd" - ], - "peer": true + ] }, "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { "version": "1.11.1", @@ -1852,8 +1836,7 @@ "optional": true, "os": [ "linux" - ], - "peer": true + ] }, "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { "version": "1.11.1", @@ -1867,8 +1850,7 @@ "optional": true, "os": [ "linux" - ], - "peer": true + ] }, "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { "version": "1.11.1", @@ -1882,8 +1864,7 @@ "optional": true, "os": [ "linux" - ], - "peer": true + ] }, "node_modules/@unrs/resolver-binding-linux-arm64-musl": { "version": "1.11.1", @@ -1897,8 +1878,7 @@ "optional": true, "os": [ "linux" - ], - "peer": true + ] }, "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { "version": "1.11.1", @@ -1912,8 +1892,7 @@ "optional": true, "os": [ "linux" - ], - "peer": true + ] }, "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { "version": "1.11.1", @@ -1927,8 +1906,7 @@ "optional": true, "os": [ "linux" - ], - "peer": true + ] }, "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { "version": "1.11.1", @@ -1942,8 +1920,7 @@ "optional": true, "os": [ "linux" - ], - "peer": true + ] }, "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { "version": "1.11.1", @@ -1957,8 +1934,7 @@ "optional": true, "os": [ "linux" - ], - "peer": true + ] }, "node_modules/@unrs/resolver-binding-linux-x64-gnu": { "version": "1.11.1", @@ -1972,8 +1948,7 @@ "optional": true, "os": [ "linux" - ], - "peer": true + ] }, "node_modules/@unrs/resolver-binding-linux-x64-musl": { "version": "1.11.1", @@ -1987,8 +1962,7 @@ "optional": true, "os": [ "linux" - ], - "peer": true + ] }, "node_modules/@unrs/resolver-binding-wasm32-wasi": { "version": "1.11.1", @@ -2000,7 +1974,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "@napi-rs/wasm-runtime": "^0.2.11" }, @@ -2020,8 +1993,7 @@ "optional": true, "os": [ "win32" - ], - "peer": true + ] }, "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { "version": "1.11.1", @@ -2035,8 +2007,7 @@ "optional": true, "os": [ "win32" - ], - "peer": true + ] }, "node_modules/@unrs/resolver-binding-win32-x64-msvc": { "version": "1.11.1", @@ -2050,13 +2021,12 @@ "optional": true, "os": [ "win32" - ], - "peer": true + ] }, "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", "bin": { @@ -2067,9 +2037,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", "dev": true, "license": "MIT", "dependencies": { @@ -2085,7 +2055,6 @@ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "type-fest": "^0.21.3" }, @@ -2102,7 +2071,6 @@ "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -2139,6 +2107,19 @@ "node": ">= 8" } }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -2167,17 +2148,16 @@ } }, "node_modules/babel-jest": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.2.0.tgz", - "integrity": "sha512-0YiBEOxWqKkSQWL9nNGGEgndoeL0ZpWrbLMNL5u/Kaxrli3Eaxlt3ZtIDktEvXt4L/R9r3ODr2zKwGM/2BjxVw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.3.0.tgz", + "integrity": "sha512-gRpauEU2KRrCox5Z296aeVHR4jQ98BCnu0IO332D/xpHNOsIH/bgSRk9k6GbKIbBw8vFeN6ctuu6tV8WOyVfYQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@jest/transform": "30.2.0", + "@jest/transform": "30.3.0", "@types/babel__core": "^7.20.5", "babel-plugin-istanbul": "^7.0.1", - "babel-preset-jest": "30.2.0", + "babel-preset-jest": "30.3.0", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", "slash": "^3.0.0" @@ -2210,12 +2190,11 @@ } }, "node_modules/babel-plugin-jest-hoist": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.2.0.tgz", - "integrity": "sha512-ftzhzSGMUnOzcCXd6WHdBGMyuwy15Wnn0iyyWGKgBDLxf9/s5ABuraCSpBX2uG0jUg4rqJnxsLc5+oYBqoxVaA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.3.0.tgz", + "integrity": "sha512-+TRkByhsws6sfPjVaitzadk1I0F5sPvOVUH5tyTSzhePpsGIVrdeunHSw/C36QeocS95OOk8lunc4rlu5Anwsg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/babel__core": "^7.20.5" }, @@ -2251,14 +2230,13 @@ } }, "node_modules/babel-preset-jest": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.2.0.tgz", - "integrity": "sha512-US4Z3NOieAQumwFnYdUWKvUKh8+YSnS/gB3t6YBiz0bskpu7Pine8pPCheNxlPEW4wnUkma2a94YuW2q3guvCQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.3.0.tgz", + "integrity": "sha512-6ZcUbWHC+dMz2vfzdNwi87Z1gQsLNK2uLuK1Q89R11xdvejcivlYYwDlEv0FHX3VwEXpbBQ9uufB/MUNpZGfhQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "babel-plugin-jest-hoist": "30.2.0", + "babel-plugin-jest-hoist": "30.3.0", "babel-preset-current-node-syntax": "^1.2.0" }, "engines": { @@ -2297,19 +2275,22 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.9.11", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.11.tgz", - "integrity": "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==", + "version": "2.10.11", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.11.tgz", + "integrity": "sha512-DAKrHphkJyiGuau/cFieRYhcTFeK/lBuD++C7cZ6KZHbMhBrisoi+EvhQ5RZrIfV5qwsW8kgQ07JIC+MDJRAhg==", "dev": true, "license": "Apache-2.0", "bin": { - "baseline-browser-mapping": "dist/cli.js" + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" } }, "node_modules/better-sqlite3": { - "version": "12.6.2", - "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.6.2.tgz", - "integrity": "sha512-8VYKM3MjCa9WcaSAI3hzwhmyHVlH8tiGFwf0RlTsZPWJ1I5MkzjiudCo4KC4DxOaL/53A5B1sI/IbldNFDbsKA==", + "version": "12.8.0", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.8.0.tgz", + "integrity": "sha512-RxD2Vd96sQDjQr20kdP+F+dK/1OUNiVOl200vKBZY8u0vTwysfolF6Hq+3ZK2+h8My9YvZhHsF+RSGZW2VYrPQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -2349,24 +2330,10 @@ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "balanced-match": "^1.0.0" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/browserslist": { "version": "4.28.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", @@ -2387,6 +2354,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -2454,8 +2422,7 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/c12": { "version": "3.1.0", @@ -2492,7 +2459,6 @@ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -2508,9 +2474,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001761", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001761.tgz", - "integrity": "sha512-JF9ptu1vP2coz98+5051jZ4PwQgd2ni8A+gYSN7EA7dPKIMf0pDlSUxhdmVOaV3/fYK5uWBkgSXJaRLr4+3A6g==", + "version": "1.0.30001781", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001781.tgz", + "integrity": "sha512-RdwNCyMsNBftLjW6w01z8bKEvT6e/5tpPVEgtn22TiLGlstHOVecsX2KHFkD5e/vRnIE4EGzpuIODb3mtswtkw==", "dev": true, "funding": [ { @@ -2551,7 +2517,6 @@ "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" } @@ -2595,9 +2560,9 @@ "license": "ISC" }, "node_modules/ci-info": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", - "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", + "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", "dev": true, "funding": [ { @@ -2621,12 +2586,11 @@ } }, "node_modules/cjs-module-lexer": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.1.1.tgz", - "integrity": "sha512-+CmxIZ/L2vNcEfvNtLdU0ZQ6mbq3FZnwAP2PPTiKP+1QOoKwlKlPgb8UKV0Dds7QVaMnHm+FwSft2VB0s/SLjQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz", + "integrity": "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/cliui": { "version": "8.0.1", @@ -2706,7 +2670,6 @@ "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "iojs": ">= 1.0.0", "node": ">= 0.12.0" @@ -2717,8 +2680,7 @@ "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/color-convert": { "version": "2.0.1", @@ -2746,9 +2708,9 @@ "license": "MIT" }, "node_modules/confbox": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", - "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.4.tgz", + "integrity": "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==", "dev": true, "license": "MIT" }, @@ -2796,8 +2758,7 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/debug": { "version": "4.4.3", @@ -2834,12 +2795,11 @@ } }, "node_modules/dedent": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.1.tgz", - "integrity": "sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz", + "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==", "dev": true, "license": "MIT", - "peer": true, "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, @@ -2865,7 +2825,6 @@ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -2920,15 +2879,14 @@ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } }, "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -2953,8 +2911,7 @@ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/effect": { "version": "3.18.4", @@ -2968,9 +2925,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.267", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", - "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", + "version": "1.5.325", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.325.tgz", + "integrity": "sha512-PwfIw7WQSt3xX7yOf5OE/unLzsK9CaN2f/FvV3WjPR1Knoc1T9vePRVV4W1EM301JzzysK51K7FNKcusCr0zYA==", "dev": true, "license": "ISC" }, @@ -2980,7 +2937,6 @@ "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -2993,8 +2949,7 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/empathic": { "version": "2.0.0", @@ -3022,7 +2977,6 @@ "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "is-arrayish": "^0.2.1" } @@ -3066,7 +3020,6 @@ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -3090,8 +3043,7 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true, - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/exit-x": { "version": "0.2.2", @@ -3099,7 +3051,6 @@ "integrity": "sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">= 0.8.0" } @@ -3115,18 +3066,18 @@ } }, "node_modules/expect": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz", - "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.3.0.tgz", + "integrity": "sha512-1zQrciTiQfRdo7qJM1uG4navm8DayFa2TgCSRlzUyNkhcJ6XUZF3hjnpkyr3VhAqPH7i/9GkG7Tv5abz6fqz0Q==", "dev": true, "license": "MIT", "dependencies": { - "@jest/expect-utils": "30.2.0", + "@jest/expect-utils": "30.3.0", "@jest/get-type": "30.1.0", - "jest-matcher-utils": "30.2.0", - "jest-message-util": "30.2.0", - "jest-mock": "30.2.0", - "jest-util": "30.2.0" + "jest-matcher-utils": "30.3.0", + "jest-message-util": "30.3.0", + "jest-mock": "30.3.0", + "jest-util": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -3213,19 +3164,6 @@ "dev": true, "license": "MIT" }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -3338,7 +3276,6 @@ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -3375,9 +3312,9 @@ "version": "10.5.0", "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", @@ -3408,10 +3345,11 @@ "license": "MIT" }, "node_modules/graphmatch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/graphmatch/-/graphmatch-1.1.0.tgz", - "integrity": "sha512-0E62MaTW5rPZVRLyIJZG/YejmdA/Xr1QydHEw3Vt+qOKkMIOE8WDLc9ZX2bmAjtJFZcId4lEdrdmASsEy7D1QA==", - "dev": true + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/graphmatch/-/graphmatch-1.1.1.tgz", + "integrity": "sha512-5ykVn/EXM1hF0XCaWh05VbYvEiOL2lY1kBxZtaYsyvjp7cmWOU1XsAdfQBwClraEofXDT197lFbXOEVMHpvQOg==", + "dev": true, + "license": "MIT" }, "node_modules/handlebars": { "version": "4.7.8", @@ -3451,6 +3389,7 @@ "integrity": "sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=16.9.0" } @@ -3460,8 +3399,7 @@ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/http-status-codes": { "version": "2.3.0", @@ -3476,7 +3414,6 @@ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, "license": "Apache-2.0", - "peer": true, "engines": { "node": ">=10.17.0" } @@ -3525,7 +3462,6 @@ "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" @@ -3581,8 +3517,7 @@ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", @@ -3599,21 +3534,10 @@ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, "node_modules/is-property": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", @@ -3627,7 +3551,6 @@ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" }, @@ -3670,9 +3593,9 @@ } }, "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "dev": true, "license": "ISC", "bin": { @@ -3688,7 +3611,6 @@ "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "license": "BSD-3-Clause", - "peer": true, "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^4.0.0", @@ -3704,7 +3626,6 @@ "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", "dev": true, "license": "BSD-3-Clause", - "peer": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.23", "debug": "^4.1.1", @@ -3720,7 +3641,6 @@ "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", "dev": true, "license": "BSD-3-Clause", - "peer": true, "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" @@ -3735,7 +3655,6 @@ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, "license": "BlueOak-1.0.0", - "peer": true, "dependencies": { "@isaacs/cliui": "^8.0.2" }, @@ -3747,17 +3666,17 @@ } }, "node_modules/jest": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-30.2.0.tgz", - "integrity": "sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-30.3.0.tgz", + "integrity": "sha512-AkXIIFcaazymvey2i/+F94XRnM6TsVLZDhBMLsd1Sf/W0wzsvvpjeyUrCZD6HGG4SDYPgDJDBKeiJTBb10WzMg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@jest/core": "30.2.0", - "@jest/types": "30.2.0", + "@jest/core": "30.3.0", + "@jest/types": "30.3.0", "import-local": "^3.2.0", - "jest-cli": "30.2.0" + "jest-cli": "30.3.0" }, "bin": { "jest": "bin/jest.js" @@ -3775,15 +3694,14 @@ } }, "node_modules/jest-changed-files": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.2.0.tgz", - "integrity": "sha512-L8lR1ChrRnSdfeOvTrwZMlnWV8G/LLjQ0nG9MBclwWZidA2N5FviRki0Bvh20WRMOX31/JYvzdqTJrk5oBdydQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.3.0.tgz", + "integrity": "sha512-B/7Cny6cV5At6M25EWDgf9S617lHivamL8vl6KEpJqkStauzcG4e+WPfDgMMF+H4FVH4A2PLRyvgDJan4441QA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "execa": "^5.1.1", - "jest-util": "30.2.0", + "jest-util": "30.3.0", "p-limit": "^3.1.0" }, "engines": { @@ -3791,30 +3709,29 @@ } }, "node_modules/jest-circus": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.2.0.tgz", - "integrity": "sha512-Fh0096NC3ZkFx05EP2OXCxJAREVxj1BcW/i6EWqqymcgYKWjyyDpral3fMxVcHXg6oZM7iULer9wGRFvfpl+Tg==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.3.0.tgz", + "integrity": "sha512-PyXq5szeSfR/4f1lYqCmmQjh0vqDkURUYi9N6whnHjlRz4IUQfMcXkGLeEoiJtxtyPqgUaUUfyQlApXWBSN1RA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@jest/environment": "30.2.0", - "@jest/expect": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/types": "30.2.0", + "@jest/environment": "30.3.0", + "@jest/expect": "30.3.0", + "@jest/test-result": "30.3.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "co": "^4.6.0", "dedent": "^1.6.0", "is-generator-fn": "^2.1.0", - "jest-each": "30.2.0", - "jest-matcher-utils": "30.2.0", - "jest-message-util": "30.2.0", - "jest-runtime": "30.2.0", - "jest-snapshot": "30.2.0", - "jest-util": "30.2.0", + "jest-each": "30.3.0", + "jest-matcher-utils": "30.3.0", + "jest-message-util": "30.3.0", + "jest-runtime": "30.3.0", + "jest-snapshot": "30.3.0", + "jest-util": "30.3.0", "p-limit": "^3.1.0", - "pretty-format": "30.2.0", + "pretty-format": "30.3.0", "pure-rand": "^7.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" @@ -3824,22 +3741,21 @@ } }, "node_modules/jest-cli": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.2.0.tgz", - "integrity": "sha512-Os9ukIvADX/A9sLt6Zse3+nmHtHaE6hqOsjQtNiugFTbKRHYIYtZXNGNK9NChseXy7djFPjndX1tL0sCTlfpAA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.3.0.tgz", + "integrity": "sha512-l6Tqx+j1fDXJEW5bqYykDQQ7mQg+9mhWXtnj+tQZrTWYHyHoi6Be8HPumDSA+UiX2/2buEgjA58iJzdj146uCw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@jest/core": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/types": "30.2.0", + "@jest/core": "30.3.0", + "@jest/test-result": "30.3.0", + "@jest/types": "30.3.0", "chalk": "^4.1.2", "exit-x": "^0.2.2", "import-local": "^3.2.0", - "jest-config": "30.2.0", - "jest-util": "30.2.0", - "jest-validate": "30.2.0", + "jest-config": "30.3.0", + "jest-util": "30.3.0", + "jest-validate": "30.3.0", "yargs": "^17.7.2" }, "bin": { @@ -3858,35 +3774,33 @@ } }, "node_modules/jest-config": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.2.0.tgz", - "integrity": "sha512-g4WkyzFQVWHtu6uqGmQR4CQxz/CH3yDSlhzXMWzNjDx843gYjReZnMRanjRCq5XZFuQrGDxgUaiYWE8BRfVckA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.3.0.tgz", + "integrity": "sha512-WPMAkMAtNDY9P/oKObtsRG/6KTrhtgPJoBTmk20uDn4Uy6/3EJnnaZJre/FMT1KVRx8cve1r7/FlMIOfRVWL4w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/core": "^7.27.4", "@jest/get-type": "30.1.0", "@jest/pattern": "30.0.1", - "@jest/test-sequencer": "30.2.0", - "@jest/types": "30.2.0", - "babel-jest": "30.2.0", + "@jest/test-sequencer": "30.3.0", + "@jest/types": "30.3.0", + "babel-jest": "30.3.0", "chalk": "^4.1.2", "ci-info": "^4.2.0", "deepmerge": "^4.3.1", - "glob": "^10.3.10", + "glob": "^10.5.0", "graceful-fs": "^4.2.11", - "jest-circus": "30.2.0", + "jest-circus": "30.3.0", "jest-docblock": "30.2.0", - "jest-environment-node": "30.2.0", + "jest-environment-node": "30.3.0", "jest-regex-util": "30.0.1", - "jest-resolve": "30.2.0", - "jest-runner": "30.2.0", - "jest-util": "30.2.0", - "jest-validate": "30.2.0", - "micromatch": "^4.0.8", + "jest-resolve": "30.3.0", + "jest-runner": "30.3.0", + "jest-util": "30.3.0", + "jest-validate": "30.3.0", "parse-json": "^5.2.0", - "pretty-format": "30.2.0", + "pretty-format": "30.3.0", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -3911,16 +3825,16 @@ } }, "node_modules/jest-diff": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", - "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.3.0.tgz", + "integrity": "sha512-n3q4PDQjS4LrKxfWB3Z5KNk1XjXtZTBwQp71OP0Jo03Z6V60x++K5L8k6ZrW8MY8pOFylZvHM0zsjS1RqlHJZQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/diff-sequences": "30.0.1", + "@jest/diff-sequences": "30.3.0", "@jest/get-type": "30.1.0", "chalk": "^4.1.2", - "pretty-format": "30.2.0" + "pretty-format": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -3932,7 +3846,6 @@ "integrity": "sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "detect-newline": "^3.1.0" }, @@ -3941,59 +3854,57 @@ } }, "node_modules/jest-each": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.2.0.tgz", - "integrity": "sha512-lpWlJlM7bCUf1mfmuqTA8+j2lNURW9eNafOy99knBM01i5CQeY5UH1vZjgT9071nDJac1M4XsbyI44oNOdhlDQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.3.0.tgz", + "integrity": "sha512-V8eMndg/aZ+3LnCJgSm13IxS5XSBM22QSZc9BtPK8Dek6pm+hfUNfwBdvsB3d342bo1q7wnSkC38zjX259qZNA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/get-type": "30.1.0", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "chalk": "^4.1.2", - "jest-util": "30.2.0", - "pretty-format": "30.2.0" + "jest-util": "30.3.0", + "pretty-format": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-environment-node": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.2.0.tgz", - "integrity": "sha512-ElU8v92QJ9UrYsKrxDIKCxu6PfNj4Hdcktcn0JX12zqNdqWHB0N+hwOnnBBXvjLd2vApZtuLUGs1QSY+MsXoNA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.3.0.tgz", + "integrity": "sha512-4i6HItw/JSiJVsC5q0hnKIe/hbYfZLVG9YJ/0pU9Hz2n/9qZe3Rhn5s5CUZA5ORZlcdT/vmAXRMyONXJwPrmYQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@jest/environment": "30.2.0", - "@jest/fake-timers": "30.2.0", - "@jest/types": "30.2.0", + "@jest/environment": "30.3.0", + "@jest/fake-timers": "30.3.0", + "@jest/types": "30.3.0", "@types/node": "*", - "jest-mock": "30.2.0", - "jest-util": "30.2.0", - "jest-validate": "30.2.0" + "jest-mock": "30.3.0", + "jest-util": "30.3.0", + "jest-validate": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-haste-map": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.2.0.tgz", - "integrity": "sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.3.0.tgz", + "integrity": "sha512-mMi2oqG4KRU0R9QEtscl87JzMXfUhbKaFqOxmjb2CKcbHcUGFrJCBWHmnTiUqi6JcnzoBlO4rWfpdl2k/RfLCA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "anymatch": "^3.1.3", "fb-watchman": "^2.0.2", "graceful-fs": "^4.2.11", "jest-regex-util": "30.0.1", - "jest-util": "30.2.0", - "jest-worker": "30.2.0", - "micromatch": "^4.0.8", + "jest-util": "30.3.0", + "jest-worker": "30.3.0", + "picomatch": "^4.0.3", "walker": "^1.0.8" }, "engines": { @@ -4004,50 +3915,49 @@ } }, "node_modules/jest-leak-detector": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.2.0.tgz", - "integrity": "sha512-M6jKAjyzjHG0SrQgwhgZGy9hFazcudwCNovY/9HPIicmNSBuockPSedAP9vlPK6ONFJ1zfyH/M2/YYJxOz5cdQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.3.0.tgz", + "integrity": "sha512-cuKmUUGIjfXZAiGJ7TbEMx0bcqNdPPI6P1V+7aF+m/FUJqFDxkFR4JqkTu8ZOiU5AaX/x0hZ20KaaIPXQzbMGQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/get-type": "30.1.0", - "pretty-format": "30.2.0" + "pretty-format": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", - "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.3.0.tgz", + "integrity": "sha512-HEtc9uFQgaUHkC7nLSlQL3Tph4Pjxt/yiPvkIrrDCt9jhoLIgxaubo1G+CFOnmHYMxHwwdaSN7mkIFs6ZK8OhA==", "dev": true, "license": "MIT", "dependencies": { "@jest/get-type": "30.1.0", "chalk": "^4.1.2", - "jest-diff": "30.2.0", - "pretty-format": "30.2.0" + "jest-diff": "30.3.0", + "pretty-format": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.3.0.tgz", + "integrity": "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/stack-utils": "^2.0.3", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", + "picomatch": "^4.0.3", + "pretty-format": "30.3.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" }, @@ -4056,15 +3966,15 @@ } }, "node_modules/jest-mock": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz", - "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.3.0.tgz", + "integrity": "sha512-OTzICK8CpE+t4ndhKrwlIdbM6Pn8j00lvmSmq5ejiO+KxukbLjgOflKWMn3KE34EZdQm5RqTuKj+5RIEniYhog==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", - "jest-util": "30.2.0" + "jest-util": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -4076,7 +3986,6 @@ "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6" }, @@ -4100,19 +4009,18 @@ } }, "node_modules/jest-resolve": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.2.0.tgz", - "integrity": "sha512-TCrHSxPlx3tBY3hWNtRQKbtgLhsXa1WmbJEqBlTBrGafd5fiQFByy2GNCEoGR+Tns8d15GaL9cxEzKOO3GEb2A==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.3.0.tgz", + "integrity": "sha512-NRtTAHQlpd15F9rUR36jqwelbrDV/dY4vzNte3S2kxCKUJRYNd5/6nTSbYiak1VX5g8IoFF23Uj5TURkUW8O5g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "jest-haste-map": "30.2.0", + "jest-haste-map": "30.3.0", "jest-pnp-resolver": "^1.2.3", - "jest-util": "30.2.0", - "jest-validate": "30.2.0", + "jest-util": "30.3.0", + "jest-validate": "30.3.0", "slash": "^3.0.0", "unrs-resolver": "^1.7.11" }, @@ -4121,48 +4029,46 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.2.0.tgz", - "integrity": "sha512-xTOIGug/0RmIe3mmCqCT95yO0vj6JURrn1TKWlNbhiAefJRWINNPgwVkrVgt/YaerPzY3iItufd80v3lOrFJ2w==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.3.0.tgz", + "integrity": "sha512-9ev8s3YN6Hsyz9LV75XUwkCVFlwPbaFn6Wp75qnI0wzAINYWY8Fb3+6y59Rwd3QaS3kKXffHXsZMziMavfz/nw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "jest-regex-util": "30.0.1", - "jest-snapshot": "30.2.0" + "jest-snapshot": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-runner": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.2.0.tgz", - "integrity": "sha512-PqvZ2B2XEyPEbclp+gV6KO/F1FIFSbIwewRgmROCMBo/aZ6J1w8Qypoj2pEOcg3G2HzLlaP6VUtvwCI8dM3oqQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.3.0.tgz", + "integrity": "sha512-gDv6C9LGKWDPLia9TSzZwf4h3kMQCqyTpq+95PODnTRDO0g9os48XIYYkS6D236vjpBir2fF63YmJFtqkS5Duw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@jest/console": "30.2.0", - "@jest/environment": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", + "@jest/console": "30.3.0", + "@jest/environment": "30.3.0", + "@jest/test-result": "30.3.0", + "@jest/transform": "30.3.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "emittery": "^0.13.1", "exit-x": "^0.2.2", "graceful-fs": "^4.2.11", "jest-docblock": "30.2.0", - "jest-environment-node": "30.2.0", - "jest-haste-map": "30.2.0", - "jest-leak-detector": "30.2.0", - "jest-message-util": "30.2.0", - "jest-resolve": "30.2.0", - "jest-runtime": "30.2.0", - "jest-util": "30.2.0", - "jest-watcher": "30.2.0", - "jest-worker": "30.2.0", + "jest-environment-node": "30.3.0", + "jest-haste-map": "30.3.0", + "jest-leak-detector": "30.3.0", + "jest-message-util": "30.3.0", + "jest-resolve": "30.3.0", + "jest-runtime": "30.3.0", + "jest-util": "30.3.0", + "jest-watcher": "30.3.0", + "jest-worker": "30.3.0", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -4171,33 +4077,32 @@ } }, "node_modules/jest-runtime": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.2.0.tgz", - "integrity": "sha512-p1+GVX/PJqTucvsmERPMgCPvQJpFt4hFbM+VN3n8TMo47decMUcJbt+rgzwrEme0MQUA/R+1de2axftTHkKckg==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.3.0.tgz", + "integrity": "sha512-CgC+hIBJbuh78HEffkhNKcbXAytQViplcl8xupqeIWyKQF50kCQA8J7GeJCkjisC6hpnC9Muf8jV5RdtdFbGng==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@jest/environment": "30.2.0", - "@jest/fake-timers": "30.2.0", - "@jest/globals": "30.2.0", + "@jest/environment": "30.3.0", + "@jest/fake-timers": "30.3.0", + "@jest/globals": "30.3.0", "@jest/source-map": "30.0.1", - "@jest/test-result": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", + "@jest/test-result": "30.3.0", + "@jest/transform": "30.3.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "cjs-module-lexer": "^2.1.0", "collect-v8-coverage": "^1.0.2", - "glob": "^10.3.10", + "glob": "^10.5.0", "graceful-fs": "^4.2.11", - "jest-haste-map": "30.2.0", - "jest-message-util": "30.2.0", - "jest-mock": "30.2.0", + "jest-haste-map": "30.3.0", + "jest-message-util": "30.3.0", + "jest-mock": "30.3.0", "jest-regex-util": "30.0.1", - "jest-resolve": "30.2.0", - "jest-snapshot": "30.2.0", - "jest-util": "30.2.0", + "jest-resolve": "30.3.0", + "jest-snapshot": "30.3.0", + "jest-util": "30.3.0", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -4206,9 +4111,9 @@ } }, "node_modules/jest-snapshot": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.2.0.tgz", - "integrity": "sha512-5WEtTy2jXPFypadKNpbNkZ72puZCa6UjSr/7djeecHWOu7iYhSXSnHScT8wBz3Rn8Ena5d5RYRcsyKIeqG1IyA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.3.0.tgz", + "integrity": "sha512-f14c7atpb4O2DeNhwcvS810Y63wEn8O1HqK/luJ4F6M4NjvxmAKQwBUWjbExUtMxWJQ0wVgmCKymeJK6NZMnfQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4217,20 +4122,20 @@ "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1", "@babel/types": "^7.27.3", - "@jest/expect-utils": "30.2.0", + "@jest/expect-utils": "30.3.0", "@jest/get-type": "30.1.0", - "@jest/snapshot-utils": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", + "@jest/snapshot-utils": "30.3.0", + "@jest/transform": "30.3.0", + "@jest/types": "30.3.0", "babel-preset-current-node-syntax": "^1.2.0", "chalk": "^4.1.2", - "expect": "30.2.0", + "expect": "30.3.0", "graceful-fs": "^4.2.11", - "jest-diff": "30.2.0", - "jest-matcher-utils": "30.2.0", - "jest-message-util": "30.2.0", - "jest-util": "30.2.0", - "pretty-format": "30.2.0", + "jest-diff": "30.3.0", + "jest-matcher-utils": "30.3.0", + "jest-message-util": "30.3.0", + "jest-util": "30.3.0", + "pretty-format": "30.3.0", "semver": "^7.7.2", "synckit": "^0.11.8" }, @@ -4239,9 +4144,9 @@ } }, "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "dev": true, "license": "ISC", "bin": { @@ -4252,50 +4157,36 @@ } }, "node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-util/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/jest-validate": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.2.0.tgz", - "integrity": "sha512-FBGWi7dP2hpdi8nBoWxSsLvBFewKAg0+uSQwBaof4Y4DPgBabXgpSYC5/lR7VmnIlSpASmCi/ntRWPbv7089Pw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.3.0.tgz", + "integrity": "sha512-I/xzC8h5G+SHCb2P2gWkJYrNiTbeL47KvKeW5EzplkyxzBRBw1ssSHlI/jXec0ukH2q7x2zAWQm7015iusg62Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/get-type": "30.1.0", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "camelcase": "^6.3.0", "chalk": "^4.1.2", "leven": "^3.1.0", - "pretty-format": "30.2.0" + "pretty-format": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -4307,7 +4198,6 @@ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -4316,20 +4206,19 @@ } }, "node_modules/jest-watcher": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.2.0.tgz", - "integrity": "sha512-PYxa28dxJ9g777pGm/7PrbnMeA0Jr7osHP9bS7eJy9DuAjMgdGtxgf0uKMyoIsTWAkIbUW5hSDdJ3urmgXBqxg==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.3.0.tgz", + "integrity": "sha512-PJ1d9ThtTR8aMiBWUdcownq9mDdLXsQzJayTk4kmaBRHKvwNQn+ANveuhEBUyNI2hR1TVhvQ8D5kHubbzBHR/w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@jest/test-result": "30.2.0", - "@jest/types": "30.2.0", + "@jest/test-result": "30.3.0", + "@jest/types": "30.3.0", "@types/node": "*", "ansi-escapes": "^4.3.2", "chalk": "^4.1.2", "emittery": "^0.13.1", - "jest-util": "30.2.0", + "jest-util": "30.3.0", "string-length": "^4.0.2" }, "engines": { @@ -4337,15 +4226,15 @@ } }, "node_modules/jest-worker": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.2.0.tgz", - "integrity": "sha512-0Q4Uk8WF7BUwqXHuAjc23vmopWJw5WH7w2tqBoUOZpOjW/ZnR44GXXd1r82RvnmI2GZge3ivrYXk/BE2+VtW2g==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.3.0.tgz", + "integrity": "sha512-DrCKkaQwHexjRUFTmPzs7sHQe0TSj9nvDALKGdwmK5mW9v7j90BudWirKAJHt3QQ9Dhrg1F7DogPzhChppkJpQ==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "*", "@ungap/structured-clone": "^1.3.0", - "jest-util": "30.2.0", + "jest-util": "30.3.0", "merge-stream": "^2.0.0", "supports-color": "^8.1.1" }, @@ -4418,8 +4307,7 @@ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/json5": { "version": "2.2.3", @@ -4440,7 +4328,6 @@ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -4460,8 +4347,7 @@ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/locate-path": { "version": "5.0.0", @@ -4513,9 +4399,9 @@ } }, "node_modules/lru.min": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.3.tgz", - "integrity": "sha512-Lkk/vx6ak3rYkRR0Nhu4lFUT2VDnQSxBe8Hbl7f36358p6ow8Bnvr8lrLt98H8J1aGxfhbX4Fs5tYg2+FTwr5Q==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.4.tgz", + "integrity": "sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA==", "dev": true, "license": "MIT", "engines": { @@ -4534,7 +4420,6 @@ "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "semver": "^7.5.3" }, @@ -4546,12 +4431,11 @@ } }, "node_modules/make-dir/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "dev": true, "license": "ISC", - "peer": true, "bin": { "semver": "bin/semver.js" }, @@ -4583,27 +4467,12 @@ "dev": true, "license": "MIT" }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, "node_modules/mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -4622,14 +4491,13 @@ } }, "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -4719,7 +4587,6 @@ "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", "dev": true, "license": "MIT", - "peer": true, "bin": { "napi-postinstall": "lib/cli.js" }, @@ -4745,9 +4612,9 @@ "license": "MIT" }, "node_modules/node-abi": { - "version": "3.85.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.85.0.tgz", - "integrity": "sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg==", + "version": "3.89.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.89.0.tgz", + "integrity": "sha512-6u9UwL0HlAl21+agMN3YAMXcKByMqwGx+pq+P76vii5f7hTPtKDp08/H9py6DY+cfDw7kQNTGEj/rly3IgbNQA==", "dev": true, "license": "MIT", "dependencies": { @@ -4758,9 +4625,9 @@ } }, "node_modules/node-abi/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "dev": true, "license": "ISC", "bin": { @@ -4785,9 +4652,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.27", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "version": "2.0.36", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", + "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", "dev": true, "license": "MIT" }, @@ -4807,7 +4674,6 @@ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "path-key": "^3.0.0" }, @@ -4816,25 +4682,30 @@ } }, "node_modules/nypm": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.2.tgz", - "integrity": "sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g==", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.5.tgz", + "integrity": "sha512-K6AJy1GMVyfyMXRVB88700BJqNUkByijGJM8kEHpLdcAt+vSQAVfkWWHYzuRXHSY6xA2sNc5RjTj0p9rE2izVQ==", "dev": true, "license": "MIT", "dependencies": { - "citty": "^0.1.6", - "consola": "^3.4.2", + "citty": "^0.2.0", "pathe": "^2.0.3", - "pkg-types": "^2.3.0", - "tinyexec": "^1.0.1" + "tinyexec": "^1.0.2" }, "bin": { "nypm": "dist/cli.mjs" }, "engines": { - "node": "^14.16.0 || >=16.10.0" + "node": ">=18" } }, + "node_modules/nypm/node_modules/citty": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.2.1.tgz", + "integrity": "sha512-kEV95lFBhQgtogAPlQfJJ0WGVSokvLr/UEoFPiKKOXF7pl98HfUVUD0ejsuTCld/9xH9vogSywZ5KqHzXrZpqg==", + "dev": true, + "license": "MIT" + }, "node_modules/ohash": { "version": "2.0.11", "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", @@ -4858,7 +4729,6 @@ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -4875,7 +4745,6 @@ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "yocto-queue": "^0.1.0" }, @@ -4938,7 +4807,6 @@ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -4988,7 +4856,6 @@ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "license": "BlueOak-1.0.0", - "peer": true, "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" @@ -5005,8 +4872,7 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/pathe": { "version": "2.0.3", @@ -5030,13 +4896,13 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { - "node": ">=8.6" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" @@ -5058,7 +4924,6 @@ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "find-up": "^4.0.0" }, @@ -5096,6 +4961,7 @@ "version": "7.1.3", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", "dev": true, "license": "MIT", "dependencies": { @@ -5120,9 +4986,9 @@ } }, "node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5148,17 +5014,18 @@ } }, "node_modules/prisma": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-7.4.2.tgz", - "integrity": "sha512-2bP8Ruww3Q95Z2eH4Yqh4KAENRsj/SxbdknIVBfd6DmjPwmpsC4OVFMLOeHt6tM3Amh8ebjvstrUz3V/hOe1dA==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-7.5.0.tgz", + "integrity": "sha512-n30qZpWehaYQzigLjmuPisyEsvOzHt7bZeRyg8gZ5DvJo9FGjD+gNaY59Ns3hlLD5/jZH5GBeftIss0jDbUoLg==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", + "peer": true, "dependencies": { - "@prisma/config": "7.4.2", + "@prisma/config": "7.5.0", "@prisma/dev": "0.20.0", - "@prisma/engines": "7.4.2", - "@prisma/studio-core": "0.13.1", + "@prisma/engines": "7.5.0", + "@prisma/studio-core": "0.21.1", "mysql2": "3.15.3", "postgres": "3.4.7" }, @@ -5315,9 +5182,9 @@ } }, "node_modules/pump": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", - "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", "dev": true, "license": "MIT", "dependencies": { @@ -5340,8 +5207,7 @@ "url": "https://opencollective.com/fast-check" } ], - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/rc": { "version": "1.2.8", @@ -5381,9 +5247,9 @@ } }, "node_modules/react": { - "version": "19.2.3", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz", - "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==", + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", + "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", "dev": true, "license": "MIT", "peer": true, @@ -5392,9 +5258,9 @@ } }, "node_modules/react-dom": { - "version": "19.2.3", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz", - "integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==", + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", + "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", "dev": true, "license": "MIT", "peer": true, @@ -5402,7 +5268,7 @@ "scheduler": "^0.27.0" }, "peerDependencies": { - "react": "^19.2.3" + "react": "^19.2.4" } }, "node_modules/react-is": { @@ -5473,7 +5339,6 @@ "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "resolve-from": "^5.0.0" }, @@ -5532,9 +5397,9 @@ } }, "node_modules/rimraf/node_modules/brace-expansion": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", - "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5563,9 +5428,9 @@ } }, "node_modules/rimraf/node_modules/lru-cache": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", - "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", "dev": true, "license": "BlueOak-1.0.0", "engines": { @@ -5638,8 +5503,7 @@ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/semver": { "version": "6.3.1", @@ -5766,7 +5630,6 @@ "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -5825,7 +5688,6 @@ "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "char-regex": "^1.0.2", "strip-ansi": "^6.0.0" @@ -5840,7 +5702,6 @@ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -5851,7 +5712,6 @@ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -5865,7 +5725,6 @@ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -5885,7 +5744,6 @@ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -5901,7 +5759,6 @@ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -5911,8 +5768,7 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/string-width-cjs/node_modules/strip-ansi": { "version": "6.0.1", @@ -5920,7 +5776,6 @@ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -5929,14 +5784,13 @@ } }, "node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "ansi-regex": "^6.0.1" + "ansi-regex": "^6.2.2" }, "engines": { "node": ">=12" @@ -5952,7 +5806,6 @@ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -5966,7 +5819,6 @@ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -5977,7 +5829,6 @@ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -5988,7 +5839,6 @@ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -5999,7 +5849,6 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" }, @@ -6021,9 +5870,9 @@ } }, "node_modules/synckit": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", - "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", + "version": "0.11.12", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz", + "integrity": "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6096,7 +5945,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "license": "ISC", "dependencies": { @@ -6115,9 +5964,9 @@ } }, "node_modules/test-exclude/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -6128,9 +5977,9 @@ } }, "node_modules/tinyexec": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", - "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.4.tgz", + "integrity": "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==", "dev": true, "license": "MIT", "engines": { @@ -6144,19 +5993,6 @@ "dev": true, "license": "BSD-3-Clause" }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, "node_modules/ts-jest": { "version": "29.4.6", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.6.tgz", @@ -6211,9 +6047,9 @@ } }, "node_modules/ts-jest/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "dev": true, "license": "ISC", "bin": { @@ -6242,6 +6078,7 @@ "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -6286,8 +6123,7 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, "license": "0BSD", - "optional": true, - "peer": true + "optional": true }, "node_modules/tunnel-agent": { "version": "0.6.0", @@ -6318,7 +6154,6 @@ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, "license": "(MIT OR CC0-1.0)", - "peer": true, "engines": { "node": ">=10" }, @@ -6332,6 +6167,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6367,7 +6203,6 @@ "dev": true, "hasInstallScript": true, "license": "MIT", - "peer": true, "dependencies": { "napi-postinstall": "^0.3.0" }, @@ -6460,7 +6295,6 @@ "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", @@ -6524,7 +6358,6 @@ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -6544,7 +6377,6 @@ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -6563,7 +6395,6 @@ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -6573,8 +6404,7 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/wrap-ansi-cjs/node_modules/string-width": { "version": "4.2.3", @@ -6582,7 +6412,6 @@ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -6598,7 +6427,6 @@ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -6612,7 +6440,6 @@ "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -6741,7 +6568,6 @@ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" },