@gate-forge/pack-http 0.7.1 → 0.9.0
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/README.md +70 -0
- package/dist/client-calls.d.ts +26 -0
- package/dist/client-calls.d.ts.map +1 -1
- package/dist/client-calls.js +664 -15
- package/dist/client-calls.js.map +1 -1
- package/dist/detector.d.ts +8 -3
- package/dist/detector.d.ts.map +1 -1
- package/dist/detector.js +34 -3
- package/dist/detector.js.map +1 -1
- package/dist/index.d.ts +12 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -10
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -10,6 +10,12 @@ classification signals** (dogfood remediation phase 4):
|
|
|
10
10
|
Fastify and Hono registrations (import-disambiguated, the pack-auth
|
|
11
11
|
convention), and NestJS `@Controller('accounts')` + `@Get/@Post/@Put/
|
|
12
12
|
@Patch/@Delete/@All('…')` decorators.
|
|
13
|
+
`app`/`server`/`router` are server names by convention; an `api.<verb>()`
|
|
14
|
+
call counts as a registration **only** where the file imports a server
|
|
15
|
+
framework (express/fastify/hono), because that is also how an axios
|
|
16
|
+
instance, a Playwright request context, or an api-client module spells
|
|
17
|
+
its calls — reading those as routes minted server routes out of test
|
|
18
|
+
and client call sites.
|
|
13
19
|
- **Frontend API-client calls** (bounded static dataflow, plan phase 3):
|
|
14
20
|
direct literal `fetch`/Axios, `fetch(url, { method })`, Axios config
|
|
15
21
|
objects and instances, configured client symbols (`apiClient.get`),
|
|
@@ -22,6 +28,17 @@ classification signals** (dogfood remediation phase 4):
|
|
|
22
28
|
disappear and never default to GET. A modeled Axios instance creation
|
|
23
29
|
with a proven literal `baseURL` joins that base into the emitted call
|
|
24
30
|
path (see *Instance baseURL joining* below).
|
|
31
|
+
- **The verb of `fetch(url, options)`** comes from a bounded
|
|
32
|
+
request-options model, never from "the options were not inline": an
|
|
33
|
+
inline object (`method` read with last-writer-wins, so a spread and
|
|
34
|
+
the override after it both participate), a module-scope constant
|
|
35
|
+
naming one, or a call to a scanned function whose body is a single
|
|
36
|
+
`return <expression>` with its first parameter bound to that argument
|
|
37
|
+
(so a forwarder resolves through it). Options that provably carry no
|
|
38
|
+
`method` keep the platform default — GET really is what the call
|
|
39
|
+
sends. Options the model cannot read yield a typed
|
|
40
|
+
`HTTP_METHOD_DYNAMIC` entry and **no call fact**: before, such a call
|
|
41
|
+
was recorded as a GET and joined a route the server never serves.
|
|
25
42
|
|
|
26
43
|
## Client-scan configuration
|
|
27
44
|
|
|
@@ -109,6 +126,59 @@ wrapper's paths fully, or use a builder with `base`). The
|
|
|
109
126
|
`urlBuilders[].base` channel is unchanged: it is configuration-declared,
|
|
110
127
|
so the builder's base is part of the resolved value itself.
|
|
111
128
|
|
|
129
|
+
### Response field reads (bounded, file-local)
|
|
130
|
+
|
|
131
|
+
Every frontend-call fact carries `attributes.responseReads`: the fields
|
|
132
|
+
the call site reads off that call's own response, each with the location
|
|
133
|
+
of the read. It is the frontend half of the dropped-response-field proof
|
|
134
|
+
(a merged frontend read `invoice.dueDate` after the FastAPI model had
|
|
135
|
+
dropped it; every test mocked the response and the screen showed
|
|
136
|
+
nothing), and it is collected by the same bounded pass that resolves the
|
|
137
|
+
call target — no execution, no type checker, no cross-file inference.
|
|
138
|
+
|
|
139
|
+
The model is deliberately small:
|
|
140
|
+
|
|
141
|
+
- the call's own awaited result is followed through `await` and
|
|
142
|
+
parentheses; `<result>.data` is the payload (the axios/kit envelope) and
|
|
143
|
+
`<result>` alone is the envelope, so `res.status`/`res.headers` are not
|
|
144
|
+
fields;
|
|
145
|
+
- a name bound from either of those (`const r = await call`,
|
|
146
|
+
`const { data: d } = await call`, `const d = (await call).data`) is
|
|
147
|
+
followed by name inside the enclosing function-like — nested
|
|
148
|
+
function-likes included, so a `useEffect` callback still counts;
|
|
149
|
+
- `holder.<field>`, `holder.data.<field>`, `holder.data['<field>']` and
|
|
150
|
+
`holder['<field>']` are reads, as is every key of an object
|
|
151
|
+
destructuring of a holder or of `<holder>.data`;
|
|
152
|
+
- a `let` holder (reassigned before the read), a computed key
|
|
153
|
+
(`d[key]`), and a JavaScript member (`data.map`, `data.length`,
|
|
154
|
+
`status`) are never reads;
|
|
155
|
+
- a branch that opens on the call's OWN envelope (`ok`, `status`) is read
|
|
156
|
+
for its POLARITY, and only the failure arm is dropped: the body a
|
|
157
|
+
failure branch reads (`res.data?.detail`) is the server's ERROR
|
|
158
|
+
envelope, never the success model. `if (res.ok)`, `if (res.ok ===
|
|
159
|
+
true)`, `if (res.status >= 400)`, `> 399`, `!== 200`, `!== 201`, `< 400`,
|
|
160
|
+
`=== 200`, `<= 299` and their `!` negations all decide which arm runs,
|
|
161
|
+
so the success arm keeps its reads — `if (res.ok) setItems(res.data.
|
|
162
|
+
items)` is exactly the shape where a dropped field hides. A compound
|
|
163
|
+
condition (`!res.ok || res.status >= 500`), a comparison this pass
|
|
164
|
+
cannot read (`>= Math.min(400, limit)`) and a `statusText` test are
|
|
165
|
+
undecidable, so NEITHER arm is collected. A ternary is the same guard as
|
|
166
|
+
an `if` — `res.ok ? res.data.items : res.data?.detail` keeps the
|
|
167
|
+
success arm — and a ternary on anything else is not a guard at all: both
|
|
168
|
+
arms are ordinary success-path reads. A read after an early-return guard
|
|
169
|
+
(`if (!res.ok) { throw … }` … then the code) is collected as usual;
|
|
170
|
+
- a read that is one operand of a `||` / `??` chain carries that chain's
|
|
171
|
+
index, so the check judges the chain as the ONE decision it is:
|
|
172
|
+
`res.data?.invoice_id || res.data?.invoice?.id` is silent when the
|
|
173
|
+
model declares `invoice_id`, because `invoice` is its defensive
|
|
174
|
+
fallback. A chain in which no operand is declared is reported whole.
|
|
175
|
+
|
|
176
|
+
`gateforge check` compares these reads against the response model the
|
|
177
|
+
joined backend route declares and emits one **non-blocking**
|
|
178
|
+
`RESPONSE_FIELD_MISSING_FROM_MODEL` advisory per undeclared field. A call
|
|
179
|
+
nobody consumes emits no attribute at all, so it stays byte-identical to
|
|
180
|
+
before.
|
|
181
|
+
|
|
112
182
|
### Scan scoping (optional, strict, back-compatible)
|
|
113
183
|
|
|
114
184
|
All scoping keys are OPTIONAL; a config without them scans exactly as
|
package/dist/client-calls.d.ts
CHANGED
|
@@ -147,6 +147,25 @@ export declare function clientSymbolActiveIn(config: ClientScanConfig, name: str
|
|
|
147
147
|
* scope, `<symbol>.<verb>(path, handler)` can only be a router).
|
|
148
148
|
*/
|
|
149
149
|
export declare function activeClientSymbolNamesIn(config: ClientScanConfig, file: string): string[];
|
|
150
|
+
/**
|
|
151
|
+
* One field the call site reads off this call's response: the name
|
|
152
|
+
* exactly as the code writes it, and where that read happens. Collected
|
|
153
|
+
* by the same bounded static pass that resolves the call target —
|
|
154
|
+
* `.data.<field>`, `.data['<field>']`, and destructuring of the awaited
|
|
155
|
+
* result or of its payload, inside the enclosing function, same file.
|
|
156
|
+
*/
|
|
157
|
+
export interface ResponseRead {
|
|
158
|
+
field: string;
|
|
159
|
+
location: Location;
|
|
160
|
+
/**
|
|
161
|
+
* Index of the `||` / `??` fallback chain this operand belongs to, in
|
|
162
|
+
* source order within the call; absent for a read that stands alone.
|
|
163
|
+
* `res.data?.invoice_id || res.data?.invoice?.id` is one decision about
|
|
164
|
+
* ONE result, so its operands are judged together by the response-model
|
|
165
|
+
* check instead of one by one.
|
|
166
|
+
*/
|
|
167
|
+
chain?: number;
|
|
168
|
+
}
|
|
150
169
|
/** One discovered frontend call (one row per source callsite). */
|
|
151
170
|
export interface ClientCall {
|
|
152
171
|
method: HttpMethod;
|
|
@@ -166,6 +185,13 @@ export interface ClientCall {
|
|
|
166
185
|
/** Producing client, e.g. `fetch`, `axios`, `apiClient`, `apiGet`. */
|
|
167
186
|
framework: string;
|
|
168
187
|
location: Location;
|
|
188
|
+
/**
|
|
189
|
+
* Fields this call site reads off the response, in source order.
|
|
190
|
+
* Absent when the code reads none — the attribute is minted only when
|
|
191
|
+
* it says something, so a call with no read stays byte-identical to
|
|
192
|
+
* the pre-feature contract.
|
|
193
|
+
*/
|
|
194
|
+
responseReads?: ResponseRead[];
|
|
169
195
|
}
|
|
170
196
|
export interface ClientScanUnresolved {
|
|
171
197
|
code: typeof FRONTEND_CALL_TARGET_UNRESOLVED | typeof HTTP_METHOD_DYNAMIC | typeof HTTP_PATH_DYNAMIC;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-calls.d.ts","sourceRoot":"","sources":["../src/client-calls.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAKH,OAAO,EACL,+BAA+B,EAC/B,mBAAmB,EACnB,iBAAiB,EAElB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAe,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE9D;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B;;;OAGG;IACH,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B;AAED,4EAA4E;AAC5E,MAAM,WAAW,kBAAmB,SAAQ,mBAAmB;IAC7D,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;CACd;AAED,yEAAyE;AACzE,MAAM,WAAW,qBAAsB,SAAQ,mBAAmB;IAChE,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,MAAM,EAAE,UAAU,CAAC;CACpB;AAED,uEAAuE;AACvE,MAAM,WAAW,gBAAiB,SAAQ,mBAAmB;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,gBAAgB;IAC/B,oEAAoE;IACpE,aAAa,CAAC,EAAE,aAAa,CAAC,MAAM,GAAG,kBAAkB,CAAC,CAAC;IAC3D;;;OAGG;IACH,gBAAgB,CAAC,EAAE,aAAa,CAAC,qBAAqB,CAAC,CAAC;IACxD,oEAAoE;IACpE,WAAW,CAAC,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;IAC9C,yEAAyE;IACzE,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC;;;;OAIG;IACH,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC;;;;OAIG;IACH,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,eAAO,MAAM,0BAA0B,EAAE,gBAAqB,CAAC;AAE/D;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAErF;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAErF;AAoBD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAGlG;AAsCD;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAO1F;
|
|
1
|
+
{"version":3,"file":"client-calls.d.ts","sourceRoot":"","sources":["../src/client-calls.ts"],"names":[],"mappings":"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"}
|