Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
f622ff2
refactor: update button styles and enhance Facebook bot form components
Wlkr123 Aug 9, 2025
512d61c
feat: add waitEvent action and enhance automation components
Wlkr123 Aug 10, 2025
28b0949
Merge branch 'main' of github.com:erxes/erxes-next into automation-up…
Wlkr123 Aug 19, 2025
38291f4
chore: add @types/lodash to package.json and update pnpm-lock.yaml; r…
Wlkr123 Aug 20, 2025
5f2e03b
feat: implement WorkflowActionMapper and enhance WorkflowNode with ac…
Wlkr123 Aug 21, 2025
cba85c9
Merge branch 'main' of github.com:erxes/erxes-next into automation-up…
Wlkr123 Aug 23, 2025
25a29b9
feat: enhance automation module with workflows support
Wlkr123 Aug 25, 2025
e6dd355
feat: enhance automation and segment management features
Wlkr123 Aug 26, 2025
e69065d
feat: integrate AI agent management and training features
Wlkr123 Aug 31, 2025
3f34ea7
Merge branch 'main' of github.com:erxes/erxes-next into automation-up…
Wlkr123 Sep 7, 2025
810600d
chore(dependencies): add xml2js and @types/xml2js to package.json
Wlkr123 Sep 7, 2025
5435c3f
feat(automations): enhance automation builder with new webhook action…
Wlkr123 Sep 13, 2025
2ed30a4
refactor(automations): streamline node components and enhance error h…
Wlkr123 Sep 16, 2025
05b71b6
feat(automations): add webhook endpoint query and enhance automation …
Wlkr123 Sep 20, 2025
975ae24
refactor(automations): update action and trigger components for impro…
Wlkr123 Sep 22, 2025
66db243
refactor(automations): enhance node components and improve type safety
Wlkr123 Sep 23, 2025
676e32b
refactor(automations): enhance action node components and improve con…
Wlkr123 Sep 24, 2025
2ca4179
refactor(automations): enhance manage properties configuration and st…
Wlkr123 Sep 25, 2025
dea152e
refactor(automations): streamline automation components and enhance c…
Wlkr123 Sep 26, 2025
def26b3
refactor(automations): reorganize builder components and enhance conn…
Wlkr123 Sep 28, 2025
edf89d3
chore(dependencies): add helmet and https-proxy-agent to package.json
Wlkr123 Oct 4, 2025
9e053fc
refactor(automations): enhance automation logic and introduce findObj…
Wlkr123 Oct 11, 2025
76d300c
refactor(automations): enhance automation initialization and improve …
Wlkr123 Oct 16, 2025
2d6aa96
refactor(automations): enhance automation initialization and streamli…
Wlkr123 Oct 20, 2025
aa384e7
refactor(config): clear mcpServers configuration and update Facebook …
Wlkr123 Oct 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 1 addition & 5 deletions .cursor/mcp.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
{
"mcpServers": {
"nx-mcp": {
"url": "http://localhost:9216/sse"
}
}
"mcpServers": {}
}
5 changes: 4 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@
"nxConsole.nxWorkspacePath": "",
"typescript.preferences.importModuleSpecifier": "non-relative",
"typescript.preferences.importModuleSpecifierEnding": "minimal",
"typescript.updateImportsOnFileMove.enabled": "always"
"typescript.updateImportsOnFileMove.enabled": "always",
"[plaintext]": {
"editor.defaultFormatter": "lkrms.inifmt"
}
}
22 changes: 21 additions & 1 deletion backend/core-api/src/connectionResolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ import {
loadClass as loadExecutionClass,
} from './modules/automations/db/models/Executions';
import {
AiAgentDocument,
aiAgentSchema,
emailDeliverySchema,
IAutomationDocument,
IAutomationExecutionDocument,
Expand All @@ -156,6 +158,8 @@ import {
notificationConfigSchema,
notificationSchema,
userNotificationSettingsSchema,
aiEmbeddingSchema,
IAiEmbeddingDocument,
} from 'erxes-api-shared/core-modules';

export interface IModels {
Expand Down Expand Up @@ -196,6 +200,8 @@ export interface IModels {
NotificationConfigs: Model<INotificationConfigDocument>;
UserNotificationSettings: Model<IUserNotificationSettingsDocument>;
EmailDeliveries: Model<IEmailDeliveryDocument>;
AiAgents: Model<AiAgentDocument>;
AiEmbeddings: Model<IAiEmbeddingDocument>;
}

export interface IContext extends IMainContext {
Expand Down Expand Up @@ -369,6 +375,20 @@ export const loadClasses = (
IEmailDeliveryDocument,
Model<IEmailDeliveryDocument>
>('email_deliveries', emailDeliverySchema);
models.EmailDeliveries = db.model<
IEmailDeliveryDocument,
Model<IEmailDeliveryDocument>
>('email_deliveries', emailDeliverySchema);

models.AiAgents = db.model<AiAgentDocument, Model<AiAgentDocument>>(
'automations_ai_agents',
aiAgentSchema,
);

models.AiEmbeddings = db.model<
IAiEmbeddingDocument,
Model<IAiEmbeddingDocument>
>('ai_embeddings', aiEmbeddingSchema);

const db_name = db.name;

Expand All @@ -383,5 +403,5 @@ export const loadClasses = (
};

export const generateModels = createGenerateModels<IModels>(loadClasses, {
ignoreModels: ['logs', 'automations_executions'],
ignoreModels: ['logs', 'automations_executions', 'ai_embeddings'],
});
6 changes: 4 additions & 2 deletions backend/core-api/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ import {
leaveErxesGateway,
} from 'erxes-api-shared/utils';

import './meta/automations';
import { initAutomation } from './meta/automations';
import { generateModels } from './connectionResolvers';
import { documents } from './meta/documents';
import { moduleObjects } from './meta/permission';
import { tags } from './meta/tags';
import './segments';
import { initSegmentCoreProducers } from './segments';
import * as path from 'path';
import rateLimit from 'express-rate-limit';

Expand Down Expand Up @@ -119,6 +119,8 @@ httpServer.listen(port, async () => {
documents,
},
});
await initAutomation(app);
await initSegmentCoreProducers(app);
});

// GRACEFULL SHUTDOWN
Expand Down
230 changes: 116 additions & 114 deletions backend/core-api/src/meta/automations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
} from 'erxes-api-shared/core-modules';
import { generateModels, IModels } from '../connectionResolvers';
import { sendTRPCMessage } from 'erxes-api-shared/utils';
import { Express } from 'express';

