From 17c50a38f1f5e62a3159a1fed084626acc52341a Mon Sep 17 00:00:00 2001 From: 2heal1 Date: Wed, 13 Mar 2024 11:50:43 +0800 Subject: [PATCH] chore: sink native-federation-typescript capability into dts-kit --- packages/dts-kit/.eslintrc.json | 19 +++++ packages/dts-kit/CHANGELOG.md | 1 + packages/dts-kit/LICENSE | 21 +++++ packages/dts-kit/README.md | 1 + packages/dts-kit/package.json | 39 ++++++++++ packages/dts-kit/project.json | 52 +++++++++++++ .../src/configurations/hostPlugin.test.ts | 8 ++ .../src/configurations/hostPlugin.ts | 4 + .../src/configurations/remotePlugin.test.ts | 4 + .../src/configurations/remotePlugin.ts | 2 + .../src/configurations/tsconfig.test.json | 0 packages/dts-kit/src/index.ts | 9 +++ .../src/interfaces/DTSManagerOptions.ts | 7 ++ .../src/interfaces/HostOptions.ts | 4 + .../src/interfaces/RemoteOptions.ts | 2 + packages/dts-kit/src/lib/DTSManager.ts | 73 ++++++++++++++++++ .../src/lib/archiveHandler.test.ts | 4 + .../src/lib/archiveHandler.ts | 0 .../src/lib/typeScriptCompiler.test.ts | 2 + .../src/lib/typeScriptCompiler.ts | 0 packages/dts-kit/src/lib/utils.ts | 7 ++ packages/dts-kit/tsconfig.json | 12 +++ packages/dts-kit/tsconfig.lib.json | 16 ++++ packages/dts-kit/tsconfig.spec.json | 19 +++++ packages/dts-kit/tsup.config.ts | 20 +++++ packages/dts-kit/typedoc.json | 5 ++ packages/dts-kit/vite.config.ts | 24 ++++++ .../native-federation-typescript/package.json | 6 +- .../native-federation-typescript/src/index.ts | 74 +++++------------- .../native-federation-typescript/src/vite.ts | 5 +- .../src/webpack.ts | 4 +- pnpm-lock.yaml | 76 +++++++++++++++---- 32 files changed, 443 insertions(+), 77 deletions(-) create mode 100644 packages/dts-kit/.eslintrc.json create mode 100644 packages/dts-kit/CHANGELOG.md create mode 100644 packages/dts-kit/LICENSE create mode 100644 packages/dts-kit/README.md create mode 100644 packages/dts-kit/package.json create mode 100644 packages/dts-kit/project.json rename packages/{native-federation-typescript => dts-kit}/src/configurations/hostPlugin.test.ts (92%) rename packages/{native-federation-typescript => dts-kit}/src/configurations/hostPlugin.ts (95%) rename packages/{native-federation-typescript => dts-kit}/src/configurations/remotePlugin.test.ts (96%) rename packages/{native-federation-typescript => dts-kit}/src/configurations/remotePlugin.ts (97%) rename packages/{native-federation-typescript => dts-kit}/src/configurations/tsconfig.test.json (100%) create mode 100644 packages/dts-kit/src/index.ts create mode 100644 packages/dts-kit/src/interfaces/DTSManagerOptions.ts rename packages/{native-federation-typescript => dts-kit}/src/interfaces/HostOptions.ts (65%) rename packages/{native-federation-typescript => dts-kit}/src/interfaces/RemoteOptions.ts (80%) create mode 100644 packages/dts-kit/src/lib/DTSManager.ts rename packages/{native-federation-typescript => dts-kit}/src/lib/archiveHandler.test.ts (97%) rename packages/{native-federation-typescript => dts-kit}/src/lib/archiveHandler.ts (100%) rename packages/{native-federation-typescript => dts-kit}/src/lib/typeScriptCompiler.test.ts (98%) rename packages/{native-federation-typescript => dts-kit}/src/lib/typeScriptCompiler.ts (100%) create mode 100644 packages/dts-kit/src/lib/utils.ts create mode 100644 packages/dts-kit/tsconfig.json create mode 100644 packages/dts-kit/tsconfig.lib.json create mode 100644 packages/dts-kit/tsconfig.spec.json create mode 100644 packages/dts-kit/tsup.config.ts create mode 100644 packages/dts-kit/typedoc.json create mode 100644 packages/dts-kit/vite.config.ts diff --git a/packages/dts-kit/.eslintrc.json b/packages/dts-kit/.eslintrc.json new file mode 100644 index 00000000000..915314d42e0 --- /dev/null +++ b/packages/dts-kit/.eslintrc.json @@ -0,0 +1,19 @@ +{ + "parser": "@typescript-eslint/parser", + "plugins": ["@typescript-eslint", "simple-import-sort"], + "extends": [ + "../../.eslintrc.json", + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended" + ], + "ignorePatterns": ["!**/*"], + "rules": { + "@typescript-eslint/explicit-module-boundary-types": 0, + "@typescript-eslint/camelcase": 0, + "@typescript-eslint/no-var-requires": 0, + "@typescript-eslint/no-unused-vars": "error", + "@typescript-eslint/no-non-null-assertion": 0, + "@typescript-eslint/no-explicit-any": "off" + } +} diff --git a/packages/dts-kit/CHANGELOG.md b/packages/dts-kit/CHANGELOG.md new file mode 100644 index 00000000000..e5eb3724a61 --- /dev/null +++ b/packages/dts-kit/CHANGELOG.md @@ -0,0 +1 @@ +# @module-federation/dts-kit diff --git a/packages/dts-kit/LICENSE b/packages/dts-kit/LICENSE new file mode 100644 index 00000000000..5a84d6beff2 --- /dev/null +++ b/packages/dts-kit/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Matteo Pietro Dazzi and NearForm Limited + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/dts-kit/README.md b/packages/dts-kit/README.md new file mode 100644 index 00000000000..e5eb3724a61 --- /dev/null +++ b/packages/dts-kit/README.md @@ -0,0 +1 @@ +# @module-federation/dts-kit diff --git a/packages/dts-kit/package.json b/packages/dts-kit/package.json new file mode 100644 index 00000000000..7ae7382625b --- /dev/null +++ b/packages/dts-kit/package.json @@ -0,0 +1,39 @@ +{ + "name": "@module-federation/dts-kit", + "version": "0.3.1", + "description": "Bundler federated types", + "keywords": [ + "module federation", + "typescript", + "remote types", + "federated types" + ], + "files": [ + "dist/", + "README.md" + ], + "publishConfig": { + "access": "public" + }, + "exports": { + ".": { + "import": "./dist/index.mjs", + "require": "./dist/index.js", + "types": "./dist/index.d.ts" + } + }, + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "author": "Matteo Pietro Dazzi (https://github.com/ilteoood)", + "license": "MIT", + "dependencies": { + "adm-zip": "^0.5.10", + "ansi-colors": "^4.1.3", + "axios": "^1.6.7", + "rambda": "^9.1.0" + }, + "peerDependencies": { + "typescript": "^4.9.0 || ^5.0.0", + "vue-tsc": "^1.0.24" + } +} diff --git a/packages/dts-kit/project.json b/packages/dts-kit/project.json new file mode 100644 index 00000000000..58eb348aff6 --- /dev/null +++ b/packages/dts-kit/project.json @@ -0,0 +1,52 @@ +{ + "name": "dts-kit", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "packages/dts-kit/src", + "projectType": "library", + "targets": { + "build": { + "executor": "nx:run-commands", + "outputs": ["{workspaceRoot}/packages/dts-kit/dist"], + "options": { + "parallel": false, + "commands": [ + "tsup --config packages/dts-kit/tsup.config.ts", + "cp packages/dts-kit/package.json packages/dts-kit/dist", + "cp packages/dts-kit/*.md packages/dts-kit/dist" + ] + } + }, + "lint": { + "executor": "@nx/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["packages/dts-kit/**/*.ts"] + } + }, + "test": { + "executor": "@nx/vite:test", + "outputs": ["{workspaceRoot}/coverage/packages/dts-kit"] + }, + "pre-release": { + "executor": "nx:run-commands", + "options": { + "parallel": false, + "commands": [ + { + "command": "nx run dts-kit:test", + "forwardAllArgs": false + }, + { + "command": "nx run dts-kit:build", + "forwardAllArgs": false + } + ] + } + }, + "semantic-release": { + "executor": "@goestav/nx-semantic-release:semantic-release" + } + }, + "tags": ["package"], + "implicitDependencies": [] +} diff --git a/packages/native-federation-typescript/src/configurations/hostPlugin.test.ts b/packages/dts-kit/src/configurations/hostPlugin.test.ts similarity index 92% rename from packages/native-federation-typescript/src/configurations/hostPlugin.test.ts rename to packages/dts-kit/src/configurations/hostPlugin.test.ts index 93a343816b7..03368ab4376 100644 --- a/packages/native-federation-typescript/src/configurations/hostPlugin.test.ts +++ b/packages/dts-kit/src/configurations/hostPlugin.test.ts @@ -33,6 +33,10 @@ describe('hostPlugin', () => { typesFolder: '@mf-types', deleteTypesFolder: true, maxRetries: 3, + implementation: '', + devServer: { + typesReload: true, + }, }); expect(mapRemotesToDownload).toStrictEqual({ @@ -46,6 +50,10 @@ describe('hostPlugin', () => { typesFolder: 'custom-types', deleteTypesFolder: false, maxRetries: 1, + implementation: '', + devServer: { + typesReload: true, + }, }; const { hostOptions, mapRemotesToDownload } = diff --git a/packages/native-federation-typescript/src/configurations/hostPlugin.ts b/packages/dts-kit/src/configurations/hostPlugin.ts similarity index 95% rename from packages/native-federation-typescript/src/configurations/hostPlugin.ts rename to packages/dts-kit/src/configurations/hostPlugin.ts index 3d767f9da91..a9d87c6841a 100644 --- a/packages/native-federation-typescript/src/configurations/hostPlugin.ts +++ b/packages/dts-kit/src/configurations/hostPlugin.ts @@ -4,6 +4,10 @@ const defaultOptions = { typesFolder: '@mf-types', deleteTypesFolder: true, maxRetries: 3, + implementation: '', + devServer: { + typesReload: true, + }, } satisfies Partial; const retrieveRemoteStringUrl = (remote: string) => { diff --git a/packages/native-federation-typescript/src/configurations/remotePlugin.test.ts b/packages/dts-kit/src/configurations/remotePlugin.test.ts similarity index 96% rename from packages/native-federation-typescript/src/configurations/remotePlugin.test.ts rename to packages/dts-kit/src/configurations/remotePlugin.test.ts index 4fd698b650c..4e3d73c74db 100644 --- a/packages/native-federation-typescript/src/configurations/remotePlugin.test.ts +++ b/packages/dts-kit/src/configurations/remotePlugin.test.ts @@ -63,6 +63,8 @@ describe('hostPlugin', () => { deleteTypesFolder: true, moduleFederationConfig, compilerInstance: 'tsc', + compileInChildProcess: false, + implementation: '', }); }); @@ -107,6 +109,8 @@ describe('hostPlugin', () => { deleteTypesFolder: false, moduleFederationConfig, compilerInstance: 'vue-tsc', + compileInChildProcess: false, + implementation: '', }); }); }); diff --git a/packages/native-federation-typescript/src/configurations/remotePlugin.ts b/packages/dts-kit/src/configurations/remotePlugin.ts similarity index 97% rename from packages/native-federation-typescript/src/configurations/remotePlugin.ts rename to packages/dts-kit/src/configurations/remotePlugin.ts index 3ec52928270..f5726185ef1 100644 --- a/packages/native-federation-typescript/src/configurations/remotePlugin.ts +++ b/packages/dts-kit/src/configurations/remotePlugin.ts @@ -11,6 +11,8 @@ const defaultOptions = { deleteTypesFolder: true, additionalFilesToCompile: [], compilerInstance: 'tsc' as const, + compileInChildProcess: false, + implementation: '', } satisfies Partial; const readTsConfig = ({ diff --git a/packages/native-federation-typescript/src/configurations/tsconfig.test.json b/packages/dts-kit/src/configurations/tsconfig.test.json similarity index 100% rename from packages/native-federation-typescript/src/configurations/tsconfig.test.json rename to packages/dts-kit/src/configurations/tsconfig.test.json diff --git a/packages/dts-kit/src/index.ts b/packages/dts-kit/src/index.ts new file mode 100644 index 00000000000..f100e9bc755 --- /dev/null +++ b/packages/dts-kit/src/index.ts @@ -0,0 +1,9 @@ +export { retrieveRemoteConfig } from './configurations/remotePlugin'; +export { retrieveHostConfig } from './configurations/hostPlugin'; +export { getDTSManagerConstructor } from './lib/utils'; +export { retrieveOriginalOutDir } from './lib/typeScriptCompiler'; +export { DTSManager } from './lib/DTSManager'; + +export { DTSManagerOptions } from './interfaces/DTSManagerOptions'; +export { HostOptions } from './interfaces/HostOptions'; +export { RemoteOptions } from './interfaces/RemoteOptions'; diff --git a/packages/dts-kit/src/interfaces/DTSManagerOptions.ts b/packages/dts-kit/src/interfaces/DTSManagerOptions.ts new file mode 100644 index 00000000000..bf292e673fe --- /dev/null +++ b/packages/dts-kit/src/interfaces/DTSManagerOptions.ts @@ -0,0 +1,7 @@ +import { HostOptions } from './HostOptions'; +import { RemoteOptions } from './RemoteOptions'; + +export interface DTSManagerOptions { + remote?: RemoteOptions; + host?: HostOptions; +} diff --git a/packages/native-federation-typescript/src/interfaces/HostOptions.ts b/packages/dts-kit/src/interfaces/HostOptions.ts similarity index 65% rename from packages/native-federation-typescript/src/interfaces/HostOptions.ts rename to packages/dts-kit/src/interfaces/HostOptions.ts index 5a90b1648a8..8321393393b 100644 --- a/packages/native-federation-typescript/src/interfaces/HostOptions.ts +++ b/packages/dts-kit/src/interfaces/HostOptions.ts @@ -3,4 +3,8 @@ export interface HostOptions { typesFolder?: string; deleteTypesFolder?: boolean; maxRetries?: number; + devServer?: { + typesReload?: boolean; + }; + implementation?: string; } diff --git a/packages/native-federation-typescript/src/interfaces/RemoteOptions.ts b/packages/dts-kit/src/interfaces/RemoteOptions.ts similarity index 80% rename from packages/native-federation-typescript/src/interfaces/RemoteOptions.ts rename to packages/dts-kit/src/interfaces/RemoteOptions.ts index 838a5ff5b5e..332be1ee3c0 100644 --- a/packages/native-federation-typescript/src/interfaces/RemoteOptions.ts +++ b/packages/dts-kit/src/interfaces/RemoteOptions.ts @@ -6,4 +6,6 @@ export interface RemoteOptions { deleteTypesFolder?: boolean; additionalFilesToCompile?: string[]; compilerInstance?: 'tsc' | 'vue-tsc'; + compileInChildProcess?: boolean; + implementation?: string; } diff --git a/packages/dts-kit/src/lib/DTSManager.ts b/packages/dts-kit/src/lib/DTSManager.ts new file mode 100644 index 00000000000..33dea3fe4d5 --- /dev/null +++ b/packages/dts-kit/src/lib/DTSManager.ts @@ -0,0 +1,73 @@ +import ansiColors from 'ansi-colors'; +import { rm } from 'fs/promises'; +import { retrieveRemoteConfig } from '../configurations/remotePlugin'; +import { createTypesArchive, downloadTypesArchive } from './archiveHandler'; +import { compileTs, retrieveMfTypesPath } from './typeScriptCompiler'; +import { retrieveHostConfig } from '../configurations/hostPlugin'; +import { DTSManagerOptions } from '../interfaces/DTSManagerOptions'; + +class DTSManager { + options: DTSManagerOptions; + + constructor(options: DTSManagerOptions) { + this.options = options; + } + + async generateTypes() { + try { + const { options } = this; + if (!options.remote) { + throw new Error( + 'options.remote is required if you want to generateTypes', + ); + } + const { remoteOptions, tsConfig, mapComponentsToExpose } = + retrieveRemoteConfig(options.remote); + compileTs(mapComponentsToExpose, tsConfig, remoteOptions); + + await createTypesArchive(tsConfig, remoteOptions); + + if (remoteOptions.deleteTypesFolder) { + await rm(retrieveMfTypesPath(tsConfig, remoteOptions), { + recursive: true, + force: true, + }); + } + console.log(ansiColors.green('Federated types created correctly')); + } catch (error) { + console.error( + ansiColors.red(`Unable to compile federated types, ${error}`), + ); + } + } + + async consumeTypes() { + const { options } = this; + if (!options.host) { + throw new Error('options.host is required if you want to consumeTypes'); + } + const { hostOptions, mapRemotesToDownload } = retrieveHostConfig( + options.host, + ); + + if (hostOptions.deleteTypesFolder) { + await rm(hostOptions.typesFolder, { + recursive: true, + force: true, + }).catch((error) => + console.error( + ansiColors.red(`Unable to remove types folder, ${error}`), + ), + ); + } + + const typesDownloader = downloadTypesArchive(hostOptions); + const downloadPromises = + Object.entries(mapRemotesToDownload).map(typesDownloader); + + await Promise.allSettled(downloadPromises); + console.log(ansiColors.green('Federated types extraction completed')); + } +} + +export { DTSManager }; diff --git a/packages/native-federation-typescript/src/lib/archiveHandler.test.ts b/packages/dts-kit/src/lib/archiveHandler.test.ts similarity index 97% rename from packages/native-federation-typescript/src/lib/archiveHandler.test.ts rename to packages/dts-kit/src/lib/archiveHandler.test.ts index ee827daf237..713b7b85d4a 100644 --- a/packages/native-federation-typescript/src/lib/archiveHandler.test.ts +++ b/packages/dts-kit/src/lib/archiveHandler.test.ts @@ -52,6 +52,10 @@ describe('archiveHandler', () => { typesFolder: tmpDir, deleteTypesFolder: true, maxRetries: 3, + implementation: '', + devServer: { + typesReload: true, + }, }; const destinationFolder = 'typesHostFolder'; diff --git a/packages/native-federation-typescript/src/lib/archiveHandler.ts b/packages/dts-kit/src/lib/archiveHandler.ts similarity index 100% rename from packages/native-federation-typescript/src/lib/archiveHandler.ts rename to packages/dts-kit/src/lib/archiveHandler.ts diff --git a/packages/native-federation-typescript/src/lib/typeScriptCompiler.test.ts b/packages/dts-kit/src/lib/typeScriptCompiler.test.ts similarity index 98% rename from packages/native-federation-typescript/src/lib/typeScriptCompiler.test.ts rename to packages/dts-kit/src/lib/typeScriptCompiler.test.ts index 7ded9d123fe..a06a29dec29 100644 --- a/packages/native-federation-typescript/src/lib/typeScriptCompiler.test.ts +++ b/packages/dts-kit/src/lib/typeScriptCompiler.test.ts @@ -26,6 +26,8 @@ describe('typeScriptCompiler', () => { tsConfigPath: './tsconfig.json', deleteTypesFolder: false, compilerInstance: 'tsc', + compileInChildProcess: false, + implementation: '', }; it('retrieveMfTypesPath correctly calculate path', () => { diff --git a/packages/native-federation-typescript/src/lib/typeScriptCompiler.ts b/packages/dts-kit/src/lib/typeScriptCompiler.ts similarity index 100% rename from packages/native-federation-typescript/src/lib/typeScriptCompiler.ts rename to packages/dts-kit/src/lib/typeScriptCompiler.ts diff --git a/packages/dts-kit/src/lib/utils.ts b/packages/dts-kit/src/lib/utils.ts new file mode 100644 index 00000000000..2770a0a3b5e --- /dev/null +++ b/packages/dts-kit/src/lib/utils.ts @@ -0,0 +1,7 @@ +import { DTSManager } from './DTSManager'; + +export function getDTSManagerConstructor( + implementation?: string, +): typeof DTSManager { + return implementation ? require(implementation) : DTSManager; +} diff --git a/packages/dts-kit/tsconfig.json b/packages/dts-kit/tsconfig.json new file mode 100644 index 00000000000..0e105b88cc2 --- /dev/null +++ b/packages/dts-kit/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "es2017", + "module": "esnext", + "lib": ["esnext"], + "moduleResolution": "node", + "esModuleInterop": true, + "strict": true, + "strictNullChecks": true, + "resolveJsonModule": true + } +} diff --git a/packages/dts-kit/tsconfig.lib.json b/packages/dts-kit/tsconfig.lib.json new file mode 100644 index 00000000000..e668d0d06f1 --- /dev/null +++ b/packages/dts-kit/tsconfig.lib.json @@ -0,0 +1,16 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "declaration": true, + "skipLibCheck": true, + "types": [] + }, + "include": ["**/*.ts"], + "exclude": [ + "jest.config.ts", + "**/*.spec.ts", + "**/*.test.ts", + "tsup.config.ts" + ] +} diff --git a/packages/dts-kit/tsconfig.spec.json b/packages/dts-kit/tsconfig.spec.json new file mode 100644 index 00000000000..6d3be742713 --- /dev/null +++ b/packages/dts-kit/tsconfig.spec.json @@ -0,0 +1,19 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "types": ["vitest/globals", "vitest/importMeta", "vite/client", "node"] + }, + "include": [ + "vite.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.test.tsx", + "src/**/*.spec.tsx", + "src/**/*.test.js", + "src/**/*.spec.js", + "src/**/*.test.jsx", + "src/**/*.spec.jsx", + "src/**/*.d.ts" + ] +} diff --git a/packages/dts-kit/tsup.config.ts b/packages/dts-kit/tsup.config.ts new file mode 100644 index 00000000000..0b83ea33dba --- /dev/null +++ b/packages/dts-kit/tsup.config.ts @@ -0,0 +1,20 @@ +import { join } from 'path'; +import { defineConfig } from 'tsup'; + +const SUPPORTED_BUNDLERS = ['esbuild', 'rollup', 'vite', 'webpack', 'rspack']; + +export default defineConfig({ + entry: [ + join(__dirname, 'src', 'index.ts'), + ...SUPPORTED_BUNDLERS.map((bundler) => + join(__dirname, 'src', `${bundler}.ts`), + ), + ], + dts: true, + splitting: true, + clean: true, + minify: true, + format: ['cjs', 'esm'], + outDir: 'packages/dts-kit/dist', + external: [join(__dirname, 'package.json')], +}); diff --git a/packages/dts-kit/typedoc.json b/packages/dts-kit/typedoc.json new file mode 100644 index 00000000000..04b843ffaa8 --- /dev/null +++ b/packages/dts-kit/typedoc.json @@ -0,0 +1,5 @@ +{ + "extends": ["../../typedoc.base.json"], + "entryPoints": ["src/index.ts"], + "tsconfig": "tsconfig.lib.json" +} diff --git a/packages/dts-kit/vite.config.ts b/packages/dts-kit/vite.config.ts new file mode 100644 index 00000000000..f0e0ded9efa --- /dev/null +++ b/packages/dts-kit/vite.config.ts @@ -0,0 +1,24 @@ +/// +import { defineConfig } from 'vite'; + +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; + +export default defineConfig({ + cacheDir: '../../node_modules/.vite/dts-kit', + + plugins: [nxViteTsPaths()], + + // Uncomment this if you are using workers. + // worker: { + // plugins: [ nxViteTsPaths() ], + // }, + + test: { + cache: { + dir: '../../node_modules/.vitest', + }, + environment: 'node', + include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], + reporters: ['default'], + }, +}); diff --git a/packages/native-federation-typescript/package.json b/packages/native-federation-typescript/package.json index 129d0465654..4fa4e81e396 100644 --- a/packages/native-federation-typescript/package.json +++ b/packages/native-federation-typescript/package.json @@ -52,11 +52,9 @@ "author": "Matteo Pietro Dazzi (https://github.com/ilteoood)", "license": "MIT", "dependencies": { - "adm-zip": "^0.5.10", - "ansi-colors": "^4.1.3", - "axios": "^1.6.7", "rambda": "^9.1.0", - "unplugin": "^1.7.1" + "unplugin": "^1.7.1", + "@module-federation/dts-kit": "workspace:*" }, "peerDependencies": { "typescript": "^4.9.0 || ^5.0.0", diff --git a/packages/native-federation-typescript/src/index.ts b/packages/native-federation-typescript/src/index.ts index eb5c4d00ac1..ec73193eb8b 100644 --- a/packages/native-federation-typescript/src/index.ts +++ b/packages/native-federation-typescript/src/index.ts @@ -1,51 +1,32 @@ -import ansiColors from 'ansi-colors'; -import { rm } from 'fs/promises'; import { resolve } from 'path'; import { mergeDeepRight } from 'rambda'; -import { UnpluginOptions, createUnplugin } from 'unplugin'; - -import { retrieveHostConfig } from './configurations/hostPlugin'; -import { retrieveRemoteConfig } from './configurations/remotePlugin'; -import { HostOptions } from './interfaces/HostOptions'; -import { RemoteOptions } from './interfaces/RemoteOptions'; -import { createTypesArchive, downloadTypesArchive } from './lib/archiveHandler'; +import { createUnplugin } from 'unplugin'; import { - compileTs, - retrieveMfTypesPath, + RemoteOptions, + HostOptions, + retrieveRemoteConfig, + getDTSManagerConstructor, retrieveOriginalOutDir, -} from './lib/typeScriptCompiler'; +} from '@module-federation/dts-kit'; export const NativeFederationTypeScriptRemote = createUnplugin( (options: RemoteOptions) => { - const { remoteOptions, tsConfig, mapComponentsToExpose } = - retrieveRemoteConfig(options); + const DTSManagerConstructor = getDTSManagerConstructor( + options.implementation, + ); + const dtsManager = new DTSManagerConstructor({ remote: options }); + const { remoteOptions, tsConfig } = retrieveRemoteConfig(options); return { name: 'native-federation-typescript/remote', async writeBundle() { - try { - compileTs(mapComponentsToExpose, tsConfig, remoteOptions); - - await createTypesArchive(tsConfig, remoteOptions); - - if (remoteOptions.deleteTypesFolder) { - await rm(retrieveMfTypesPath(tsConfig, remoteOptions), { - recursive: true, - force: true, - }); - } - console.log(ansiColors.green('Federated types created correctly')); - } catch (error) { - console.error( - ansiColors.red(`Unable to compile federated types, ${error}`), - ); - } + await dtsManager.generateTypes(); }, get vite() { return process.env.NODE_ENV === 'production' ? undefined : { - buildStart: (this as UnpluginOptions).writeBundle, - watchChange: (this as UnpluginOptions).writeBundle, + buildStart: dtsManager.generateTypes, + watchChange: dtsManager.generateTypes, }; }, webpack: (compiler) => { @@ -78,34 +59,21 @@ export const NativeFederationTypeScriptRemote = createUnplugin( export const NativeFederationTypeScriptHost = createUnplugin( (options: HostOptions) => { - const { hostOptions, mapRemotesToDownload } = retrieveHostConfig(options); + const DTSManagerConstructor = getDTSManagerConstructor( + options.implementation, + ); + const dtsManager = new DTSManagerConstructor({ host: options }); return { name: 'native-federation-typescript/host', async writeBundle() { - if (hostOptions.deleteTypesFolder) { - await rm(hostOptions.typesFolder, { - recursive: true, - force: true, - }).catch((error) => - console.error( - ansiColors.red(`Unable to remove types folder, ${error}`), - ), - ); - } - - const typesDownloader = downloadTypesArchive(hostOptions); - const downloadPromises = - Object.entries(mapRemotesToDownload).map(typesDownloader); - - await Promise.allSettled(downloadPromises); - console.log(ansiColors.green('Federated types extraction completed')); + await dtsManager.consumeTypes(); }, get vite() { return process.env.NODE_ENV === 'production' ? undefined : { - buildStart: (this as UnpluginOptions).writeBundle, - watchChange: (this as UnpluginOptions).writeBundle, + buildStart: dtsManager.consumeTypes, + watchChange: dtsManager.consumeTypes, }; }, }; diff --git a/packages/native-federation-typescript/src/vite.ts b/packages/native-federation-typescript/src/vite.ts index a09225b9398..21bb58a961c 100644 --- a/packages/native-federation-typescript/src/vite.ts +++ b/packages/native-federation-typescript/src/vite.ts @@ -1,9 +1,10 @@ +import { RemoteOptions, HostOptions } from '@module-federation/dts-kit'; + import { NativeFederationTypeScriptHost as GeneralHost, NativeFederationTypeScriptRemote as GeneralRemote, } from '.'; -import { HostOptions } from './interfaces/HostOptions'; -import { RemoteOptions } from './interfaces/RemoteOptions'; + export const NativeFederationTypeScriptRemote = GeneralRemote.vite as ( options: RemoteOptions, ) => any; diff --git a/packages/native-federation-typescript/src/webpack.ts b/packages/native-federation-typescript/src/webpack.ts index a1424f57c75..b18a3b67038 100644 --- a/packages/native-federation-typescript/src/webpack.ts +++ b/packages/native-federation-typescript/src/webpack.ts @@ -1,13 +1,11 @@ import { WebpackPluginInstance } from 'unplugin'; +import { RemoteOptions, HostOptions } from '@module-federation/dts-kit'; import { NativeFederationTypeScriptHost as GeneralHost, NativeFederationTypeScriptRemote as GeneralRemote, } from '.'; -import { HostOptions } from './interfaces/HostOptions'; -import { RemoteOptions } from './interfaces/RemoteOptions'; - export const NativeFederationTypeScriptRemote: ( options: RemoteOptions, ) => WebpackPluginInstance = GeneralRemote.webpack; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cf40a1c5c99..d6136b130f3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1156,6 +1156,27 @@ importers: specifier: 8.5.3 version: 8.5.3 + packages/dts-kit: + dependencies: + adm-zip: + specifier: ^0.5.10 + version: 0.5.10 + ansi-colors: + specifier: ^4.1.3 + version: 4.1.3 + axios: + specifier: ^1.6.7 + version: 1.6.7 + rambda: + specifier: ^9.1.0 + version: 9.1.0 + typescript: + specifier: ^4.9.0 || ^5.0.0 + version: 5.0.4 + vue-tsc: + specifier: ^1.0.24 + version: 1.8.27(typescript@5.0.4) + packages/enhanced: dependencies: '@module-federation/managers': @@ -1254,15 +1275,9 @@ importers: packages/native-federation-typescript: dependencies: - adm-zip: - specifier: ^0.5.10 - version: 0.5.10 - ansi-colors: - specifier: ^4.1.3 - version: 4.1.3 - axios: - specifier: ^1.6.7 - version: 1.6.7 + '@module-federation/dts-kit': + specifier: workspace:* + version: link:../dts-kit rambda: specifier: ^9.1.0 version: 9.1.0 @@ -13778,6 +13793,26 @@ packages: '@vue/compiler-core': 3.4.21 '@vue/shared': 3.4.21 + /@vue/language-core@1.8.27(typescript@5.0.4): + resolution: {integrity: sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@volar/language-core': 1.11.1 + '@volar/source-map': 1.11.1 + '@vue/compiler-dom': 3.4.21 + '@vue/shared': 3.4.21 + computeds: 0.0.1 + minimatch: 9.0.3 + muggle-string: 0.3.1 + path-browserify: 1.0.1 + typescript: 5.0.4 + vue-template-compiler: 2.7.16 + dev: false + /@vue/language-core@1.8.27(typescript@5.3.3): resolution: {integrity: sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==} peerDependencies: @@ -15699,7 +15734,7 @@ packages: /builtins@5.0.1: resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==} dependencies: - semver: 7.5.3 + semver: 7.6.0 dev: true /bundle-name@4.1.0: @@ -20706,7 +20741,7 @@ packages: fs.realpath: 1.0.0 inflight: 1.0.6 inherits: 2.0.4 - minimatch: 3.0.5 + minimatch: 3.1.2 once: 1.4.0 path-is-absolute: 1.0.1 dev: true @@ -23117,7 +23152,7 @@ packages: acorn: 8.11.3 eslint-visitor-keys: 3.4.3 espree: 9.6.1 - semver: 7.5.3 + semver: 7.6.0 dev: true /jsonc-parser@3.2.0: @@ -23157,7 +23192,7 @@ packages: lodash.isstring: 4.0.1 lodash.once: 4.1.1 ms: 2.1.3 - semver: 7.5.4 + semver: 7.6.0 dev: true /jsprim@2.0.2: @@ -25412,7 +25447,7 @@ packages: dependencies: hosted-git-info: 7.0.1 proc-log: 3.0.0 - semver: 7.5.3 + semver: 7.6.0 validate-npm-package-name: 5.0.0 dev: true @@ -32355,7 +32390,6 @@ packages: resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==} engines: {node: '>=12.20'} hasBin: true - dev: true /typescript@5.1.6: resolution: {integrity: sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==} @@ -33342,6 +33376,18 @@ packages: de-indent: 1.0.2 he: 1.2.0 + /vue-tsc@1.8.27(typescript@5.0.4): + resolution: {integrity: sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==} + hasBin: true + peerDependencies: + typescript: '*' + dependencies: + '@volar/typescript': 1.11.1 + '@vue/language-core': 1.8.27(typescript@5.0.4) + semver: 7.6.0 + typescript: 5.0.4 + dev: false + /vue-tsc@1.8.27(typescript@5.3.3): resolution: {integrity: sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==} hasBin: true