Feature: Implement Atomic Resume Patching API (#2692)

This commit is contained in:
Amruth Pillai
2026-02-08 00:16:11 +01:00
committed by GitHub
parent 5e8e1349bc
commit cc01fb9418
8 changed files with 594 additions and 205 deletions
+6 -1
View File
@@ -69,7 +69,12 @@
},
{
"group": "Integrations",
"pages": ["guides/using-the-api", "guides/using-ai", "guides/json-resume-schema"]
"pages": [
"guides/using-the-api",
"guides/using-the-patch-api",
"guides/using-ai",
"guides/json-resume-schema"
]
},
{
"group": "Self-Hosting",
+191
View File
@@ -0,0 +1,191 @@
---
title: "Using the Patch API"
description: "Learn how to partially update your resume using JSON Patch (RFC 6902) operations"
---
The Patch API lets you make small, targeted changes to your resume without sending the entire data object. Instead of replacing the whole resume with a `PUT`, you send a list of **JSON Patch** operations that describe exactly what to change.
This is based on the [JSON Patch (RFC 6902)](https://datatracker.ietf.org/doc/html/rfc6902) standard.
## When to Use PATCH vs PUT
| Use case | Method |
| --- | --- |
| Update a single field (e.g., name, headline) | **PATCH** |
| Add or remove an item in a section | **PATCH** |
| Change template, colors, or fonts | **PATCH** |
| Replace the entire resume data at once | **PUT** |
<Info>
The PATCH endpoint only modifies the resume `data` (the JSONB column). To update top-level resume properties like `name`, `slug`, `tags`, or `isPublic`, use the existing `PUT /resume/{id}` endpoint.
</Info>
## Authentication
All requests require your API key in the `x-api-key` header. See [Using the API](/guides/using-the-api) for how to create one.
<Info>
If you're self-hosting, replace `https://rxresu.me` with your instance URL. The API is served under `/api/openapi`.
</Info>
## Endpoint
```
PATCH /api/openapi/resume/{id}
```
### Request Body
The resume ID is taken from the URL path, so the request body only requires the `operations` array:
```json
{
"operations": [
{ "op": "replace", "path": "/basics/name", "value": "Jane Doe" }
]
}
```
Each operation is an object with the following properties:
| Property | Required | Description |
| --- | --- | --- |
| `op` | Yes | The operation to perform: `add`, `remove`, `replace`, `move`, `copy`, or `test` |
| `path` | Yes | A JSON Pointer (RFC 6901) to the target location in the resume data |
| `value` | For `add`, `replace`, `test` | The value to use for the operation |
| `from` | For `move`, `copy` | A JSON Pointer to the source location |
## Examples
### Replace a Basic Field
Update the resume holder's name and headline:
```bash
curl -X PATCH "https://rxresu.me/api/openapi/resume/YOUR_RESUME_ID" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"operations": [
{ "op": "replace", "path": "/basics/name", "value": "Jane Doe" },
{ "op": "replace", "path": "/basics/headline", "value": "Senior Software Engineer" }
]
}'
```
### Add an Experience Entry
Append a new item to the experience section:
```bash
curl -X PATCH "https://rxresu.me/api/openapi/resume/YOUR_RESUME_ID" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"operations": [
{
"op": "add",
"path": "/sections/experience/items/-",
"value": {
"id": "a1b2c3d4-0000-0000-0000-000000000000",
"hidden": false,
"company": "Acme Corp",
"position": "Staff Engineer",
"location": "San Francisco, CA",
"period": "Jan 2024 - Present",
"website": { "url": "https://acme.example.com", "label": "Acme Corp" },
"description": "<p>Leading the platform team.</p>"
}
}
]
}'
```
<Tip>
The path `/sections/experience/items/-` uses the special `-` index, which means "append to the end of the array".
To insert at a specific position, use a numeric index like `/sections/experience/items/0` for the beginning.
</Tip>
### Remove an Item from a Section
Remove the second skill (index `1`) from the skills section:
```bash
curl -X PATCH "https://rxresu.me/api/openapi/resume/YOUR_RESUME_ID" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"operations": [
{ "op": "remove", "path": "/sections/skills/items/1" }
]
}'
```
### Update Metadata (Template, Colors, Fonts)
Switch the template and update the primary color:
```bash
curl -X PATCH "https://rxresu.me/api/openapi/resume/YOUR_RESUME_ID" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"operations": [
{ "op": "replace", "path": "/metadata/template", "value": "bronzor" },
{ "op": "replace", "path": "/metadata/design/colors/primary", "value": "rgba(37, 99, 235, 1)" }
]
}'
```
### Test-Then-Replace (Optimistic Concurrency)
The `test` operation checks that a value matches before proceeding. If the test fails, the entire patch is rejected. This is useful to avoid overwriting changes made by another client:
```bash
curl -X PATCH "https://rxresu.me/api/openapi/resume/YOUR_RESUME_ID" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"operations": [
{ "op": "test", "path": "/basics/name", "value": "Albert Einstein" },
{ "op": "replace", "path": "/basics/name", "value": "Jane Doe" }
]
}'
```
If `/basics/name` is not `"Albert Einstein"` at the time of the request, the entire patch will fail with a `400` error and no changes will be applied.
### Move an Item Within a Section
Move the first experience item to the third position:
```bash
curl -X PATCH "https://rxresu.me/api/openapi/resume/YOUR_RESUME_ID" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"operations": [
{ "op": "move", "from": "/sections/experience/items/0", "path": "/sections/experience/items/2" }
]
}'
```
## Error Handling
| Status | Error Code | Description |
| --- | --- | --- |
| `400` | `INVALID_PATCH_OPERATIONS` | The operations are structurally invalid, target a non-existent path, or produce resume data that fails schema validation. |
| `401` | `UNAUTHORIZED` | Missing or invalid API key. |
| `404` | `NOT_FOUND` | The resume does not exist or does not belong to the authenticated user. |
| `403` | `RESUME_LOCKED` | The resume is locked and cannot be modified. Unlock it first. |
<Warning>
All operations in a single request are applied atomically. If any operation fails (including a `test`), none of the operations are applied.
</Warning>
## Tips
- **Fetch first, then patch.** Use `GET /resume/{id}` to inspect the current structure before crafting your operations. This helps you target the correct paths and array indices.
- **Use `test` for safety.** When updating a value you expect to be a specific value, combine `test` + `replace` to avoid accidentally overwriting concurrent changes.
- **Batch related changes.** You can send multiple operations in a single request. They are applied in order, so later operations can depend on earlier ones.
- **The `-` index appends.** When adding items to arrays, use `-` as the index (e.g., `/sections/skills/items/-`) to append to the end.
+12 -11
View File
@@ -4,7 +4,7 @@
"version": "5.0.5",
"license": "MIT",
"type": "module",
"packageManager": "pnpm@10.28.2+sha512.41872f037ad22f7348e3b1debbaf7e867cfd448f2726d9cf74c08f19507c31d2c8e7a11525b983febc2df640b5438dee6023ebb1f84ed43cc2d654d2bc326264",
"packageManager": "pnpm@10.29.1+sha512.48dae233635a645768a3028d19545cacc1688639eeb1f3734e42d6d6b971afbf22aa1ac9af52a173d9c3a20c15857cfa400f19994d79a2f626fcc73fccda9bbc",
"repository": {
"type": "git",
"url": "https://github.com/amruthpillai/reactive-resume.git"
@@ -35,8 +35,8 @@
"@ai-sdk/google": "^3.0.22",
"@ai-sdk/openai": "^3.0.26",
"@aws-sdk/client-s3": "^3.985.0",
"@better-auth/core": "1.5.0-beta.11",
"@better-auth/passkey": "1.5.0-beta.11",
"@better-auth/core": "1.5.0-beta.13",
"@better-auth/passkey": "1.5.0-beta.13",
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
@@ -56,20 +56,20 @@
"@sindresorhus/slugify": "^3.0.0",
"@t3-oss/env-core": "^0.13.10",
"@tanstack/react-query": "5.90.20",
"@tanstack/react-router": "^1.158.1",
"@tanstack/react-router-ssr-query": "^1.158.1",
"@tanstack/react-start": "^1.158.3",
"@tanstack/zod-adapter": "^1.158.1",
"@tanstack/react-router": "^1.158.4",
"@tanstack/react-router-ssr-query": "^1.158.4",
"@tanstack/react-start": "^1.159.0",
"@tanstack/zod-adapter": "^1.158.4",
"@tiptap/extension-highlight": "^3.19.0",
"@tiptap/extension-table": "^3.19.0",
"@tiptap/extension-text-align": "^3.19.0",
"@tiptap/pm": "^3.19.0",
"@tiptap/react": "^3.19.0",
"@tiptap/starter-kit": "^3.19.0",
"ai": "^6.0.75",
"ai-sdk-ollama": "^3.4.0",
"ai": "^6.0.77",
"ai-sdk-ollama": "^3.5.0",
"bcrypt": "^6.0.0",
"better-auth": "1.5.0-beta.11",
"better-auth": "1.5.0-beta.13",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
@@ -78,13 +78,14 @@
"drizzle-zod": "^0.8.3",
"es-toolkit": "^1.44.0",
"fast-deep-equal": "^3.1.3",
"fast-json-patch": "^3.1.1",
"fuse.js": "^7.1.0",
"immer": "^11.1.3",
"input-otp": "^1.4.2",
"js-cookie": "^3.0.5",
"monaco-editor": "^0.55.1",
"motion": "^12.33.0",
"nodemailer": "^8.0.0",
"nodemailer": "^8.0.1",
"pg": "^8.18.0",
"puppeteer-core": "^24.37.2",
"qrcode.react": "^4.2.0",
+180 -193
View File
@@ -24,11 +24,11 @@ importers:
specifier: ^3.985.0
version: 3.985.0
'@better-auth/core':
specifier: 1.5.0-beta.11
version: 1.5.0-beta.11(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.0(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)
specifier: 1.5.0-beta.13
version: 1.5.0-beta.13(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.1(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)
'@better-auth/passkey':
specifier: 1.5.0-beta.11
version: 1.5.0-beta.11(38c18a8d8b45924e68e857ec7a702968)
specifier: 1.5.0-beta.13
version: 1.5.0-beta.13(2258e4f412fd167666cad25c7546abd6)
'@dnd-kit/core':
specifier: ^6.3.1
version: 6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
@@ -87,17 +87,17 @@ importers:
specifier: 5.90.20
version: 5.90.20(react@19.2.4)
'@tanstack/react-router':
specifier: ^1.158.1
version: 1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
specifier: ^1.158.4
version: 1.158.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@tanstack/react-router-ssr-query':
specifier: ^1.158.1
version: 1.158.1(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.4))(@tanstack/react-router@1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@tanstack/router-core@1.158.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
specifier: ^1.158.4
version: 1.158.4(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.4))(@tanstack/react-router@1.158.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@tanstack/router-core@1.158.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@tanstack/react-start':
specifier: ^1.158.3
version: 1.158.3(crossws@0.4.3(srvx@0.10.1))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rolldown-vite@7.3.1(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0))
specifier: ^1.159.0
version: 1.159.0(crossws@0.4.3(srvx@0.10.1))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rolldown-vite@7.3.1(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0))
'@tanstack/zod-adapter':
specifier: ^1.158.1
version: 1.158.1(@tanstack/react-router@1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(zod@4.3.6)
specifier: ^1.158.4
version: 1.158.4(@tanstack/react-router@1.158.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(zod@4.3.6)
'@tiptap/extension-highlight':
specifier: ^3.19.0
version: 3.19.0(@tiptap/core@3.19.0(@tiptap/pm@3.19.0))
@@ -117,17 +117,17 @@ importers:
specifier: ^3.19.0
version: 3.19.0
ai:
specifier: ^6.0.75
version: 6.0.75(zod@4.3.6)
specifier: ^6.0.77
version: 6.0.77(zod@4.3.6)
ai-sdk-ollama:
specifier: ^3.4.0
version: 3.4.0(ai@6.0.75(zod@4.3.6))(zod@4.3.6)
specifier: ^3.5.0
version: 3.5.0(ai@6.0.77(zod@4.3.6))(zod@4.3.6)
bcrypt:
specifier: ^6.0.0
version: 6.0.0
better-auth:
specifier: 1.5.0-beta.11
version: 1.5.0-beta.11(@prisma/client@7.2.0(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(@tanstack/react-start@1.158.3(crossws@0.4.3(srvx@0.10.1))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rolldown-vite@7.3.1(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)))(drizzle-kit@1.0.0-beta.9-e89174b)(drizzle-orm@1.0.0-beta.9-e89174b(@electric-sql/pglite@0.3.2)(@opentelemetry/api@1.9.0)(@prisma/client@7.2.0(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(@types/mssql@9.1.9)(@types/pg@8.16.0)(mssql@11.0.1)(mysql2@3.15.3)(pg@8.18.0)(postgres@3.4.7)(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)))(mongodb@7.0.0(socks@2.8.7))(mysql2@3.15.3)(pg@8.18.0)(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
specifier: 1.5.0-beta.13
version: 1.5.0-beta.13(@prisma/client@7.2.0(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(@tanstack/react-start@1.159.0(crossws@0.4.3(srvx@0.10.1))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rolldown-vite@7.3.1(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)))(drizzle-kit@1.0.0-beta.9-e89174b)(drizzle-orm@1.0.0-beta.9-e89174b(@electric-sql/pglite@0.3.2)(@opentelemetry/api@1.9.0)(@prisma/client@7.2.0(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(@types/mssql@9.1.9)(@types/pg@8.16.0)(mssql@11.0.1)(mysql2@3.15.3)(pg@8.18.0)(postgres@3.4.7)(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)))(mongodb@7.0.0(socks@2.8.7))(mysql2@3.15.3)(pg@8.18.0)(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
class-variance-authority:
specifier: ^0.7.1
version: 0.7.1
@@ -152,6 +152,9 @@ importers:
fast-deep-equal:
specifier: ^3.1.3
version: 3.1.3
fast-json-patch:
specifier: ^3.1.1
version: 3.1.1
fuse.js:
specifier: ^7.1.0
version: 7.1.0
@@ -171,8 +174,8 @@ importers:
specifier: ^12.33.0
version: 12.33.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
nodemailer:
specifier: ^8.0.0
version: 8.0.0
specifier: ^8.0.1
version: 8.0.1
pg:
specifier: ^8.18.0
version: 8.18.0
@@ -336,8 +339,8 @@ packages:
peerDependencies:
zod: ^3.25.76 || ^4.1.8
'@ai-sdk/gateway@3.0.37':
resolution: {integrity: sha512-w7rxPd2WOuSr4he2ALvtCAM/W1/33rGdv3kkU52tCGj/bJSYJnJDpnTvoWRLNESp9HEkkiNFfBLFZY0PB9n4aQ==}
'@ai-sdk/gateway@3.0.39':
resolution: {integrity: sha512-SeCZBAdDNbWpVUXiYgOAqis22p5MEYfrjRw0hiBa5hM+7sDGYQpMinUjkM8kbPXMkY+AhKLrHleBl+SuqpzlgA==}
engines: {node: '>=18'}
peerDependencies:
zod: ^3.25.76 || ^4.1.8
@@ -354,22 +357,12 @@ packages:
peerDependencies:
zod: ^3.25.76 || ^4.1.8
'@ai-sdk/provider-utils@4.0.13':
resolution: {integrity: sha512-HHG72BN4d+OWTcq2NwTxOm/2qvk1duYsnhCDtsbYwn/h/4zeqURu1S0+Cn0nY2Ysq9a9HGKvrYuMn9bgFhR2Og==}
engines: {node: '>=18'}
peerDependencies:
zod: ^3.25.76 || ^4.1.8
'@ai-sdk/provider-utils@4.0.14':
resolution: {integrity: sha512-7bzKd9lgiDeXM7O4U4nQ8iTxguAOkg8LZGD9AfDVZYjO5cKYRwBPwVjboFcVrxncRHu0tYxZtXZtiLKpG4pEng==}
engines: {node: '>=18'}
peerDependencies:
zod: ^3.25.76 || ^4.1.8
'@ai-sdk/provider@3.0.7':
resolution: {integrity: sha512-VkPLrutM6VdA924/mG8OS+5frbVTcu6e046D2bgDo00tehBANR1QBJ/mPcZ9tXMFOsVcm6SQArOregxePzTFPw==}
engines: {node: '>=18'}
'@ai-sdk/provider@3.0.8':
resolution: {integrity: sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ==}
engines: {node: '>=18'}
@@ -1175,65 +1168,65 @@ packages:
resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==}
engines: {node: '>=6.9.0'}
'@better-auth/core@1.5.0-beta.11':
resolution: {integrity: sha512-8fbGKD8RhnKJ6FSUKDj4mHp1RIS82T4vB4AjFj95/XOEExzM9qShbYKFL5+RZrkt+oqSViuFX61iAB+LH/SJ9g==}
'@better-auth/core@1.5.0-beta.13':
resolution: {integrity: sha512-oOK1O3bwfzebK5W4iIYOdB+IBLk+RLWfOm/MU6dMq4l1HNWvi5iZ75lxxk7Sgx0MfaeEn1C+lXIHplDyeeZKhQ==}
peerDependencies:
'@better-auth/utils': 0.3.1
'@better-fetch/fetch': 1.1.21
better-call: 1.2.0
better-call: 1.2.1
jose: ^6.1.0
kysely: ^0.28.5
nanostores: ^1.0.1
'@better-auth/drizzle-adapter@1.5.0-beta.11':
resolution: {integrity: sha512-XtxYPr3nNlIndONyoxd3jijkq9g1/p+x8WZd6ZDP8ygcz8iARS31CCJ919eH6P6rpoUy4VXx+eSPvjzALbKrWQ==}
'@better-auth/drizzle-adapter@1.5.0-beta.13':
resolution: {integrity: sha512-PZmyTDun2AEhwQtO/xQb8Zi5eBMyJ/o69T3h4wj59CxHtBD11fvhY19csJd3hVk1YvFJobgMv3icWXmz02Egmw==}
peerDependencies:
'@better-auth/core': 1.5.0-beta.11
'@better-auth/core': 1.5.0-beta.13
'@better-auth/utils': ^0.3.0
drizzle-orm: '>=0.41.0'
'@better-auth/kysely-adapter@1.5.0-beta.11':
resolution: {integrity: sha512-VV5RF0+648leeNgXoNbuoePh6PjmRyVP2qxgDU5gnEzA8x9SqfOUppHhi4ssfOdjaQHf+pLo1sWHFb8Wy7+JlQ==}
'@better-auth/kysely-adapter@1.5.0-beta.13':
resolution: {integrity: sha512-1Ek0jV/FiFUEcTkoPkf4MWNR3k6b5t1mLBanJVjvSD+UhAXhe93H8onEKlRcSopNu2ls6z70BI75jYBxYSdf5Q==}
peerDependencies:
'@better-auth/core': 1.5.0-beta.11
'@better-auth/core': 1.5.0-beta.13
'@better-auth/utils': ^0.3.0
kysely: ^0.27.0 || ^0.28.0
'@better-auth/memory-adapter@1.5.0-beta.11':
resolution: {integrity: sha512-Ggq+F2YB2ywTfX/0w5xgFvr73IiihmVF6IUYM0v79BMnEQa72Qc3J/8D/iU33WRNwvYAo4CfDD1OECp/78PjgA==}
'@better-auth/memory-adapter@1.5.0-beta.13':
resolution: {integrity: sha512-7pCJXEiI4MPduxueVtUUnfUOxOQhu4EcFmQQ7zUodumtYmi5Xwar/bctl7v8GsabkG8bZwEQUEvO5uqVtnGwhA==}
peerDependencies:
'@better-auth/core': 1.5.0-beta.11
'@better-auth/core': 1.5.0-beta.13
'@better-auth/utils': ^0.3.0
'@better-auth/mongo-adapter@1.5.0-beta.11':
resolution: {integrity: sha512-32JQTtp/84tZd0ZpWSV4+uaiMhyZGmeyAJF0B4FrHnI8/i/auOrNK3imLP+afv/ne7U+hQEyfUObgtUDr+DLzw==}
'@better-auth/mongo-adapter@1.5.0-beta.13':
resolution: {integrity: sha512-FDqbLWqreELN/wiIwGlItZmi+FShzGPNdNk2KaRo2hVLakBQy9hlCtnxeYV7OfptOPs+AkGc8hboKjBzFA1uUQ==}
peerDependencies:
'@better-auth/core': 1.5.0-beta.11
'@better-auth/core': 1.5.0-beta.13
'@better-auth/utils': ^0.3.0
mongodb: ^6.0.0 || ^7.0.0
'@better-auth/passkey@1.5.0-beta.11':
resolution: {integrity: sha512-dZ2oO4ePY9mo0h6SO3Uzhh/yMuD0rYKVosDzD6kuwyX+0S0guWbpSL+r1VwdZzOT/eP3XIMv6AnA+J4gmD7ibQ==}
'@better-auth/passkey@1.5.0-beta.13':
resolution: {integrity: sha512-M6ORIcQQUIkmTDKZ4lvWn4grYisuE48k995Bdv4DoBW8ezbkHoJt0tRzxSJoD6BsArV79jZ+jG9sci1tfeF6rw==}
peerDependencies:
'@better-auth/core': 1.5.0-beta.11
'@better-auth/core': 1.5.0-beta.13
'@better-auth/utils': 0.3.1
'@better-fetch/fetch': 1.1.21
better-auth: 1.5.0-beta.11
better-call: 1.2.0
better-auth: 1.5.0-beta.13
better-call: 1.2.1
nanostores: ^1.0.1
'@better-auth/prisma-adapter@1.5.0-beta.11':
resolution: {integrity: sha512-jAlAql0bZx62IgZ6/UsXXCR6L28tKipLYe4iPutjMAOi9Wl9oM2OsAmr/ZhcrHj9mjmKZXot1mqGcCcROZ1aSg==}
'@better-auth/prisma-adapter@1.5.0-beta.13':
resolution: {integrity: sha512-w2+KMfoWrPeYKAmG1tinwmsHe2Lc3HNyOASEO5jw6oJY7BrLDKcqeqCJuhavuwhd2fCAq3fEiqyJVCYDDLVKqA==}
peerDependencies:
'@better-auth/core': 1.5.0-beta.11
'@better-auth/core': 1.5.0-beta.13
'@better-auth/utils': ^0.3.0
'@prisma/client': ^5.0.0 || ^6.0.0 || ^7.0.0
prisma: ^5.0.0 || ^6.0.0 || ^7.0.0
'@better-auth/telemetry@1.5.0-beta.11':
resolution: {integrity: sha512-DDHXD37FCF+N7Sx80wY1QI351SgCMH7KQ2YsxwF5JDw/DYdY4vbjcEGYB7Ipum+dzEfq5o6cSdWvQqtjcT2o2w==}
'@better-auth/telemetry@1.5.0-beta.13':
resolution: {integrity: sha512-Ju/29VMM+pfgFs/i7rX7scMO2QFgNbt/PRQGU3VJEQDC9M9NHhGgLe2kPkUEFQic5Z6sOYpXTGKFJyF/YSJRFw==}
peerDependencies:
'@better-auth/core': 1.5.0-beta.11
'@better-auth/core': 1.5.0-beta.13
'@better-auth/utils@0.3.1':
resolution: {integrity: sha512-+CGp4UmZSUrHHnpHhLPYu6cV+wSUSvVbZbNykxhUDocpVNTo9uFFxw/NqJlh1iC4wQ9HKKWGCKuZ5wUgS0v6Kg==}
@@ -3899,8 +3892,8 @@ packages:
peerDependencies:
react: ^18 || ^19
'@tanstack/react-router-ssr-query@1.158.1':
resolution: {integrity: sha512-WDwwwVFjoDsm9IMjbv+cQJzCkUZ1zfZYy/bXqjcNmN+eK7NLIc3ePCOeMjqb3bMOg5173qPMyFD9mWeHg+wNjQ==}
'@tanstack/react-router-ssr-query@1.158.4':
resolution: {integrity: sha512-f+XzxO06ILM2i5CGtWqcb3+yaAvp8XgT5hMykKmwwaBnf3Ctc6O8tN/05Ovj0ajXWuROk3HTjg67OcWD7JxI6Q==}
engines: {node: '>=12'}
peerDependencies:
'@tanstack/query-core': '>=5.90.0'
@@ -3909,29 +3902,29 @@ packages:
react: '>=18.0.0 || >=19.0.0'
react-dom: '>=18.0.0 || >=19.0.0'
'@tanstack/react-router@1.158.1':
resolution: {integrity: sha512-ZRBhs0tJDPeYGVrBhXPkGs+mOKqKKMM4OfvYSNvWIYZGfs8KQcqxPaN8OnUvKsnAGtzwusVWDpBipqVZWJd0lA==}
'@tanstack/react-router@1.158.4':
resolution: {integrity: sha512-i15xXumgvpuM+4NSuIwgouGezuj9eHjZsgpTZSQ7E9pa8rYmhZbWnf8xU68qaLmaKIol/e75o/YzVH2QWHs3iQ==}
engines: {node: '>=12'}
peerDependencies:
react: '>=18.0.0 || >=19.0.0'
react-dom: '>=18.0.0 || >=19.0.0'
'@tanstack/react-start-client@1.158.3':
resolution: {integrity: sha512-ScZwp1ovnthjroqs6qVk37AIbN+9Bf5MDK+uFhU+T6fWew/XHrxgtJzx2k1vqXJBi0tUKqZYSaH2zqc3OIdkfg==}
'@tanstack/react-start-client@1.158.4':
resolution: {integrity: sha512-ctEBgpYAPZ3i4EPZlJ45XS/lXPO73MkELec+hXf8NfK0lDQDaUy7LfWu41NPaftdZFJPOncDCfutwpUXD98YlA==}
engines: {node: '>=22.12.0'}
peerDependencies:
react: '>=18.0.0 || >=19.0.0'
react-dom: '>=18.0.0 || >=19.0.0'
'@tanstack/react-start-server@1.158.3':
resolution: {integrity: sha512-luLTjbccYPSl1nvVhP2vJGgIVPLksvXap2oXCGGouwG+2nGPprBEglLAtd9gmnJ7dbd4QknSIXBFoeUuoCsdsQ==}
'@tanstack/react-start-server@1.159.0':
resolution: {integrity: sha512-1nPj7TEOpoIlTW0lftaHuU9Ol1ZDQwRCUWr6UvaPUbapq9nWR8kwYFjyCLbopBjyakFFNgz88/stdbZObt5h2A==}
engines: {node: '>=22.12.0'}
peerDependencies:
react: '>=18.0.0 || >=19.0.0'
react-dom: '>=18.0.0 || >=19.0.0'
'@tanstack/react-start@1.158.3':
resolution: {integrity: sha512-dn54I+frxfItkxAQngBZDwlnOM1DM53Lhd+iHhinRRk1HzwoGXtc1lJZ/aIk5YanXguIFsxBhqsejX3+kT4y8A==}
'@tanstack/react-start@1.159.0':
resolution: {integrity: sha512-/ky8Pbu0cmj5dAQfi8LXHpAd/eepyQqDo0eSI/OPYQ2wZ8u8UPwycFvou8t8mq5pkinu+l7JX45UD7mNvzvVNg==}
engines: {node: '>=22.12.0'}
peerDependencies:
react: '>=18.0.0 || >=19.0.0'
@@ -3944,20 +3937,20 @@ packages:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
'@tanstack/router-core@1.158.1':
resolution: {integrity: sha512-8B9X3GzN1JWsqa+OTgg2k+LrayLQYmgtv26b96difyrRS32DaDBvEpU3xXDaLNmi/+zoqG1ffAcDT4D6tyC2hw==}
'@tanstack/router-core@1.158.4':
resolution: {integrity: sha512-KikgYdyrEFqsjjgv9pMhDTMmASMAyFRvUiKFdQPQtXq3aD1qv/zck4CbA4bfzp9N9nYu/qvWwU1mlYU4u5JeXg==}
engines: {node: '>=12'}
'@tanstack/router-generator@1.158.1':
resolution: {integrity: sha512-geBpsIxJNvdjw2kt/Ii/j68hIUvfGnra0HKlGrDZw8/Ny4AJ2nnOcszUlZRbuQyxByk05r4lneOShKy5V5MUCQ==}
'@tanstack/router-generator@1.158.4':
resolution: {integrity: sha512-RQmqMTT0oV8dS/3Glcq9SPzDZqOPyKb/LVFUkNoTfMwW88WyGnQcYqZAkmVk/CGBWWDfwObOUZoGq5jTF7bG8w==}
engines: {node: '>=12'}
'@tanstack/router-plugin@1.158.1':
resolution: {integrity: sha512-IPCnf1CBc0jnczuy65+3iBaoABv5TKhOJ1YLzwel4kb9D8Abcq0vF8ooR5FiPmaGnree/z3SvjgHe5eQtgcsSQ==}
'@tanstack/router-plugin@1.158.4':
resolution: {integrity: sha512-g2sytAhljw6Jd6Klu37OZ75+o+vhiGdbWtnBy/4rYLC4NN6hSnjgJQRI3+h1CI1KQ4EUgsZYZr/hgE1KHoiWYQ==}
engines: {node: '>=12'}
peerDependencies:
'@rsbuild/core': '>=1.0.2'
'@tanstack/react-router': ^1.158.1
'@tanstack/react-router': ^1.158.4
vite: '>=5.0.0 || >=6.0.0 || >=7.0.0'
vite-plugin-solid: ^2.11.10
webpack: '>=5.92.0'
@@ -3973,8 +3966,8 @@ packages:
webpack:
optional: true
'@tanstack/router-ssr-query-core@1.158.1':
resolution: {integrity: sha512-Paucg5utPgSFS0aJOFKefKPNJaYUneTH4gXI32dB5EiNgjFuXcrXMWT4n0Hm2t0WUgMxn7KIcGgD2cB9wuOGAw==}
'@tanstack/router-ssr-query-core@1.158.4':
resolution: {integrity: sha512-gZRx0pGaRc7NPrwQSAfnn/DVWEsd01cf5TaW5yTyf3R5ZP/I++KNEW3lBXyRo1RyKedPC45R+Id6HpDeEaidyg==}
engines: {node: '>=12'}
peerDependencies:
'@tanstack/query-core': '>=5.90.0'
@@ -3984,26 +3977,26 @@ packages:
resolution: {integrity: sha512-qZ76eaLKU6Ae9iI/mc5zizBX149DXXZkBVVO3/QRIll79uKLJZHQlMKR++2ba7JsciBWz1pgpIBcCJPE9S0LVg==}
engines: {node: '>=12'}
'@tanstack/start-client-core@1.158.3':
resolution: {integrity: sha512-PAZfD0kEi6GHKFPJK2vn5CKTYZ503YVCGgJZ+RCyfH55/6qTzaPrY68Pk5nhUxp7WmjrAJEhGqr1V42hLGM5EA==}
'@tanstack/start-client-core@1.158.4':
resolution: {integrity: sha512-qpUYwJMMCEKgJuMz2CJLt53XrObi1BSjV1gG5SgBWRRVOHL8zky55tu1fEqHEa26jTTA6mUcBnPzYE8vIjRpAw==}
engines: {node: '>=22.12.0'}
'@tanstack/start-fn-stubs@1.154.7':
resolution: {integrity: sha512-D69B78L6pcFN5X5PHaydv7CScQcKLzJeEYqs7jpuyyqGQHSUIZUjS955j+Sir8cHhuDIovCe2LmsYHeZfWf3dQ==}
engines: {node: '>=22.12.0'}
'@tanstack/start-plugin-core@1.158.3':
resolution: {integrity: sha512-ZXC++5jXHuApsQpi33eK3WsQSuiCOVFtYE5oAU0fkn2+iV8NpXdqO2RzpQCVo2/Co7LcKulPm4OBdsgYIkuHYQ==}
'@tanstack/start-plugin-core@1.159.0':
resolution: {integrity: sha512-HGcji+Mhste9mDKUlKpRPfoIOaURr7UqQZ3AMb+6zpbXumc+apYW/CvlvWdF/hoZGBSVAniFpwXgV5L5IimnhA==}
engines: {node: '>=22.12.0'}
peerDependencies:
vite: '>=7.0.0'
'@tanstack/start-server-core@1.158.3':
resolution: {integrity: sha512-xPjPALT9M8ZsAcbzlk0Yhj1P48O6q8VUX7S5MJ8psrxh0CIo6nhz2Z5NOSuejjJ6YDSh91KZMNMskHW+MNJpcQ==}
'@tanstack/start-server-core@1.159.0':
resolution: {integrity: sha512-oE9UkWc7uIDvjAOsmzZ65Vz+JLb4S+bhMLGjx84lWY0G+GelJJvdr0rQiUFTWPIsbIxO2pdyIY995H55VUcowg==}
engines: {node: '>=22.12.0'}
'@tanstack/start-storage-context@1.158.1':
resolution: {integrity: sha512-0VJt3lUPylglgNmquHs5M4xmfudqEPGWItlvxVEFjrIPoZLHZ098TDSHSycra4RlRbtvlvD6qt0k745ncI0OHw==}
'@tanstack/start-storage-context@1.158.4':
resolution: {integrity: sha512-tz70q/6LTytstBIMRYt5GDRjPJPOHjnPNay85RJdq9ZlQKryeDThnshEttlBTDAxZP7wtwOv00lcAgFLFGP1hA==}
engines: {node: '>=22.12.0'}
'@tanstack/store@0.8.0':
@@ -4013,8 +4006,8 @@ packages:
resolution: {integrity: sha512-cHHDnewHozgjpI+MIVp9tcib6lYEQK5MyUr0ChHpHFGBl8Xei55rohFK0I0ve/GKoHeioaK42Smd8OixPp6CTg==}
engines: {node: '>=12'}
'@tanstack/zod-adapter@1.158.1':
resolution: {integrity: sha512-aaC28Y7gA1nPJNLklxa6yaCqe230uiQ89OL0fP2QNSQjCxEtqRMlicUWMMPM37wEdm4yZWMFfXuXKGXY1dAoag==}
'@tanstack/zod-adapter@1.158.4':
resolution: {integrity: sha512-tjCwJIbWiAae7JOWwgQ5Exc7YZgWLy3pjnXQ8/ON64p0+tHGDI8usrL5dJMEhRNOt7T3+3ytmRNRaVj8vVDvRw==}
engines: {node: '>=12'}
peerDependencies:
'@tanstack/react-router': '>=1.43.2'
@@ -4330,14 +4323,14 @@ packages:
resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==}
engines: {node: '>= 14'}
ai-sdk-ollama@3.4.0:
resolution: {integrity: sha512-iJQ4XwMOgX+mQO9NpJnj7S3AGiaEjBSO1ahc946mlp57T7t81dr1TtB/hoTZuqpjvV3jZY17Vv3LS4NI5qsmqQ==}
ai-sdk-ollama@3.5.0:
resolution: {integrity: sha512-G7cD0AEz3MJ3kGuhotDnscH2YnlX2gEdIuY7Y3A4fFxhocEsvS6bAiyO2A4EcPVEa5a6iniJaYTlqDKVXPis4Q==}
engines: {node: '>=22'}
peerDependencies:
ai: ^6.0.70
ai: ^6.0.77
ai@6.0.75:
resolution: {integrity: sha512-pT1xtwaE5Un261GO9Mt9DZ2rv26v+gQZNRXo433CNAMo0JDYs2ef+5MvcNkBe1jXCY9XrXxUG/VT6Y6/9S2SWg==}
ai@6.0.77:
resolution: {integrity: sha512-tyyhrRpCRFVlivdNIFLK8cexSBB2jwTqO0z1qJQagk+UxZ+MW8h5V8xsvvb+xdKDY482Y8KAm0mr7TDnPKvvlw==}
engines: {node: '>=18'}
peerDependencies:
zod: ^3.25.76 || ^4.1.8
@@ -4513,8 +4506,8 @@ packages:
resolution: {integrity: sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==}
engines: {node: '>= 18'}
better-auth@1.5.0-beta.11:
resolution: {integrity: sha512-rf5Rq217KyN+EuagsYHpzrXZodhPLrUJ6ViTUbmY+HZBvfvHtHxREOrl0Sv+wAXL8XND9P1n2eTIcVHDIuBTvw==}
better-auth@1.5.0-beta.13:
resolution: {integrity: sha512-J/48ye6NRNQH5Wj1FXrQdBR6/4l1ohOCVhHIqTB3u48jNCwmXwarhDcctTXM3/FGSffYmY8Hjc+kvbxd5IM5Ug==}
peerDependencies:
'@lynx-js/react': '*'
'@prisma/client': ^5.0.0 || ^6.0.0 || ^7.0.0
@@ -4575,8 +4568,8 @@ packages:
vue:
optional: true
better-call@1.2.0:
resolution: {integrity: sha512-7msprrikJah2Pq+OPJOUkqqlDOpVQysBPfxLfXQZr1XeIPqUD3O5z6qxh0vsAU8m/GDFbJD0n1a4vvTnekM7Kw==}
better-call@1.2.1:
resolution: {integrity: sha512-Ccgd5hj2Fmtu9Vjb9APXNYxutJWPRDhJanWAzFLwSzYAiOvkXN61OmYdvSirfrL2Z7REuK7TRklP8SIbZRlGwA==}
peerDependencies:
zod: ^4.0.0
peerDependenciesMeta:
@@ -5387,6 +5380,9 @@ packages:
resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==}
engines: {node: '>=8.6.0'}
fast-json-patch@3.1.1:
resolution: {integrity: sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==}
fast-json-stable-stringify@2.1.0:
resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
@@ -6537,8 +6533,8 @@ packages:
node-releases@2.0.27:
resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==}
nodemailer@8.0.0:
resolution: {integrity: sha512-xvVJf/f0bzmNpnRIbhCp/IKxaHgJ6QynvUbLXzzMRPG3LDQr5oXkYuw4uDFyFYs8cge8agwwrJAXZsd4hhMquw==}
nodemailer@8.0.1:
resolution: {integrity: sha512-5kcldIXmaEjZcHR6F28IKGSgpmZHaF1IXLWFTG+Xh3S+Cce4MiakLtWY+PlBU69fLbRa8HlaGIrC/QolUpHkhg==}
engines: {node: '>=6.0.0'}
nopt@9.0.0:
@@ -8215,7 +8211,7 @@ snapshots:
'@ai-sdk/provider-utils': 4.0.14(zod@4.3.6)
zod: 4.3.6
'@ai-sdk/gateway@3.0.37(zod@4.3.6)':
'@ai-sdk/gateway@3.0.39(zod@4.3.6)':
dependencies:
'@ai-sdk/provider': 3.0.8
'@ai-sdk/provider-utils': 4.0.14(zod@4.3.6)
@@ -8234,13 +8230,6 @@ snapshots:
'@ai-sdk/provider-utils': 4.0.14(zod@4.3.6)
zod: 4.3.6
'@ai-sdk/provider-utils@4.0.13(zod@4.3.6)':
dependencies:
'@ai-sdk/provider': 3.0.7
'@standard-schema/spec': 1.1.0
eventsource-parser: 3.0.6
zod: 4.3.6
'@ai-sdk/provider-utils@4.0.14(zod@4.3.6)':
dependencies:
'@ai-sdk/provider': 3.0.8
@@ -8248,10 +8237,6 @@ snapshots:
eventsource-parser: 3.0.6
zod: 4.3.6
'@ai-sdk/provider@3.0.7':
dependencies:
json-schema: 0.4.0
'@ai-sdk/provider@3.0.8':
dependencies:
json-schema: 0.4.0
@@ -9666,62 +9651,62 @@ snapshots:
'@babel/helper-string-parser': 7.27.1
'@babel/helper-validator-identifier': 7.28.5
'@better-auth/core@1.5.0-beta.11(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.0(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)':
'@better-auth/core@1.5.0-beta.13(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.1(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)':
dependencies:
'@better-auth/utils': 0.3.1
'@better-fetch/fetch': 1.1.21
'@standard-schema/spec': 1.1.0
better-call: 1.2.0(zod@4.3.6)
better-call: 1.2.1(zod@4.3.6)
jose: 6.1.3
kysely: 0.28.10
nanostores: 1.1.0
zod: 4.3.6
'@better-auth/drizzle-adapter@1.5.0-beta.11(@better-auth/core@1.5.0-beta.11(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.0(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))(@better-auth/utils@0.3.1)(drizzle-orm@1.0.0-beta.9-e89174b(@electric-sql/pglite@0.3.2)(@opentelemetry/api@1.9.0)(@prisma/client@7.2.0(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(@types/mssql@9.1.9)(@types/pg@8.16.0)(mssql@11.0.1)(mysql2@3.15.3)(pg@8.18.0)(postgres@3.4.7)(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)))':
'@better-auth/drizzle-adapter@1.5.0-beta.13(@better-auth/core@1.5.0-beta.13(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.1(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))(@better-auth/utils@0.3.1)(drizzle-orm@1.0.0-beta.9-e89174b(@electric-sql/pglite@0.3.2)(@opentelemetry/api@1.9.0)(@prisma/client@7.2.0(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(@types/mssql@9.1.9)(@types/pg@8.16.0)(mssql@11.0.1)(mysql2@3.15.3)(pg@8.18.0)(postgres@3.4.7)(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)))':
dependencies:
'@better-auth/core': 1.5.0-beta.11(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.0(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)
'@better-auth/core': 1.5.0-beta.13(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.1(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)
'@better-auth/utils': 0.3.1
drizzle-orm: 1.0.0-beta.9-e89174b(@electric-sql/pglite@0.3.2)(@opentelemetry/api@1.9.0)(@prisma/client@7.2.0(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(@types/mssql@9.1.9)(@types/pg@8.16.0)(mssql@11.0.1)(mysql2@3.15.3)(pg@8.18.0)(postgres@3.4.7)(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))
'@better-auth/kysely-adapter@1.5.0-beta.11(@better-auth/core@1.5.0-beta.11(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.0(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))(@better-auth/utils@0.3.1)(kysely@0.28.10)':
'@better-auth/kysely-adapter@1.5.0-beta.13(@better-auth/core@1.5.0-beta.13(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.1(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))(@better-auth/utils@0.3.1)(kysely@0.28.10)':
dependencies:
'@better-auth/core': 1.5.0-beta.11(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.0(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)
'@better-auth/core': 1.5.0-beta.13(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.1(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)
'@better-auth/utils': 0.3.1
kysely: 0.28.10
'@better-auth/memory-adapter@1.5.0-beta.11(@better-auth/core@1.5.0-beta.11(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.0(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))(@better-auth/utils@0.3.1)':
'@better-auth/memory-adapter@1.5.0-beta.13(@better-auth/core@1.5.0-beta.13(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.1(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))(@better-auth/utils@0.3.1)':
dependencies:
'@better-auth/core': 1.5.0-beta.11(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.0(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)
'@better-auth/core': 1.5.0-beta.13(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.1(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)
'@better-auth/utils': 0.3.1
'@better-auth/mongo-adapter@1.5.0-beta.11(@better-auth/core@1.5.0-beta.11(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.0(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))(@better-auth/utils@0.3.1)(mongodb@7.0.0(socks@2.8.7))':
'@better-auth/mongo-adapter@1.5.0-beta.13(@better-auth/core@1.5.0-beta.13(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.1(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))(@better-auth/utils@0.3.1)(mongodb@7.0.0(socks@2.8.7))':
dependencies:
'@better-auth/core': 1.5.0-beta.11(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.0(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)
'@better-auth/core': 1.5.0-beta.13(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.1(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)
'@better-auth/utils': 0.3.1
mongodb: 7.0.0(socks@2.8.7)
'@better-auth/passkey@1.5.0-beta.11(38c18a8d8b45924e68e857ec7a702968)':
'@better-auth/passkey@1.5.0-beta.13(2258e4f412fd167666cad25c7546abd6)':
dependencies:
'@better-auth/core': 1.5.0-beta.11(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.0(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)
'@better-auth/core': 1.5.0-beta.13(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.1(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)
'@better-auth/utils': 0.3.1
'@better-fetch/fetch': 1.1.21
'@simplewebauthn/browser': 13.2.2
'@simplewebauthn/server': 13.2.2
better-auth: 1.5.0-beta.11(@prisma/client@7.2.0(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(@tanstack/react-start@1.158.3(crossws@0.4.3(srvx@0.10.1))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rolldown-vite@7.3.1(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)))(drizzle-kit@1.0.0-beta.9-e89174b)(drizzle-orm@1.0.0-beta.9-e89174b(@electric-sql/pglite@0.3.2)(@opentelemetry/api@1.9.0)(@prisma/client@7.2.0(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(@types/mssql@9.1.9)(@types/pg@8.16.0)(mssql@11.0.1)(mysql2@3.15.3)(pg@8.18.0)(postgres@3.4.7)(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)))(mongodb@7.0.0(socks@2.8.7))(mysql2@3.15.3)(pg@8.18.0)(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
better-call: 1.2.0(zod@4.3.6)
better-auth: 1.5.0-beta.13(@prisma/client@7.2.0(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(@tanstack/react-start@1.159.0(crossws@0.4.3(srvx@0.10.1))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rolldown-vite@7.3.1(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)))(drizzle-kit@1.0.0-beta.9-e89174b)(drizzle-orm@1.0.0-beta.9-e89174b(@electric-sql/pglite@0.3.2)(@opentelemetry/api@1.9.0)(@prisma/client@7.2.0(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(@types/mssql@9.1.9)(@types/pg@8.16.0)(mssql@11.0.1)(mysql2@3.15.3)(pg@8.18.0)(postgres@3.4.7)(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)))(mongodb@7.0.0(socks@2.8.7))(mysql2@3.15.3)(pg@8.18.0)(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
better-call: 1.2.1(zod@4.3.6)
nanostores: 1.1.0
zod: 4.3.6
'@better-auth/prisma-adapter@1.5.0-beta.11(@better-auth/core@1.5.0-beta.11(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.0(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))(@better-auth/utils@0.3.1)(@prisma/client@7.2.0(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))':
'@better-auth/prisma-adapter@1.5.0-beta.13(@better-auth/core@1.5.0-beta.13(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.1(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))(@better-auth/utils@0.3.1)(@prisma/client@7.2.0(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))':
dependencies:
'@better-auth/core': 1.5.0-beta.11(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.0(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)
'@better-auth/core': 1.5.0-beta.13(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.1(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)
'@better-auth/utils': 0.3.1
'@prisma/client': 7.2.0(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3)
prisma: 7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)
'@better-auth/telemetry@1.5.0-beta.11(@better-auth/core@1.5.0-beta.11(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.0(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))':
'@better-auth/telemetry@1.5.0-beta.13(@better-auth/core@1.5.0-beta.13(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.1(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))':
dependencies:
'@better-auth/core': 1.5.0-beta.11(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.0(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)
'@better-auth/core': 1.5.0-beta.13(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.1(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)
'@better-auth/utils': 0.3.1
'@better-fetch/fetch': 1.1.21
@@ -12314,59 +12299,59 @@ snapshots:
'@tanstack/query-core': 5.90.20
react: 19.2.4
'@tanstack/react-router-ssr-query@1.158.1(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.4))(@tanstack/react-router@1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@tanstack/router-core@1.158.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
'@tanstack/react-router-ssr-query@1.158.4(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.4))(@tanstack/react-router@1.158.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@tanstack/router-core@1.158.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
dependencies:
'@tanstack/query-core': 5.90.20
'@tanstack/react-query': 5.90.20(react@19.2.4)
'@tanstack/react-router': 1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@tanstack/router-ssr-query-core': 1.158.1(@tanstack/query-core@5.90.20)(@tanstack/router-core@1.158.1)
'@tanstack/react-router': 1.158.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@tanstack/router-ssr-query-core': 1.158.4(@tanstack/query-core@5.90.20)(@tanstack/router-core@1.158.4)
react: 19.2.4
react-dom: 19.2.4(react@19.2.4)
transitivePeerDependencies:
- '@tanstack/router-core'
'@tanstack/react-router@1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
'@tanstack/react-router@1.158.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
dependencies:
'@tanstack/history': 1.154.14
'@tanstack/react-store': 0.8.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@tanstack/router-core': 1.158.1
'@tanstack/router-core': 1.158.4
isbot: 5.1.33
react: 19.2.4
react-dom: 19.2.4(react@19.2.4)
tiny-invariant: 1.3.3
tiny-warning: 1.0.3
'@tanstack/react-start-client@1.158.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
'@tanstack/react-start-client@1.158.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
dependencies:
'@tanstack/react-router': 1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@tanstack/router-core': 1.158.1
'@tanstack/start-client-core': 1.158.3
'@tanstack/react-router': 1.158.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@tanstack/router-core': 1.158.4
'@tanstack/start-client-core': 1.158.4
react: 19.2.4
react-dom: 19.2.4(react@19.2.4)
tiny-invariant: 1.3.3
tiny-warning: 1.0.3
'@tanstack/react-start-server@1.158.3(crossws@0.4.3(srvx@0.10.1))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
'@tanstack/react-start-server@1.159.0(crossws@0.4.3(srvx@0.10.1))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
dependencies:
'@tanstack/history': 1.154.14
'@tanstack/react-router': 1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@tanstack/router-core': 1.158.1
'@tanstack/start-client-core': 1.158.3
'@tanstack/start-server-core': 1.158.3(crossws@0.4.3(srvx@0.10.1))
'@tanstack/react-router': 1.158.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@tanstack/router-core': 1.158.4
'@tanstack/start-client-core': 1.158.4
'@tanstack/start-server-core': 1.159.0(crossws@0.4.3(srvx@0.10.1))
react: 19.2.4
react-dom: 19.2.4(react@19.2.4)
transitivePeerDependencies:
- crossws
'@tanstack/react-start@1.158.3(crossws@0.4.3(srvx@0.10.1))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rolldown-vite@7.3.1(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0))':
'@tanstack/react-start@1.159.0(crossws@0.4.3(srvx@0.10.1))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rolldown-vite@7.3.1(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0))':
dependencies:
'@tanstack/react-router': 1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@tanstack/react-start-client': 1.158.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@tanstack/react-start-server': 1.158.3(crossws@0.4.3(srvx@0.10.1))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@tanstack/react-router': 1.158.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@tanstack/react-start-client': 1.158.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@tanstack/react-start-server': 1.159.0(crossws@0.4.3(srvx@0.10.1))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@tanstack/router-utils': 1.158.0
'@tanstack/start-client-core': 1.158.3
'@tanstack/start-plugin-core': 1.158.3(@tanstack/react-router@1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(crossws@0.4.3(srvx@0.10.1))(rolldown-vite@7.3.1(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0))
'@tanstack/start-server-core': 1.158.3(crossws@0.4.3(srvx@0.10.1))
'@tanstack/start-client-core': 1.158.4
'@tanstack/start-plugin-core': 1.159.0(@tanstack/react-router@1.158.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(crossws@0.4.3(srvx@0.10.1))(rolldown-vite@7.3.1(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0))
'@tanstack/start-server-core': 1.159.0(crossws@0.4.3(srvx@0.10.1))
pathe: 2.0.3
react: 19.2.4
react-dom: 19.2.4(react@19.2.4)
@@ -12385,7 +12370,7 @@ snapshots:
react-dom: 19.2.4(react@19.2.4)
use-sync-external-store: 1.6.0(react@19.2.4)
'@tanstack/router-core@1.158.1':
'@tanstack/router-core@1.158.4':
dependencies:
'@tanstack/history': 1.154.14
'@tanstack/store': 0.8.0
@@ -12395,9 +12380,9 @@ snapshots:
tiny-invariant: 1.3.3
tiny-warning: 1.0.3
'@tanstack/router-generator@1.158.1':
'@tanstack/router-generator@1.158.4':
dependencies:
'@tanstack/router-core': 1.158.1
'@tanstack/router-core': 1.158.4
'@tanstack/router-utils': 1.158.0
'@tanstack/virtual-file-routes': 1.154.7
prettier: 3.8.0
@@ -12408,7 +12393,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@tanstack/router-plugin@1.158.1(@tanstack/react-router@1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(rolldown-vite@7.3.1(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0))':
'@tanstack/router-plugin@1.158.4(@tanstack/react-router@1.158.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(rolldown-vite@7.3.1(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0))':
dependencies:
'@babel/core': 7.29.0
'@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0)
@@ -12416,23 +12401,23 @@ snapshots:
'@babel/template': 7.28.6
'@babel/traverse': 7.29.0
'@babel/types': 7.29.0
'@tanstack/router-core': 1.158.1
'@tanstack/router-generator': 1.158.1
'@tanstack/router-core': 1.158.4
'@tanstack/router-generator': 1.158.4
'@tanstack/router-utils': 1.158.0
'@tanstack/virtual-file-routes': 1.154.7
chokidar: 3.6.0
unplugin: 2.3.11
zod: 3.25.76
optionalDependencies:
'@tanstack/react-router': 1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@tanstack/react-router': 1.158.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
vite: rolldown-vite@7.3.1(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)
transitivePeerDependencies:
- supports-color
'@tanstack/router-ssr-query-core@1.158.1(@tanstack/query-core@5.90.20)(@tanstack/router-core@1.158.1)':
'@tanstack/router-ssr-query-core@1.158.4(@tanstack/query-core@5.90.20)(@tanstack/router-core@1.158.4)':
dependencies:
'@tanstack/query-core': 5.90.20
'@tanstack/router-core': 1.158.1
'@tanstack/router-core': 1.158.4
'@tanstack/router-utils@1.158.0':
dependencies:
@@ -12448,29 +12433,29 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@tanstack/start-client-core@1.158.3':
'@tanstack/start-client-core@1.158.4':
dependencies:
'@tanstack/router-core': 1.158.1
'@tanstack/router-core': 1.158.4
'@tanstack/start-fn-stubs': 1.154.7
'@tanstack/start-storage-context': 1.158.1
'@tanstack/start-storage-context': 1.158.4
seroval: 1.4.2
tiny-invariant: 1.3.3
tiny-warning: 1.0.3
'@tanstack/start-fn-stubs@1.154.7': {}
'@tanstack/start-plugin-core@1.158.3(@tanstack/react-router@1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(crossws@0.4.3(srvx@0.10.1))(rolldown-vite@7.3.1(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0))':
'@tanstack/start-plugin-core@1.159.0(@tanstack/react-router@1.158.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(crossws@0.4.3(srvx@0.10.1))(rolldown-vite@7.3.1(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0))':
dependencies:
'@babel/code-frame': 7.27.1
'@babel/core': 7.29.0
'@babel/types': 7.29.0
'@rolldown/pluginutils': 1.0.0-beta.40
'@tanstack/router-core': 1.158.1
'@tanstack/router-generator': 1.158.1
'@tanstack/router-plugin': 1.158.1(@tanstack/react-router@1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(rolldown-vite@7.3.1(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0))
'@tanstack/router-core': 1.158.4
'@tanstack/router-generator': 1.158.4
'@tanstack/router-plugin': 1.158.4(@tanstack/react-router@1.158.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(rolldown-vite@7.3.1(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0))
'@tanstack/router-utils': 1.158.0
'@tanstack/start-client-core': 1.158.3
'@tanstack/start-server-core': 1.158.3(crossws@0.4.3(srvx@0.10.1))
'@tanstack/start-client-core': 1.158.4
'@tanstack/start-server-core': 1.159.0(crossws@0.4.3(srvx@0.10.1))
cheerio: 1.1.2
exsolve: 1.0.8
pathe: 2.0.3
@@ -12489,29 +12474,29 @@ snapshots:
- vite-plugin-solid
- webpack
'@tanstack/start-server-core@1.158.3(crossws@0.4.3(srvx@0.10.1))':
'@tanstack/start-server-core@1.159.0(crossws@0.4.3(srvx@0.10.1))':
dependencies:
'@tanstack/history': 1.154.14
'@tanstack/router-core': 1.158.1
'@tanstack/start-client-core': 1.158.3
'@tanstack/start-storage-context': 1.158.1
'@tanstack/router-core': 1.158.4
'@tanstack/start-client-core': 1.158.4
'@tanstack/start-storage-context': 1.158.4
h3-v2: h3@2.0.1-rc.11(crossws@0.4.3(srvx@0.10.1))
seroval: 1.4.2
tiny-invariant: 1.3.3
transitivePeerDependencies:
- crossws
'@tanstack/start-storage-context@1.158.1':
'@tanstack/start-storage-context@1.158.4':
dependencies:
'@tanstack/router-core': 1.158.1
'@tanstack/router-core': 1.158.4
'@tanstack/store@0.8.0': {}
'@tanstack/virtual-file-routes@1.154.7': {}
'@tanstack/zod-adapter@1.158.1(@tanstack/react-router@1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(zod@4.3.6)':
'@tanstack/zod-adapter@1.158.4(@tanstack/react-router@1.158.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(zod@4.3.6)':
dependencies:
'@tanstack/react-router': 1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@tanstack/react-router': 1.158.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
zod: 4.3.6
'@tediousjs/connection-string@0.5.0': {}
@@ -12869,18 +12854,18 @@ snapshots:
agent-base@7.1.4: {}
ai-sdk-ollama@3.4.0(ai@6.0.75(zod@4.3.6))(zod@4.3.6):
ai-sdk-ollama@3.5.0(ai@6.0.77(zod@4.3.6))(zod@4.3.6):
dependencies:
'@ai-sdk/provider': 3.0.7
'@ai-sdk/provider-utils': 4.0.13(zod@4.3.6)
ai: 6.0.75(zod@4.3.6)
'@ai-sdk/provider': 3.0.8
'@ai-sdk/provider-utils': 4.0.14(zod@4.3.6)
ai: 6.0.77(zod@4.3.6)
ollama: 0.6.3
transitivePeerDependencies:
- zod
ai@6.0.75(zod@4.3.6):
ai@6.0.77(zod@4.3.6):
dependencies:
'@ai-sdk/gateway': 3.0.37(zod@4.3.6)
'@ai-sdk/gateway': 3.0.39(zod@4.3.6)
'@ai-sdk/provider': 3.0.8
'@ai-sdk/provider-utils': 4.0.14(zod@4.3.6)
'@opentelemetry/api': 1.9.0
@@ -13054,20 +13039,20 @@ snapshots:
node-addon-api: 8.5.0
node-gyp-build: 4.8.4
better-auth@1.5.0-beta.11(@prisma/client@7.2.0(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(@tanstack/react-start@1.158.3(crossws@0.4.3(srvx@0.10.1))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rolldown-vite@7.3.1(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)))(drizzle-kit@1.0.0-beta.9-e89174b)(drizzle-orm@1.0.0-beta.9-e89174b(@electric-sql/pglite@0.3.2)(@opentelemetry/api@1.9.0)(@prisma/client@7.2.0(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(@types/mssql@9.1.9)(@types/pg@8.16.0)(mssql@11.0.1)(mysql2@3.15.3)(pg@8.18.0)(postgres@3.4.7)(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)))(mongodb@7.0.0(socks@2.8.7))(mysql2@3.15.3)(pg@8.18.0)(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
better-auth@1.5.0-beta.13(@prisma/client@7.2.0(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(@tanstack/react-start@1.159.0(crossws@0.4.3(srvx@0.10.1))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rolldown-vite@7.3.1(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)))(drizzle-kit@1.0.0-beta.9-e89174b)(drizzle-orm@1.0.0-beta.9-e89174b(@electric-sql/pglite@0.3.2)(@opentelemetry/api@1.9.0)(@prisma/client@7.2.0(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(@types/mssql@9.1.9)(@types/pg@8.16.0)(mssql@11.0.1)(mysql2@3.15.3)(pg@8.18.0)(postgres@3.4.7)(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)))(mongodb@7.0.0(socks@2.8.7))(mysql2@3.15.3)(pg@8.18.0)(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
dependencies:
'@better-auth/core': 1.5.0-beta.11(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.0(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)
'@better-auth/drizzle-adapter': 1.5.0-beta.11(@better-auth/core@1.5.0-beta.11(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.0(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))(@better-auth/utils@0.3.1)(drizzle-orm@1.0.0-beta.9-e89174b(@electric-sql/pglite@0.3.2)(@opentelemetry/api@1.9.0)(@prisma/client@7.2.0(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(@types/mssql@9.1.9)(@types/pg@8.16.0)(mssql@11.0.1)(mysql2@3.15.3)(pg@8.18.0)(postgres@3.4.7)(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)))
'@better-auth/kysely-adapter': 1.5.0-beta.11(@better-auth/core@1.5.0-beta.11(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.0(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))(@better-auth/utils@0.3.1)(kysely@0.28.10)
'@better-auth/memory-adapter': 1.5.0-beta.11(@better-auth/core@1.5.0-beta.11(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.0(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))(@better-auth/utils@0.3.1)
'@better-auth/mongo-adapter': 1.5.0-beta.11(@better-auth/core@1.5.0-beta.11(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.0(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))(@better-auth/utils@0.3.1)(mongodb@7.0.0(socks@2.8.7))
'@better-auth/prisma-adapter': 1.5.0-beta.11(@better-auth/core@1.5.0-beta.11(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.0(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))(@better-auth/utils@0.3.1)(@prisma/client@7.2.0(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))
'@better-auth/telemetry': 1.5.0-beta.11(@better-auth/core@1.5.0-beta.11(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.0(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))
'@better-auth/core': 1.5.0-beta.13(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.1(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)
'@better-auth/drizzle-adapter': 1.5.0-beta.13(@better-auth/core@1.5.0-beta.13(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.1(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))(@better-auth/utils@0.3.1)(drizzle-orm@1.0.0-beta.9-e89174b(@electric-sql/pglite@0.3.2)(@opentelemetry/api@1.9.0)(@prisma/client@7.2.0(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(@types/mssql@9.1.9)(@types/pg@8.16.0)(mssql@11.0.1)(mysql2@3.15.3)(pg@8.18.0)(postgres@3.4.7)(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)))
'@better-auth/kysely-adapter': 1.5.0-beta.13(@better-auth/core@1.5.0-beta.13(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.1(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))(@better-auth/utils@0.3.1)(kysely@0.28.10)
'@better-auth/memory-adapter': 1.5.0-beta.13(@better-auth/core@1.5.0-beta.13(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.1(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))(@better-auth/utils@0.3.1)
'@better-auth/mongo-adapter': 1.5.0-beta.13(@better-auth/core@1.5.0-beta.13(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.1(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))(@better-auth/utils@0.3.1)(mongodb@7.0.0(socks@2.8.7))
'@better-auth/prisma-adapter': 1.5.0-beta.13(@better-auth/core@1.5.0-beta.13(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.1(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))(@better-auth/utils@0.3.1)(@prisma/client@7.2.0(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))
'@better-auth/telemetry': 1.5.0-beta.13(@better-auth/core@1.5.0-beta.13(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.2.1(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))
'@better-auth/utils': 0.3.1
'@better-fetch/fetch': 1.1.21
'@noble/ciphers': 2.1.1
'@noble/hashes': 2.0.1
better-call: 1.2.0(zod@4.3.6)
better-call: 1.2.1(zod@4.3.6)
defu: 6.1.4
jose: 6.1.3
kysely: 0.28.10
@@ -13075,7 +13060,7 @@ snapshots:
zod: 4.3.6
optionalDependencies:
'@prisma/client': 7.2.0(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3)
'@tanstack/react-start': 1.158.3(crossws@0.4.3(srvx@0.10.1))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rolldown-vite@7.3.1(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0))
'@tanstack/react-start': 1.159.0(crossws@0.4.3(srvx@0.10.1))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rolldown-vite@7.3.1(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0))
drizzle-kit: 1.0.0-beta.9-e89174b
drizzle-orm: 1.0.0-beta.9-e89174b(@electric-sql/pglite@0.3.2)(@opentelemetry/api@1.9.0)(@prisma/client@7.2.0(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(@types/mssql@9.1.9)(@types/pg@8.16.0)(mssql@11.0.1)(mysql2@3.15.3)(pg@8.18.0)(postgres@3.4.7)(prisma@7.2.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))
mongodb: 7.0.0(socks@2.8.7)
@@ -13085,7 +13070,7 @@ snapshots:
react: 19.2.4
react-dom: 19.2.4(react@19.2.4)
better-call@1.2.0(zod@4.3.6):
better-call@1.2.1(zod@4.3.6):
dependencies:
'@better-auth/utils': 0.3.1
'@better-fetch/fetch': 1.1.21
@@ -13943,6 +13928,8 @@ snapshots:
merge2: 1.4.1
micromatch: 4.0.8
fast-json-patch@3.1.1: {}
fast-json-stable-stringify@2.1.0: {}
fast-uri@3.1.0: {}
@@ -15006,7 +14993,7 @@ snapshots:
node-releases@2.0.27: {}
nodemailer@8.0.0: {}
nodemailer@8.0.1: {}
nopt@9.0.0:
dependencies:
+20
View File
@@ -77,6 +77,26 @@ export const resumeDto = {
output: z.void(),
},
patch: {
input: z.object({
id: z.string().describe("The ID of the resume to patch."),
operations: z
.array(
z.object({
op: z.enum(["add", "remove", "replace", "move", "copy", "test"]),
path: z.string(),
value: z.any().optional(),
from: z.string().optional(),
}),
)
.min(1)
.describe("An array of JSON Patch (RFC 6902) operations to apply to the resume data."),
}),
output: resumeSchema
.omit({ password: true, userId: true, createdAt: true, updatedAt: true })
.extend({ hasPassword: z.boolean() }),
},
duplicate: {
input: resumeSchema.pick({ id: true, name: true, slug: true, tags: true }),
output: z.string().describe("The ID of the duplicated resume."),
+26
View File
@@ -1,3 +1,4 @@
import type { Operation } from "fast-json-patch";
import z from "zod";
import { sampleResumeData } from "@/schema/resume/sample";
import { generateRandomName, slugify } from "@/utils/string";
@@ -193,6 +194,31 @@ export const resumeRouter = {
});
}),
patch: protectedProcedure
.route({
method: "PATCH",
path: "/resume/{id}",
tags: ["Resume"],
summary: "Patch a resume",
description:
"Apply JSON Patch (RFC 6902) operations to partially update a resume's data. This allows you to make small, targeted changes without sending the entire resume object.",
})
.input(resumeDto.patch.input)
.output(resumeDto.patch.output)
.errors({
INVALID_PATCH_OPERATIONS: {
message: "The patch operations are invalid or produced an invalid resume.",
status: 400,
},
})
.handler(async ({ context, input }) => {
return await resumeService.patch({
id: input.id,
userId: context.user.id,
operations: input.operations as Operation[],
});
}),
setLocked: protectedProcedure
.route({
method: "POST",
+50
View File
@@ -1,6 +1,7 @@
import { ORPCError } from "@orpc/client";
import { and, arrayContains, asc, desc, eq, sql } from "drizzle-orm";
import { get } from "es-toolkit/compat";
import type { Operation } from "fast-json-patch";
import { match } from "ts-pattern";
import { schema } from "@/integrations/drizzle";
import { db } from "@/integrations/drizzle/client";
@@ -9,6 +10,7 @@ import { defaultResumeData } from "@/schema/resume/data";
import { env } from "@/utils/env";
import type { Locale } from "@/utils/locale";
import { hashPassword } from "@/utils/password";
import { applyResumePatches, ResumePatchError } from "@/utils/resume/patch";
import { generateId } from "@/utils/string";
import { hasResumeAccess } from "../helpers/resume-access";
import { getStorageService } from "./storage";
@@ -317,6 +319,54 @@ export const resumeService = {
}
},
patch: async (input: { id: string; userId: string; operations: Operation[] }) => {
const [existing] = await db
.select({ data: schema.resume.data, isLocked: schema.resume.isLocked })
.from(schema.resume)
.where(and(eq(schema.resume.id, input.id), eq(schema.resume.userId, input.userId)));
if (!existing) throw new ORPCError("NOT_FOUND");
if (existing.isLocked) throw new ORPCError("RESUME_LOCKED");
let patchedData: ResumeData;
try {
patchedData = applyResumePatches(existing.data, input.operations);
} catch (error) {
if (error instanceof ResumePatchError) {
throw new ORPCError("INVALID_PATCH_OPERATIONS", {
status: 400,
message: error.message,
data: { code: error.code, index: error.index, operation: error.operation },
});
}
throw new ORPCError("INVALID_PATCH_OPERATIONS", {
status: 400,
message: error instanceof Error ? error.message : "Failed to apply patch operations",
});
}
const [resume] = await db
.update(schema.resume)
.set({ data: patchedData })
.where(
and(eq(schema.resume.id, input.id), eq(schema.resume.isLocked, false), eq(schema.resume.userId, input.userId)),
)
.returning({
id: schema.resume.id,
name: schema.resume.name,
slug: schema.resume.slug,
tags: schema.resume.tags,
data: schema.resume.data,
isPublic: schema.resume.isPublic,
isLocked: schema.resume.isLocked,
hasPassword: sql<boolean>`${schema.resume.password} IS NOT NULL`,
});
return resume;
},
setLocked: async (input: { id: string; userId: string; isLocked: boolean }) => {
await db
.update(schema.resume)
+109
View File
@@ -0,0 +1,109 @@
import type { JsonPatchError, Operation } from "fast-json-patch";
import jsonpatch from "fast-json-patch";
import { type ResumeData, resumeDataSchema } from "@/schema/resume/data";
export type { Operation };
/**
* A structured error thrown when a JSON Patch operation fails.
* Contains only the relevant details -- never the full document tree.
*/
export class ResumePatchError extends Error {
/** The error code from `fast-json-patch`, e.g. `TEST_OPERATION_FAILED`. */
code: string;
/** The zero-based index of the failing operation in the operations array. */
index: number;
/** The operation object that caused the failure. */
operation: Operation;
constructor(code: string, message: string, index: number, operation: Operation) {
super(message);
this.name = "ResumePatchError";
this.code = code;
this.index = index;
this.operation = operation;
}
}
/**
* Human-readable messages for each `fast-json-patch` error code.
* These are returned to the API consumer instead of the raw library output.
*/
const patchErrorMessages: Record<string, string> = {
SEQUENCE_NOT_AN_ARRAY: "Patch sequence must be an array.",
OPERATION_NOT_AN_OBJECT: "Operation is not an object.",
OPERATION_OP_INVALID: "Operation `op` property is not one of the operations defined in RFC 6902.",
OPERATION_PATH_INVALID: "Operation `path` property is not a valid JSON Pointer string.",
OPERATION_FROM_REQUIRED: "Operation `from` property is required for `move` and `copy` operations.",
OPERATION_VALUE_REQUIRED: "Operation `value` property is required for `add`, `replace`, and `test` operations.",
OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED:
"Operation `value` contains an `undefined` value, which is not valid in JSON.",
OPERATION_PATH_CANNOT_ADD: "Cannot perform an `add` operation at the desired path.",
OPERATION_PATH_UNRESOLVABLE: "Cannot perform the operation at a path that does not exist.",
OPERATION_FROM_UNRESOLVABLE: "Cannot perform the operation from a path that does not exist.",
OPERATION_PATH_ILLEGAL_ARRAY_INDEX: "Array index in path must be an unsigned base-10 integer.",
OPERATION_VALUE_OUT_OF_BOUNDS: "The specified array index is greater than the number of elements in the array.",
TEST_OPERATION_FAILED: "Test operation failed -- the value at the given path did not match the expected value.",
};
/**
* Checks whether an error is a `JsonPatchError` from `fast-json-patch`.
* The library doesn't export the class directly, so we duck-type it.
*/
function isJsonPatchError(error: unknown): error is JsonPatchError {
return error instanceof Error && "index" in error && "operation" in error;
}
/**
* Converts a `JsonPatchError` into a clean `ResumePatchError` that omits the document tree.
*/
function toResumePatchError(error: JsonPatchError): ResumePatchError {
const code = error.name;
const message = patchErrorMessages[code] ?? error.message;
const index = error.index ?? 0;
const operation = error.operation as Operation;
return new ResumePatchError(code, message, index, operation);
}
/**
* Applies an array of JSON Patch (RFC 6902) operations to a `ResumeData` object.
*
* This function validates the operations before applying them, then validates the
* resulting document against the `resumeDataSchema` to ensure the patched data is
* still a valid resume.
*
* The original `data` object is not mutated; a deep clone is created internally.
*
* @see https://docs.rxresu.me/guides/using-the-patch-api — for usage examples and API details.
* @see https://datatracker.ietf.org/doc/html/rfc6902 — JSON Patch specification.
*
* @param data - The current resume data to patch.
* @param operations - An array of JSON Patch operations to apply.
* @returns The patched and validated `ResumeData` object.
* @throws {ResumePatchError} If the operations are structurally invalid or target non-existent paths.
* @throws {ResumePatchError} If a `test` operation does not match.
* @throws {Error} If the patched document does not conform to the `ResumeData` schema.
*/
export function applyResumePatches(data: ResumeData, operations: Operation[]): ResumeData {
// Validate operations structurally before applying.
const validationError = jsonpatch.validate(operations, data);
if (validationError) throw toResumePatchError(validationError);
// Apply operations. applyPatch throws on `test` failures.
let patched: ResumeData;
try {
const result = jsonpatch.applyPatch(data, operations, false, false);
patched = result.newDocument;
} catch (error: unknown) {
if (isJsonPatchError(error)) throw toResumePatchError(error);
throw error;
}
// Validate the result still conforms to ResumeData.
const parsed = resumeDataSchema.safeParse(patched);
if (!parsed.success) throw new Error(`Patch produced invalid resume data: ${parsed.error.message}`);
return parsed.data;
}