Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .changeset/typecheck-covers-the-test-layer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
---

ci(dx): the type-check coverage ratchet now judges the test layer too (#4311). #4324 counted a package covered the moment it declared a `typecheck` script — but 27 of the 48 it waved through `exclude` `**/*.test.ts` from the very `tsconfig.json` that `tsc --noEmit` reads, hiding 568 test files and 1451 errors behind a green check (`@objectstack/spec` alone: 272 files, 902 errors). A new `TESTS_COVERED` invariant fails any package that excludes its own tests without a measured `TEST_DEBT` entry, and the gate now prints both layers so the src figure can never again stand in for the whole. Nine packages that were already clean with tests included had the exclusion dropped outright; nine more graduate out of DEBT after repairing 44 NodeNext imports missing their `.js` extension — a repair that closed 110 errors (most of the "noise" tier was one unresolved import degrading symbols to `any`) and exposed 12 real defects in `service-settings` that those broken imports had been masking. Dev scripts, tests and CI only; releases nothing.
13 changes: 13 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,19 @@ workspace package declares a `typecheck` script or carries a measured DEBT/EXEMP
in `scripts/check-type-check-coverage.mjs`. New packages must arrive covered; a package
that graduates deletes its ledger entry in the same PR.

**Do not `exclude` `*.test.ts` / `*.spec.ts` from a package's `tsconfig.json`.** `tsc
--noEmit` reads that config, so an exclusion there hides the tests from the check the
`typecheck` script advertises — a green gate over source nothing read, which is the
#4311 defect itself. The ratchet's `TESTS_COVERED` invariant fails on any new exclusion;
the packages that already had one carry a measured `TEST_DEBT` entry and graduate by
dropping the exclusion.

One trap worth knowing before you read any of these counts: under `moduleResolution:
NodeNext` a relative import missing its `.js` extension does not resolve, every symbol it
names becomes `any`, and the callbacks over those symbols then report TS7006 "implicitly
any". A pile of TS7006 is usually one broken import upstream, not a package that needs
type annotations — fix the extension first and re-measure.

### Running the dev server

| Scenario | Command | Notes |
Expand Down
2 changes: 1 addition & 1 deletion packages/connectors/connector-slack/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"types": ["node"]
},
"include": ["src/**/*"],
"exclude": ["dist", "node_modules", "**/*.test.ts"]
"exclude": ["dist", "node_modules"]
}
1 change: 1 addition & 0 deletions packages/create-objectstack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
},
"scripts": {
"build": "tsup",
"typecheck": "tsc --noEmit",
"dev": "tsup --watch",
"test": "vitest run"
},
Expand Down
3 changes: 3 additions & 0 deletions packages/create-objectstack/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,8 @@
},
"include": [
"src"
],
"exclude": [
"src/templates"
]
}
1 change: 1 addition & 0 deletions packages/plugins/plugin-approvals/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
},
"scripts": {
"build": "tsup --config ../../../tsup.config.ts",
"typecheck": "tsc --noEmit",
"test": "vitest run --passWithNoTests"
},
"dependencies": {
Expand Down
3 changes: 2 additions & 1 deletion packages/plugins/plugin-approvals/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src",
"types": ["node"]
"types": ["node"],
"lib": ["ES2021"]
},
"include": ["src/**/*"],
"exclude": ["dist", "node_modules", "**/*.test.ts"]
Expand Down
3 changes: 1 addition & 2 deletions packages/plugins/plugin-audit/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
],
"exclude": [
"dist",
"node_modules",
"**/*.test.ts"
"node_modules"
]
}
2 changes: 1 addition & 1 deletion packages/plugins/plugin-email/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"types": ["node"]
},
"include": ["src/**/*"],
"exclude": ["dist", "node_modules", "**/*.test.ts"]
"exclude": ["dist", "node_modules"]
}
3 changes: 1 addition & 2 deletions packages/plugins/plugin-hono-server/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
],
"exclude": [
"node_modules",
"dist",
"**/*.test.ts"
"dist"
]
}
2 changes: 1 addition & 1 deletion packages/plugins/plugin-pinyin-search/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"types": ["node"]
},
"include": ["src/**/*"],
"exclude": ["dist", "node_modules", "**/*.test.ts"]
"exclude": ["dist", "node_modules"]
}
2 changes: 1 addition & 1 deletion packages/plugins/plugin-reports/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"types": ["node"]
},
"include": ["src/**/*"],
"exclude": ["dist", "node_modules", "**/*.test.ts"]
"exclude": ["dist", "node_modules"]
}
2 changes: 1 addition & 1 deletion packages/sdui-parser/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"extends": "../../tsconfig.json",
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "**/*.test.ts"],
"exclude": ["node_modules", "dist"],
"compilerOptions": {
"outDir": "dist",
"rootDir": "src"
Expand Down
1 change: 1 addition & 0 deletions packages/services/service-cache/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
},
"scripts": {
"build": "tsup --config ../../../tsup.config.ts",
"typecheck": "tsc --noEmit",
"test": "vitest run"
},
"dependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
OBSERVABILITY_METRICS_SERVICE,
SEMCONV,
} from '@objectstack/observability';
import { CacheServicePlugin } from './cache-service-plugin';
import { CacheServicePlugin } from './cache-service-plugin.js';

/**
* Verifies the metrics resolution chain wired in PR #3:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { describe, it, expect } from 'vitest';
import { InMemoryMetricsRegistry, SEMCONV } from '@objectstack/observability';
import { MemoryCacheAdapter } from './memory-cache-adapter';
import { MemoryCacheAdapter } from './memory-cache-adapter.js';

describe('MemoryCacheAdapter instrumentation', () => {
it('emits cache_lookups_total{result=hit|miss} on get()', async () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.

import { describe, it, expect } from 'vitest';
import { MemoryCacheAdapter } from './memory-cache-adapter';
import { MemoryCacheAdapter } from './memory-cache-adapter.js';
import type { ICacheService } from '@objectstack/spec/contracts';

describe('MemoryCacheAdapter', () => {
Expand Down
1 change: 1 addition & 0 deletions packages/services/service-i18n/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
},
"scripts": {
"build": "tsup --config ../../../tsup.config.ts",
"typecheck": "tsc --noEmit",
"test": "vitest run"
},
"dependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
import { describe, it, expect, vi } from 'vitest';
import { BaseResponseSchema, envelopeViolations } from '@objectstack/spec/api';
import type { IHttpRequest, IHttpResponse, RouteHandler } from '@objectstack/spec/contracts';
import { I18nServicePlugin } from './i18n-service-plugin';
import { I18nServicePlugin } from './i18n-service-plugin.js';

const BASE = '/api/v1/i18n';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.

import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { FileI18nAdapter } from './file-i18n-adapter';
import { FileI18nAdapter } from './file-i18n-adapter.js';
import type { II18nService } from '@objectstack/spec/contracts';
import * as fs from 'node:fs';
import * as path from 'node:path';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
*/

import { describe, it, expect, vi } from 'vitest';
import { I18nServicePlugin } from './i18n-service-plugin';
import { I18N_ROUTE_LEDGER } from './i18n-route-ledger';
import { I18nServicePlugin } from './i18n-service-plugin.js';
import { I18N_ROUTE_LEDGER } from './i18n-route-ledger.js';

/** Minimal IHttpServer mock that records registrations. */
function createMockServer() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { I18nServicePlugin } from './i18n-service-plugin';
import { I18nServicePlugin } from './i18n-service-plugin.js';
import type { IHttpRequest, IHttpResponse, RouteHandler } from '@objectstack/spec/contracts';

// ---------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions packages/services/service-job/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
},
"scripts": {
"build": "tsup --config ../../../tsup.config.ts",
"typecheck": "tsc --noEmit",
"test": "vitest run"
},
"dependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/services/service-job/src/cron-job-adapter.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.

import { describe, it, expect, afterEach } from 'vitest';
import { CronJobAdapter } from './cron-job-adapter';
import { CronJobAdapter } from './cron-job-adapter.js';

describe('CronJobAdapter', () => {
let adapter: CronJobAdapter;
Expand Down
2 changes: 1 addition & 1 deletion packages/services/service-job/src/db-job-adapter.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.

import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { DbJobAdapter } from './db-job-adapter';
import { DbJobAdapter } from './db-job-adapter.js';

function makeFakeEngine() {
const tables = new Map<string, any[]>();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.

import { describe, it, expect, afterEach } from 'vitest';
import { IntervalJobAdapter } from './interval-job-adapter';
import { IntervalJobAdapter } from './interval-job-adapter.js';
import type { IJobService } from '@objectstack/spec/contracts';

describe('IntervalJobAdapter', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

import { describe, it, expect, vi } from 'vitest';
import { JobServicePlugin } from './job-service-plugin';
import { JobServicePlugin } from './job-service-plugin.js';

function makeFakeEngine() {
const tables = new Map<string, any[]>();
Expand Down
1 change: 1 addition & 0 deletions packages/services/service-messaging/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
},
"scripts": {
"build": "tsup --config ../../../tsup.config.ts",
"typecheck": "tsc --noEmit",
"test": "vitest run"
},
"dependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ function fakeEmail() {
};
}

function channel(getEmail: () => any, data: any, templates: any[] = []) {
function channel(getEmail: () => any, data: any) {
const store = new NotificationTemplateStore({ getData: () => data });
return createEmailChannel({ getEmail, getData: () => data, store: store });
}
Expand Down
1 change: 1 addition & 0 deletions packages/services/service-queue/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
},
"scripts": {
"build": "tsup --config ../../../tsup.config.ts",
"typecheck": "tsc --noEmit",
"test": "vitest run"
},
"dependencies": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.

import { describe, it, expect, beforeEach } from 'vitest';
import { DbQueueAdapter } from './db-queue-adapter';
import { DbQueueAdapter } from './db-queue-adapter.js';

/**
* In-memory engine that mimics objectql's `where:`-based find and
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.

import { describe, it, expect } from 'vitest';
import { MemoryQueueAdapter } from './memory-queue-adapter';
import { MemoryQueueAdapter } from './memory-queue-adapter.js';
import type { IQueueService, QueueMessage } from '@objectstack/spec/contracts';

describe('MemoryQueueAdapter', () => {
Expand Down
1 change: 1 addition & 0 deletions packages/services/service-realtime/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
},
"scripts": {
"build": "tsup --config ../../../tsup.config.ts",
"typecheck": "tsc --noEmit",
"test": "vitest run"
},
"dependencies": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.

import { describe, it, expect } from 'vitest';
import { InMemoryRealtimeAdapter, DEFAULT_MAX_SUBSCRIPTIONS } from './in-memory-realtime-adapter';
import { InMemoryRealtimeAdapter, DEFAULT_MAX_SUBSCRIPTIONS } from './in-memory-realtime-adapter.js';
import type { IRealtimeService, RealtimeEventPayload } from '@objectstack/spec/contracts';

describe('InMemoryRealtimeAdapter', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ import { describe, expect, it, vi } from 'vitest';
import { ApiErrorSchema, BaseResponseSchema, FieldErrorSchema, envelopeViolations } from '@objectstack/spec/api';
import { SettingsNamespacePayloadSchema } from '@objectstack/spec/system';
import type { IHttpServer, IHttpRequest, IHttpResponse, RouteHandler } from '@objectstack/spec/contracts';
import { SettingsService } from './settings-service';
import { registerSettingsRoutes } from './settings-routes';
import { brandingSettingsManifest } from './manifests/branding.manifest';
import { SettingsService } from './settings-service.js';
import { registerSettingsRoutes } from './settings-routes.js';
import { brandingSettingsManifest } from './manifests/branding.manifest.js';

class MockHttp implements IHttpServer {
routes = new Map<string, RouteHandler>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { randomBytes } from 'node:crypto';
import {
LocalCryptoProvider,
InMemoryCryptoProvider,
} from './local-crypto-provider';
} from './local-crypto-provider.js';

const ctx = { namespace: 'mail', key: 'api_key' };

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { describe, it, expect } from 'vitest';
import { SettingsManifestSchema } from '@objectstack/spec/system';
import { aiSettingsManifest, aiTestActionHandler, aiTestEmbedderActionHandler } from './ai.manifest';
import { aiSettingsManifest, aiTestActionHandler, aiTestEmbedderActionHandler } from './ai.manifest.js';

describe('aiSettingsManifest', () => {
it('parses against SettingsManifestSchema', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { describe, it, expect } from 'vitest';
import { SettingsManifestSchema } from '@objectstack/spec/system';
import { authSettingsManifest } from './auth.manifest';
import { authSettingsManifest } from './auth.manifest.js';

describe('authSettingsManifest', () => {
it('parses against SettingsManifestSchema', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { describe, it, expect } from 'vitest';
import { SettingsManifestSchema } from '@objectstack/spec/system';
import { companySettingsManifest } from './company.manifest';
import { companySettingsManifest } from './company.manifest.js';

describe('companySettingsManifest', () => {
it('parses against SettingsManifestSchema', () => {
Expand Down
Loading
Loading