@commercetools/cli-topic-integration-layer 0.2.2 → 0.3.1

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.
Files changed (33) hide show
  1. package/dist/commands/integration-layer/explore.d.ts +20 -0
  2. package/dist/commands/integration-layer/explore.js +209 -0
  3. package/dist/commands/integration-layer/explore.js.map +1 -0
  4. package/dist/commands/integration-layer/extension/invoke.d.ts +1 -0
  5. package/dist/commands/integration-layer/extension/invoke.js +9 -4
  6. package/dist/commands/integration-layer/extension/invoke.js.map +1 -1
  7. package/dist/commands/integration-layer/extension/serve.d.ts +11 -0
  8. package/dist/commands/integration-layer/extension/serve.js +35 -5
  9. package/dist/commands/integration-layer/extension/serve.js.map +1 -1
  10. package/dist/commands/integration-layer/init.js +11 -4
  11. package/dist/commands/integration-layer/init.js.map +1 -1
  12. package/dist/lib/base.d.ts +35 -0
  13. package/dist/lib/base.js +99 -13
  14. package/dist/lib/base.js.map +1 -1
  15. package/dist/lib/ilClient.d.ts +16 -0
  16. package/dist/lib/ilClient.js +28 -0
  17. package/dist/lib/ilClient.js.map +1 -1
  18. package/dist/lib/tooling/exploreSchema.d.ts +15 -0
  19. package/dist/lib/tooling/exploreSchema.js +77 -0
  20. package/dist/lib/tooling/exploreSchema.js.map +1 -0
  21. package/dist/lib/tooling/explorerPage.d.ts +1 -0
  22. package/dist/lib/tooling/explorerPage.js +96 -0
  23. package/dist/lib/tooling/explorerPage.js.map +1 -0
  24. package/dist/lib/tooling/explorerServer.d.ts +27 -0
  25. package/dist/lib/tooling/explorerServer.js +134 -0
  26. package/dist/lib/tooling/explorerServer.js.map +1 -0
  27. package/dist/lib/tooling/introspectionRequest.d.ts +13 -0
  28. package/dist/lib/tooling/introspectionRequest.js +47 -0
  29. package/dist/lib/tooling/introspectionRequest.js.map +1 -0
  30. package/dist/lib/tooling/session.d.ts +36 -0
  31. package/dist/lib/tooling/session.js +99 -0
  32. package/dist/lib/tooling/session.js.map +1 -0
  33. package/package.json +9 -12
package/dist/lib/base.js CHANGED
@@ -1,16 +1,62 @@
1
1
  // Base class for the topic's commands that reach the integration layer's
2
- // `manage_project` boundary. It extends the host CLI's `AuthCommand`
3
- // (`@commercetools/cli-plugin-auth`), so the bearer is the token
4
- // `commercetools auth login` already persisted to `~/.commercetools/credentials`
5
- // (loaded into the security context by the auth plugin's prerun hook) — no separate
6
- // credential handling, exactly as the `connect` topic does.
2
+ // `manage_project` boundary. The bearer is the token `commercetools auth login`
3
+ // already persisted to `~/.commercetools/credentials`; we read it back from disk
4
+ // here rather than from the auth plugin's in-memory security context — see below.
7
5
  //
8
- // `@commercetools/cli-plugin-auth` is a PEER dependency: at runtime the plugin uses
9
- // the HOST CLI's copy, so the static auth manager/repository the host wires up are
10
- // the same singletons this class reads (a bundled second copy would see an empty
11
- // security context and reject every logged-in caller).
6
+ // `@commercetools/cli-plugin-auth` holds the security context in a MODULE-LEVEL
7
+ // STATIC (`SecurityContextHolder.globalContext`), so there is one context per loaded
8
+ // copy of that module. When this topic is bundled into the host CLI it resolves up
9
+ // into the host's single copy and the static the host fills is the one we read. But
10
+ // when the topic is installed via `oclif plugins install`, it lands in the oclif data
11
+ // dir's own node_modules tree, npm auto-installs the declared `cli-plugin-auth` there,
12
+ // and Node loads that as a SECOND, distinct module instance. `auth login`'s prerun
13
+ // hook (running in the host) fills the HOST copy's static; a read via the inherited
14
+ // `getAuthentication()` would hit the DATA-DIR copy's empty static and reject every
15
+ // logged-in caller ("not logged in"). This is not hypothetical — it is the exact
16
+ // failure mode that a CI symlink-dedupe workaround previously papered over.
17
+ //
18
+ // The cure is to stop depending on cross-copy static identity. `auth login` serializes
19
+ // the full principal (token, region, project key, scope, expiry) to
20
+ // `~/.commercetools/credentials` via the host CLI's `FileBasedAuthenticationRepository`.
21
+ // We reconstruct it from that same file, from THIS module's own copy of the repository
22
+ // — no network, no auth manager, no shared static — so it no longer matters whether one
23
+ // or two copies of `cli-plugin-auth` are loaded. Accordingly `cli-plugin-auth` is a
24
+ // regular `dependency`, not a peer: a second copy is now harmless. The path, auth id
25
+ // (`"client-credentials"`), and serialized shape mirror the host CLI's
26
+ // `providers.ts`/`init.ts` wiring exactly.
27
+ import os from "node:os";
28
+ import path from "node:path";
12
29
  import { Flags } from "@oclif/core";
