@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 ADDED
@@ -0,0 +1,59 @@
1
+ [![github](https://img.shields.io/badge/github-stackables/bridge-blue?logo=github)](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 { Instruction, ToolMap } from "@stackables/bridge-core";
3
+ import type { BridgeDocument, ToolMap } from "@stackables/bridge-core";
4
4
  export type { Logger };
5
5
  export type BridgeOptions = {
6
- /** Tool functions available to the engine.
7
- * Supports namespaced nesting: `{ myNamespace: { myTool } }`.
8
- * The built-in `std` namespace and `httpCall` are always included;
9
- * user tools are merged on top (shallow). */
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
- /** Instructions can be a static array or a function that selects per-request */
28
- export type InstructionSource = Instruction[] | ((context: any) => Instruction[]);
29
- export declare function bridgeTransform(schema: GraphQLSchema, instructions: InstructionSource, options?: BridgeOptions): 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,EAGL,KAAK,MAAM,EACX,KAAK,SAAS,EACd,KAAK,UAAU,EAChB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAGpE,YAAY,EAAE,MAAM,EAAE,CAAC;AAUvB,MAAM,MAAM,aAAa,GAAG;IAC1B;;;kDAG8C;IAC9C,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,gFAAgF;AAChF,MAAM,MAAM,iBAAiB,GACzB,WAAW,EAAE,GACb,CAAC,CAAC,OAAO,EAAE,GAAG,KAAK,WAAW,EAAE,CAAC,CAAC;AAEtC,wBAAgB,eAAe,CAC7B,MAAM,EAAE,aAAa,EACrB,YAAY,EAAE,iBAAiB,EAC/B,OAAO,CAAC,EAAE,aAAa,GACtB,aAAa,CAqHf;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
+ {"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, instructions, options) {
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 activeInstructions = typeof instructions === "function"
37
- ? instructions(context)
38
- : instructions;
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 = activeInstructions.some((i) => i.kind === "bridge" &&
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
- // std is always included; user tools merge on top (shallow)
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, InstructionSource } from "./bridge-transform.ts";
10
+ export type { BridgeOptions, DocumentSource } from "./bridge-transform.ts";
11
11
  //# sourceMappingURL=index.d.ts.map
@@ -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,iBAAiB,EAAE,MAAM,uBAAuB,CAAC"}
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.1",
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": "0.0.1",
26
- "@stackables/bridge-core": "0.0.1"
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"