Skip to content

Commit 2acc811

Browse files
committed
feat(node): add initial lib for ssr
1 parent 205135d commit 2acc811

25 files changed

+634
-57
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"extends": ["../../.eslintrc.base.json"],
3+
"ignorePatterns": ["!**/*"],
4+
"overrides": [
5+
{
6+
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
7+
"rules": {}
8+
},
9+
{
10+
"files": ["*.ts", "*.tsx"],
11+
"rules": {}
12+
},
13+
{
14+
"files": ["*.js", "*.jsx"],
15+
"rules": {}
16+
},
17+
{
18+
"files": ["*.json"],
19+
"parser": "jsonc-eslint-parser",
20+
"rules": {
21+
"@nx/dependency-checks": "error"
22+
}
23+
}
24+
]
25+
}

libs/native-federation-node/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# native-federation-node
2+
3+
This library was generated with [Nx](https://nx.dev).
4+
5+
## Building
6+
7+
Run `nx build native-federation-node` to build the library.
8+
9+
## Running unit tests
10+
11+
Run `nx test native-federation-node` to execute the unit tests via [Jest](https://jestjs.io).
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/* eslint-disable */
2+
export default {
3+
displayName: 'native-federation-node',
4+
preset: '../../jest.preset.js',
5+
testEnvironment: 'node',
6+
transform: {
7+
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
8+
},
9+
moduleFileExtensions: ['ts', 'js', 'html'],
10+
coverageDirectory: '../../coverage/libs/native-federation-node',
11+
};
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"name": "@softarc/native-federation-node",
3+
"version": "0.0.1"
4+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"name": "native-federation-node",
3+
"$schema": "../../node_modules/nx/schemas/project-schema.json",
4+
"sourceRoot": "libs/native-federation-node/src",
5+
"projectType": "library",
6+
"release": {
7+
"version": {
8+
"generatorOptions": {
9+
"packageRoot": "dist/{projectRoot}",
10+
"currentVersionResolver": "git-tag"
11+
}
12+
}
13+
},
14+
"tags": [],
15+
"targets": {
16+
"build": {
17+
"executor": "@nx/js:tsc",
18+
"outputs": ["{options.outputPath}"],
19+
"options": {
20+
"outputPath": "dist/libs/native-federation-node",
21+
"tsConfig": "libs/native-federation-node/tsconfig.lib.json",
22+
"packageJson": "libs/native-federation-node/package.json",
23+
"main": "libs/native-federation-node/src/index.ts",
24+
"assets": ["libs/native-federation-node/*.md"]
25+
}
26+
},
27+
"nx-release-publish": {
28+
"options": {
29+
"packageRoot": "dist/{projectRoot}"
30+
}
31+
}
32+
}
33+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './lib/node/init-node-federation';
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { URL } from 'url';
2+
import { resolveAndComposeImportMap } from '../utils/import-map-utils';
3+
4+
console.log('resolveAndComposeImportMap', resolveAndComposeImportMap);
5+
6+
interface ResolveContext {
7+
conditions: string[];
8+
importAssertions: Record<string, string>;
9+
parentURL?: string;
10+
}
11+
12+
interface LoadContext {
13+
format: string | null;
14+
importAssertions: Record<string, string>;
15+
}
16+
17+
interface ResolveResult {
18+
url: string;
19+
}
20+
21+
interface LoadResult {
22+
format: string;
23+
source: string | ArrayBuffer | Uint8Array;
24+
}
25+
26+
type ResolveFunction = (
27+
specifier: string,
28+
context: ResolveContext,
29+
defaultResolve: (specifier: string, context: ResolveContext) => Promise<ResolveResult>
30+
) => Promise<ResolveResult>;
31+
32+
type LoadFunction = (
33+
url: string,
34+
context: LoadContext,
35+
defaultLoad: (url: string, context: LoadContext) => Promise<LoadResult>
36+
) => Promise<LoadResult>;
37+
38+
export const resolve: ResolveFunction = async (specifier, context, defaultResolve) => {
39+
console.log(`Resolving: ${specifier}`);
40+
41+
return defaultResolve(specifier, context);
42+
};
43+
44+
export const load: LoadFunction = async (url, context, defaultLoad) => {
45+
console.log(`Loading: ${url}`);
46+
47+
return defaultLoad(url, context);
48+
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { ImportMap } from "@softarc/native-federation-runtime";
2+
3+
let _importMap: ImportMap;
4+
5+
export function setImportMap(importMap: ImportMap): void {
6+
_importMap = importMap;
7+
}
8+
9+
export function getImportMap(): ImportMap {
10+
return _importMap;
11+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { register } from "node:module";
2+
import { pathToFileURL } from "node:url";
3+
import * as fs from 'node:fs/promises';
4+
import * as path from 'node:path';
5+
import { processHostInfo, processRemoteInfos, FederationInfo } from "@softarc/native-federation-runtime";
6+
import { ImportMap, mergeImportMaps } from "@softarc/native-federation-runtime";
7+
import { setImportMap } from "./import-map-store";
8+
9+
export type InitNodeFederationOptions = {
10+
relBundlePath: string;
11+
};
12+
13+
export async function initNodeFederation(
14+
remotesOrManifestUrl: Record<string, string> | string = {},
15+
options: InitNodeFederationOptions
16+
): Promise<void> {
17+
const importMap = await createNodeImportMap(remotesOrManifestUrl, options);
18+
setImportMap(importMap);
19+
register(pathToFileURL('./federation-resolver.js').href);
20+
}
21+
22+
async function createNodeImportMap(
23+
remotesOrManifestUrl: Record<string, string> | string = {},
24+
options: InitNodeFederationOptions
25+
): Promise<ImportMap> {
26+
const remotes =
27+
typeof remotesOrManifestUrl === 'object'
28+
? remotesOrManifestUrl
29+
: await loadFsManifest(options.relBundlePath, remotesOrManifestUrl);
30+
31+
const hostInfo = await loadFsFederationInfo(options.relBundlePath);
32+
const hostImportMap = await processHostInfo(hostInfo, options.relBundlePath);
33+
const remotesImportMap = await processRemoteInfos(remotes);
34+
35+
const importMap = mergeImportMaps(hostImportMap, remotesImportMap);
36+
37+
return importMap;
38+
}
39+
40+
async function loadFsManifest(
41+
relBundlePath: string,
42+
manifestName: string
43+
): Promise<Record<string, string>> {
44+
const manifestPath = path.join(relBundlePath, manifestName);
45+
const content = await fs.readFile(manifestPath, 'utf-8');
46+
const manifest = JSON.parse(content) as Record<string, string>;
47+
return manifest;
48+
}
49+
50+
async function loadFsFederationInfo(
51+
relBundlePath: string
52+
): Promise<FederationInfo> {
53+
const manifestPath = path.join(relBundlePath, 'remoteEntry.json');
54+
const content = await fs.readFile(manifestPath, 'utf-8');
55+
const manifest = JSON.parse(content) as FederationInfo;
56+
return manifest;
57+
}

0 commit comments

Comments
 (0)