Skip to content

Commit c266b45

Browse files
author
teable-bot
committed
[sync] Merge pull request #1077 from teableio/fix/T1720-ai-field-prompt-editor-resize
Synced from teableio/teable-ee@2f9c9c1
1 parent afb5f32 commit c266b45

File tree

47 files changed

+2860
-1174
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+2860
-1174
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ node_modules
2929
/build
3030
/dist/
3131

32+
# Next.js auto-generated type definitions
33+
**/next-env.d.ts
34+
3235
# Cache
3336
*.tsbuildinfo
3437
**/.eslintcache

apps/nestjs-backend/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@
9898
"dotenv-flow-cli": "1.1.1",
9999
"es-check": "7.1.1",
100100
"eslint": "8.57.0",
101-
"eslint-config-next": "14.2.14",
101+
"eslint-config-next": "15.5.9",
102102
"get-tsconfig": "4.7.3",
103103
"istanbul-merge": "2.0.0",
104104
"npm-run-all2": "6.1.2",
@@ -213,7 +213,7 @@
213213
"nestjs-i18n": "10.5.1",
214214
"nestjs-pino": "4.4.1",
215215
"nestjs-redoc": "2.2.2",
216-
"next": "14.2.35",
216+
"next": "16.1.3",
217217
"node-fetch": "2.7.0",
218218
"node-sql-parser": "5.3.8",
219219
"nodemailer": "6.9.13",

apps/nestjs-backend/src/features/next/next.service.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,13 @@ import { ConfigService } from '@nestjs/config';
44
import { generateQueryId } from '@teable/core';
55
import type { IQueryParamsRo, IQueryParamsVo } from '@teable/openapi';
66
import createServer from 'next';
7-
import type { NextServer } from 'next/dist/server/next';
87
import { CacheService } from '../../cache/cache.service';
98
import type { ICacheStore } from '../../cache/types';
109

