1635 extensibilitytwenty cli app vars (#15143)

- Update twenty-cli to support application env variable definition
- Update twenty-server to create a new `core.applicationVariable` entity
to store env variables and provide env var when executing serverless
function
- Update twenty-front to support application environment variable value
setting

<img width="1044" height="660" alt="image"
src="https://github.com/user-attachments/assets/24c3d323-5370-4a80-8174-fc4653cc3c22"
/>

<img width="1178" height="662" alt="image"
src="https://github.com/user-attachments/assets/c124f423-8ed8-4246-ae5b-a9bd6672c7dc"
/>

<img width="1163" height="823" alt="image"
src="https://github.com/user-attachments/assets/fb7425a3-facc-4895-a5eb-8a8e278e0951"
/>

<img width="1087" height="696" alt="image"
src="https://github.com/user-attachments/assets/113da8a2-5590-433c-b1b3-5ed3137f24ca"
/>

<img width="1512" height="715" alt="image"
src="https://github.com/user-attachments/assets/1d2110b7-301d-4f21-a45c-ddd54d6e3391"
/>

<img width="1287" height="581" alt="image"
src="https://github.com/user-attachments/assets/353b16c6-0527-444c-87d6-51447a96cbc7"
/>
This commit is contained in:
martmull
2025-10-17 10:54:38 +02:00
committed by GitHub
parent 54baa47fbb
commit d2e7f2a910
58 changed files with 1305 additions and 359 deletions
@@ -0,0 +1,15 @@
# Set environment values for your application here.
# Use the format: KEY=value
#
# These variables are automatically loaded when running your serverless functions.
# You can access them directly in your code using:
# const myValue = process.env.KEY;
#
# To make these variables available to your application,
# add them to package.json "env" key. This "env" key defines all
# environment variables that will be provided to your serverless
# functions at runtime.
#
# Example:
# API_TOKEN=your-api-token
# TIMEOUT_MS=3000
@@ -1 +1,2 @@
.yarn/install-state.gz
.env
@@ -6,5 +6,8 @@
"npm": "please-use-yarn",
"yarn": ">=4.0.2"
},
"packageManager": "yarn@4.9.2"
"packageManager": "yarn@4.9.2",
"devDependencies": {
"@types/node": "^24.7.2"
}
}
@@ -1,3 +1,4 @@
import dotenv from 'dotenv';
import assert from 'assert';
import * as fs from 'fs-extra';
import * as path from 'path';
@@ -111,12 +112,44 @@ export const loadManifest = async (
manifest: AppManifest;
}> => {
const packageJsonPath = await findPathFile(appPath, 'package.json');
const rawPackageJson = await parseJsoncFile(packageJsonPath);
const yarnLockPath = await findPathFile(appPath, 'yarn.lock');
const rawYarnLock = await fs.readFile(yarnLockPath, 'utf8');
await validateSchema('appManifest', rawPackageJson, packageJsonPath);
let envFile = '';
try {
const envFilePath = await findPathFile(appPath, '.env');
envFile = await fs.readFile(envFilePath, 'utf8');
} catch {
// Allow missing .env
}
const envVariables = dotenv.parse(envFile);
const packageJsonEnv = rawPackageJson.env || {};
for (const key of Object.keys(envVariables)) {
if (packageJsonEnv[key]) {
packageJsonEnv[key] = {
isSecret: false,
...packageJsonEnv[key],
value: envVariables[key],
};
} else {
throw new Error(
`Environment variable "${key}" is defined in .env but missing from package.json. Please add it to the "env" section in package.json.`,
);
}
}
const packageJson = { ...rawPackageJson, env: packageJsonEnv };
await validateSchema('appManifest', packageJson, packageJsonPath);
const agents = await loadCoreEntity(
path.join(appPath, 'agents'),
@@ -134,10 +167,10 @@ export const loadManifest = async (
);
return {
packageJson: rawPackageJson,
packageJson,
yarnLock: rawYarnLock,
manifest: {
...rawPackageJson,
...packageJson,
agents,
objects,
serverlessFunctions,