Skip to content

Commit be50c7f

Browse files
Use convex linter in deploy tool
1 parent 19669e3 commit be50c7f

File tree

6 files changed

+46
-13
lines changed

6 files changed

+46
-13
lines changed

app/lib/runtime/action-runner.ts

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -412,17 +412,26 @@ export class ActionRunner {
412412
};
413413

414414
// START deploy tool call
415-
// /
416-
// /
417-
// codegen `convex typecheck` includes typecheck of convex/ dir
418-
// + typecheck
419-
// |
420-
// |
421-
// app typecheck `tsc --noEmit --project tsconfig.app.json
422-
// \
423-
// \
415+
// / \
416+
// / \
417+
// codegen \ `convex typecheck` includes typecheck of convex/ dir
418+
// + typecheck \
419+
// | ESLint `eslint` must not include rules that check imports
420+
// | /
421+
// app typecheck / `tsc --noEmit --project tsconfig.app.json
422+
// \ /
423+
// \ /
424424
// deploy `deploy` can fail
425425

426+
// ESLint doesn't need to wait for codegen since we don't use rules like plugin-import to validate imports.
427+
const runEslint = async () => {
428+
if (await hasMatchingEslintConfig(container)) {
429+
// ESLint results don't stream to the terminal
430+
return await run(['eslint', 'convex'], outputLabels.convexLint);
431+
}
432+
return '';
433+
};
434+
426435
const runCodegenAndTypecheck = async (onOutput?: (output: string) => void) => {
427436
// Convex codegen does a convex directory typecheck, then tsc does a full-project typecheck.
428437
let output = await run(['convex', 'codegen'], outputLabels.convexTypecheck, onOutput);
@@ -435,9 +444,14 @@ export class ActionRunner {
435444
};
436445

437446
const t0 = performance.now();
438-
result += await runCodegenAndTypecheck((output) => {
439-
this.terminalOutput.set(output);
440-
});
447+
const [eslintResult, codegenResult] = await Promise.all([
448+
runEslint(),
449+
runCodegenAndTypecheck((output) => {
450+
this.terminalOutput.set(output);
451+
}),
452+
]);
453+
result += codegenResult;
454+
result += eslintResult;
441455
result += await run(['convex', 'dev', '--once', '--typecheck=disable'], outputLabels.convexDeploy);
442456
const time = performance.now() - t0;
443457
logger.info('deploy action finished in', time);
@@ -513,3 +527,16 @@ function cleanConvexOutput(output: string) {
513527
}
514528
return result;
515529
}
530+
531+
async function hasMatchingEslintConfig(container: WebContainer): Promise<boolean> {
532+
// Only run eslint if the file we expect is present and contains '@convex-dev/eslint-plugin'.
533+
let contents = '';
534+
try {
535+
contents = await container.fs.readFile('eslint.config.js', 'utf-8');
536+
} catch (e: any) {
537+
if (!e.message.includes('ENOENT: no such file or directory')) {
538+
throw e;
539+
}
540+
}
541+
return contents.includes('@convex-dev/eslint-plugin');
542+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
export const outputLabels = {
2+
convexCodegen: 'ConvexCodegen',
23
convexTypecheck: 'ConvexTypecheck',
34
frontendTypecheck: 'FrontendTypecheck',
5+
convexLint: 'ConvexLint',
46
convexDeploy: 'ConvexDeploy',
57
} as const;
68
export type OutputLabels = (typeof outputLabels)[keyof typeof outputLabels];

app/lib/stores/startup/useContainerSetup.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { getFileUpdateCounter } from '~/lib/stores/fileUpdateCounter';
2121
import { chatSyncState } from '~/lib/stores/startup/history';
2222
import { FILE_EVENTS_DEBOUNCE_MS } from '~/lib/stores/files';
2323

24-
const TEMPLATE_URL = '/template-snapshot-80c98556.bin';
24+
const TEMPLATE_URL = '/template-snapshot-86225363.bin';
2525

2626
export function useNewChatContainerSetup() {
2727
const convex = useConvex();
233 KB
Binary file not shown.

template/eslint.config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import globals from "globals";
33
import reactHooks from "eslint-plugin-react-hooks";
44
import reactRefresh from "eslint-plugin-react-refresh";
55
import tseslint from "typescript-eslint";
6+
import convexPlugin from "@convex-dev/eslint-plugin";
67

78
export default tseslint.config(
89
{
@@ -15,6 +16,8 @@ export default tseslint.config(
1516
"vite.config.ts",
1617
],
1718
},
19+
// limited, commonsense Convex function rules
20+
...convexPlugin.configs.recommended,
1821
{
1922
extends: [
2023
js.configs.recommended,

template/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
},
1212
"dependencies": {
1313
"@convex-dev/auth": "^0.0.80",
14+
"@convex-dev/eslint-plugin": "0.0.1-alpha.4",
1415
"clsx": "^2.1.1",
1516
"convex": "1.21.1-alpha.1",
1617
"react": "^19.0.0",

0 commit comments

Comments
 (0)