## Summary
Logic-function bundles produced by the SDK CLI were ~1.2 MB each (source
maps ~3.1 MB) because esbuild was inlining `twenty-sdk/define` and its
transitive dependencies (zod + locales, twenty-shared, etc.). Those
`define*` factories are pure build-time metadata used only by the
manifest extractor — the Lambda runtime only ever invokes
`default.config.handler`, so the factories are dead weight at runtime.
This PR shrinks the bundles to ~9.5 KB each (~99% reduction) without
changing runtime behaviour.
## What changes
- **Stub `twenty-sdk/define` at user-app build time.** New esbuild
plugin
(`packages/twenty-sdk/src/cli/utilities/build/common/plugins/stub-twenty-sdk-define.plugin.ts`)
intercepts every import of `twenty-sdk/define` during user-app builds
and replaces it with a tiny virtual module:
- Factory functions (`defineLogicFunction`,
`definePostInstallLogicFunction`, …) become `(config) => ({ success:
true, config, errors: [] })`.
- Enums and helpers become `Proxy`-based no-ops.
- Wired into both the one-shot build (`build-application.ts`) and the
watcher (`esbuild-watcher.ts`), for logic functions and front
components.
- **New runtime barrel `twenty-sdk/logic-function`.** Re-exports only
the types logic-function authors need (`InstallPayload`, `RoutePayload`,
`CronPayload`, `DatabaseEventPayload`, `LogicFunctionConfig`,
`InputJsonSchema`, …). Compiled `.mjs` is 36 bytes. Wired into Vite,
Rollup `.d.ts` bundling, `package.json#exports`, and `typesVersions`.
- **Lint enforcement.** Added an oxlint `no-restricted-imports` rule
that forbids `twenty-shared` / `twenty-shared/*` imports from
`**/*.logic-function.ts` and `**/logic-functions/**/*.ts`, with a help
message pointing at the new barrel. Applied to the `create-twenty-app`
template and to `github-connector`, `hello-world`, `postcard`.
- **Migrated existing sources.** All logic-function files across
`community/{github-connector, apollo-enrich}`, `examples/{hello-world,
postcard}`, and `internal/{twenty-for-twenty, self-hosting, exa}` now
import types from `twenty-sdk/logic-function` instead of
`twenty-sdk/define` or `twenty-shared/*`. Renamed leftover
`InstallLogicFunctionPayload` references to `InstallPayload`.
## Why this is safe
- `define*` exports from `twenty-sdk/define` are metadata factories
whose call expressions are statically inspected by the manifest
extractor (`manifest-extract-config.ts`). They're never evaluated at
runtime — the Lambda executor only walks `default.config.handler`
(`logic-function-drivers/constants/executor/index.mjs`).
- The stub keeps the same call shape (`{ success, config, errors }`), so
any logic-function module that re-exports
`defineX(config).config.handler` still resolves to the user's handler at
runtime.
- Front-component bundles are unaffected by the stub because the
pre-existing JSX transform plugin
(`jsx-transform-to-remote-dom-worker-format-plugin.ts`) unwraps
`defineFrontComponent(...)` earlier in the pipeline. That's intentional
— front-component bloat is React/Preact, not in scope here.
## Measurements (github-connector)
| Asset | Before | After |
|---|---|---|
| `*.logic-function.mjs` | ~1.2 MB | ~9.5 KB |
| `*.logic-function.mjs.map` | ~3.1 MB | ~22 KB |
137 lines
3.5 KiB
JSON
137 lines
3.5 KiB
JSON
{
|
|
"name": "twenty-sdk",
|
|
"version": "2.1.0",
|
|
"sideEffects": false,
|
|
"bin": {
|
|
"twenty": "dist/cli.cjs"
|
|
},
|
|
"files": [
|
|
"dist",
|
|
"README.md",
|
|
"package.json"
|
|
],
|
|
"scripts": {
|
|
"build": "npx rimraf dist && npx vite build"
|
|
},
|
|
"keywords": [
|
|
"twenty",
|
|
"cli",
|
|
"sdk",
|
|
"crm",
|
|
"application",
|
|
"development"
|
|
],
|
|
"exports": {
|
|
"./billing": {
|
|
"types": "./dist/billing/index.d.ts",
|
|
"import": "./dist/billing/index.mjs",
|
|
"require": "./dist/billing/index.cjs"
|
|
},
|
|
"./define": {
|
|
"types": "./dist/define/index.d.ts",
|
|
"import": "./dist/define/index.mjs",
|
|
"require": "./dist/define/index.cjs"
|
|
},
|
|
"./front-component": {
|
|
"types": "./dist/front-component/index.d.ts",
|
|
"import": "./dist/front-component/index.mjs",
|
|
"require": "./dist/front-component/index.cjs"
|
|
},
|
|
"./logic-function": {
|
|
"types": "./dist/logic-function/index.d.ts",
|
|
"import": "./dist/logic-function/index.mjs",
|
|
"require": "./dist/logic-function/index.cjs"
|
|
},
|
|
"./ui": {
|
|
"types": "./dist/ui/index.d.ts",
|
|
"import": "./dist/ui/index.mjs",
|
|
"require": "./dist/ui/index.cjs"
|
|
},
|
|
"./cli": {
|
|
"types": "./dist/cli/operations/index.d.ts",
|
|
"import": "./dist/operations.mjs",
|
|
"require": "./dist/operations.cjs"
|
|
},
|
|
"./front-component-renderer": {
|
|
"types": "./dist/front-component-renderer/index.d.ts",
|
|
"import": "./dist/front-component-renderer.mjs",
|
|
"require": "./dist/front-component-renderer.cjs"
|
|
},
|
|
"./front-component-renderer/build": {
|
|
"types": "./dist/front-component-renderer/build/index.d.ts",
|
|
"import": "./dist/front-component-renderer/build.mjs",
|
|
"require": "./dist/front-component-renderer/build.cjs"
|
|
}
|
|
},
|
|
"license": "AGPL-3.0",
|
|
"dependencies": {
|
|
"@genql/cli": "^3.0.3",
|
|
"@genql/runtime": "^2.10.0",
|
|
"@sniptt/guards": "^0.2.0",
|
|
"axios": "^1.13.5",
|
|
"chalk": "^5.3.0",
|
|
"chokidar": "^4.0.0",
|
|
"commander": "^12.0.0",
|
|
"dotenv": "^16.4.0",
|
|
"esbuild": "^0.25.0",
|
|
"graphql": "^16.8.1",
|
|
"graphql-sse": "^2.5.4",
|
|
"ink": "^6.8.0",
|
|
"inquirer": "^10.0.0",
|
|
"jsonc-parser": "^3.2.0",
|
|
"preact": "^10.28.3",
|
|
"react": "^19.0.0",
|
|
"react-dom": "^19.0.0",
|
|
"tinyglobby": "^0.2.15",
|
|
"twenty-client-sdk": "workspace:*",
|
|
"typescript": "^5.9.2",
|
|
"uuid": "^13.0.0",
|
|
"vite": "^7.0.0",
|
|
"vite-tsconfig-paths": "^4.2.1",
|
|
"zod": "^4.1.11"
|
|
},
|
|
"devDependencies": {
|
|
"@prettier/sync": "^0.5.2",
|
|
"@types/inquirer": "^9.0.0",
|
|
"@types/node": "^24.0.0",
|
|
"@types/react": "^19.0.0",
|
|
"@types/react-dom": "^19.0.0",
|
|
"rollup-plugin-dts": "^6.4.1",
|
|
"ts-morph": "^25.0.0",
|
|
"tsx": "^4.7.0",
|
|
"twenty-shared": "workspace:*",
|
|
"twenty-ui": "workspace:*",
|
|
"vite-plugin-dts": "^4.5.4",
|
|
"wait-on": "^7.2.0"
|
|
},
|
|
"engines": {
|
|
"node": "^24.5.0",
|
|
"yarn": "^4.0.2"
|
|
},
|
|
"typesVersions": {
|
|
"*": {
|
|
"define": [
|
|
"dist/define/index.d.ts"
|
|
],
|
|
"front-component": [
|
|
"dist/front-component/index.d.ts"
|
|
],
|
|
"logic-function": [
|
|
"dist/logic-function/index.d.ts"
|
|
],
|
|
"cli": [
|
|
"dist/cli/operations/index.d.ts"
|
|
],
|
|
"ui": [
|
|
"dist/ui/index.d.ts"
|
|
],
|
|
"front-component-renderer": [
|
|
"dist/front-component-renderer/index.d.ts"
|
|
],
|
|
"front-component-renderer/build": [
|
|
"dist/front-component-renderer/build/index.d.ts"
|
|
]
|
|
}
|
|
}
|
|
}
|