@descryy/adapter-go 0.4.1 → 0.5.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/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +17 -4
- package/dist/adapter.js.map +1 -1
- package/dist/client-base.d.ts +83 -0
- package/dist/client-base.d.ts.map +1 -0
- package/dist/client-base.js +79 -0
- package/dist/client-base.js.map +1 -0
- package/dist/client.d.ts +26 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +208 -2
- package/dist/client.js.map +1 -1
- package/dist/extract.d.ts.map +1 -1
- package/dist/extract.js +175 -25
- package/dist/extract.js.map +1 -1
- package/dist/gorm.d.ts +81 -0
- package/dist/gorm.d.ts.map +1 -0
- package/dist/gorm.js +140 -0
- package/dist/gorm.js.map +1 -0
- package/dist/parse.d.ts +31 -0
- package/dist/parse.d.ts.map +1 -1
- package/dist/parse.js +124 -14
- package/dist/parse.js.map +1 -1
- package/package.json +4 -4
package/dist/adapter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,EAML,KAAK,eAAe,EAGpB,KAAK,eAAe,
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,EAML,KAAK,eAAe,EAGpB,KAAK,eAAe,EAMrB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAyB,cAAc,EAAwB,MAAM,yBAAyB,CAAC;AAKtG,OAAO,EAAW,QAAQ,EAA4B,MAAM,cAAc,CAAC;AAE3E,eAAO,MAAM,UAAU,eAAe,CAAC;AACvC;;;;;;kCAMkC;AAClC,eAAO,MAAM,eAAe,EAAE,MAErB,CAAC;AACV,eAAO,MAAM,gBAAgB,sBAAuB,CAAC;AAerD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,aAAa,CAAC,EAAE,eAAe,CAAC;CAC1C;AAkBD,MAAM,WAAW,SAAU,SAAQ,eAAe;IAChD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,eAAe,CAAC,OAAO,GAAE,gBAAqB,GAAG,SAAS,CAyNzE;AAED,2DAA2D;AAC3D,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAS7D;AAED,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC"}
|
package/dist/adapter.js
CHANGED
|
@@ -6,7 +6,7 @@ import { createHash } from "node:crypto";
|
|
|
6
6
|
import { createRequire } from "node:module";
|
|
7
7
|
import { existsSync, readFileSync } from "node:fs";
|
|
8
8
|
import { join } from "node:path";
|
|
9
|
-
import { CLIENT_CALL_EXTRACTOR, ROUTE_EXTRACTOR, ROUTE_HANDLER_EXTRACTOR, } from "@descryy/ir";
|
|
9
|
+
import { CLIENT_BASE_EXTRACTOR, CLIENT_CALL_EXTRACTOR, ORM_EXTRACTOR, ROUTE_EXTRACTOR, ROUTE_HANDLER_EXTRACTOR, } from "@descryy/ir";
|
|
10
10
|
import { discover, isolateFile, toRepoRelative } from "@descryy/adapter-common";
|
|
11
11
|
import { parserFor, parseText } from "@descryy/adapter-treesitter";
|
|
12
12
|
import { buildConstraintOf, readFile as readGoFile } from "./parse.js";
|
|
@@ -78,15 +78,16 @@ export function createGoAdapter(options = {}) {
|
|
|
78
78
|
capabilities() {
|
|
79
79
|
return {
|
|
80
80
|
maxResolution: ceiling,
|
|
81
|
-
nodeTypes: ["MODULE", "CLASS", "FUNCTION", "TEST_CASE", "API_ROUTE", "API_ENDPOINT"],
|
|
81
|
+
nodeTypes: ["MODULE", "CLASS", "MODEL", "FUNCTION", "TEST_CASE", "API_ROUTE", "API_ENDPOINT"],
|
|
82
82
|
// `IMPLEMENTS` absent: Go satisfaction is structural, needs R3 this adapter lacks. Embedding becomes `INHERITS`.
|
|
83
|
-
edgeTypes: ["IMPORTS", "CALLS", "TESTS", "INHERITS", "USES_TYPE", "SERVES_API", "USES_API"],
|
|
83
|
+
edgeTypes: ["IMPORTS", "CALLS", "READS", "TESTS", "INHERITS", "USES_TYPE", "SERVES_API", "USES_API"],
|
|
84
84
|
hasCallHierarchy: false,
|
|
85
85
|
hasTypeHierarchy: false,
|
|
86
86
|
// DEC-110: engine no longer hardcodes noise dirs, consumes this instead. Names only, one path component.
|
|
87
87
|
noiseDirectories: ["vendor"],
|
|
88
88
|
frameworkExtractors: [
|
|
89
89
|
"net/http",
|
|
90
|
+
"gorm.io/gorm",
|
|
90
91
|
"github.com/gin-gonic/gin",
|
|
91
92
|
"github.com/go-chi/chi",
|
|
92
93
|
"github.com/labstack/echo",
|
|
@@ -99,7 +100,19 @@ export function createGoAdapter(options = {}) {
|
|
|
99
100
|
// read in the two shapes that name a function — a plain package-level
|
|
100
101
|
// name, and Go's far commoner inline `func(w, r) { … }`, whose single
|
|
101
102
|
// in-repository call is the handler. Every other shape is disclosed.
|
|
102
|
-
|
|
103
|
+
// `client-base-extractor` (DEC-164): declared because it is emitted —
|
|
104
|
+
// every caller this reader reads an HTTP call from carries
|
|
105
|
+
// `attrs.clientBase`, and the splice shape (`client.ts`'s
|
|
106
|
+
// `admitSplice`) composes one per DEC-097 with the origin stripped.
|
|
107
|
+
// `ORM_EXTRACTOR` is `gorm.ts`'s, landed by a different lane in the
|
|
108
|
+
// same session — the union of the two.
|
|
109
|
+
frameworkCapabilities: [
|
|
110
|
+
ROUTE_EXTRACTOR,
|
|
111
|
+
ORM_EXTRACTOR,
|
|
112
|
+
CLIENT_CALL_EXTRACTOR,
|
|
113
|
+
CLIENT_BASE_EXTRACTOR,
|
|
114
|
+
ROUTE_HANDLER_EXTRACTOR,
|
|
115
|
+
],
|
|
103
116
|
};
|
|
104
117
|
},
|
|
105
118
|
async prepare(ctx) {
|
package/dist/adapter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The client-base extractor for Go — DEC-164's contract.
|
|
3
|
+
*
|
|
4
|
+
* Go is a splice-at-the-call-site language and has no choice about it:
|
|
5
|
+
* `net/http.Client` carries no URL prefix of any kind — no `BaseAddress`, no
|
|
6
|
+
* `base_uri`, no `defaultRequest` — so a service base lives in a package
|
|
7
|
+
* constant and is concatenated where the call is written:
|
|
8
|
+
*
|
|
9
|
+
* ```go
|
|
10
|
+
* const apiV1Base = "https://api.acme.example/api/v1"
|
|
11
|
+
* client.Get(apiV1Base + "/orders/" + id)
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* Before this file `client.ts` saw a `binary_expression`, failed the
|
|
15
|
+
* bare-string-literal test and filed a `capability-gap` row reading "a
|
|
16
|
+
* variable, a concatenation, or an expression this reader does not evaluate" —
|
|
17
|
+
* true, and silent about the one thing that was actually unreadable. This
|
|
18
|
+
* reader names it: the first operand of the `+` chain is the base, the rest is
|
|
19
|
+
* the call's own path, and the two are reported separately so a refusal can
|
|
20
|
+
* say which half it refused.
|
|
21
|
+
*
|
|
22
|
+
* ## The origin rule, and why it is evidence rather than a guess
|
|
23
|
+
*
|
|
24
|
+
* An absolute URL written at a call site is refused as out-of-scope (DEC-113),
|
|
25
|
+
* because the origin usually names a host this repository does not serve and
|
|
26
|
+
* DEC-014 makes an endpoint host-free, so a third party's `/v1/charges` and a
|
|
27
|
+
* local route of the same path would collide as one node. That stays, with the
|
|
28
|
+
* one exception `adapter-typescript` and `adapter-python` already adopted:
|
|
29
|
+
* **an origin some base in this same file resolves to is an origin this
|
|
30
|
+
* program treats as its own API.** It admits nothing DEC-097 does not already
|
|
31
|
+
* admit — a resolved base at that origin has already minted endpoints there —
|
|
32
|
+
* and with no absolute base anywhere the origin set is empty and the rule
|
|
33
|
+
* never fires.
|
|
34
|
+
*
|
|
35
|
+
* ## Two disclosed limits, both narrower than the other adapters' rule
|
|
36
|
+
*
|
|
37
|
+
* The constant table and the origin set are both **per file**, not per
|
|
38
|
+
* package. Go's parse pass reads one file at a time and a package-level
|
|
39
|
+
* constant is visible package-wide, so a base declared in a sibling file of the
|
|
40
|
+
* same package stays `unresolved` here. That is a recall gap and never a
|
|
41
|
+
* precision one (rule 2): refusing a base this reader cannot see is the
|
|
42
|
+
* honest answer, and the refusal row says so.
|
|
43
|
+
*/
|
|
44
|
+
/**
|
|
45
|
+
* DEC-164's contract, minus its fourth state — the field's own absence from
|
|
46
|
+
* `attrs`, which is a fact about the adapter rather than a value this type
|
|
47
|
+
* can hold.
|
|
48
|
+
*/
|
|
49
|
+
export type ClientBaseResult = {
|
|
50
|
+
/** A base traced to a literal. `path` is DEC-097's kept prefix, origin already stripped. */
|
|
51
|
+
readonly state: "resolved";
|
|
52
|
+
readonly path: string;
|
|
53
|
+
}
|
|
54
|
+
/** No base-setting mechanism in play. A positive statement, not a default. */
|
|
55
|
+
| {
|
|
56
|
+
readonly state: "none";
|
|
57
|
+
} | {
|
|
58
|
+
/** A base was spliced and its value is not a literal this reader can evaluate. */
|
|
59
|
+
readonly state: "unresolved";
|
|
60
|
+
readonly why: string;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* DEC-097: the origin — scheme, host, port — is removed and the path prefix
|
|
64
|
+
* kept. `undefined` when the value is not an absolute URI this reader can
|
|
65
|
+
* split, which is refused rather than guessed at.
|
|
66
|
+
*
|
|
67
|
+
* Shared verbatim with `adapter-typescript` and `adapter-python` so the three
|
|
68
|
+
* cannot drift; a fourth spelling of this split is how a host reaches an id.
|
|
69
|
+
*/
|
|
70
|
+
export declare function pathPrefixOf(uri: string): string | undefined;
|
|
71
|
+
/** The scheme/host/port of an absolute URI, or `undefined` when it is not one. */
|
|
72
|
+
export declare function originOf(uri: string): string | undefined;
|
|
73
|
+
/**
|
|
74
|
+
* The prefix a base literal contributes, or `undefined` when it contributes
|
|
75
|
+
* none this reader can state.
|
|
76
|
+
*
|
|
77
|
+
* Two shapes resolve: an absolute URI, whose origin is discarded, and a
|
|
78
|
+
* repository-relative path, which is already what it composes to. Anything
|
|
79
|
+
* else — `"api/v1"`, with neither an origin to strip nor a leading slash to
|
|
80
|
+
* anchor it — makes no claim.
|
|
81
|
+
*/
|
|
82
|
+
export declare function prefixOfBaseLiteral(value: string): string | undefined;
|
|
83
|
+
//# sourceMappingURL=client-base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-base.d.ts","sourceRoot":"","sources":["../src/client-base.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GACxB;IACE,4FAA4F;IAC5F,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AACH,8EAA8E;GAC5E;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC1B;IACE,kFAAkF;IAClF,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB,CAAC;AAIN;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAK5D;AAED,kFAAkF;AAClF,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGxD;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGrE"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The client-base extractor for Go — DEC-164's contract.
|
|
3
|
+
*
|
|
4
|
+
* Go is a splice-at-the-call-site language and has no choice about it:
|
|
5
|
+
* `net/http.Client` carries no URL prefix of any kind — no `BaseAddress`, no
|
|
6
|
+
* `base_uri`, no `defaultRequest` — so a service base lives in a package
|
|
7
|
+
* constant and is concatenated where the call is written:
|
|
8
|
+
*
|
|
9
|
+
* ```go
|
|
10
|
+
* const apiV1Base = "https://api.acme.example/api/v1"
|
|
11
|
+
* client.Get(apiV1Base + "/orders/" + id)
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* Before this file `client.ts` saw a `binary_expression`, failed the
|
|
15
|
+
* bare-string-literal test and filed a `capability-gap` row reading "a
|
|
16
|
+
* variable, a concatenation, or an expression this reader does not evaluate" —
|
|
17
|
+
* true, and silent about the one thing that was actually unreadable. This
|
|
18
|
+
* reader names it: the first operand of the `+` chain is the base, the rest is
|
|
19
|
+
* the call's own path, and the two are reported separately so a refusal can
|
|
20
|
+
* say which half it refused.
|
|
21
|
+
*
|
|
22
|
+
* ## The origin rule, and why it is evidence rather than a guess
|
|
23
|
+
*
|
|
24
|
+
* An absolute URL written at a call site is refused as out-of-scope (DEC-113),
|
|
25
|
+
* because the origin usually names a host this repository does not serve and
|
|
26
|
+
* DEC-014 makes an endpoint host-free, so a third party's `/v1/charges` and a
|
|
27
|
+
* local route of the same path would collide as one node. That stays, with the
|
|
28
|
+
* one exception `adapter-typescript` and `adapter-python` already adopted:
|
|
29
|
+
* **an origin some base in this same file resolves to is an origin this
|
|
30
|
+
* program treats as its own API.** It admits nothing DEC-097 does not already
|
|
31
|
+
* admit — a resolved base at that origin has already minted endpoints there —
|
|
32
|
+
* and with no absolute base anywhere the origin set is empty and the rule
|
|
33
|
+
* never fires.
|
|
34
|
+
*
|
|
35
|
+
* ## Two disclosed limits, both narrower than the other adapters' rule
|
|
36
|
+
*
|
|
37
|
+
* The constant table and the origin set are both **per file**, not per
|
|
38
|
+
* package. Go's parse pass reads one file at a time and a package-level
|
|
39
|
+
* constant is visible package-wide, so a base declared in a sibling file of the
|
|
40
|
+
* same package stays `unresolved` here. That is a recall gap and never a
|
|
41
|
+
* precision one (rule 2): refusing a base this reader cannot see is the
|
|
42
|
+
* honest answer, and the refusal row says so.
|
|
43
|
+
*/
|
|
44
|
+
const ABSOLUTE = /^([a-zA-Z][a-zA-Z0-9+.-]*:\/\/[^/?#]*)(\/[^?#]*)?/;
|
|
45
|
+
/**
|
|
46
|
+
* DEC-097: the origin — scheme, host, port — is removed and the path prefix
|
|
47
|
+
* kept. `undefined` when the value is not an absolute URI this reader can
|
|
48
|
+
* split, which is refused rather than guessed at.
|
|
49
|
+
*
|
|
50
|
+
* Shared verbatim with `adapter-typescript` and `adapter-python` so the three
|
|
51
|
+
* cannot drift; a fourth spelling of this split is how a host reaches an id.
|
|
52
|
+
*/
|
|
53
|
+
export function pathPrefixOf(uri) {
|
|
54
|
+
const match = ABSOLUTE.exec(uri.trim());
|
|
55
|
+
if (match === null)
|
|
56
|
+
return undefined;
|
|
57
|
+
const path = match[2] ?? "";
|
|
58
|
+
return path === "/" ? "" : path.replace(/\/+$/, "");
|
|
59
|
+
}
|
|
60
|
+
/** The scheme/host/port of an absolute URI, or `undefined` when it is not one. */
|
|
61
|
+
export function originOf(uri) {
|
|
62
|
+
const match = ABSOLUTE.exec(uri.trim());
|
|
63
|
+
return match === null ? undefined : match[1];
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The prefix a base literal contributes, or `undefined` when it contributes
|
|
67
|
+
* none this reader can state.
|
|
68
|
+
*
|
|
69
|
+
* Two shapes resolve: an absolute URI, whose origin is discarded, and a
|
|
70
|
+
* repository-relative path, which is already what it composes to. Anything
|
|
71
|
+
* else — `"api/v1"`, with neither an origin to strip nor a leading slash to
|
|
72
|
+
* anchor it — makes no claim.
|
|
73
|
+
*/
|
|
74
|
+
export function prefixOfBaseLiteral(value) {
|
|
75
|
+
if (value.startsWith("/"))
|
|
76
|
+
return value.length > 1 ? value.replace(/\/+$/, "") : "";
|
|
77
|
+
return pathPrefixOf(value);
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=client-base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-base.js","sourceRoot":"","sources":["../src/client-base.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAqBH,MAAM,QAAQ,GAAG,mDAAmD,CAAC;AAErE;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IACxC,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IACrC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5B,OAAO,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACtD,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IACxC,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACpF,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC;AAC7B,CAAC"}
|
package/dist/client.d.ts
CHANGED
|
@@ -6,6 +6,10 @@
|
|
|
6
6
|
import type { Node } from "@descryy/adapter-treesitter";
|
|
7
7
|
import { type IdentityScope, type IRNode } from "@descryy/ir";
|
|
8
8
|
import type { GoFile } from "./parse.ts";
|
|
9
|
+
import { type ClientBaseResult } from "./client-base.ts";
|
|
10
|
+
export type { ClientBaseResult };
|
|
11
|
+
/** The origin set before any base has been read. Named so a caller cannot pass `new Set()` by accident and mean something else. */
|
|
12
|
+
export declare const NO_KNOWN_ORIGINS: ReadonlySet<string>;
|
|
9
13
|
export interface GoClientCallSite {
|
|
10
14
|
readonly method: string;
|
|
11
15
|
readonly template: string;
|
|
@@ -13,6 +17,15 @@ export interface GoClientCallSite {
|
|
|
13
17
|
readonly line: number;
|
|
14
18
|
/** `test` when the file is a `_test.go` file, else `production`. */
|
|
15
19
|
readonly callerKind: "test" | "production";
|
|
20
|
+
/** DEC-164's contract — see `client-base.ts`. Every call this reader admits states one. */
|
|
21
|
+
readonly clientBase: ClientBaseResult;
|
|
22
|
+
/**
|
|
23
|
+
* The origin a *resolved* base was written at, before DEC-097 stripped it.
|
|
24
|
+
* Reported out rather than kept internally so the collection pass the
|
|
25
|
+
* origin rule needs is one the caller owns and can see. It is never folded
|
|
26
|
+
* back into `template`.
|
|
27
|
+
*/
|
|
28
|
+
readonly baseOrigin?: string;
|
|
16
29
|
}
|
|
17
30
|
export interface GoClientRefusalSite {
|
|
18
31
|
readonly raw: string;
|
|
@@ -28,6 +41,14 @@ export interface GoClientRefusalSite {
|
|
|
28
41
|
* contract. Present only on the generic fallthrough of `diagnoseArgument`.
|
|
29
42
|
*/
|
|
30
43
|
readonly argumentKind?: "field" | "call" | "concatenation" | "other";
|
|
44
|
+
/** Present only for DEC-164's `unresolved` state — a base was spliced and could not be read. */
|
|
45
|
+
readonly clientBase?: ClientBaseResult;
|
|
46
|
+
/**
|
|
47
|
+
* The call's OWN path, with the unreadable base removed — golden 08b's
|
|
48
|
+
* requirement that a refusal name both halves. Without it the row says a
|
|
49
|
+
* base was unreadable and cannot say which call site it belonged to.
|
|
50
|
+
*/
|
|
51
|
+
readonly callPath?: string;
|
|
31
52
|
}
|
|
32
53
|
export type BaseRefusalClass = "value-unknown" | "varies-per-call" | "capability-gap";
|
|
33
54
|
export interface GoClientCall extends GoClientCallSite {
|
|
@@ -37,7 +58,11 @@ export interface GoClientRefusal extends GoClientRefusalSite {
|
|
|
37
58
|
readonly fromId: string;
|
|
38
59
|
}
|
|
39
60
|
/** Every outbound HTTP call in a function body, ledger row per refusal. `locals` read but never written here. */
|
|
40
|
-
export declare function readGoClientCalls(body: Node, unit: GoFile, locals: ReadonlyMap<string, string | null>, isTest: boolean, parameterNames?: ReadonlySet<string
|
|
61
|
+
export declare function readGoClientCalls(body: Node, unit: GoFile, locals: ReadonlyMap<string, string | null>, isTest: boolean, parameterNames?: ReadonlySet<string>,
|
|
62
|
+
/** DEC-164: this file's package-level string constants, the only base table Go's per-file parse has. */
|
|
63
|
+
packageConsts?: ReadonlyMap<string, string>,
|
|
64
|
+
/** Origins some base in this same file already resolves to — see `client-base.ts`'s header. */
|
|
65
|
+
knownOrigins?: ReadonlySet<string>): {
|
|
41
66
|
readonly calls: readonly GoClientCallSite[];
|
|
42
67
|
readonly refusals: readonly GoClientRefusalSite[];
|
|
43
68
|
};
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAuB,KAAK,aAAa,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAEnF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAuB,KAAK,aAAa,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAEnF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAA+C,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEtG,YAAY,EAAE,gBAAgB,EAAE,CAAC;AAEjC,mIAAmI;AACnI,eAAO,MAAM,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAAa,CAAC;AAyB/D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY,CAAC;IAC3C,2FAA2F;IAC3F,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC;IACtC;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,sFAAsF;IACtF,QAAQ,CAAC,YAAY,EAAE,gBAAgB,GAAG,cAAc,GAAG,SAAS,CAAC;IACrE;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,eAAe,GAAG,OAAO,CAAC;IACrE,gGAAgG;IAChG,QAAQ,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAC;IACvC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAKD,MAAM,MAAM,gBAAgB,GAAG,eAAe,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AAiCtF,MAAM,WAAW,YAAa,SAAQ,gBAAgB;IACpD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,eAAgB,SAAQ,mBAAmB;IAC1D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AA8KD,iHAAiH;AACjH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,EAC1C,MAAM,EAAE,OAAO,EACf,cAAc,GAAE,WAAW,CAAC,MAAM,CAAa;AAC/C,wGAAwG;AACxG,aAAa,GAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAa;AACtD,+FAA+F;AAC/F,YAAY,GAAE,WAAW,CAAC,MAAM,CAAoB,GACnD;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,mBAAmB,EAAE,CAAA;CAAE,CA6MpG;AAED,iHAAiH;AACjH,wBAAgB,WAAW,CACzB,KAAK,EAAE,aAAa,EACpB,IAAI,EAAE,YAAY,EAClB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,GACtC,MAAM,CAaR"}
|
package/dist/client.js
CHANGED
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
* `client.*` only admitted on a resolved `http.Client` type.
|
|
5
5
|
*/
|
|
6
6
|
import { endpointQsp, nodeId } from "@descryy/ir";
|
|
7
|
+
import { originOf, pathPrefixOf, prefixOfBaseLiteral } from "./client-base.js";
|
|
8
|
+
/** The origin set before any base has been read. Named so a caller cannot pass `new Set()` by accident and mean something else. */
|
|
9
|
+
export const NO_KNOWN_ORIGINS = new Set();
|
|
7
10
|
const HTTP_PACKAGE = "net/http";
|
|
8
11
|
/** Convenience methods whose name states the verb, on either the package or a `*Client`. */
|
|
9
12
|
const VERB_METHODS = new Map([
|
|
@@ -70,6 +73,11 @@ function relativePath(value) {
|
|
|
70
73
|
const cut = value.indexOf("?");
|
|
71
74
|
return cut === -1 ? value : value.slice(0, cut);
|
|
72
75
|
}
|
|
76
|
+
/** Everything before the first `?` — the query is stripped before an id is built from a path (DEC-013). */
|
|
77
|
+
function stripQueryOf(value) {
|
|
78
|
+
const cut = value.indexOf("?");
|
|
79
|
+
return cut === -1 ? value : value.slice(0, cut);
|
|
80
|
+
}
|
|
73
81
|
/** A literal that unambiguously names a *different* origin. Copied, not re-derived. */
|
|
74
82
|
function namesAnotherOrigin(value) {
|
|
75
83
|
return /^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(value) || value.startsWith("//");
|
|
@@ -104,18 +112,148 @@ function isHttpClientType(written, unit) {
|
|
|
104
112
|
const name = written.slice(cut + 1);
|
|
105
113
|
return name === "Client" && unit.imports.get(qualifier) === HTTP_PACKAGE;
|
|
106
114
|
}
|
|
115
|
+
// --- DEC-164's splice reader -------------------------------------------------
|
|
116
|
+
//
|
|
117
|
+
// Go's base-carrying shape is `NAME + "/suffix/" + param`. The chain is
|
|
118
|
+
// left-nested, so it is flattened back into source order before anything is
|
|
119
|
+
// read from it.
|
|
120
|
+
/** The operands of a left-nested `+` chain, in source order. `undefined` for anything else. */
|
|
121
|
+
function spliceOperands(node) {
|
|
122
|
+
if (node.type !== "binary_expression")
|
|
123
|
+
return undefined;
|
|
124
|
+
const operator = node.childForFieldName("operator");
|
|
125
|
+
if (operator === null || operator.text !== "+")
|
|
126
|
+
return undefined;
|
|
127
|
+
const left = node.childForFieldName("left");
|
|
128
|
+
const right = node.childForFieldName("right");
|
|
129
|
+
if (left === null || right === null)
|
|
130
|
+
return undefined;
|
|
131
|
+
return [...(spliceOperands(left) ?? [left]), right];
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* `name := expr` / `var name = expr` / `const name = expr` inside one body.
|
|
135
|
+
*
|
|
136
|
+
* Only the expression is kept, not a value: whether it is readable is
|
|
137
|
+
* `baseOf`'s question, and a binding whose RHS is `os.Getenv("X")` has to
|
|
138
|
+
* reach the refusal row as that exact text (DEC-242's `blockedBy`).
|
|
139
|
+
*/
|
|
140
|
+
function localBindings(body) {
|
|
141
|
+
const bound = new Map();
|
|
142
|
+
const pair = (left, right) => {
|
|
143
|
+
if (left === null || right === null)
|
|
144
|
+
return;
|
|
145
|
+
if (left.namedChildCount !== 1 || right.namedChildCount !== 1)
|
|
146
|
+
return;
|
|
147
|
+
const name = left.namedChild(0);
|
|
148
|
+
const value = right.namedChild(0);
|
|
149
|
+
if (name === null || value === null || name.type !== "identifier")
|
|
150
|
+
return;
|
|
151
|
+
// First writer wins: a name reassigned later is one this reader cannot
|
|
152
|
+
// follow, and the first binding is the one it can state honestly.
|
|
153
|
+
if (!bound.has(name.text))
|
|
154
|
+
bound.set(name.text, value);
|
|
155
|
+
};
|
|
156
|
+
const visit = (node) => {
|
|
157
|
+
if (node.type === "short_var_declaration") {
|
|
158
|
+
pair(node.childForFieldName("left"), node.childForFieldName("right"));
|
|
159
|
+
}
|
|
160
|
+
if (node.type === "var_declaration" || node.type === "const_declaration") {
|
|
161
|
+
for (let i = 0; i < node.namedChildCount; i += 1) {
|
|
162
|
+
const spec = node.namedChild(i);
|
|
163
|
+
if (spec === null || (spec.type !== "var_spec" && spec.type !== "const_spec"))
|
|
164
|
+
continue;
|
|
165
|
+
const names = [];
|
|
166
|
+
for (let n = 0; n < spec.namedChildCount; n += 1) {
|
|
167
|
+
const child = spec.namedChild(n);
|
|
168
|
+
if (child !== null && child.type === "identifier")
|
|
169
|
+
names.push(child);
|
|
170
|
+
}
|
|
171
|
+
const values = spec.childForFieldName("value");
|
|
172
|
+
if (names.length !== 1 || values === null || values.namedChildCount !== 1)
|
|
173
|
+
continue;
|
|
174
|
+
const name = names[0];
|
|
175
|
+
const value = values.namedChild(0);
|
|
176
|
+
if (name === undefined || value === null)
|
|
177
|
+
continue;
|
|
178
|
+
if (!bound.has(name.text))
|
|
179
|
+
bound.set(name.text, value);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
for (let i = 0; i < node.namedChildCount; i += 1) {
|
|
183
|
+
const child = node.namedChild(i);
|
|
184
|
+
if (child !== null)
|
|
185
|
+
visit(child);
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
visit(body);
|
|
189
|
+
return bound;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* The base a named head operand resolves to.
|
|
193
|
+
*
|
|
194
|
+
* A *string literal* head is deliberately not a base — `"/orders/" + id` is a
|
|
195
|
+
* path with an interpolated segment, which `adapter-typescript` draws the same
|
|
196
|
+
* line on ("a non-empty head is a path, not a base"). Only a name can carry
|
|
197
|
+
* one, and a name this file does not bind to a literal is `unresolved` rather
|
|
198
|
+
* than a guess.
|
|
199
|
+
*/
|
|
200
|
+
function baseOf(head, locals, packageConsts) {
|
|
201
|
+
const unreadable = (why) => ({ base: { state: "unresolved", why } });
|
|
202
|
+
if (head.type !== "identifier")
|
|
203
|
+
return unreadable(head.text.slice(0, 120));
|
|
204
|
+
const bound = locals.get(head.text);
|
|
205
|
+
const literal = bound === undefined ? packageConsts.get(head.text) : literalOf(bound);
|
|
206
|
+
if (literal === undefined) {
|
|
207
|
+
return unreadable((bound === undefined ? head : bound).text.slice(0, 120));
|
|
208
|
+
}
|
|
209
|
+
const prefix = prefixOfBaseLiteral(literal);
|
|
210
|
+
// A literal that is neither absolute nor repository-relative — `"api/v1"`.
|
|
211
|
+
// Nothing to strip and nothing to anchor it to, so no claim is made and the
|
|
212
|
+
// existing refusal keeps the call.
|
|
213
|
+
if (prefix === undefined)
|
|
214
|
+
return unreadable(literal.slice(0, 120));
|
|
215
|
+
const origin = originOf(literal);
|
|
216
|
+
return { base: { state: "resolved", path: prefix }, ...(origin === undefined ? {} : { origin }) };
|
|
217
|
+
}
|
|
218
|
+
/** The written suffix after the base operand, as a `{param}` template. */
|
|
219
|
+
function suffixOf(operands) {
|
|
220
|
+
let out = "";
|
|
221
|
+
for (const operand of operands.slice(1)) {
|
|
222
|
+
const literal = literalOf(operand);
|
|
223
|
+
out += literal ?? "{param}";
|
|
224
|
+
}
|
|
225
|
+
return out;
|
|
226
|
+
}
|
|
107
227
|
/** Every outbound HTTP call in a function body, ledger row per refusal. `locals` read but never written here. */
|
|
108
|
-
export function readGoClientCalls(body, unit, locals, isTest, parameterNames = new Set()
|
|
228
|
+
export function readGoClientCalls(body, unit, locals, isTest, parameterNames = new Set(),
|
|
229
|
+
/** DEC-164: this file's package-level string constants, the only base table Go's per-file parse has. */
|
|
230
|
+
packageConsts = new Map(),
|
|
231
|
+
/** Origins some base in this same file already resolves to — see `client-base.ts`'s header. */
|
|
232
|
+
knownOrigins = NO_KNOWN_ORIGINS) {
|
|
109
233
|
const calls = [];
|
|
110
234
|
const refusals = [];
|
|
111
235
|
const callerKind = isTest ? "test" : "production";
|
|
236
|
+
const bindings = localBindings(body);
|
|
237
|
+
/** DEC-164's `none`: no base-setting mechanism in play at this call site. */
|
|
238
|
+
const NO_BASE = { state: "none" };
|
|
112
239
|
const admit = (method, verb, rawUrl, line) => {
|
|
113
240
|
const template = relativePath(rawUrl);
|
|
114
241
|
if (template !== undefined) {
|
|
115
|
-
calls.push({ method, verb, template, line, callerKind });
|
|
242
|
+
calls.push({ method, verb, template, line, callerKind, clientBase: NO_BASE });
|
|
116
243
|
return;
|
|
117
244
|
}
|
|
118
245
|
if (namesAnotherOrigin(rawUrl)) {
|
|
246
|
+
// DEC-164's 08c, and the one narrow exception to DEC-113: an origin
|
|
247
|
+
// some base in this same file resolves to is an origin this program
|
|
248
|
+
// treats as its own API, so the path under it is a path in this
|
|
249
|
+
// repository. A bare origin with no path is not an endpoint anything
|
|
250
|
+
// serves and stays out of scope.
|
|
251
|
+
const origin = originOf(rawUrl);
|
|
252
|
+
const under = origin !== undefined && knownOrigins.has(origin) ? pathPrefixOf(stripQueryOf(rawUrl)) : undefined;
|
|
253
|
+
if (under !== undefined && under !== "") {
|
|
254
|
+
calls.push({ method, verb, template: under, line, callerKind, clientBase: NO_BASE });
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
119
257
|
refusals.push({
|
|
120
258
|
raw: `${method}(${rawUrl})`,
|
|
121
259
|
line,
|
|
@@ -133,9 +271,69 @@ export function readGoClientCalls(body, unit, locals, isTest, parameterNames = n
|
|
|
133
271
|
`— or elsewhere, so neither an endpoint nor a scope boundary is claimed.`,
|
|
134
272
|
// Not a per-call value and not a named blocking expression either —
|
|
135
273
|
// this reader just cannot see the base configuration.
|
|
274
|
+
//
|
|
275
|
+
// And NO `clientBase`: this row exists precisely because the reader
|
|
276
|
+
// could not tell whether a base applies, so DEC-164's fourth state —
|
|
277
|
+
// the field's absence — is the only honest one. Writing `none` here
|
|
278
|
+
// would turn "I did not determine this" into "there is none", which is
|
|
279
|
+
// the claim the refusal's own text denies making.
|
|
136
280
|
...CAPABILITY_GAP,
|
|
137
281
|
});
|
|
138
282
|
};
|
|
283
|
+
/**
|
|
284
|
+
* DEC-164: a base spliced in front of the path. Returns `true` when this
|
|
285
|
+
* reader owned the argument — admitted or refused — and `false` when it is
|
|
286
|
+
* not a splice at all and the caller's own rules still apply.
|
|
287
|
+
*/
|
|
288
|
+
const admitSplice = (method, verb, urlArg, line) => {
|
|
289
|
+
const operands = spliceOperands(urlArg);
|
|
290
|
+
const head = operands?.[0];
|
|
291
|
+
// Only a NAME carries a base. A string-literal head is a path with an
|
|
292
|
+
// interpolated segment, which this reader does not own.
|
|
293
|
+
if (operands === undefined || head === undefined || head.type !== "identifier")
|
|
294
|
+
return false;
|
|
295
|
+
const { base, origin } = baseOf(head, bindings, packageConsts);
|
|
296
|
+
const suffix = suffixOf(operands);
|
|
297
|
+
if (base.state === "unresolved") {
|
|
298
|
+
// DEC-164 §2: never guess. No edge, and the row names BOTH halves —
|
|
299
|
+
// the blocking expression and the call's own path.
|
|
300
|
+
refusals.push({
|
|
301
|
+
raw: `${method}(${urlArg.text.slice(0, 120)})`,
|
|
302
|
+
line,
|
|
303
|
+
reason: `an HTTP call whose path splices the base \`${base.why}\` in front of \`${suffix}\`, and that base ` +
|
|
304
|
+
`does not resolve to a string literal this reader can see. DEC-164 refuses rather than guesses ` +
|
|
305
|
+
`what an unreadable base composes to.`,
|
|
306
|
+
...diagnoseArgument(base.why, parameterNames),
|
|
307
|
+
clientBase: base,
|
|
308
|
+
...(suffix.startsWith("/") ? { callPath: suffix } : {}),
|
|
309
|
+
});
|
|
310
|
+
return true;
|
|
311
|
+
}
|
|
312
|
+
if (!suffix.startsWith("/")) {
|
|
313
|
+
// A base this reader read, joined to a suffix that does not start a
|
|
314
|
+
// path. Nothing composes without inventing the separator, so the base
|
|
315
|
+
// is reported and the edge is not.
|
|
316
|
+
refusals.push({
|
|
317
|
+
raw: `${method}(${urlArg.text.slice(0, 120)})`,
|
|
318
|
+
line,
|
|
319
|
+
reason: `an HTTP call whose base this reader resolved to \`${base.path}\` but whose remaining path ` +
|
|
320
|
+
`\`${suffix}\` does not begin at a segment boundary. Joining the two would invent a separator.`,
|
|
321
|
+
...CAPABILITY_GAP,
|
|
322
|
+
clientBase: base,
|
|
323
|
+
});
|
|
324
|
+
return true;
|
|
325
|
+
}
|
|
326
|
+
calls.push({
|
|
327
|
+
method,
|
|
328
|
+
verb,
|
|
329
|
+
template: `${base.path}${suffix}`,
|
|
330
|
+
line,
|
|
331
|
+
callerKind,
|
|
332
|
+
clientBase: base,
|
|
333
|
+
...(origin === undefined ? {} : { baseOrigin: origin }),
|
|
334
|
+
});
|
|
335
|
+
return true;
|
|
336
|
+
};
|
|
139
337
|
const readCall = (call) => {
|
|
140
338
|
const callee = call.childForFieldName("function");
|
|
141
339
|
if (callee === null || callee.type !== "selector_expression")
|
|
@@ -160,6 +358,12 @@ export function readGoClientCalls(body, unit, locals, isTest, parameterNames = n
|
|
|
160
358
|
const urlArg = args?.namedChild(skip + 1) ?? null;
|
|
161
359
|
const verb = verbOf(methodArg, unit);
|
|
162
360
|
const rawUrl = literalOf(urlArg);
|
|
361
|
+
if (verb !== undefined && rawUrl === undefined && urlArg !== null) {
|
|
362
|
+
// DEC-164: a base spliced in front of the path. Owned here or not at
|
|
363
|
+
// all — `admitSplice` returns false for anything that is not one.
|
|
364
|
+
if (admitSplice(`${base.text}.${method}`, verb, urlArg, line))
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
163
367
|
if (verb === undefined || rawUrl === undefined) {
|
|
164
368
|
refusals.push({
|
|
165
369
|
raw: `${base.text}.${method}(...)`,
|
|
@@ -195,6 +399,8 @@ export function readGoClientCalls(body, unit, locals, isTest, parameterNames = n
|
|
|
195
399
|
// `Get`/`Head`/`Post`/`PostForm` all take the URL as their first argument.
|
|
196
400
|
const urlArg = args?.namedChild(0) ?? null;
|
|
197
401
|
const rawUrl = literalOf(urlArg);
|
|
402
|
+
if (rawUrl === undefined && urlArg !== null && admitSplice(`${base.text}.${method}`, verb, urlArg, line))
|
|
403
|
+
return;
|
|
198
404
|
if (rawUrl === undefined) {
|
|
199
405
|
refusals.push({
|
|
200
406
|
raw: `${base.text}.${method}(...)`,
|