From 35d925b5eb24b51716a05bac3fdb40154738ea49 Mon Sep 17 00:00:00 2001 From: Hanric Date: Wed, 26 Feb 2025 14:10:46 +0800 Subject: [PATCH] fix(dts-plugin): support remoteTypeUrls option which allow user to specify the remote types url (#3532) --- .changeset/clean-pets-kick.md | 6 ++ .changeset/curly-bears-marry.md | 6 ++ .github/workflows/e2e-modern-ssr.yml | 2 +- apps/website-new/docs/en/configure/dts.mdx | 4 +- apps/website-new/docs/zh/configure/dts.mdx | 4 +- .../core/configurations/hostPlugin.test.ts | 2 + .../src/core/configurations/hostPlugin.ts | 22 +++++-- .../dts-plugin/src/core/lib/DTSManager.ts | 61 ++++++++++++++----- packages/dts-plugin/src/core/lib/DtsWorker.ts | 2 - packages/dts-plugin/src/core/lib/utils.ts | 6 +- .../src/plugins/ConsumeTypesPlugin.ts | 47 ++++++++++---- packages/dts-plugin/src/plugins/DevPlugin.ts | 24 ++++++-- packages/dts-plugin/src/plugins/DtsPlugin.ts | 27 +++++--- .../src/plugins/GenerateTypesPlugin.ts | 29 +++++++-- packages/sdk/__tests__/parseEntry.spec.ts | 15 ++++- .../types/plugins/ModuleFederationPlugin.ts | 10 +++ packages/sdk/src/utils.ts | 7 ++- 17 files changed, 210 insertions(+), 64 deletions(-) create mode 100644 .changeset/clean-pets-kick.md create mode 100644 .changeset/curly-bears-marry.md diff --git a/.changeset/clean-pets-kick.md b/.changeset/clean-pets-kick.md new file mode 100644 index 00000000000..af8f984fdd9 --- /dev/null +++ b/.changeset/clean-pets-kick.md @@ -0,0 +1,6 @@ +--- +'@module-federation/dts-plugin': patch +'@module-federation/sdk': patch +--- + +feat(dts-plugin): support remoteTypeUrls option which allow user to specify the remote types url diff --git a/.changeset/curly-bears-marry.md b/.changeset/curly-bears-marry.md new file mode 100644 index 00000000000..0793556517f --- /dev/null +++ b/.changeset/curly-bears-marry.md @@ -0,0 +1,6 @@ +--- +"@module-federation/sdk": patch +"@module-federation/dts-plugin": patch +--- + +fix(dts-plugin): support parse @scope@manifest-url.json entry diff --git a/.github/workflows/e2e-modern-ssr.yml b/.github/workflows/e2e-modern-ssr.yml index 91434cc0d89..b32b85580cb 100644 --- a/.github/workflows/e2e-modern-ssr.yml +++ b/.github/workflows/e2e-modern-ssr.yml @@ -47,7 +47,7 @@ jobs: run: | lsof -ti tcp:3050,3051,3052,3053,3054,3055,3056 | xargs -r kill && pnpm run app:modern:dev & - sleep 1 && + sleep 30 && npx wait-on http://127.0.0.1:3050/ && npx wait-on http://127.0.0.1:3051/ && npx wait-on http://127.0.0.1:3052/ && diff --git a/apps/website-new/docs/en/configure/dts.mdx b/apps/website-new/docs/en/configure/dts.mdx index a584fa0f749..4d7e29604a2 100644 --- a/apps/website-new/docs/en/configure/dts.mdx +++ b/apps/website-new/docs/en/configure/dts.mdx @@ -48,8 +48,8 @@ When configuring `generateTypes` to `true`, the following configuration will be { "generateAPITypes": true, "abortOnError": false, - "extractThirdParty": true, - "extractRemoteTypes": true, + "extractThirdParty": false, + "extractRemoteTypes": false, "compileInChildProcess": true } ``` diff --git a/apps/website-new/docs/zh/configure/dts.mdx b/apps/website-new/docs/zh/configure/dts.mdx index 3c4b945abba..a3445e08f52 100644 --- a/apps/website-new/docs/zh/configure/dts.mdx +++ b/apps/website-new/docs/zh/configure/dts.mdx @@ -47,8 +47,8 @@ interface DtsRemoteOptions { { "generateAPITypes": true, "abortOnError": false, - "extractThirdParty": true, - "extractRemoteTypes": true, + "extractThirdParty": false, + "extractRemoteTypes": false, "compileInChildProcess": true } ``` diff --git a/packages/dts-plugin/src/core/configurations/hostPlugin.test.ts b/packages/dts-plugin/src/core/configurations/hostPlugin.test.ts index fe5cc1c0e0b..4a5de9220db 100644 --- a/packages/dts-plugin/src/core/configurations/hostPlugin.test.ts +++ b/packages/dts-plugin/src/core/configurations/hostPlugin.test.ts @@ -41,6 +41,7 @@ describe('hostPlugin', () => { abortOnError: true, consumeAPITypes: false, runtimePkgs: [], + remoteTypeUrls: {}, }); expect(mapRemotesToDownload).toStrictEqual({ @@ -66,6 +67,7 @@ describe('hostPlugin', () => { abortOnError: true, consumeAPITypes: false, runtimePkgs: [], + remoteTypeUrls: {}, }; const { hostOptions, mapRemotesToDownload } = diff --git a/packages/dts-plugin/src/core/configurations/hostPlugin.ts b/packages/dts-plugin/src/core/configurations/hostPlugin.ts index bc2f113cec1..4f05e11edbb 100644 --- a/packages/dts-plugin/src/core/configurations/hostPlugin.ts +++ b/packages/dts-plugin/src/core/configurations/hostPlugin.ts @@ -1,5 +1,4 @@ import { - MANIFEST_EXT, parseEntry, ENCODE_NAME_PREFIX, decodeName, @@ -18,6 +17,7 @@ const defaultOptions = { abortOnError: true, consumeAPITypes: false, runtimePkgs: [], + remoteTypeUrls: {}, } satisfies Partial; const buildZipUrl = (hostOptions: Required, url: string) => { @@ -45,6 +45,7 @@ export const retrieveRemoteInfo = (options: { remote: string; }): RemoteInfo => { const { hostOptions, remoteAlias, remote } = options; + const { remoteTypeUrls } = hostOptions; let decodedRemote = remote; if (decodedRemote.startsWith(ENCODE_NAME_PREFIX)) { decodedRemote = decodeName(decodedRemote, ENCODE_NAME_PREFIX); @@ -59,13 +60,26 @@ export const retrieveRemoteInfo = (options: { ? decodedRemote : ''; - const zipUrl = url ? buildZipUrl(hostOptions, url) : ''; + let zipUrl = ''; + let apiTypeUrl = ''; + const name = parsedInfo.name || remoteAlias; + if (typeof remoteTypeUrls === 'object' && remoteTypeUrls[name]) { + zipUrl = remoteTypeUrls[name].zip; + apiTypeUrl = remoteTypeUrls[name].api; + } + if (!zipUrl && url) { + zipUrl = buildZipUrl(hostOptions, url); + } + + if (!apiTypeUrl && zipUrl) { + apiTypeUrl = buildApiTypeUrl(zipUrl); + } return { - name: parsedInfo.name || remoteAlias, + name, url: url, zipUrl, - apiTypeUrl: buildApiTypeUrl(zipUrl), + apiTypeUrl, alias: remoteAlias, }; }; diff --git a/packages/dts-plugin/src/core/lib/DTSManager.ts b/packages/dts-plugin/src/core/lib/DTSManager.ts index 820db138d43..2490846cfd2 100644 --- a/packages/dts-plugin/src/core/lib/DTSManager.ts +++ b/packages/dts-plugin/src/core/lib/DTSManager.ts @@ -1,7 +1,7 @@ -import ansiColors from 'ansi-colors'; import path from 'path'; import { rm } from 'fs/promises'; import fs from 'fs'; +import fse from 'fs-extra'; import { MANIFEST_EXT, Manifest, @@ -103,21 +103,35 @@ class DTSManager { const mfTypesPath = retrieveMfTypesPath(tsConfig, remoteOptions); - if (hasRemotes) { - const tempHostOptions = { - moduleFederationConfig: remoteOptions.moduleFederationConfig, - typesFolder: path.join(mfTypesPath, 'node_modules'), - remoteTypesFolder: - remoteOptions?.hostRemoteTypesFolder || remoteOptions.typesFolder, - deleteTypesFolder: true, - context: remoteOptions.context, - implementation: remoteOptions.implementation, - abortOnError: false, - }; - await this.consumeArchiveTypes(tempHostOptions); + if (hasRemotes && this.options.host) { + try { + const { hostOptions } = retrieveHostConfig(this.options.host); + const remoteTypesFolder = path.resolve( + hostOptions.context, + hostOptions.typesFolder, + ); + + const targetDir = path.join(mfTypesPath, 'node_modules'); + if (fs.existsSync(remoteTypesFolder)) { + const targetFolder = path.resolve(remoteOptions.context, targetDir); + await fse.ensureDir(targetFolder); + await fse.copy(remoteTypesFolder, targetFolder, { overwrite: true }); + } + } catch (err) { + if (this.options.host?.abortOnError === false) { + fileLog( + `Unable to copy remote types, ${err}`, + 'extractRemoteTypes', + 'error', + ); + } else { + throw err; + } + } } } + // it must execute after consumeTypes async generateTypes() { try { const { options } = this; @@ -134,6 +148,21 @@ class DTSManager { return; } + if (tsConfig.compilerOptions.tsBuildInfoFile) { + try { + const tsBuildInfoFile = path.resolve( + remoteOptions.context, + tsConfig.compilerOptions.tsBuildInfoFile, + ); + const mfTypesPath = retrieveMfTypesPath(tsConfig, remoteOptions); + if (!fs.existsSync(mfTypesPath)) { + fs.rmSync(tsBuildInfoFile, { force: true }); + } + } catch (e) { + //noop + } + } + await this.extractRemoteTypes({ remoteOptions, tsConfig, @@ -150,7 +179,6 @@ class DTSManager { apiTypesPath = retrieveMfAPITypesPath(tsConfig, remoteOptions); fs.writeFileSync(apiTypesPath, apiTypes); } - try { if (remoteOptions.deleteTypesFolder) { await rm(retrieveMfTypesPath(tsConfig, remoteOptions), { @@ -167,7 +195,7 @@ class DTSManager { } catch (error) { if (this.options.remote?.abortOnError === false) { if (this.options.displayErrorInTerminal) { - logger.error(`Unable to compile federated types${error}`); + logger.error(`Unable to compile federated types ${error}`); } } else { throw error; @@ -182,6 +210,9 @@ class DTSManager { if (!remoteInfo.url.includes(MANIFEST_EXT)) { return remoteInfo as Required; } + if (remoteInfo.zipUrl) { + return remoteInfo as Required; + } const url = remoteInfo.url; const res = await axiosGet(url); const manifestJson = res.data as unknown as Manifest; diff --git a/packages/dts-plugin/src/core/lib/DtsWorker.ts b/packages/dts-plugin/src/core/lib/DtsWorker.ts index 0593684ecbc..b38e012a83b 100644 --- a/packages/dts-plugin/src/core/lib/DtsWorker.ts +++ b/packages/dts-plugin/src/core/lib/DtsWorker.ts @@ -12,10 +12,8 @@ export class DtsWorker { rpcWorker: RpcWorker; private _options: DtsWorkerOptions; private _res: Promise; - constructor(options: DtsWorkerOptions) { this._options = cloneDeepOptions(options); - this.removeUnSerializationOptions(); this.rpcWorker = createRpcWorker( path.resolve(__dirname, './fork-generate-dts.js'), diff --git a/packages/dts-plugin/src/core/lib/utils.ts b/packages/dts-plugin/src/core/lib/utils.ts index ac106e7a353..916aea76c04 100644 --- a/packages/dts-plugin/src/core/lib/utils.ts +++ b/packages/dts-plugin/src/core/lib/utils.ts @@ -124,11 +124,15 @@ export const isTSProject = ( export function cloneDeepOptions(options: DTSManagerOptions) { const excludeKeys = ['manifest', 'async']; - return cloneDeepWith(options, (_value, key) => { + + return cloneDeepWith(options, (value, key) => { // moduleFederationConfig.manifest may have un serialization options if (typeof key === 'string' && excludeKeys.includes(key)) { return false; } + if (typeof value === 'function') { + return false; + } }); } diff --git a/packages/dts-plugin/src/plugins/ConsumeTypesPlugin.ts b/packages/dts-plugin/src/plugins/ConsumeTypesPlugin.ts index 1504b97e62c..b314e4cda79 100644 --- a/packages/dts-plugin/src/plugins/ConsumeTypesPlugin.ts +++ b/packages/dts-plugin/src/plugins/ConsumeTypesPlugin.ts @@ -11,36 +11,46 @@ export class ConsumeTypesPlugin implements WebpackPluginInstance { dtsOptions: moduleFederationPlugin.PluginDtsOptions; defaultOptions: moduleFederationPlugin.DtsHostOptions; callback: () => void; + fetchRemoteTypeUrlsResolve: ( + options: moduleFederationPlugin.RemoteTypeUrls, + ) => void; constructor( pluginOptions: moduleFederationPlugin.ModuleFederationPluginOptions, dtsOptions: moduleFederationPlugin.PluginDtsOptions, defaultOptions: moduleFederationPlugin.DtsHostOptions, - callback: () => void, + fetchRemoteTypeUrlsResolve: ( + options: moduleFederationPlugin.RemoteTypeUrls, + ) => void, ) { this.pluginOptions = pluginOptions; this.dtsOptions = dtsOptions; this.defaultOptions = defaultOptions; - this.callback = callback; + this.fetchRemoteTypeUrlsResolve = fetchRemoteTypeUrlsResolve; } apply(compiler: Compiler) { - const { dtsOptions, defaultOptions, pluginOptions, callback } = this; + const { + dtsOptions, + defaultOptions, + pluginOptions, + fetchRemoteTypeUrlsResolve, + } = this; if (isPrd()) { - callback(); + fetchRemoteTypeUrlsResolve(undefined); return; } const normalizedConsumeTypes = - normalizeOptions( + normalizeOptions( true, defaultOptions, 'mfOptions.dts.consumeTypes', )(dtsOptions.consumeTypes); if (!normalizedConsumeTypes) { - callback(); + fetchRemoteTypeUrlsResolve(undefined); return; } @@ -56,14 +66,25 @@ export class ConsumeTypesPlugin implements WebpackPluginInstance { }; validateOptions(finalOptions.host); - - const promise = consumeTypes(finalOptions) - .then(() => { - callback(); + const fetchRemoteTypeUrlsPromise = + typeof normalizedConsumeTypes.remoteTypeUrls === 'function' + ? normalizedConsumeTypes.remoteTypeUrls() + : Promise.resolve(normalizedConsumeTypes.remoteTypeUrls); + const promise = fetchRemoteTypeUrlsPromise.then((remoteTypeUrls) => { + consumeTypes({ + ...finalOptions, + host: { + ...finalOptions.host, + remoteTypeUrls, + }, }) - .catch(() => { - callback(); - }); + .then(() => { + fetchRemoteTypeUrlsResolve(remoteTypeUrls); + }) + .catch(() => { + fetchRemoteTypeUrlsResolve(remoteTypeUrls); + }); + }); compiler.hooks.thisCompilation.tap('mf:generateTypes', (compilation) => { compilation.hooks.processAssets.tapPromise( diff --git a/packages/dts-plugin/src/plugins/DevPlugin.ts b/packages/dts-plugin/src/plugins/DevPlugin.ts index a46e2858c5b..7e51d7f88e8 100644 --- a/packages/dts-plugin/src/plugins/DevPlugin.ts +++ b/packages/dts-plugin/src/plugins/DevPlugin.ts @@ -37,16 +37,23 @@ export class DevPlugin implements WebpackPluginInstance { private _options: moduleFederationPlugin.ModuleFederationPluginOptions; private _devWorker?: DevWorker; dtsOptions: moduleFederationPlugin.PluginDtsOptions; - fetchTypesPromise: Promise; + generateTypesPromise: Promise; + fetchRemoteTypeUrlsPromise: Promise< + moduleFederationPlugin.DtsHostOptions['remoteTypeUrls'] | undefined + >; constructor( options: moduleFederationPlugin.ModuleFederationPluginOptions, dtsOptions: moduleFederationPlugin.PluginDtsOptions, - fetchTypesPromise: Promise, + generateTypesPromise: Promise, + fetchRemoteTypeUrlsPromise: Promise< + moduleFederationPlugin.DtsHostOptions['remoteTypeUrls'] | undefined + >, ) { this._options = options; - this.fetchTypesPromise = fetchTypesPromise; + this.generateTypesPromise = generateTypesPromise; this.dtsOptions = dtsOptions; + this.fetchRemoteTypeUrlsPromise = fetchRemoteTypeUrlsPromise; } static ensureLiveReloadEntry( @@ -253,11 +260,18 @@ export class DevPlugin implements WebpackPluginInstance { ) { remote.tsConfigPath = normalizedDtsOptions.tsConfigPath; } - this.fetchTypesPromise.then(() => { + + Promise.all([ + this.generateTypesPromise, + this.fetchRemoteTypeUrlsPromise, + ]).then(([_, remoteTypeUrls]) => { this._devWorker = createDevWorker({ name, remote: remote, - host: host, + host: { + ...host, + remoteTypeUrls, + }, extraOptions: extraOptions, disableLiveReload: normalizedDev.disableHotTypesReload, disableHotTypesReload: normalizedDev.disableHotTypesReload, diff --git a/packages/dts-plugin/src/plugins/DtsPlugin.ts b/packages/dts-plugin/src/plugins/DtsPlugin.ts index 84d1a9bdd52..1289b8252d1 100644 --- a/packages/dts-plugin/src/plugins/DtsPlugin.ts +++ b/packages/dts-plugin/src/plugins/DtsPlugin.ts @@ -20,8 +20,8 @@ export class DtsPlugin implements WebpackPluginInstance { generateAPITypes: true, compileInChildProcess: true, abortOnError: false, - extractThirdParty: true, - extractRemoteTypes: true, + extractThirdParty: false, + extractRemoteTypes: false, }; const defaultConsumeTypes = { abortOnError: false, consumeAPITypes: true }; const normalizedDtsOptions = @@ -40,9 +40,13 @@ export class DtsPlugin implements WebpackPluginInstance { return; } - let consumeTypesPromiseResolve; - const consumeTypesPromise: Promise = new Promise((resolve) => { - consumeTypesPromiseResolve = resolve; + let fetchRemoteTypeUrlsResolve: ( + options: moduleFederationPlugin.RemoteTypeUrls, + ) => void; + const fetchRemoteTypeUrlsPromise: Promise< + moduleFederationPlugin.DtsHostOptions['remoteTypeUrls'] | undefined + > = new Promise((resolve) => { + fetchRemoteTypeUrlsResolve = resolve; }); let generateTypesPromiseResolve; @@ -52,16 +56,19 @@ export class DtsPlugin implements WebpackPluginInstance { // Because the plugin will delete dist/@mf-types.zip while generating types, which will be used in GenerateTypesPlugin // So it should apply after GenerateTypesPlugin - new DevPlugin(options, normalizedDtsOptions, generateTypesPromise).apply( - compiler, - ); + new DevPlugin( + options, + normalizedDtsOptions, + generateTypesPromise, + fetchRemoteTypeUrlsPromise, + ).apply(compiler); // The exposes files may use remote types, so it need to consume types first, otherwise the generate types will fail new GenerateTypesPlugin( options, normalizedDtsOptions, defaultGenerateTypes, - consumeTypesPromise, + fetchRemoteTypeUrlsPromise, generateTypesPromiseResolve, ).apply(compiler); @@ -69,7 +76,7 @@ export class DtsPlugin implements WebpackPluginInstance { options, normalizedDtsOptions, defaultConsumeTypes, - consumeTypesPromiseResolve, + fetchRemoteTypeUrlsResolve, ).apply(compiler); } } diff --git a/packages/dts-plugin/src/plugins/GenerateTypesPlugin.ts b/packages/dts-plugin/src/plugins/GenerateTypesPlugin.ts index c3855d16f81..03729e684b7 100644 --- a/packages/dts-plugin/src/plugins/GenerateTypesPlugin.ts +++ b/packages/dts-plugin/src/plugins/GenerateTypesPlugin.ts @@ -18,20 +18,24 @@ export class GenerateTypesPlugin implements WebpackPluginInstance { pluginOptions: moduleFederationPlugin.ModuleFederationPluginOptions; dtsOptions: moduleFederationPlugin.PluginDtsOptions; defaultOptions: moduleFederationPlugin.DtsRemoteOptions; - consumeTypesPromise: Promise; + fetchRemoteTypeUrlsPromise: Promise< + moduleFederationPlugin.DtsHostOptions['remoteTypeUrls'] | undefined + >; callback: () => void; constructor( pluginOptions: moduleFederationPlugin.ModuleFederationPluginOptions, dtsOptions: moduleFederationPlugin.PluginDtsOptions, defaultOptions: moduleFederationPlugin.DtsRemoteOptions, - consumeTypesPromise: Promise, + fetchRemoteTypeUrlsPromise: Promise< + moduleFederationPlugin.DtsHostOptions['remoteTypeUrls'] | undefined + >, callback: () => void, ) { this.pluginOptions = pluginOptions; this.dtsOptions = dtsOptions; this.defaultOptions = defaultOptions; - this.consumeTypesPromise = consumeTypesPromise; + this.fetchRemoteTypeUrlsPromise = fetchRemoteTypeUrlsPromise; this.callback = callback; } @@ -40,7 +44,7 @@ export class GenerateTypesPlugin implements WebpackPluginInstance { dtsOptions, defaultOptions, pluginOptions, - consumeTypesPromise, + fetchRemoteTypeUrlsPromise, callback, } = this; @@ -56,6 +60,13 @@ export class GenerateTypesPlugin implements WebpackPluginInstance { return; } + const normalizedConsumeTypes = + normalizeOptions( + true, + defaultOptions, + 'mfOptions.dts.consumeTypes', + )(dtsOptions.consumeTypes); + const finalOptions: DTSManagerOptions = { remote: { implementation: dtsOptions.implementation, @@ -64,6 +75,14 @@ export class GenerateTypesPlugin implements WebpackPluginInstance { moduleFederationConfig: pluginOptions, ...normalizedGenerateTypes, }, + host: + normalizedConsumeTypes === false + ? undefined + : { + context: compiler.context, + moduleFederationConfig: pluginOptions, + ...normalizedGenerateTypes, + }, extraOptions: dtsOptions.extraOptions || {}, displayErrorInTerminal: dtsOptions.displayErrorInTerminal, }; @@ -222,7 +241,7 @@ export class GenerateTypesPlugin implements WebpackPluginInstance { compilation.constructor.PROCESS_ASSETS_STAGE_OPTIMIZE_TRANSFER, }, async () => { - await consumeTypesPromise; + await fetchRemoteTypeUrlsPromise; const emitTypesFilesPromise = emitTypesFiles(compilation); if (isProd) { await emitTypesFilesPromise; diff --git a/packages/sdk/__tests__/parseEntry.spec.ts b/packages/sdk/__tests__/parseEntry.spec.ts index 819eb2ca658..e8fdf0f42f4 100644 --- a/packages/sdk/__tests__/parseEntry.spec.ts +++ b/packages/sdk/__tests__/parseEntry.spec.ts @@ -24,13 +24,24 @@ describe('parseEntry', () => { }); it('get correct entryInfo by parsing local version entry', () => { - const entry = '@byted/app1:http://localhost:8080/vmok-manifest.json'; + const entry = '@byted/app1:http://localhost:8080/mf-manifest.json'; const entryInfo = parseEntry(entry); expect(entryInfo).toMatchObject({ name: '@byted/app1', - entry: 'http://localhost:8080/vmok-manifest.json', + entry: 'http://localhost:8080/mf-manifest.json', + }); + }); + + it('get correct entryInfo by parsing dts manifest entry', () => { + const entry = '@scope/app1@http://domain/@version/mf-manifest.json'; + + const entryInfo = parseEntry(entry, undefined, '@'); + + expect(entryInfo).toMatchObject({ + name: '@scope/app1', + entry: 'http://domain/@version/mf-manifest.json', }); }); }); diff --git a/packages/sdk/src/types/plugins/ModuleFederationPlugin.ts b/packages/sdk/src/types/plugins/ModuleFederationPlugin.ts index eb707849579..8a992a1b65c 100644 --- a/packages/sdk/src/types/plugins/ModuleFederationPlugin.ts +++ b/packages/sdk/src/types/plugins/ModuleFederationPlugin.ts @@ -136,6 +136,15 @@ export interface PluginDevOptions { disableDynamicRemoteTypeHints?: boolean; } +interface RemoteTypeUrl { + api: string; + zip: string; +} + +export interface RemoteTypeUrls { + [remoteName: string]: RemoteTypeUrl; +} + export interface DtsHostOptions { typesFolder?: string; abortOnError?: boolean; @@ -144,6 +153,7 @@ export interface DtsHostOptions { maxRetries?: number; consumeAPITypes?: boolean; runtimePkgs?: string[]; + remoteTypeUrls?: (() => Promise) | RemoteTypeUrls; } export interface DtsRemoteOptions { diff --git a/packages/sdk/src/utils.ts b/packages/sdk/src/utils.ts index 1f34c5334ef..ec563860093 100644 --- a/packages/sdk/src/utils.ts +++ b/packages/sdk/src/utils.ts @@ -28,9 +28,12 @@ const parseEntry = ( // Check if the string starts with a type if (strSplit.length >= 2) { let [name, ...versionOrEntryArr] = strSplit; + // @name@manifest-url.json if (str.startsWith(separator)) { - versionOrEntryArr = [devVersionOrUrl || strSplit.slice(-1)[0]]; - name = strSplit.slice(0, -1).join(separator); + name = strSplit.slice(0, 2).join(separator); + versionOrEntryArr = [ + devVersionOrUrl || strSplit.slice(2).join(separator), + ]; } let versionOrEntry = devVersionOrUrl || versionOrEntryArr.join(separator);