Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update for resolving tarball location of custom registries to support NPM clients #16

Merged
merged 5 commits into from
Jul 25, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion src/load.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,21 @@ import { getCustomRegistry } from './utils/customRegistry';
import { AxiosResponse } from 'axios';
import { LatestVersionUnavailableError } from './errors/LatestVersionUnavailableError';

async function getDistUrl(registry: string, packageName: string, version: string): Promise<string> {
const cleanedRegistry = registry.replace(/\/$/, '');
// 1 get the manifest information about the package from the registry
const res = await axiosGet(`${cleanedRegistry}/${packageName}`);
// 2 find the NPM tarball location
const npmLocation = res.data?.versions?.[version]?.dist?.tarball;

// 3 if found, use it, otherwise fallback to the FHIR spec location
if (npmLocation) {
return npmLocation;
} else {
return `${cleanedRegistry}/${packageName}/${version}`;
}
}

/**
* Loads multiple dependencies from a directory (the user FHIR cache or a specified directory) or from online
* @param {string[]} fhirPackages - An array of FHIR packages to download and load definitions from (format: packageId#version)
Expand Down Expand Up @@ -220,7 +235,7 @@ export async function mergeDependency(
} else if (!loadedPackage) {
const customRegistry = getCustomRegistry(log);
if (customRegistry) {
packageUrl = `${customRegistry.replace(/\/$/, '')}/${packageName}/${version}`;
packageUrl = await getDistUrl(customRegistry, packageName, version);
} else {
packageUrl = `https://packages.fhir.org/${packageName}/${version}`;
}
Expand Down
62 changes: 53 additions & 9 deletions test/load.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ describe('#mergeDependency()', () => {
// This function encapsulates that testing logic. It's coupled more tightly to
// the actual implementation than I'd prefer, but... at least it's in one place.
const expectDownloadSequence = (
sources: string | string[],
sources: string | string[] | { source: string; omitResponseType?: boolean }[],
destination: string | null,
isCurrent = false,
isCurrentFound = true
Expand All @@ -485,14 +485,33 @@ describe('#mergeDependency()', () => {
if (isCurrent) {
const mockCalls: any[] = [['https://build.fhir.org/ig/qas.json']];
if (isCurrentFound) {
mockCalls.push(
[sources[0].replace(/package\.tgz$/, 'package.manifest.json')],
[sources[0], { responseType: 'arraybuffer' }]
);
if (typeof sources[0] === 'string') {
mockCalls.push(
[sources[0].replace(/package\.tgz$/, 'package.manifest.json')],
[sources[0], { responseType: 'arraybuffer' }]
);
} else {
mockCalls.push([sources[0].source.replace(/package\.tgz$/, 'package.manifest.json')]);
if (sources[0].omitResponseType !== true) {
mockCalls.push([sources[0].source, { responseType: 'arraybuffer' }]);
}
}
}
expect(axiosSpy.mock.calls).toEqual(mockCalls);
} else {
expect(axiosSpy.mock.calls).toEqual(sources.map(s => [s, { responseType: 'arraybuffer' }]));
expect(axiosSpy.mock.calls).toEqual(
sources.map(s => {
if (typeof s === 'string') {
return [s, { responseType: 'arraybuffer' }];
} else {
if (s.omitResponseType === true) {
return [s.source];
} else {
return [s.source, { responseType: 'arraybuffer' }];
}
}
})
);
}
if (destination != null) {
const tempTarFile = writeSpy.mock.calls[0][0];
Expand Down Expand Up @@ -591,6 +610,10 @@ describe('#mergeDependency()', () => {
date: '20200413230227'
}
};
} else if (uri === 'https://packages.fhir.org/hl7.fhir.r4.core') {
return { data: TERM_PKG_RESPONSE };
bkaney marked this conversation as resolved.
Show resolved Hide resolved
} else if (uri === 'https://packages2.fhir.org/hl7.fhir.r4.core') {
return { data: EXT_PKG_RESPONSE };
bkaney marked this conversation as resolved.
Show resolved Hide resolved
} else if (
uri === 'https://packages.fhir.org/sushi-test/0.2.0' ||
uri === 'https://build.fhir.org/ig/sushi/sushi-test/branches/testbranch/package.tgz' ||
Expand Down Expand Up @@ -736,13 +759,31 @@ describe('#mergeDependency()', () => {
);
});

it('should try to load a package from a custom registry', async () => {
it('should try to load a package from a custom registry that is like NPM', async () => {
// packages.fhir.org supports NPM clients
process.env.FPL_REGISTRY = 'https://packages.fhir.org';
await expect(mergeDependency('hl7.fhir.r4.core', '4.0.1', defs, 'foo', log)).rejects.toThrow(
'The package hl7.fhir.r4.core#4.0.1 could not be loaded locally or from the custom FHIR package registry https://packages.fhir.org.'
); // the package is never actually added to the cache, since tar is mocked
expectDownloadSequence(
[
{ source: 'https://packages.fhir.org/hl7.fhir.r4.core', omitResponseType: true },
{ source: 'https://packages.fhir.org/hl7.fhir.r4.core/4.0.1' }
],
path.join('foo', 'hl7.fhir.r4.core#4.0.1')
);
});

it('should try to load a package from a custom registry that is not like NPM', async () => {
process.env.FPL_REGISTRY = 'https://custom-registry.example.org';
await expect(mergeDependency('good-thing', '0.3.6', defs, 'foo', log)).rejects.toThrow(
'The package good-thing#0.3.6 could not be loaded locally or from the custom FHIR package registry https://custom-registry.example.org'
); // the package is never actually added to the cache, since tar is mocked
expectDownloadSequence(
'https://custom-registry.example.org/good-thing/0.3.6',
[
{ source: 'https://custom-registry.example.org/good-thing', omitResponseType: true },
{ source: 'https://custom-registry.example.org/good-thing/0.3.6' }
],
path.join('foo', 'good-thing#0.3.6')
);
});
Expand All @@ -753,7 +794,10 @@ describe('#mergeDependency()', () => {
'The package good-thing#0.3.6 could not be loaded locally or from the custom FHIR package registry https://custom-registry.example.org/'
); // the package is never actually added to the cache, since tar is mocked
expectDownloadSequence(
'https://custom-registry.example.org/good-thing/0.3.6',
[
{ source: 'https://custom-registry.example.org/good-thing', omitResponseType: true },
{ source: 'https://custom-registry.example.org/good-thing/0.3.6' }
],
path.join('foo', 'good-thing#0.3.6')
);
});
Expand Down
Loading