This repository has no description
7.3 kB
193 lines
1import express, { Express } from 'express';
2import cors from 'cors';
3import cookieParser from 'cookie-parser';
4import { Router } from 'express';
5import * as Sentry from '@sentry/node';
6import { createUserRoutes } from '../../../modules/user/infrastructure/http/routes/userRoutes';
7import { createAtprotoRoutes } from '../../../modules/atproto/infrastructure/atprotoRoutes';
8import { createCardsModuleRoutes } from '../../../modules/cards/infrastructure/http/routes';
9import { createConnectionRoutes } from '../../../modules/cards/infrastructure/http/routes/connectionRoutes';
10import { createGraphRoutes } from '../../../modules/cards/infrastructure/http/routes/graphRoutes';
11import { createFeedRoutes } from '../../../modules/feeds/infrastructure/http/routes/feedRoutes';
12import { createSearchRoutes } from '../../../modules/search/infrastructure/http/routes/searchRoutes';
13import { createNotificationRoutes } from '../../../modules/notifications/infrastructure/http/routes/notificationRoutes';
14import { createTestRoutes } from './routes/testRoutes';
15import {
16 EnvironmentConfigService,
17 Environment,
18} from '../config/EnvironmentConfigService';
19import { RepositoryFactory } from './factories/RepositoryFactory';
20import { ServiceFactory } from './factories/ServiceFactory';
21import { UseCaseFactory } from './factories/UseCaseFactory';
22import { ControllerFactory } from './factories/ControllerFactory';
23
24export const createExpressApp = (
25 configService: EnvironmentConfigService,
26): Express => {
27 const app = express();
28
29 // Determine allowed origins based on environment
30 const getAllowedOrigins = () => {
31 const environment = configService.get().environment;
32 const appUrl = configService.getAppConfig().appUrl;
33
34 switch (environment) {
35 case Environment.PROD:
36 return ['https://semble.so', 'https://api.semble.so'];
37 case Environment.DEV:
38 return ['https://dev.semble.so', 'https://api.dev.semble.so'];
39 case Environment.LOCAL:
40 default:
41 // Allow both localhost:4000 and configured appUrl for flexibility
42 return [
43 'http://localhost:4000',
44 'http://127.0.0.1:4000',
45 appUrl,
46 'http://localhost:3000',
47 'http://127.0.0.1:3000',
48 ];
49 }
50 };
51
52 app.use(
53 cors({
54 origin: getAllowedOrigins(),
55 methods: ['GET', 'POST', 'PUT', 'DELETE'],
56 credentials: true, // Required for cookies to work in cross-origin requests
57 }),
58 );
59
60 // Middleware setup
61 app.use(cookieParser()); // Parse cookies from incoming requests
62 app.use(express.json());
63 app.use(express.urlencoded({ extended: true }));
64
65 // Create all dependencies using factories
66 const repositories = RepositoryFactory.create(configService);
67 const services = ServiceFactory.createForWebApp(configService, repositories);
68 const useCases = UseCaseFactory.createForWebApp(repositories, services);
69 const controllers = ControllerFactory.create(
70 useCases,
71 services.cookieService,
72 );
73
74 // Routes
75 const userRouter = Router();
76 const atprotoRouter = Router();
77
78 createUserRoutes(
79 userRouter,
80 services.authMiddleware,
81 controllers.initiateOAuthSignInController,
82 controllers.completeOAuthSignInController,
83 controllers.loginWithAppPasswordController,
84 controllers.logoutController,
85 controllers.getMyProfileController,
86 controllers.getUserProfileController,
87 controllers.refreshAccessTokenController,
88 controllers.generateExtensionTokensController,
89 controllers.followTargetController,
90 controllers.unfollowTargetController,
91 controllers.getFollowingUsersController,
92 controllers.getFollowersController,
93 controllers.getFollowingCollectionsController,
94 controllers.getFollowingCountController,
95 controllers.getFollowersCountController,
96 controllers.getFollowingCollectionsCountController,
97 );
98
99 createAtprotoRoutes(atprotoRouter, services.nodeOauthClient);
100
101 const cardsRouter = createCardsModuleRoutes(
102 services.authMiddleware,
103 // Card controllers
104 controllers.addUrlToLibraryController,
105 controllers.addCardToLibraryController,
106 controllers.addCardToCollectionController,
107 controllers.updateNoteCardController,
108 controllers.updateUrlCardAssociationsController,
109 controllers.removeCardFromLibraryController,
110 controllers.removeCardFromCollectionController,
111 controllers.getUrlMetadataController,
112 controllers.getUrlCardViewController,
113 controllers.getLibrariesForCardController,
114 controllers.getMyUrlCardsController,
115 controllers.getUserUrlCardsController,
116 controllers.getUrlStatusForMyLibraryController,
117 controllers.getLibrariesForUrlController,
118 controllers.getNoteCardsForUrlController,
119 controllers.searchUrlsController,
120 // Collection controllers
121 controllers.createCollectionController,
122 controllers.updateCollectionController,
123 controllers.deleteCollectionController,
124 controllers.getCollectionPageController,
125 controllers.getCollectionPageByAtUriController,
126 controllers.getMyCollectionsController,
127 controllers.getCollectionsController,
128 controllers.getCollectionsForUrlController,
129 controllers.searchCollectionsController,
130 controllers.getOpenCollectionsWithContributorController,
131 controllers.getCollectionFollowersController,
132 controllers.getCollectionFollowersCountController,
133 controllers.getCollectionContributorsController,
134 );
135
136 const connectionRouter = createConnectionRoutes(
137 services.authMiddleware,
138 controllers.createConnectionController,
139 controllers.updateConnectionController,
140 controllers.deleteConnectionController,
141 controllers.getConnectionsController,
142 controllers.getForwardConnectionsForUrlController,
143 controllers.getBackwardConnectionsForUrlController,
144 );
145
146 const graphRouter = createGraphRoutes(
147 services.authMiddleware,
148 controllers.getGraphDataController,
149 );
150
151 const feedRouter = createFeedRoutes(
152 services.authMiddleware,
153 controllers.getGlobalFeedController,
154 controllers.getGemActivityFeedController,
155 controllers.getFollowingFeedController,
156 );
157
158 const searchRouter = createSearchRoutes(
159 services.authMiddleware,
160 controllers.getSimilarUrlsForUrlController,
161 controllers.searchBskyPostsForUrlController,
162 controllers.semanticSearchUrlsController,
163 controllers.searchAtProtoAccountsController,
164 controllers.searchLeafletDocsForUrlController,
165 );
166
167 const notificationRouter = createNotificationRoutes(
168 services.authMiddleware,
169 controllers.getMyNotificationsController,
170 controllers.getUnreadNotificationCountController,
171 controllers.markNotificationsAsReadController,
172 controllers.markAllNotificationsAsReadController,
173 );
174
175 const testRouter = Router();
176 createTestRoutes(testRouter);
177
178 // Register routes
179 app.use('/api/users', userRouter);
180 app.use('/atproto', atprotoRouter);
181 app.use('/api', cardsRouter);
182 app.use('/api/connections', connectionRouter);
183 app.use('/api/graph', graphRouter);
184 app.use('/api/feeds', feedRouter);
185 app.use('/api/search', searchRouter);
186 app.use('/api/notifications', notificationRouter);
187 app.use('/api/test', testRouter);
188
189 // Sentry error handler - must be after all routes and before other error middleware
190 Sentry.setupExpressErrorHandler(app);
191
192 return app;
193};