Add triggers to cli sync (#14828)

This commit is contained in:
Weiko
2025-10-02 02:08:38 +02:00
committed by GitHub
parent 6fdd7894a1
commit 3f9c315d93
7 changed files with 510 additions and 36 deletions
@@ -4,13 +4,14 @@ import inquirer from 'inquirer';
import path from 'path';
import { v4 } from 'uuid';
import { resolveAppPath } from '../utils/app-path-resolver';
import { writeJsoncFile } from '../utils/jsonc-parser';
import { parseJsoncFile, writeJsoncFile } from '../utils/jsonc-parser';
import { getSchemaUrls } from '../utils/schema-validator';
enum SyncableEntity {
AGENT = 'agent',
OBJECT = 'object',
SERVERLESS_FUNCTION = 'serverlessFunction',
TRIGGER = 'trigger',
}
const getFolderName = (entity: SyncableEntity) => {
@@ -40,6 +41,11 @@ export class AppAddCommand {
process.exit(1);
}
if (entity === SyncableEntity.TRIGGER) {
await this.addTriggerToServerlessFunction(appPath);
return;
}
const entityName = await this.getEntityName(entity);
const entityData = await this.getEntityToCreateData(entity, entityName);
@@ -97,6 +103,7 @@ export class AppAddCommand {
SyncableEntity.AGENT,
SyncableEntity.OBJECT,
SyncableEntity.SERVERLESS_FUNCTION,
SyncableEntity.TRIGGER,
],
},
]);
@@ -184,4 +191,123 @@ export class AppAddCommand {
return entityToCreateData;
}
private async addTriggerToServerlessFunction(appPath: string) {
const serverlessFunctionsDir = path.join(appPath, 'serverlessFunctions');
if (!(await fs.pathExists(serverlessFunctionsDir))) {
console.error(chalk.red('No serverless functions found in this app'));
process.exit(1);
}
const serverlessFunctions = await fs.readdir(serverlessFunctionsDir);
if (serverlessFunctions.length === 0) {
console.error(chalk.red('No serverless functions found in this app'));
process.exit(1);
}
const { serverlessFunctionName } = await inquirer.prompt([
{
type: 'list',
name: 'serverlessFunctionName',
message: 'Select a serverless function to add a trigger to:',
choices: serverlessFunctions,
},
]);
const { triggerType } = await inquirer.prompt([
{
type: 'list',
name: 'triggerType',
message: 'Select the type of trigger:',
choices: ['databaseEvent', 'cron'],
},
]);
let triggerData: any;
if (triggerType === 'databaseEvent') {
triggerData = await this.createDatabaseEventTrigger();
} else if (triggerType === 'cron') {
triggerData = await this.createCronTrigger();
}
const manifestPath = path.join(
serverlessFunctionsDir,
serverlessFunctionName,
'serverlessFunction.manifest.jsonc',
);
const manifest = await parseJsoncFile(manifestPath);
if (!manifest.triggers) {
manifest.triggers = [];
}
manifest.triggers.push(triggerData);
await writeJsoncFile(manifestPath, manifest);
console.log(
chalk.green(`✅ Trigger added successfully to ${serverlessFunctionName}`),
);
}
private async createDatabaseEventTrigger() {
const uuid = v4();
const { eventName } = await inquirer.prompt([
{
type: 'input',
name: 'eventName',
message: 'Enter the database event name (e.g., company.created):',
validate: (input) => {
if (input.length === 0) {
return 'Event name is required';
}
if (!/^[a-zA-Z]+\.(created|updated|deleted)$/.test(input)) {
return 'Event name must be in format: objectName.(created|updated|deleted)';
}
return true;
},
},
]);
return {
universalIdentifier: uuid,
type: 'databaseEvent',
eventName,
};
}
private async createCronTrigger() {
const uuid = v4();
const { schedule } = await inquirer.prompt([
{
type: 'input',
name: 'schedule',
message: 'Enter the cron schedule (e.g., 0 9 * * * for daily at 9 AM):',
validate: (input) => {
if (input.length === 0) {
return 'Schedule is required';
}
const parts = input.trim().split(/\s+/);
if (parts.length < 5 || parts.length > 6) {
return 'Cron schedule must have 5 or 6 fields (e.g., 0 9 * * *)';
}
return true;
},
},
]);
return {
universalIdentifier: uuid,
type: 'cron',
schedule,
};
}
}