Compare commits
14 Commits
e94d405922
..
0.1.13
| Author | SHA1 | Date | |
|---|---|---|---|
| 30070f7f9c | |||
| 3730a56a77 | |||
| e790aebac3 | |||
| 0b4b5fb319 | |||
| e785907b2b | |||
| 26c2bb0a79 | |||
| 07c599b06b | |||
| 04b5ff2c14 | |||
| 6bf2c1355a | |||
| 0c625523f5 | |||
| 4b9360b451 | |||
| d4f1827b60 | |||
| 05f411803c | |||
| ab27892312 |
@@ -0,0 +1,8 @@
|
|||||||
|
[*]
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
max_line_length = 80
|
||||||
@@ -13,14 +13,14 @@ jobs:
|
|||||||
name: Release
|
name: Release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Increment tag
|
- name: Increment tag
|
||||||
id: tag
|
id: tag
|
||||||
uses: https://gitea.t000-n.de/t.behrendt/conventional-semantic-git-tag-increment@41b7e04221df8a033bec841d40a097b76e5f67ff # 0.1.29
|
uses: https://gitea.t000-n.de/t.behrendt/conventional-semantic-git-tag-increment@e393dbb067c09fd43519392572ccf63b66cba92d # 0.1.39
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITEA_TOKEN }}
|
token: ${{ secrets.GITEA_TOKEN }}
|
||||||
- uses: https://gitea.t000-n.de/t.behrendt/actions/release-git-tag@f386e2570df6a796ba0a69865c89ea0c1a7109ab # 0.2.2
|
- uses: https://gitea.t000-n.de/t.behrendt/actions/release-git-tag@29f50ea246d5d9a62ac3c611fa5c8a6e9846df5a # 0.2.8
|
||||||
with:
|
with:
|
||||||
tag: ${{ steps.tag.outputs.new-tag }}
|
tag: ${{ steps.tag.outputs.new-tag }}
|
||||||
|
|||||||
@@ -8,8 +8,61 @@ jobs:
|
|||||||
name: Dry-Run
|
name: Dry-Run
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||||
- name: Validate JSON
|
- name: Validate Renovate Config
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
json-file: renovate.json
|
json-file: renovate.json
|
||||||
|
|
||||||
|
test:
|
||||||
|
name: Test
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||||
|
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||||
|
with:
|
||||||
|
node-version-file: .nvmrc
|
||||||
|
- name: Cache dependencies
|
||||||
|
id: cache-deps
|
||||||
|
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
node_modules
|
||||||
|
key: ${{ runner.os }}-npm-${{ hashFiles('package-lock.json') }}
|
||||||
|
- name: Install dependencies
|
||||||
|
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||||
|
run: npm ci
|
||||||
|
- name: Typecheck
|
||||||
|
run: npm run typecheck
|
||||||
|
- name: Format code
|
||||||
|
run: npm run format:check
|
||||||
|
- name: Run test
|
||||||
|
run: npm run test
|
||||||
|
|
||||||
|
check-dist:
|
||||||
|
name: Check Dist
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||||
|
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||||
|
with:
|
||||||
|
node-version-file: .nvmrc
|
||||||
|
- name: Cache dependencies
|
||||||
|
id: cache-deps
|
||||||
|
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
node_modules
|
||||||
|
key: ${{ runner.os }}-npm-${{ hashFiles('package-lock.json') }}
|
||||||
|
- name: Install dependencies
|
||||||
|
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||||
|
run: npm ci
|
||||||
|
- run: mv dist dist_orig
|
||||||
|
- run: npm run build
|
||||||
|
- run: |
|
||||||
|
original_hash=$(sha256sum dist_orig/index.js | cut -d' ' -f1)
|
||||||
|
new_hash=$(sha256sum dist/index.js | cut -d' ' -f1)
|
||||||
|
if [ "$original_hash" != "$new_hash" ]; then
|
||||||
|
echo "Build is not up to date. Original hash: $original_hash, new hash: $new_hash"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|||||||
@@ -8,15 +8,15 @@ jobs:
|
|||||||
name: Release
|
name: Release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Increment tag
|
- name: Increment tag
|
||||||
id: tag
|
id: tag
|
||||||
uses: https://gitea.t000-n.de/t.behrendt/conventional-semantic-git-tag-increment@41b7e04221df8a033bec841d40a097b76e5f67ff # 0.1.29
|
uses: https://gitea.t000-n.de/t.behrendt/conventional-semantic-git-tag-increment@e393dbb067c09fd43519392572ccf63b66cba92d # 0.1.39
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITEA_TOKEN }}
|
token: ${{ secrets.GITEA_TOKEN }}
|
||||||
prerelease: true
|
prerelease: true
|
||||||
- uses: https://gitea.t000-n.de/t.behrendt/actions/release-git-tag@f386e2570df6a796ba0a69865c89ea0c1a7109ab # 0.2.2
|
- uses: https://gitea.t000-n.de/t.behrendt/actions/release-git-tag@29f50ea246d5d9a62ac3c611fa5c8a6e9846df5a # 0.2.8
|
||||||
with:
|
with:
|
||||||
tag: ${{ steps.tag.outputs.new-tag }}
|
tag: ${{ steps.tag.outputs.new-tag }}
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
name: Run TAS
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
branch:
|
|
||||||
description: "The branch to run TAS on"
|
|
||||||
required: true
|
|
||||||
default: "main"
|
|
||||||
schedule:
|
|
||||||
- cron: "0 6 * * 5"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
run-tas:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
||||||
- uses: https://gitea.t000-n.de/t.behrendt/trivy-actions/setup-trivy@a6508d695d7bb6137f14372392d5c312c98225cf # 1.4.7
|
|
||||||
- uses: https://gitea.t000-n.de/t.behrendt/trivy-actions/setup-db@a6508d695d7bb6137f14372392d5c312c98225cf # 1.4.7
|
|
||||||
- env:
|
|
||||||
TRIVY_CACHE_DIR: ${{ runner.temp }}/trivy
|
|
||||||
run: |
|
|
||||||
trivy config --cache-dir "$TRIVY_CACHE_DIR" --exit-code 0 --format sarif --output sarif.json .
|
|
||||||
- uses: https://gitea.t000-n.de/t.behrendt/tas-actions/tas-upload-sarif@5e1031a9eff4a83fc17d0893332ad896386c082f # 0.0.3
|
|
||||||
with:
|
|
||||||
tas-base-url: ${{ vars.TAS_BASE_URL }}
|
|
||||||
sarif-file: sarif.json
|
|
||||||
owner: t.behrendt
|
|
||||||
repo: validate-json-by-json-schema-action
|
|
||||||
branch: ${{ inputs.branch || github.head_ref || 'main' }}
|
|
||||||
+1
-137
@@ -1,138 +1,2 @@
|
|||||||
# ---> Node
|
node_modules
|
||||||
# Logs
|
|
||||||
logs
|
|
||||||
*.log
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
lerna-debug.log*
|
|
||||||
.pnpm-debug.log*
|
|
||||||
|
|
||||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
|
||||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
|
||||||
|
|
||||||
# Runtime data
|
|
||||||
pids
|
|
||||||
*.pid
|
|
||||||
*.seed
|
|
||||||
*.pid.lock
|
|
||||||
|
|
||||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
|
||||||
lib-cov
|
|
||||||
|
|
||||||
# Coverage directory used by tools like istanbul
|
|
||||||
coverage
|
coverage
|
||||||
*.lcov
|
|
||||||
|
|
||||||
# nyc test coverage
|
|
||||||
.nyc_output
|
|
||||||
|
|
||||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
|
||||||
.grunt
|
|
||||||
|
|
||||||
# Bower dependency directory (https://bower.io/)
|
|
||||||
bower_components
|
|
||||||
|
|
||||||
# node-waf configuration
|
|
||||||
.lock-wscript
|
|
||||||
|
|
||||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
|
||||||
build/Release
|
|
||||||
|
|
||||||
# Dependency directories
|
|
||||||
node_modules/
|
|
||||||
jspm_packages/
|
|
||||||
|
|
||||||
# Snowpack dependency directory (https://snowpack.dev/)
|
|
||||||
web_modules/
|
|
||||||
|
|
||||||
# TypeScript cache
|
|
||||||
*.tsbuildinfo
|
|
||||||
|
|
||||||
# Optional npm cache directory
|
|
||||||
.npm
|
|
||||||
|
|
||||||
# Optional eslint cache
|
|
||||||
.eslintcache
|
|
||||||
|
|
||||||
# Optional stylelint cache
|
|
||||||
.stylelintcache
|
|
||||||
|
|
||||||
# Microbundle cache
|
|
||||||
.rpt2_cache/
|
|
||||||
.rts2_cache_cjs/
|
|
||||||
.rts2_cache_es/
|
|
||||||
.rts2_cache_umd/
|
|
||||||
|
|
||||||
# Optional REPL history
|
|
||||||
.node_repl_history
|
|
||||||
|
|
||||||
# Output of 'npm pack'
|
|
||||||
*.tgz
|
|
||||||
|
|
||||||
# Yarn Integrity file
|
|
||||||
.yarn-integrity
|
|
||||||
|
|
||||||
# dotenv environment variable files
|
|
||||||
.env
|
|
||||||
.env.development.local
|
|
||||||
.env.test.local
|
|
||||||
.env.production.local
|
|
||||||
.env.local
|
|
||||||
|
|
||||||
# parcel-bundler cache (https://parceljs.org/)
|
|
||||||
.cache
|
|
||||||
.parcel-cache
|
|
||||||
|
|
||||||
# Next.js build output
|
|
||||||
.next
|
|
||||||
out
|
|
||||||
|
|
||||||
# Nuxt.js build / generate output
|
|
||||||
.nuxt
|
|
||||||
dist
|
|
||||||
|
|
||||||
# Gatsby files
|
|
||||||
.cache/
|
|
||||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
|
||||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
|
||||||
# public
|
|
||||||
|
|
||||||
# vuepress build output
|
|
||||||
.vuepress/dist
|
|
||||||
|
|
||||||
# vuepress v2.x temp and cache directory
|
|
||||||
.temp
|
|
||||||
.cache
|
|
||||||
|
|
||||||
# vitepress build output
|
|
||||||
**/.vitepress/dist
|
|
||||||
|
|
||||||
# vitepress cache directory
|
|
||||||
**/.vitepress/cache
|
|
||||||
|
|
||||||
# Docusaurus cache and generated files
|
|
||||||
.docusaurus
|
|
||||||
|
|
||||||
# Serverless directories
|
|
||||||
.serverless/
|
|
||||||
|
|
||||||
# FuseBox cache
|
|
||||||
.fusebox/
|
|
||||||
|
|
||||||
# DynamoDB Local files
|
|
||||||
.dynamodb/
|
|
||||||
|
|
||||||
# TernJS port file
|
|
||||||
.tern-port
|
|
||||||
|
|
||||||
# Stores VSCode versions used for testing VSCode extensions
|
|
||||||
.vscode-test
|
|
||||||
|
|
||||||
# yarn v2
|
|
||||||
.yarn/cache
|
|
||||||
.yarn/unplugged
|
|
||||||
.yarn/build-state.yml
|
|
||||||
.yarn/install-state.gz
|
|
||||||
.pnp.*
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"$schema": "./node_modules/oxfmt/configuration_schema.json",
|
||||||
|
"ignorePatterns": ["dist/**", "node_modules/**", "coverage/**"]
|
||||||
|
}
|
||||||
@@ -2,17 +2,17 @@ MIT License
|
|||||||
|
|
||||||
Copyright (c) 2025 t.behrendt
|
Copyright (c) 2025 t.behrendt
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||||
associated documentation files (the "Software"), to deal in the Software without restriction, including
|
associated documentation files (the "Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
|
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
|
||||||
following conditions:
|
following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial
|
The above copyright notice and this permission notice shall be included in all copies or substantial
|
||||||
portions of the Software.
|
portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
||||||
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
|
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
|
||||||
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|||||||
+2
-23
@@ -8,26 +8,5 @@ inputs:
|
|||||||
required: true
|
required: true
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: "composite"
|
using: "node24"
|
||||||
steps:
|
main: "dist/index.js"
|
||||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
|
||||||
with:
|
|
||||||
node-version: "latest"
|
|
||||||
- name: Extract schema
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
schema=$(jq -r '.["$schema"]' < ${{ inputs.json-file }})
|
|
||||||
if [ -n "$schema" ]; then
|
|
||||||
curl -s $schema > schema.json
|
|
||||||
else
|
|
||||||
echo "No schema found"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
- name: Update the schema to the latest version
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
npx ajv-cli migrate -s schema.json -o schema.json
|
|
||||||
- name: Validate JSON
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
npx ajv-cli validate -s schema.json -d ${{ inputs.json-file }} --strict=false
|
|
||||||
|
|||||||
Vendored
+22249
File diff suppressed because one or more lines are too long
Generated
+2037
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"name": "validate-json-by-json-schema-action",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"type": "commonjs",
|
||||||
|
"main": "src/index.ts",
|
||||||
|
"scripts": {
|
||||||
|
"test": "vitest --config vitext.config.ts",
|
||||||
|
"format": "oxfmt",
|
||||||
|
"format:check": "oxfmt --check",
|
||||||
|
"build": "rolldown -c",
|
||||||
|
"typecheck": "tsc --noEmit"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@actions/core": "3.0.1",
|
||||||
|
"ajv": "8.20.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "24.13.2",
|
||||||
|
"@vitest/coverage-v8": "4.1.9",
|
||||||
|
"oxfmt": "0.56.0",
|
||||||
|
"rolldown": "1.1.3",
|
||||||
|
"typescript": "6.0.3",
|
||||||
|
"vitest": "4.1.9"
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
-3
@@ -1,7 +1,12 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||||
"extends": [
|
"extends": [
|
||||||
"local>t.behrendt/renovate-configs:common",
|
"local>t.behrendt/renovate-configs:action",
|
||||||
"local>t.behrendt/renovate-configs:action"
|
"local>t.behrendt/renovate-configs:bun-npm"
|
||||||
]
|
],
|
||||||
|
"postUpgradeTasks": {
|
||||||
|
"commands": ["npm ci", "npm run build"],
|
||||||
|
"fileFilters": ["dist/**"],
|
||||||
|
"executionMode": "update"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { defineConfig } from "rolldown";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
input: "src/index.ts",
|
||||||
|
platform: "node",
|
||||||
|
tsconfig: "./tsconfig.json",
|
||||||
|
output: {
|
||||||
|
file: "dist/index.js",
|
||||||
|
format: "cjs",
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import { run } from "./main";
|
||||||
|
|
||||||
|
run();
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
import * as core from "@actions/core";
|
||||||
|
import { readFileSync } from "node:fs";
|
||||||
|
import { validateJson } from "./validation";
|
||||||
|
|
||||||
|
export async function run(): Promise<void> {
|
||||||
|
try {
|
||||||
|
const jsonFilePath = core.getInput("json-file");
|
||||||
|
core.info(`Validating JSON file: ${jsonFilePath}`);
|
||||||
|
|
||||||
|
const json = readFileSync(jsonFilePath, "utf8");
|
||||||
|
|
||||||
|
await validateJson(json);
|
||||||
|
|
||||||
|
core.info("JSON file is valid");
|
||||||
|
} catch (error) {
|
||||||
|
core.setFailed(`Error validating JSON file: ${error}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
import { validateJson } from "./validation";
|
||||||
|
|
||||||
|
global.fetch = vi.fn();
|
||||||
|
|
||||||
|
const validSchema = JSON.stringify({
|
||||||
|
$id: "https://t00n.de/schema.json",
|
||||||
|
title:
|
||||||
|
"JSON schema for Renovate 43.244.4 config files (https://renovatebot.com/)",
|
||||||
|
$schema: "http://json-schema.org/draft-07/schema#",
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
$schema: {
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ["name"],
|
||||||
|
additionalProperties: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("validateJson()", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws an error if the JSON file is not valid JSON", async () => {
|
||||||
|
const jsonFile = {
|
||||||
|
despiteThisBeingValidJson: "toString() breaks it, making it invalid",
|
||||||
|
}.toString();
|
||||||
|
await expect(validateJson(jsonFile)).rejects.toThrow(
|
||||||
|
'"[object Object]" is not valid JSON',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws an error if the JSON file does not contain a $schema property", async () => {
|
||||||
|
const jsonFile = JSON.stringify({
|
||||||
|
validJson: true,
|
||||||
|
});
|
||||||
|
await expect(validateJson(jsonFile)).rejects.toThrow(
|
||||||
|
"No schema found in JSON file.",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws an error if the schema cannot be fetched", async () => {
|
||||||
|
vi.mocked(fetch).mockRejectedValue(new Error("Failed to fetch schema"));
|
||||||
|
const jsonFile = JSON.stringify({ $schema: "http://t00n.de/404.json" });
|
||||||
|
await expect(validateJson(jsonFile)).rejects.toThrow(
|
||||||
|
"Failed to fetch schema",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws an error if the schema file is not valid", async () => {
|
||||||
|
vi.mocked(fetch).mockResolvedValue(
|
||||||
|
// @ts-expect-error - mock response
|
||||||
|
{
|
||||||
|
ok: true,
|
||||||
|
text: async () =>
|
||||||
|
({
|
||||||
|
despiteThisBeingValidJson:
|
||||||
|
"toString() breaks it, making it invalid",
|
||||||
|
}).toString(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const jsonFile = JSON.stringify({
|
||||||
|
$schema: "https://json-schema.org/draft-07/schema",
|
||||||
|
});
|
||||||
|
await expect(validateJson(jsonFile)).rejects.toThrow(
|
||||||
|
'"[object Object]" is not valid JSON',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws an error if the JSON file does not match the schema", async () => {
|
||||||
|
vi.mocked(fetch).mockResolvedValue(
|
||||||
|
// @ts-expect-error - mock response
|
||||||
|
{
|
||||||
|
ok: true,
|
||||||
|
text: async () => validSchema,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const jsonFile = JSON.stringify({
|
||||||
|
$schema: "https://json-schema.org/draft-07/schema",
|
||||||
|
notTheExpectedField: 42,
|
||||||
|
});
|
||||||
|
await expect(validateJson(jsonFile)).rejects.toThrow(
|
||||||
|
"JSON file is not valid: No errors",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not throw an error if the JSON file is valid", async () => {
|
||||||
|
vi.mocked(fetch).mockResolvedValue(
|
||||||
|
// @ts-expect-error - mock response
|
||||||
|
{
|
||||||
|
ok: true,
|
||||||
|
text: async () => validSchema,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const jsonFile = JSON.stringify({
|
||||||
|
$schema: "https://t00n.de/schema.json",
|
||||||
|
name: "John Doe",
|
||||||
|
});
|
||||||
|
await expect(validateJson(jsonFile)).resolves.toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import Ajv from "ajv";
|
||||||
|
|
||||||
|
export const validateJson = async (jsonFileContent: string): Promise<void> => {
|
||||||
|
const jsonObject = JSON.parse(jsonFileContent);
|
||||||
|
|
||||||
|
const schema = jsonObject["$schema"];
|
||||||
|
if (!schema) {
|
||||||
|
throw new Error("No schema found in JSON file.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const schemaUrl = new URL(schema);
|
||||||
|
|
||||||
|
const schemaContent = await fetch(schemaUrl.toString());
|
||||||
|
const schemaText = await schemaContent.text();
|
||||||
|
const schemaObject = JSON.parse(schemaText);
|
||||||
|
|
||||||
|
const validator = new Ajv({
|
||||||
|
strict: false,
|
||||||
|
});
|
||||||
|
const validate = validator.compile(schemaObject);
|
||||||
|
const isValid = validate(jsonObject);
|
||||||
|
if (!isValid) {
|
||||||
|
throw new Error(`JSON file is not valid: ${validator.errorsText()}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2022",
|
||||||
|
"module": "commonjs",
|
||||||
|
"lib": ["ES2022"],
|
||||||
|
"types": ["node"],
|
||||||
|
"strict": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"removeComments": false,
|
||||||
|
"noImplicitAny": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noImplicitThis": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"exactOptionalPropertyTypes": true,
|
||||||
|
"noImplicitOverride": true
|
||||||
|
},
|
||||||
|
"include": ["src/**/*"],
|
||||||
|
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { defineConfig } from "vitest/config";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
test: {
|
||||||
|
coverage: {
|
||||||
|
enabled: true,
|
||||||
|
provider: "v8",
|
||||||
|
reporter: ["lcov"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user