Merge branch 'main' into merge-scan-into-ingest-v1

This commit is contained in:
Andrey Avtomonov 2026-05-14 01:24:27 +02:00 committed by GitHub
commit 2fd2bfde98
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 273 additions and 21 deletions

View file

@ -188,6 +188,70 @@ jobs:
- name: Run Python checks
run: uv run pytest
coverage:
name: Coverage
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup pnpm
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
with:
run_install: false
- name: Setup Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "24"
cache: "pnpm"
cache-dependency-path: "pnpm-lock.yaml"
- name: Install TypeScript dependencies
run: pnpm install --frozen-lockfile
- name: Setup Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.13"
- name: Setup uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
version: "0.11.11"
enable-cache: true
cache-dependency-glob: "uv.lock"
- name: Install Python dependencies
run: uv sync --all-packages --all-groups
- name: Generate TypeScript coverage
run: pnpm run test:coverage:ts
- name: Upload TypeScript coverage
uses: codecov/codecov-action@75cd11691c0faa626561e295848008c8a7dddffe # v5.5.4
with:
use_oidc: true
files: ./packages/cli/coverage/lcov.info,./packages/connector-bigquery/coverage/lcov.info,./packages/connector-clickhouse/coverage/lcov.info,./packages/connector-mysql/coverage/lcov.info,./packages/connector-postgres/coverage/lcov.info,./packages/connector-snowflake/coverage/lcov.info,./packages/connector-sqlite/coverage/lcov.info,./packages/connector-sqlserver/coverage/lcov.info,./packages/context/coverage/lcov.info,./packages/llm/coverage/lcov.info
flags: typescript
name: typescript
fail_ci_if_error: false
- name: Generate Python coverage
run: pnpm run test:coverage:py
- name: Upload Python coverage
uses: codecov/codecov-action@75cd11691c0faa626561e295848008c8a7dddffe # v5.5.4
with:
use_oidc: true
files: ./coverage/python.xml
flags: python
name: python
fail_ci_if_error: false
artifact-checks:
name: Artifact checks
runs-on: ubuntu-latest

View file

@ -8,6 +8,7 @@
<p align="center">
<a href="https://www.npmjs.com/package/@kaelio/ktx"><img src="https://img.shields.io/npm/v/@kaelio/ktx?style=flat-square&color=f97316" alt="npm version" /></a>
<a href="https://codecov.io/gh/Kaelio/ktx"><img src="https://codecov.io/gh/Kaelio/ktx/branch/main/graph/badge.svg" alt="Codecov" /></a>
<a href="https://github.com/Kaelio/ktx/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-blue?style=flat-square" alt="License" /></a>
<a href="https://github.com/Kaelio/ktx"><img src="https://img.shields.io/github/stars/Kaelio/ktx?style=flat-square" alt="GitHub stars" /></a>
</p>

View file

@ -79,6 +79,7 @@
"**/*.gen.ts",
"**/*.generated.ts"
],
"ignoreBinaries": ["uv"],
"ignoreIssues": {
"packages/cli/src/clack.ts": ["exports"],
"packages/cli/src/commands/connection-metabase-setup.ts": ["exports", "types"],

View file

@ -36,6 +36,9 @@
"relationships:verify-orbit": "node scripts/relationship-orbit-verification.mjs",
"smoke": "pnpm run build && pnpm --filter @ktx/cli run smoke",
"test": "node --test scripts/*.test.mjs && pnpm --filter './packages/*' run test",
"test:coverage": "pnpm run test:coverage:ts && pnpm run test:coverage:py",
"test:coverage:py": "uv run pytest --cov=python/ktx-sl/semantic_layer --cov=python/ktx-daemon/src/ktx_daemon --cov-report=xml:coverage/python.xml --cov-report=term",
"test:coverage:ts": "pnpm --filter './packages/*' run build && pnpm --filter './packages/*' run test --coverage --coverage.reporter=lcov --coverage.exclude='dist/**'",
"test:slow": "pnpm --filter @ktx/context run test:slow && pnpm --filter @ktx/cli run test:slow",
"type-check": "pnpm --filter './packages/*' run type-check"
},

View file

