Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
9 changes: 5 additions & 4 deletions specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,11 @@ $ manager config get <key>

List of registries which will be searched for packages. This allows brands/companies to each own a package list, but registries are combined for the user consuming the list.

| Field | Type | Description | Example |
| :---- | :----- | :------------ | :--------------------------------------------------------------- |
| name | string | Registry name | `"Open Audio Registry"` |
| url | string | Registry url | `"https://open-audio-stack.github.io/open-audio-stack-registry"` |
| Field | Type | Description | Example |
| :------ | :----- | :------------------------------------------------------------------ | :--------------------------------------------------------------- |
| name | string | Registry name | `"Open Audio Registry"` |
| url | string | Registry url | `"https://open-audio-stack.github.io/open-audio-stack-registry"` |
| version | string | Optional - see [Registry versioning](#registry-versioning-optional) | `"v1"` |

#### Get registries

Expand Down
3 changes: 2 additions & 1 deletion src/classes/Manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { ManagerReport, PackageVersion } from '../types/Package.js';
import { RegistryInterface, RegistryPackages, RegistryType } from '../types/Registry.js';
import { Base } from './Base.js';
import { packageCompatibleFiles } from '../helpers/package.js';
import { registryUrl } from '../helpers/registry.js';
import { Architecture, SystemType } from '../index-browser.js';

export class Manager extends Base {
Expand Down Expand Up @@ -137,7 +138,7 @@ export class Manager extends Base {
for (const index in registries) {
let json: RegistryInterface;
try {
json = await apiJson(registries[index].url);
json = await apiJson(registryUrl(registries[index]));
} catch (err) {
// One unreachable/misconfigured registry shouldn't stop the others from being synced -
// record the failure and move on, matching the spec's goal of combining packages from
Expand Down
8 changes: 8 additions & 0 deletions src/helpers/registry.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ConfigRegistry } from '../types/Config.js';
import { RegistryInterface } from '../types/Registry.js';

export function registryDefaults(): RegistryInterface {
Expand All @@ -10,3 +11,10 @@ export function registryDefaults(): RegistryInterface {
version: '1.0.0',
};
}

// See specification.md "Registry versioning (optional)" - appends the version segment to the
// registry root when one is configured. Unversioned registries (the common case) are untouched,
// resolving to whatever the registry serves as its latest version.
export function registryUrl(registry: ConfigRegistry): string {
return registry.version ? `${registry.url.replace(/\/$/, '')}/${registry.version}` : registry.url;
}
5 changes: 5 additions & 0 deletions src/types/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,9 @@ export interface ConfigInterface {
export interface ConfigRegistry {
name: string;
url: string;
// Optional versioned endpoint (see specification.md "Registry versioning (optional)") - when
// set, appended as a path segment onto `url` when requesting resources, so a registry can
// introduce breaking changes on a new version without affecting managers still pointed at the
// root (which always resolves to the latest version).
version?: string;
}
18 changes: 18 additions & 0 deletions tests/classes/Manager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,24 @@ test('Manager sync isolates a malformed package version instead of throwing', as
apiJsonSpy.mockRestore();
});

test('Manager sync appends a configured registry version to the request url', async () => {
const apiJsonSpy = vi.spyOn(apiHelpers, 'apiJson').mockResolvedValue({
name: 'Mock Registry',
url: 'https://example.invalid/registry',
version: '1.0.0',
[RegistryType.Plugins]: {},
});

const manager = new Manager(RegistryType.Plugins, {
registries: [{ name: 'Mock Registry', url: 'https://example.invalid/registry', version: 'v1' }],
});
await manager.sync();

expect(apiJsonSpy).toHaveBeenCalledWith('https://example.invalid/registry/v1');

apiJsonSpy.mockRestore();
});

test('Manager sync with existing package', async () => {
const manager = new Manager(RegistryType.Plugins);
const pkg = new Package(PLUGIN_PACKAGE.slug);
Expand Down
34 changes: 34 additions & 0 deletions tests/helpers/registry.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { expect, test } from 'vitest';
import { registryDefaults, registryUrl } from '../../src/helpers/registry';
import { RegistryInterface } from '../../src/types/Registry';

const REGISTRY: RegistryInterface = {
name: 'Open Audio Registry',
plugins: {},
presets: {},
projects: {},
url: 'https://open-audio-stack.github.io/open-audio-stack-registry',
version: '1.0.0',
};

test('Get default value', () => {
expect(registryDefaults()).toEqual(REGISTRY);
});

test('Registry url without a version is unchanged', () => {
expect(registryUrl({ name: 'Open Audio Registry', url: 'https://example.com/registry' })).toEqual(
'https://example.com/registry',
);
});

test('Registry url with a version appends the version segment', () => {
expect(registryUrl({ name: 'Open Audio Registry', url: 'https://example.com/registry', version: 'v1' })).toEqual(
'https://example.com/registry/v1',
);
});

test('Registry url with a version strips a trailing slash from the root first', () => {
expect(registryUrl({ name: 'Open Audio Registry', url: 'https://example.com/registry/', version: 'v1' })).toEqual(
'https://example.com/registry/v1',
);
});
Loading