perf(sdk): split twenty-sdk barrel into per-purpose subpaths to cut logic-function bundle ~700x (#19834)
## Summary
Logic-function bundles produced by the twenty-sdk CLI were ~1.18 MB even
for a one-line handler. Root cause: the SDK shipped as a single bundled
barrel (`twenty-sdk` → `dist/index.mjs`) that co-mingled server-side
definition factories with the front-component runtime, validation (zod),
and React. With no `\"sideEffects\"` declaration on the SDK package,
esbuild had to assume every module-level statement could have side
effects and refused to drop unused code.
This PR restructures the SDK so consumers' bundlers can tree-shake at
the leaf level:
- **Reorganized SDK source.** All server-side definition factories now
live under `src/sdk/define/` (agents, application, fields,
logic-functions, objects, page-layouts, roles, skills, views,
navigation-menu-items, etc.). All front-component runtime
(components, hooks, host APIs, command primitives) lives under
`src/sdk/front-component/`. The legacy bare `src/sdk/index.ts` is
removed; the bare `twenty-sdk` entry no longer exists.
- **Split the build configs by purpose / runtime env.** Replaced
`vite.config.sdk.ts` with two purpose-specific configs:
- `vite.config.define.ts` — node target, externals from package
`dependencies`, emits to `dist/define/**`
- `vite.config.front-component.ts` — browser/React target, emits to
`dist/front-component/**`
Both use `preserveModules: true` so each leaf ships as its own `.mjs`.
- **\`\"sideEffects\": false\`** on `twenty-sdk` so esbuild can drop
unreferenced re-exports.
- **\`package.json\` exports + \`typesVersions\`** updated: dropped the
bare \`.\` entry, added \`./front-component\`, and pointed \`./define\`
at the new per-module dist layout.
- **Migrated every internal/example/community app** to the new subpath
imports (`twenty-sdk/define`, `twenty-sdk/front-component`,
`twenty-sdk/ui`).
- **Added \`bundle-investigation\` internal app** that reproduces the
bundle bloat and demonstrates the fix.
- Cleaned up dead \`twenty-sdk/dist/sdk/...\` references in the
front-component story builder, the call-recording app, and the SDK
tsconfig.
## Bundle size impact
Measured with esbuild using the same options as the SDK CLI
(\`packages/twenty-apps/internal/bundle-investigation\`):
| Variant | Imports | Before | After |
| ----------------------- |
------------------------------------------------------- | ---------- |
--------- |
| \`01-bare\` | \`defineLogicFunction\` from \`twenty-sdk/define\` |
1177 KB | **1.6 KB** |
| \`02-with-sdk-client\` | + \`CoreApiClient\` from
\`twenty-client-sdk/core\` | 1177 KB | **1.9 KB** |
| \`03-fetch-issues\` | + GitHub GraphQL fetch + JWT signing + 2
mutations | 1181 KB | **5.8 KB** |
| \`05-via-define-subpath\` | same as \`01\`, via the public subpath |
1177 KB | **1.7 KB** |
That's a ~735× reduction on the bare baseline. Knock-on benefits for
Lambda warm + cold starts, S3 upload size, and \`/tmp\` disk usage in
warm containers.
## Test plan
- [x] \`npx nx run twenty-sdk:build\` succeeds
- [x] \`npx nx run twenty-sdk:typecheck\` passes
- [x] \`npx nx run twenty-sdk:test:unit\` passes (31 files / 257 tests)
- [x] \`npx nx run-many -t typecheck
--projects=twenty-front,twenty-server,twenty-front-component-renderer,twenty-sdk,twenty-shared,bundle-investigation\`
passes
- [x] \`node
packages/twenty-apps/internal/bundle-investigation/scripts/build-variants.mjs\`
produces the sizes above
- [ ] CI green
Made with [Cursor](https://cursor.com)
This commit is contained in:
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { FieldType } from '@/sdk';
|
||||
import { FieldType } from '@/sdk/define';
|
||||
import type { Manifest } from 'twenty-shared/application';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { FieldType } from '@/sdk';
|
||||
import { FieldType } from '@/sdk/define';
|
||||
import type { Manifest } from 'twenty-shared/application';
|
||||
import { PermissionFlagType } from 'twenty-shared/constants';
|
||||
import {
|
||||
|
||||
+2
-1
@@ -1,4 +1,5 @@
|
||||
import { defineFrontComponent, numberOfSelectedRecords } from '@/sdk';
|
||||
import { defineFrontComponent } from '@/sdk/define';
|
||||
import { numberOfSelectedRecords } from '@/sdk/front-component';
|
||||
|
||||
const MyComponent = () => null;
|
||||
|
||||
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
import { defineFrontComponent } from '@/sdk/define';
|
||||
import {
|
||||
defineFrontComponent,
|
||||
none,
|
||||
numberOfSelectedRecords,
|
||||
objectPermissions,
|
||||
selectedRecords,
|
||||
} from '@/sdk';
|
||||
} from '@/sdk/front-component';
|
||||
|
||||
const MyComponent = () => null;
|
||||
|
||||
|
||||
+2
-1
@@ -1,4 +1,5 @@
|
||||
import { defineFrontComponent, someDefined, selectedRecords } from '@/sdk';
|
||||
import { defineFrontComponent } from '@/sdk/define';
|
||||
import { someDefined, selectedRecords } from '@/sdk/front-component';
|
||||
|
||||
const MyComponent = () => null;
|
||||
|
||||
|
||||
+2
-1
@@ -1,4 +1,5 @@
|
||||
import { defineFrontComponent, featureFlags, objectPermissions } from '@/sdk';
|
||||
import { defineFrontComponent } from '@/sdk/define';
|
||||
import { featureFlags, objectPermissions } from '@/sdk/front-component';
|
||||
|
||||
const MyComponent = () => null;
|
||||
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
import { defineFrontComponent } from '@/sdk/define';
|
||||
import {
|
||||
defineFrontComponent,
|
||||
favoriteRecordIds,
|
||||
objectMetadataItem,
|
||||
pageType,
|
||||
} from '@/sdk';
|
||||
} from '@/sdk/front-component';
|
||||
|
||||
const MyComponent = () => null;
|
||||
|
||||
|
||||
+2
-1
@@ -1,4 +1,5 @@
|
||||
import { defineFrontComponent, isInSidePanel, objectPermissions } from '@/sdk';
|
||||
import { defineFrontComponent } from '@/sdk/define';
|
||||
import { isInSidePanel, objectPermissions } from '@/sdk/front-component';
|
||||
|
||||
const MyComponent = () => null;
|
||||
|
||||
|
||||
+2
-1
@@ -1,4 +1,5 @@
|
||||
import { defineFrontComponent, pageType } from '@/sdk';
|
||||
import { defineFrontComponent } from '@/sdk/define';
|
||||
import { pageType } from '@/sdk/front-component';
|
||||
|
||||
const MyComponent = () => null;
|
||||
|
||||
|
||||
+2
-6
@@ -1,9 +1,5 @@
|
||||
import {
|
||||
defineFrontComponent,
|
||||
everyEquals,
|
||||
pageType,
|
||||
selectedRecords,
|
||||
} from '@/sdk';
|
||||
import { defineFrontComponent } from '@/sdk/define';
|
||||
import { everyEquals, pageType, selectedRecords } from '@/sdk/front-component';
|
||||
|
||||
const MyComponent = () => null;
|
||||
|
||||
|
||||
+2
-5
@@ -1,8 +1,5 @@
|
||||
import {
|
||||
defineFrontComponent,
|
||||
pageType,
|
||||
targetObjectWritePermissions,
|
||||
} from '@/sdk';
|
||||
import { defineFrontComponent } from '@/sdk/define';
|
||||
import { pageType, targetObjectWritePermissions } from '@/sdk/front-component';
|
||||
|
||||
const MyComponent = () => null;
|
||||
|
||||
|
||||
+9
-9
@@ -3,7 +3,7 @@ import { extractDefineEntity } from '@/cli/utilities/build/manifest/manifest-ext
|
||||
describe('extractDefineEntity', () => {
|
||||
it('should detect defineApplication in default export', () => {
|
||||
const fileContent = `
|
||||
import { defineApplication } from 'twenty-sdk';
|
||||
import { defineApplication } from 'twenty-sdk/define';
|
||||
export default defineApplication({ name: 'MyApp' });
|
||||
`;
|
||||
const result = extractDefineEntity(fileContent);
|
||||
@@ -12,7 +12,7 @@ describe('extractDefineEntity', () => {
|
||||
|
||||
it('should detect defineField in default export', () => {
|
||||
const fileContent = `
|
||||
import { defineField } from 'twenty-sdk';
|
||||
import { defineField } from 'twenty-sdk/define';
|
||||
export default defineField({ name: 'myField' });
|
||||
`;
|
||||
const result = extractDefineEntity(fileContent);
|
||||
@@ -21,7 +21,7 @@ describe('extractDefineEntity', () => {
|
||||
|
||||
it('should detect defineLogicFunction in default export', () => {
|
||||
const fileContent = `
|
||||
import { defineLogicFunction } from 'twenty-sdk';
|
||||
import { defineLogicFunction } from 'twenty-sdk/define';
|
||||
export default defineLogicFunction({ name: 'myFunction' });
|
||||
`;
|
||||
const result = extractDefineEntity(fileContent);
|
||||
@@ -30,7 +30,7 @@ describe('extractDefineEntity', () => {
|
||||
|
||||
it('should detect defineObject in default export', () => {
|
||||
const fileContent = `
|
||||
import { defineObject } from 'twenty-sdk';
|
||||
import { defineObject } from 'twenty-sdk/define';
|
||||
export default defineObject({ name: 'myObject' });
|
||||
`;
|
||||
const result = extractDefineEntity(fileContent);
|
||||
@@ -39,7 +39,7 @@ describe('extractDefineEntity', () => {
|
||||
|
||||
it('should detect defineRole in default export', () => {
|
||||
const fileContent = `
|
||||
import { defineRole } from 'twenty-sdk';
|
||||
import { defineRole } from 'twenty-sdk/define';
|
||||
export default defineRole({ name: 'myRole' });
|
||||
`;
|
||||
const result = extractDefineEntity(fileContent);
|
||||
@@ -48,7 +48,7 @@ describe('extractDefineEntity', () => {
|
||||
|
||||
it('should detect defineFrontComponent in default export', () => {
|
||||
const fileContent = `
|
||||
import { defineFrontComponent } from 'twenty-sdk';
|
||||
import { defineFrontComponent } from 'twenty-sdk/define';
|
||||
export default defineFrontComponent({ name: 'myComponent' });
|
||||
`;
|
||||
const result = extractDefineEntity(fileContent);
|
||||
@@ -57,7 +57,7 @@ describe('extractDefineEntity', () => {
|
||||
|
||||
it('should not detect non-target function in default export', () => {
|
||||
const fileContent = `
|
||||
import { someOtherFunction } from 'twenty-sdk';
|
||||
import { someOtherFunction } from 'twenty-sdk/define';
|
||||
export default someOtherFunction({ name: 'myFunction' });
|
||||
`;
|
||||
const result = extractDefineEntity(fileContent);
|
||||
@@ -66,7 +66,7 @@ describe('extractDefineEntity', () => {
|
||||
|
||||
it('should handle files without default export', () => {
|
||||
const fileContent = `
|
||||
import { defineApplication } from 'twenty-sdk';
|
||||
import { defineApplication } from 'twenty-sdk/define';
|
||||
const app = defineApplication({ name: 'MyApp' });
|
||||
`;
|
||||
const result = extractDefineEntity(fileContent);
|
||||
@@ -75,7 +75,7 @@ describe('extractDefineEntity', () => {
|
||||
|
||||
it('should handle files with non-call default export', () => {
|
||||
const fileContent = `
|
||||
import { defineApplication } from 'twenty-sdk';
|
||||
import { defineApplication } from 'twenty-sdk/define';
|
||||
export default { name: 'MyApp' };
|
||||
`;
|
||||
const result = extractDefineEntity(fileContent);
|
||||
|
||||
@@ -7,14 +7,11 @@ import {
|
||||
} from '@/cli/utilities/build/manifest/manifest-extract-config';
|
||||
import { extractManifestFromFile } from '@/cli/utilities/build/manifest/manifest-extract-config-from-file';
|
||||
import { getDefaultFieldsInObjectFields } from '@/cli/utilities/build/manifest/utils/get-default-fields-in-object-fields';
|
||||
import {
|
||||
type ApplicationConfig,
|
||||
type FrontComponentConfig,
|
||||
type LogicFunctionConfig,
|
||||
} from '@/sdk';
|
||||
import { type ObjectConfig } from '@/sdk/objects/object-config';
|
||||
import { type PageLayoutConfig } from '@/sdk/page-layouts/page-layout-config';
|
||||
import { type ViewConfig } from '@/sdk/views/view-config';
|
||||
import { type ApplicationConfig, type LogicFunctionConfig } from '@/sdk/define';
|
||||
import { type FrontComponentConfig } from '@/sdk/define/front-component/front-component-config';
|
||||
import { type ObjectConfig } from '@/sdk/define/objects/object-config';
|
||||
import { type PageLayoutConfig } from '@/sdk/define/page-layouts/page-layout-config';
|
||||
import { type ViewConfig } from '@/sdk/define/views/view-config';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { basename, extname, relative } from 'path';
|
||||
import { glob } from 'tinyglobby';
|
||||
@@ -40,10 +37,10 @@ import {
|
||||
import { getInputSchemaFromSourceCode } from 'twenty-shared/logic-function';
|
||||
import { assertUnreachable } from 'twenty-shared/utils';
|
||||
import { addMissingFieldOptionIds } from '@/cli/utilities/build/manifest/utils/add-missing-field-option-ids';
|
||||
import { type PostInstallLogicFunctionConfig } from '@/sdk/logic-functions/post-install-logic-function-config';
|
||||
import { type PreInstallLogicFunctionConfig } from '@/sdk/logic-functions/pre-install-logic-function-config';
|
||||
import { type PostInstallLogicFunctionConfig } from '@/sdk/define/logic-functions/post-install-logic-function-config';
|
||||
import { type PreInstallLogicFunctionConfig } from '@/sdk/define/logic-functions/pre-install-logic-function-config';
|
||||
import { fromRoleConfigToRoleManifest } from '@/cli/utilities/build/manifest/utils/from-role-config-to-role-manifest';
|
||||
import { type RoleConfig } from '@/sdk/roles/role-config';
|
||||
import { type RoleConfig } from '@/sdk/define/roles/role-config';
|
||||
|
||||
const loadSources = async (appPath: string): Promise<string[]> => {
|
||||
return await glob(['**/*.ts', '**/*.tsx'], {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { conditionalAvailabilityTransformPlugin } from '@/cli/utilities/build/common/conditional-availability/conditional-availability-transform-plugin';
|
||||
import { pathExists, remove } from '@/cli/utilities/file/fs-utils';
|
||||
import { type ValidationResult } from '@/sdk';
|
||||
import { type ValidationResult } from '@/sdk/define';
|
||||
import * as esbuild from 'esbuild';
|
||||
import { createRequire } from 'module';
|
||||
import { mkdtemp, writeFile } from 'node:fs/promises';
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { generateDefaultFieldUniversalIdentifier } from '@/cli/utilities/build/manifest/utils/generate-default-field-universal-identifier';
|
||||
import { type ObjectConfig } from '@/sdk/objects/object-config';
|
||||
import { type ObjectConfig } from '@/sdk/define/objects/object-config';
|
||||
|
||||
describe('generateDefaultFieldUniversalIdentifier', () => {
|
||||
it('should generate a unique universal identifier', () => {
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { getDefaultFieldsInObjectFields } from '@/cli/utilities/build/manifest/utils/get-default-fields-in-object-fields';
|
||||
import { getDefaultObjectFields } from '@/cli/utilities/build/manifest/utils/get-default-object-fields';
|
||||
import type { ObjectConfig } from '@/sdk/objects/object-config';
|
||||
import type { ObjectConfig } from '@/sdk/define/objects/object-config';
|
||||
import { getDefaultRelationObjectFields } from '@/cli/utilities/build/manifest/utils/get-default-relation-object-fields';
|
||||
import { type ObjectFieldManifest } from 'twenty-shared/application';
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { getDefaultObjectFields } from '@/cli/utilities/build/manifest/utils/get-default-object-fields';
|
||||
import { generateDefaultFieldUniversalIdentifier } from '@/cli/utilities/build/manifest/utils/generate-default-field-universal-identifier';
|
||||
import type { ObjectConfig } from '@/sdk/objects/object-config';
|
||||
import type { ObjectConfig } from '@/sdk/define/objects/object-config';
|
||||
|
||||
const mockObjectConfig: ObjectConfig = {
|
||||
universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { type RoleConfig } from '@/sdk/roles/role-config';
|
||||
import { type RoleConfig } from '@/sdk/define/roles/role-config';
|
||||
import { type RoleManifest } from 'twenty-shared/application';
|
||||
import { v5 as uuidv5 } from 'uuid';
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import type { ObjectConfig } from '@/sdk/objects/object-config';
|
||||
import type { ObjectConfig } from '@/sdk/define/objects/object-config';
|
||||
import { v5 } from 'uuid';
|
||||
|
||||
const UNIVERSAL_IDENTIFIER_NAMESPACE = '142046f0-4d80-48b5-ad56-26ad410e895c';
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import type { ObjectConfig } from '@/sdk/objects/object-config';
|
||||
import type { ObjectConfig } from '@/sdk/define/objects/object-config';
|
||||
import { getDefaultObjectFields } from '@/cli/utilities/build/manifest/utils/get-default-object-fields';
|
||||
import { getDefaultRelationObjectFields } from '@/cli/utilities/build/manifest/utils/get-default-relation-object-fields';
|
||||
import {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import type { ObjectConfig } from '@/sdk/objects/object-config';
|
||||
import type { ObjectConfig } from '@/sdk/define/objects/object-config';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { generateDefaultFieldUniversalIdentifier } from '@/cli/utilities/build/manifest/utils/generate-default-field-universal-identifier';
|
||||
import { type ObjectFieldManifest } from 'twenty-shared/application';
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import { generateDefaultFieldUniversalIdentifier } from '@/cli/utilities/build/manifest/utils/generate-default-field-universal-identifier';
|
||||
import { RelationType } from '@/sdk';
|
||||
import type { ObjectConfig } from '@/sdk/objects/object-config';
|
||||
import { RelationType } from '@/sdk/define';
|
||||
import type { ObjectConfig } from '@/sdk/define/objects/object-config';
|
||||
import {
|
||||
type FieldManifest,
|
||||
type ObjectFieldManifest,
|
||||
|
||||
@@ -7,7 +7,9 @@ describe('getAgentBaseFile', () => {
|
||||
universalIdentifier: '71e45a58-41da-4ae4-8b73-a543c0a9d3d4',
|
||||
});
|
||||
|
||||
expect(result).toContain("import { defineAgent } from 'twenty-sdk'");
|
||||
expect(result).toContain(
|
||||
"import { defineAgent } from 'twenty-sdk/define';",
|
||||
);
|
||||
expect(result).toContain('export default defineAgent({');
|
||||
expect(result).toContain(
|
||||
'universalIdentifier: MY_AGENT_AGENT_UNIVERSAL_IDENTIFIER',
|
||||
|
||||
@@ -13,7 +13,7 @@ describe('getFieldBaseFile', () => {
|
||||
});
|
||||
|
||||
expect(result).toContain(
|
||||
"import { defineField, FieldType } from 'twenty-sdk'",
|
||||
"import { defineField, FieldType } from 'twenty-sdk/define';",
|
||||
);
|
||||
expect(result).toContain('export default defineField({');
|
||||
expect(result).toContain("name: 'email'");
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ describe('getFrontComponentBaseFile', () => {
|
||||
});
|
||||
|
||||
expect(result).toContain(
|
||||
"import { defineFrontComponent } from 'twenty-sdk'",
|
||||
"import { defineFrontComponent } from 'twenty-sdk/define';",
|
||||
);
|
||||
expect(result).toContain('export default defineFrontComponent({');
|
||||
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ describe('getFunctionBaseFile', () => {
|
||||
});
|
||||
|
||||
expect(result).toContain(
|
||||
"import { defineLogicFunction } from 'twenty-sdk'",
|
||||
"import { defineLogicFunction } from 'twenty-sdk/define';",
|
||||
);
|
||||
expect(result).toContain('export default defineLogicFunction({');
|
||||
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ describe('getNavigationMenuItemBaseFile', () => {
|
||||
});
|
||||
|
||||
expect(result).toContain(
|
||||
"import { defineNavigationMenuItem } from 'twenty-sdk'",
|
||||
"import { defineNavigationMenuItem } from 'twenty-sdk/define';",
|
||||
);
|
||||
expect(result).toContain('export default defineNavigationMenuItem({');
|
||||
expect(result).toContain(
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ describe('getNewObjectFileContent', () => {
|
||||
});
|
||||
|
||||
expect(result).toContain(
|
||||
"import { defineObject, FieldType } from 'twenty-sdk'",
|
||||
"import { defineObject, FieldType } from 'twenty-sdk/define';",
|
||||
);
|
||||
expect(result).toContain('export default defineObject({');
|
||||
expect(result).toContain('export const NAME_FIELD_UNIVERSAL_IDENTIFIER');
|
||||
|
||||
+3
-1
@@ -6,7 +6,9 @@ describe('getPageLayoutBaseFile', () => {
|
||||
name: 'my-layout',
|
||||
});
|
||||
|
||||
expect(result).toContain("import { definePageLayout } from 'twenty-sdk'");
|
||||
expect(result).toContain(
|
||||
"import { definePageLayout } from 'twenty-sdk/define';",
|
||||
);
|
||||
expect(result).toContain('export default definePageLayout({');
|
||||
expect(result).toContain("name: 'my-layout'");
|
||||
expect(result).toContain("title: 'Overview'");
|
||||
|
||||
@@ -7,7 +7,7 @@ describe('getRoleBaseFile', () => {
|
||||
universalIdentifier: '71e45a58-41da-4ae4-8b73-a543c0a9d3d4',
|
||||
});
|
||||
|
||||
expect(result).toContain("import { defineRole } from 'twenty-sdk'");
|
||||
expect(result).toContain("import { defineRole } from 'twenty-sdk/define';");
|
||||
expect(result).toContain('export default defineRole({');
|
||||
|
||||
expect(result).toContain(
|
||||
|
||||
@@ -7,7 +7,9 @@ describe('getSkillBaseFile', () => {
|
||||
universalIdentifier: '71e45a58-41da-4ae4-8b73-a543c0a9d3d4',
|
||||
});
|
||||
|
||||
expect(result).toContain("import { defineSkill } from 'twenty-sdk'");
|
||||
expect(result).toContain(
|
||||
"import { defineSkill } from 'twenty-sdk/define';",
|
||||
);
|
||||
expect(result).toContain('export default defineSkill({');
|
||||
expect(result).toContain(
|
||||
'universalIdentifier: MY_SKILL_SKILL_UNIVERSAL_IDENTIFIER',
|
||||
|
||||
@@ -8,7 +8,7 @@ describe('getViewBaseFile', () => {
|
||||
objectUniversalIdentifier: 'obj-abc-123',
|
||||
});
|
||||
|
||||
expect(result).toContain("import { defineView } from 'twenty-sdk'");
|
||||
expect(result).toContain("import { defineView } from 'twenty-sdk/define';");
|
||||
expect(result).toContain('export default defineView({');
|
||||
expect(result).toContain(
|
||||
"universalIdentifier: '71e45a58-41da-4ae4-8b73-a543c0a9d3d4'",
|
||||
|
||||
@@ -10,7 +10,7 @@ export const getAgentBaseFile = ({
|
||||
}) => {
|
||||
const kebabCaseName = kebabCase(name);
|
||||
|
||||
return `import { defineAgent } from 'twenty-sdk';
|
||||
return `import { defineAgent } from 'twenty-sdk/define';
|
||||
|
||||
export const ${kebabCaseName.toUpperCase().replace(/-/g, '_')}_AGENT_UNIVERSAL_IDENTIFIER =
|
||||
'${universalIdentifier}';
|
||||
|
||||
@@ -18,7 +18,7 @@ export const getFieldBaseFile = ({
|
||||
? `\n description: '${data.description}',`
|
||||
: '';
|
||||
|
||||
return `import { defineField, FieldType } from 'twenty-sdk';
|
||||
return `import { defineField, FieldType } from 'twenty-sdk/define';
|
||||
|
||||
export default defineField({
|
||||
universalIdentifier: '${universalIdentifier}',
|
||||
|
||||
@@ -10,7 +10,7 @@ export const getFrontComponentBaseFile = ({
|
||||
}) => {
|
||||
const kebabCaseName = kebabCase(name);
|
||||
|
||||
return `import { defineFrontComponent } from 'twenty-sdk';
|
||||
return `import { defineFrontComponent } from 'twenty-sdk/define';
|
||||
|
||||
// React component - implement your UI here
|
||||
const Component = () => {
|
||||
|
||||
@@ -10,7 +10,7 @@ export const getLogicFunctionBaseFile = ({
|
||||
}) => {
|
||||
const kebabCaseName = kebabCase(name);
|
||||
|
||||
return `import { defineLogicFunction } from 'twenty-sdk';
|
||||
return `import { defineLogicFunction } from 'twenty-sdk/define';
|
||||
|
||||
// Logic function handler - rename and implement your logic
|
||||
const handler = async (params: {
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ export const getNavigationMenuItemBaseFile = ({
|
||||
// viewUniversalIdentifier: '...',`;
|
||||
}
|
||||
|
||||
return `import { defineNavigationMenuItem } from 'twenty-sdk';
|
||||
return `import { defineNavigationMenuItem } from 'twenty-sdk/define';
|
||||
|
||||
export default defineNavigationMenuItem({
|
||||
universalIdentifier: '${universalIdentifier}',
|
||||
|
||||
@@ -15,7 +15,7 @@ export const getObjectBaseFile = ({
|
||||
universalIdentifier?: string;
|
||||
nameFieldUniversalIdentifier?: string;
|
||||
}) => {
|
||||
return `import { defineObject, FieldType } from 'twenty-sdk';
|
||||
return `import { defineObject, FieldType } from 'twenty-sdk/define';
|
||||
|
||||
export const NAME_FIELD_UNIVERSAL_IDENTIFIER =
|
||||
'${nameFieldUniversalIdentifier}';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
export const getPageLayoutBaseFile = ({ name }: { name: string }) => {
|
||||
return `import { definePageLayout } from 'twenty-sdk';
|
||||
return `import { definePageLayout } from 'twenty-sdk/define';
|
||||
|
||||
export default definePageLayout({
|
||||
universalIdentifier: '${uuidv4()}',
|
||||
|
||||
@@ -10,7 +10,7 @@ export const getRoleBaseFile = ({
|
||||
}) => {
|
||||
const kebabCaseName = kebabCase(name);
|
||||
|
||||
return `import { defineRole } from 'twenty-sdk';
|
||||
return `import { defineRole } from 'twenty-sdk/define';
|
||||
|
||||
export const ${kebabCaseName.toUpperCase().replace(/-/g, '_')}_ROLE_UNIVERSAL_IDENTIFIER =
|
||||
'${universalIdentifier}';
|
||||
|
||||
@@ -10,7 +10,7 @@ export const getSkillBaseFile = ({
|
||||
}) => {
|
||||
const kebabCaseName = kebabCase(name);
|
||||
|
||||
return `import { defineSkill } from 'twenty-sdk';
|
||||
return `import { defineSkill } from 'twenty-sdk/define';
|
||||
|
||||
export const ${kebabCaseName.toUpperCase().replace(/-/g, '_')}_SKILL_UNIVERSAL_IDENTIFIER =
|
||||
'${universalIdentifier}';
|
||||
|
||||
@@ -51,7 +51,7 @@ export const getViewBaseFile = ({
|
||||
],`
|
||||
: defaultFields;
|
||||
|
||||
return `import { defineView } from 'twenty-sdk';
|
||||
return `import { defineView } from 'twenty-sdk/define';
|
||||
|
||||
export default defineView({
|
||||
universalIdentifier: '${universalIdentifier}',
|
||||
|
||||
Reference in New Issue
Block a user