1573 extensibility twenty cli handle custom layers for serverless functions of applications (#14779)

- allow specific layers for serverless functions
- add a serverlessFunctionLayer table
- sync application layer
This commit is contained in:
martmull
2025-09-30 16:47:49 +02:00
committed by GitHub
parent 5560d823c3
commit 1938202780
42 changed files with 748 additions and 108 deletions
@@ -23,6 +23,12 @@ describe('app-template', () => {
label: 'My Test App',
description: 'A Twenty application for my-test-app',
version: '0.0.1',
engines: {
node: '^24.5.0',
npm: 'please-use-yarn',
yarn: '>=4.0.2',
},
license: 'MIT',
});
});
@@ -1,17 +1,24 @@
import * as fs from 'fs-extra';
import * as path from 'path';
import { AppManifest, CoreEntityManifest } from '../types/config.types';
import {
AppManifest,
CoreEntityManifest,
PackageJson,
} from '../types/config.types';
import { parseJsoncFile } from './jsonc-parser';
import { validateSchema } from '../utils/schema-validator';
const findPackageJsonFile = async (appPath: string): Promise<string> => {
const jsonPath = path.join(appPath, 'package.json');
const findPathFile = async (
appPath: string,
fileName: string,
): Promise<string> => {
const jsonPath = path.join(appPath, fileName);
if (await fs.pathExists(jsonPath)) {
return jsonPath;
}
throw new Error(`package.json not found in ${appPath}`);
throw new Error(`${fileName} not found in ${appPath}`);
};
const loadCoreEntity = async (
@@ -40,10 +47,19 @@ const loadCoreEntity = async (
return coreEntities;
};
export const loadManifest = async (appPath: string): Promise<AppManifest> => {
const packageJsonPath = await findPackageJsonFile(appPath);
export const loadManifest = async (
appPath: string,
): Promise<{
packageJson: PackageJson;
yarnLock: string;
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('app-manifest', rawPackageJson, packageJsonPath);
const agents = await loadCoreEntity(
@@ -57,8 +73,12 @@ export const loadManifest = async (appPath: string): Promise<AppManifest> => {
);
return {
...rawPackageJson,
agents,
objects,
packageJson: rawPackageJson,
yarnLock: rawYarnLock,
manifest: {
...rawPackageJson,
agents,
objects,
},
};
};
+6 -2
View File
@@ -6,10 +6,14 @@ export const syncApp = async (
appPath: string,
apiService: ApiService,
): Promise<any> => {
const manifest = await loadManifest(appPath);
const { manifest, packageJson, yarnLock } = await loadManifest(appPath);
try {
const result = await apiService.syncApplication(manifest);
const result = await apiService.syncApplication({
manifest,
packageJson,
yarnLock,
});
if (result.success) {
console.log(chalk.green('✅ Application synced successfully'));
@@ -15,7 +15,13 @@ export const createBasePackageJson = (
.split('-')
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(' '),
engines: {
node: '^24.5.0',
npm: 'please-use-yarn',
yarn: '>=4.0.2',
},
description,
license: 'MIT',
version: '0.0.1',
};
};