Files
twenty/packages/twenty-apps/community/rollup-engine
MarieandGitHub 96aef62ae4 [Apps] Get rid of .yarn binaries in apps (#17306)
Fixes https://github.com/twentyhq/core-team-issues/issues/1956

**Problem**
Within an app, the `.yarn/releases/` folder contains executable Yarn
binaries that run when executing any yarn command (`.yarnrc` file
indicates yarn path to be `.yarn/releases/yarn-4.9.2.cjs `.)
This is a supply chain attack vector: a malicious actor could submit a
PR with a compromised `yarn-4.9.2.cjs binary`, which would execute
arbitrary code on developers' machines or CI systems.

**Fix**
Actually, thanks to Corepack, we don't need to store and execute this
binary.
Corepack can be seen as the manager of a package manager: in
`package.json` we indicate a packageManager version like
`"packageManager": "yarn@4.9.2"`, and when executing `yarn` Corepack
will securely fetch the verified version from npm, avoiding the risk of
executing a compromised binary committed to the repository. This was
already in our app's package.json template but we were not using it!

We can now
- remove the folder containing the binary from our app template
base-application (that is scaffolded when creating an app through cli),
`.yarn/releases/`, and remove `yarnPath: .yarn/releases/yarn-4.9.2.cjs`
from its .yarnrc
- remove them from the community apps that were already published in the
repo
- add .yarn to gitignore 

**Tested**
This has been tested and works for app created in the repo, outside the
repo, and existing apps in the repo
2026-01-21 17:23:16 +00:00
..
2025-11-21 14:10:51 +01:00
2025-11-21 14:10:51 +01:00
2025-11-21 14:10:51 +01:00
2025-11-21 14:10:51 +01:00

Rollup engine

General-purpose rollup engine for Twenty workspaces. The bundle ships a serverless function that materialises aggregations from a child object onto a parent object. The default configuration targets Opportunity → Company rollups.

Requirements

  • twenty-cli npm install -g twenty-cli
  • an API key with access to your workspace. Generate one at https://twenty.com/settings/api-webhooks.
  • Node 20+ (only required if you plan to run the optional smoke test locally).

Metadata prerequisites

  • Opportunity is a standard object, no extra provisioning required.
  • Add these fields to the company object (API names shown):
    • totalPipelineAmount (Currency)
    • totalOpportunityCount (Number)
    • wonPipelineAmount (Currency)
    • wonOpportunityCount (Number)
    • openPipelineAmount (Currency)
    • openOpportunityCount (Number)
    • lastOpportunityCloseDate (Date)
  • To script the setup, export TWENTY_API_KEY (and TWENTY_METADATA_BASE_URL if you are not targeting http://localhost:3000/rest/metadata) and run yarn setup:metadata. The helper script calls the Metadata API to ensure each field exists on the Company object, skipping anything already provisioned.

Create the fields before syncing so PATCH requests succeed.

Quick start

  1. Deploy the app

    twenty auth login
    cd rollup-engine
    twenty app sync
    
  2. Configure environment variables

    • Open Settings → Apps → Rollup engine → Configuration.
    • Provide values for the manifest-defined keys:
      • TWENTY_API_KEY (required secret; create it in Twenty → Settings → API & Webhooks).
      • TWENTY_API_BASE_URL (optional; leave blank to use https://app.twenty.com/rest).
      • ROLLUP_ENGINE_CONFIG (optional JSON override; leave blank to use the baked-in config).
    • Save the configuration. Changes are applied immediately—no redeploy required.
  3. Verify via the Test panel

    • Still on the app page, select Test.

    • Paste a JSON payload with the company ID you want to validate:

      {
        "trigger": { "type": "databaseEvent", "eventName": "opportunity.updated" },
        "record": { "companyId": "YOUR_COMPANY_ID" },
        "opportunity": { "companyId": "YOUR_COMPANY_ID" }
      }
      
    • Click Run. You should see a success summary and the companys rollup fields updating.

  4. Trigger live rollups

    • Any Opportunity create/update/delete (or the nightly cron) now feeds into the Company metrics.

Runtime configuration

  • serverlessFunctions/calculaterollups/src/rollupConfig.ts holds the baked-in defaults. Override them by setting ROLLUP_ENGINE_CONFIG (aliases: ROLLUPS_CONFIG, CALCULATE_ROLLUPS_CONFIG) to a JSON array in the Configuration UI.
  • config/templates/opportunity-to-company.json matches the default rollups shipped with the bundle. Copy it, tweak the object/field names you need, and paste the edited JSON into ROLLUP_ENGINE_CONFIG.
  • filters[].dynamicValue currently supports "startOfYear" (UTC midnight on the first day of the current calendar year).

Default Opportunity → Company rollups

Parent field Suggested type Description
totalPipelineAmount Currency (amountMicros, currencyCode) Sum of positive-valued Opportunities linked to the Company.
totalOpportunityCount Number Count of Opportunities linked to the Company.
wonPipelineAmount Currency (amountMicros, currencyCode) Sum of Opportunities where stage === "CUSTOMER".
wonOpportunityCount Number Count of Opportunities where stage === "CUSTOMER".
openPipelineAmount Currency (amountMicros, currencyCode) Sum of Opportunities where stage !== "CUSTOMER".
openOpportunityCount Number Count of Opportunities where stage !== "CUSTOMER".
lastOpportunityCloseDate Date Most recent closeDate (ISO date).

Assumptions:

  • Opportunities expose companyId, amount.amountMicros, amount.currencyCode, stage, and closeDate. Adjust filters or fields as needed via the JSON config.
  • Amount totals are stored in micros (integers) to align with Twentys composite currency fields.

Optional local smoke test

Run this if you want to exercise the aggregation logic without calling the live API.

cd rollup-engine
yarn install
yarn smoke

The smoke script replaces fetch with an in-memory mock, executes the rollup function using sample Opportunity data, and asserts the PATCH payload that would be sent to Twenty.

Troubleshooting

  • Test your function reports mainFile.main is not a function: delete the app (twenty app delete) and sync it again (twenty app sync) to clear any stale bundle.
  • status: "error", message: "Unable to parse rollup configuration override": confirm that ROLLUP_ENGINE_CONFIG contains valid JSON or leave it blank to fall back to the baked-in defaults.
  • No company updates after configuring everything: double-check the Company field API names, confirm the Opportunity records have amount.amountMicros > 0, and use the Test panel to inspect the summary details/logs.