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
17 changes: 17 additions & 0 deletions .changeset/date-bucket-parity-call-sites-drop-as-never.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
"@objectstack/driver-turso": patch
---

test(verify): `checkDateBucketParity` / `checkReadCoercion` 的调用点不再 `as never`,替身的编译期检查恢复生效 (#6354)

`@objectstack/verify` 用 `BucketableDriver` / `CoercibleDriver` 两个**结构替身**表达「被测驱动确实具备这组方法」。这是一个**已发布**的契约面——仓外驱动(cloud 的 `driver-turso`)照着它实现自己的一致性测试。但全仓 **10 个**调用点无一例外把驱动 `as never` 之后再传进去,于是这件事**一次也没有被检查过**:替身存在的全部意义,被 100% 的调用点关掉了。

本次逐处删掉这 10 个 cast,一个不留:

- `packages/qa/dogfood/test/date-bucket-parity-conformance.test.ts` **6 处**(真实 `SqlDriver` / `SqliteWasmDriver` 1 处,负向控制的假驱动 5 处)
- `packages/drivers/driver-turso/src/date-bucket-parity.test.ts` **2 处**(`TursoDriver` 本地模式 + 那条 `week` 绊线)
- `packages/qa/dogfood/test/read-coercion-conformance.test.ts` **2 处**(`checkReadCoercion` 同族,同形且同样是死 cast)

**零运行时改动,零新增逃逸口**——只删不加,全程未引入任何 `as any` / `as unknown as` / `@ts-expect-error` / `as never`。三个包 typecheck 全绿:这些 cast 每一个都是死的,替身与真实驱动的形状本来就一致,被抹掉的只是**说出这件事**的能力。

代价原本是休眠的,也正因为休眠才值得修:哪天某个驱动少掉替身要求的一个方法、或替身自身长出新成员,10 个调用点一个都不会红,`checkDateBucketParity` 会在运行期抛 `driver.aggregate is not a function`,而不是在 `tsc` 里被拦下。对仓外驱动作者而言,这个替身是他们唯一能对照的形状说明书,而说明书此前从不校验。
4 changes: 2 additions & 2 deletions packages/drivers/driver-turso/src/date-bucket-parity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ describe('TursoDriver date-bucket parity (framework#3773)', () => {
const driver = new TursoDriver({ url: ':memory:' });
expect(driver.transportMode).toBe('local');

const problems = await checkDateBucketParity(driver as never, {
const problems = await checkDateBucketParity(driver, {
createOptions: { bypassTenantAudit: true },
});
expect(problems).toEqual([]);
Expand Down Expand Up @@ -125,7 +125,7 @@ describe('TursoDriver date-bucket parity (framework#3773)', () => {
configurable: true,
});

const problems = await checkDateBucketParity(driver as never, {
const problems = await checkDateBucketParity(driver, {
createOptions: { bypassTenantAudit: true },
});
expect(problems.join('\n')).toMatch(/advertises this granularity but aggregate\(\) threw/);
Expand Down
12 changes: 6 additions & 6 deletions packages/qa/dogfood/test/date-bucket-parity-conformance.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const DRIVERS = [

describe.each(DRIVERS)('date-bucket parity conformance: $name', ({ make }) => {
it('buckets identically pushed-down and in-memory, on both storage forms', async () => {
const problems = await checkDateBucketParity(make() as never, {
const problems = await checkDateBucketParity(make(), {
createOptions: { bypassTenantAudit: true },
});
expect(problems).toEqual([]);
Expand Down Expand Up @@ -87,7 +87,7 @@ describe('checkDateBucketParity detects a driver whose SQL bucketing is wrong',
}

it('flags every advertised granularity on both columns', async () => {
const problems = await checkDateBucketParity(brokenDriver() as never);
const problems = await checkDateBucketParity(brokenDriver());
// 4 advertised granularities × 2 storage forms = 8 disagreements, and the
// cross-column pass stays quiet because both columns are broken the same way.
expect(problems).toHaveLength(8);
Expand All @@ -102,7 +102,7 @@ describe('checkDateBucketParity detects a driver whose SQL bucketing is wrong',
async aggregate() {
throw new Error("dateGranularity 'month' not supported on dialect");
},
}) as never,
})
);
expect(problems.join('\n')).toMatch(/advertises this granularity but aggregate\(\) threw/);
});
Expand All @@ -124,7 +124,7 @@ describe('checkDateBucketParity detects a driver whose SQL bucketing is wrong',
return [{ at: null, n: 8 }];
},
supports: { queryDateGranularity: { year: true } },
}) as never,
})
);
expect(problems.join('\n')).toMatch(/Field\.datetime 'at' @ year/);
expect(problems.join('\n')).toMatch(
Expand Down Expand Up @@ -153,15 +153,15 @@ describe('checkDateBucketParity detects a driver whose SQL bucketing is wrong',
];
},
supports: { queryDateGranularity: { year: true } },
}) as never,
})
);
expect(problems.join('\n')).toMatch(/pushed-down SQL and in-memory bucketing disagree/);
expect(problems.join('\n')).toContain(sentinel);
});

it('stays quiet on a driver that advertises nothing', async () => {
const problems = await checkDateBucketParity(
brokenDriver({ supports: { queryDateGranularity: {} } }) as never,
brokenDriver({ supports: { queryDateGranularity: {} } })
);
// Nothing advertised ⇒ the engine buckets everything in-memory ⇒ nothing to
// disagree about. A driver is never faulted for declining.
Expand Down
4 changes: 2 additions & 2 deletions packages/qa/dogfood/test/read-coercion-conformance.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const DRIVERS = [

describe.each(DRIVERS)('read-coercion conformance: $name', ({ make }) => {
it('reads a stored row back as its declared types (boolean/json/number)', async () => {
const problems = await checkReadCoercion(make() as never);
const problems = await checkReadCoercion(make());
expect(problems).toEqual([]);
});
});
Expand All @@ -53,7 +53,7 @@ describe('checkReadCoercion detects a non-coercing driver', () => {
return [{ id: '1', name: 'Widget', active: 1, meta: '{"k":1,"arr":[1,2]}', count: '5' }];
},
};
const problems = await checkReadCoercion(raw as never);
const problems = await checkReadCoercion(raw);
expect(problems).toHaveLength(3);
expect(problems.join('\n')).toMatch(/boolean not coerced/);
expect(problems.join('\n')).toMatch(/json not coerced/);
Expand Down
Loading