Compare commits

..

2 Commits

Author SHA1 Message Date
60422da644 chore(glitchtip): ignore version drift errors like ChunkLoadError globally
All checks were successful
Build & Deploy / 🔍 Prepare (push) Successful in 11s
Build & Deploy / 🧪 QA (push) Successful in 1m11s
Build & Deploy / 🏗️ Build (push) Successful in 2m30s
Build & Deploy / 🚀 Deploy (push) Successful in 16s
Build & Deploy / 🔔 Notify (push) Successful in 2s
Build & Deploy / 🧪 Post-Deploy Verification (push) Successful in 1m26s
2026-07-21 12:23:52 +02:00
fc6da4e9aa fix(mdx): Handle brace counting correctly inside strings for Next-MDX-Remote data props parsing
All checks were successful
Build & Deploy / 🔍 Prepare (push) Successful in 8s
Build & Deploy / 🧪 QA (push) Successful in 1m13s
Build & Deploy / 🏗️ Build (push) Successful in 2m31s
Build & Deploy / 🚀 Deploy (push) Successful in 16s
Build & Deploy / 🔔 Notify (push) Successful in 3s
Build & Deploy / 🧪 Post-Deploy Verification (push) Successful in 1m18s
2026-07-18 09:43:33 +02:00
5 changed files with 89 additions and 10 deletions

View File

@@ -7,14 +7,36 @@ export function fixMdxDataProps(content: string): string {
let endIndex = -1;
const startObj = dataIndex + 6; // index of the first '{' in 'data={{'
let inString = false;
let isEscaped = false;
for (let i = startObj; i < fixedContent.length; i++) {
if (fixedContent[i] === '{') {
openCount++;
} else if (fixedContent[i] === '}') {
openCount--;
if (openCount === 0) {
endIndex = i;
break;
const char = fixedContent[i];
if (isEscaped) {
isEscaped = false;
continue;
}
if (char === '\\') {
isEscaped = true;
continue;
}
if (char === '"') {
inString = !inString;
continue;
}
if (!inString) {
if (char === '{') {
openCount++;
} else if (char === '}') {
openCount--;
if (openCount === 0) {
endIndex = i;
break;
}
}
}
}

View File

@@ -56,6 +56,11 @@ export class GlitchtipErrorReportingService implements ErrorReportingService {
tracesSampleRate: this.options.tracesSampleRate ?? 0.1,
replaysOnErrorSampleRate: 1.0,
replaysSessionSampleRate: 0.1,
ignoreErrors: [
'ChunkLoadError',
'Failed to fetch dynamically imported module',
'Failed to find Server Action',
],
});
}
return Sentry;

View File

@@ -116,7 +116,7 @@
"prepare": "husky",
"preinstall": "npx only-allow pnpm"
},
"version": "2.3.30",
"version": "2.3.32",
"pnpm": {
"onlyBuiltDependencies": [
"@parcel/watcher",

View File

@@ -0,0 +1,47 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { GlitchtipErrorReportingService } from '../lib/services/errors/glitchtip-error-reporting-service';
// Mock the LoggerService
const mockLogger = {
child: vi.fn().mockReturnThis(),
info: vi.fn(),
error: vi.fn(),
warn: vi.fn(),
debug: vi.fn(),
} as any;
const mockSentryInit = vi.fn();
vi.mock('@sentry/nextjs', () => ({
init: (...args: any[]) => mockSentryInit(...args),
captureException: vi.fn(),
captureMessage: vi.fn(),
}));
describe('GlitchtipErrorReportingService', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('should ignore version drift errors (ChunkLoadError and Server Action) in Sentry config', async () => {
// Simulate window to force client-side init behavior instantly
const originalWindow = global.window;
global.window = {
requestIdleCallback: (cb: Function) => cb(),
} as any;
const service = new GlitchtipErrorReportingService({ enabled: true }, mockLogger);
// Give the dynamic import a moment to resolve
await new Promise((resolve) => setTimeout(resolve, 50));
expect(mockSentryInit).toHaveBeenCalledOnce();
const initCallArgs = mockSentryInit.mock.calls[0][0];
expect(initCallArgs.ignoreErrors).toBeDefined();
expect(initCallArgs.ignoreErrors).toContain('ChunkLoadError');
expect(initCallArgs.ignoreErrors).toContain('Failed to find Server Action');
global.window = originalWindow;
});
});

View File

@@ -8,10 +8,15 @@ describe('MDX Data Props Fixer', () => {
const result = fixMdxDataProps(mdxInput);
// The expected output should have the entire JSON object enclosed in data="{...}"
// and NO trailing characters left over from the regex truncating early.
const expected = `<Block type="productTabs" data="{&quot;content&quot;:{&quot;root&quot;:{&quot;children&quot;:[]}},&quot;id&quot;:&quot;123&quot;}" />`;
expect(result).toBe(expected);
});
it('should not prematurely truncate if } appears inside a string literal', () => {
const mdxInput = `<Block type="productTabs" data={{"content":{"text":"}>"}}} />`;
const result = fixMdxDataProps(mdxInput);
const expected = `<Block type="productTabs" data="{&quot;content&quot;:{&quot;text&quot;:&quot;}&gt;&quot;}}" />`;
expect(result).toBe(expected.replace('&gt;', '>'));
});
});