const getRelatedValue = async (
models: IModels,
Expand Down Expand Up @@ -123,126 +124,127 @@ const getItems = async (
return filter ? model.find(filter) : [];
};

export default startAutomations('core', {
receiveActions: async (
{ subdomain },
{ action, execution, triggerType, actionType },
) => {
const models = await generateModels(subdomain);

if (actionType === 'set-property') {
const { module, rules } = action.config;

const relatedItems = await getItems(
subdomain,
module,
execution,
triggerType,
);

const result = await setProperty({
export const initAutomation = (app: Express) =>
startAutomations(app, 'core', {
receiveActions: async (
{ subdomain },
{ action, execution, triggerType, actionType },
) => {
const models = await generateModels(subdomain);

if (actionType === 'set-property') {
const { module, rules } = action.config;

const relatedItems = await getItems(
subdomain,
module,
execution,
triggerType,
);

const result = await setProperty({
models,
subdomain,
getRelatedValue,
module: module.includes('lead') ? 'core:customer' : module,
rules,
execution,
relatedItems,
triggerType,
});
return { result };
}
return { result: 'Hello World Core' };
},
replacePlaceHolders: async ({ subdomain }, { data }) => {
const { target, config, relatedValueProps } = data || {};
const models = await generateModels(subdomain);

return await replacePlaceHolders<IModels>({
models,
subdomain,
getRelatedValue,
module: module.includes('lead') ? 'core:customer' : module,
rules,
execution,
relatedItems,
triggerType,
target,
actionData: config,
customResolver: {
resolver: getRelatedValue,
props: relatedValueProps,
},
});
return { result };
}
return { result: 'Hello World Core' };
},
replacePlaceHolders: async ({ subdomain }, { data }) => {
const { target, config, relatedValueProps } = data || {};
const models = await generateModels(subdomain);

return await replacePlaceHolders<IModels>({
models,
subdomain,
target,
actionData: config,
customResolver: {
resolver: getRelatedValue,
props: relatedValueProps,
},
});
},
getRecipientsEmails: async ({ subdomain }, { data }) => {
const models = await generateModels(subdomain);
const { type, config } = data;
},
getRecipientsEmails: async ({ subdomain }, { data }) => {
const models = await generateModels(subdomain);
const { type, config } = data;

const ids = config[`${type}Ids`];
const ids = config[`${type}Ids`];

const commonFilter = {
_id: { $in: Array.isArray(ids) ? ids : [ids] },
};
const commonFilter = {
_id: { $in: Array.isArray(ids) ? ids : [ids] },
};

if (type === 'user') {
const result = await models.Users.find(commonFilter).distinct('email');
if (type === 'user') {
const result = await models.Users.find(commonFilter).distinct('email');

return result;
}
return result;
}

const CONTACT_TYPES = {
lead: {
model: models.Customers,
filter: { ...commonFilter },
},
customer: {
model: models.Customers,
filter: {
...commonFilter,
const CONTACT_TYPES = {
lead: {
model: models.Customers,
filter: { ...commonFilter },
},
},
company: {
model: models.Companies,
filter: { ...commonFilter },
},
};

const { model, filter } = CONTACT_TYPES[type];

return await model.find(filter).distinct('primaryEmail');
},
constants: {
triggers: [
{
type: 'core:user',
icon: 'Users',
label: 'Team member',
description:
'Start with a blank workflow that enrolls and is triggered off team members',
},
{
type: 'core:customer',
icon: 'UsersGroup',
label: 'Customer',
description:
'Start with a blank workflow that enrolls and is triggered off Customers',
},
{
type: 'core:lead',
icon: 'UsersGroup',
label: 'Lead',
description:
'Start with a blank workflow that enrolls and is triggered off Leads',
},
{
type: 'core:company',
icon: 'Building',
label: 'Company',
description:
'Start with a blank workflow that enrolls and is triggered off company',
},
{
type: 'core:form_submission',
icon: 'Forms',
label: 'Form submission',
description:
'Start with a blank workflow that enrolls and is triggered off form submission',
},
],
},
});
customer: {
model: models.Customers,
filter: {
...commonFilter,
},
},
company: {
model: models.Companies,
filter: { ...commonFilter },
},
};

const { model, filter } = CONTACT_TYPES[type];

return await model.find(filter).distinct('primaryEmail');
},
constants: {
triggers: [
{
type: 'core:user',
icon: 'Users',
label: 'Team member',
description:
'Start with a blank workflow that enrolls and is triggered off team members',
},
{
type: 'core:customer',
icon: 'UsersGroup',
label: 'Customer',
description:
'Start with a blank workflow that enrolls and is triggered off Customers',
},
{
type: 'core:lead',
icon: 'UsersGroup',
label: 'Lead',
description:
'Start with a blank workflow that enrolls and is triggered off Leads',
},
{
type: 'core:company',
icon: 'Building',
label: 'Company',
description:
'Start with a blank workflow that enrolls and is triggered off company',
},
{
type: 'core:form_submission',
icon: 'Forms',
label: 'Form submission',
description:
'Start with a blank workflow that enrolls and is triggered off form submission',
},
],
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ export const authMutations = {
assertSaasEnvironment();
const WORKOS_API_KEY = getEnv({ name: 'WORKOS_API_KEY', subdomain });

const CORE_DOMAIN = getEnv({ name: 'CORE_DOMAIN', subdomain });

const workosClient = new WorkOS(WORKOS_API_KEY);

const state = await jwt.sign(
Expand All @@ -162,7 +164,7 @@ export const authMutations = {

const authorizationURL = workosClient.sso.getAuthorizationUrl({
provider: 'GoogleOAuth',
redirectUri: getCallbackRedirectUrl(subdomain, 'sso-callback'),
redirectUri: `${CORE_DOMAIN}/saas-sso-callback`,

clientId: getEnv({ name: 'WORKOS_PROJECT_ID', subdomain }),
state,
Expand Down
Loading
Loading