1110
@Injectable()
1211
export class NextService implements OnModuleInit, OnModuleDestroy {
1312
private logger = new Logger(NextService.name);
14-
public server!: NextServer;
13+
public server!: ReturnType<typeof createServer>;
1514
constructor(
1615
private configService: ConfigService,
1716
private readonly cacheService: CacheService<ICacheStore>

apps/nestjs-backend/src/index.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,23 @@ async function main() {
1414

1515
main();
1616

17+
// Force exit after timeout if app.close() hangs during development
18+
// enableShutdownHooks() in bootstrap.ts handles graceful shutdown,
19+
// but some modules may not release resources properly
1720
if (module.hot) {
21+
const forceExitTimeout = 5000; // 5 seconds
22+
23+
const forceExit = (signal: string) => {
24+
console.log(`Received ${signal}, forcing exit in ${forceExitTimeout}ms if not closed...`);
25+
setTimeout(() => {
26+
console.log('Force exiting due to timeout...');
27+
process.exit(0);
28+
}, forceExitTimeout).unref();
29+
};
30+
31+
process.on('SIGINT', () => forceExit('SIGINT'));
32+
process.on('SIGTERM', () => forceExit('SIGTERM'));
33+
1834
module.hot.accept((err: Error) => {
1935
if (err) {
2036
console.error('[HMR] Update failed, restarting...', err);

apps/nestjs-backend/test/base-export-sentry.e2e-spec.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,9 @@ describe('Base export sentry reporting (e2e)', () => {
4444

4545
it('captures export failures in sentry even when running asynchronously', async () => {
4646
const exportError = new Error('mock export failure');
47-
type ExportServiceTestTarget = BaseExportService & {
48-
captureExportError: (err: unknown, context: Record<string, unknown>) => void;
49-
processExportBaseZip: (...args: unknown[]) => Promise<unknown>;
50-
notifyExportResult: (...args: unknown[]) => Promise<unknown>;
51-
};
52-
const exportService = baseExportService as ExportServiceTestTarget;
47+
// Cast to `any` to access private methods for testing purposes
48+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
49+
const exportService = baseExportService as any;
5350

5451
const captureErrorSpy = vi.spyOn(exportService, 'captureExportError');
5552
const processSpy = vi

apps/nextjs-app/next-env.d.ts

Lines changed: 0 additions & 5 deletions
This file was deleted.

apps/nextjs-app/next.config.js

Lines changed: 67 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
// @ts-check
22

3-
const { readFileSync } = require('node:fs');
4-
const path = require('node:path');
3+
const { readFileSync } = require('fs');
4+
const path = require('path');
55
const { createSecureHeaders } = require('next-secure-headers');
66
const pc = require('picocolors');
77

8-
const workspaceRoot = path.resolve(__dirname, '..', '..');
8+
const workspaceRoot = path.resolve(__dirname, '..', '..', '..');
99
/**
1010
* Once supported replace by node / eslint / ts and out of experimental, replace by
1111
* `import packageJson from './package.json' assert { type: 'json' };`
@@ -122,7 +122,18 @@ const nextConfig = {
122122
: '',
123123
reactStrictMode: true,
124124
productionBrowserSourceMaps: NEXT_BUILD_ENV_SOURCEMAPS === true,
125-
optimizeFonts: true,
125+
// optimizeFonts is enabled by default in Next.js 16
126+
127+
// Transpile packages that use React to ensure single React instance
128+
transpilePackages: [
129+
'streamdown',
130+
'd3-interpolate',
131+
'd3-color',
132+
// Fix Turbopack "unexpected export *" warnings for CommonJS modules
133+
'@dnd-kit/core',
134+
'@dnd-kit/sortable',
135+
'@dnd-kit/utilities',
136+
],
126137

127138
httpAgentOptions: {
128139
// @link https://nextjs.org/blog/next-11-1#builds--data-fetching
@@ -136,20 +147,14 @@ const nextConfig = {
136147

137148
// @link https://nextjs.org/docs/advanced-features/compiler#minification
138149
// @link discussion: https://github.com/vercel/next.js/discussions/30237
139-
// Sometimes buggy so enable/disable when debugging.
140-
swcMinify: true,
150+
// swcMinify is enabled by default in Next.js 15+
141151

142152
compiler: {
143153
// emotion: true,
144154
},
145155

146-
sentry: {
147-
hideSourceMaps: true,
148-
// To disable the automatic instrumentation of API route handlers and server-side data fetching functions
149-
// In other words, disable if you prefer to explicitly handle sentry per api routes (ie: wrapApiHandlerWithSentry)
150-
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/#configure-server-side-auto-instrumentation
151-
autoInstrumentServerFunctions: false,
152-
},
156+
// Note: sentry configuration moved to withSentryConfig wrapper
157+
// See: https://docs.sentry.io/platforms/javascript/guides/nextjs/
153158

154159
// @link https://nextjs.org/docs/basic-features/image-optimization
155160
images: {
@@ -187,6 +192,10 @@ const nextConfig = {
187192
? { output: 'standalone', outputFileTracing: true }
188193
: {}),
189194

195+
// Server-only packages that should not be bundled for the browser
196+
// @link https://nextjs.org/docs/app/api-reference/config/next-config-js/serverExternalPackages
197+
serverExternalPackages: ['next-i18next', 'i18next-fs-backend'],
198+
190199
experimental: {
191200
// @link https://nextjs.org/docs/advanced-features/output-file-tracing#caveats
192201
...(NEXT_BUILD_ENV_OUTPUT === 'standalone' ? { outputFileTracingRoot: workspaceRoot } : {}),
@@ -204,15 +213,29 @@ const nextConfig = {
204213
// appDir: true,
205214
},
206215

216+
// Turbopack configuration (Next.js 16 default bundler)
217+
turbopack: {
218+
// Set workspace root to fix multiple lockfile detection
219+
root: workspaceRoot,
220+
rules: {
221+
'*.svg': {
222+
loaders: ['@svgr/webpack'],
223+
as: '*.js',
224+
},
225+
},
226+
resolveAlias: {
227+
// Required: next-i18next and i18next-fs-backend require 'fs' at top level
228+
fs: './turbopack-empty-stub.js',
229+
},
230+
},
231+
207232
typescript: {
208233
ignoreBuildErrors: !NEXT_BUILD_ENV_TYPECHECK,
209234
tsconfigPath: NEXT_BUILD_ENV_TSCONFIG,
210235
},
211236

212-
eslint: {
213-
ignoreDuringBuilds: !NEXT_BUILD_ENV_LINT,
214-
// dirs: [`${__dirname}/src`],
215-
},
237+
// Note: eslint configuration is no longer supported in next.config.js
238+
// Use ESLint CLI directly: npx eslint .
216239

217240
// @link https://nextjs.org/docs/api-reference/next.config.js/rewrites
218241
async rewrites() {
@@ -266,6 +289,21 @@ const nextConfig = {
266289
config.resolve.fallback = { ...config.resolve.fallback, fs: false };
267290
}
268291

292+
// Handle node: protocol imports for server-side (e.g., node:fs from i18next-fs-backend)
293+
// This tells webpack to treat node: protocol imports as external commonjs modules
294+
if (isServer) {
295+
config.externals = config.externals || [];
296+
config.externals.push(
297+
(/** @type {{ request: string }} */ { request }, /** @type {Function} */ callback) => {
298+
if (request.startsWith('node:')) {
299+
// Convert node:fs -> fs, node:path -> path, etc.
300+
return callback(null, 'commonjs ' + request.slice(5));
301+
}
302+
callback();
303+
}
304+
);
305+
}
306+
269307
// https://docs.sentry.io/platforms/javascript/guides/nextjs/configuration/tree-shaking/
270308
config.plugins.push(
271309
new webpack.DefinePlugin({
@@ -304,6 +342,8 @@ const nextConfig = {
304342
APP_NAME: packageJson.name ?? 'not-in-package.json',
305343
APP_VERSION: packageJson.version ?? 'not-in-package.json',
306344
BUILD_TIME: new Date().toISOString(),
345+
// Note: Sentry debug/tracing variables are handled via webpack DefinePlugin
346+
// and cannot be set via Next.js env config (reserved key format)
307347
},
308348
};
309349

@@ -313,26 +353,22 @@ if (NEXT_BUILD_ENV_SENTRY_ENABLED === true) {
313353
try {
314354
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
315355
const { withSentryConfig } = require('@sentry/nextjs');
316-
// @ts-ignore because sentry does not match nextjs current definitions
317356
config = withSentryConfig(config, {
318-
// Additional config options for the Sentry Webpack plugin. Keep in mind that
319-
// the following options are set automatically, and overriding them is not
320-
// recommended:
321-
// release, url, org, project, authToken, configFile, stripPrefix,
322-
// urlPrefix, include, ignore
323-
// For all available options, see:
324-
// https://github.com/getsentry/sentry-webpack-plugin#options.
325-
// silent: isProd, // Suppresses all logs
326-
dryRun: NEXT_BUILD_ENV_SENTRY_UPLOAD_DRY_RUN === true,
327-
silent: NEXT_BUILD_ENV_SENTRY_DEBUG === false,
357+
// Sentry 10.x options
358+
// https://docs.sentry.io/platforms/javascript/guides/nextjs/configuration/build/
359+
bundleSizeOptimizations: {
360+
excludeDebugStatements: !NEXT_BUILD_ENV_SENTRY_DEBUG,
361+
excludeTracing: !NEXT_BUILD_ENV_SENTRY_TRACING,
362+
},
363+
sourcemaps: {
364+
disable: NEXT_BUILD_ENV_SENTRY_UPLOAD_DRY_RUN,
365+
},
366+
silent: !NEXT_BUILD_ENV_SENTRY_DEBUG,
328367
});
329368
console.log(`- ${pc.green('info')} Sentry enabled for this build`);
330369
} catch {
331370
console.log(`- ${pc.red('error')} Could not enable sentry, import failed`);
332371
}
333-
} else {
334-
const { sentry, ...rest } = config;
335-
config = rest;
336372
}
337373

338374
if (tmModules.length > 0) {

apps/nextjs-app/package.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@
4444
"flamegraph-home": "npx 0x --output-dir './.debug/flamegraph/{pid}.0x' --on-port 'autocannon http://localhost:$PORT --duration 20' -- node ../../node_modules/.bin/next start"
4545
},
4646
"devDependencies": {
47-
"@next/bundle-analyzer": "14.2.14",
48-
"@next/env": "14.2.14",
47+
"@next/bundle-analyzer": "16.1.1",
48+
"@next/env": "16.1.1",
4949
"@playwright/test": "1.42.1",
5050
"@size-limit/file": "11.1.2",
5151
"@svgr/webpack": "8.1.0",
@@ -59,11 +59,11 @@
5959
"@types/lodash": "4.17.0",
6060
"@types/node": "22.18.0",
6161
"@types/nprogress": "0.2.3",
62-
"@types/react": "18.2.69",
63-
"@types/react-dom": "18.2.22",
62+
"@types/react": "18.3.18",
63+
"@types/react-dom": "18.3.5",
6464
"@types/react-grid-layout": "1.3.5",
6565
"@types/react-syntax-highlighter": "15.5.11",
66-
"@types/react-test-renderer": "18.0.7",
66+
"@types/react-test-renderer": "18.3.1",
6767
"@types/sharedb": "3.3.10",
6868
"@types/streamsaver": "2.0.5",
6969
"@vitejs/plugin-react-swc": "3.6.0",
@@ -74,7 +74,7 @@
7474
"dotenv-flow-cli": "1.1.1",
7575
"es-check": "7.1.1",
7676
"eslint": "8.57.0",
77-
"eslint-config-next": "14.2.14",
77+
"eslint-config-next": "15.5.9",
7878
"get-tsconfig": "4.7.3",
7979
"happy-dom": "15.11.6",
8080
"npm-run-all2": "6.1.2",
@@ -118,8 +118,8 @@
118118
"@hookform/resolvers": "3.3.4",
119119
"@nem035/gpt-3-encoder": "1.1.7",
120120
"@radix-ui/react-icons": "1.3.0",
121-
"@sentry/nextjs": "7.108.0",
122-
"@sentry/react": "7.108.0",
121+
"@sentry/nextjs": "10.33.0",
122+
"@sentry/react": "10.33.0",
123123
"@tailwindcss/container-queries": "0.1.1",
124124
"@tanstack/react-query": "5.90.16",
125125
"@tanstack/react-table": "8.11.7",
@@ -153,7 +153,7 @@
153153
"lodash": "4.17.21",
154154
"lru-cache": "10.2.0",
155155
"lucide-react": "0.363.0",
156-
"next": "14.2.35",
156+
"next": "16.1.3",
157157
"next-i18next": "15.2.0",
158158
"next-secure-headers": "2.2.0",
159159
"next-seo": "6.5.0",

apps/nextjs-app/src/features/app/automation/workflow-panel/WorkFlowPanel.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { forwardRef, useImperativeHandle } from 'react';
22
import { AutomationPage } from '../Pages';
33

4-
interface WorkFlowPanelRef {
4+
export interface WorkFlowPanelRef {
55
getWorkflow?: () => unknown | undefined;
66
checkCanActive?: () => {
77
canActive: boolean;

apps/nextjs-app/src/features/app/automation/workflow-panel/WorkFlowPanelModal.tsx

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@ import { XIcon } from 'lucide-react';
1717
import { forwardRef, lazy, Suspense, useImperativeHandle, useRef, useState } from 'react';
1818
import { useTranslation } from 'react-i18next';
1919
import { tableConfig } from '@/features/i18n/table.config';
20+
import type { WorkFlowPanelRef } from '@overridable/WorkFlowPanel';
2021
import { useWorkFlowPanelStore } from './useWorkFlowPaneStore';
2122

2223
const WorkFlowPanelLazy = lazy(() =>
23-
import('./WorkFlowPanel').then((module) => ({
24+
import('@overridable/WorkFlowPanel').then((module) => ({
2425
default: module.WorkFlowPanel,
2526
}))
2627
);
@@ -71,15 +72,6 @@ const AlertCloseWorkflowDialog = forwardRef<AlertCloseDialogRef, AlertCloseDialo
7172

7273
AlertCloseWorkflowDialog.displayName = 'AlertCloseWorkflowDialog';
7374

74-
interface WorkFlowPanelRef {
75-
getWorkflow?: () => unknown | undefined;
76-
checkCanActive?: () => {
77-
canActive: boolean;
78-
message: string;
79-
};
80-
activeWorkflow?: () => Promise<void>;
81-
}
82-
8375
export const WorkFlowPanelModal = () => {
8476
const { baseId = '', workflowId = '', closeModal, open } = useWorkFlowPanelStore();
8577
const isHydrated = useIsHydrated();

0 commit comments

Comments
 (0)