@starci/eslint-canon-fe 8.4.37 → 8.4.39
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
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 8.4.39 - 2026-10-25
|
|
4
|
+
- Changed: the bundled canon pins select @starci/grammar 0.11.0, @starci/hfs 4.7.32 and @starci/cli 1.7.32.
|
|
5
|
+
|
|
6
|
+
## 8.4.38 - 2026-10-24
|
|
7
|
+
- Changed: the bundled runtime copies and canon pins carry the alpha.30 canon (the `zod` pin is `side: both`) and select @starci/hfs 4.7.31 and @starci/cli 1.7.31.
|
|
8
|
+
|
|
3
9
|
## 8.4.37 - 2026-10-24
|
|
4
10
|
- Changed: the bundled canon pins add the multer 2.5.0 security override and select @starci/hfs 4.7.30 and @starci/cli 1.7.30.
|
|
5
11
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@starci/eslint-canon-fe",
|
|
3
|
-
"version": "8.4.
|
|
3
|
+
"version": "8.4.39",
|
|
4
4
|
"description": "The StarCi front-end lint canon: every rule its laws publish, gathered as one flat-config plugin and attached by one factory.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -22,21 +22,21 @@ pins:
|
|
|
22
22
|
source: packages/heroicons/package.json
|
|
23
23
|
why: 'StarCi custom Heroicons-compatible cuts; eslint-canon-fe (icon.mjs) admits @starci/heroicons/24/outline and /16/solid as icon sources, so an app that uses them gets this exact version.'
|
|
24
24
|
'@starci/grammar':
|
|
25
|
-
version: 0.
|
|
25
|
+
version: 0.11.0
|
|
26
26
|
group: starci
|
|
27
27
|
install: registry
|
|
28
28
|
side: fe
|
|
29
29
|
source: packages/grammar/package.json
|
|
30
30
|
why: 'the grammar front ends read: the brand layer sets `--font-sans` and `--font-mono` and the grammar reads them; it carries the Input tel kind, the copyable and read-only Input, the IconButton disclosure props and count badge, ChatBubble, FillViewport, Textarea mentions and Enter-to-send, the leading PrimaryRailLayout rail, the plate-less Image, ListRow, the soft Alert, Progress steps, the floating primary IconButton, FlowGraph, the STATE-8 loading views and the bordered selectable TagGroup chips. The runtime source version wins for a @starci package.'
|
|
31
31
|
'@starci/eslint-canon-be':
|
|
32
|
-
version: 3.4.
|
|
32
|
+
version: 3.4.40
|
|
33
33
|
group: starci
|
|
34
34
|
install: registry
|
|
35
35
|
side: be
|
|
36
36
|
source: packages/eslint/be/package.json
|
|
37
37
|
why: 'the back-end ESLint canon: `loadHfs(import.meta.url)` of be/eslint.config.mjs finds the app-root hfs.json (kind app) and gives every linted file the view of the be side, and the project graph is built per side; its bundled runtime copies (slots, canon-pins, failure codes, the architecture machine) put .starcistacks and .sops.yaml at the app root; `starciBeConfig({ hfs: loadHfs(import.meta.url) })` is the typed factory and the BE-CONVENTION laws are its rules.'
|
|
38
38
|
'@starci/eslint-canon-fe':
|
|
39
|
-
version: 8.4.
|
|
39
|
+
version: 8.4.39
|
|
40
40
|
group: starci
|
|
41
41
|
install: registry
|
|
42
42
|
side: fe
|
|
@@ -76,14 +76,14 @@ pins:
|
|
|
76
76
|
source: packages/test-world/package.json
|
|
77
77
|
why: 'the shared e2e library of every back end (R47, R48), a devDependency of every back end: the warm stack behind toxiproxy, the network-edge fakes, the Nest boot, the typed useTestWorld handle, useSandbox for contract specs and the outage lock. Kafka is real own infra (the one digest-pinned apache/kafka KRaft image, a broker listener and proxy per slot, slot-prefixed topics, consumer groups and client ids) and Postgres is schema-per-context (a schema and a login role per context in a shared database). Each worker has its own data slot (<ns>_w<k>) with its own databases, Keycloak realm, leased Redis DB, bucket/collection/topic prefixes, fakes host, toxiproxy proxies and outage lock; a run provisions min(jest workers, workers cap, default 2) slots, and state file protocol 2 pairs exactly with @starci/jest-preset (TEST_WORLD_PAIR_MISMATCH otherwise). A modules world boots real peer apps beside its modules, world.apps.<name>.during(fn) is the outage of a peer app, w.keycloak.clientSecret(client) answers the run-generated secret of a confidential realm client, world.keycloak.events/sessions read the realm user events and live sessions, world.infra.postgresql.connection(name) takes one database connection down while the others serve, and world.resolve and scope.resolve take any Nest token. Every path a declaration names (`stack`, seeds, the realm, Dockerfiles) resolves from the app root (the directory of hfs.json); the globalSetup registers the path aliases as TypeScript resolves them. Its CLI main is exported at ./cli for starci app stack.'
|
|
78
78
|
'@starci/cli':
|
|
79
|
-
version: 1.7.
|
|
79
|
+
version: 1.7.32
|
|
80
80
|
group: starci
|
|
81
81
|
install: registry
|
|
82
82
|
side: both
|
|
83
83
|
source: packages/cli/package.json
|
|
84
84
|
why: 'the only StarCi command package; product repositories install it for starci app, while @starci/hfs remains its pinned transitive implementation.'
|
|
85
85
|
'@starci/hfs':
|
|
86
|
-
version: 4.7.
|
|
86
|
+
version: 4.7.32
|
|
87
87
|
group: starci
|
|
88
88
|
install: registry
|
|
89
89
|
side: both
|
|
@@ -338,8 +338,8 @@ pins:
|
|
|
338
338
|
'zod':
|
|
339
339
|
version: 4.6.7
|
|
340
340
|
group: framework
|
|
341
|
-
side:
|
|
342
|
-
why: 'the schema library of front-end forms and boundary
|
|
341
|
+
side: both
|
|
342
|
+
why: 'the schema library of front-end forms (fe-stack forms) and, on the back end, of the boundary parsers (R304 and R305: provider responses, model output and queue payloads, never a transport DTO), also an npm override of every app root; 4.6.7 (the registry latest on 2026-10-24) closes GHSA-mrhx-c7xc-m3w5 (high, fixed in 4.6.6), which npm audit --audit-level=high reported against 4.4.3.'
|
|
343
343
|
'@reduxjs/toolkit':
|
|
344
344
|
version: 2.11.2
|
|
345
345
|
group: framework
|
|
@@ -75,7 +75,7 @@ concerns:
|
|
|
75
75
|
home: [fe.hooks.socketio]
|
|
76
76
|
pattern: FE-REALTIME
|
|
77
77
|
forbids: [graphql-ws, subscriptions-transport-ws, '@supabase/realtime-js', pusher-js, ably]
|
|
78
|
-
why: one socket.io-client singleton per namespace and one side-effect component that dispatches to redux and SWR; lite runs the gateway in the be api process.
|
|
78
|
+
why: one socket.io-client singleton per namespace and one side-effect component that dispatches to redux and SWR; lite runs the gateway in the be api process. A one-way channel served as server-sent events needs no package, only a fetch reader in modules/api/sse and a use<Channel>Stream hook (FE-REALTIME).
|
|
79
79
|
- id: auth
|
|
80
80
|
tier: core
|
|
81
81
|
packages: []
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
# catalog READ this file through scripts/hfs/slots.mjs; none of them hardcodes a path.
|
|
8
8
|
# Shape: modules/schemas/hfs-slots.schema.yaml. The repository side is hfs.json: modules/schemas/hfs-repo.schema.yaml.
|
|
9
9
|
schema: starci/hfs-slots@3
|
|
10
|
-
version: 3.
|
|
10
|
+
version: 3.6.0
|
|
11
11
|
|
|
12
12
|
versioning:
|
|
13
13
|
# MAJOR.MINOR.PATCH of this manifest. A repository pins only the MAJOR in hfs.json ("hfs": 3).
|
|
@@ -41,6 +41,8 @@ versioning:
|
|
|
41
41
|
# 3.4.0 is a minor (alpha.25): it ADDS the opt-in be.contract.mcp-tools slot, the committed MCP tool-catalog snapshot of an app.
|
|
42
42
|
# 3.5.0 is a minor (alpha.27): it ADDS the opt-in app.browser-config slot, the managed browser/tsconfig.json that type-checks the browser
|
|
43
43
|
# journey (enabled with app.browser by `browser: true`).
|
|
44
|
+
# 3.6.0 is a minor (alpha.30): it ADDS the opt-in be.feature.realtime.sse slot, the server-sent-events door of the realtime kind (owner decision
|
|
45
|
+
# 2026-10-24: lite may serve SSE, and SSE is the default door for one-way push), and lets fe.modules.api hold the SSE stream readers (sse/).
|
|
44
46
|
|
|
45
47
|
# Field meaning, per slot.
|
|
46
48
|
# id stable name, never changes meaning inside a major.
|
|
@@ -217,7 +219,7 @@ ruleParams:
|
|
|
217
219
|
kafkajs: [platform/event-bus] # pattern event-bus: Kafka is the only event transport
|
|
218
220
|
"@nestjs/schedule": [] # no @Cron / @Interval / @Timeout anywhere: a schedule is a BullMQ job scheduler of a queue
|
|
219
221
|
eventemitter2: []
|
|
220
|
-
setInterval: [platform/retry, platform/event-bus, platform/queue, platform/http]
|
|
222
|
+
setInterval: [platform/retry, platform/event-bus, platform/queue, platform/http, platform/realtime]
|
|
221
223
|
setTimeout: [platform/retry, platform/event-bus, platform/queue, platform/http]
|
|
222
224
|
"node:timers": [platform/retry, platform/event-bus, platform/queue, platform/http]
|
|
223
225
|
"node:timers/promises": [platform/retry, platform/event-bus, platform/queue, platform/http]
|
|
@@ -279,7 +281,7 @@ ruleParams:
|
|
|
279
281
|
# R89 BE_SOURCE_FORM: the closed role-suffix vocabulary of a source file name (<kebab-name>.<suffix>.ts; BE-CONVENTION 1.15)
|
|
280
282
|
# and the suffixes that are never a role. index.ts, main.ts, app.module.ts and the migrations of be.persistence are the
|
|
281
283
|
# only names outside it.
|
|
282
|
-
suffixes: [module, module-definition, decorators, options, config, connection, service, command, query, handler, templates, compensation, saga-state, saga-step, saga, contracts, port, resolver, controller, gateway, webhook, subscription, consumer, cli, event, queue, projection, projection-entity, processor, step, input, type, args, request, response, mapper, policy, entity, sql, rows, error, messages, log-events, cache-keys, guard, interceptor, filter, client, spec, integration-spec, e2e-spec, contract-spec, global-setup, builder]
|
|
284
|
+
suffixes: [module, module-definition, decorators, options, config, connection, service, schema, command, query, handler, templates, compensation, saga-state, saga-step, saga, contracts, port, resolver, controller, gateway, webhook, subscription, consumer, cli, event, queue, projection, projection-entity, processor, step, input, type, args, request, response, mapper, policy, entity, sql, rows, error, messages, log-events, cache-keys, guard, interceptor, filter, client, spec, integration-spec, e2e-spec, contract-spec, global-setup, builder]
|
|
283
285
|
# R47 BE_CONTRACT_UNGUARDED: the world's shape vocabulary. `helper` names the function a contract spec imports to erase the values of a JSON
|
|
284
286
|
# payload (`shapeOf`); a contract spec proves a fake's fixtures by asserting helper(real) equals helper(fixture).
|
|
285
287
|
contractShape: {helper: shapeOf}
|
|
@@ -298,7 +300,7 @@ ruleParams:
|
|
|
298
300
|
# options, config, command, query, contracts, port, event, queue, entity, sql, rows, messages, log-events, error, decorators, cache-keys,
|
|
299
301
|
# projection-entity, connection, and every file with no role: index.ts, main.ts, migrations) is declaration or composition and is never measured.
|
|
300
302
|
# A unit spec beside such a file (`<name>.<role>.spec.ts`) is legal but not required: the file owes 100, not a spec of its own.
|
|
301
|
-
logicRoles: [service, policy, projection, guard, mapper, client, filter, interceptor, processor, step, saga, saga-step, compensation, consumer, webhook]
|
|
303
|
+
logicRoles: [service, schema, policy, projection, guard, mapper, client, filter, interceptor, processor, step, saga, saga-step, compensation, consumer, webhook]
|
|
302
304
|
# R203 BE_FEATURE_THIN. THE roles a feature-tier file is judged thin by: a file `<name>.<role>.ts` of one of these roles inside a slot of tier
|
|
303
305
|
# feature maps parameters and makes ONE delegating call into modules/ (a service, the command or query bus, the event bus, a queue producer): no
|
|
304
306
|
# branch, loop, ternary, try or throw, no computation; orchestration (step order, compensation, claim, fencing, retry) lives in platform/*.
|
|
@@ -1434,9 +1436,9 @@ slots:
|
|
|
1434
1436
|
since: 1.0.0
|
|
1435
1437
|
- id: be.feature.realtime
|
|
1436
1438
|
profiles: [be]
|
|
1437
|
-
editionWhy: "ruling:R212/case-2 (owner:lite-production-swarm) (with the Work boundary amended by ruling:R212/case-4): lite runs socket.io in the api process, one instance without Redis; full may scale its gateway."
|
|
1439
|
+
editionWhy: "ruling:R212/case-2 (owner:lite-production-swarm) (with the Work boundary amended by ruling:R212/case-4) and ruling:R212/case-5 (owner decision 2026-10-24): lite serves server-sent events (the default door for one-way push) or runs socket.io in the api process, one instance without Redis; full may scale its gateway."
|
|
1438
1440
|
path: "src/features/realtime/<channel>/"
|
|
1439
|
-
presence: opt-in # a push channel: reads and pushes only (a socket gateway or a GraphQL subscription), no domain write
|
|
1441
|
+
presence: opt-in # a push channel: reads and pushes only (an SSE controller, a socket gateway or a GraphQL subscription), no domain write
|
|
1440
1442
|
pattern: realtime # declaring the pattern (hfs.json sides.be.patterns) enables the kind (knowledge/patterns/be/realtime.yaml)
|
|
1441
1443
|
trigger: realtime
|
|
1442
1444
|
tracked: tracked
|
|
@@ -1447,9 +1449,9 @@ slots:
|
|
|
1447
1449
|
tests: none
|
|
1448
1450
|
lite:
|
|
1449
1451
|
why: >-
|
|
1450
|
-
a push channel
|
|
1451
|
-
|
|
1452
|
-
(knowledge/patterns/be/realtime.yaml, liteAdapter)
|
|
1452
|
+
a push channel: the server-sent-events door (be.feature.realtime.sse, the default for one-way push, owner decision 2026-10-24)
|
|
1453
|
+
or the same socket.io gateway as full (owner ruling 2026-10-13), both run inside the be api process, one instance and no
|
|
1454
|
+
Redis adapter; the front end listens through a use<Channel>Stream hook over modules/api/sse, or hooks/socketio (knowledge/patterns/be/realtime.yaml, liteAdapter)
|
|
1453
1455
|
coverage: none
|
|
1454
1456
|
rules: [BE_KIND_ISOLATION, BE_FEATURE_IMPORTS_FEATURE, BE_FEATURE_NOT_COMPOSED]
|
|
1455
1457
|
since: 1.0.0
|
|
@@ -1457,14 +1459,14 @@ slots:
|
|
|
1457
1459
|
- {path: packages/hfs/src/hfs-stacks-swarm.spec.mjs, edition: lite}
|
|
1458
1460
|
- id: be.feature.realtime.graphql
|
|
1459
1461
|
profiles: [be]
|
|
1460
|
-
editionWhy: "ruling:R212/case-2 (owner:lite-production-swarm) (with the Work boundary amended by ruling:R212/case-4): lite
|
|
1462
|
+
editionWhy: "ruling:R212/case-2 (owner:lite-production-swarm) (with the Work boundary amended by ruling:R212/case-4): lite pushes through the SSE door or the in-process socket.io gateway; the GraphQL subscription door remains full-only."
|
|
1461
1463
|
path: "src/features/realtime/<channel>/transport/graphql/"
|
|
1462
1464
|
presence: opt-in # a GraphQL subscription over graphql-ws
|
|
1463
|
-
litePresence: forbidden # ruling:R212/case-2 (owner:lite-production-swarm) (with the Work boundary amended by ruling:R212/case-4): lite pushes through the api's in-process socket.io gateway
|
|
1465
|
+
litePresence: forbidden # ruling:R212/case-2 (owner:lite-production-swarm) (with the Work boundary amended by ruling:R212/case-4): lite pushes through the api's SSE door or its in-process socket.io gateway
|
|
1464
1466
|
pattern: realtime
|
|
1465
1467
|
tracked: tracked
|
|
1466
1468
|
tier: feature
|
|
1467
|
-
goesTo: "src/features/realtime/<channel>/transport/
|
|
1469
|
+
goesTo: "src/features/realtime/<channel>/transport/sse/ (be.feature.realtime.sse, the default for one-way push) or transport/websocket/ (be.feature.realtime.websocket): lite runs either door in the api process"
|
|
1468
1470
|
requires: ["<channel>-graphql.module.ts", "<channel>.subscription.ts", "<channel>.subscription.spec.ts"]
|
|
1469
1471
|
allows: ["<channel>-graphql.module.ts", "<channel>-graphql.module-definition.ts", "<channel>-graphql.options.ts", "<channel>.subscription.ts", "<channel>.subscription.spec.ts", dto/]
|
|
1470
1472
|
tests: unit-beside # the door's own spec beside the door (a subscription has no service of its own)
|
|
@@ -1474,14 +1476,14 @@ slots:
|
|
|
1474
1476
|
since: 1.0.0
|
|
1475
1477
|
- id: be.feature.realtime.dto
|
|
1476
1478
|
profiles: [be]
|
|
1477
|
-
editionWhy: "ruling:R212/case-2 (owner:lite-production-swarm) (with the Work boundary amended by ruling:R212/case-4): GraphQL subscription DTOs exist only with the full subscription door; lite uses socket.io contracts."
|
|
1479
|
+
editionWhy: "ruling:R212/case-2 (owner:lite-production-swarm) (with the Work boundary amended by ruling:R212/case-4): GraphQL subscription DTOs exist only with the full subscription door; lite uses SSE or socket.io contracts."
|
|
1478
1480
|
path: "src/features/realtime/<channel>/transport/graphql/dto/"
|
|
1479
1481
|
presence: opt-in
|
|
1480
1482
|
litePresence: forbidden # the dto of the graphql door, which lite does not serve
|
|
1481
1483
|
pattern: realtime
|
|
1482
1484
|
tracked: tracked
|
|
1483
1485
|
tier: feature
|
|
1484
|
-
goesTo: "src/features/realtime/<channel>/transport/
|
|
1486
|
+
goesTo: "src/features/realtime/<channel>/transport/sse/ (be.feature.realtime.sse, the default for one-way push) or transport/websocket/ (be.feature.realtime.websocket): lite runs either door in the api process"
|
|
1485
1487
|
allows: ["<name>.{input,type,args}.ts"]
|
|
1486
1488
|
tests: none
|
|
1487
1489
|
coverage: none
|
|
@@ -1502,6 +1504,22 @@ slots:
|
|
|
1502
1504
|
composedBy: [api]
|
|
1503
1505
|
rules: [BE_REALTIME_SHAPE, BE_REALTIME_WRITES, BE_REALTIME_TOPIC_SCOPE, BE_DEFAULT_DENY]
|
|
1504
1506
|
since: 1.0.0
|
|
1507
|
+
- id: be.feature.realtime.sse
|
|
1508
|
+
since: 3.6.0
|
|
1509
|
+
profiles: [be]
|
|
1510
|
+
path: "src/features/realtime/<channel>/transport/sse/"
|
|
1511
|
+
presence: opt-in # a server-sent-events door: one @Sse method, the default door for one-way push (owner decision 2026-10-24), served in both editions
|
|
1512
|
+
pattern: realtime
|
|
1513
|
+
tracked: tracked
|
|
1514
|
+
tier: feature
|
|
1515
|
+
requires: ["<channel>-sse.module.ts", "<channel>.controller.ts", "<channel>.controller.spec.ts"]
|
|
1516
|
+
allows: ["<channel>-sse.module.ts", "<channel>-sse.module-definition.ts", "<channel>-sse.options.ts", "<channel>.controller.ts", "<channel>.controller.spec.ts"]
|
|
1517
|
+
tests: unit-beside # the door's own spec beside the door (an SSE controller has no service of its own)
|
|
1518
|
+
coverage: none
|
|
1519
|
+
composedBy: [api]
|
|
1520
|
+
rules: [BE_REALTIME_SHAPE, BE_REALTIME_WRITES, BE_REALTIME_TOPIC_SCOPE, BE_DEFAULT_DENY, BE_REST_DOOR_EVIDENCE]
|
|
1521
|
+
exemplifiedBy:
|
|
1522
|
+
- {path: packages/eslint/be/webhooks-realtime-coverage.spec.mjs, editions: [lite, full]}
|
|
1505
1523
|
- id: be.cli
|
|
1506
1524
|
since: 3.1.0
|
|
1507
1525
|
profiles: [be]
|
|
@@ -1552,7 +1570,7 @@ slots:
|
|
|
1552
1570
|
requires: [index.ts]
|
|
1553
1571
|
# <name>.templates.ts holds the capability's static templates, copy and presets as TS constants (owner ruling 2026-10-13);
|
|
1554
1572
|
# user-editable ones are seed rows, large or user media live in object storage.
|
|
1555
|
-
allows: ["<capability>.module.ts", "<capability>.module-definition.ts", "<capability>.config.ts", "<capability>.options.ts", errors/, messages/, persistence/, policies/, "*.service.ts", "*.service.spec.ts", "*.contracts.ts", "*.templates.ts"]
|
|
1573
|
+
allows: ["<capability>.module.ts", "<capability>.module-definition.ts", "<capability>.config.ts", "<capability>.options.ts", errors/, messages/, persistence/, policies/, "*.service.ts", "*.service.spec.ts", "*.contracts.ts", "*.templates.ts", "*.schema.ts", "*.schema.spec.ts"]
|
|
1556
1574
|
forbids: [testing/, exceptions/, utils/, helpers/, shared/]
|
|
1557
1575
|
tests: unit-beside # <name>.service.spec.ts beside each <name>.service.ts, nothing else
|
|
1558
1576
|
coverage: required
|
|
@@ -2254,15 +2272,17 @@ slots:
|
|
|
2254
2272
|
# The browser's calls to the back end (owner ruling 2026-10-13, fe-stack graphql/rest/codegen, FE-API-GRAPHQL): the auth and
|
|
2255
2273
|
# no-auth Apollo clients with their link chain (graphql/clients), one file per operation (graphql/queries/query-<x>.ts,
|
|
2256
2274
|
# graphql/mutations/mutation-<x>.ts with its gql document map and typed request/response in types/), the generated wire types
|
|
2257
|
-
# (graphql/__generated__)
|
|
2275
|
+
# (graphql/__generated__), the axios calls (rest/<area>/*.ts) for uploads, presigned URLs and auth endpoints and the fetch readers of
|
|
2276
|
+
# server-sent-events streams (sse/<area>/*.ts, one file per stream, the bearer token from modules/auth). A repository has
|
|
2258
2277
|
# exactly ONE client folder and ONE GraphQLResponse union: the app's (fe.transport.client/outcome) when one app calls the back end,
|
|
2259
2278
|
# or the api package's (fe.package.api.client/outcome) when several do (FE_TRANSPORT_OWNER, machine).
|
|
2260
2279
|
requires: [index.ts]
|
|
2261
2280
|
allows: [index.ts, graphql/index.ts, graphql/types.ts, "graphql/clients/**", "graphql/queries/query-*.ts", "graphql/queries/types/*.ts",
|
|
2262
|
-
"graphql/mutations/mutation-*.ts", "graphql/mutations/types/*.ts", "graphql/__generated__/**", "rest/index.ts", "rest/<area>/*.ts"
|
|
2281
|
+
"graphql/mutations/mutation-*.ts", "graphql/mutations/types/*.ts", "graphql/__generated__/**", "rest/index.ts", "rest/<area>/*.ts",
|
|
2282
|
+
"sse/index.ts", "sse/<area>/*.ts"]
|
|
2263
2283
|
roles: {entry: index.ts, query: "query-*.ts", mutation: "mutation-*.ts"}
|
|
2264
2284
|
# A hook imports its one operation file directly (one file per operation, FE-API-GRAPHQL), never through a barrel of every operation.
|
|
2265
|
-
entries: ["graphql/queries/query-*.ts", "graphql/queries/types/*.ts", "graphql/mutations/mutation-*.ts", "graphql/mutations/types/*.ts"]
|
|
2285
|
+
entries: ["graphql/queries/query-*.ts", "graphql/queries/types/*.ts", "graphql/mutations/mutation-*.ts", "graphql/mutations/types/*.ts", "sse/<area>/*.ts"]
|
|
2266
2286
|
tests: none
|
|
2267
2287
|
rules: [FE_TRANSPORT_OWNER, FE_HTTP_STATUS_COLLAPSE, FE_WIRE_GENERATED]
|
|
2268
2288
|
- id: fe.transport.generated
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* HFS_UNUSED_EXPORT an export of an owner's public entry that no production file outside the owner imports is dead.
|
|
4
4
|
* HFS_UNUSED_FILE a production source file that no root reaches is dead. Roots: the files an app slot requires
|
|
5
5
|
* (main.ts, app.module.ts), every route file (slot tier `route`), the public entry of every package,
|
|
6
|
+
* and an api app operation table `operations.ts` (the contract emit reads it by path),
|
|
6
7
|
* and a source file a framework config of the app names by a relative string literal
|
|
7
8
|
* (next.config.ts pointing next-intl at its request config). Specs and tests are not in the graph,
|
|
8
9
|
* so a file only a spec imports is dead, on purpose. Type-only imports reach a file.
|
|
@@ -24,7 +25,7 @@
|
|
|
24
25
|
* Specs and tests are not in the graph, so an export used only by a spec is dead, on purpose, with these exceptions (unit test
|
|
25
26
|
* standard): the unit spec of every unit role (ruleParams.be.unitRoles: `<name>.service.spec.ts`, `<name>.cli.spec.ts`) and of every logic role
|
|
26
27
|
* (ruleParams.be.logicRoles: `<name>.policy.spec.ts`, `<name>.client.spec.ts`, ...), a
|
|
27
|
-
* unit spec of a webhook, gateway or
|
|
28
|
+
* unit spec of a webhook, gateway, subscription or SSE controller door (`.webhook.spec.ts`, `.gateway.spec.ts`, `.subscription.spec.ts`, `.controller.spec.ts`: a door has no service of its own), a
|
|
28
29
|
* `*.builder.ts` under src/tests/fixtures/builders, and a file of the test world (slots be.tests.world and be.tests.world.kit, which
|
|
29
30
|
* open and migrate the real databases of the e2e run) read from disk or staged in the git index count as consumers, because a spec can only provide an
|
|
30
31
|
* Inject*() token or a param type the entry exports, and the world wires the same capabilities the apps do. An integration
|
|
@@ -47,6 +48,8 @@ export const DEAD_EXPORT_RULE_IDS = ['HFS_UNUSED_EXPORT', 'HFS_UNUSED_FILE'];
|
|
|
47
48
|
const PACKAGE_ENTRIES = ['src/index.ts', 'src/index.tsx', 'index.ts', 'index.tsx'];
|
|
48
49
|
const OWNER_ENTRIES = ['index.ts', 'index.tsx'];
|
|
49
50
|
const CHAIN_DEPTH = 6;
|
|
51
|
+
/** The file of an api app that the contract emit reads by path for the typed operation table (BE-OPERATIONS-1): no import reaches it, the emit does. */
|
|
52
|
+
const OPERATION_TABLE_FILE = "operations.ts";
|
|
50
53
|
/** Tiers whose files are not production source that an app serves: judged by no dead-file rule. */
|
|
51
54
|
const UNJUDGED_TIERS = new Set(['none', 'e2e', 'fixtures']);
|
|
52
55
|
const CONFIG_EXTENSIONS = ['', '.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '/index.ts', '/index.tsx', '/index.js'];
|
|
@@ -144,7 +147,7 @@ function rootFiles(graph, config) {
|
|
|
144
147
|
if (!node.owner || node.tier !== 'app') continue;
|
|
145
148
|
const slot = graph.resolver.slot(node.owner.slot);
|
|
146
149
|
const inside = rel.slice(withoutSlash(node.owner.root).length + 1);
|
|
147
|
-
if ((slot?.requires ?? []).includes(inside)) roots.add(rel);
|
|
150
|
+
if ((slot?.requires ?? []).includes(inside) || inside === OPERATION_TABLE_FILE) roots.add(rel);
|
|
148
151
|
}
|
|
149
152
|
for (const [key, owner] of graph.ownerRoots) {
|
|
150
153
|
if (owner.tier !== 'package') continue;
|
|
@@ -177,8 +180,8 @@ function deadFiles(graph, config) {
|
|
|
177
180
|
return { violations, judged: judgedFiles.length, roots: roots.size };
|
|
178
181
|
}
|
|
179
182
|
|
|
180
|
-
/** The unit spec of a webhook, gateway or
|
|
181
|
-
const DOOR_SPEC = /^src\/features\/(?:webhooks|realtime)\/.+\.(?:webhook|gateway|subscription)\.spec\.ts$/u;
|
|
183
|
+
/** The unit spec of a webhook, gateway, subscription or SSE controller door: a door has no service of its own, so its spec is the only unit spec of its kind. */
|
|
184
|
+
const DOOR_SPEC = /^src\/features\/(?:webhooks|realtime)\/.+\.(?:webhook|gateway|subscription|controller)\.spec\.ts$/u;
|
|
182
185
|
const BUILDER_CONSUMER = /^src\/tests\/fixtures\/builders\/.+\.builder\.ts$/u;
|
|
183
186
|
/** The test world slots (knowledge/hfs/slots.yaml): their files wire the real capabilities of the e2e run. */
|
|
184
187
|
const WORLD_SLOTS = new Set(['be.tests.world', 'be.tests.world.kit']);
|