snapshot of https://github.com/frappe/crm.git (develop, 2026-09-18; blobs > 131072B omitted)
Some checks failed
Frontend / Unit Tests & Coverage (push) Has been skipped
Regenerate POT file (translatable strings) / Regenerate POT file (develop) (push) Failing after 1m13s
Regenerate POT file (translatable strings) / Regenerate POT file (main-hotfix) (push) Failing after 6s
Server / Tests (frappe ${{ matrix.frappe-branch }}) (push) Has been skipped
Server / Resolve frappe matrix (push) Failing after 1s
Frontend / Lint (push) Failing after 1s
Frontend / Production Build (push) Failing after 1s
Server / Coverage Wrap Up (push) Has been skipped
Frontend / Coverage Wrap Up (push) Has been skipped
Some checks failed
Frontend / Unit Tests & Coverage (push) Has been skipped
Regenerate POT file (translatable strings) / Regenerate POT file (develop) (push) Failing after 1m13s
Regenerate POT file (translatable strings) / Regenerate POT file (main-hotfix) (push) Failing after 6s
Server / Tests (frappe ${{ matrix.frappe-branch }}) (push) Has been skipped
Server / Resolve frappe matrix (push) Failing after 1s
Frontend / Lint (push) Failing after 1s
Frontend / Production Build (push) Failing after 1s
Server / Coverage Wrap Up (push) Has been skipped
Frontend / Coverage Wrap Up (push) Has been skipped
This commit is contained in:
195
frontend/vite.config.js
Normal file
195
frontend/vite.config.js
Normal file
@@ -0,0 +1,195 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import vueJsx from '@vitejs/plugin-vue-jsx'
|
||||
import path from 'path'
|
||||
import { VitePWA } from 'vite-plugin-pwa'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig(async ({ mode }) => {
|
||||
const isDev = mode === 'development'
|
||||
const config = {
|
||||
plugins: [
|
||||
vue(),
|
||||
vueJsx(),
|
||||
VitePWA({
|
||||
registerType: 'autoUpdate',
|
||||
workbox: {
|
||||
maximumFileSizeToCacheInBytes: 8 * 1024 * 1024,
|
||||
},
|
||||
devOptions: {
|
||||
enabled: true,
|
||||
},
|
||||
manifest: {
|
||||
display: 'standalone',
|
||||
name: 'Frappe CRM',
|
||||
short_name: 'Frappe CRM',
|
||||
start_url: '/crm',
|
||||
description:
|
||||
'Modern & 100% Open-source CRM tool to supercharge your sales operations',
|
||||
icons: [
|
||||
{
|
||||
src: '/assets/crm/manifest/manifest-icon-192.maskable.png',
|
||||
sizes: '192x192',
|
||||
type: 'image/png',
|
||||
purpose: 'any',
|
||||
},
|
||||
{
|
||||
src: '/assets/crm/manifest/manifest-icon-192.maskable.png',
|
||||
sizes: '192x192',
|
||||
type: 'image/png',
|
||||
purpose: 'maskable',
|
||||
},
|
||||
{
|
||||
src: '/assets/crm/manifest/manifest-icon-512.maskable.png',
|
||||
sizes: '512x512',
|
||||
type: 'image/png',
|
||||
purpose: 'any',
|
||||
},
|
||||
{
|
||||
src: '/assets/crm/manifest/manifest-icon-512.maskable.png',
|
||||
sizes: '512x512',
|
||||
type: 'image/png',
|
||||
purpose: 'maskable',
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': path.resolve(import.meta.dirname, 'src'),
|
||||
// point at the package src dir (not index.ts) so subpath imports like
|
||||
// `@framework/ui/components/Notifications` resolve. Importing subpaths avoids the
|
||||
// barrel, which `export *`s components (Grid/Phone/FormLayout) that need a newer
|
||||
// frappe-ui (`frappe-ui/internals`) than this app pins.
|
||||
'@framework/ui': path.resolve(
|
||||
import.meta.dirname,
|
||||
'../../frappe/ui/src',
|
||||
),
|
||||
},
|
||||
// ensure the linked framework package reuses the host app's single copy of each peer.
|
||||
// `dompurify` is an implicit dep of @framework/ui's sanitize util (not declared in its
|
||||
// package.json); dedupe resolves it to the host's copy since the symlinked source has
|
||||
// no node_modules of its own.
|
||||
// the editor packages must resolve to one copy each: tiptap imports
|
||||
// `@tiptap/pm/model` while prosemirror-state/transform/tables import bare
|
||||
// `prosemirror-model`, so a nested install of either throws "multiple
|
||||
// versions of prosemirror-model were loaded" on mention insert. Unlike
|
||||
// optimizeDeps (dev-only) this also applies to the production build.
|
||||
dedupe: [
|
||||
'vue',
|
||||
'vue-router',
|
||||
'frappe-ui',
|
||||
'dompurify',
|
||||
'@tiptap/core',
|
||||
'@tiptap/pm',
|
||||
'@tiptap/vue-3',
|
||||
'prosemirror-model',
|
||||
'prosemirror-state',
|
||||
'prosemirror-view',
|
||||
'prosemirror-transform',
|
||||
],
|
||||
},
|
||||
optimizeDeps: {
|
||||
include: [
|
||||
'feather-icons',
|
||||
'tailwind.config.js',
|
||||
'prosemirror-state',
|
||||
'prosemirror-view',
|
||||
'lowlight',
|
||||
'interactjs',
|
||||
],
|
||||
},
|
||||
server: {
|
||||
fs: {
|
||||
// allow the bench `apps/` dir so Vite can serve linked local packages
|
||||
// (frappe-ui, @framework/ui) that live in sibling app repos
|
||||
allow: [path.resolve(import.meta.dirname, '../..')],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const frappeui = await importFrappeUIPlugin(isDev, config)
|
||||
config.plugins.unshift(
|
||||
frappeui({
|
||||
frappeProxy: true,
|
||||
lucideIcons: true,
|
||||
jinjaBootData: true,
|
||||
buildConfig: {
|
||||
indexHtmlPath: '../crm/www/crm.html',
|
||||
emptyOutDir: true,
|
||||
sourcemap: true,
|
||||
},
|
||||
}),
|
||||
)
|
||||
|
||||
return config
|
||||
})
|
||||
|
||||
async function importFrappeUIPlugin(isDev, config) {
|
||||
if (isDev) {
|
||||
try {
|
||||
// Check if local frappe-ui has the vite plugin file
|
||||
const fs = await import('node:fs')
|
||||
const localVitePluginPath = path.resolve(
|
||||
import.meta.dirname,
|
||||
'../frappe-ui/vite/index.js',
|
||||
)
|
||||
|
||||
if (fs.existsSync(localVitePluginPath)) {
|
||||
const module = await import('../frappe-ui/vite/index.js')
|
||||
console.info('Local frappe-ui vite plugin found, using local plugin')
|
||||
config.resolve.alias = getAliases(config)
|
||||
return module.default
|
||||
} else {
|
||||
console.warn('Local frappe-ui vite plugin not found, using npm package')
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
'Local frappe-ui not found, falling back to npm package:',
|
||||
error.message,
|
||||
)
|
||||
}
|
||||
}
|
||||
// Fall back to npm package if local import fails
|
||||
const module = await import('frappe-ui/vite')
|
||||
return module.default
|
||||
}
|
||||
|
||||
function getAliases(config) {
|
||||
return {
|
||||
...config.resolve.alias,
|
||||
'frappe-ui/tailwind': path.resolve(
|
||||
import.meta.dirname,
|
||||
'../frappe-ui/tailwind/preset.js',
|
||||
),
|
||||
'frappe-ui/style.css': path.resolve(
|
||||
import.meta.dirname,
|
||||
'../frappe-ui/src/style.css',
|
||||
),
|
||||
'frappe-ui/frappe': path.resolve(
|
||||
import.meta.dirname,
|
||||
'../frappe-ui/frappe/index.js',
|
||||
),
|
||||
// subpath entries must precede the bare `frappe-ui` key: a plain string alias
|
||||
// matches by prefix, so without these subpaths would rewrite under
|
||||
// `.../src/index.ts`. `internals` is pulled in by @framework/ui.
|
||||
'frappe-ui/icons': path.resolve(
|
||||
import.meta.dirname,
|
||||
'../frappe-ui/icons/index.ts',
|
||||
),
|
||||
'frappe-ui/editor': path.resolve(
|
||||
import.meta.dirname,
|
||||
'../frappe-ui/src/molecules/editor/index.ts',
|
||||
),
|
||||
'frappe-ui/editor-style.css': path.resolve(
|
||||
import.meta.dirname,
|
||||
'../frappe-ui/src/molecules/editor/style.css',
|
||||
),
|
||||
'frappe-ui/internals': path.resolve(
|
||||
import.meta.dirname,
|
||||
'../frappe-ui/internals.ts',
|
||||
),
|
||||
'frappe-ui': path.resolve(import.meta.dirname, '../frappe-ui/src/index.ts'),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user