@ -54,6 +54,7 @@
"@types/better-sqlite3": "^7.6.13",
"@types/node": "^25.7.0",
"@types/react": "^19.2.14",
"@vitest/coverage-v8": "^4.1.6",
"better-sqlite3": "^12.10.0",
"ink-testing-library": "^4.0.0",
"typescript": "^6.0.3",

View file

@ -281,7 +281,7 @@ describe('runKtxDoctor', () => {
});
it('runs project checks against a valid ktx.yaml', async () => {
process.env.ANTHROPIC_API_KEY = 'test-key';
process.env.ANTHROPIC_API_KEY = 'test-key'; // pragma: allowlist secret
await writeFile(
join(tempDir, 'ktx.yaml'),
[
@ -306,7 +306,7 @@ describe('runKtxDoctor', () => {
].join('\n'),
'utf-8',
);
process.env.OPENAI_API_KEY = 'test-key';
process.env.OPENAI_API_KEY = 'test-key'; // pragma: allowlist secret
const testIo = makeIo();
await expect(
@ -419,7 +419,7 @@ describe('runKtxDoctor', () => {
});
it('warns when semantic-search embeddings are not configured', async () => {
process.env.ANTHROPIC_API_KEY = 'test-key';
process.env.ANTHROPIC_API_KEY = 'test-key'; // pragma: allowlist secret
await writeFile(
join(tempDir, 'ktx.yaml'),
[

View file

@ -1144,13 +1144,13 @@ describe('setup sources step', () => {
});
expect(discoverMetabaseDatabases).toHaveBeenCalledWith({
sourceUrl: 'https://metabase-new.example.com',
sourceApiKeyRef: 'env:METABASE_API_KEY',
sourceApiKeyRef: 'env:METABASE_API_KEY', // pragma: allowlist secret
sourceConnectionId: 'metabase-main',
});
expect((await readConfig()).connections['metabase-main']).toMatchObject({
driver: 'metabase',
api_url: 'https://metabase-new.example.com',
api_key_ref: 'env:METABASE_API_KEY',
api_key_ref: 'env:METABASE_API_KEY', // pragma: allowlist secret
mappings: {
databaseMappings: { '2': 'warehouse' },
syncEnabled: { '2': true },

View file

@ -168,9 +168,13 @@ describe('standalone built ktx CLI smoke', () => {
it('runs doctor setup through the built binary', async () => {
const result = await runBuiltCli(['status', '--no-input']);
expect(result.stdout).toMatch(/KTX (setup|project) doctor/);
expect(result.stdout).toContain('Node 22+');
expect(result.stdout).toContain('Workspace-local CLI');
expect(result.stdout).toMatch(/KTX (setup doctor|project doctor|status)/);
if (result.stdout.includes('No project here yet.')) {
expect(result.stdout).toContain('Before you can run ktx setup');
} else {
expect(result.stdout).toContain('Node 22+');
expect(result.stdout).toContain('Workspace-local CLI');
}
expect(result.stderr === '' || result.stderr.startsWith('Project: ')).toBe(true);
expect([0, 1]).toContain(result.code);
});

View file

@ -31,6 +31,7 @@
},
"devDependencies": {
"@types/node": "^25.7.0",
"@vitest/coverage-v8": "^4.1.6",
"typescript": "^6.0.3",
"vitest": "^4.1.6"
},

View file

@ -31,6 +31,7 @@
},
"devDependencies": {
"@types/node": "^25.7.0",
"@vitest/coverage-v8": "^4.1.6",
"typescript": "^6.0.3",
"vitest": "^4.1.6"
},

View file

@ -31,6 +31,7 @@
},
"devDependencies": {
"@types/node": "^25.7.0",
"@vitest/coverage-v8": "^4.1.6",
"typescript": "^6.0.3",
"vitest": "^4.1.6"
},

View file

@ -32,6 +32,7 @@
"devDependencies": {
"@types/node": "^25.7.0",
"@types/pg": "^8.20.0",
"@vitest/coverage-v8": "^4.1.6",
"typescript": "^6.0.3",
"vitest": "^4.1.6"
},

View file

@ -31,6 +31,7 @@
},
"devDependencies": {
"@types/node": "^25.7.0",
"@vitest/coverage-v8": "^4.1.6",
"typescript": "^6.0.3",
"vitest": "^4.1.6"
},

View file

@ -32,6 +32,7 @@
"devDependencies": {
"@types/better-sqlite3": "^7.6.13",
"@types/node": "^25.7.0",
"@vitest/coverage-v8": "^4.1.6",
"typescript": "^6.0.3",
"vitest": "^4.1.6"
},

View file

@ -32,6 +32,7 @@
"devDependencies": {
"@types/mssql": "^12.3.0",
"@types/node": "^25.7.0",
"@vitest/coverage-v8": "^4.1.6",
"typescript": "^6.0.3",
"vitest": "^4.1.6"
},

View file

@ -152,6 +152,7 @@
"@types/better-sqlite3": "^7.6.13",
"@types/node": "^25.7.0",
"@types/pg": "^8.20.0",
"@vitest/coverage-v8": "^4.1.6",
"typescript": "^6.0.3",
"vitest": "^4.1.6"
},

View file

@ -34,6 +34,7 @@
},
"devDependencies": {
"@types/node": "^25.7.0",
"@vitest/coverage-v8": "^4.1.6",
"typescript": "^6.0.3",
"vitest": "^4.1.6"
},

187
pnpm-lock.yaml generated
View file

@ -128,6 +128,9 @@ importers:
'@types/react':
specifier: ^19.2.14
version: 19.2.14
'@vitest/coverage-v8':
specifier: ^4.1.6
version: 4.1.6(vitest@4.1.6)
better-sqlite3:
specifier: ^12.10.0
version: 12.10.0
@ -139,7 +142,7 @@ importers:
version: 6.0.3
vitest:
specifier: ^4.1.6
version: 4.1.6(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.7.0)(yaml@2.9.0))
version: 4.1.6(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/coverage-v8@4.1.6)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.7.0)(yaml@2.9.0))
packages/connector-bigquery:
dependencies:
@ -153,12 +156,15 @@ importers:
'@types/node':
specifier: ^24.3.0
version: 24.12.2
'@vitest/coverage-v8':
specifier: ^4.1.6
version: 4.1.6(vitest@4.1.6)
typescript:
specifier: ^6.0.3
version: 6.0.3
vitest:
specifier: ^4.1.6
version: 4.1.6(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.7.0)(yaml@2.9.0))
version: 4.1.6(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/coverage-v8@4.1.6)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.7.0)(yaml@2.9.0))
packages/connector-clickhouse:
dependencies:
@ -172,12 +178,15 @@ importers:
'@types/node':
specifier: ^24.3.0
version: 24.12.2
'@vitest/coverage-v8':
specifier: ^4.1.6
version: 4.1.6(vitest@4.1.6)
typescript:
specifier: ^6.0.3
version: 6.0.3
vitest:
specifier: ^4.1.6
version: 4.1.6(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.7.0)(yaml@2.9.0))
version: 4.1.6(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/coverage-v8@4.1.6)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.7.0)(yaml@2.9.0))
packages/connector-mysql:
dependencies:
@ -191,12 +200,15 @@ importers:
'@types/node':
specifier: ^24.3.0
version: 24.12.2
'@vitest/coverage-v8':
specifier: ^4.1.6
version: 4.1.6(vitest@4.1.6)
typescript:
specifier: ^6.0.3
version: 6.0.3
vitest:
specifier: ^4.1.6
version: 4.1.6(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.7.0)(yaml@2.9.0))
version: 4.1.6(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/coverage-v8@4.1.6)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.7.0)(yaml@2.9.0))
packages/connector-postgres:
dependencies:
@ -213,12 +225,15 @@ importers:
'@types/pg':
specifier: ^8.20.0
version: 8.20.0
'@vitest/coverage-v8':
specifier: ^4.1.6
version: 4.1.6(vitest@4.1.6)
typescript:
specifier: ^6.0.3
version: 6.0.3
vitest:
specifier: ^4.1.6
version: 4.1.6(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.7.0)(yaml@2.9.0))
version: 4.1.6(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/coverage-v8@4.1.6)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.7.0)(yaml@2.9.0))
packages/connector-snowflake:
dependencies:
@ -232,12 +247,15 @@ importers:
'@types/node':
specifier: ^24.3.0
version: 24.12.2
'@vitest/coverage-v8':
specifier: ^4.1.6
version: 4.1.6(vitest@4.1.6)
typescript:
specifier: ^6.0.3
version: 6.0.3
vitest:
specifier: ^4.1.6
version: 4.1.6(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.7.0)(yaml@2.9.0))
version: 4.1.6(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/coverage-v8@4.1.6)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.7.0)(yaml@2.9.0))
packages/connector-sqlite:
dependencies:
@ -254,12 +272,15 @@ importers:
'@types/node':
specifier: ^24.3.0
version: 24.12.2
'@vitest/coverage-v8':
specifier: ^4.1.6
version: 4.1.6(vitest@4.1.6)
typescript:
specifier: ^6.0.3
version: 6.0.3
vitest:
specifier: ^4.1.6
version: 4.1.6(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.7.0)(yaml@2.9.0))
version: 4.1.6(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/coverage-v8@4.1.6)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.7.0)(yaml@2.9.0))
packages/connector-sqlserver:
dependencies:
@ -276,12 +297,15 @@ importers:
'@types/node':
specifier: ^24.3.0
version: 24.12.2
'@vitest/coverage-v8':
specifier: ^4.1.6
version: 4.1.6(vitest@4.1.6)
typescript:
specifier: ^6.0.3
version: 6.0.3
vitest:
specifier: ^4.1.6
version: 4.1.6(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.7.0)(yaml@2.9.0))
version: 4.1.6(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/coverage-v8@4.1.6)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.7.0)(yaml@2.9.0))
packages/context:
dependencies:
@ -349,12 +373,15 @@ importers:
'@types/pg':
specifier: ^8.20.0
version: 8.20.0
'@vitest/coverage-v8':
specifier: ^4.1.6
version: 4.1.6(vitest@4.1.6)
typescript:
specifier: ^6.0.3
version: 6.0.3
vitest:
specifier: ^4.1.6
version: 4.1.6(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.7.0)(yaml@2.9.0))
version: 4.1.6(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/coverage-v8@4.1.6)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.7.0)(yaml@2.9.0))
packages/llm:
dependencies:
@ -377,12 +404,15 @@ importers:
'@types/node':
specifier: ^24.3.0
version: 24.12.2
'@vitest/coverage-v8':
specifier: ^4.1.6
version: 4.1.6(vitest@4.1.6)
typescript:
specifier: ^6.0.3
version: 6.0.3
vitest:
specifier: ^4.1.6
version: 4.1.6(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.7.0)(yaml@2.9.0))
version: 4.1.6(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/coverage-v8@4.1.6)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.7.0)(yaml@2.9.0))
packages:
@ -750,6 +780,27 @@ packages:
resolution: {integrity: sha512-SriLPKezypIsiZ+TtlFfE46uuBIap2HeaQVS78e1P7rz5OSbq0rsd52WE1mC5f7vAeLiXqv7I7oRhL3WFZEw3Q==}
engines: {node: '>=18.0.0'}
'@babel/helper-string-parser@7.27.1':
resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
engines: {node: '>=6.9.0'}
'@babel/helper-validator-identifier@7.28.5':
resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==}
engines: {node: '>=6.9.0'}
'@babel/parser@7.29.3':
resolution: {integrity: sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==}
engines: {node: '>=6.0.0'}
hasBin: true
'@babel/types@7.29.0':
resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==}
engines: {node: '>=6.9.0'}
'@bcoe/v8-coverage@1.0.2':
resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==}
engines: {node: '>=18'}
'@biomejs/biome@2.4.15':
resolution: {integrity: sha512-j5VH3a/h/HXTKBM50MDMxRCzkeLv9S2XJcW2WgnZT1+xyisi+0bISrXR82gCX+8S9lvK0skEvHJRN+3Ktr2hlw==}
engines: {node: '>=14.21.3'}
@ -2517,6 +2568,15 @@ packages:
resolution: {integrity: sha512-UycprH3T6n3jH0k44NHMa7pnFHGu/N05MjojYr+Mc6I7obkoLIJujSWwin1pCvdy/eOxrI/l3uDLQsmcrOb4ug==}
engines: {node: '>= 20'}
'@vitest/coverage-v8@4.1.6':
resolution: {integrity: sha512-36l628fQ/9a/8ihy97eOtEnvWQEdqULQOJtcaxtoNq0G1w3Mxd4szSahOaMM9/NGyZ+hyKcMtIW/WIxq0XQViQ==}
peerDependencies:
'@vitest/browser': 4.1.6
vitest: 4.1.6
peerDependenciesMeta:
'@vitest/browser':
optional: true
'@vitest/expect@4.1.6':
resolution: {integrity: sha512-7EHDquPthALSV0jhhjgEW8FXaviMx7rSqu8W6oqCoAuOhKov814P99QDV1pxMA3QPv21YudvJngIhjrNI4opLg==}
@ -2627,6 +2687,9 @@ packages:
resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
engines: {node: '>=12'}
ast-v8-to-istanbul@1.0.0:
resolution: {integrity: sha512-1fSfIwuDICFA4LKkCzRPO7F0hzFf0B7+Xqrl27ynQaa+Rh0e1Es0v6kWHPott3lU10AyAr7oKHa65OppjLn3Rg==}
astring@1.9.0:
resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==}
hasBin: true
@ -3364,6 +3427,10 @@ packages:
engines: {node: '>=0.4.7'}
hasBin: true
has-flag@4.0.0:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
has-symbols@1.1.0:
resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
engines: {node: '>= 0.4'}
@ -3414,6 +3481,9 @@ packages:
html-entities@2.6.0:
resolution: {integrity: sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==}
html-escaper@2.0.2:
resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
html-void-elements@3.0.0:
resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
@ -3548,6 +3618,18 @@ packages:
isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
istanbul-lib-coverage@3.2.2:
resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==}
engines: {node: '>=8'}
istanbul-lib-report@3.0.1:
resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==}
engines: {node: '>=10'}
istanbul-reports@3.2.0:
resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==}
engines: {node: '>=8'}
jiti@2.7.0:
resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==}
hasBin: true
@ -3558,6 +3640,9 @@ packages:
js-md4@0.3.2:
resolution: {integrity: sha512-/GDnfQYsltsjRswQhN9fhv3EMw2sCpUdrdxyWDOUK7eyD++r3gRhzgiQgc/x4MAv2i1iuQ4lxO5mvqM3vj4bwA==}
js-tokens@10.0.0:
resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==}
js-yaml@4.1.1:
resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
hasBin: true
@ -3718,6 +3803,13 @@ packages:
magic-string@0.30.21:
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
magicast@0.5.2:
resolution: {integrity: sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==}
make-dir@4.0.0:
resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==}
engines: {node: '>=10'}
markdown-extensions@2.0.0:
resolution: {integrity: sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==}
engines: {node: '>=16'}
@ -4574,6 +4666,10 @@ packages:
babel-plugin-macros:
optional: true
supports-color@7.2.0:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
engines: {node: '>=8'}
tagged-tag@1.0.0:
resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==}
engines: {node: '>=20'}
@ -5892,6 +5988,21 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@babel/helper-string-parser@7.27.1': {}
'@babel/helper-validator-identifier@7.28.5': {}
'@babel/parser@7.29.3':
dependencies:
'@babel/types': 7.29.0
'@babel/types@7.29.0':
dependencies:
'@babel/helper-string-parser': 7.27.1
'@babel/helper-validator-identifier': 7.28.5
'@bcoe/v8-coverage@1.0.2': {}
'@biomejs/biome@2.4.15':
optionalDependencies:
'@biomejs/cli-darwin-arm64': 2.4.15
@ -7607,6 +7718,20 @@ snapshots:
'@vercel/oidc@3.2.0': {}
'@vitest/coverage-v8@4.1.6(vitest@4.1.6)':
dependencies:
'@bcoe/v8-coverage': 1.0.2
'@vitest/utils': 4.1.6
ast-v8-to-istanbul: 1.0.0
istanbul-lib-coverage: 3.2.2
istanbul-lib-report: 3.0.1
istanbul-reports: 3.2.0
magicast: 0.5.2
obug: 2.1.1
std-env: 4.1.0
tinyrainbow: 3.1.0
vitest: 4.1.6(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/coverage-v8@4.1.6)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.7.0)(yaml@2.9.0))
'@vitest/expect@4.1.6':
dependencies:
'@standard-schema/spec': 1.1.0
@ -7720,6 +7845,12 @@ snapshots:
assertion-error@2.0.1: {}
ast-v8-to-istanbul@1.0.0:
dependencies:
'@jridgewell/trace-mapping': 0.3.31
estree-walker: 3.0.3
js-tokens: 10.0.0
astring@1.9.0: {}
async@3.2.6: {}
@ -8458,6 +8589,8 @@ snapshots:
optionalDependencies:
uglify-js: 3.19.3
has-flag@4.0.0: {}
has-symbols@1.1.0: {}
has-tostringtag@1.0.2:
@ -8584,6 +8717,8 @@ snapshots:
html-entities@2.6.0: {}
html-escaper@2.0.2: {}
html-void-elements@3.0.0: {}
http-errors@2.0.1:
@ -8714,12 +8849,27 @@ snapshots:
isexe@2.0.0: {}
istanbul-lib-coverage@3.2.2: {}
istanbul-lib-report@3.0.1:
dependencies:
istanbul-lib-coverage: 3.2.2
make-dir: 4.0.0
supports-color: 7.2.0
istanbul-reports@3.2.0:
dependencies:
html-escaper: 2.0.2
istanbul-lib-report: 3.0.1
jiti@2.7.0: {}
jose@6.2.2: {}
js-md4@0.3.2: {}
js-tokens@10.0.0: {}
js-yaml@4.1.1:
dependencies:
argparse: 2.0.1
@ -8875,6 +9025,16 @@ snapshots:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
magicast@0.5.2:
dependencies:
'@babel/parser': 7.29.3
'@babel/types': 7.29.0
source-map-js: 1.2.1
make-dir@4.0.0:
dependencies:
semver: 7.7.4
markdown-extensions@2.0.0: {}
markdown-table@3.0.4: {}
@ -10176,6 +10336,10 @@ snapshots:
client-only: 0.0.1
react: 19.2.6
supports-color@7.2.0:
dependencies:
has-flag: 4.0.0
tagged-tag@1.0.0: {}
tailwind-merge@3.6.0: {}
@ -10386,7 +10550,7 @@ snapshots:
jiti: 2.7.0
yaml: 2.9.0
vitest@4.1.6(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.7.0)(yaml@2.9.0)):
vitest@4.1.6(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/coverage-v8@4.1.6)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.7.0)(yaml@2.9.0)):
dependencies:
'@vitest/expect': 4.1.6
'@vitest/mocker': 4.1.6(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.7.0)(yaml@2.9.0))
@ -10411,6 +10575,7 @@ snapshots:
optionalDependencies:
'@opentelemetry/api': 1.9.0
'@types/node': 24.12.2
'@vitest/coverage-v8': 4.1.6(vitest@4.1.6)
transitivePeerDependencies:
- msw

