Skip to content

Commit

Permalink
feat: added options to configure paths
Browse files Browse the repository at this point in the history
  • Loading branch information
steven-pribilinskiy committed Aug 4, 2022
1 parent f899b88 commit 6022a8d
Show file tree
Hide file tree
Showing 11 changed files with 100 additions and 34 deletions.
27 changes: 19 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ compiled remote types from other federated microapps into _src/@types/remotes_ f

Global type definitions from _src/@types/*.d.ts_ are included in compilation.

Paths can be customized to meet your environment.

## Feature comparison tables

| Feature | @touk/<br>federated-types | ruanyl/dts-loader | ruanyl/webpack-remote-types-plugin | @module-federation/typescript | @cloudbeds/wmf-types-plugin |
Expand Down Expand Up @@ -69,6 +71,13 @@ Or it can be added to `package.json`:
}
```

### CLI options

| Option | Default value | Description |
|-------------------------------|---------------|--------------------------------------------------------------------------------|
| `--output-types-folder`, `-o` | `dist/@types` | Path to the output folder, absolute or relative to the working directory |
| `--global-types`, `-g` | `src/@types` | Path to project's global ambient type definitions, relative to the working dir |

## Plugin Configuration

### Exposed modules
Expand Down Expand Up @@ -136,14 +145,16 @@ To enable verbose logging add folowing in webpack config:

### Plugin Options

| Option | Value | Default | Description |
|-----------------------------------------:|:--------------------:|:-------------------:|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `disableTypeCompilation` | `boolean` | `false` | Disable compilation of types |
| `disableDownladingRemoteTypes` | `boolean` | `false` | Disable downloading of remote types |
| `cloudbedsRemoteManifestsBaseUrl` | `string` | `'/remotes/dev-ga'` | Base URL for remote manifest files (a.k.a remote entry configs) that is specific to Cloudbeds microapps <br><br> _ Examples:_ <br> `http://localhost:4480/remotes/dev` <br> `https://cb-front.cloudbeds-dev.com/remotes/[env]` <br> `use-domain-name` |
| `doNotUseCloudbedsRemoteManifests` | `boolean` | `false` | Disable downloading default remote manifest files for Cloudbeds microapps (`mfd-common-remote-entry.json` and `mfd-remote-entries.json` files) and download only those provided via `remoteManifestUrls` |
| `downloadTypesWhenIdleIntervalInSeconds` | `number`, `-1` | `60` | Synchronize types continusouly - compile types after every compilation, download when idle with a specified delay value in seconds. <br><br> `-1` - disables continuous synchronization (compile and download will happen only on startup). |
| `remoteManifestUrls` | `RemoteManifestUrls` | `{}` | URLs to remote manifest files. A manifest contains a URL to a remote entry that is substituted in runtime. Multiple remote entries is supported via `registry` field. <br><br> More details available in [this section](#templated-remote-urls) |
| Setting | Value | Default | Description |
|-----------------------------------------:|:--------------------:|:--------------------:|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `dirEmittedTypes` | `string` | `@types` | Path to the output folder for emitted types, relative to the distribution folder |
| `dirGlobalTypes` | `string` | `src/@types` | Path to project's global ambient type definitions, relative to the working dir |
| `dirDownloadedTypes` | `string` | `src/@types/remotes` | Path to the output folder for downloaded types |
| `disableTypeCompilation` | `boolean` | `false` | Disable compilation of types |
| `disableDownladingRemoteTypes` | `boolean` | `false` | Disable downloading of remote types |
| `downloadTypesWhenIdleIntervalInSeconds` | `number`, `-1` | `60` | Synchronize types continusouly - compile types after every compilation, download when idle with a specified delay value in seconds. <br><br> `-1` - disables continuous synchronization (compile and download will happen only on startup). |
| `remoteManifestUrls` | `RemoteManifestUrls` | `{}` | URLs to remote manifest files. A manifest contains a URL to a remote entry that is substituted in runtime. Multiple remote entries is supported via `registry` field. <br><br> More details available in [this section](#templated-remote-urls) |
| `cloudbedsRemoteManifestsBaseUrl` | `string` | `'/remotes/dev-ga'` | Base URL for remote manifest files (a.k.a remote entry configs) that is specific to Cloudbeds microapps <br><br> _ Examples:_ <br> `http://localhost:4480/remotes/dev` <br> `https://cb-front.cloudbeds-dev.com/remotes/[env]` <br> `use-domain-name`. <br><br> Following remote manifest files are downloaded: `mfd-common-remote-entry.json` and `mfd-remote-entries.json` files). <br><br> `remoteManifestUrls` is ignored when this setting has a value other than `undefined`. |


## Consuming remote types
Expand Down
24 changes: 24 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@
},
"dependencies": {
"download": "^8.0.0",
"minimist": "^1.2.6",
"mkdirp": "^1.0.4"
},
"devDependencies": {
"@types/download": "^8.0.1",
"@types/jest": "^28.1.6",
"@types/minimist": "^1.2.2",
"@types/mkdirp": "^1.0.2",
"jest": "^28.1.3",
"ts-jest": "^28.0.7",
Expand Down
8 changes: 4 additions & 4 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
export const FEDERATION_CONFIG_FILE = 'federation.config.json';

export const DIR_DIST = 'dist';
export const DIR_EMITTED_TYPES = '@types';
export const DEFAULT_DIR_DIST = 'dist';
export const DEFAULT_DIR_EMITTED_TYPES = '@types';

export const DIR_SRC_TYPES = 'src/@types';
export const DIR_DOWNLOADED_TYPES = `${DIR_SRC_TYPES}/remotes`;
export const DEFAULT_DIR_GLOBAL_TYPES = 'src/@types';
export const DEFAULT_DIR_DOWNLOADED_TYPES = `src/@types/remotes`;

export const DEFAULT_DOWNLOAD_TYPES_INTERVAL_IN_SECONDS = 60;

Expand Down
2 changes: 1 addition & 1 deletion src/helpers/cloudbedsRemoteManifests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
import { ModuleFederationTypesPluginOptions, RemoteManifestUrls } from '../types';

export function getRemoteManifestUrls(options?: ModuleFederationTypesPluginOptions): RemoteManifestUrls | undefined {
if (!options?.doNotUseCloudbedsRemoteManifests) {
if (options?.cloudbedsRemoteManifestsBaseUrl !== undefined) {
let baseUrl = options?.cloudbedsRemoteManifestsBaseUrl;
if (!baseUrl || baseUrl === 'use-domain-name') {
baseUrl = `${CLOUDBEDS_DEV_FRONTEND_ASSETS_DOMAIN}/remotes/dev-ga`;
Expand Down
7 changes: 3 additions & 4 deletions src/helpers/compileTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import ts from 'typescript';

import { getLogger } from './logger';

import { DIR_SRC_TYPES } from '../constants';
import { CompileTypesResult, FederationConfig } from '../types';
import { getAllFilePaths } from './files';

Expand All @@ -27,7 +26,7 @@ export function reportCompileDiagnostic(diagnostic: ts.Diagnostic): void {
logger.log(' at', `${diagnostic.file!.fileName}:${line + 1}`, '\n');
}

export function compileTypes(exposedComponents: string[], outFile: string): CompileTypesResult {
export function compileTypes(exposedComponents: string[], outFile: string, dirGlobalTypes: string): CompileTypesResult {
const logger = getLogger();

const exposedFileNames = Object.values(exposedComponents);
Expand All @@ -44,8 +43,8 @@ export function compileTypes(exposedComponents: string[], outFile: string): Comp
host.writeFile = (_fileName: string, contents: string) => fileContent = contents;

// Including global type definitions from `src/@types` directory
if (fs.existsSync(DIR_SRC_TYPES)) {
exposedFileNames.push(...getAllFilePaths(`./${DIR_SRC_TYPES}`).filter(path => path.endsWith('.d.ts')));
if (fs.existsSync(dirGlobalTypes)) {
exposedFileNames.push(...getAllFilePaths(`./${dirGlobalTypes}`).filter(path => path.endsWith('.d.ts')));
}
logger.log('Including a set of root files in compilation', exposedFileNames);

Expand Down
14 changes: 10 additions & 4 deletions src/helpers/downloadTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import fs from 'fs';
import mkdirp from 'mkdirp';
import path from 'path';

import { DIR_DOWNLOADED_TYPES, DIR_EMITTED_TYPES } from '../constants';
import { RemoteManifest, RemoteManifestUrls, RemotesRegistryManifest } from '../types';

import { getLogger } from './logger';
Expand All @@ -15,10 +14,10 @@ async function downloadRemoteEntryManifest(url: string): Promise<unknown> {
return JSON.parse(json);
}

async function downloadRemoteEntryTypes(remoteName: string, dtsUrl: string): Promise<void> {
async function downloadRemoteEntryTypes(remoteName: string, dtsUrl: string, dirDownloadedTypes: string): Promise<void> {
const logger = getLogger();
const types = (await download(dtsUrl, downloadOptions)).toString();
const outDir = path.join(DIR_DOWNLOADED_TYPES, remoteName);
const outDir = path.join(dirDownloadedTypes, remoteName);
const outFile = path.join(outDir, 'index.d.ts');
let shouldWriteFile = true;

Expand Down Expand Up @@ -71,6 +70,8 @@ export async function downloadRemoteEntryURLsFromManifests(remoteManifestUrls?:
}

export async function downloadTypes(
dirEmittedTypes: string,
dirDownloadedTypes: string,
remotes: Record<string, string>,
remoteManifestUrls?: RemoteManifestUrls,
): Promise<void> {
Expand All @@ -91,8 +92,13 @@ export async function downloadTypes(
try {
const remoteEntryUrl = remoteEntryURLs[remoteName] || remoteLocation.split('@')[1];
const remoteEntryBaseUrl = remoteEntryUrl.split('/').slice(0, -1).join('/');
const promiseDownload = downloadRemoteEntryTypes(
remoteName,
`${remoteEntryBaseUrl}/${dirEmittedTypes}/index.d.ts`,
dirDownloadedTypes,
)

promises.push(downloadRemoteEntryTypes(remoteName, `${remoteEntryBaseUrl}/${DIR_EMITTED_TYPES}/index.d.ts`));
promises.push(promiseDownload);
} catch (err) {
logger.error(`${remoteName}: '${remoteLocation}' is not a valid remote federated module URL`);
logger.log(err);
Expand Down
16 changes: 13 additions & 3 deletions src/make-federated-types.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
#!/usr/bin/env node

import parseArgs from 'minimist';
import path from 'path';

import { DIR_DIST, DIR_EMITTED_TYPES } from './constants';
import { DEFAULT_DIR_DIST, DEFAULT_DIR_EMITTED_TYPES, DEFAULT_DIR_GLOBAL_TYPES } from './constants';
import { compileTypes, rewritePathsWithExposedFederatedModules } from './helpers/compileTypes';
import { assertRunningFromRoot, getFederationConfig } from './helpers/cli';

assertRunningFromRoot();

const argv = parseArgs(process.argv.slice(2), {
alias: {
'global-types': 'g',
'output-types-folder': 'o',
},
});

const federationConfig = getFederationConfig();
const compileFiles = Object.values(federationConfig.exposes);

const outFile = path.join(DIR_DIST, DIR_EMITTED_TYPES, 'index.d.ts');
const outDir = argv['output-types-folder'] || path.join(DEFAULT_DIR_DIST, DEFAULT_DIR_EMITTED_TYPES);
const outFile = path.join(outDir, 'index.d.ts');
const dirGlobalTypes = argv['global-types'] || DEFAULT_DIR_GLOBAL_TYPES;

console.log(`Emitting types for ${compileFiles.length} exposed module(s)`);

const { isSuccess, typeDefinitions } = compileTypes(compileFiles as string[], outFile);
const { isSuccess, typeDefinitions } = compileTypes(compileFiles as string[], outFile, dirGlobalTypes);
if (!isSuccess) {
process.exit(1);
}
Expand Down
4 changes: 3 additions & 1 deletion src/plugin.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import webpack, { Compilation, Compiler } from 'webpack';
import { downloadTypes } from './helpers/downloadTypes';
import { ModuleFederationTypesPlugin } from './plugin';
import { ModuleFederationPluginOptions, ModuleFederationTypesPluginOptions } from './types';
import { CloudbedsMicrofrontend } from './constants';
import { CloudbedsMicrofrontend, DEFAULT_DIR_DOWNLOADED_TYPES, DEFAULT_DIR_EMITTED_TYPES } from './constants';

jest.mock('./helpers/downloadTypes');

Expand Down Expand Up @@ -64,6 +64,8 @@ describe('ModuleFederationTypesPlugin', () => {
installPlugin(moduleFederationPluginOptions, typesPluginOptions);

expect(mockDownloadTypes.mock.calls[0]).toEqual([
DEFAULT_DIR_EMITTED_TYPES,
DEFAULT_DIR_DOWNLOADED_TYPES,
moduleFederationPluginOptions.remotes,
typesPluginOptions.remoteManifestUrls,
]);
Expand Down
Loading

0 comments on commit 6022a8d

Please sign in to comment.