Skip to content

Commit 58f32b2

Browse files
Add desktop Vite, ESLint, and TypeScript configuration
1 parent 582ebd1 commit 58f32b2

7 files changed

Lines changed: 329 additions & 0 deletions

File tree

apps/desktop/eslint.config.mjs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import blitzPlugin from '@blitz/eslint-plugin';
2+
import { jsFileExtensions } from '@blitz/eslint-plugin/dist/configs/javascript.js';
3+
import { getNamingConventionRule, tsFileExtensions } from '@blitz/eslint-plugin/dist/configs/typescript.js';
4+
5+
export default [
6+
{
7+
ignores: ['**/dist', '**/node_modules', '**/.wrangler', '**/codinit/build', '**/.history'],
8+
},
9+
...blitzPlugin.configs.recommended(),
10+
{
11+
rules: {
12+
'@blitz/catch-error-name': 'off',
13+
'@typescript-eslint/no-this-alias': 'off',
14+
'@typescript-eslint/no-empty-object-type': 'off',
15+
'@blitz/comment-syntax': 'off',
16+
'@blitz/block-scope-case': 'off',
17+
'array-bracket-spacing': ['error', 'never'],
18+
'object-curly-newline': ['error', { consistent: true }],
19+
'keyword-spacing': ['error', { before: true, after: true }],
20+
'consistent-return': 'error',
21+
semi: ['error', 'always'],
22+
curly: ['error'],
23+
'no-eval': ['error'],
24+
'linebreak-style': ['error', 'unix'],
25+
'arrow-spacing': ['error', { before: true, after: true }],
26+
},
27+
},
28+
{
29+
files: ['**/*.tsx'],
30+
rules: {
31+
...getNamingConventionRule({}, true),
32+
},
33+
},
34+
{
35+
files: ['**/*.d.ts'],
36+
rules: {
37+
'@typescript-eslint/no-empty-object-type': 'off',
38+
},
39+
},
40+
{
41+
files: [...tsFileExtensions, ...jsFileExtensions, '**/*.tsx'],
42+
ignores: ['functions/*', 'electron/**/*'],
43+
rules: {
44+
'no-restricted-imports': [
45+
'error',
46+
{
47+
patterns: [
48+
{
49+
group: ['../'],
50+
message: "Relative imports are not allowed. Please use '~/' instead.",
51+
},
52+
],
53+
},
54+
],
55+
},
56+
},
57+
];