View file

@ -15,6 +15,7 @@ Issues = "https://github.com/kaelio/ktx/issues"
dev = [
"pre-commit>=4.6.0",
"pytest>=9.0.2",
"pytest-cov>=7.1.0",
"ruff>=0.8.4",
]

View file

@ -915,8 +915,9 @@ try {
const doctor = await run('pnpm', ['exec', 'ktx', 'status', '--no-input']);
assert.ok([0, 1].includes(doctor.code), 'ktx status setup exit code must be 0 or 1');
requireStdout('ktx status setup', doctor, /KTX setup doctor/);
requireStdout('ktx status setup', doctor, /Node 22\\+/);
requireStdout('ktx status setup', doctor, /KTX status/);
requireStdout('ktx status setup', doctor, /No project here yet\\./);
requireStdout('ktx status setup', doctor, /Before you can run ktx setup/);
assert.equal(doctor.stderr, '', 'ktx status setup wrote unexpected stderr');
} finally {
await rm(root, { recursive: true, force: true });

2
uv.lock generated
View file

@ -548,6 +548,7 @@ source = { virtual = "." }
dev = [
{ name = "pre-commit" },
{ name = "pytest" },
{ name = "pytest-cov" },
{ name = "ruff" },
]
@ -557,6 +558,7 @@ dev = [
dev = [
{ name = "pre-commit", specifier = ">=4.6.0" },
{ name = "pytest", specifier = ">=9.0.2" },
{ name = "pytest-cov", specifier = ">=7.1.0" },
{ name = "ruff", specifier = ">=0.8.4" },
]