|

Introducing Harmony: Unified JavaScript Platform for Building Composable Frontends and Backends | by Mike Chen | Feb, 2025

We can start by creating a Harmony platform for the application. Then we can register the required runtimes (e.g BrowserRuntime , NodeJSRuntime ) which are directly supported by the platform.

export const MyApp = HarmonyPlatform.from({
name: ‘my-app’,
platform: [
SymphonyPlatformAspect,
{
name: ‘MyApp’,
slogan: ‘Platform’,
logo: ‘https://static.bit.dev/extensions-icons/wayne.svg’,
},
],

runtimes: [new BrowserRuntime(), new NodeJSRuntime()],

aspects: [MyAppAspect, KubernetesAspect],
});

Choosing runtimes is optional. For example, if you are building purely an API or a CLI application, you can opt-out the BrowserRuntime.

Symphony Platform Aspect: A ready-made aspect built by the Bit team. It acts as the platform’s foundation and gateway.

Then we can start building functional aspects and register them into the Harmony Platform.

Example: The “People” Aspect for Authentication

Let’s consider an authentication service built as a Harmony Aspect. Instead of having separate frontend and backend services, the People Aspect provides both:

  • Frontend UI for login and user management

export class PeopleBrowser {
// …

// Declare this aspect’s dependencies (Harmony uses this to initialize the aspects at the right order)
static dependencies = [MyPlatformAspect];

// List the aspects to be injected into this aspect
static async provider([myPlatform]: [MyPlatformBrowser]) {
const people = new PeopleBrowser(config, menuItemSlot);
myPlatform.registerRoute([
{
path: ‘people’,
component: () => {
return ;
},
},
]);

// Registration via other aspects can be optional (depending on whether the aspect is part of the platform or not)

// Add a widget to the platform’s homepage
myPlatform?.registerPanel([
{
category: ‘People’,
component: () => {
return ;
},
},
]);

// Register a top-level component to wrap the platform with the authentication context
myPlatform?.registerTopLevelComponents({
component: ({ children }) => {
return {children};
},
});

See Also  CSS min() All The Things — Smashing Magazine

// …

return people;
}
}

  • Backend API for authentication and user data storage

// …

export class PeopleNode {
constructor(
private myPlatform: MyPlatformNode,
private userRepo: UserRepository
) {}

// …

async getCurrentUser(req: any): Promise {
// …
return User.from(user);
}

static dependencies = [SymphonyPlatformAspect, MyPlatformAspect];

static async provider([symphonyPlatform, myPlatform]: [
SymphonyPlatformNode,
MyPlatformNode
]) {
const userRepo = new UserRepository();
const people = new PeopleNode(myPlatform, userRepo);
const gqlSchema = createPeopleGqlSchema(people);

/**
* Register a GraphQL schema to the platform’s backend server.
*/
myPlatform.registerBackendServer([
{
routes: [],
gql: gqlSchema,
},
]);

/**
* Register to the platform’s middleware to intercept requests to the backend
* and attach the user to the request.
*/
symphonyPlatform.registerMiddlewares([
(req, _, next) => {
const user = people.getCurrentUser(req);
req.user = user;
next();
},
]);

return people;
}
}

export default PeopleNode;

You can see how we can create the Browser-related functionality of the People aspects and Node-related functionality of the people aspects in unification and inject them into the Harmony platform using dependency injection.

Source link

Similar Posts