@stackables/bridge-graphql 0.0.1 → 1.0.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 +59 -0
- package/build/bridge-transform.d.ts +16 -8
- package/build/bridge-transform.d.ts.map +1 -1
- package/build/bridge-transform.js +17 -15
- package/build/index.d.ts +1 -1
- package/build/index.d.ts.map +1 -1
- package/package.json +3 -3
package/README.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
[](https://github.com/stackables/bridge)
|
|
2
|
+
|
|
3
|
+
# The Bridge GraphQL adapter
|
|
4
|
+
|
|
5
|
+
The GraphQL adapter for [The Bridge](https://github.com/stackables/bridge) — takes your existing GraphQL schema and wires bridge logic into it. Your `.bridge` files become the resolvers. No boilerplate, no codegen.
|
|
6
|
+
|
|
7
|
+
# Installing
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @stackables/bridge-graphql @stackables/bridge-compiler graphql @graphql-tools/utils
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
`graphql` (≥ 16) and `@graphql-tools/utils` (≥ 11) are peer dependencies.
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { bridgeTransform } from "@stackables/bridge-graphql";
|
|
19
|
+
import { parseBridge } from "@stackables/bridge-compiler";
|
|
20
|
+
import { createSchema, createYoga } from "graphql-yoga";
|
|
21
|
+
import { createServer } from "node:http";
|
|
22
|
+
import { readFileSync } from "node:fs";
|
|
23
|
+
|
|
24
|
+
const typeDefs = readFileSync("schema.graphql", "utf8");
|
|
25
|
+
const bridgeSource = readFileSync("logic.bridge", "utf8");
|
|
26
|
+
|
|
27
|
+
// Parse the bridge file and wire it into the schema
|
|
28
|
+
const schema = bridgeTransform(
|
|
29
|
+
createSchema({ typeDefs }),
|
|
30
|
+
parseBridge(bridgeSource),
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
// That's it — start serving
|
|
34
|
+
const yoga = createYoga({ schema });
|
|
35
|
+
createServer(yoga).listen(4000, () => {
|
|
36
|
+
console.log("http://localhost:4000/graphql");
|
|
37
|
+
});
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Tracing
|
|
41
|
+
|
|
42
|
+
Enable tool-call tracing to see exactly what the engine did during a request:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
const schema = bridgeTransform(createSchema({ typeDefs }), instructions, {
|
|
46
|
+
trace: "basic", // "off" | "basic" | "full"
|
|
47
|
+
logger: console, // plug in pino, winston, or anything with debug/info/warn/error
|
|
48
|
+
});
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Part of the Bridge Ecosystem
|
|
52
|
+
|
|
53
|
+
| Package | What it does |
|
|
54
|
+
| ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------- |
|
|
55
|
+
| [`@stackables/bridge`](https://www.npmjs.com/package/@stackables/bridge) | **The All-in-One** — everything in a single install |
|
|
56
|
+
| [`@stackables/bridge-compiler`](https://www.npmjs.com/package/@stackables/bridge-compiler) | **The Parser** — turns `.bridge` text into instructions |
|
|
57
|
+
| [`@stackables/bridge-core`](https://www.npmjs.com/package/@stackables/bridge-core) | **The Engine** — also supports standalone execution without GraphQL |
|
|
58
|
+
| [`@stackables/bridge-stdlib`](https://www.npmjs.com/package/@stackables/bridge-stdlib) | **The Standard Library** — httpCall, strings, arrays, and more |
|
|
59
|
+
| [`@stackables/bridge-types`](https://www.npmjs.com/package/@stackables/bridge-types) | **Shared Types** — `ToolCallFn`, `ToolMap`, `CacheStore` |
|
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
import { type GraphQLSchema } from "graphql";
|
|
2
2
|
import { type Logger, type ToolTrace, type TraceLevel } from "@stackables/bridge-core";
|
|
3
|
-
import type {
|
|
3
|
+
import type { BridgeDocument, ToolMap } from "@stackables/bridge-core";
|
|
4
4
|
export type { Logger };
|
|
5
5
|
export type BridgeOptions = {
|
|
6
|
-
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
/**
|
|
7
|
+
* Tool functions available to the engine.
|
|
8
|
+
* Supports namespaced nesting: `{ myNamespace: { myTool } }`.
|
|
9
|
+
* The built-in `std` namespace is always included; user tools are
|
|
10
|
+
* merged on top (shallow).
|
|
11
|
+
*
|
|
12
|
+
* To provide a specific version of std (e.g. when bridge files
|
|
13
|
+
* target an older major), use a versioned namespace key:
|
|
14
|
+
* ```ts
|
|
15
|
+
* tools: { "std@1.5": oldStdNamespace }
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
10
18
|
tools?: ToolMap;
|
|
11
19
|
/** Optional function to reshape/restrict the GQL context before it reaches bridge files.
|
|
12
20
|
* By default the full context is exposed via `with context`. */
|
|
@@ -24,9 +32,9 @@ export type BridgeOptions = {
|
|
|
24
32
|
*/
|
|
25
33
|
logger?: Logger;
|
|
26
34
|
};
|
|
27
|
-
/**
|
|
28
|
-
export type
|
|
29
|
-
export declare function bridgeTransform(schema: GraphQLSchema,
|
|
35
|
+
/** Document can be a static BridgeDocument or a function that selects per-request */
|
|
36
|
+
export type DocumentSource = BridgeDocument | ((context: any) => BridgeDocument);
|
|
37
|
+
export declare function bridgeTransform(schema: GraphQLSchema, document: DocumentSource, options?: BridgeOptions): GraphQLSchema;
|
|
30
38
|
/**
|
|
31
39
|
* Read traces that were collected during the current request.
|
|
32
40
|
* Pass the GraphQL context object; returns an empty array when tracing is
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge-transform.d.ts","sourceRoot":"","sources":["../src/bridge-transform.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,aAAa,EAEnB,MAAM,SAAS,CAAC;AACjB,OAAO,
|
|
1
|
+
{"version":3,"file":"bridge-transform.d.ts","sourceRoot":"","sources":["../src/bridge-transform.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,aAAa,EAEnB,MAAM,SAAS,CAAC;AACjB,OAAO,EAKL,KAAK,MAAM,EACX,KAAK,SAAS,EACd,KAAK,UAAU,EAChB,MAAM,yBAAyB,CAAC;AAKjC,OAAO,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAGvE,YAAY,EAAE,MAAM,EAAE,CAAC;AAUvB,MAAM,MAAM,aAAa,GAAG;IAC1B;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;qEACiE;IACjE,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACtD;;;6DAGyD;IACzD,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,qFAAqF;AACrF,MAAM,MAAM,cAAc,GACtB,cAAc,GACd,CAAC,CAAC,OAAO,EAAE,GAAG,KAAK,cAAc,CAAC,CAAC;AAEvC,wBAAgB,eAAe,CAC7B,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,cAAc,EACxB,OAAO,CAAC,EAAE,aAAa,GACtB,aAAa,CAmIf;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,GAAG,GAAG,SAAS,EAAE,CAEzD;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB;wBAER;QAAE,IAAI,EAAE;YAAE,YAAY,EAAE,GAAG,CAAA;SAAE,CAAA;KAAE;8CAK5C;YACD,MAAM,EAAE,GAAG,CAAC;YACZ,SAAS,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;SAC7B;;EAeR"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { MapperKind, mapSchema } from "@graphql-tools/utils";
|
|
2
2
|
import { GraphQLList, GraphQLNonNull, defaultFieldResolver, } from "graphql";
|
|
3
|
-
import { ExecutionTree, TraceCollector, } from "@stackables/bridge-core";
|
|
4
|
-
import { std } from "@stackables/bridge-stdlib";
|
|
3
|
+
import { ExecutionTree, TraceCollector, resolveStd, checkHandleVersions, } from "@stackables/bridge-core";
|
|
4
|
+
import { std as bundledStd, STD_VERSION as BUNDLED_STD_VERSION, } from "@stackables/bridge-stdlib";
|
|
5
5
|
import { SELF_MODULE } from "@stackables/bridge-core";
|
|
6
6
|
const noop = () => { };
|
|
7
7
|
const defaultLogger = {
|
|
@@ -10,8 +10,8 @@ const defaultLogger = {
|
|
|
10
10
|
warn: noop,
|
|
11
11
|
error: noop,
|
|
12
12
|
};
|
|
13
|
-
export function bridgeTransform(schema,
|
|
14
|
-
const userTools = options?.tools;
|
|
13
|
+
export function bridgeTransform(schema, document, options) {
|
|
14
|
+
const userTools = options?.tools ?? {};
|
|
15
15
|
const contextMapper = options?.contextMapper;
|
|
16
16
|
const traceLevel = options?.trace ?? "off";
|
|
17
17
|
const logger = options?.logger ?? defaultLogger;
|
|
@@ -33,13 +33,21 @@ export function bridgeTransform(schema, instructions, options) {
|
|
|
33
33
|
resolve: async function (source, args, context, info) {
|
|
34
34
|
// Start execution tree at query/mutation root
|
|
35
35
|
if (!source && !info.path.prev) {
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
const activeDoc = typeof document === "function" ? document(context) : document;
|
|
37
|
+
// Resolve which std to use: bundled, or a versioned namespace from tools
|
|
38
|
+
const { namespace: activeStd, version: activeStdVersion } = resolveStd(activeDoc.version, bundledStd, BUNDLED_STD_VERSION, userTools);
|
|
39
|
+
// std is always included; user tools merge on top (shallow)
|
|
40
|
+
// internal tools are injected automatically by ExecutionTree
|
|
41
|
+
const allTools = {
|
|
42
|
+
std: activeStd,
|
|
43
|
+
...userTools,
|
|
44
|
+
};
|
|
45
|
+
// Verify all @version-tagged handles can be satisfied
|
|
46
|
+
checkHandleVersions(activeDoc.instructions, allTools, activeStdVersion);
|
|
39
47
|
// Only intercept fields that have a matching bridge instruction.
|
|
40
48
|
// Fields without one fall through to their original resolver,
|
|
41
49
|
// allowing hand-coded resolvers to coexist with bridge-powered ones.
|
|
42
|
-
const hasBridge =
|
|
50
|
+
const hasBridge = activeDoc.instructions.some((i) => i.kind === "bridge" &&
|
|
43
51
|
i.type === typeName &&
|
|
44
52
|
i.field === fieldName);
|
|
45
53
|
if (!hasBridge) {
|
|
@@ -48,13 +56,7 @@ export function bridgeTransform(schema, instructions, options) {
|
|
|
48
56
|
const bridgeContext = contextMapper
|
|
49
57
|
? contextMapper(context)
|
|
50
58
|
: (context ?? {});
|
|
51
|
-
|
|
52
|
-
// internal tools are injected automatically by ExecutionTree
|
|
53
|
-
const allTools = {
|
|
54
|
-
std,
|
|
55
|
-
...(userTools ?? {}),
|
|
56
|
-
};
|
|
57
|
-
source = new ExecutionTree(trunk, activeInstructions, allTools, bridgeContext);
|
|
59
|
+
source = new ExecutionTree(trunk, activeDoc, allTools, bridgeContext);
|
|
58
60
|
source.logger = logger;
|
|
59
61
|
if (traceLevel !== "off") {
|
|
60
62
|
source.tracer = new TraceCollector(traceLevel);
|
package/build/index.d.ts
CHANGED
|
@@ -7,5 +7,5 @@
|
|
|
7
7
|
* Peer dependencies: `graphql`, `@graphql-tools/utils`.
|
|
8
8
|
*/
|
|
9
9
|
export { bridgeTransform, getBridgeTraces, useBridgeTracing, } from "./bridge-transform.ts";
|
|
10
|
-
export type { BridgeOptions,
|
|
10
|
+
export type { BridgeOptions, DocumentSource } from "./bridge-transform.ts";
|
|
11
11
|
//# sourceMappingURL=index.d.ts.map
|
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,eAAe,EACf,eAAe,EACf,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,eAAe,EACf,eAAe,EACf,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stackables/bridge-graphql",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Bridge GraphQL adapter — wire bridges into a GraphQL schema",
|
|
5
5
|
"main": "./build/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
},
|
|
23
23
|
"license": "MIT",
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@stackables/bridge-stdlib": "
|
|
26
|
-
"@stackables/bridge-core": "0.0
|
|
25
|
+
"@stackables/bridge-stdlib": "1.5.0",
|
|
26
|
+
"@stackables/bridge-core": "1.0.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"typescript": "^5.9.3"
|