diff --git a/lib/modules/datasource/packagist/schema.spec.ts b/lib/modules/datasource/packagist/schema.spec.ts index ee0f6bbe93ae9ae9f682722b7044a1fc4bc6d766..12541ea984204bcd500c45e13dc4863a8a92c64c 100644 --- a/lib/modules/datasource/packagist/schema.spec.ts +++ b/lib/modules/datasource/packagist/schema.spec.ts @@ -80,34 +80,78 @@ describe('modules/datasource/packagist/schema', () => { }); it('parses ComposerRelease', () => { - expect(ComposerRelease.parse({ version: '' })).toEqual({ version: '' }); + expect(ComposerRelease.parse({ version: '' })).toEqual({ + version: '', + homepage: null, + source: null, + time: null, + require: null, + }); expect(ComposerRelease.parse({ version: 'dev-main' })).toEqual({ version: 'dev-main', + homepage: null, + source: null, + time: null, + require: null, }); expect(ComposerRelease.parse({ version: '1.2.3' })).toEqual({ version: '1.2.3', + homepage: null, + source: null, + time: null, + require: null, }); expect(ComposerRelease.parse({ version: '1.2.3', homepage: 42 })).toEqual( - { version: '1.2.3', homepage: null } + { + version: '1.2.3', + homepage: null, + source: null, + time: null, + require: null, + } ); expect( ComposerRelease.parse({ version: '1.2.3', homepage: 'example.com' }) - ).toEqual({ version: '1.2.3', homepage: 'example.com' }); + ).toEqual({ + version: '1.2.3', + homepage: 'example.com', + source: null, + time: null, + require: null, + }); expect( ComposerRelease.parse({ version: '1.2.3', source: 'nonsense' }) - ).toEqual({ version: '1.2.3', source: null }); + ).toEqual({ + version: '1.2.3', + homepage: null, + source: null, + time: null, + require: null, + }); expect( ComposerRelease.parse({ version: '1.2.3', source: { url: 'foobar' } }) - ).toEqual({ version: '1.2.3', source: { url: 'foobar' } }); + ).toEqual({ + version: '1.2.3', + source: { url: 'foobar' }, + homepage: null, + time: null, + require: null, + }); expect( ComposerRelease.parse({ version: '1.2.3', time: '12345' }) - ).toEqual({ version: '1.2.3', time: '12345' }); + ).toEqual({ + version: '1.2.3', + time: '12345', + homepage: null, + source: null, + require: null, + }); }); }); @@ -123,7 +167,22 @@ describe('modules/datasource/packagist/schema', () => { expect(ComposerReleases.parse(['foobar'])).toBeEmptyArray(); expect( ComposerReleases.parse([{ version: '1.2.3' }, { version: 'dev-main' }]) - ).toEqual([{ version: '1.2.3' }, { version: 'dev-main' }]); + ).toEqual([ + { + version: '1.2.3', + homepage: null, + source: null, + time: null, + require: null, + }, + { + version: 'dev-main', + homepage: null, + source: null, + time: null, + require: null, + }, + ]); }); }); @@ -133,6 +192,7 @@ describe('modules/datasource/packagist/schema', () => { expect(parsePackagesResponse('foo/bar', {})).toEqual([]); expect(parsePackagesResponse('foo/bar', { packages: '123' })).toEqual([]); expect(parsePackagesResponse('foo/bar', { packages: {} })).toEqual([]); + expect( parsePackagesResponse('foo/bar', { packages: { @@ -140,7 +200,16 @@ describe('modules/datasource/packagist/schema', () => { 'baz/qux': [{ version: '4.5.6' }], }, }) - ).toEqual([{ version: '1.2.3' }]); + ).toEqual([ + { + version: '1.2.3', + homepage: null, + source: null, + time: null, + require: null, + }, + ]); + expect( parsePackagesResponse('foo/bar', { packages: { @@ -148,7 +217,15 @@ describe('modules/datasource/packagist/schema', () => { 'baz/qux': { '4.5.6': { version: '4.5.6' } }, }, }) - ).toEqual([{ version: '1.2.3' }]); + ).toEqual([ + { + version: '1.2.3', + homepage: null, + source: null, + time: null, + require: null, + }, + ]); }); it('expands minified fields', () => { @@ -167,14 +244,56 @@ describe('modules/datasource/packagist/schema', () => { }, }) ).toEqual([ - { version: '3.3.3', require: { php: '^8.0' } }, - { version: '2.2.2', require: { php: '^8.0' } }, - { version: '1.1.1', require: { php: '^8.0' } }, - { version: '0.0.4', require: { php: '^7.0' } }, - { version: '0.0.3', require: { php: '^7.0' } }, - { version: '0.0.2' }, - { version: '0.0.1' }, - ] satisfies ComposerRelease[]); + { + version: '3.3.3', + require: { php: '^8.0' }, + homepage: null, + source: null, + time: null, + }, + { + version: '2.2.2', + require: { php: '^8.0' }, + homepage: null, + source: null, + time: null, + }, + { + version: '1.1.1', + require: { php: '^8.0' }, + homepage: null, + source: null, + time: null, + }, + { + version: '0.0.4', + require: { php: '^7.0' }, + homepage: null, + source: null, + time: null, + }, + { + version: '0.0.3', + require: { php: '^7.0' }, + homepage: null, + source: null, + time: null, + }, + { + version: '0.0.2', + homepage: null, + source: null, + time: null, + require: null, + }, + { + version: '0.0.1', + homepage: null, + source: null, + time: null, + require: null, + }, + ]); }); }); @@ -205,6 +324,7 @@ describe('modules/datasource/packagist/schema', () => { time: '222', homepage: 'https://example.com/2', source: { url: 'git@example.com:baz/qux-2' }, + require: null, }, ], }, @@ -226,6 +346,7 @@ describe('modules/datasource/packagist/schema', () => { time: '444', homepage: 'https://example.com/4', source: { url: 'git@example.com:baz/qux-3' }, + require: null, }, ], }, diff --git a/lib/modules/datasource/packagist/schema.ts b/lib/modules/datasource/packagist/schema.ts index 2dca13a950e0f8eab9c6bb7a52212fb88f246a5c..31c0ce0100a3ea8f5cfc77e952aeaf68f8750de3 100644 --- a/lib/modules/datasource/packagist/schema.ts +++ b/lib/modules/datasource/packagist/schema.ts @@ -1,12 +1,7 @@ import is from '@sindresorhus/is'; import { z } from 'zod'; import { logger } from '../../../logger'; -import { - looseArray, - looseObject, - looseRecord, - looseValue, -} from '../../../util/schema'; +import { looseArray, looseRecord, looseValue } from '../../../util/schema'; import type { Release, ReleaseResult } from '../types'; export const MinifiedArray = z.array(z.record(z.unknown())).transform((xs) => { @@ -45,18 +40,13 @@ export const MinifiedArray = z.array(z.record(z.unknown())).transform((xs) => { }); export type MinifiedArray = z.infer<typeof MinifiedArray>; -export const ComposerRelease = z - .object({ - version: z.string(), - }) - .merge( - looseObject({ - homepage: z.string(), - source: z.object({ url: z.string() }), - time: z.string(), - require: z.object({ php: z.string() }), - }) - ); +export const ComposerRelease = z.object({ + version: z.string(), + homepage: looseValue(z.string()), + source: looseValue(z.object({ url: z.string() })), + time: looseValue(z.string()), + require: looseValue(z.object({ php: z.string() })), +}); export type ComposerRelease = z.infer<typeof ComposerRelease>; const ComposerReleasesLooseArray = looseArray(ComposerRelease); diff --git a/lib/util/schema.spec.ts b/lib/util/schema.spec.ts index 39096a1168a1f0beb05ca6eb39b705ccd7142a9a..3bcabb285c196a9c9bebea49f5c2a798d821a5a5 100644 --- a/lib/util/schema.spec.ts +++ b/lib/util/schema.spec.ts @@ -172,29 +172,4 @@ describe('util/schema', () => { expect(called).toBeTrue(); }); }); - - describe('looseObject', () => { - it('parses object', () => { - const s = schema.looseObject({ - foo: z.string(), - bar: z.number(), - }); - expect(s.parse({ foo: 'foo', bar: 123 })).toEqual({ - foo: 'foo', - bar: 123, - }); - }); - - it('drops wrong items', () => { - const s = schema.looseObject({ - foo: z.string(), - bar: z.number(), - baz: z.string(), - }); - expect(s.parse({ foo: 'foo', bar: 'bar' })).toEqual({ - foo: 'foo', - bar: null, - }); - }); - }); }); diff --git a/lib/util/schema.ts b/lib/util/schema.ts index 8d369a33b2155481b20cd2cb2c11a0c349e1b588..3d6f0254a8cc709fceeb4ef8f9d8fbc9f68ee812 100644 --- a/lib/util/schema.ts +++ b/lib/util/schema.ts @@ -157,18 +157,3 @@ export function looseValue<T, U extends z.ZodTypeDef, V>( : nullableSchema.catch(null); return schemaWithFallback; } - -export function looseObject<T extends z.ZodRawShape>( - shape: T -): z.ZodObject<{ - [k in keyof T]: z.ZodOptional<z.ZodCatch<z.ZodNullable<T[k]>>>; -}> { - const newShape: Record<keyof T, z.ZodTypeAny> = { ...shape }; - const keys: (keyof T)[] = Object.keys(shape); - for (const k of keys) { - const v = looseValue(shape[k]); - newShape[k] = v; - } - - return z.object(newShape).partial() as never; -}