13
- import { AuthCommand, AuthorizationError, CtpAuthorizedClient, } from "@commercetools/cli-plugin-auth";
30
+ import { AuthCommand, AuthorizationError, CtpAuthorizedClient, CtpClientAuthenticationToken, FileBasedAuthenticationRepository, } from "@commercetools/cli-plugin-auth";
31
+ /**
32
+ * Where `commercetools auth login` persists the serialized principal, and the auth id
33
+ * it files the client-credentials token under. These mirror the host CLI's
34
+ * `providers.ts` (`@commercetools/cli`) — the on-disk credentials contract — verbatim.
35
+ */
36
+ const CREDENTIALS_FILE = path.join(os.homedir(), ".commercetools", "credentials");
37
+ const CLIENT_CREDENTIALS_AUTH_ID = "client-credentials";
38
+ /**
39
+ * A `FileBasedAuthenticationRepository` over the shared credentials file, wired to
40
+ * deserialize the client-credentials principal. Constructed from THIS module's copy of
41
+ * `cli-plugin-auth`, so `loadAuthentication()` reconstructs the principal regardless of
42
+ * how many copies of the auth plugin are loaded (see the header note).
43
+ */
44
+ function persistedAuthenticationRepository(credentialsFile) {
45
+ const repository = new FileBasedAuthenticationRepository(credentialsFile);
46
+ repository.addSerializable(CLIENT_CREDENTIALS_AUTH_ID, CtpClientAuthenticationToken, CtpClientAuthenticationToken.Serializable);
47
+ return repository;
48
+ }
49
+ /**
50
+ * Reconstruct the logged-in principal from the persisted credentials file. Returns
51
+ * undefined when no valid client-credentials login is on disk (absent file, or a
52
+ * different auth kind), so unauthorized commands still run. No network. Exported for
53
+ * tests; commands go through {@link IntegrationLayerCommand.requirePrincipal}.
54
+ */
55
+ export async function loadPersistedPrincipal(credentialsFile = CREDENTIALS_FILE) {
56
+ const authentication = await persistedAuthenticationRepository(credentialsFile).loadAuthentication();
57
+ const principal = authentication?.getPrincipal();
58
+ return principal instanceof CtpAuthorizedClient ? principal : undefined;
59
+ }
14
60
  /**
15
61
  * Derive the integration-layer EXTENSIONS edge base URL from the authenticated
16
62
  * principal's commercetools region. The extensions edge — the connector-backend pod
@@ -30,6 +76,31 @@ export function edgeUrlForRegion(region) {
30
76
  return undefined;
31
77
  return `https://extensions.integration-layer.${trimmed}.commercetools.com`;
32
78
  }
79
+ /**
80
+ * The GRAPHQL edge (the integration-router) for a region — where operations are
81
+ * actually served, at `/{project}/graphql`. A distinct host from the extensions
82
+ * edge above: the extensions edge is the connector backend (manage_project routes),
83
+ * the graphql edge is the router. `--graphql-url` / `IL_GRAPHQL_URL` overrides it
84
+ * for staging zones, which don't follow the production convention.
85
+ */
86
+ export function graphqlEdgeUrlForRegion(region) {
87
+ const trimmed = region.trim();
88
+ if (!trimmed)
89
+ return undefined;
90
+ return `https://graphql.integration-layer.${trimmed}.commercetools.com`;
91
+ }
92
+ /**
93
+ * The IDENTITY edge (the storefront pod) for a region — where sessions are minted,
94
+ * at `POST /{project}/session`. Again a distinct host from both of the above; the
95
+ * four-pod split put shopper identity, shopper GraphQL, and the machine surface on
96
+ * separate ingresses. `--auth-url` / `IL_AUTH_URL` overrides it.
97
+ */
98
+ export function authEdgeUrlForRegion(region) {
99
+ const trimmed = region.trim();
100
+ if (!trimmed)
101
+ return undefined;
102
+ return `https://auth.integration-layer.${trimmed}.commercetools.com`;
103
+ }
33
104
  export class IntegrationLayerCommand extends AuthCommand {
34
105
  /**
35
106
  * Whether the command needs a logged-in principal. True for every command that
@@ -38,6 +109,12 @@ export class IntegrationLayerCommand extends AuthCommand {
38
109
  * to fail loudly if the network path is actually taken.
39
110
  */
40
111
  authorized = true;
112
+ /**
113
+ * The principal loaded from `~/.commercetools/credentials` in {@link init}, or
114
+ * undefined when no valid login is persisted. Resolved once per command run so the
115
+ * synchronous {@link requirePrincipal} call sites (here and in `explore`) are unchanged.
116
+ */
117
+ persistedPrincipal;
41
118
  static baseFlags = {
42
119
  "integration-layer-url": Flags.string({
43
120
  description: "integration-layer extensions edge base URL (also settable via INTEGRATION_LAYER_URL); overrides the URL derived from your login region",
@@ -51,14 +128,23 @@ export class IntegrationLayerCommand extends AuthCommand {
51
128
  };
52
129
  async init() {
53
130
  await super.init();
131
+ this.persistedPrincipal = await this.loadPersistedPrincipal();
54
132
  if (this.authorized)
55
133
  this.requirePrincipal();
56
134
  }
135
+ /**
136
+ * Read the persisted login from `~/.commercetools/credentials`. Returns undefined when
137
+ * no login is on disk (so unauthorized commands like standalone `serve` still run) and
138
+ * only fails loudly when the file is present but malformed. No network — the token was
139
+ * already minted by `auth login` and serialized whole.
140
+ */
141
+ async loadPersistedPrincipal() {
142
+ return loadPersistedPrincipal();
143
+ }
57
144
  /** The logged-in commercetools principal, or an `AuthorizationError` pointing at `auth login`. */
58
145
  requirePrincipal() {
59
- const principal = this.getAuthentication()?.getPrincipal();
60
- if (principal instanceof CtpAuthorizedClient)
61
- return principal;
146
+ if (this.persistedPrincipal)
147
+ return this.persistedPrincipal;
62
148
  throw new AuthorizationError("not logged in — run `commercetools auth login` first");
63
149
  }
64
150
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/lib/base.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,qEAAqE;AACrE,iEAAiE;AACjE,iFAAiF;AACjF,oFAAoF;AACpF,4DAA4D;AAC5D,EAAE;AACF,oFAAoF;AACpF,mFAAmF;AACnF,iFAAiF;AACjF,uDAAuD;AAEvD,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,gCAAgC,CAAC;AAiBxC;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAC/B,OAAO,wCAAwC,OAAO,oBAAoB,CAAC;AAC7E,CAAC;AAED,MAAM,OAAgB,uBAAwB,SAAQ,WAAW;IAC/D;;;;;OAKG;IACO,UAAU,GAAG,IAAI,CAAC;IAE5B,MAAM,CAAU,SAAS,GAAG;QAC1B,uBAAuB,EAAE,KAAK,CAAC,MAAM,CAAC;YACpC,WAAW,EACT,wIAAwI;YAC1I,GAAG,EAAE,uBAAuB;YAC5B,SAAS,EAAE,mBAAmB;SAC/B,CAAC;QACF,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC;YAC1B,WAAW,EAAE,oCAAoC;YACjD,SAAS,EAAE,mBAAmB;SAC/B,CAAC;KACH,CAAC;IAEiB,KAAK,CAAC,IAAI;QAC3B,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,IAAI,IAAI,CAAC,UAAU;YAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC;IAC/C,CAAC;IAED,kGAAkG;IACxF,gBAAgB;QACxB,MAAM,SAAS,GAAG,IAAI,CAAC,iBAAiB,EAAE,EAAE,YAAY,EAAE,CAAC;QAC3D,IAAI,SAAS,YAAY,mBAAmB;YAAE,OAAO,SAAS,CAAC;QAC/D,MAAM,IAAI,kBAAkB,CAAC,sDAAsD,CAAC,CAAC;IACvF,CAAC;IAED;;;;OAIG;IACO,KAAK,CAAC,gBAAgB,CAAC,KAAmB;QAClD,MAAM,SAAS,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,SAAS,CAAC,cAAc,EAAE,CAAC,aAAa,EAAE,CAAC;QAEzD,MAAM,UAAU,GAAG,KAAK,CAAC,aAAa,CAAC,IAAI,SAAS,CAAC,aAAa,EAAE,CAAC;QACrE,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CACb,mGAAmG,CACpG,CAAC;QACJ,CAAC;QAED,MAAM,OAAO,GAAG,KAAK,CAAC,uBAAuB,CAAC,IAAI,gBAAgB,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC,CAAC;QAC1F,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,mFAAmF;gBACjF,wDAAwD;gBACxD,0EAA0E,CAC7E,CAAC;QACJ,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;IACrE,CAAC"}
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/lib/base.ts"],"names":[],"mappings":"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"}
@@ -65,6 +65,22 @@ export interface RemoteValidationResult {
65
65
  }
66
66
  /** GET the project's raw core-subgraph SDL — the compose input (`GET …/subgraph`). */
67
67
  export declare function fetchSubgraphSdl(baseUrl: string, projectKey: string, token: string): Promise<string>;
68
+ /**
69
+ * GET the project's DEPLOYED composed graph as a PUBLIC API SCHEMA — what the router
70
+ * actually plans and serves (core subgraph + the project's published extension),
71
+ * read from Hive by the integration layer and reduced there (`GET …/schema/api`).
72
+ *
73
+ * The integration layer strips the federation machinery before sending, so this is
74
+ * `buildSchema`-able as-is; there is no supergraph to reduce client-side. It is the
75
+ * byte-identical response the Merchant Center console's explorer reads under its
76
+ * own operator JWT — one artifact, two guards.
77
+ *
78
+ * This is the authenticated replacement for introspecting the public edge: the
79
+ * router runs `introspection: false`, so the composed graph is read here, over the
80
+ * same `manage_project` boundary as `/subgraph`. 404 means the project has never
81
+ * published a composable version.
82
+ */
83
+ export declare function fetchDeployedApiSchemaSdl(baseUrl: string, projectKey: string, token: string): Promise<string>;
68
84
  /** POST a candidate SDL to the composition + breaking-change gate (`POST …/extension/validate`). */
69
85
  export declare function remoteValidate(baseUrl: string, projectKey: string, token: string, typeDefs: string): Promise<RemoteValidationResult>;
70
86
  /**
@@ -22,6 +22,34 @@ export async function fetchSubgraphSdl(baseUrl, projectKey, token) {
22
22
  }
23
23
  return text;
24
24
  }
25
+ /**
26
+ * GET the project's DEPLOYED composed graph as a PUBLIC API SCHEMA — what the router
27
+ * actually plans and serves (core subgraph + the project's published extension),
28
+ * read from Hive by the integration layer and reduced there (`GET …/schema/api`).
29
+ *
30
+ * The integration layer strips the federation machinery before sending, so this is
31
+ * `buildSchema`-able as-is; there is no supergraph to reduce client-side. It is the
32
+ * byte-identical response the Merchant Center console's explorer reads under its
33
+ * own operator JWT — one artifact, two guards.
34
+ *
35
+ * This is the authenticated replacement for introspecting the public edge: the
36
+ * router runs `introspection: false`, so the composed graph is read here, over the
37
+ * same `manage_project` boundary as `/subgraph`. 404 means the project has never
38
+ * published a composable version.
39
+ */
40
+ export async function fetchDeployedApiSchemaSdl(baseUrl, projectKey, token) {
41
+ const url = `${apiRoot(baseUrl, projectKey)}/schema/api`;
42
+ const res = await fetch(url, { headers: { accept: "text/plain", ...bearer(token) } });
43
+ const text = await res.text();
44
+ if (res.status === 404) {
45
+ throw new Error(`project '${projectKey}' has no composed schema published yet — publish one from the ` +
46
+ `Merchant Center console (Schema → Refresh schema), or drop --deployed to compose locally`);
47
+ }
48
+ if (!res.ok) {
49
+ throw new Error(`could not fetch the deployed composed schema (${res.status}) from ${url}: ${text}`);
50
+ }
51
+ return text;
52
+ }
25
53
  /** POST a candidate SDL to the composition + breaking-change gate (`POST …/extension/validate`). */
26
54
  export async function remoteValidate(baseUrl, projectKey, token, typeDefs) {
27
55
  const url = `${apiRoot(baseUrl, projectKey)}/extension/validate`;
@@ -1 +1 @@
1
- {"version":3,"file":"ilClient.js","sourceRoot":"","sources":["../../src/lib/ilClient.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ilClient.js","sourceRoot":"","sources":["../../src/lib/ilClient.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,oFAAoF;AACpF,uFAAuF;AACvF,+EAA+E;AAC/E,kEAAkE;AAClE,sFAAsF;AACtF,oFAAoF;AACpF,kEAAkE;AAwElE,SAAS,OAAO,CAAC,OAAe,EAAE,UAAkB;IAClD,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,kBAAkB,CAAC,UAAU,CAAC,EAAE,CAAC;AAC5E,CAAC;AAED,SAAS,MAAM,CAAC,KAAa;IAC3B,OAAO,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE,CAAC;AAC9C,CAAC;AAED,sFAAsF;AACtF,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAe,EACf,UAAkB,EAClB,KAAa;IAEb,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,WAAW,CAAC;IACvD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;IACtF,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,sCAAsC,GAAG,CAAC,MAAM,UAAU,GAAG,KAAK,IAAI,EAAE,CAAC,CAAC;IAC5F,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,OAAe,EACf,UAAkB,EAClB,KAAa;IAEb,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,aAAa,CAAC;IACzD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;IACtF,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CACb,YAAY,UAAU,gEAAgE;YACpF,0FAA0F,CAC7F,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,iDAAiD,GAAG,CAAC,MAAM,UAAU,GAAG,KAAK,IAAI,EAAE,CAAC,CAAC;IACvG,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,oGAAoG;AACpG,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAe,EACf,UAAkB,EAClB,KAAa,EACb,QAAgB;IAEhB,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,qBAAqB,CAAC;IACjE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE;QACjE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;KACnC,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,qCAAqC,GAAG,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC,CAAC;IAC/E,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAA2B,CAAC;AACpD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,OAAe,EACf,UAAkB,EAClB,KAAa,EACb,MAAc,EACd,QAAgB,EAChB,cAAuB;IAEvB,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,mBAAmB,CAAC;IAC/D,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,MAAM,EAAE,KAAK;QACb,OAAO,EAAE;YACP,cAAc,EAAE,iBAAiB;YACjC,4EAA4E;YAC5E,mEAAmE;YACnE,sBAAsB,EAAE,kBAAkB,CAAC,QAAQ,CAAC;YACpD,+EAA+E;YAC/E,+EAA+E;YAC/E,0DAA0D;YAC1D,GAAG,CAAC,cAAc;gBAChB,CAAC,CAAC,EAAE,6BAA6B,EAAE,kBAAkB,CAAC,cAAc,CAAC,EAAE;gBACvE,CAAC,CAAC,EAAE,CAAC;YACP,GAAG,MAAM,CAAC,KAAK,CAAC;SACjB;QACD,IAAI,EAAE,MAAM;KACb,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,gCAAgC,GAAG,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAkB,CAAC;AAC3C,CAAC;AAED,+FAA+F;AAC/F,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,OAAe,EACf,UAAkB,EAClB,KAAa;IAEb,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,wBAAwB,CAAC;IACpE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;IAC5F,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG;QAAE,OAAO,IAAI,CAAC;IACpC,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,qCAAqC,GAAG,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC,CAAC;IAC/E,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAkB,CAAC;AAC3C,CAAC;AAED,yFAAyF;AACzF,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,OAAe,EACf,UAAkB,EAClB,KAAa;IAEb,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,qBAAqB,CAAC;IACjE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;IAClF,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,qCAAqC,GAAG,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC,CAAC;IAC/E,CAAC;AACH,CAAC;AAED,sGAAsG;AACtG,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,OAAe,EACf,UAAkB,EAClB,KAAa;IAEb,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,mBAAmB,CAAC;IAC/D,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;IAC5F,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,gCAAgC,GAAG,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAkB,CAAC;AAC3C,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,OAAe,EACf,UAAkB,EAClB,KAAa,EACb,OAAuE;IAEvE,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,mBAAmB,CAAC;IAC/D,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,MAAM,EAAE,OAAO;QACf,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE;QACjE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;KAC9B,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,kCAAkC,GAAG,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAkB,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { type GraphQLSchema } from "graphql";
2
+ /** A resolved explorer schema plus how it was obtained (for the startup banner). */
3
+ export interface ExplorerSchema {
4
+ schema: GraphQLSchema;
5
+ sdl: string;
6
+ /** e.g. `local compose (core + your extension)` or `deployed (Hive)`. */
7
+ describe: string;
8
+ }
9
+ /**
10
+ * The local-composition path: the project's core subgraph, plus `extensionSdl` when
11
+ * the caller found a local extension to build. Throws with the composition errors
12
+ * when the two don't compose — the same failure `extension validate` reports, and a
13
+ * real answer rather than a half-rendered explorer.
14
+ */
15
+ export declare function composeLocalExplorerSchema(coreSdl: string, extensionSdl: string | undefined): ExplorerSchema;
@@ -0,0 +1,77 @@
1
+ // The schema the local explorer renders — resolved one of two ways.
2
+ //
3
+ // default compose locally: the project's core-subgraph SDL (GET /subgraph)
4
+ // plus, when the working directory holds one, your LOCAL extension.
5
+ // Fast inner loop: edit the extension, restart, see your fields.
6
+ //
7
+ // --deployed the project's DEPLOYED composed graph (GET /schema/api), read from
8
+ // Hive by the integration layer and reduced THERE to a public API
9
+ // schema — exactly what the router plans and serves, including
10
+ // whichever extension is actually deployed. The command just
11
+ // buildSchema()s it, so nothing in this module handles that path.
12
+ //
13
+ // Only the LOCAL path composes, which is why this module exists at all: a supergraph
14
+ // can't be composed on the server for a working-tree extension that was never pushed.
15
+ // Both paths end at a client-facing `GraphQLSchema`, which the explorer serves to
16
+ // GraphiQL (answering introspection locally). Execution is proxied to the real edge
17
+ // either way — this schema drives the docs pane, autocomplete, and validation only.
18
+ import { printSchema } from "graphql";
19
+ import { composeServices } from "@apollo/composition";
20
+ import { parse } from "graphql";
21
+ import { composeWithIntegrationLayer, INTEGRATION_LAYER_SERVICE, } from "./compose.js";
22
+ /** Placeholder URLs baked into a locally-composed supergraph. The explorer never
23
+ * routes through them (it proxies whole operations to the edge), so they are
24
+ * cosmetic — but composition requires each subgraph to declare one. */
25
+ const LOCAL_IL_URL = "http://integration-layer.local/graphql";
26
+ const LOCAL_EXTENSION_URL = "http://extension.local/graphql";
27
+ /**
28
+ * Compose the core subgraph ALONE into an API schema — the local path when the
29
+ * working directory has no extension. `composeWithIntegrationLayer` takes two
30
+ * subgraphs, so the single-subgraph case goes straight to `composeServices`.
31
+ */
32
+ function composeCoreOnly(coreSdl) {
33
+ let services;
34
+ try {
35
+ services = [
36
+ { name: INTEGRATION_LAYER_SERVICE, typeDefs: parse(coreSdl), url: LOCAL_IL_URL },
37
+ ];
38
+ }
39
+ catch (err) {
40
+ return { ok: false, errors: [`core-subgraph SDL is not valid GraphQL: ${err.message}`] };
41
+ }
42
+ const result = composeServices(services);
43
+ if (result.errors)
44
+ return { ok: false, errors: result.errors.map((e) => e.message) };
45
+ const apiSchema = result.schema.toAPISchema().toGraphQLJSSchema();
46
+ return {
47
+ ok: true,
48
+ apiSchema,
49
+ apiSdl: printSchema(apiSchema),
50
+ supergraphSdl: result.supergraphSdl,
51
+ };
52
+ }
53
+ /**
54
+ * The local-composition path: the project's core subgraph, plus `extensionSdl` when
55
+ * the caller found a local extension to build. Throws with the composition errors
56
+ * when the two don't compose — the same failure `extension validate` reports, and a
57
+ * real answer rather than a half-rendered explorer.
58
+ */
59
+ export function composeLocalExplorerSchema(coreSdl, extensionSdl) {
60
+ const result = extensionSdl
61
+ ? composeWithIntegrationLayer(coreSdl, extensionSdl, {
62
+ integrationLayerUrl: LOCAL_IL_URL,
63
+ extensionUrl: LOCAL_EXTENSION_URL,
64
+ })
65
+ : composeCoreOnly(coreSdl);
66
+ if (!result.ok) {
67
+ throw new Error(`could not compose the schema locally:\n${result.errors.map((e) => ` - ${e}`).join("\n")}`);
68
+ }
69
+ return {
70
+ schema: result.apiSchema,
71
+ sdl: result.apiSdl,
72
+ describe: extensionSdl
73
+ ? "local compose (core subgraph + your local extension)"
74
+ : "local compose (core subgraph only — no extension in this directory)",
75
+ };
76
+ }
77
+ //# sourceMappingURL=exploreSchema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exploreSchema.js","sourceRoot":"","sources":["../../../src/lib/tooling/exploreSchema.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,EAAE;AACF,kFAAkF;AAClF,mFAAmF;AACnF,gFAAgF;AAChF,EAAE;AACF,oFAAoF;AACpF,iFAAiF;AACjF,8EAA8E;AAC9E,4EAA4E;AAC5E,iFAAiF;AACjF,EAAE;AACF,qFAAqF;AACrF,sFAAsF;AACtF,kFAAkF;AAClF,oFAAoF;AACpF,oFAAoF;AAEpF,OAAO,EAAE,WAAW,EAAsB,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,GAE1B,MAAM,cAAc,CAAC;AAEtB;;wEAEwE;AACxE,MAAM,YAAY,GAAG,wCAAwC,CAAC;AAC9D,MAAM,mBAAmB,GAAG,gCAAgC,CAAC;AAU7D;;;;GAIG;AACH,SAAS,eAAe,CAAC,OAAe;IACtC,IAAI,QAAQ,CAAC;IACb,IAAI,CAAC;QACH,QAAQ,GAAG;YACT,EAAE,IAAI,EAAE,yBAAyB,EAAE,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,YAAY,EAAE;SACjF,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,2CAA4C,GAAa,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;IACtG,CAAC;IACD,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,MAAM,CAAC,MAAM;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACrF,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,iBAAiB,EAAE,CAAC;IAClE,OAAO;QACL,EAAE,EAAE,IAAI;QACR,SAAS;QACT,MAAM,EAAE,WAAW,CAAC,SAAS,CAAC;QAC9B,aAAa,EAAE,MAAM,CAAC,aAAa;KACpC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CACxC,OAAe,EACf,YAAgC;IAEhC,MAAM,MAAM,GAAG,YAAY;QACzB,CAAC,CAAC,2BAA2B,CAAC,OAAO,EAAE,YAAY,EAAE;YACjD,mBAAmB,EAAE,YAAY;YACjC,YAAY,EAAE,mBAAmB;SAClC,CAAC;QACJ,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;IAE7B,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,0CAA0C,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC5F,CAAC;IACJ,CAAC;IACD,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,SAAS;QACxB,GAAG,EAAE,MAAM,CAAC,MAAM;QAClB,QAAQ,EAAE,YAAY;YACpB,CAAC,CAAC,sDAAsD;YACxD,CAAC,CAAC,qEAAqE;KAC1E,CAAC;AACJ,CAAC"}
@@ -0,0 +1 @@
1
+ export declare const EXPLORER_HTML: string;
@@ -0,0 +1,96 @@
1
+ // The GraphiQL page the local explorer serves at `/`.
2
+ //
3
+ // A static HTML shell loading GraphiQL from a CDN (esm.sh, version-pinned + SRI),
4
+ // pointed at this same local server's `/graphql`. Nothing is templated into it: the
5
+ // project key, the edge URL, and the session bearer all live server-side, so the
6
+ // page holds no credential and needs no configuration.
7
+ //
8
+ // The local server answers introspection itself from the resolved schema and proxies
9
+ // everything else to the deployed edge, so GraphiQL gets full docs/autocomplete even
10
+ // though the edge itself has introspection disabled.
11
+ export const EXPLORER_HTML = String.raw `<!doctype html>
12
+ <html lang="en">
13
+ <head>
14
+ <meta charset="utf-8" />
15
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
16
+ <title>GraphQL Explorer · commercetools integration layer</title>
17
+ <style>
18
+ body { margin: 0; height: 100dvh; overflow: hidden; }
19
+ #graphiql { height: 100dvh; }
20
+ .loading { display: flex; height: 100dvh; align-items: center;
21
+ justify-content: center; font-family: ui-sans-serif, system-ui, sans-serif;
22
+ color: #6b7280; }
23
+ </style>
24
+ <link
25
+ rel="stylesheet"
26
+ href="https://esm.sh/graphiql@5.2.4/dist/style.css"
27
+ integrity="sha384-TFpQQKp325U5sd3PddH4cS0KOB3Gz/aqdEe12Mqkkq3wm2MGcDhRX5WhWf+o8akh"
28
+ crossorigin="anonymous"
29
+ />
30
+ <link
31
+ rel="stylesheet"
32
+ href="https://esm.sh/@graphiql/plugin-explorer@5.1.3/dist/style.css"
33
+ integrity="sha384-vTFGj0krVqwFXLB7kq/VHR0/j2+cCT/B63rge2mULaqnib2OX7DVLUVksTlqvMab"
34
+ crossorigin="anonymous"
35
+ />
36
+ <script type="importmap">
37
+ {
38
+ "imports": {
39
+ "react": "https://esm.sh/react@19.2.0",
40
+ "react/jsx-runtime": "https://esm.sh/react@19.2.0/jsx-runtime",
41
+ "react-dom": "https://esm.sh/react-dom@19.2.0",
42
+ "react-dom/client": "https://esm.sh/react-dom@19.2.0/client",
43
+ "graphql": "https://esm.sh/graphql@16.11.0",
44
+ "graphiql": "https://esm.sh/graphiql@5.2.4?standalone&external=react,react-dom,@graphiql/react,graphql",
45
+ "graphiql/": "https://esm.sh/graphiql@5.2.4/",
46
+ "@graphiql/plugin-explorer": "https://esm.sh/@graphiql/plugin-explorer@5.1.3?standalone&external=react,@graphiql/react,graphql",
47
+ "@graphiql/react": "https://esm.sh/@graphiql/react@0.37.7?standalone&external=react,react-dom,graphql,@graphiql/toolkit,@emotion/is-prop-valid",
48
+ "@graphiql/toolkit": "https://esm.sh/@graphiql/toolkit@0.12.1?standalone&external=graphql"
49
+ }
50
+ }
51
+ </script>
52
+ </head>
53
+ <body>
54
+ <div id="graphiql"><div class="loading">Loading the explorer…</div></div>
55
+ <script type="module">
56
+ import React from 'react';
57
+ import ReactDOM from 'react-dom/client';
58
+ import { GraphiQL, HISTORY_PLUGIN } from 'graphiql';
59
+ import { createGraphiQLFetcher } from '@graphiql/toolkit';
60
+ import { explorerPlugin } from '@graphiql/plugin-explorer';
61
+ import 'graphiql/setup-workers/esm.sh';
62
+
63
+ // Same-origin: this page and the GraphQL endpoint are both served by the CLI's
64
+ // local server, which holds the session bearer and forwards to the edge.
65
+ const fetcher = createGraphiQLFetcher({ url: location.origin + '/graphql' });
66
+
67
+ const plugins = [HISTORY_PLUGIN, explorerPlugin()];
68
+
69
+ const DEFAULT_QUERY = [
70
+ '# Local GraphQL explorer for your commercetools integration layer.',
71
+ '#',
72
+ '# Operations run against the DEPLOYED edge under the session shown in your',
73
+ '# terminal. Docs and autocomplete come from the schema the CLI resolved.',
74
+ '',
75
+ 'query Categories {',
76
+ ' categories {',
77
+ ' items {',
78
+ ' name',
79
+ ' }',
80
+ ' }',
81
+ '}',
82
+ '',
83
+ ].join('\n');
84
+
85
+ ReactDOM.createRoot(document.getElementById('graphiql')).render(
86
+ React.createElement(GraphiQL, {
87
+ fetcher,
88
+ plugins,
89
+ defaultQuery: DEFAULT_QUERY,
90
+ }),
91
+ );
92
+ </script>
93
+ </body>
94
+ </html>
95
+ `;
96
+ //# sourceMappingURL=explorerPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explorerPage.js","sourceRoot":"","sources":["../../../src/lib/tooling/explorerPage.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,EAAE;AACF,kFAAkF;AAClF,oFAAoF;AACpF,iFAAiF;AACjF,uDAAuD;AACvD,EAAE;AACF,qFAAqF;AACrF,qFAAqF;AACrF,qDAAqD;AAErD,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoFtC,CAAC"}
@@ -0,0 +1,27 @@
1
+ import { type Server } from "node:http";
2
+ import { type GraphQLSchema } from "graphql";
3
+ /** The GraphQL-over-HTTP request body GraphiQL sends. */
4
+ export interface GraphQLBody {
5
+ query?: string;
6
+ variables?: Record<string, unknown>;
7
+ operationName?: string;
8
+ }
9
+ export interface ExplorerServerOptions {
10
+ /** The schema introspection is answered from (docs, autocomplete, validation). */
11
+ schema: GraphQLSchema;
12
+ /** Absolute URL of the deployed edge's per-project GraphQL endpoint. */
13
+ endpoint: string;
14
+ /** Session bearer attached to every proxied operation. Never sent to the browser. */
15
+ bearer: string;
16
+ }
17
+ /**
18
+ * Build (but do not listen on) the explorer's server.
19
+ *
20
+ * The edge endpoint is validated ONCE here, not per request: it must be an
21
+ * absolute `http:`/`https:` URL. It comes from the operator's own login region or
22
+ * their explicit `--graphql-url` / `IL_GRAPHQL_URL`, so this is not a trust
23
+ * boundary — but pinning the scheme up front means a typo or a stray `file://`
24
+ * fails at startup with a clear message rather than at the first query, and the
25
+ * value the proxy uses can never be anything else.
26
+ */
27
+ export declare function createExplorerServer(opts: ExplorerServerOptions): Server;
@@ -0,0 +1,134 @@
1
+ // The explorer's local HTTP server.
2
+ //
3
+ // Three responsibilities, and the split between the last two is the whole design:
4
+ //
5
+ // GET / the GraphiQL page
6
+ // POST /graphql introspection → answered HERE from the resolved schema, because
7
+ // the deployed edge runs `introspection: false`
8
+ // everything else → proxied to the edge under a session bearer
9
+ //
10
+ // The bearer never reaches the browser: the page is same-origin and this process
11
+ // attaches the credential on the way out.
12
+ //
13
+ // Kept out of the command so it can be started and driven in tests against a stub
14
+ // edge, rather than only exercised by hand.
15
+ import { createServer } from "node:http";
16
+ import { execute, parse, validate } from "graphql";
17
+ import { EXPLORER_HTML } from "./explorerPage.js";
18
+ import { isIntrospectionRequest } from "./introspectionRequest.js";
19
+ /**
20
+ * Build (but do not listen on) the explorer's server.
21
+ *
22
+ * The edge endpoint is validated ONCE here, not per request: it must be an
23
+ * absolute `http:`/`https:` URL. It comes from the operator's own login region or
24
+ * their explicit `--graphql-url` / `IL_GRAPHQL_URL`, so this is not a trust
25
+ * boundary — but pinning the scheme up front means a typo or a stray `file://`
26
+ * fails at startup with a clear message rather than at the first query, and the
27
+ * value the proxy uses can never be anything else.
28
+ */
29
+ export function createExplorerServer(opts) {
30
+ let parsed;
31
+ try {
32
+ parsed = new URL(opts.endpoint);
33
+ }
34
+ catch {
35
+ throw new Error(`the GraphQL edge endpoint is not a valid URL: ${opts.endpoint}`);
36
+ }
37
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
38
+ throw new Error(`the GraphQL edge endpoint must be http(s), got '${parsed.protocol}': ${opts.endpoint}`);
39
+ }
40
+ const endpoint = parsed.toString();
41
+ return createServer((req, res) => {
42
+ void handle(req, res, { ...opts, endpoint });
43
+ });
44
+ }
45
+ async function handle(req, res, opts) {
46
+ const path = (req.url ?? "/").split("?")[0];
47
+ const json = (status, payload) => {
48
+ res.writeHead(status, { "content-type": "application/json" });
49
+ res.end(JSON.stringify(payload));
50
+ };
51
+ if (req.method === "GET" && (path === "/" || path === "/index.html")) {
52
+ res.writeHead(200, { "content-type": "text/html; charset=utf-8" });
53
+ res.end(EXPLORER_HTML);
54
+ return;
55
+ }
56
+ if (path !== "/graphql") {
57
+ json(404, { errors: [{ message: `no route ${path}` }] });
58
+ return;
59
+ }
60
+ if (req.method !== "POST") {
61
+ json(405, { errors: [{ message: "the GraphQL endpoint accepts POST" }] });
62
+ return;
63
+ }
64
+ let body;
65
+ try {
66
+ body = JSON.parse(await readBody(req));
67
+ }
68
+ catch (err) {
69
+ json(400, { errors: [{ message: `invalid JSON body: ${err.message}` }] });
70
+ return;
71
+ }
72
+ const query = body.query ?? "";
73
+ if (!query.trim()) {
74
+ json(400, { errors: [{ message: "request body must include a 'query'" }] });
75
+ return;
76
+ }
77
+ if (isIntrospectionRequest(query, body.operationName)) {
78
+ let document;
79
+ try {
80
+ document = parse(query);
81
+ }
82
+ catch (err) {
83
+ json(400, { errors: [{ message: err.message }] });
84
+ return;
85
+ }
86
+ const errors = validate(opts.schema, document);
87
+ if (errors.length) {
88
+ json(400, { errors: errors.map((e) => ({ message: e.message })) });
89
+ return;
90
+ }
91
+ json(200, await execute({
92
+ schema: opts.schema,
93
+ document,
94
+ variableValues: body.variables,
95
+ operationName: body.operationName,
96
+ }));
97
+ return;
98
+ }
99
+ try {
100
+ // Not SSRF: `opts.endpoint` is fixed when the server is constructed, from the
101
+ // operator's OWN login region or their explicit --graphql-url/IL_GRAPHQL_URL,
102
+ // and validated to be an absolute http(s) URL there. Nothing in the request
103
+ // influences it — the body is forwarded, the destination is not. The server
104
+ // also binds 127.0.0.1, so the only caller is the developer who chose the URL;
105
+ // there is no privilege boundary for a forged request to cross.
106
+ // nosemgrep
107
+ const upstream = await fetch(opts.endpoint, {
108
+ method: "POST",
109
+ headers: {
110
+ "content-type": "application/json",
111
+ accept: "application/json",
112
+ authorization: `Bearer ${opts.bearer}`,
113
+ },
114
+ body: JSON.stringify(body),
115
+ });
116
+ const text = await upstream.text();
117
+ res.writeHead(upstream.status, {
118
+ "content-type": upstream.headers.get("content-type") ?? "application/json",
119
+ });
120
+ res.end(text);
121
+ }
122
+ catch (err) {
123
+ json(502, {
124
+ errors: [{ message: `could not reach ${opts.endpoint}: ${err.message}` }],
125
+ });
126
+ }
127
+ }
128
+ async function readBody(req) {
129
+ const chunks = [];
130
+ for await (const chunk of req)
131
+ chunks.push(chunk);
132
+ return Buffer.concat(chunks).toString("utf8");
133
+ }
134
+ //# sourceMappingURL=explorerServer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explorerServer.js","sourceRoot":"","sources":["../../../src/lib/tooling/explorerServer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * True when `query`'s selected operation is a query whose every top-level selection
3
+ * is an introspection meta-field (`__schema`, `__type`, `__typename`).
4
+ *
5
+ * Unparseable input is NOT introspection: forwarding it lets the edge produce the
6
+ * error, which is the same message the developer would get in production.
7
+ *
8
+ * A mixed operation (`{ __schema { … } categories { … } }`) is also not
9
+ * introspection — it needs real resolvers, so it goes to the edge and the edge
10
+ * refuses the `__schema` half. That is the honest answer: the edge genuinely can't
11
+ * serve it, and pretending otherwise would return half-null data.
12
+ */
13
+ export declare function isIntrospectionRequest(query: string, operationName?: string): boolean;