Skip to content

Commit 4cc7a09

Browse files
committed
feat: Module Loader 스캐폴드와 manifest 계약 추가
1 parent 9d8ef19 commit 4cc7a09

3 files changed

Lines changed: 152 additions & 0 deletions

File tree

apps/api/src/loader/index.ts

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
export interface ModuleRoutes {
2+
frontend: string;
3+
api: string;
4+
}
5+
6+
export interface ModuleManifest {
7+
name: string;
8+
version: string;
9+
enabled: boolean;
10+
dependencies: string[];
11+
routes: ModuleRoutes;
12+
}
13+
14+
export interface BackendRouteRegistration {
15+
moduleName: string;
16+
apiBasePath: string;
17+
}
18+
19+
export interface BackendModuleEntry {
20+
name: string;
21+
manifestJson: string;
22+
}
23+
24+
export function parseModuleJson(content: string): ModuleManifest {
25+
const parsed = JSON.parse(content) as Partial<ModuleManifest>;
26+
27+
return {
28+
name: parsed.name ?? "",
29+
version: parsed.version ?? "0.0.0",
30+
enabled: parsed.enabled ?? false,
31+
dependencies: parsed.dependencies ?? [],
32+
routes: {
33+
frontend: parsed.routes?.frontend ?? "",
34+
api: parsed.routes?.api ?? "",
35+
},
36+
};
37+
}
38+
39+
export async function scanBackendModules(
40+
entries: BackendModuleEntry[],
41+
): Promise<ModuleManifest[]> {
42+
const manifests = entries.map((entry) => {
43+
const manifest = parseModuleJson(entry.manifestJson);
44+
return {
45+
...manifest,
46+
name: manifest.name || entry.name,
47+
};
48+
});
49+
50+
return manifests.filter((manifest) => manifest.enabled);
51+
}
52+
53+
export function buildBackendRouteRegistrations(
54+
manifests: ModuleManifest[],
55+
): BackendRouteRegistration[] {
56+
return manifests.map((manifest) => ({
57+
moduleName: manifest.name,
58+
apiBasePath: manifest.routes.api,
59+
}));
60+
}
61+
62+
export interface DependencyIssue {
63+
moduleName: string;
64+
missingDependencies: string[];
65+
}
66+
67+
export function validateModuleDependencies(manifests: ModuleManifest[]): DependencyIssue[] {
68+
const installedModules = new Set(manifests.map((manifest) => manifest.name));
69+
70+
return manifests
71+
.map((manifest) => {
72+
const missingDependencies = manifest.dependencies.filter(
73+
(dependency) => !installedModules.has(dependency),
74+
);
75+
76+
return {
77+
moduleName: manifest.name,
78+
missingDependencies,
79+
};
80+
})
81+
.filter((issue) => issue.missingDependencies.length > 0);
82+
}

apps/web/src/loader/index.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
export interface ModuleRoutes {
2+
frontend: string;
3+
api: string;
4+
}
5+
6+
export interface ModuleManifest {
7+
name: string;
8+
version: string;
9+
enabled: boolean;
10+
dependencies: string[];
11+
routes: ModuleRoutes;
12+
}
13+
14+
export interface FrontendRouteRegistration {
15+
moduleName: string;
16+
path: string;
17+
}
18+
19+
export interface NavigationItem {
20+
id: string;
21+
label: string;
22+
path: string;
23+
}
24+
25+
export function parseModuleJson(content: string): ModuleManifest {
26+
const parsed = JSON.parse(content) as Partial<ModuleManifest>;
27+
28+
return {
29+
name: parsed.name ?? "",
30+
version: parsed.version ?? "0.0.0",
31+
enabled: parsed.enabled ?? false,
32+
dependencies: parsed.dependencies ?? [],
33+
routes: {
34+
frontend: parsed.routes?.frontend ?? "",
35+
api: parsed.routes?.api ?? "",
36+
},
37+
};
38+
}
39+
40+
export function buildFrontendRouteRegistrations(
41+
manifests: ModuleManifest[],
42+
): FrontendRouteRegistration[] {
43+
return manifests.filter((manifest) => manifest.enabled).map((manifest) => ({
44+
moduleName: manifest.name,
45+
path: manifest.routes.frontend,
46+
}));
47+
}
48+
49+
export function buildNavigationItems(manifests: ModuleManifest[]): NavigationItem[] {
50+
return manifests
51+
.filter((manifest) => manifest.enabled)
52+
.map((manifest) => ({
53+
id: manifest.name,
54+
label: manifest.name,
55+
path: manifest.routes.frontend,
56+
}));
57+
}

packages/core/src/types/index.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,19 @@ export interface ModuleMetadata {
1515
enabled: boolean;
1616
}
1717

18+
export interface ModuleRoutes {
19+
frontend: string;
20+
api: string;
21+
}
22+
23+
export interface ModuleManifest {
24+
name: string;
25+
version: string;
26+
enabled: boolean;
27+
dependencies: string[];
28+
routes: ModuleRoutes;
29+
}
30+
1831
export interface IntegrationConfig {
1932
provider: string;
2033
enabled: boolean;

0 commit comments

Comments
 (0)