@starci/eslint-canon-be 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/package.json +1 -1
- package/testing.mjs +23 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.0.1 - 2026-10-01
|
|
4
|
+
|
|
5
|
+
- Fixed: `e2e-asserts-persisted-state` accepts `<world>.db.<connection>` and `<world>.services.<name>.api` state reads, the world identified by its `TestWorld` type (from `@starci/test-world` or the `be.tests.world` slot), not by a variable name.
|
|
6
|
+
|
|
3
7
|
## 2.0.0 - 2026-09-30
|
|
4
8
|
|
|
5
9
|
- Changed (lane PORT): `ruleParams.be.infraOwners` names `@nestjs/cache-manager` (the `CACHE_MANAGER` token) beside `cache-manager`: it is reached only by `integrations/cache` and `integrations/redis`, which is the retired repository rule `must-use-cache-service`; `infra-import-owner` (R90) covers it with a passing and a violating case.
|
package/package.json
CHANGED
package/testing.mjs
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
import { statSync } from "node:fs"
|
|
26
26
|
import { basename, dirname, join } from "node:path"
|
|
27
27
|
import { hfsOf } from "./lib/hfs.mjs"
|
|
28
|
-
import { isPackageType } from "./lib/types.mjs"
|
|
28
|
+
import { isPackageType, typeOrigins } from "./lib/types.mjs"
|
|
29
29
|
import { isServiceSpecFile, isUnitSpecFile, serviceNameOfSpec } from "./lib/unit-spec.mjs"
|
|
30
30
|
|
|
31
31
|
/** The file name of a linted path, in forward-slash form. */
|
|
@@ -172,6 +172,27 @@ const STATE_TYPES = ["EntityManager", "DataSource", "QueryRunner"]
|
|
|
172
172
|
/** Whether an expression is a receiver of persisted state, by the TYPE it has and the package that declares it. */
|
|
173
173
|
const isStateReader = (context, node) => STATE_TYPES.some((name) => isPackageType(context, node, name, "typeorm"))
|
|
174
174
|
|
|
175
|
+
/** The handle `useTestWorld` answers, by where its type is declared: the `@starci/test-world` package or the repository's world slot. */
|
|
176
|
+
const isWorldHandle = (context, node) => {
|
|
177
|
+
const hfs = hfsOf(context)
|
|
178
|
+
return typeOrigins(context, node).some((origin) => origin.name === "TestWorld" && (origin.module === "@starci/test-world" || hfs.slotOf(origin.file) === "be.tests.world"))
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** The name a non-computed member access reads, or null. */
|
|
182
|
+
const propertyNameOf = (node) => (node.type === "MemberExpression" && !node.computed && node.property.type === "Identifier" ? node.property.name : null)
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Whether a member expression is the world's own state read: `<world>.db` (its connections are EntityManagers) or
|
|
186
|
+
* `<world>.services.<name>.api` (a sibling service's own API). The receiver is judged by its type, not its name.
|
|
187
|
+
*/
|
|
188
|
+
const isWorldStateRead = (context, node) => {
|
|
189
|
+
if (propertyNameOf(node) === "db") return isWorldHandle(context, node.object)
|
|
190
|
+
if (propertyNameOf(node) !== "api") return false
|
|
191
|
+
const service = node.object
|
|
192
|
+
const services = service.type === "MemberExpression" ? service.object : null
|
|
193
|
+
return Boolean(services) && propertyNameOf(services) === "services" && isWorldHandle(context, services.object)
|
|
194
|
+
}
|
|
195
|
+
|
|
175
196
|
/** An end-to-end spec that never reads state back proves only that the server replied. */
|
|
176
197
|
export const e2eAssertsPersistedState = {
|
|
177
198
|
meta: {
|
|
@@ -188,7 +209,7 @@ export const e2eAssertsPersistedState = {
|
|
|
188
209
|
let readsState = false
|
|
189
210
|
return {
|
|
190
211
|
MemberExpression(node) {
|
|
191
|
-
if (!readsState && isStateReader(context, node.object)) readsState = true
|
|
212
|
+
if (!readsState && (isStateReader(context, node.object) || isWorldStateRead(context, node))) readsState = true
|
|
192
213
|
},
|
|
193
214
|
CallExpression(node) {
|
|
194
215
|
if (!readsState && node.arguments.some((argument) => argument.type !== "SpreadElement" && isStateReader(context, argument))) readsState = true
|