apps/desktop/load-context.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { type PlatformProxy } from 'wrangler';
2+
3+
type Cloudflare = Omit<PlatformProxy<Env>, 'dispose'>;
4+
5+
declare module '@remix-run/cloudflare' {
6+
interface AppLoadContext {
7+
cloudflare: Cloudflare;
8+
}
9+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// @ts-ignore - Playwright is only installed for testing environments
2+
import { defineConfig, devices } from '@playwright/test';
3+
4+
/**
5+
* Playwright configuration for preview environment testing
6+
* Used by the preview deployment workflow for smoke tests
7+
*/
8+
export default defineConfig({
9+
testDir: './tests/preview',
10+
fullyParallel: true,
11+
forbidOnly: !!process.env.CI,
12+
retries: process.env.CI ? 2 : 0,
13+
workers: process.env.CI ? 1 : undefined,
14+
reporter: 'html',
15+
16+
use: {
17+
baseURL: process.env.PREVIEW_URL || 'http://localhost:5173',
18+
trace: 'on-first-retry',
19+
video: 'retain-on-failure',
20+
screenshot: 'only-on-failure',
21+
},
22+
23+
projects: [
24+
{
25+
name: 'chromium',
26+
use: { ...devices['Desktop Chrome'] },
27+
},
28+
],
29+
30+
webServer: process.env.CI
31+
? undefined
32+
: {
33+
command: 'pnpm run start',
34+
port: 5173,
35+
reuseExistingServer: !process.env.CI,
36+
},
37+
});
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { defineConfig } from 'vite';
2+
import { vitePlugin as remixVitePlugin } from '@remix-run/dev';
3+
import UnoCSS from 'unocss/vite';
4+
import { nodePolyfills } from 'vite-plugin-node-polyfills';
5+
import { optimizeCssModules } from 'vite-plugin-optimize-css-modules';
6+
import tsconfigPaths from 'vite-tsconfig-paths';
7+
8+
import { execSync } from 'child_process';
9+
10+
// Get git hash with fallback
11+
const getGitHash = () => {
12+
try {
13+
return execSync('git rev-parse --short HEAD').toString().trim();
14+
} catch {
15+
return 'no-git-info';
16+
}
17+
};
18+
19+
export default defineConfig((config) => {
20+
return {
21+
define: {
22+
__COMMIT_HASH: JSON.stringify(getGitHash()),
23+
__APP_VERSION: JSON.stringify(process.env.npm_package_version),
24+
},
25+
build: {
26+
target: 'esnext',
27+
},
28+
plugins: [
29+
nodePolyfills({
30+
include: ['path', 'buffer', 'process'],
31+
}),
32+
remixVitePlugin({
33+
future: {
34+
v3_fetcherPersist: true,
35+
v3_relativeSplatPath: true,
36+
v3_throwAbortReason: true,
37+
v3_lazyRouteDiscovery: true,
38+
},
39+
serverModuleFormat: 'esm',
40+
}),
41+
UnoCSS(),
42+
tsconfigPaths(),
43+
config.mode === 'production' && optimizeCssModules({ apply: 'build' }),
44+
{
45+
name: 'replaceReactDomServerImport',
46+
enforce: 'pre',
47+
transform(code, id) {
48+
if (id.endsWith('entry.server.tsx')) {
49+
/*
50+
* Hack: fix the issue with react-dom/server not being found in electron
51+
* Replace the import from 'react-dom/server' with 'react-dom/server.browser', only for electron build
52+
*/
53+
return code.replace(/from 'react-dom\/server';?/g, "from 'react-dom/server.browser';");
54+
}
55+
56+
return undefined;
57+
},
58+
},
59+
],
60+
envPrefix: [
61+
'VITE_',
62+
'OPENAI_LIKE_API_BASE_URL',
63+
'OPENAI_LIKE_API_MODELS',
64+
'OLLAMA_API_BASE_URL',
65+
'LMSTUDIO_API_BASE_URL',
66+
'TOGETHER_API_BASE_URL',
67+
],
68+
css: {
69+
preprocessorOptions: {
70+
scss: {
71+
api: 'modern-compiler',
72+
},
73+
},
74+
},
75+
};
76+
});

apps/desktop/vite.config.ts

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import { cloudflareDevProxyVitePlugin as remixCloudflareDevProxy, vitePlugin as remixVitePlugin } from '@remix-run/dev';
2+
import UnoCSS from 'unocss/vite';
3+
import { defineConfig, type ViteDevServer } from 'vite';
4+
import { nodePolyfills } from 'vite-plugin-node-polyfills';
5+
import { optimizeCssModules } from 'vite-plugin-optimize-css-modules';
6+
import tsconfigPaths from 'vite-tsconfig-paths';
7+
import * as dotenv from 'dotenv';
8+
9+
// Load environment variables from multiple files
10+
dotenv.config({ path: '.env.local' });
11+
dotenv.config({ path: '.env' });
12+
dotenv.config();
13+
14+
export default defineConfig((config) => {
15+
return {
16+
define: {
17+
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
18+
},
19+
build: {
20+
target: 'esnext',
21+
rollupOptions: {
22+
onwarn(warning, warn) {
23+
// Suppress warnings about mixed static/dynamic imports
24+
if (warning.code === 'MODULE_LEVEL_DIRECTIVE' ||
25+
(warning.message && warning.message.includes('is dynamically imported by') && warning.message.includes('but also statically imported by'))) {
26+
return;
27+
}
28+
warn(warning);
29+
},
30+
},
31+
},
32+
plugins: [
33+
nodePolyfills({
34+
include: ['buffer', 'process', 'util', 'stream', 'path'],
35+
globals: {
36+
Buffer: true,
37+
process: true,
38+
global: true,
39+
},
40+
protocolImports: true,
41+
exclude: ['child_process', 'fs'],
42+
}),
43+
{
44+
name: 'buffer-polyfill',
45+
transform(code, id) {
46+
if (id.includes('env.mjs')) {
47+
return {
48+
code: `import { Buffer } from 'buffer';\n${code}`,
49+
map: null,
50+
};
51+
}
52+
53+
return null;
54+
},
55+
},
56+
config.mode !== 'test' && remixCloudflareDevProxy(),
57+
remixVitePlugin({
58+
future: {
59+
v3_fetcherPersist: true,
60+
v3_relativeSplatPath: true,
61+
v3_throwAbortReason: true,
62+
v3_lazyRouteDiscovery: true,
63+
},
64+
}),
65+
UnoCSS(),
66+
tsconfigPaths(),
67+
chrome129IssuePlugin(),
68+
config.mode === 'production' && optimizeCssModules({ apply: 'build' }),
69+
],
70+
envPrefix: [
71+
'VITE_',
72+
'OPENAI_LIKE_API_BASE_URL',
73+
'OPENAI_LIKE_API_MODELS',
74+
'OLLAMA_API_BASE_URL',
75+
'LMSTUDIO_API_BASE_URL',
76+
'TOGETHER_API_BASE_URL',
77+
],
78+
css: {
79+
preprocessorOptions: {
80+
scss: {
81+
api: 'modern-compiler',
82+
},
83+
},
84+
},
85+
test: {
86+
exclude: [
87+
'**/node_modules/**',
88+
'**/dist/**',
89+
'**/cypress/**',
90+
'**/.{idea,git,cache,output,temp}/**',
91+
'**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build}.config.*',
92+
'**/tests/preview/**', // Exclude preview tests that require Playwright
93+
],
94+
},
95+
};
96+
});
97+
98+
function chrome129IssuePlugin() {
99+
return {
100+
name: 'chrome129IssuePlugin',
101+
configureServer(server: ViteDevServer) {
102+
server.middlewares.use((req, res, next) => {
103+
const raw = req.headers['user-agent']?.match(/Chrom(e|ium)\/([0-9]+)\./);
104+
105+
if (raw) {
106+
const version = parseInt(raw[2], 10);
107+
108+
if (version === 129) {
109+
res.setHeader('content-type', 'text/html');
110+
res.end(
111+
'<body><h1>Please use Chrome Canary for testing.</h1><p>Chrome 129 has an issue with JavaScript modules & Vite local development, see <a href="https://github.com/stackblitz/bolt.new/issues/86#issuecomment-2395519258">for more information.</a></p><p><b>Note:</b> This only impacts <u>local development</u>. `pnpm run build` and `pnpm run start` will work fine in this browser.</p></body>',
112+
);
113+
114+
return;
115+
}
116+
}
117+
118+
next();
119+
});
120+
},
121+
};
122+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
interface Env {
2+
RUNNING_IN_DOCKER: Settings;
3+
DEFAULT_NUM_CTX: Settings;
4+
ANTHROPIC_API_KEY: string;
5+
OPENAI_API_KEY: string;
6+
GROQ_API_KEY: string;
7+
HuggingFace_API_KEY: string;
8+
OPEN_ROUTER_API_KEY: string;
9+
OLLAMA_API_BASE_URL: string;
10+
OPENAI_LIKE_API_KEY: string;
11+
OPENAI_LIKE_API_BASE_URL: string;
12+
OPENAI_LIKE_API_MODELS: string;
13+
TOGETHER_API_KEY: string;
14+
TOGETHER_API_BASE_URL: string;
15+
DEEPSEEK_API_KEY: string;
16+
LMSTUDIO_API_BASE_URL: string;
17+
GOOGLE_GENERATIVE_AI_API_KEY: string;
18+
MISTRAL_API_KEY: string;
19+
XAI_API_KEY: string;
20+
PERPLEXITY_API_KEY: string;
21+
AWS_BEDROCK_CONFIG: string;
22+
}

apps/desktop/wrangler.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#:schema node_modules/wrangler/config-schema.json
2+
name = "codinit"
3+
compatibility_flags = ["nodejs_compat"]
4+
compatibility_date = "2025-03-28"
5+
pages_build_output_dir = "./build/client"
6+
send_metrics = false

0 commit comments

Comments
 (0)