diff --git a/.changeset/breezy-papayas-grab.md b/.changeset/breezy-papayas-grab.md new file mode 100644 index 00000000..0de46151 --- /dev/null +++ b/.changeset/breezy-papayas-grab.md @@ -0,0 +1,5 @@ +--- +"jsrepo": patch +--- + +Ensure parsed urls from http provider end with a trailing slash. diff --git a/.changeset/lazy-coins-admire.md b/.changeset/lazy-coins-admire.md new file mode 100644 index 00000000..26aafcf2 --- /dev/null +++ b/.changeset/lazy-coins-admire.md @@ -0,0 +1,5 @@ +--- +"jsrepo": patch +--- + +Catch `JSON.parse` errors when fetching the manifest to provide a more clear error to the user. diff --git a/packages/cli/package.json b/packages/cli/package.json index aa15df23..2b4ae940 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -15,16 +15,7 @@ "bugs": { "url": "https://github.com/ieedan/jsrepo/issues" }, - "keywords": [ - "repo", - "cli", - "svelte", - "vue", - "typescript", - "javascript", - "shadcn", - "registry" - ], + "keywords": ["repo", "cli", "svelte", "vue", "typescript", "javascript", "shadcn", "registry"], "type": "module", "exports": { ".": { @@ -34,10 +25,7 @@ }, "bin": "./dist/index.js", "main": "./dist/index.js", - "files": [ - "./schemas/**/*", - "dist/**/*" - ], + "files": ["./schemas/**/*", "dist/**/*"], "scripts": { "start": "tsup --silent && node ./dist/index.js", "build": "tsup", diff --git a/packages/cli/src/commands/init.ts b/packages/cli/src/commands/init.ts index f4d00cc6..10190770 100644 --- a/packages/cli/src/commands/init.ts +++ b/packages/cli/src/commands/init.ts @@ -33,7 +33,6 @@ import { loadFormatterConfig } from '../utils/format'; import { json } from '../utils/language-support'; import * as persisted from '../utils/persisted'; import { type Task, intro, nextSteps, runTasks } from '../utils/prompts'; -import { http, providers } from '../utils/registry-providers'; import * as registry from '../utils/registry-providers/internal'; const schema = v.object({ @@ -199,8 +198,8 @@ const _initProject = async (registries: string[], options: Options) => { validate: (val) => { if (val.trim().length === 0) return 'Please provide a value'; - if (!providers.find((provider) => provider.matches(val))) { - return `Invalid provider! Valid providers (${providers.map((provider) => provider.name).join(', ')})`; + if (!registry.selectProvider(val)) { + return `Invalid provider! Valid providers (${registry.providers.map((provider) => provider.name).join(', ')})`; } }, }); @@ -290,12 +289,12 @@ const promptForProviderConfig = async (repo: string, paths: Paths): Promise p.matches(repo)); + const provider = registry.selectProvider(repo); if (!provider) { program.error( color.red( - `Invalid provider! Valid providers (${providers.map((provider) => provider.name).join(', ')})` + `Invalid provider! Valid providers (${registry.providers.map((provider) => provider.name).join(', ')})` ) ); } @@ -305,7 +304,7 @@ const promptForProviderConfig = async (repo: string, paths: Paths): Promise { }); it('correctly parses base url', () => { - const cases: BaseUrlTestCase[] = [ + const cases: StringTestCase[] = [ { url: 'github/ieedan/std', expected: 'https://github.com/ieedan/std', @@ -372,7 +373,7 @@ describe('gitlab', () => { }); it('correctly parses base url', () => { - const cases: BaseUrlTestCase[] = [ + const cases: StringTestCase[] = [ { url: 'gitlab/ieedan/std', expected: 'https://gitlab.com/ieedan/std', @@ -648,7 +649,7 @@ describe('bitbucket', () => { }); it('correctly parses base url', () => { - const cases: BaseUrlTestCase[] = [ + const cases: StringTestCase[] = [ { url: 'bitbucket/ieedan/std', expected: 'https://bitbucket.org/ieedan/std', @@ -916,7 +917,7 @@ describe('azure', () => { }); it('correctly parses base url', () => { - const cases: BaseUrlTestCase[] = [ + const cases: StringTestCase[] = [ { url: 'azure/ieedan/std/std', expected: 'https://dev.azure.com/ieedan/_git/std', @@ -1144,7 +1145,7 @@ describe('http', () => { url: 'https://example.com/', opts: { fullyQualified: false }, expected: { - url: 'https://example.com', + url: 'https://example.com/', specifier: undefined, }, }, @@ -1152,7 +1153,7 @@ describe('http', () => { url: 'https://example.com/new-york', opts: { fullyQualified: false }, expected: { - url: 'https://example.com/new-york', + url: 'https://example.com/new-york/', specifier: undefined, }, }, @@ -1160,7 +1161,7 @@ describe('http', () => { url: 'https://example.com/utils/math', opts: { fullyQualified: true }, expected: { - url: 'https://example.com', + url: 'https://example.com/', specifier: 'utils/math', }, }, @@ -1168,7 +1169,7 @@ describe('http', () => { url: 'https://example.com/new-york/utils/math', opts: { fullyQualified: true }, expected: { - url: 'https://example.com/new-york', + url: 'https://example.com/new-york/', specifier: 'utils/math', }, }, @@ -1179,8 +1180,31 @@ describe('http', () => { } }); + it('correctly resolves url', async () => { + const cases: StringTestCase[] = [ + { + url: 'https://example.com', + expected: 'https://example.com/jsrepo-manifest.json', + }, + { + url: 'https://example.com/new-york', + expected: 'https://example.com/new-york/jsrepo-manifest.json', + }, + ]; + + for (const c of cases) { + const state = await registry.getProviderState(c.url); + + assert(!state.isErr()); + + expect( + await state.unwrap().provider.resolveRaw(state.unwrap(), MANIFEST_FILE) + ).toStrictEqual(new URL(c.expected)); + } + }); + it('correctly parses base url', () => { - const cases: BaseUrlTestCase[] = [ + const cases: StringTestCase[] = [ { url: 'https://example.com/', expected: 'https://example.com',