diff --git a/lib/config/definitions.js b/lib/config/definitions.js index df8d53ebe0dbbd8f364c5fbf49eb8e52ae82a9b5..b01f2c7d01a3fc109670aa4fbbfa74170eec470b 100644 --- a/lib/config/definitions.js +++ b/lib/config/definitions.js @@ -1000,6 +1000,18 @@ const options = [ mergeable: true, cli: false, }, + { + name: 'nuget', + description: 'Configuration object for C#/Nuget', + stage: 'package', + type: 'json', + default: { + enabled: false, + fileMatch: ['(^|/)*\\.csproj$'], + }, + mergeable: true, + cli: false, + }, ]; function getOptions() { diff --git a/lib/datasource/nuget.js b/lib/datasource/nuget.js new file mode 100644 index 0000000000000000000000000000000000000000..80fafb90360a2c6294bc10b246c8d87877977794 --- /dev/null +++ b/lib/datasource/nuget.js @@ -0,0 +1,52 @@ +const got = require('got'); +const xmlParser = require('fast-xml-parser'); + +module.exports = { + getVersions, + getNuspec, +}; + +const map = new Map(); +const headers = {}; + +async function getVersions(name, retries = 5) { + logger.trace(`getVersions(${name})`); + + const url = `https://api.nuget.org/v3-flatcontainer/${name.toLowerCase()}/index.json`; + + try { + const result = (await got(url, { + cache: process.env.RENOVATE_SKIP_CACHE ? undefined : map, + json: true, + retries, + headers, + })).body; + + return result.versions; + } catch (err) { + logger.warn({ err, name }, 'nuget getVersions failures: Unknown error'); + return null; + } +} + +async function getNuspec(name, version, retries = 5) { + logger.trace(`getNuspec(${name} - ${version})`); + + const url = `https://api.nuget.org/v3-flatcontainer/${name.toLowerCase()}/${version}/${name.toLowerCase()}.nuspec`; + + try { + const result = await got(url, { + cache: process.env.RENOVATE_SKIP_CACHE ? undefined : map, + json: false, + retries, + headers, + }); + + const nuspec = xmlParser.parse(result.body, { ignoreAttributes: false }); + + return nuspec.package; + } catch (err) { + logger.warn({ err, name }, 'nuget getNuspec failures: Unknown error'); + return null; + } +} diff --git a/lib/manager/index.js b/lib/manager/index.js index 236458e7794337f5cc65da214f11011c44d36552..ba990736aa961c76bf69da511af5ef6948b8a0b2 100644 --- a/lib/manager/index.js +++ b/lib/manager/index.js @@ -10,6 +10,7 @@ const managerList = [ 'nvm', 'pip_requirements', 'travis', + 'nuget', ]; const managers = {}; for (const manager of managerList) { diff --git a/lib/manager/nuget/extract.js b/lib/manager/nuget/extract.js new file mode 100644 index 0000000000000000000000000000000000000000..5dddce0c003c744a2c5987203981f56adec54f10 --- /dev/null +++ b/lib/manager/nuget/extract.js @@ -0,0 +1,28 @@ +module.exports = { + extractDependencies, +}; + +function extractDependencies(content) { + logger.debug('nuget.extractDependencies()'); + const deps = []; + + let lineNumber = 0; + for (const line of content.split('\n')) { + const match = line.match( + /<PackageReference.*Include\s*=\s*"([^"]+)".*Version\s*=\s*"([^"]+)"/ + ); + if (match) { + const depName = match[1]; + const currentVersion = match[2]; + + deps.push({ + depType: 'nuget', + depName, + currentVersion, + lineNumber, + }); + } + lineNumber += 1; + } + return { deps }; +} diff --git a/lib/manager/nuget/index.js b/lib/manager/nuget/index.js new file mode 100644 index 0000000000000000000000000000000000000000..0e9687649368740ebb4e90c97681b1802ed13fc9 --- /dev/null +++ b/lib/manager/nuget/index.js @@ -0,0 +1,9 @@ +const { extractDependencies } = require('./extract'); +const { getPackageUpdates } = require('./package'); +const { updateDependency } = require('./update'); + +module.exports = { + extractDependencies, + getPackageUpdates, + updateDependency, +}; diff --git a/lib/manager/nuget/package.js b/lib/manager/nuget/package.js new file mode 100644 index 0000000000000000000000000000000000000000..efce265e6ab525a5948143ec05785bec11a7fe2f --- /dev/null +++ b/lib/manager/nuget/package.js @@ -0,0 +1,55 @@ +const nugetApi = require('../../datasource/nuget'); +const { + semverSort, + isStable, + isGreaterThan, + getMajor, + getMinor, + isValid, +} = require('../../versioning/semver'); + +module.exports = { + getPackageUpdates, +}; + +async function getPackageUpdates(config) { + const { currentVersion, depName, lineNumber, ignoreUnstable } = config; + const upgrades = []; + + logger.debug('nuget.getPackageUpdates()'); + logger.trace({ config }); + + const versions = await nugetApi.getVersions(depName); + if (versions === undefined) { + logger.warn('No versions retrieved from nuget'); + return upgrades; + } + const applicableVersions = ignoreUnstable + ? versions.filter(v => isStable(v)) + : versions; + const newVersion = applicableVersions.sort(semverSort).pop(); + + if (!isValid(currentVersion)) { + logger.debug({ newVersion }, 'Skipping non-semver current version.'); + } else if (!isValid(newVersion)) { + logger.debug({ newVersion }, 'Skipping non-semver newVersion version.'); + } else if ( + newVersion !== undefined && + isGreaterThan(newVersion, currentVersion) + ) { + const upgrade = {}; + + upgrade.newVersion = newVersion; + upgrade.newVersionMajor = getMajor(newVersion); + upgrade.newVersionMinor = getMinor(newVersion); + upgrade.type = + getMajor(newVersion) > getMajor(currentVersion) ? 'major' : 'minor'; + upgrade.lineNumber = lineNumber; + upgrade.changeLogFromVersion = currentVersion; + upgrade.changeLogToVersion = newVersion; + + upgrades.push(upgrade); + } + + return upgrades; +} diff --git a/lib/manager/nuget/update.js b/lib/manager/nuget/update.js new file mode 100644 index 0000000000000000000000000000000000000000..7def06d743d83f9f0d86c0cf5f0a192bf0238e07 --- /dev/null +++ b/lib/manager/nuget/update.js @@ -0,0 +1,22 @@ +module.exports = { + updateDependency, +}; + +function updateDependency(fileContent, upgrade) { + try { + logger.debug(`nuget.updateDependency(): ${upgrade.newFrom}`); + const lines = fileContent.split('\n'); + const lineToChange = lines[upgrade.lineNumber]; + const regex = /(Version\s*=\s*")([^"]+)/; + const newLine = lineToChange.replace(regex, `$1${upgrade.newVersion}`); + if (newLine === lineToChange) { + logger.debug('No changes necessary'); + return fileContent; + } + lines[upgrade.lineNumber] = newLine; + return lines.join('\n'); + } catch (err) { + logger.info({ err }, 'Error setting new Dockerfile value'); + return null; + } +} diff --git a/package.json b/package.json index 97969708fa9a17eedda22d361c54e2871901c1be..d2246a7a968744204940fc2ae253068e817ee04d 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "detect-indent": "5.0.0", "email-addresses": "3.0.1", "fast-clone": "1.5.3", + "fast-xml-parser": "3.10.0", "fs-extra": "6.0.1", "get-installed-path": "4.0.8", "gh-got": "7.0.0", diff --git a/test/_fixtures/nuget/sample.csproj b/test/_fixtures/nuget/sample.csproj new file mode 100644 index 0000000000000000000000000000000000000000..d5d2473e4a390b0c9f5c09926b5d6a3bc049e460 --- /dev/null +++ b/test/_fixtures/nuget/sample.csproj @@ -0,0 +1,37 @@ +<Project Sdk="Microsoft.NET.Sdk.Web"> + + <PropertyGroup> + <TargetFramework>netcoreapp1.1</TargetFramework> + <Version>0.1.0</Version> + </PropertyGroup> + + <ItemGroup> + <Folder Include="Controllers\" /> + <Folder Include="wwwroot\" /> + </ItemGroup> + <ItemGroup> + <PackageReference Include="Autofac" Version="4.5.0" /> + <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.1.0" /> + <PackageReference Include="Microsoft.AspNetCore.Hosting" Version="1.1.2" /> + <PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="1.1.3" /> + <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.2" /> + <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.2" /> + <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.2" /> + <PackageReference Include="Newtonsoft.Json" Version="10.0.2" /> + <PackageReference Include="Serilog" Version="2.4.0" /> + <PackageReference Include="Serilog.Extensions.Logging" Version="1.4.0" /> + <PackageReference Include="Serilog.Sinks.Literate" Version="2.1.0" /> + <PackageReference Include="Stateless" Version="3.1.0" /> + </ItemGroup> + <ItemGroup> + <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="1.0.0" /> + </ItemGroup> + <ItemGroup> + <Content Update="appsettings.development.json"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </Content> + <Content Update="appsettings.json"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </Content> + </ItemGroup> +</Project> diff --git a/test/_fixtures/nuget/sample.nuspec b/test/_fixtures/nuget/sample.nuspec new file mode 100644 index 0000000000000000000000000000000000000000..920db03eec74b8dc31d82009ce2c2ceb01007441 --- /dev/null +++ b/test/_fixtures/nuget/sample.nuspec @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<package xmlns="http://schemas.microsoft.com/packaging/2013/01/nuspec.xsd"> + <metadata minClientVersion="2.12"> + <id>Newtonsoft.Json</id> + <version>11.0.2</version> + <title>Json.NET</title> + <authors>James Newton-King</authors> + <owners>James Newton-King</owners> + <requireLicenseAcceptance>false</requireLicenseAcceptance> + <licenseUrl>https://raw.github.com/JamesNK/Newtonsoft.Json/master/LICENSE.md</licenseUrl> + <projectUrl>https://www.newtonsoft.com/json</projectUrl> + <iconUrl>https://www.newtonsoft.com/content/images/nugeticon.png</iconUrl> + <description>Json.NET is a popular high-performance JSON framework for .NET</description> + <copyright>Copyright © James Newton-King 2008</copyright> + <tags>json</tags> + <repository type="git" url="https://github.com/JamesNK/Newtonsoft.Json.git" /> + <dependencies> + <group targetFramework=".NETFramework2.0" /> + <group targetFramework=".NETFramework3.5" /> + <group targetFramework=".NETFramework4.0" /> + <group targetFramework=".NETFramework4.5" /> + <group targetFramework=".NETPortable0.0-Profile259" /> + <group targetFramework=".NETPortable0.0-Profile328" /> + <group targetFramework=".NETStandard1.0"> + <dependency id="Microsoft.CSharp" version="4.3.0" exclude="Build,Analyzers" /> + <dependency id="NETStandard.Library" version="1.6.1" exclude="Build,Analyzers" /> + <dependency id="System.ComponentModel.TypeConverter" version="4.3.0" exclude="Build,Analyzers" /> + <dependency id="System.Runtime.Serialization.Primitives" version="4.3.0" exclude="Build,Analyzers" /> + </group> + <group targetFramework=".NETStandard1.3"> + <dependency id="Microsoft.CSharp" version="4.3.0" exclude="Build,Analyzers" /> + <dependency id="NETStandard.Library" version="1.6.1" exclude="Build,Analyzers" /> + <dependency id="System.ComponentModel.TypeConverter" version="4.3.0" exclude="Build,Analyzers" /> + <dependency id="System.Runtime.Serialization.Formatters" version="4.3.0" exclude="Build,Analyzers" /> + <dependency id="System.Runtime.Serialization.Primitives" version="4.3.0" exclude="Build,Analyzers" /> + <dependency id="System.Xml.XmlDocument" version="4.3.0" exclude="Build,Analyzers" /> + </group> + <group targetFramework=".NETStandard2.0" /> + </dependencies> + </metadata> +</package> \ No newline at end of file diff --git a/test/datasource/nuget.spec.js b/test/datasource/nuget.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..0c0097301caceca7f9a9e9b6ddd1a99aacc0eea3 --- /dev/null +++ b/test/datasource/nuget.spec.js @@ -0,0 +1,44 @@ +const fs = require('fs'); +const nuget = require('../../lib/datasource/nuget'); +const got = require('got'); + +const withRepositoryInNuspec = fs.readFileSync( + 'test/_fixtures/nuget/sample.nuspec', + 'utf8' +); +jest.mock('got'); + +describe('api/nuget', () => { + describe('getVersions', () => { + it('returns null if errored', async () => { + got.mockReturnValueOnce({}); + const nuspec = await nuget.getVersions('MyPackage'); + expect(nuspec).toBe(null); + }); + it('returns versions list', async () => { + got.mockReturnValueOnce({ + body: { versions: ['1.0.0', '2.0.0', '2.1.0', '2.1.1-alpha'] }, + }); + const versions = await nuget.getVersions('MyPackage'); + expect(versions).toHaveLength(4); + }); + }); + + describe('getNuspec', () => { + it('returns null if errored', async () => { + got.mockReturnValueOnce({}); + const nuspec = await nuget.getNuspec('MyPackage', '1.0.0.0'); + expect(nuspec).toBe(null); + }); + it('returns json-ified nuspec with attributes', async () => { + got.mockReturnValueOnce({ headers: {}, body: withRepositoryInNuspec }); + const nuspec = await nuget.getNuspec('MyPackage', '1.0.0.0'); + + expect(nuspec.metadata.id).toBe('Newtonsoft.Json'); + expect(nuspec.metadata.version).toBe('11.0.2'); + expect(nuspec.metadata.repository['@_url']).toBe( + 'https://github.com/JamesNK/Newtonsoft.Json.git' + ); + }); + }); +}); diff --git a/test/manager/nuget/__snapshots__/extract.spec.js.snap b/test/manager/nuget/__snapshots__/extract.spec.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..3440eca4e7e8699295bbba03c5a5e29e3aac8069 --- /dev/null +++ b/test/manager/nuget/__snapshots__/extract.spec.js.snap @@ -0,0 +1,84 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`lib/manager/nuget/extract extractDependencies() extracts all dependencies 1`] = ` +Array [ + Object { + "currentVersion": "4.5.0", + "depName": "Autofac", + "depType": "nuget", + "lineNumber": 12, + }, + Object { + "currentVersion": "4.1.0", + "depName": "Autofac.Extensions.DependencyInjection", + "depType": "nuget", + "lineNumber": 13, + }, + Object { + "currentVersion": "1.1.2", + "depName": "Microsoft.AspNetCore.Hosting", + "depType": "nuget", + "lineNumber": 14, + }, + Object { + "currentVersion": "1.1.3", + "depName": "Microsoft.AspNetCore.Mvc.Core", + "depType": "nuget", + "lineNumber": 15, + }, + Object { + "currentVersion": "1.1.2", + "depName": "Microsoft.AspNetCore.Server.Kestrel", + "depType": "nuget", + "lineNumber": 16, + }, + Object { + "currentVersion": "1.1.2", + "depName": "Microsoft.Extensions.Configuration.Json", + "depType": "nuget", + "lineNumber": 17, + }, + Object { + "currentVersion": "1.1.2", + "depName": "Microsoft.Extensions.Logging.Debug", + "depType": "nuget", + "lineNumber": 18, + }, + Object { + "currentVersion": "10.0.2", + "depName": "Newtonsoft.Json", + "depType": "nuget", + "lineNumber": 19, + }, + Object { + "currentVersion": "2.4.0", + "depName": "Serilog", + "depType": "nuget", + "lineNumber": 20, + }, + Object { + "currentVersion": "1.4.0", + "depName": "Serilog.Extensions.Logging", + "depType": "nuget", + "lineNumber": 21, + }, + Object { + "currentVersion": "2.1.0", + "depName": "Serilog.Sinks.Literate", + "depType": "nuget", + "lineNumber": 22, + }, + Object { + "currentVersion": "3.1.0", + "depName": "Stateless", + "depType": "nuget", + "lineNumber": 23, + }, +] +`; + +exports[`lib/manager/nuget/extract extractDependencies() returns empty for invalid csproj 1`] = ` +Object { + "deps": Array [], +} +`; diff --git a/test/manager/nuget/__snapshots__/package.spec.js.snap b/test/manager/nuget/__snapshots__/package.spec.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..938ba62890654d39e951991f541408ea15ac46e1 --- /dev/null +++ b/test/manager/nuget/__snapshots__/package.spec.js.snap @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`lib/manager/nuget/package getPackageUpdates() returns higher version if available 1`] = ` +Array [ + Object { + "changeLogFromVersion": "2.3.0", + "changeLogToVersion": "2.4.0", + "lineNumber": 1337, + "newVersion": "2.4.0", + "newVersionMajor": 2, + "newVersionMinor": 4, + "type": "minor", + }, +] +`; diff --git a/test/manager/nuget/extract.spec.js b/test/manager/nuget/extract.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..dfd46149f6c36697a4b76910654ff39d88af49c2 --- /dev/null +++ b/test/manager/nuget/extract.spec.js @@ -0,0 +1,20 @@ +const fs = require('fs'); +const { extractDependencies } = require('../../../lib/manager/nuget/extract'); + +const sample = fs.readFileSync('test/_fixtures/nuget/sample.csproj', 'utf8'); + +describe('lib/manager/nuget/extract', () => { + describe('extractDependencies()', () => { + let config; + beforeEach(() => { + config = {}; + }); + it('returns empty for invalid csproj', () => { + expect(extractDependencies('nothing here', config)).toMatchSnapshot(); + }); + it('extracts all dependencies', () => { + const res = extractDependencies(sample, config).deps; + expect(res).toMatchSnapshot(); + }); + }); +}); diff --git a/test/manager/nuget/package.spec.js b/test/manager/nuget/package.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..a43042697996627801eff753dc870bafbb4046a5 --- /dev/null +++ b/test/manager/nuget/package.spec.js @@ -0,0 +1,48 @@ +const { getPackageUpdates } = require('../../../lib/manager/nuget/package'); +const nugetApi = require('../../../lib/datasource/nuget'); +const defaultConfig = require('../../../lib/config/defaults').getConfig(); + +nugetApi.getNuspec = jest.fn(); +nugetApi.getVersions = jest.fn(); + +describe('lib/manager/nuget/package', () => { + describe('getPackageUpdates()', () => { + let config; + beforeEach(() => { + config = { + ...defaultConfig, + depName: 'some-dep', + currentVersion: '2.3.0', + lineNumber: 1337, + ignoreUnstable: true, + }; + }); + it('returns empty if no versions are found', async () => { + expect(await getPackageUpdates(config)).toEqual([]); + }); + it('returns empty if current version is not semver', async () => { + config.currentVersion = undefined; + nugetApi.getVersions.mockReturnValueOnce(['1.0.0']); + expect(await getPackageUpdates(config)).toEqual([]); + }); + it('returns empty if latest version is not semver', async () => { + nugetApi.getVersions.mockReturnValueOnce(['5.0.0.0']); + expect(await getPackageUpdates(config)).toEqual([]); + }); + it('returns empty if highest version is current version', async () => { + nugetApi.getVersions.mockReturnValueOnce([ + '1.0.0', + config.currentVersion, + ]); + expect(await getPackageUpdates(config)).toEqual([]); + }); + it('returns higher version if available', async () => { + nugetApi.getVersions.mockReturnValueOnce(['1.0.0', '2.3.1', '2.4.0']); + expect(await getPackageUpdates(config)).toMatchSnapshot(); + }); + it('ignores unstable version if specified', async () => { + nugetApi.getVersions.mockReturnValueOnce(['3.0.0-alpha1']); + expect(await getPackageUpdates(config)).toEqual([]); + }); + }); +}); diff --git a/test/manager/nuget/update.spec.js b/test/manager/nuget/update.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..0e2eb24108e647efb327bedc7a9585fa19b21806 --- /dev/null +++ b/test/manager/nuget/update.spec.js @@ -0,0 +1,29 @@ +const fs = require('fs'); +const nugetUpdater = require('../../../lib/manager/nuget/update'); + +const csProj = fs.readFileSync('test/_fixtures/nuget/sample.csproj', 'utf8'); + +describe('manager/nuget/update', () => { + describe('updateDependency', () => { + it('replaces existing value', () => { + const upgrade = { + lineNumber: 13, + newVersion: '5.0.0', + }; + const res = nugetUpdater.updateDependency(csProj, upgrade); + expect(res).not.toEqual(csProj); + }); + it('keeps intact when same version', () => { + const upgrade = { + lineNumber: 13, + newVersion: '4.1.0', + }; + const res = nugetUpdater.updateDependency(csProj, upgrade); + expect(res).toEqual(csProj); + }); + it('returns null on errors', () => { + const res = nugetUpdater.updateDependency(csProj, null); + expect(res).toBe(null); + }); + }); +}); diff --git a/test/workers/repository/extract/__snapshots__/index.spec.js.snap b/test/workers/repository/extract/__snapshots__/index.spec.js.snap index 9cfcebb26f3e39aba2f27693f4577c16af3ad658..dbc6dd67a3f805d2455704e16745ecd1329602da 100644 --- a/test/workers/repository/extract/__snapshots__/index.spec.js.snap +++ b/test/workers/repository/extract/__snapshots__/index.spec.js.snap @@ -26,6 +26,9 @@ Object { "npm": Array [ Object {}, ], + "nuget": Array [ + Object {}, + ], "nvm": Array [ Object {}, ], diff --git a/website/docs/configuration-options.md b/website/docs/configuration-options.md index c20d8cdfce5c44106c9786a997b537fe13cd5456..137e780ac6f321cee02ee8048415aab77fec94e8 100644 --- a/website/docs/configuration-options.md +++ b/website/docs/configuration-options.md @@ -304,6 +304,8 @@ See https://renovateapp.com/docs/deep-dives/private-modules for details on how t See https://renovateapp.com/docs/deep-dives/private-modules for details on how this is used. +## nuget + ## nvm For settings common to all node.js version updates (e.g. travis, nvm, etc) you can use the `node` object instead. diff --git a/yarn.lock b/yarn.lock index aa72a246655a1dfd86a203ccb4a5bef695964085..4f933fb86d7cb5a25e91c209ad3605d7bc04441d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1895,6 +1895,12 @@ fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" +fast-xml-parser@3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-3.10.0.tgz#cea8fb0960ce5b43e2ae37379fbdf75ed3107c1f" + dependencies: + nimnjs "^1.3.2" + fb-watchman@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58" @@ -4197,6 +4203,21 @@ nice-try@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.4.tgz#d93962f6c52f2c1558c0fbda6d512819f1efe1c4" +nimn-date-parser@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/nimn-date-parser/-/nimn-date-parser-1.0.0.tgz#4ce55d1fd5ea206bbe82b76276f7b7c582139351" + +nimn_schema_builder@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/nimn_schema_builder/-/nimn_schema_builder-1.1.0.tgz#b370ccf5b647d66e50b2dcfb20d0aa12468cd247" + +nimnjs@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/nimnjs/-/nimnjs-1.3.2.tgz#a6a877968d87fad836375a4f616525e55079a5ba" + dependencies: + nimn-date-parser "^1.0.0" + nimn_schema_builder "^1.0.0" + nock@9.3.3: version "9.3.3" resolved "https://registry.yarnpkg.com/nock/-/nock-9.3.3.tgz#d9f4cd3c011afeadaf5ccf1b243f6e353781cda0"