mirror of
https://github.com/twentyhq/twenty
synced 2026-04-21 13:37:22 +00:00
fix(twenty-front): fix tsconfig to properly typecheck all files with tsgo (#17380)
## Summary This PR fixes the `tsconfig` setup in `twenty-front` so that `tsgo -p tsconfig.json` properly type-checks all files. ### Root Cause The previous setup used TypeScript project references with `files: []` in the main `tsconfig.json`. When running `tsgo -p tsconfig.json`, this checks nothing because `tsgo` requires the `-b` (build) flag for project references, but the configs weren't set up for composite mode. ### Changes **Simplified tsconfig architecture (4 files → 2):** - `tsconfig.json` - All files (dev, tests, stories) for typecheck/IDE/lint - `tsconfig.build.json` - Production files only (excludes tests/stories) **Removed redundant configs:** - `tsconfig.dev.json` - `tsconfig.spec.json` - `tsconfig.storybook.json` **Updated references:** - `jest.config.mjs` → uses `tsconfig.json` - `eslint.config.mjs` → uses `tsconfig.json` - `vite.config.ts` → uses `tsconfig.json` for dev **Type fixes (pre-existing errors revealed by proper typechecking):** - Made `applicationId` optional in `FieldMetadataItem` and `ObjectMetadataItem` - Added missing `navigationMenuItem` translation - Added `objectLabelSingular` to Search GraphQL query - Fixed `sortMorphItems.test.ts` mock data ## Test plan - [ ] Run `npx nx typecheck twenty-front` - should pass - [ ] Run `npx nx lint twenty-front` - should work - [ ] Run `npx nx test twenty-front` - should work - [ ] Run `npx nx build twenty-front` - should work - [ ] Verify IDE type checking works correctly
This commit is contained in:
parent
cb9fe604e4
commit
41dd9856e6
57 changed files with 186 additions and 339 deletions
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": false,
|
||||
"esModuleInterop": false,
|
||||
|
|
@ -8,19 +9,17 @@
|
|||
"noImplicitAny": true,
|
||||
"strictBindCallApply": false,
|
||||
"noEmit": true,
|
||||
"types": ["jest", "node"],
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
}
|
||||
],
|
||||
"extends": "../../tsconfig.base.json"
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx",
|
||||
"src/**/*.d.ts",
|
||||
"**/__mocks__/**/*",
|
||||
"vite.config.ts",
|
||||
"jest.config.mjs"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"types": ["jest", "node"]
|
||||
},
|
||||
"include": [
|
||||
"**/__mocks__/**/*",
|
||||
"vite.config.ts",
|
||||
"jest.config.mjs",
|
||||
"src/**/*.d.ts",
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.spec.tsx",
|
||||
"src/**/*.test.ts",
|
||||
"src/**/*.test.tsx"
|
||||
]
|
||||
}
|
||||
|
|
@ -230,7 +230,7 @@ npm run test -- --watch
|
|||
npx twenty-cli app dev
|
||||
|
||||
# Type checking
|
||||
npx tsc --noEmit
|
||||
npx tsgo --noEmit
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
|
|
|||
6
packages/twenty-emails/.gitignore
vendored
6
packages/twenty-emails/.gitignore
vendored
|
|
@ -1,2 +1,8 @@
|
|||
dist
|
||||
.react-email/
|
||||
|
||||
# Build artifacts
|
||||
src/**/*.js
|
||||
src/**/*.js.map
|
||||
vite.config.js
|
||||
vite.config.js.map
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ export default [
|
|||
languageOptions: {
|
||||
parser: typescriptParser,
|
||||
parserOptions: {
|
||||
project: [path.resolve(__dirname, 'tsconfig.*.json')],
|
||||
project: [path.resolve(__dirname, 'tsconfig.json')],
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,23 +1,20 @@
|
|||
{
|
||||
"type": "module",
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
"allowJs": false,
|
||||
"esModuleInterop": false,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"types": ["vite/client"],
|
||||
"types": ["vite/client", "node"],
|
||||
"paths": {
|
||||
"@/*": ["./src/*"],
|
||||
"src/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"files": [],
|
||||
"include": ["vite.config.ts"],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
}
|
||||
],
|
||||
"extends": "../../tsconfig.base.json"
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx",
|
||||
"vite.config.ts"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,21 +4,13 @@
|
|||
"outDir": "../../.cache/tsc",
|
||||
"composite": true,
|
||||
"declaration": true,
|
||||
"types": [
|
||||
"node",
|
||||
"@nx/react/typings/image.d.ts",
|
||||
"vite/client"
|
||||
]
|
||||
"types": ["node", "@nx/react/typings/image.d.ts", "vite/client"]
|
||||
},
|
||||
"include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"],
|
||||
"exclude": [
|
||||
"**/*.spec.ts",
|
||||
"**/*.test.ts",
|
||||
"**/*.spec.tsx",
|
||||
"**/*.test.tsx",
|
||||
"**/*.spec.js",
|
||||
"**/*.test.js",
|
||||
"**/*.spec.jsx",
|
||||
"**/*.test.jsx"
|
||||
],
|
||||
"include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"]
|
||||
"**/*.test.tsx"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,13 @@ export default defineConfig({
|
|||
root: __dirname,
|
||||
cacheDir: '../../node_modules/.vite/packages/twenty-emails',
|
||||
|
||||
resolve: {
|
||||
alias: {
|
||||
'@/': path.resolve(__dirname, 'src') + '/',
|
||||
'src/': path.resolve(__dirname, 'src') + '/',
|
||||
},
|
||||
},
|
||||
|
||||
plugins: [
|
||||
react({
|
||||
plugins: [['@lingui/swc-plugin', {}]],
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ export default {
|
|||
silent: false,
|
||||
preset: '../../jest.preset.js',
|
||||
transform: {
|
||||
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
|
||||
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.json' }],
|
||||
},
|
||||
moduleFileExtensions: ['ts', 'js', 'html'],
|
||||
coverageDirectory: '../../coverage/packages/twenty-eslint-rules',
|
||||
|
|
|
|||
|
|
@ -4,16 +4,8 @@
|
|||
"outDir": "../../.cache/tsc",
|
||||
"esModuleInterop": true,
|
||||
"moduleResolution": "node16",
|
||||
"module": "node16"
|
||||
"module": "node16",
|
||||
"types": ["jest", "node"]
|
||||
},
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.lint.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
}
|
||||
]
|
||||
"include": ["**/*.ts", "jest.config.mjs"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"types": ["node"]
|
||||
},
|
||||
"exclude": ["**/*.spec.ts"],
|
||||
"include": ["**/*.ts"]
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"types": ["jest", "node"]
|
||||
},
|
||||
"include": ["jest.config.mjs", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"]
|
||||
}
|
||||
|
|
@ -49,11 +49,7 @@ const config = [
|
|||
languageOptions: {
|
||||
parser: typescriptParser,
|
||||
parserOptions: {
|
||||
project: [
|
||||
path.resolve(__dirname, 'tsconfig.dev.json'),
|
||||
path.resolve(__dirname, 'tsconfig.storybook.json'),
|
||||
path.resolve(__dirname, 'tsconfig.spec.json'),
|
||||
],
|
||||
project: [path.resolve(__dirname, 'tsconfig.json')],
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { fileURLToPath } from 'url';
|
|||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
const tsConfigPath = resolve(__dirname, './tsconfig.spec.json');
|
||||
const tsConfigPath = resolve(__dirname, './tsconfig.json');
|
||||
const tsConfig = JSON.parse(readFileSync(tsConfigPath, 'utf8'));
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
|
|
@ -55,7 +55,7 @@ const jestConfig = {
|
|||
'<rootDir>/__mocks__/imageMockFront.js',
|
||||
'\\.css$': '<rootDir>/__mocks__/styleMock.js',
|
||||
...pathsToModuleNameMapper(tsConfig.compilerOptions.paths, {
|
||||
prefix: '<rootDir>/../../',
|
||||
prefix: '<rootDir>/',
|
||||
}),
|
||||
},
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -21,6 +21,7 @@ export const SEARCH_QUERY = gql`
|
|||
node {
|
||||
recordId
|
||||
objectNameSingular
|
||||
objectLabelSingular
|
||||
label
|
||||
imageUrl
|
||||
tsRankCD
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ export const useMetadataErrorHandler = () => {
|
|||
viewFilterGroup: t`view filter group`,
|
||||
commandMenuItem: t`command menu item`,
|
||||
frontComponent: t`front component`,
|
||||
navigationMenuItem: t`navigation menu item`,
|
||||
} as const satisfies Record<AllMetadataName, string>;
|
||||
|
||||
const handleMetadataError = (
|
||||
|
|
|
|||
|
|
@ -17,9 +17,15 @@ export type FieldMetadataItemOption = PartialFieldMetadataItemOption & {
|
|||
|
||||
export type FieldMetadataItem = Omit<
|
||||
Field,
|
||||
'__typename' | 'defaultValue' | 'options' | 'relation' | 'morphRelations'
|
||||
| '__typename'
|
||||
| 'applicationId'
|
||||
| 'defaultValue'
|
||||
| 'options'
|
||||
| 'relation'
|
||||
| 'morphRelations'
|
||||
> & {
|
||||
__typename?: string;
|
||||
applicationId?: string;
|
||||
defaultValue?: any;
|
||||
options?: FieldMetadataItemOption[] | null;
|
||||
relation?: FieldMetadataItemRelation | null;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { type FieldMetadataItem } from './FieldMetadataItem';
|
|||
export type ObjectMetadataItem = Omit<
|
||||
GeneratedObject,
|
||||
| '__typename'
|
||||
| 'applicationId'
|
||||
| 'fields'
|
||||
| 'indexMetadatas'
|
||||
| 'labelIdentifierFieldMetadataId'
|
||||
|
|
@ -13,6 +14,7 @@ export type ObjectMetadataItem = Omit<
|
|||
| 'indexMetadataList'
|
||||
> & {
|
||||
__typename?: string;
|
||||
applicationId?: string;
|
||||
fields: FieldMetadataItem[];
|
||||
readableFields: FieldMetadataItem[];
|
||||
updatableFields: FieldMetadataItem[];
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import { ObjectFilterDropdownFilterSelectMenuItem } from '@/object-record/object
|
|||
import { fieldMetadataItemIdUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemIdUsedInDropdownComponentState';
|
||||
import { objectFilterDropdownIsSelectingCompositeFieldComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownIsSelectingCompositeFieldComponentState';
|
||||
import { objectFilterDropdownSubMenuFieldTypeComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSubMenuFieldTypeComponentState';
|
||||
import { isCompositeFieldType } from '@/object-record/object-filter-dropdown/utils/isCompositeFieldType';
|
||||
import { isCompositeFilterableFieldType } from '@/object-record/object-filter-dropdown/utils/isCompositeFilterableFieldType';
|
||||
import { visibleRecordFieldsComponentSelector } from '@/object-record/record-field/states/visibleRecordFieldsComponentSelector';
|
||||
import { useFilterableFieldMetadataItems } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItems';
|
||||
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
|
||||
|
|
@ -117,7 +117,7 @@ export const AdvancedFilterFieldSelectMenu = ({
|
|||
recordFilterId,
|
||||
});
|
||||
|
||||
if (isCompositeFieldType(filterType)) {
|
||||
if (isCompositeFilterableFieldType(filterType)) {
|
||||
setObjectFilterDropdownSubMenuFieldType(filterType);
|
||||
|
||||
setFieldMetadataItemIdUsedInDropdown(selectedFieldMetadataItem.id);
|
||||
|
|
|
|||
|
|
@ -54,6 +54,13 @@ export const computeDraftValueFromString = <FieldValue>({
|
|||
if (isFieldAddress(fieldDefinition)) {
|
||||
return {
|
||||
addressStreet1: value,
|
||||
addressStreet2: null,
|
||||
addressCity: null,
|
||||
addressState: null,
|
||||
addressPostcode: null,
|
||||
addressCountry: null,
|
||||
addressLat: null,
|
||||
addressLng: null,
|
||||
} as FieldInputDraftValue<FieldValue>;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ export const computeEmptyDraftValue = <FieldValue>({
|
|||
addressState: '',
|
||||
addressCountry: '',
|
||||
addressPostcode: '',
|
||||
} as FieldInputDraftValue<FieldValue>;
|
||||
} as unknown as FieldInputDraftValue<FieldValue>;
|
||||
}
|
||||
|
||||
if (isFieldCurrency(fieldDefinition)) {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ const createSearchRecord = (recordId: string): SearchRecord => ({
|
|||
recordId,
|
||||
label: `Record ${recordId}`,
|
||||
objectNameSingular: 'person',
|
||||
objectLabelSingular: 'Person',
|
||||
tsRank: 0,
|
||||
tsRankCD: 0,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import { fieldMetadataItemIdUsedInDropdownComponentState } from '@/object-record
|
|||
import { objectFilterDropdownIsSelectingCompositeFieldComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownIsSelectingCompositeFieldComponentState';
|
||||
import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState';
|
||||
import { objectFilterDropdownSubMenuFieldTypeComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSubMenuFieldTypeComponentState';
|
||||
import { isCompositeFieldType } from '@/object-record/object-filter-dropdown/utils/isCompositeFieldType';
|
||||
import { isCompositeFilterableFieldType } from '@/object-record/object-filter-dropdown/utils/isCompositeFilterableFieldType';
|
||||
import { useFilterableFieldMetadataItems } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItems';
|
||||
import { RECORD_LEVEL_PERMISSION_PREDICATE_FIELD_TYPES } from '@/settings/roles/role-permissions/object-level-permissions/record-level-permissions/constants/RecordLevelPermissionPredicateFieldTypes';
|
||||
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
|
||||
|
|
@ -99,7 +99,7 @@ export const SettingsRolePermissionsObjectLevelRecordLevelPermissionFieldSelectF
|
|||
selectedFieldMetadataItem.type,
|
||||
);
|
||||
|
||||
if (isCompositeFieldType(filterType)) {
|
||||
if (isCompositeFilterableFieldType(filterType)) {
|
||||
setObjectFilterDropdownSubMenuFieldType(filterType);
|
||||
setFieldMetadataItemIdUsedInDropdown(selectedFieldMetadataItem.id);
|
||||
setObjectFilterDropdownIsSelectingCompositeField(true);
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ export const Dialog = ({
|
|||
{children}
|
||||
{buttons.map(({ accent, onClick, role, title: key, variant }) => (
|
||||
<StyledDialogButton
|
||||
onClick={(event) => {
|
||||
onClick={(event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
onClose?.();
|
||||
onClick?.(event);
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -272,7 +272,9 @@ export const WorkflowEditActionIfElseBody = ({
|
|||
title={t`Add route`}
|
||||
variant="secondary"
|
||||
size="small"
|
||||
onClick={(event) => handleAddRoute(event)}
|
||||
onClick={(event: React.MouseEvent<HTMLButtonElement>) =>
|
||||
handleAddRoute(event)
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,16 @@
|
|||
"compilerOptions": {
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.js",
|
||||
"src/**/*.jsx",
|
||||
"src/**/*.d.ts",
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"**/__mocks__/**/*",
|
||||
"**/__tests__/**/*",
|
||||
"**/*.spec.ts",
|
||||
"**/*.spec.tsx",
|
||||
"**/*.stories.ts",
|
||||
|
|
@ -12,12 +20,5 @@
|
|||
"**/*.test.ts",
|
||||
"**/*.test.tsx",
|
||||
"src/testing/**/*"
|
||||
],
|
||||
"include": [
|
||||
"src/**/*.js",
|
||||
"src/**/*.jsx",
|
||||
"src/**/*.d.ts",
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.js",
|
||||
"src/**/*.jsx",
|
||||
"src/**/*.d.ts",
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx",
|
||||
"lingui.config.ts",
|
||||
"jest.config.mjs",
|
||||
"vite.config.ts",
|
||||
"vitest.config.ts",
|
||||
"setupTests.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"src/testing/**/*"
|
||||
]
|
||||
}
|
||||
|
|
@ -24,29 +24,29 @@
|
|||
"@/*": ["./src/modules/*"],
|
||||
"~/*": ["./src/*"]
|
||||
},
|
||||
"types": ["node", "jest"],
|
||||
"plugins": [
|
||||
{
|
||||
"name": "@styled/typescript-styled-plugin",
|
||||
"lint": {
|
||||
"validProperties": ["container-type"],
|
||||
"validProperties": ["container-type"]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"files": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.dev.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.storybook.json"
|
||||
}
|
||||
"include": [
|
||||
"src/**/*.js",
|
||||
"src/**/*.jsx",
|
||||
"src/**/*.d.ts",
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx",
|
||||
".storybook/*.ts",
|
||||
".storybook/*.tsx",
|
||||
"lingui.config.ts",
|
||||
"jest.config.mjs",
|
||||
"vite.config.ts",
|
||||
"vitest.config.ts",
|
||||
"setupTests.ts"
|
||||
],
|
||||
"extends": "../../tsconfig.base.json"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"types": ["jest", "node"],
|
||||
"baseUrl": "../..",
|
||||
"paths": {
|
||||
"@/*": ["./packages/twenty-front/src/modules/*"],
|
||||
"~/*": ["./packages/twenty-front/src/*"]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"**/__mocks__/**/*",
|
||||
"**/__tests__/**/*",
|
||||
"jest.config.mjs",
|
||||
"setupTests.ts",
|
||||
"src/**/*.d.ts",
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.spec.tsx",
|
||||
"src/**/*.test.ts",
|
||||
"src/**/*.test.tsx",
|
||||
"src/testing/**/*",
|
||||
"tsup.config.ts",
|
||||
"tsup.ui.index.tsx",
|
||||
"vite.config.ts"
|
||||
]
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"emitDecoratorMetadata": true
|
||||
},
|
||||
"include": [
|
||||
".storybook/*.ts",
|
||||
".storybook/*.tsx",
|
||||
"src/**/*.d.ts",
|
||||
"src/**/*.stories.mdx",
|
||||
"src/**/*.stories.ts",
|
||||
"src/**/*.stories.tsx"
|
||||
]
|
||||
}
|
||||
|
|
@ -39,7 +39,7 @@ export default defineConfig(({ command, mode }) => {
|
|||
|
||||
const tsConfigPath = isBuildCommand
|
||||
? path.resolve(__dirname, './tsconfig.build.json')
|
||||
: path.resolve(__dirname, './tsconfig.dev.json');
|
||||
: path.resolve(__dirname, './tsconfig.json');
|
||||
|
||||
const CHUNK_SIZE_WARNING_LIMIT = 1024 * 1024; // 1MB
|
||||
// Please don't increase this limit for main index chunk
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
import { type ApplicationManifest } from 'twenty-shared/application';
|
||||
// Loose type for JSON manifest imports where enum values are inferred as strings
|
||||
type JsonManifestInput = {
|
||||
functions?: Array<{ builtHandlerChecksum?: string | null; [key: string]: unknown }>;
|
||||
frontComponents?: Array<{ builtComponentChecksum?: string | null; [key: string]: unknown }>;
|
||||
[key: string]: unknown;
|
||||
};
|
||||
|
||||
// Replace dynamic checksum values with a placeholder for consistent comparisons
|
||||
export const normalizeManifestForComparison = <
|
||||
T extends Partial<ApplicationManifest>,
|
||||
>(
|
||||
export const normalizeManifestForComparison = <T extends JsonManifestInput>(
|
||||
manifest: T,
|
||||
): T => ({
|
||||
...manifest,
|
||||
|
|
|
|||
|
|
@ -33,7 +33,9 @@ export const processEsbuildResult = async ({
|
|||
for (const outputFile of outputFiles) {
|
||||
const absoluteOutputFile = path.resolve(outputFile);
|
||||
const relativePath = path.relative(outputDir, absoluteOutputFile);
|
||||
const builtPath = `${builtDir}/${relativePath}`;
|
||||
// Normalize path separators to forward slashes for consistent matching
|
||||
const normalizedRelativePath = relativePath.split(path.sep).join('/');
|
||||
const builtPath = `${builtDir}/${normalizedRelativePath}`;
|
||||
|
||||
const content = await fs.readFile(absoluteOutputFile);
|
||||
const checksum = crypto.createHash('md5').update(content).digest('hex');
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
import { glob } from 'fast-glob';
|
||||
import path from 'path';
|
||||
import { type Application } from 'twenty-shared/application';
|
||||
import {
|
||||
type Application,
|
||||
type ApplicationVariables,
|
||||
} from 'twenty-shared/application';
|
||||
import { createLogger } from '../../common/logger';
|
||||
import { manifestExtractFromFileServer } from '../manifest-extract-from-file-server';
|
||||
import { type ValidationError } from '../manifest.types';
|
||||
|
|
@ -82,7 +85,7 @@ export class ApplicationEntityBuilder
|
|||
if (application?.applicationVariables) {
|
||||
for (const [name, variable] of Object.entries(
|
||||
application.applicationVariables,
|
||||
)) {
|
||||
) as [string, ApplicationVariables[string]][]) {
|
||||
if (variable.universalIdentifier) {
|
||||
const locations = seen.get(variable.universalIdentifier) ?? [];
|
||||
locations.push(`application.variables.${name}`);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": false,
|
||||
"esModuleInterop": false,
|
||||
|
|
@ -9,19 +10,19 @@
|
|||
"noImplicitAny": true,
|
||||
"strictBindCallApply": false,
|
||||
"noEmit": true,
|
||||
"types": ["jest", "node"],
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
}
|
||||
],
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx",
|
||||
"src/**/*.d.ts",
|
||||
"**/__mocks__/**/*",
|
||||
"**/__tests__/**/*",
|
||||
"vite.config.ts",
|
||||
"scripts/generateBarrels.ts",
|
||||
"jest.config.mjs"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"types": ["jest", "node"]
|
||||
},
|
||||
"include": [
|
||||
"**/__mocks__/**/*",
|
||||
"**/__tests__/**/*",
|
||||
"vite.config.ts",
|
||||
"scripts/generateBarrels.ts",
|
||||
"jest.config.mjs",
|
||||
"src/**/*.d.ts",
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.spec.tsx",
|
||||
"src/**/*.test.ts",
|
||||
"src/**/*.test.tsx",
|
||||
"src/**/*.e2e-spec.ts"
|
||||
]
|
||||
}
|
||||
|
|
@ -120,7 +120,7 @@ export default [
|
|||
languageOptions: {
|
||||
parser: typescriptParser,
|
||||
parserOptions: {
|
||||
project: [path.resolve(__dirname, 'tsconfig.*.json')],
|
||||
project: [path.resolve(__dirname, 'tsconfig.json')],
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { type AllMetadataName } from '@/metadata/all-metadata-name.type';
|
||||
import { type AllMetadataName } from './all-metadata-name.type';
|
||||
|
||||
export type FailedMetadataValidationError = {
|
||||
code: string;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { SOURCE_LOCALE } from '@/translations/constants/SourceLocale';
|
||||
|
||||
export const APP_LOCALES = {
|
||||
[SOURCE_LOCALE]: SOURCE_LOCALE,
|
||||
en: SOURCE_LOCALE,
|
||||
'pseudo-en': 'pseudo-en',
|
||||
'af-ZA': 'af-ZA',
|
||||
'ar-SA': 'ar-SA',
|
||||
|
|
@ -33,3 +33,5 @@ export const APP_LOCALES = {
|
|||
'zh-CN': 'zh-CN',
|
||||
'zh-TW': 'zh-TW',
|
||||
} as const;
|
||||
|
||||
export type AppLocale = keyof typeof APP_LOCALES;
|
||||
|
|
|
|||
|
|
@ -7,5 +7,6 @@
|
|||
* |___/
|
||||
*/
|
||||
|
||||
export type { AppLocale } from './constants/AppLocales';
|
||||
export { APP_LOCALES } from './constants/AppLocales';
|
||||
export { SOURCE_LOCALE } from './constants/SourceLocale';
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ describe('isMatchingCurrencyFilter', () => {
|
|||
currencyCode: 'USD',
|
||||
},
|
||||
}),
|
||||
).toThrowError('Unexpected filter for currency : {}');
|
||||
).toThrow('Unexpected filter for currency : {}');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -320,7 +320,7 @@ describe('isMatchingCurrencyFilter', () => {
|
|||
currencyFilter,
|
||||
value: { amountMicros: 10 },
|
||||
}),
|
||||
).toThrowError(
|
||||
).toThrow(
|
||||
'Unexpected operand for currency amount micros filter : {"unexpected":10}',
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { APP_LOCALES } from '@/translations';
|
||||
import { APP_LOCALES, type AppLocale } from '@/translations/constants/AppLocales';
|
||||
|
||||
export const isValidLocale = (
|
||||
value: string | null,
|
||||
): value is keyof typeof APP_LOCALES => value !== null && value in APP_LOCALES;
|
||||
export const isValidLocale = (value: string | null): value is AppLocale =>
|
||||
value !== null && value in APP_LOCALES;
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
import { APP_LOCALES, SOURCE_LOCALE } from '@/translations';
|
||||
import {
|
||||
APP_LOCALES,
|
||||
type AppLocale,
|
||||
} from '@/translations/constants/AppLocales';
|
||||
import { SOURCE_LOCALE } from '@/translations/constants/SourceLocale';
|
||||
|
||||
/**
|
||||
* Maps language codes to full locale keys in APP_LOCALES
|
||||
* Example: 'fr' -> 'fr-FR', 'en' -> 'en'
|
||||
*/
|
||||
// Maps language codes to full locale keys in APP_LOCALES
|
||||
// Example: 'fr' -> 'fr-FR', 'en' -> 'en'
|
||||
const languageToLocaleMap = Object.keys(APP_LOCALES).reduce<
|
||||
Record<string, string>
|
||||
>((map, locale) => {
|
||||
// Extract the language code (part before the hyphen or the whole code if no hyphen)
|
||||
const language = locale.split('-')[0].toLowerCase();
|
||||
|
||||
// Only add to the map if not already added or if the current locale is the source locale
|
||||
|
|
@ -20,19 +21,14 @@ const languageToLocaleMap = Object.keys(APP_LOCALES).reduce<
|
|||
return map;
|
||||
}, {});
|
||||
|
||||
/**
|
||||
* Normalizes a locale string to match our supported formats
|
||||
*/
|
||||
export const normalizeLocale = (
|
||||
value: string | null,
|
||||
): keyof typeof APP_LOCALES => {
|
||||
export const normalizeLocale = (value: string | null): AppLocale => {
|
||||
if (value === null) {
|
||||
return SOURCE_LOCALE;
|
||||
}
|
||||
|
||||
// Direct match in our supported locales
|
||||
if (value in APP_LOCALES) {
|
||||
return value as keyof typeof APP_LOCALES;
|
||||
return value as AppLocale;
|
||||
}
|
||||
|
||||
// Try case-insensitive match (e.g., 'fr-fr' -> 'fr-FR')
|
||||
|
|
@ -40,13 +36,13 @@ export const normalizeLocale = (
|
|||
(locale) => locale.toLowerCase() === value.toLowerCase(),
|
||||
);
|
||||
if (caseInsensitiveMatch) {
|
||||
return caseInsensitiveMatch as keyof typeof APP_LOCALES;
|
||||
return caseInsensitiveMatch as AppLocale;
|
||||
}
|
||||
|
||||
// Try matching just the language part (e.g., 'fr' -> 'fr-FR')
|
||||
const languageCode = value?.trim() ? value.split('-')[0].toLowerCase() : '';
|
||||
if (languageToLocaleMap[languageCode]) {
|
||||
return languageToLocaleMap[languageCode] as keyof typeof APP_LOCALES;
|
||||
return languageToLocaleMap[languageCode] as AppLocale;
|
||||
}
|
||||
|
||||
return SOURCE_LOCALE;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": false,
|
||||
"esModuleInterop": false,
|
||||
|
|
@ -8,19 +9,15 @@
|
|||
"noImplicitAny": true,
|
||||
"strictBindCallApply": false,
|
||||
"noEmit": true,
|
||||
"types": ["jest", "node"],
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
}
|
||||
],
|
||||
"extends": "../../tsconfig.base.json"
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx",
|
||||
"**/__mocks__/**/*",
|
||||
"jest.config.mjs"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,19 +4,15 @@
|
|||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"noEmit": false,
|
||||
"baseUrl": ".",
|
||||
"outDir": "../../.cache/tsc",
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"],
|
||||
"exclude": [
|
||||
"**/*.spec.ts",
|
||||
"**/*.test.ts",
|
||||
"**/*.spec.tsx",
|
||||
"**/*.test.tsx",
|
||||
"**/*.spec.js",
|
||||
"**/*.test.js",
|
||||
"**/*.spec.jsx",
|
||||
"**/*.test.jsx"
|
||||
],
|
||||
"include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"]
|
||||
"**/__mocks__/**/*"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"types": ["jest", "node"]
|
||||
},
|
||||
"include": [
|
||||
"**/__mocks__/**/*",
|
||||
"jest.config.mjs",
|
||||
"src/**/*.d.ts",
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.spec.tsx",
|
||||
"src/**/*.test.ts",
|
||||
"src/**/*.test.tsx",
|
||||
]
|
||||
}
|
||||
|
|
@ -41,6 +41,11 @@ export default defineConfig(() => {
|
|||
return {
|
||||
root: __dirname,
|
||||
cacheDir: '../../node_modules/.vite/packages/twenty-shared',
|
||||
resolve: {
|
||||
alias: {
|
||||
'@/': path.resolve(__dirname, 'src') + '/',
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
tsconfigPaths({
|
||||
root: __dirname
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ const config: StorybookConfig = {
|
|||
plugins.push(
|
||||
checker({
|
||||
typescript: {
|
||||
tsconfigPath: path.resolve(dirname, '../tsconfig.dev.json'),
|
||||
tsconfigPath: path.resolve(dirname, '../tsconfig.json'),
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ export default [
|
|||
languageOptions: {
|
||||
parser: typescriptParser,
|
||||
parserOptions: {
|
||||
project: [path.resolve(__dirname, 'tsconfig.*.json')],
|
||||
project: [path.resolve(__dirname, 'tsconfig.json')],
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -9,9 +9,8 @@ const StyledButtonGroupContainer = styled.div`
|
|||
display: flex;
|
||||
`;
|
||||
|
||||
export type ButtonGroupProps = Pick<
|
||||
ButtonProps,
|
||||
'variant' | 'size' | 'accent'
|
||||
export type ButtonGroupProps = Partial<
|
||||
Pick<ButtonProps, 'variant' | 'size' | 'accent'>
|
||||
> & {
|
||||
className?: string;
|
||||
children: ReactNode[];
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": [
|
||||
"jest.config.mjs",
|
||||
"setupTests.ts",
|
||||
"src/*.d.ts",
|
||||
"src/**/*.d.ts",
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.test.ts",
|
||||
"src/**/*.stories.tsx",
|
||||
"src/**/*.tsx",
|
||||
"src/**/*.ts",
|
||||
"vite.config.ts"
|
||||
]
|
||||
}
|
||||
|
|
@ -9,27 +9,21 @@
|
|||
"moduleResolution": "bundler",
|
||||
"esModuleInterop": true,
|
||||
"noEmit": true,
|
||||
"types": ["node"],
|
||||
"types": ["node", "jest"],
|
||||
"outDir": "../../.cache/tsc",
|
||||
"paths": {
|
||||
"@ui/*": ["./src/*"],
|
||||
"@assets/*": ["./src/assets/*"]
|
||||
}
|
||||
},
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.dev.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.storybook.json"
|
||||
}
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx",
|
||||
"src/**/*.d.ts",
|
||||
".storybook/*.ts",
|
||||
".storybook/*.tsx",
|
||||
"jest.config.mjs",
|
||||
"setupTests.ts",
|
||||
"vite.config.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@
|
|||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"baseUrl": ".",
|
||||
"noEmit": false
|
||||
},
|
||||
"include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.tsx"],
|
||||
"exclude": [
|
||||
"**/*.spec.ts",
|
||||
"**/*.spec.tsx",
|
||||
|
|
@ -13,6 +13,5 @@
|
|||
"**/*.stories.tsx",
|
||||
"**/*.test.ts",
|
||||
"**/*.test.tsx"
|
||||
],
|
||||
"include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.tsx"]
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": [
|
||||
"jest.config.mjs",
|
||||
"setupTests.ts",
|
||||
"src/**/*.d.ts",
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.test.ts",
|
||||
"vite.config.ts"
|
||||
]
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"emitDecoratorMetadata": true
|
||||
},
|
||||
"include": [
|
||||
".storybook/*.ts",
|
||||
".storybook/*.tsx",
|
||||
"src/*.d.ts",
|
||||
"src/**/*.d.ts",
|
||||
"src/**/*.stories.mdx",
|
||||
"src/**/*.stories.ts",
|
||||
"src/**/*.stories.tsx"
|
||||
]
|
||||
}
|
||||
|
|
@ -41,7 +41,7 @@ export default defineConfig(({ command }) => {
|
|||
|
||||
const tsConfigPath = isBuildCommand
|
||||
? path.resolve(__dirname, './tsconfig.lib.json')
|
||||
: path.resolve(__dirname, './tsconfig.dev.json');
|
||||
: path.resolve(__dirname, './tsconfig.json');
|
||||
|
||||
const checkersConfig: Checkers = {
|
||||
typescript: {
|
||||
|
|
@ -55,6 +55,12 @@ export default defineConfig(({ command }) => {
|
|||
};
|
||||
|
||||
return {
|
||||
resolve: {
|
||||
alias: {
|
||||
'@ui/': path.resolve(__dirname, 'src') + '/',
|
||||
'@assets/': path.resolve(__dirname, 'src/assets') + '/',
|
||||
},
|
||||
},
|
||||
css: {
|
||||
modules: {
|
||||
localsConvention: 'camelCaseOnly',
|
||||
|
|
|
|||
Loading…
Reference in a new issue