Skip to content

Commit

Permalink
refactor(root): Rename Echo to Bridge (#6003)
Browse files Browse the repository at this point in the history
  • Loading branch information
rifont authored Jul 7, 2024
1 parent edf7c23 commit 8f0ef99
Show file tree
Hide file tree
Showing 82 changed files with 516 additions and 467 deletions.
2 changes: 1 addition & 1 deletion .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -654,7 +654,7 @@
"tailwindcss",
"focusable",
"textareas",
"echoterminal"
"frameworkterminal"
],
"flagWords": [],
"patterns": [
Expand Down
2 changes: 1 addition & 1 deletion .source
70 changes: 25 additions & 45 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ With Novu, you can create custom workflows and define conditions for each channe
To get started, type the following command in your Terminal.

```bash
npx novu-labs@latest echo
npx novu@latest dev
```

## 📚 Table Of Contents
Expand All @@ -90,54 +90,34 @@ npx novu-labs@latest echo

## Notification Workflows as Code

For API documentation and reference, please visit [Echo API Reference](https://docs.novu.co/framework/quickstart?utm_campaign=github-readme).
For API documentation and reference, please visit our [API Reference](https://docs.novu.co/getting-started/introduction?utm_campaign=github-readme).

```ts

client.workflow('comment-on-post', async ({step, subscriber}) => {
const inAppResponse = await step.inApp('in-app-step', async (controls) => {
return {
body: renderReactComponent(controls)
};
}, {
controlSchema: {
// ...JSON Schema or ZOD/Ajv/Class Validators definition
}
import { workflow, CronExpression } from '@novu/framework';
import { z } from 'zod';
import { render } from '@react-email/render';

const commentWorkflow = workflow('comment-workflow', async (event) => {
const digest = await event.step.digest('digest-comments', (controls) => ({
cron: controls.schedule
}), { controlSchema: z.object({ schedule: z.nativeEnum(CronExpression) }) });

await event.step.email('digest-email', async (controls) => ({
subject: controls.subject,
body: render(<WeeklyDigestEmail { ...controls } events = { digest.events } />)
}), {
skip: () => !digest.events.length,
controlSchema: z.object({
subject: z.string().default('Hi {{subscriber.firstName}} - Acme Comments'),
openAiModel: z.enum(['gpt-3.5-turbo', 'gpt-4o']).default('gpt-4o'),
aiPrompt: z.string().default('Produce a concise comment digest'),
})
});
}, { payloadSchema: z.object({ name: z.string(), comment: z.string() }) });

// Novu Worker Engine will manage the state and durability of each step in isolation
const { events } = await step.digest('1 day');

await step.email('email-step', async () => {
return {
subject: 'E-mail Subject',
body: renderReactEmail(<ReactEmailComponent events={digestedEvents} />);
}
}, {
// Step-level controls defined in code and controlled in the novu Cloud UI by a Non-Technical Team member
controlSchema: {
// ...JSON Schema
},
providers: {
sendgrid: async (controls) => {
// Echo runs as part of your application, so you have access to your database or resources

return {
to: email,
ipPoolName: 'custom-pool'
};
}
},
skip: () => {
// Write custom skip logic
return inAppResponse.seen || subscriber.isOnline;
}
});
// Define your workflow trigger payload using json schema and custom validation;
}, {
payloadSchema: {
// ...JSON Schema
}
await commentWorkflow.trigger({
payload: { name: 'John', comment: 'Are you free to give me a call?' },
to: '[email protected]'
});

```
Expand Down
6 changes: 3 additions & 3 deletions apps/api/e2e/echo.server.ts → apps/api/e2e/bridge.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ export type ServerStartOptions = {
workflows: Array<Workflow>;
};

export class EchoServer {
export class BridgeServer {
private server: express.Express;
private app: http.Server;
private port = 9999;
public echo = new Client({ strictAuthentication: false });
public client = new Client({ strictAuthentication: false });

get serverPath() {
return `http://localhost:${this.port}`;
Expand All @@ -21,7 +21,7 @@ export class EchoServer {
async start(options: ServerStartOptions) {
this.server = express();
this.server.use(express.json());
this.server.use(serve({ client: this.echo, workflows: options.workflows }));
this.server.use(serve({ client: this.client, workflows: options.workflows }));

await new Promise<void>((resolve) => {
this.app = this.server.listen(this.port, () => {
Expand Down
2 changes: 1 addition & 1 deletion apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@
"optionalDependencies": {
"@novu/ee-auth": "workspace:*",
"@novu/ee-billing": "workspace:*",
"@novu/ee-echo-api": "workspace:*",
"@novu/ee-bridge-api": "workspace:*",
"@novu/ee-shared-services": "workspace:*",
"@novu/ee-translation": "workspace:*"
}
Expand Down
4 changes: 2 additions & 2 deletions apps/api/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ const enterpriseImports = (): Array<Type | DynamicModule | Promise<DynamicModule
if (require('@novu/ee-auth')?.EEAuthModule) {
modules.push(require('@novu/ee-auth')?.EEAuthModule);
}
if (require('@novu/ee-echo-api')?.EchoModule) {
modules.push(require('@novu/ee-echo-api')?.EchoModule);
if (require('@novu/ee-bridge-api')?.BridgeModule) {
modules.push(require('@novu/ee-bridge-api')?.BridgeModule);
}
if (require('@novu/ee-translation')?.EnterpriseTranslationModule) {
modules.push(require('@novu/ee-translation')?.EnterpriseTranslationModule);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { expect } from 'chai';
import { UserSession, SubscribersService } from '@novu/testing';
import { SubscriberEntity } from '@novu/dal';
import { workflow } from '@novu/framework';
import { EchoServer } from '../../../../e2e/echo.server';
import { BridgeServer } from '../../../../e2e/bridge.server';

describe('Echo Health Check', async () => {
describe('Bridge Health Check', async () => {
let session: UserSession;
let frameworkClient: EchoServer;
let frameworkClient: BridgeServer;
let subscriber: SubscriberEntity;
let subscriberService: SubscribersService;

Expand All @@ -20,7 +20,7 @@ describe('Echo Health Check', async () => {
};
});
});
frameworkClient = new EchoServer();
frameworkClient = new BridgeServer();
await frameworkClient.start({ workflows: [healthCheckWorkflow] });
});

Expand All @@ -36,25 +36,25 @@ describe('Echo Health Check', async () => {
});

it('should have a status', async () => {
const result = await axios.get(frameworkClient.serverPath + '/echo?action=health-check');
const result = await axios.get(frameworkClient.serverPath + '/novu?action=health-check');

expect(result.data.status).to.equal('ok');
});

it('should have an sdk version', async () => {
const result = await axios.get(frameworkClient.serverPath + '/echo?action=health-check');
const result = await axios.get(frameworkClient.serverPath + '/novu?action=health-check');

expect(result.data.sdkVersion).to.be.a('string');
});

it('should have a framework version', async () => {
const result = await axios.get(frameworkClient.serverPath + '/echo?action=health-check');
const result = await axios.get(frameworkClient.serverPath + '/novu?action=health-check');

expect(result.data.frameworkVersion).to.be.a('string');
});

it('should return the discovered resources', async () => {
const result = await axios.get(frameworkClient.serverPath + '/echo?action=health-check');
const result = await axios.get(frameworkClient.serverPath + '/novu?action=health-check');

expect(result.data.discovered).to.deep.equal({ workflows: 1, steps: 1 });
});
Expand Down
Loading

0 comments on commit 8f0ef99

Please sign in to comment.