/** * gRPC server registrations (change: add-contract-graph-projection, protobuf phase). * * A gRPC server is wired up at ONE call that names both the service and its implementation, in * the code the generator emits for every language: * * Go pb.RegisterOrderServiceServer(s, &orderServer{}) * Python orders_pb2_grpc.add_OrderServiceServicer_to_server(OrderServicer(), server) * Node server.addService(proto.orders.v1.OrderService.service, { getOrder, listOrders: list }) * * That call is the literal evidence an `implements_endpoint` edge rests on: the RPC `GetOrder` of * `OrderService` is served by the method `GetOrder` of the type registered for it (Go, Python), or * by the function the implementation map names under that key (Node). No name similarity — a type * that merely looks like a servicer, or a method that merely shares an RPC's name, binds nothing. * * Scanning is a regex pass over source with comments and strings blanked first (`maskNonCode`), * so a registration written in a comment, a docstring or a test fixture's string is not read as * code. Generated stubs are skipped: they DEFINE the registration function, they do not call it. */ export type GrpcRuntime = 'go' | 'python' | 'node'; export interface GrpcRegistration { file: string; line: number; runtime: GrpcRuntime; /** * The service as the registration names it: `OrderService` (Go, Python), or the dotted * expression before `.service` (Node: `proto.orders.v1.OrderService`). */ service: string; /** Go, Python: the implementing type, as written (its last component). */ implType?: string; /** * The package (Go) or module (Python) the type was qualified with — `v2` in `&v2.OrderServer{}`. * Absent when written bare. It decides WHERE the type may be: a bare Go type is in the * registration's own package, a qualified one is not. */ implQualifier?: string; /** * Node: `false` when the first argument is a service object rather than a `.service` * descriptor (`addService(services.GreeterService, …)`, the grpc-tools and ts-proto form). Such a * call is a gRPC registration only if it names a declared service, so an unknown one is dropped * rather than disclosed — `addService` is a common method name. */ descriptor?: false; /** Node: each key of the implementation map, with the function it names (absent = written inline). */ methods?: Array<{ key: string; fn?: string; imported?: true; from?: string; notFollowed?: string; }>; /** * Node, class instance: the module the registration's own file imports `implType` FROM. Absent * means the class is declared in the registration's own file, which is then the only place it * may be. Go and Python use `implQualifier` for the same purpose. */ implFrom?: string; /** Why the implementation is not written literally at the registration (a variable, a factory call). */ notLiteral?: string; } /** * Whether a file is a generated gRPC stub. A stub is never an implementation either: Python's * `*_pb2_grpc.py` declares a client class named exactly like the service, with every RPC as a * method — the name a hand-written servicer usually has too. */ export declare const isGeneratedGrpcStub: (file: string) => boolean; /** 1-based line of an offset, from a precomputed list of line starts. */ export declare function lineAt(starts: readonly number[], offset: number): number; /** * Node: the object literal a bare local name was bound to ONCE, in this same file — the shape * every official grpc-node example uses: * * const serviceImplementation = { bidirectionalStreamingEcho }; * server.addService(echoProto.Echo.service, serviceImplementation); * * The literal is returned so the caller can read it with `nodeImplMap`, exactly as if it had been * written at the call. Returned only when the name's value is beyond doubt from this file's text: * ONE unindented top-level `const`/`let`/`var` binding of the name, no other binding of it * anywhere, no later assignment to the name or to one of its members, no `Object.assign` onto it, * no computed access, no `delete`. Anything else — a name bound in a function, an import, a * conditional reassignment — is a value this cannot read, and stays disclosed. */ export declare function nodeImplObject(text: string, name: string): string | undefined; /** * Node: `new MyHandlers()` / `new ns.MyHandlers(cfg)` — a class INSTANTIATED at the registration, * the one non-literal-map shape whose implementing type is written right there. A variable, a * factory call's result, `this.handlers` or `new Impl().wrap()` name a value, not a type. */ export declare function nodeImplClass(arg: string): { implType: string; implQualifier?: string; } | undefined; /** Node: the keys of an object-literal implementation map, each with the function it names. */ export declare function nodeImplMap(arg: string): Array<{ key: string; fn?: string; base?: string; }> | undefined; /** * The names a JavaScript/TypeScript module binds from imports: `import a, { b, c as d } from`, * `import * as e from`, `const { f, g: h } = require(…)`, `const i = require(…)`. Read on masked * text, with every clause bounded, so a hostile file stays linear. */ export declare function importedNames(text: string): Map; export interface ImportedName { exported: string | null; from: string; } /** A file and the name a function is defined under in it. */ export interface ImportTarget { file: string; name: string; } /** One declared mapping: the pattern as written, and the repository-relative targets it names. */ export interface PathAlias { /** `@app/*`, `#internal/*`, `@/orders` — at most one `*`. */ pattern: string; /** Repository-relative, normalized, each with at most one `*` (the pattern's capture). */ targets: readonly string[]; /** The config that declared it. */ source: string; } /** * The alias mappings a set of config texts declares, keyed by path (`tsconfig.json`, * `packages/api/package.json`, …). A config that cannot be parsed, is over the byte bound, or * states a `paths` value that is not an array of strings contributes nothing — it is never read as * "declares no alias" for the purpose of binding, because an unresolved specifier simply stays * unresolved and disclosed. */ export declare function readPathAliases(configs: ReadonlyMap): PathAlias[]; /** * The extensionless repository path a BARE specifier resolves to through the declared aliases, or * `undefined`. Exactly one pattern must match and name exactly one target — the "exact one * candidate" rule: two patterns matching, or one pattern with a fallback list, leave the specifier * unresolved rather than pick. */ export declare function aliasModuleBase(aliases: readonly PathAlias[], specifier: string): string | undefined; /** * Whether `file` is the module a JS/TS import of `specifier` from `fromFile` names. A RELATIVE * specifier resolves from the importing file (`./orders`, `../db/orders.js`). A bare one resolves * only through `aliases` — the mappings the repository DECLARED in a tsconfig/jsconfig or a * `package.json` `imports` field — and only when exactly one of them names exactly one target. * Without them (no config read, an ambiguous mapping, a real package) the specifier names a module * this check cannot locate, so a same-named function elsewhere is NOT the imported one. */ export declare function isImportedModule(fromFile: string, specifier: string, file: string, aliases?: readonly PathAlias[]): boolean; /** * Whether `file` is the module a Python `from import …` in `fromFile` names: relative * (`.resolvers`, `..api.orders`) from the file's package, or absolute (`app.resolvers`) as a path * suffix. `.py` or `/__init__.py`. */ export declare function isImportedPythonModule(fromFile: string, module: string, file: string): boolean; /** * An import resolver over one set of files: the files (and names) an import of `name` from * `specifier` in `fromFile` can mean — the module the specifier names, and ONE level of re-export * (`export { a as name } from './x'`, `export * from './x'`, a Python package's `__init__.py` doing * `from .x import a as name`). A barrel `index.ts` is the common case; following further would be * guessing at a chain. * * Indexed once: modules are looked up by path stem, and each barrel's re-exports are parsed once, * so the cost is linear in the files and the imports, never their product. */ export declare function createImportResolver(files: readonly string[], contentOf: (file: string) => string | undefined, aliases?: readonly PathAlias[]): (fromFile: string, specifier: string, name: string, runtime: "node" | "python") => ImportTarget[]; /** Every gRPC server registration in one source file. */ export declare function scanGrpcRegistrations(file: string, content: string): GrpcRegistration[]; //# sourceMappingURL=grpc-registration.d.ts.map