mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-08-25 15:52:21 +10:00
Release v5.2.8 (#3375)
Upgrades to Better Auth 1.7, expands Custom Styles coverage of item headers, and adds a human-approval step to the AI agent's resume edits. Breaking for self-hosters using a custom OAuth provider: the callback path changes from /api/auth/oauth2/callback/custom to /api/auth/callback/custom, and installs using OAUTH_DISCOVERY_URL need one additional UPDATE after upgrading. Both are documented in docs/self-hosting/sso.mdx. - Better Auth 1.7, with the account issuer migration and the jwks alg/crv columns the 1.7 jwt plugin requires - Agent edits gated behind an approval step, with crash-safe runs and context pruning - item-header now covers every section header row on every template; adds the item-header-row part - Fixes provider unlinking, auth error messages, and version conflicts on freshly created resumes - New /auth/error page, translated across all 53 target locales - DeepSeek Harness plugin moved into packages/dsh-plugin - Dependency bumps across the workspace
This commit is contained in:
@@ -23,13 +23,13 @@
|
||||
"@reactive-resume/resume": "workspace:*",
|
||||
"@reactive-resume/schema": "workspace:*",
|
||||
"@reactive-resume/utils": "workspace:*",
|
||||
"deepmerge-ts": "^8.0.1",
|
||||
"deepmerge-ts": "^8.0.2",
|
||||
"jsonrepair": "^3.15.0",
|
||||
"zod": "^4.4.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@reactive-resume/config": "workspace:*",
|
||||
"ai": "^7.0.66",
|
||||
"ai": "^7.0.77",
|
||||
"@typescript/native-preview": "7.0.0-dev.20260707.2",
|
||||
"typescript": "^7.0.2"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { fileURLToPath } from "node:url";
|
||||
// @boundaries-ignore root shared Vitest config
|
||||
import { createVitestProjectConfig } from "../../vitest.shared";
|
||||
import { createVitestProjectConfig } from "../../vitest.shared.mts";
|
||||
|
||||
export default createVitestProjectConfig({
|
||||
name: "@reactive-resume/ai",
|
||||
|
||||
+16
-16
@@ -21,20 +21,20 @@
|
||||
"test:agent": "vitest run --reporter=agent --reporter=json --outputFile.json=reports/vitest-results.json --passWithNoTests"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ai-sdk/anthropic": "^4.0.39",
|
||||
"@ai-sdk/cerebras": "^3.0.31",
|
||||
"@ai-sdk/cohere": "^4.0.27",
|
||||
"@ai-sdk/deepseek": "^3.0.28",
|
||||
"@ai-sdk/fireworks": "^3.0.33",
|
||||
"@ai-sdk/google": "^4.0.44",
|
||||
"@ai-sdk/groq": "^4.0.28",
|
||||
"@ai-sdk/mistral": "^4.0.29",
|
||||
"@ai-sdk/openai": "^4.0.42",
|
||||
"@ai-sdk/openai-compatible": "^3.0.31",
|
||||
"@ai-sdk/perplexity": "^4.0.29",
|
||||
"@ai-sdk/togetherai": "^3.0.32",
|
||||
"@ai-sdk/xai": "^4.0.40",
|
||||
"@aws-sdk/client-s3": "^3.1111.0",
|
||||
"@ai-sdk/anthropic": "^4.0.41",
|
||||
"@ai-sdk/cerebras": "^3.0.35",
|
||||
"@ai-sdk/cohere": "^4.0.29",
|
||||
"@ai-sdk/deepseek": "^3.0.31",
|
||||
"@ai-sdk/fireworks": "^3.0.38",
|
||||
"@ai-sdk/google": "^4.0.50",
|
||||
"@ai-sdk/groq": "^4.0.30",
|
||||
"@ai-sdk/mistral": "^4.0.32",
|
||||
"@ai-sdk/openai": "^4.0.46",
|
||||
"@ai-sdk/openai-compatible": "^3.0.35",
|
||||
"@ai-sdk/perplexity": "^4.0.31",
|
||||
"@ai-sdk/togetherai": "^3.0.36",
|
||||
"@ai-sdk/xai": "^4.0.43",
|
||||
"@aws-sdk/client-s3": "^3.1116.0",
|
||||
"@orpc/client": "^1.15.0",
|
||||
"@orpc/experimental-ratelimit": "^1.15.0",
|
||||
"@orpc/server": "^1.15.0",
|
||||
@@ -46,9 +46,9 @@
|
||||
"@reactive-resume/resume": "workspace:*",
|
||||
"@reactive-resume/schema": "workspace:*",
|
||||
"@reactive-resume/utils": "workspace:*",
|
||||
"ai": "^7.0.66",
|
||||
"ai": "^7.0.77",
|
||||
"bcrypt": "^6.0.0",
|
||||
"better-auth": "1.6.29",
|
||||
"better-auth": "1.7.1",
|
||||
"drizzle-orm": "1.0.0-rc.4",
|
||||
"drizzle-zod": "1.0.0-beta.14-a36c63d",
|
||||
"es-toolkit": "^1.51.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { fileURLToPath } from "node:url";
|
||||
// @boundaries-ignore root shared Vitest config
|
||||
import { createVitestProjectConfig } from "../../vitest.shared";
|
||||
import { createVitestProjectConfig } from "../../vitest.shared.mts";
|
||||
|
||||
export default createVitestProjectConfig({
|
||||
name: "@reactive-resume/api",
|
||||
|
||||
@@ -15,19 +15,19 @@
|
||||
"test:agent": "vitest run --reporter=agent --reporter=json --outputFile.json=reports/vitest-results.json --passWithNoTests"
|
||||
},
|
||||
"dependencies": {
|
||||
"@better-auth/api-key": "^1.6.29",
|
||||
"@better-auth/drizzle-adapter": "^1.6.29",
|
||||
"@better-auth/infra": "^0.3.7",
|
||||
"@better-auth/oauth-provider": "^1.6.29",
|
||||
"@better-auth/passkey": "^1.6.29",
|
||||
"@better-auth/api-key": "^1.7.1",
|
||||
"@better-auth/drizzle-adapter": "^1.7.1",
|
||||
"@better-auth/infra": "^0.4.2",
|
||||
"@better-auth/oauth-provider": "^1.7.1",
|
||||
"@better-auth/passkey": "^1.7.1",
|
||||
"@reactive-resume/db": "workspace:*",
|
||||
"@reactive-resume/email": "workspace:*",
|
||||
"@reactive-resume/env": "workspace:*",
|
||||
"@reactive-resume/utils": "workspace:*",
|
||||
"bcrypt": "^6.0.0",
|
||||
"better-auth": "1.6.29",
|
||||
"better-auth": "1.7.1",
|
||||
"drizzle-orm": "1.0.0-rc.4",
|
||||
"jose": "^6.2.9",
|
||||
"jose": "^6.2.10",
|
||||
"react": "^19.2.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -6,7 +6,9 @@ describe("social provider signup policy", () => {
|
||||
it.each(["google", "github", "linkedin"] as const)(
|
||||
"allows implicit signup through %s while honoring the global signup restriction",
|
||||
(provider) => {
|
||||
// Better Auth 1.7 allows a lazy `() => config` form; ours are always static objects.
|
||||
const config = auth.options.socialProviders?.[provider];
|
||||
if (typeof config === "function") throw new TypeError(`${provider} provider config should be a static object`);
|
||||
|
||||
expect(config).not.toHaveProperty("disableImplicitSignUp");
|
||||
expect(config?.disableSignUp).toBe(env.FLAG_DISABLE_SIGNUPS);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { GenericOAuthConfig } from "better-auth/plugins";
|
||||
import type { GenericOAuthConfig, GenericOAuthUserInfo } from "better-auth/plugins";
|
||||
import type { JWTPayload } from "jose";
|
||||
import { apiKey } from "@better-auth/api-key";
|
||||
import { drizzleAdapter } from "@better-auth/drizzle-adapter";
|
||||
@@ -8,7 +8,7 @@ import { passkey } from "@better-auth/passkey";
|
||||
import { compare, hash } from "bcrypt";
|
||||
import { APIError, betterAuth } from "better-auth";
|
||||
import { createAuthMiddleware } from "better-auth/api";
|
||||
import { verifyAccessToken } from "better-auth/oauth2";
|
||||
import { verifyBearerToken } from "better-auth/oauth2";
|
||||
import { admin, jwt } from "better-auth/plugins";
|
||||
import { genericOAuth } from "better-auth/plugins/generic-oauth";
|
||||
import { twoFactor } from "better-auth/plugins/two-factor";
|
||||
@@ -54,7 +54,7 @@ const OAUTH_AUDIENCES = [
|
||||
];
|
||||
|
||||
export function verifyOAuthToken(token: string): Promise<JWTPayload> {
|
||||
return verifyAccessToken(token, {
|
||||
return verifyBearerToken(token, {
|
||||
jwksUrl: `${internalBaseUrl}/api/auth/jwks`,
|
||||
verifyOptions: {
|
||||
issuer: `${authBaseUrl}/api/auth`,
|
||||
@@ -83,6 +83,34 @@ const oauthProviderRateLimit = isRateLimitEnabled
|
||||
userinfo: false,
|
||||
} as const);
|
||||
|
||||
// Better Auth 1.7 types generic-OAuth profile extras as `unknown`.
|
||||
function asString(value: unknown): string | undefined {
|
||||
return typeof value === "string" ? value : undefined;
|
||||
}
|
||||
|
||||
// `@better-auth/oauth-provider@1.7.1` declares OpenAPI parameter metadata (`schema.items`) in a
|
||||
// shape that is not `exactOptionalPropertyTypes`-clean, which stops the plugin from structurally
|
||||
// satisfying `BetterAuthPlugin`. `metadata` only feeds doc generation, so dropping it from the
|
||||
// endpoint types keeps request/response inference (`auth.api.*`) intact. Remove once upstream ships
|
||||
// EOPT-compatible endpoint types.
|
||||
type WithoutEndpointMetadata<TPlugin> = TPlugin extends { endpoints: infer TEndpoints }
|
||||
? Omit<TPlugin, "endpoints"> & {
|
||||
endpoints: {
|
||||
[K in keyof TEndpoints]: TEndpoints[K] extends {
|
||||
(...args: infer TArgs): infer TResult;
|
||||
options: infer TOptions;
|
||||
path: infer TPath;
|
||||
}
|
||||
? {
|
||||
(...args: TArgs): TResult;
|
||||
options: Omit<TOptions, "metadata">;
|
||||
path: TPath;
|
||||
}
|
||||
: TEndpoints[K];
|
||||
};
|
||||
}
|
||||
: TPlugin;
|
||||
|
||||
const getAuthConfig = () => {
|
||||
const authConfigs: GenericOAuthConfig[] = [];
|
||||
|
||||
@@ -97,12 +125,15 @@ const getAuthConfig = () => {
|
||||
tokenUrl: env.OAUTH_TOKEN_URL,
|
||||
userInfoUrl: env.OAUTH_USER_INFO_URL,
|
||||
scopes: env.OAUTH_SCOPES,
|
||||
redirectURI: `${authBaseUrl}/api/auth/oauth2/callback/custom`,
|
||||
mapProfileToUser: createProfileMapper({
|
||||
// Better Auth 1.7 folds generic OAuth providers into `socialProviders`, so the callback
|
||||
// is served by `/callback/:id` — the old `/oauth2/callback/:id` route no longer exists.
|
||||
redirectURI: `${authBaseUrl}/api/auth/callback/custom`,
|
||||
mapProfileToUser: createProfileMapper<GenericOAuthUserInfo>({
|
||||
providerName: "OAuth Provider",
|
||||
getPreferredUsername: (profile, context) => profile.preferred_username ?? context.emailLocalPart,
|
||||
getName: (profile, context) => profile.name ?? profile.preferred_username ?? context.emailLocalPart,
|
||||
getImage: (profile) => profile.image ?? profile.picture ?? profile.avatar_url,
|
||||
getPreferredUsername: (profile, context) => asString(profile.preferred_username) ?? context.emailLocalPart,
|
||||
getName: (profile, context) =>
|
||||
asString(profile.name) ?? asString(profile.preferred_username) ?? context.emailLocalPart,
|
||||
getImage: (profile) => asString(profile.image) ?? asString(profile.picture) ?? asString(profile.avatar_url),
|
||||
}),
|
||||
} satisfies GenericOAuthConfig);
|
||||
}
|
||||
@@ -146,6 +177,11 @@ const getAuthConfig = () => {
|
||||
}),
|
||||
},
|
||||
|
||||
// Without this, OAuth callback failures land on Better Auth's built-in `/api/auth/error`
|
||||
// page. It also backs the `oauthProvider` plugin's authorization errors that happen before
|
||||
// `redirect_uri` is validated and so cannot be returned to the requesting client.
|
||||
onAPIError: { errorURL: "/auth/error" },
|
||||
|
||||
advanced: {
|
||||
database: { generateId },
|
||||
useSecureCookies: authBaseUrl.startsWith("https://"),
|
||||
@@ -273,7 +309,7 @@ const getAuthConfig = () => {
|
||||
allowUnauthenticatedClientRegistration: true,
|
||||
rateLimit: oauthProviderRateLimit,
|
||||
silenceWarnings: { oauthAuthServerConfig: true },
|
||||
}),
|
||||
}) as WithoutEndpointMetadata<ReturnType<typeof oauthProvider>>,
|
||||
username({
|
||||
minUsernameLength: 3,
|
||||
maxUsernameLength: 64,
|
||||
|
||||
@@ -75,7 +75,6 @@ describe("createProfileMapper", () => {
|
||||
expect(dbMock.update).toHaveBeenCalledTimes(1);
|
||||
expect(dbMock.updateSet).toHaveBeenCalledWith({ email: "legacy.user@example.com" });
|
||||
expect(result).toEqual({
|
||||
id: "user-1",
|
||||
name: "Legacy User",
|
||||
email: "legacy.user@example.com",
|
||||
image: "https://example.com/new.png",
|
||||
@@ -153,7 +152,6 @@ describe("createProfileMapper", () => {
|
||||
|
||||
expect(dbMock.select).toHaveBeenCalledTimes(2);
|
||||
expect(result).toEqual({
|
||||
id: "user-1",
|
||||
name: "GitHub User",
|
||||
email: "github.user@example.com",
|
||||
image: "https://example.com/new.png",
|
||||
@@ -190,7 +188,6 @@ describe("createProfileMapper", () => {
|
||||
expect(dbMock.update).toHaveBeenCalledTimes(1);
|
||||
expect(dbMock.updateSet).toHaveBeenCalledWith({ email: "legacy.user@example.com" });
|
||||
expect(result).toEqual({
|
||||
id: "user-1",
|
||||
name: "Legacy User",
|
||||
email: "legacy.user@example.com",
|
||||
image: "https://example.com/new.png",
|
||||
|
||||
@@ -137,14 +137,14 @@ async function findAvailableUsernameSuffix(baseUsername: string, index = 1): Pro
|
||||
}
|
||||
|
||||
interface OAuthProfile {
|
||||
email?: string | null;
|
||||
id?: string | number | null;
|
||||
name?: string | null;
|
||||
picture?: string | null;
|
||||
image?: string | null;
|
||||
avatar_url?: string | null;
|
||||
login?: string | null;
|
||||
preferred_username?: string | null;
|
||||
email?: string | null | undefined;
|
||||
id?: string | number | null | undefined;
|
||||
name?: string | null | undefined;
|
||||
picture?: string | null | undefined;
|
||||
image?: string | null | undefined;
|
||||
avatar_url?: string | null | undefined;
|
||||
login?: string | null | undefined;
|
||||
preferred_username?: string | null | undefined;
|
||||
}
|
||||
|
||||
interface OAuthMapperContext {
|
||||
@@ -185,11 +185,14 @@ export function createProfileMapper<TProfile extends OAuthProfile>({
|
||||
const existingEmail = existingUser.email.trim().toLowerCase();
|
||||
await normalizeExistingUserEmail(existingUser.id, existingUser.email, existingEmail);
|
||||
|
||||
// Better Auth 1.7 forbids `mapProfileToUser` from returning `id`; provider identity is
|
||||
// resolved by `accountSubject` and existing local users are matched by `account.accountLinking`.
|
||||
const existingImage = image ?? existingUser.image;
|
||||
|
||||
return {
|
||||
id: existingUser.id,
|
||||
name: existingUser.name,
|
||||
email: existingEmail,
|
||||
image: image ?? existingUser.image,
|
||||
...(existingImage ? { image: existingImage } : {}),
|
||||
username: existingUser.username,
|
||||
displayUsername: existingUser.displayUsername,
|
||||
emailVerified: existingUser.emailVerified,
|
||||
@@ -203,7 +206,7 @@ export function createProfileMapper<TProfile extends OAuthProfile>({
|
||||
return {
|
||||
name: mappedName || username || emailLocalPart,
|
||||
email,
|
||||
image,
|
||||
...(image ? { image } : {}),
|
||||
username,
|
||||
displayUsername: username,
|
||||
emailVerified: true,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { fileURLToPath } from "node:url";
|
||||
// @boundaries-ignore root shared Vitest config
|
||||
import { createVitestProjectConfig } from "../../vitest.shared";
|
||||
import { createVitestProjectConfig } from "../../vitest.shared.mts";
|
||||
|
||||
export default createVitestProjectConfig({
|
||||
name: "@reactive-resume/auth",
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"isolatedModules": true,
|
||||
"allowImportingTsExtensions": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"noUncheckedSideEffectImports": true,
|
||||
"noUnusedLocals": true,
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@reactive-resume/config": "workspace:*",
|
||||
"@types/pg": "^8.23.0",
|
||||
"@types/pg": "^8.23.1",
|
||||
"@typescript/native-preview": "7.0.0-dev.20260707.2",
|
||||
"drizzle-kit": "1.0.0-rc.4",
|
||||
"typescript": "^7.0.2"
|
||||
|
||||
@@ -78,6 +78,10 @@ export const account = pg.pgTable(
|
||||
.$defaultFn(() => generateId()),
|
||||
accountId: pg.text("account_id").notNull(),
|
||||
providerId: pg.text("provider_id").notNull().default("credential"),
|
||||
// Better Auth 1.7 scopes account identity to (issuer, accountId) rather than providerId.
|
||||
// Real OIDC issuers are stored verbatim; providers without one get a synthetic
|
||||
// `local:`/`local:oauth:` namespace. See migrations/*_account_issuer for the backfill.
|
||||
issuer: pg.text("issuer").notNull(),
|
||||
userId: pg
|
||||
.text("user_id")
|
||||
.notNull()
|
||||
@@ -100,7 +104,7 @@ export const account = pg.pgTable(
|
||||
.defaultNow()
|
||||
.$onUpdate(() => /* @__PURE__ */ new Date()),
|
||||
},
|
||||
(t) => [pg.index().on(t.userId)],
|
||||
(t) => [pg.index().on(t.userId), pg.uniqueIndex("account_issuer_account_id_unique_idx").on(t.issuer, t.accountId)],
|
||||
);
|
||||
|
||||
export const verification = pg.pgTable(
|
||||
@@ -236,6 +240,11 @@ export const jwks = pg.pgTable("jwks", {
|
||||
privateKey: pg.text("private_key").notNull(),
|
||||
createdAt: pg.timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
||||
expiresAt: pg.timestamp("expires_at", { withTimezone: true }),
|
||||
// Better Auth 1.7 added `alg` and `crv` to the jwt plugin's jwks model. Both are optional to
|
||||
// the plugin, but the Drizzle adapter rejects a model whose columns it cannot find, so every
|
||||
// session verification throws until they exist. Existing rows keep NULL and stay valid.
|
||||
alg: pg.text("alg"),
|
||||
crv: pg.text("crv"),
|
||||
});
|
||||
|
||||
export const oauthClient = pg.pgTable(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { fileURLToPath } from "node:url";
|
||||
// @boundaries-ignore root shared Vitest config
|
||||
import { createVitestProjectConfig } from "../../vitest.shared";
|
||||
import { createVitestProjectConfig } from "../../vitest.shared.mts";
|
||||
|
||||
export default createVitestProjectConfig({
|
||||
name: "@reactive-resume/db",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { fileURLToPath } from "node:url";
|
||||
// @boundaries-ignore root shared Vitest config
|
||||
import { createVitestProjectConfig } from "../../vitest.shared";
|
||||
import { createVitestProjectConfig } from "../../vitest.shared.mts";
|
||||
|
||||
export default createVitestProjectConfig({
|
||||
name: "@reactive-resume/docx",
|
||||
|
||||
@@ -57,15 +57,15 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@deepseek-ai/cordis": "^4.0.1",
|
||||
"@deepseek-ai/dsh-mcp-client": "^0.1.0-rc.6",
|
||||
"@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6",
|
||||
"@deepseek-ai/dsh-mcp-client": "^0.1.0-rc.8",
|
||||
"@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.8",
|
||||
"@deepseek-ai/schemastery": "^3.18.1",
|
||||
"@reactive-resume/config": "workspace:*",
|
||||
"@reactive-resume/mcp": "workspace:*",
|
||||
"@typescript/native-preview": "7.0.0-dev.20260707.2",
|
||||
"tsdown": "^0.22.0",
|
||||
"tsdown": "^0.22.14",
|
||||
"typescript": "^7.0.2",
|
||||
"vitest": "^4.1.10"
|
||||
"vitest": "^4.1.11"
|
||||
},
|
||||
"dsh": {
|
||||
"bundle": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { fileURLToPath } from "node:url";
|
||||
// @boundaries-ignore root shared Vitest config
|
||||
import { createVitestProjectConfig } from "../../vitest.shared";
|
||||
import { createVitestProjectConfig } from "../../vitest.shared.mts";
|
||||
|
||||
export default createVitestProjectConfig({
|
||||
name: "dsh-plugin-reactive-resume",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { fileURLToPath } from "node:url";
|
||||
// @boundaries-ignore root shared Vitest config
|
||||
import { createVitestProjectConfig } from "../../vitest.shared";
|
||||
import { createVitestProjectConfig } from "../../vitest.shared.mts";
|
||||
|
||||
export default createVitestProjectConfig({
|
||||
name: "@reactive-resume/email",
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { fileURLToPath } from "node:url";
|
||||
// @boundaries-ignore root shared Vitest config
|
||||
import { createVitestProjectConfig } from "../../vitest.shared";
|
||||
import { createVitestProjectConfig } from "../../vitest.shared.mts";
|
||||
|
||||
export default createVitestProjectConfig({
|
||||
name: "@reactive-resume/env",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { fileURLToPath } from "node:url";
|
||||
// @boundaries-ignore root shared Vitest config
|
||||
import { createVitestProjectConfig } from "../../vitest.shared";
|
||||
import { createVitestProjectConfig } from "../../vitest.shared.mts";
|
||||
|
||||
export default createVitestProjectConfig({
|
||||
name: "@reactive-resume/fonts",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { fileURLToPath } from "node:url";
|
||||
// @boundaries-ignore root shared Vitest config
|
||||
import { createVitestProjectConfig } from "../../vitest.shared";
|
||||
import { createVitestProjectConfig } from "../../vitest.shared.mts";
|
||||
|
||||
export default createVitestProjectConfig({
|
||||
name: "@reactive-resume/import",
|
||||
|
||||
@@ -29,6 +29,6 @@
|
||||
"@reactive-resume/config": "workspace:*",
|
||||
"@typescript/native-preview": "7.0.0-dev.20260707.2",
|
||||
"typescript": "^7.0.2",
|
||||
"vitest": "^4.1.10"
|
||||
"vitest": "^4.1.11"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { fileURLToPath } from "node:url";
|
||||
// @boundaries-ignore root shared Vitest config
|
||||
import { createVitestProjectConfig } from "../../vitest.shared";
|
||||
import { createVitestProjectConfig } from "../../vitest.shared.mts";
|
||||
|
||||
export default createVitestProjectConfig({
|
||||
name: "@reactive-resume/mcp",
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
"test:agent": "vitest run --reporter=agent --reporter=json --outputFile.json=reports/vitest-results.json --passWithNoTests"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-pdf/renderer": "^4.6.1",
|
||||
"@react-pdf/renderer": "^4.8.1",
|
||||
"@reactive-resume/fonts": "workspace:*",
|
||||
"@reactive-resume/resume": "workspace:*",
|
||||
"@reactive-resume/schema": "workspace:*",
|
||||
@@ -36,8 +36,8 @@
|
||||
"react-pdf-html": "^2.1.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@napi-rs/canvas": "1.0.6",
|
||||
"@react-pdf/types": "^2.11.3",
|
||||
"@napi-rs/canvas": "1.0.8",
|
||||
"@react-pdf/types": "^2.13.1",
|
||||
"@reactive-resume/config": "workspace:*",
|
||||
"@types/react": "^19.2.18",
|
||||
"@typescript/native-preview": "7.0.0-dev.20260707.2",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { fileURLToPath } from "node:url";
|
||||
// @boundaries-ignore root shared Vitest config
|
||||
import { createVitestProjectConfig } from "../../vitest.shared";
|
||||
import { createVitestProjectConfig } from "../../vitest.shared.mts";
|
||||
|
||||
const config = createVitestProjectConfig({
|
||||
name: "@reactive-resume/pdf",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { fileURLToPath } from "node:url";
|
||||
// @boundaries-ignore root shared Vitest config
|
||||
import { createVitestProjectConfig } from "../../vitest.shared";
|
||||
import { createVitestProjectConfig } from "../../vitest.shared.mts";
|
||||
|
||||
export default createVitestProjectConfig({
|
||||
name: "@reactive-resume/resume",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { fileURLToPath } from "node:url";
|
||||
// @boundaries-ignore root shared Vitest config
|
||||
import { createVitestProjectConfig } from "../../vitest.shared";
|
||||
import { createVitestProjectConfig } from "../../vitest.shared.mts";
|
||||
|
||||
export default createVitestProjectConfig({
|
||||
name: "@reactive-resume/schema",
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
"react": "^19.2.8",
|
||||
"react-dom": "^19.2.8",
|
||||
"react-resizable-panels": "^4.12.3",
|
||||
"shadcn": "^4.18.0",
|
||||
"shadcn": "^4.19.0",
|
||||
"tw-animate-css": "^1.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -37,7 +37,7 @@
|
||||
"@tailwindcss/postcss": "^4.3.3",
|
||||
"@tailwindcss/typography": "^0.5.20",
|
||||
"@types/react": "^19.2.18",
|
||||
"@types/react-dom": "^19.2.4",
|
||||
"@types/react-dom": "^19.2.5",
|
||||
"@typescript/native-preview": "7.0.0-dev.20260707.2",
|
||||
"postcss": "^8.5.26",
|
||||
"tailwindcss": "^4.3.3",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { fileURLToPath } from "node:url";
|
||||
// @boundaries-ignore root shared Vitest config
|
||||
import { createVitestProjectConfig } from "../../vitest.shared";
|
||||
import { createVitestProjectConfig } from "../../vitest.shared.mts";
|
||||
|
||||
export default createVitestProjectConfig({
|
||||
name: "@reactive-resume/ui",
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"clsx": "^2.1.1",
|
||||
"tailwind-merge": "^3.6.0",
|
||||
"unique-names-generator": "^4.7.1",
|
||||
"uuid": "^14.0.1",
|
||||
"uuid": "^14.0.2",
|
||||
"zod": "^4.4.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { fileURLToPath } from "node:url";
|
||||
// @boundaries-ignore root shared Vitest config
|
||||
import { createVitestProjectConfig } from "../../vitest.shared";
|
||||
import { createVitestProjectConfig } from "../../vitest.shared.mts";
|
||||
|
||||
export default createVitestProjectConfig({
|
||||
name: "@reactive-resume/utils",
|
||||
|
||||
Reference in New Issue
Block a user