Follow up dev and build (#17364)

fresh eye report

- Improve template entities
- Ignore .twenty properly
- Add base src alias to tsconfig
This commit is contained in:
martmull
2026-01-22 18:19:06 +01:00
committed by GitHub
parent 210c66b5dd
commit e72f652723
7 changed files with 61 additions and 20 deletions
@@ -22,6 +22,10 @@
"skipLibCheck": true,
"skipDefaultLibCheck": true,
"resolveJsonModule": true,
"paths": {
"src/*": ["./src/*"],
"~/*": ["./*"]
}
},
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
}
@@ -41,7 +41,7 @@ describe('copyBaseApplicationProject', () => {
});
// Verify src/app/ folder exists
const srcAppPath = join(testAppDirectory, 'src', 'app');
const srcAppPath = join(testAppDirectory, 'src');
expect(await fs.pathExists(srcAppPath)).toBe(true);
// Verify application.config.ts exists in src/app/
@@ -114,7 +114,6 @@ describe('copyBaseApplicationProject', () => {
const appConfigPath = join(
testAppDirectory,
'src',
'app',
'application.config.ts',
);
const appConfigContent = await fs.readFile(appConfigPath, 'utf8');
@@ -127,7 +126,7 @@ describe('copyBaseApplicationProject', () => {
// Verify it imports the role identifier
expect(appConfigContent).toContain(
"import { DEFAULT_FUNCTION_ROLE_UNIVERSAL_IDENTIFIER } from './default-function.role'",
"import { DEFAULT_FUNCTION_ROLE_UNIVERSAL_IDENTIFIER } from 'src/default-function.role'",
);
// Verify display name and description
@@ -156,7 +155,6 @@ describe('copyBaseApplicationProject', () => {
const roleConfigPath = join(
testAppDirectory,
'src',
'app',
'default-function.role.ts',
);
const roleConfigContent = await fs.readFile(roleConfigPath, 'utf8');
@@ -216,7 +214,6 @@ describe('copyBaseApplicationProject', () => {
const appConfigPath = join(
testAppDirectory,
'src',
'app',
'application.config.ts',
);
const appConfigContent = await fs.readFile(appConfigPath, 'utf8');
@@ -247,11 +244,11 @@ describe('copyBaseApplicationProject', () => {
// Read both app configs
const firstAppConfig = await fs.readFile(
join(firstAppDir, 'src', 'app', 'application.config.ts'),
join(firstAppDir, 'src', 'application.config.ts'),
'utf8',
);
const secondAppConfig = await fs.readFile(
join(secondAppDir, 'src', 'app', 'application.config.ts'),
join(secondAppDir, 'src', 'application.config.ts'),
'utf8',
);
@@ -289,11 +286,11 @@ describe('copyBaseApplicationProject', () => {
// Read both role configs
const firstRoleConfig = await fs.readFile(
join(firstAppDir, 'src', 'app', 'default-function.role.ts'),
join(firstAppDir, 'src', 'default-function.role.ts'),
'utf8',
);
const secondRoleConfig = await fs.readFile(
join(secondAppDir, 'src', 'app', 'default-function.role.ts'),
join(secondAppDir, 'src', 'default-function.role.ts'),
'utf8',
);
@@ -2,7 +2,7 @@ import * as fs from 'fs-extra';
import { join } from 'path';
import { v4 } from 'uuid';
const APP_FOLDER = 'src/app';
const APP_FOLDER = 'src';
export const copyBaseApplicationProject = async ({
appName,
@@ -36,6 +36,10 @@ export const copyBaseApplicationProject = async ({
appDirectory: appFolderPath,
});
await createDefaultFunction({
appDirectory: appFolderPath,
});
await createApplicationConfig({
displayName: appDisplayName,
description: appDescription,
@@ -67,6 +71,7 @@ generated
# dev
/dist/
.twenty
# production
/build
@@ -139,7 +144,7 @@ export const HelloWorld = () => {
export default defineFrontComponent({
universalIdentifier: '${universalIdentifier}',
name: 'hello-world',
name: 'hello-world-front-component',
description: 'A sample front component',
component: HelloWorld,
});
@@ -151,6 +156,41 @@ export default defineFrontComponent({
);
};
const createDefaultFunction = async ({
appDirectory,
}: {
appDirectory: string;
}) => {
const universalIdentifier = v4();
const triggerUniversalIdentifier = v4();
const content = `import { defineFunction } from 'twenty-sdk';
const handler = async (): Promise<{ message: string }> => {
return { message: 'Hello, World!' };
};
export default defineFunction({
universalIdentifier: '${universalIdentifier}',
name: 'hello-world-function',
description: 'A sample serverless function',
timeoutSeconds: 5,
handler,
triggers: [
{
universalIdentifier: '${triggerUniversalIdentifier}',
type: 'route',
path: '/hello-world-function',
httpMethod: 'GET',
isAuthRequired: false,
},
],
});
`;
await fs.writeFile(join(appDirectory, 'hello-world.function.ts'), content);
};
const createApplicationConfig = async ({
displayName,
description,
@@ -161,7 +201,7 @@ const createApplicationConfig = async ({
appDirectory: string;
}) => {
const content = `import { defineApp } from 'twenty-sdk';
import { DEFAULT_FUNCTION_ROLE_UNIVERSAL_IDENTIFIER } from './default-function.role';
import { DEFAULT_FUNCTION_ROLE_UNIVERSAL_IDENTIFIER } from 'src/default-function.role';
export default defineApp({
universalIdentifier: '${v4()}',
@@ -16,9 +16,9 @@ describe('getFrontComponentBaseFile', () => {
"universalIdentifier: '71e45a58-41da-4ae4-8b73-a543c0a9d3d4'",
);
expect(result).toContain("name: 'my-component'");
expect(result).toContain('component: HelloWorld,');
expect(result).toContain('component: Component,');
expect(result).toContain('export const HelloWorld = () => {');
expect(result).toContain('const Component = () => {');
expect(result).toContain(
"description: 'Add a description for your front component'",
@@ -49,7 +49,7 @@ describe('getFrontComponentBaseFile', () => {
});
expect(result).toContain('<div');
expect(result).toContain('<h1>Hello, World!</h1>');
expect(result).toContain('<h1>My new component!</h1>');
expect(result).toContain('</div>');
});
});
@@ -18,7 +18,7 @@ describe('getFunctionBaseFile', () => {
expect(result).toContain('handler,');
expect(result).toContain('triggers: [');
expect(result).toContain('export const handler = async');
expect(result).toContain('const handler = async');
expect(result).toContain(
"description: 'Add a description for your function'",
@@ -13,10 +13,10 @@ export const getFrontComponentBaseFile = ({
return `import { defineFrontComponent } from 'twenty-sdk';
// React component - implement your UI here
export const HelloWorld = () => {
const Component = () => {
return (
<div style={{ padding: '20px', fontFamily: 'sans-serif' }}>
<h1>Hello, World!</h1>
<h1>My new component!</h1>
<p>This is your front component: ${kebabCaseName}</p>
</div>
);
@@ -26,7 +26,7 @@ export default defineFrontComponent({
universalIdentifier: '${universalIdentifier}',
name: '${kebabCaseName}',
description: 'Add a description for your front component',
component: HelloWorld,
component: Component,
});
`;
};
@@ -14,7 +14,7 @@ export const getFunctionBaseFile = ({
return `import { defineFunction } from 'twenty-sdk';
// Handler function - rename and implement your logic
export const handler = async (params: {
const handler = async (params: {
a: string;
b: number;
}): Promise<{ message: string }> => {