Skip to content

Commit

Permalink
refactor(framework): Move API servers into collective folder (#5995)
Browse files Browse the repository at this point in the history
* refactor: Reorganize server-related files and imports

* refactor(constants): rename NOVU_FRAMEWORK_API to SERVER

* refactor(version): move version constants to separate file

* refactor: Reorganize workflow resource imports

* refactor(test): refactor action strings to enums

* refactor(constants): rename and update cron types path

* refactor: Replace strings with ChannelStepEnum keys

* fix(api): correct subpath import in echo.server.ts
  • Loading branch information
rifont authored Jul 5, 2024
1 parent 3e83976 commit edf7c23
Show file tree
Hide file tree
Showing 28 changed files with 97 additions and 90 deletions.
2 changes: 1 addition & 1 deletion apps/api/e2e/echo.server.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as http from 'http';
import * as express from 'express';
// FIXME: subpath import not working with `workspace:` protocol. Currently we need to drill into the module instead of using the ES export.
import { serve } from '../../../packages/framework/dist/express';
import { serve } from '../../../packages/framework/dist/servers/express';
import { Client, Workflow } from '@novu/framework';

export type ServerStartOptions = {
Expand Down
36 changes: 18 additions & 18 deletions packages/framework/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,34 +56,34 @@
"types": "./dist/index.d.ts"
},
"./express": {
"require": "./dist/express.js",
"import": "./dist/express.js",
"types": "./dist/express.d.ts"
"require": "./dist/servers/express.js",
"import": "./dist/servers/express.js",
"types": "./dist/servers/express.d.ts"
},
"./next": {
"require": "./dist/next.js",
"import": "./dist/next.js",
"types": "./dist/next.d.ts"
"require": "./dist/servers/next.js",
"import": "./dist/servers/next.js",
"types": "./dist/servers/next.d.ts"
},
"./nuxt": {
"require": "./dist/nuxt.js",
"import": "./dist/nuxt.js",
"types": "./dist/nuxt.d.ts"
"require": "./dist/servers/nuxt.js",
"import": "./dist/servers/nuxt.js",
"types": "./dist/servers/nuxt.d.ts"
},
"./h3": {
"require": "./dist/h3.js",
"import": "./dist/h3.js",
"types": "./dist/h3.d.ts"
"require": "./dist/servers/h3.js",
"import": "./dist/servers/h3.js",
"types": "./dist/servers/h3.d.ts"
},
"./sveltekit": {
"require": "./dist/sveltekit.js",
"import": "./dist/sveltekit.js",
"types": "./dist/sveltekit.d.ts"
"require": "./dist/servers/sveltekit.js",
"import": "./dist/servers/sveltekit.js",
"types": "./dist/servers/sveltekit.d.ts"
},
"./remix": {
"require": "./dist/remix.js",
"import": "./dist/remix.js",
"types": "./dist/remix.d.ts"
"require": "./dist/servers/remix.js",
"import": "./dist/servers/remix.js",
"types": "./dist/servers/remix.d.ts"
}
},
"peerDependencies": {
Expand Down
36 changes: 17 additions & 19 deletions packages/framework/src/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@ import {
StepNotFoundError,
WorkflowNotFoundError,
} from './errors';
import { workflow } from './workflow';
import { Event, Step } from './types';
import { delayOutputSchema } from './schemas';
import { emailChannelSchemas } from './schemas/steps/channels/email.schema';
import { FromSchema } from './types/schema.types';
import { FRAMEWORK_VERSION, SDK_VERSION } from './version';
import { workflow } from './resources';
import { Event, Step, FromSchema } from './types';
import { delayOutputSchema, channelStepSchemas } from './schemas';
import { FRAMEWORK_VERSION, SDK_VERSION, ChannelStepEnum, PostActionEnum } from './constants';

describe('Novu Client', () => {
let client: Client;
Expand Down Expand Up @@ -341,7 +339,7 @@ describe('Novu Client', () => {
client.addWorkflows([newWorkflow]);

const emailEvent: Event = {
action: 'preview',
action: PostActionEnum.PREVIEW,
data: { name: 'John' },
payload: { name: 'John' },
workflowId: 'test-workflow',
Expand All @@ -367,7 +365,7 @@ describe('Novu Client', () => {
describe('executeWorkflow method', () => {
it('should execute workflow successfully when action is execute and payload is provided', async () => {
const delayConfiguration: FromSchema<typeof delayOutputSchema> = { type: 'regular', unit: 'seconds', amount: 1 };
const emailConfiguration: FromSchema<typeof emailChannelSchemas.output> = {
const emailConfiguration: FromSchema<(typeof channelStepSchemas)[ChannelStepEnum.EMAIL]['output']> = {
body: 'Test Body',
subject: 'Subject',
};
Expand All @@ -377,7 +375,7 @@ describe('Novu Client', () => {
});

const emailEvent: Event = {
action: 'execute',
action: PostActionEnum.EXECUTE,
data: {},
payload: {},
workflowId: 'test-workflow',
Expand Down Expand Up @@ -406,7 +404,7 @@ describe('Novu Client', () => {
expect(metadata.duration).toEqual(expect.any(Number));

const delayEvent: Event = {
action: 'execute',
action: PostActionEnum.EXECUTE,
data: {},
payload: {},
workflowId: 'test-workflow',
Expand Down Expand Up @@ -489,7 +487,7 @@ describe('Novu Client', () => {
client.addWorkflows([newWorkflow]);

const emailEvent: Event = {
action: 'execute',
action: PostActionEnum.EXECUTE,
data: { role: 'product manager', elements: ['cat', 'dog'] },
payload: { role: 'product manager', elements: ['cat', 'dog'] },
workflowId: 'test-workflow',
Expand Down Expand Up @@ -522,7 +520,7 @@ describe('Novu Client', () => {
client.addWorkflows([newWorkflow]);

const event: Event = {
action: 'execute',
action: PostActionEnum.EXECUTE,
workflowId: 'test-workflow',
stepId: 'send-email',
subscriber: {},
Expand Down Expand Up @@ -558,7 +556,7 @@ describe('Novu Client', () => {
client.addWorkflows([newWorkflow]);

const event: Event = {
action: 'execute',
action: PostActionEnum.EXECUTE,
workflowId: 'test-workflow',
stepId: 'send-email',
subscriber: {},
Expand Down Expand Up @@ -597,7 +595,7 @@ describe('Novu Client', () => {
client.addWorkflows([workflowMock]);

const event: Event = {
action: 'preview',
action: PostActionEnum.PREVIEW,
workflowId: 'mock-workflow',
stepId: 'send-email',
subscriber: {},
Expand All @@ -623,7 +621,7 @@ describe('Novu Client', () => {
client.addWorkflows([newWorkflow]);

const event: Event = {
action: 'preview',
action: PostActionEnum.PREVIEW,
workflowId: 'test-workflow',
stepId: 'send-email',
subscriber: {},
Expand Down Expand Up @@ -664,7 +662,7 @@ describe('Novu Client', () => {
client.addWorkflows([newWorkflow]);

const event: Event = {
action: 'preview',
action: PostActionEnum.PREVIEW,
workflowId: 'test-workflow',
stepId: 'send-email',
subscriber: {},
Expand Down Expand Up @@ -698,7 +696,7 @@ describe('Novu Client', () => {
it('should throw an error when workflow ID is invalid', async () => {
// non-existing workflow ID
const event: Event = {
action: 'execute',
action: PostActionEnum.EXECUTE,
workflowId: 'non-existent-workflow',
stepId: 'send-email',
subscriber: {},
Expand All @@ -719,7 +717,7 @@ describe('Novu Client', () => {

// no workflow ID
const event2 = {
action: 'execute',
action: PostActionEnum.EXECUTE,
stepId: 'send-email',
subscriber: {},
state: [],
Expand All @@ -735,7 +733,7 @@ describe('Novu Client', () => {
client.addWorkflows([newWorkflow]);

const event: Event = {
action: 'execute',
action: PostActionEnum.EXECUTE,
workflowId: 'test-workflow',
stepId: 'non-existing-step',
subscriber: {},
Expand Down
3 changes: 1 addition & 2 deletions packages/framework/src/client.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { JSONSchemaFaker } from 'json-schema-faker';
import { Liquid } from 'liquidjs';
import ora from 'ora';
import { PostActionEnum } from './constants';

import { FRAMEWORK_VERSION, PostActionEnum, SDK_VERSION } from './constants';
import {
ExecutionEventControlsInvalidError,
ExecutionEventPayloadInvalidError,
Expand Down Expand Up @@ -35,7 +35,6 @@ import type {
} from './types';
import { EMOJI, log } from './utils';
import { transformSchema, validateData } from './validators';
import { FRAMEWORK_VERSION, SDK_VERSION } from './version';

/**
* We want to respond with a consistent string value for preview
Expand Down
2 changes: 1 addition & 1 deletion packages/framework/src/client.validation.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect, it, describe, beforeEach } from 'vitest';
import { Client } from './client';
import { z } from 'zod';
import { workflow } from './workflow';
import { workflow } from './resources/workflow';
import { ExecutionStateControlsInvalidError } from './errors';

describe('validation', () => {
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion packages/framework/src/constants/http-headers.constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export enum HttpHeaderKeysEnum {
NOVU_SIGNATURE_DEPRECATED = 'x-novu-signature',
NOVU_ANONYMOUS_DEPRECATED = 'x-novu-anonymous',
NOVU_FRAMEWORK_SDK = 'novu-framework-sdk',
NOVU_FRAMEWORK_API = 'novu-framework-api',
NOVU_FRAMEWORK_SERVER = 'novu-framework-server',
NOVU_FRAMEWORK_VERSION = 'novu-framework-version',
USER_AGENT = 'user-agent',
CONTENT_TYPE = 'content-type',
Expand Down
2 changes: 2 additions & 0 deletions packages/framework/src/constants/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
export * from './action.constants';
export * from './api.constants';
export * from './cron.constants';
export * from './error.constants';
export * from './http-headers.constants';
export * from './http-methods.constants';
export * from './http-query.constants';
export * from './http-status.constants';
export * from './resource.constants';
export * from './step.constants';
export * from './version.constants';
4 changes: 4 additions & 0 deletions packages/framework/src/constants/version.constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { version } from '../../package.json';

export const SDK_VERSION = version;
export const FRAMEWORK_VERSION = '2024-06-26';
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { expect, test, describe } from 'vitest';
import { SDK_VERSION } from './version';
import { SDK_VERSION } from './version.constants';

describe('version', () => {
test('should export the current version', () => {
const importVersion = SDK_VERSION;
const packageJsonVersion = require('../package.json').version;
const packageJsonVersion = require('../../package.json').version;
expect(importVersion).toEqual(packageJsonVersion);
});
});
11 changes: 6 additions & 5 deletions packages/framework/src/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,30 @@ import { createHmac } from 'node:crypto';
import { Client } from './client';
import {
ErrorCodeEnum,
FRAMEWORK_VERSION,
GetActionEnum,
HttpHeaderKeysEnum,
HttpMethodEnum,
HttpQueryKeysEnum,
HttpStatusEnum,
PostActionEnum,
SDK_VERSION,
SIGNATURE_TIMESTAMP_TOLERANCE,
} from './constants';
import {
BridgeError,
FrameworkError,
InvalidActionError,
MethodNotAllowedError,
FrameworkError,
BridgeError,
PlatformError,
SignatureExpiredError,
SignatureInvalidError,
SignatureMismatchError,
SignatureNotFoundError,
SigningKeyNotFoundError,
PlatformError,
} from './errors';
import type { Awaitable, EventTriggerParams, Workflow } from './types';
import { initApiClient } from './utils';
import { FRAMEWORK_VERSION, SDK_VERSION } from './version';

// eslint-disable-next-line @typescript-eslint/naming-convention
export type ServeHandlerOptions = {
Expand Down Expand Up @@ -97,7 +98,7 @@ export class NovuRequestHandler<Input extends any[] = any[], Output = any> {
[HttpHeaderKeysEnum.ACCESS_CONTROL_MAX_AGE]: '604800',
[HttpHeaderKeysEnum.NOVU_FRAMEWORK_VERSION]: FRAMEWORK_VERSION,
[HttpHeaderKeysEnum.NOVU_FRAMEWORK_SDK]: SDK_VERSION,
[HttpHeaderKeysEnum.NOVU_FRAMEWORK_API]: this.frameworkName,
[HttpHeaderKeysEnum.NOVU_FRAMEWORK_SERVER]: this.frameworkName,
[HttpHeaderKeysEnum.USER_AGENT]: sdkVersion,
};
}
Expand Down
4 changes: 2 additions & 2 deletions packages/framework/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export { Client } from './client';
export * from './types';
export * from './constants';
export { NovuRequestHandler, type ServeHandlerOptions } from './handler';
export { workflow } from './workflow';
export * from './resources';
export * from './types';
1 change: 1 addition & 0 deletions packages/framework/src/resources/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './workflow';
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { it, describe, beforeEach, expect, vi, afterEach } from 'vitest';
import { MissingSecretKeyError } from './errors';
import { MissingSecretKeyError } from '../errors';
import { workflow } from './workflow';

describe('workflow function', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { ChannelStepEnum } from './constants';
import { MissingSecretKeyError, StepAlreadyExistsError, WorkflowPayloadInvalidError } from './errors';
import { channelStepSchemas, delayChannelSchemas, digestChannelSchemas, emptySchema, providerSchemas } from './schemas';
import { ChannelStepEnum } from '../constants';
import { MissingSecretKeyError, StepAlreadyExistsError, WorkflowPayloadInvalidError } from '../errors';
import {
channelStepSchemas,
delayChannelSchemas,
digestChannelSchemas,
emptySchema,
providerSchemas,
} from '../schemas';
import type {
ActionStep,
Awaitable,
Expand All @@ -15,9 +21,9 @@ import type {
EventTriggerResponse,
Workflow,
WorkflowOptions,
} from './types';
import { EMOJI, getBridgeUrl, initApiClient, log } from './utils';
import { transformSchema, validateData } from './validators';
} from '../types';
import { EMOJI, getBridgeUrl, initApiClient, log } from '../utils';
import { transformSchema, validateData } from '../validators';

/**
* Define a new notification workflow.
Expand Down
10 changes: 5 additions & 5 deletions packages/framework/src/schemas/providers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ type ProvidersSchemas =
| SmsProvidersSchemas;

export const providerSchemas = {
chat: chatProviderSchemas,
sms: smsProviderSchemas,
email: emailProviderSchemas,
push: pushProviderSchemas,
in_app: inAppProviderSchemas,
[ChannelStepEnum.CHAT]: chatProviderSchemas,
[ChannelStepEnum.SMS]: smsProviderSchemas,
[ChannelStepEnum.EMAIL]: emailProviderSchemas,
[ChannelStepEnum.PUSH]: pushProviderSchemas,
[ChannelStepEnum.IN_APP]: inAppProviderSchemas,
} satisfies Record<ChannelStepEnum, ProvidersSchemas>;
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { type VercelRequest, type VercelResponse } from '@vercel/node';
import { type Request, type Response } from 'express';

import { NovuRequestHandler, ServeHandlerOptions } from './handler';
import { Either } from './types';
import { type SupportedFrameworkName } from './types';
import { NovuRequestHandler, ServeHandlerOptions } from '../handler';
import { Either } from '../types';
import { type SupportedFrameworkName } from '../types';

export const frameworkName: SupportedFrameworkName = 'express';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getHeader, getQuery, type H3Event, readBody, send, setHeaders, type EventHandlerRequest } from 'h3';

import { NovuRequestHandler, type ServeHandlerOptions } from './handler';
import { type SupportedFrameworkName } from './types';
import { NovuRequestHandler, type ServeHandlerOptions } from '../handler';
import { type SupportedFrameworkName } from '../types';

export const frameworkName: SupportedFrameworkName = 'h3';

Expand Down
Loading

0 comments on commit edf7c23

Please sign in to comment.