diff --git a/default.json b/default.json index 1aa4aad..de443d6 100644 --- a/default.json +++ b/default.json @@ -7,10 +7,7 @@ ], "packageRules": [ { - "matchUpdateTypes": [ - "minor", - "patch" - ], + "matchUpdateTypes": ["minor", "patch"], "matchCurrentVersion": "!/^0/", "automerge": true } diff --git a/deno.json b/deno.json index ff29be0..4b3664c 100644 --- a/deno.json +++ b/deno.json @@ -4,6 +4,7 @@ "github>Omochice/renovate-config//deno/deno-land", "github>Omochice/renovate-config//deno/npm", "github>Omochice/renovate-config//deno/github-tag", - "github>Omochice/renovate-config//deno/nest-land" + "github>Omochice/renovate-config//deno/nest-land", + "github>Omochice/renovate-config//deno/jsr" ] } diff --git a/deno/jsr.json b/deno/jsr.json new file mode 100644 index 0000000..72ac6f2 --- /dev/null +++ b/deno/jsr.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "customManagers": [ + { + "customType": "regex", + "fileMatch": ["^import_map.json$", "^deno.jsonc?$"], + "matchStrings": [ + "['\"].+?['\"]\\s*:\\s*['\"]jsr:(?@(?.+?)/(?.+?))@[\\^~]?(?(?:0|[1-9]\\d*)(?:\\.(?:0|[1-9]\\d*)(?:\\.(?:0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)?)?)[/\"']" + ], + "datasourceTemplate": "npm" + }, + { + "customType": "regex", + "fileMatch": ["\\.[jt]sx?$"], + "matchStrings": [ + "((?:im|ex)port(?:.|\\s)+?from\\s*|//\\s*@deno-types=)['\"]jsr:(?@(?.+?)/(?.+?))@[\\^~]?(?(?:0|[1-9]\\d*)(?:\\.(?:0|[1-9]\\d*)(?:\\.(?:0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)?)?)[/'\"]" + ], + "datasourceTemplate": "npm", + "packageNameTemplate": "@jsr/{{namespace}}__{{package}}" + } + ], + "npmrc": "@jsr:registry=https://npm.jsr.io" +} diff --git a/package.json b/package.json index e28c2a9..a938675 100644 --- a/package.json +++ b/package.json @@ -3,9 +3,7 @@ "version": "2.1.0", "private": true, "description": "renovate configuration for me", - "keywords": [ - "renovate" - ], + "keywords": ["renovate"], "license": "zlib", "author": "Omochice", "scripts": { diff --git a/test/deno/jsr.test.ts b/test/deno/jsr.test.ts new file mode 100644 index 0000000..76b2231 --- /dev/null +++ b/test/deno/jsr.test.ts @@ -0,0 +1,123 @@ +import { expect, expectTypeOf, describe, it } from "vitest"; +import { readFileSync } from "node:fs"; +import { dirname, join } from "node:path"; + +const repositoryRoot = dirname(dirname(__dirname)); + +const file = readFileSync(join(repositoryRoot, "deno", "jsr.json")).toString(); +const config: string[][] = JSON.parse(file)?.customManagers?.map( + (manager: { matchStrings?: string[] }) => manager.matchStrings, +); + +const regexps: RegExp[][] = config.map((matchStrings: string[]) => + matchStrings.map((re) => new RegExp(re)), +); + +describe("check configuration existing", () => { + it("should be array", () => { + expect(Array.isArray(config)); + }); + it("should be array of regexp", () => { + expectTypeOf(regexps).toEqualTypeOf(); + }); +}); + +describe("jsr for import map", () => { + const testCases = [ + { + title: "should accept jsr specifier", + input: `{ + "imports": { + "@luca/flag": "jsr:@luca/flag@^1.0.1" + } + }`, + currentValue: "1.0.1", + depName: "@luca/flag", + }, + ] as const; + + for (const testCase of testCases) { + it(testCase.title, () => { + const re = regexps[0].map((r) => new RegExp(r, "gm")); + const matches = re + .map((r) => Array.from(testCase.input.matchAll(r)).map((e) => e.groups)) + .filter((match) => match.length !== 0) + .flat(); + expect(matches.length).toBe(1); + expect(matches[0]?.currentValue).toBe(testCase.currentValue); + expect(matches[0]?.depName).toBe(testCase.depName); + }); + } +}); + +describe("jsr for js file", () => { + const testCases = [ + { + title: "should accept jsr specifier", + input: `import { printProgress } from "jsr:@luca/flag@1.0.1";`, + currentValue: "1.0.1", + depName: "@luca/flag", + }, + { + title: "should accept version pinning(^)", + input: `import { printProgress } from "jsr:@luca/flag@^1.0.1";`, + currentValue: "1.0.1", + depName: "@luca/flag", + }, + { + title: "should accept version pinning(~)", + input: `import { printProgress } from "jsr:@luca/flag@~1.0.1";`, + currentValue: "1.0.1", + depName: "@luca/flag", + }, + { + title: "should accept only major version", + input: `import { printProgress } from "jsr:@luca/flag@1";`, + currentValue: "1", + depName: "@luca/flag", + }, + { + title: "should accept jsr specifier in //@deno-types", + input: `// @deno-types="jsr:@luca/flag@1.0.1";`, + currentValue: "1.0.1", + depName: "@luca/flag", + }, + { + title: "should accept jsr specifier in //@deno-types", + input: `// @deno-types="jsr:@luca/flag@1.0.1";`, + currentValue: "1.0.1", + depName: "@luca/flag", + }, + { + title: "version pinning(^) with //@deno-types", + input: `// @deno-types="jsr:@luca/flag@^1.0.1";`, + currentValue: "1.0.1", + depName: "@luca/flag", + }, + { + title: "version pinning(~) with //@deno-types", + input: `// @deno-types="jsr:@luca/flag@~1.0.1";`, + currentValue: "1.0.1", + depName: "@luca/flag", + }, + { + title: "only major version with //@deno-types", + input: `// @deno-types="jsr:@luca/flag@1";`, + currentValue: "1", + depName: "@luca/flag", + }, + ] as const; + + for (const testCase of testCases) { + it(testCase.title, () => { + const re = regexps[1].map((r) => new RegExp(r, "gm")); + const matches = re + .map((r) => Array.from(testCase.input.matchAll(r)).map((e) => e.groups)) + .filter((match) => match.length !== 0) + .flat(); + expect(matches.length).toBe(1); + expect(matches[0]?.currentValue).toBe(testCase.currentValue); + expect(matches[0]?.depName).toBe(testCase.depName); + }); + } +});