@rytass/bpm-core-client 0.1.4 → 0.1.6
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/CHANGELOG.md +63 -0
- package/README.md +105 -3
- package/package.json +2 -2
- package/src/index.d.ts +1 -0
- package/src/index.js +1 -0
- package/src/index.js.map +1 -1
- package/src/lib/api-auth-client.js +9 -1
- package/src/lib/api-auth-client.js.map +1 -1
- package/src/lib/client-config.d.ts +81 -0
- package/src/lib/client-config.js +63 -0
- package/src/lib/client-config.js.map +1 -0
- package/src/lib/graphql-client.js +10 -1
- package/src/lib/graphql-client.js.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,69 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
8
8
|
Releases are managed by [`nx release`](https://nx.dev/recipes/nx-release) with
|
|
9
9
|
Conventional Commits — see `nx.json` for the release config.
|
|
10
10
|
|
|
11
|
+
## 0.1.6 — 2026-05-28
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **`configureBPMClient({ baseUrl, authBaseUrl, fetch, headers })`**.
|
|
16
|
+
Server-side Node scripts (cron workers, org seeds, integration tests)
|
|
17
|
+
can now override the GraphQL endpoint, REST auth base URL, fetch
|
|
18
|
+
implementation, and default request headers programmatically without
|
|
19
|
+
relying on `NEXT_PUBLIC_API_URL` environment resolution. Both the
|
|
20
|
+
`requestGraphQl` GraphQL transport and the REST auth client honor the
|
|
21
|
+
override. Browser consumers under Next.js typically still rely on
|
|
22
|
+
`NEXT_PUBLIC_API_URL` and do not need to call this.
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import { configureBPMClient } from '@rytass/bpm-core-client';
|
|
26
|
+
|
|
27
|
+
configureBPMClient({
|
|
28
|
+
baseUrl: 'https://api.shuttle.example.com',
|
|
29
|
+
headers: { 'X-Service-Token': process.env.BPM_SYNC_TOKEN ?? '' },
|
|
30
|
+
});
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Documentation
|
|
34
|
+
|
|
35
|
+
- README "Organization Mirror Pattern" rewritten with the correct
|
|
36
|
+
flat-input API shape (`updateOrgUnit({ id, code, name, type,
|
|
37
|
+
parentId, metadataJson })`, not the `{ id, input: {...} }` form the
|
|
38
|
+
0.1.5 example incorrectly showed). Adds a "Server-side base URL
|
|
39
|
+
override" section pointing at `configureBPMClient`.
|
|
40
|
+
|
|
41
|
+
### Why a patch
|
|
42
|
+
|
|
43
|
+
`configureBPMClient` is purely additive. Existing callers see no
|
|
44
|
+
change to behavior unless they call the new API.
|
|
45
|
+
|
|
46
|
+
## 0.1.5 — 2026-05-28
|
|
47
|
+
|
|
48
|
+
### Documentation
|
|
49
|
+
|
|
50
|
+
- **README "Organization mirror pattern" section.** Condensed pointer to
|
|
51
|
+
the full pattern in `@rytass/bpm-core-nestjs-module`'s README plus a
|
|
52
|
+
client-side worked example using `createOrgUnit`, `updateOrgUnit`,
|
|
53
|
+
`deleteOrgUnit`, `commitOrgUnitTreeDraft`, `createPosition`,
|
|
54
|
+
`createMembership`, `createManagerResolution`. Clarifies that BPM owns
|
|
55
|
+
the org graph and host applications mirror their existing org data in
|
|
56
|
+
rather than expose a resolver (in contrast to the member-resolver
|
|
57
|
+
pattern).
|
|
58
|
+
|
|
59
|
+
### Why a patch
|
|
60
|
+
|
|
61
|
+
No type or runtime change. README only.
|
|
62
|
+
|
|
63
|
+
## 0.1.4 — 2026-05-27
|
|
64
|
+
|
|
65
|
+
No source changes. Bumped in lockstep with
|
|
66
|
+
`@rytass/bpm-core-nestjs-module@0.1.4` (re-publish after the 0.1.3
|
|
67
|
+
backend tarball shipped only `.ts` source — see that package's CHANGELOG).
|
|
68
|
+
|
|
69
|
+
## 0.1.3 — 2026-05-27 (deprecated on npm)
|
|
70
|
+
|
|
71
|
+
Lockstep bump alongside the broken 0.1.3 backend release. Avoid;
|
|
72
|
+
upgrade directly to 0.1.4 or newer.
|
|
73
|
+
|
|
11
74
|
## 0.1.2 — 2026-05-27
|
|
12
75
|
|
|
13
76
|
No source changes. Bumped in lockstep with
|
package/README.md
CHANGED
|
@@ -151,9 +151,9 @@ default endpoint, no cookie jar. Treat them the same as Server Components.
|
|
|
151
151
|
|
|
152
152
|
## Endpoint Resolution
|
|
153
153
|
|
|
154
|
-
By default the client targets the same origin (no `/api` prefix) — see
|
|
155
|
-
|
|
156
|
-
host contract. Endpoint resolution rules:
|
|
154
|
+
By default the client targets the same origin (no `/api` prefix) — see the
|
|
155
|
+
"Embedding & auth" section of `@rytass/bpm-core-nestjs-module`'s README for
|
|
156
|
+
the host-side contract. Endpoint resolution rules:
|
|
157
157
|
|
|
158
158
|
| Source | Behavior |
|
|
159
159
|
| ----------------------------------------------- | -------------------------------------------------------------------------- |
|
|
@@ -206,6 +206,108 @@ Every subpath uses the same `requestGraphQl` transport from the root. Hosts
|
|
|
206
206
|
can mix and match — for example a read-only dashboard might only import
|
|
207
207
|
`workflow` queries, never reaching for `/organization` mutations.
|
|
208
208
|
|
|
209
|
+
## Organization Mirror Pattern (Important)
|
|
210
|
+
|
|
211
|
+
> **TL;DR:** BPM owns the org graph (`org_units`, `positions`,
|
|
212
|
+
> `memberships`, `manager_resolutions`). Hosts with their own org model
|
|
213
|
+
> mirror data **into** BPM via the `/organization` mutations rather than
|
|
214
|
+
> exposing a host-side resolver. See the
|
|
215
|
+
> "Organization Data Ownership" section of
|
|
216
|
+
> `@rytass/bpm-core-nestjs-module`'s README for the rationale.
|
|
217
|
+
|
|
218
|
+
The integration shape is **asymmetric** with `BPMMemberResolver`:
|
|
219
|
+
member identity stays in the host's user table and BPM reaches in via
|
|
220
|
+
the resolver token; the org structure lives in BPM and the host pushes
|
|
221
|
+
data in. Three rules keep the mirror idempotent:
|
|
222
|
+
|
|
223
|
+
1. **Use `code` as the natural key.** Both `OrgUnit` and `Position`
|
|
224
|
+
carry a unique `code` you control. On every sync, look up by `code`
|
|
225
|
+
before deciding INSERT vs UPDATE.
|
|
226
|
+
2. **Stash the host-FK in `metadata`.** Both entities carry an opaque
|
|
227
|
+
`metadata` JSON BPM never introspects — store your host's primary
|
|
228
|
+
key there to chase pointers back during reconciliation.
|
|
229
|
+
3. **Soft-delete via the `delete*` mutations.** They set `deletedAt`;
|
|
230
|
+
live queries (`orgUnits`, `orgUnitCount`, etc.) filter soft-deleted
|
|
231
|
+
rows automatically.
|
|
232
|
+
|
|
233
|
+
Quick wire-up using only this package's exports. Note the flat input
|
|
234
|
+
shape on the create/update mutations (no `{id, input: {...}}` wrapper):
|
|
235
|
+
|
|
236
|
+
```ts
|
|
237
|
+
import {
|
|
238
|
+
readOrganizationDashboard,
|
|
239
|
+
createOrgUnit,
|
|
240
|
+
updateOrgUnit,
|
|
241
|
+
} from '@rytass/bpm-core-client/organization';
|
|
242
|
+
import type { OrgUnitType } from '@rytass/bpm-core-shared';
|
|
243
|
+
|
|
244
|
+
async function upsertOrgUnit(hostUnit: {
|
|
245
|
+
code: string;
|
|
246
|
+
name: string;
|
|
247
|
+
type: OrgUnitType;
|
|
248
|
+
parentCode: string | null;
|
|
249
|
+
hostId: string;
|
|
250
|
+
}): Promise<string> {
|
|
251
|
+
// One round trip pulls every org unit; index by code in your sync loop.
|
|
252
|
+
const dash = await readOrganizationDashboard({ orgUnitPageSize: null });
|
|
253
|
+
const existing = dash.orgUnits.find((u) => u.code === hostUnit.code);
|
|
254
|
+
const parentId = hostUnit.parentCode
|
|
255
|
+
? dash.orgUnits.find((u) => u.code === hostUnit.parentCode)?.id ?? null
|
|
256
|
+
: null;
|
|
257
|
+
const metadataJson = JSON.stringify({ hostId: hostUnit.hostId });
|
|
258
|
+
|
|
259
|
+
if (existing) {
|
|
260
|
+
return (
|
|
261
|
+
await updateOrgUnit({
|
|
262
|
+
id: existing.id,
|
|
263
|
+
code: hostUnit.code,
|
|
264
|
+
name: hostUnit.name,
|
|
265
|
+
type: hostUnit.type,
|
|
266
|
+
parentId,
|
|
267
|
+
metadataJson,
|
|
268
|
+
})
|
|
269
|
+
).id;
|
|
270
|
+
}
|
|
271
|
+
return (
|
|
272
|
+
await createOrgUnit({
|
|
273
|
+
code: hostUnit.code,
|
|
274
|
+
name: hostUnit.name,
|
|
275
|
+
type: hostUnit.type,
|
|
276
|
+
parentId,
|
|
277
|
+
metadataJson,
|
|
278
|
+
})
|
|
279
|
+
).id;
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
`createPosition`, `createMembership`, `updateMembership`, and
|
|
284
|
+
`createManagerResolution` follow the same flat-input pattern. For bulk
|
|
285
|
+
tree moves in one transaction, see `commitOrgUnitTreeDraft`. **Only**
|
|
286
|
+
that one mutation is transactional — sequential `createMembership` calls
|
|
287
|
+
are independent and partial-failures stay committed.
|
|
288
|
+
|
|
289
|
+
### Server-side base URL override
|
|
290
|
+
|
|
291
|
+
The GraphQL client resolves its endpoint via `NEXT_PUBLIC_API_URL` or
|
|
292
|
+
same-origin. Node scripts that aren't running inside Next.js (cron
|
|
293
|
+
workers, one-off org seeds, integration tests) should call
|
|
294
|
+
`configureBPMClient` from the root package barrel once at startup:
|
|
295
|
+
|
|
296
|
+
```ts
|
|
297
|
+
import { configureBPMClient } from '@rytass/bpm-core-client';
|
|
298
|
+
|
|
299
|
+
configureBPMClient({
|
|
300
|
+
baseUrl: 'https://api.shuttle.example.com',
|
|
301
|
+
// Optional: inject your own fetch (e.g. node-fetch) or default headers.
|
|
302
|
+
fetch: globalThis.fetch,
|
|
303
|
+
headers: { 'X-Service-Token': process.env.BPM_SYNC_TOKEN ?? '' },
|
|
304
|
+
});
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
All subsequent calls to `requestGraphQl` and the REST auth client honor
|
|
308
|
+
the override. Both `baseUrl` and `headers` are static for the process
|
|
309
|
+
lifetime — call `configureBPMClient` again to replace.
|
|
310
|
+
|
|
209
311
|
## Auth REST Endpoints
|
|
210
312
|
|
|
211
313
|
The BPM wrapper-host exposes the following endpoints under the host root (no
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rytass/bpm-core-client",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Framework-agnostic TypeScript client for the Rytass BPM approval workflow GraphQL surface: fetch-based GraphQL transport, REST auth client, pre-baked typed operations for organization, member, form, template, and workflow.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bpm",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
}
|
|
74
74
|
},
|
|
75
75
|
"peerDependencies": {
|
|
76
|
-
"@rytass/bpm-core-shared": "^0.1.
|
|
76
|
+
"@rytass/bpm-core-shared": "^0.1.6"
|
|
77
77
|
},
|
|
78
78
|
"dependencies": {
|
|
79
79
|
"tslib": "^2.3.0"
|
package/src/index.d.ts
CHANGED
package/src/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
tslib_1.__exportStar(require("./lib/api-auth-client"), exports);
|
|
5
|
+
tslib_1.__exportStar(require("./lib/client-config"), exports);
|
|
5
6
|
tslib_1.__exportStar(require("./lib/graphql-client"), exports);
|
|
6
7
|
tslib_1.__exportStar(require("./lib/member-api"), exports);
|
|
7
8
|
//# sourceMappingURL=index.js.map
|
package/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/bpm-core-client/src/index.ts"],"names":[],"mappings":";;;AAAA,gEAAsC;AACtC,+DAAqC;AACrC,2DAAiC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/bpm-core-client/src/index.ts"],"names":[],"mappings":";;;AAAA,gEAAsC;AACtC,8DAAoC;AACpC,+DAAqC;AACrC,2DAAiC"}
|
|
@@ -7,6 +7,7 @@ exports.readApiCurrentMember = readApiCurrentMember;
|
|
|
7
7
|
exports.readApiBaseUrl = readApiBaseUrl;
|
|
8
8
|
exports.resolveApiBaseUrlFromGraphQlEndpoint = resolveApiBaseUrlFromGraphQlEndpoint;
|
|
9
9
|
const graphql_client_1 = require("./graphql-client");
|
|
10
|
+
const client_config_1 = require("./client-config");
|
|
10
11
|
/**
|
|
11
12
|
* Lists seeded test members exposed by the host's `/auth/test-members`
|
|
12
13
|
* endpoint. Hosts targeting production typically disable this endpoint or
|
|
@@ -71,6 +72,10 @@ async function readApiCurrentMember() {
|
|
|
71
72
|
* assumed to expose both `/graphql` and `/auth/*` at the same origin.
|
|
72
73
|
*/
|
|
73
74
|
function readApiBaseUrl() {
|
|
75
|
+
const config = (0, client_config_1.readBPMClientConfig)();
|
|
76
|
+
if (config.authBaseUrl?.trim()) {
|
|
77
|
+
return config.authBaseUrl.trim().replace(/\/$/, '');
|
|
78
|
+
}
|
|
74
79
|
const explicitApiBaseUrl = process.env.NEXT_PUBLIC_API_AUTH_URL?.trim();
|
|
75
80
|
if (explicitApiBaseUrl) {
|
|
76
81
|
return explicitApiBaseUrl.replace(/\/$/, '');
|
|
@@ -89,9 +94,12 @@ function resolveApiBaseUrlFromGraphQlEndpoint(graphQlEndpoint) {
|
|
|
89
94
|
return endpoint.toString().replace(/\/$/, '');
|
|
90
95
|
}
|
|
91
96
|
async function requestApi(path, init) {
|
|
92
|
-
const
|
|
97
|
+
const fetchImpl = (0, client_config_1.resolveBPMFetch)();
|
|
98
|
+
const configuredHeaders = (0, client_config_1.readBPMConfiguredHeaders)();
|
|
99
|
+
const response = await fetchImpl(`${readApiBaseUrl()}${path}`, {
|
|
93
100
|
credentials: 'include',
|
|
94
101
|
...init,
|
|
102
|
+
headers: { ...configuredHeaders, ...(init?.headers ?? {}) },
|
|
95
103
|
});
|
|
96
104
|
if (!response.ok) {
|
|
97
105
|
throw new ApiRequestError(response.status, await readError(response));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-auth-client.js","sourceRoot":"","sources":["../../../../../libs/bpm-core-client/src/lib/api-auth-client.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"api-auth-client.js","sourceRoot":"","sources":["../../../../../libs/bpm-core-client/src/lib/api-auth-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Programmatic configuration override for the BPM client transport.
|
|
3
|
+
*
|
|
4
|
+
* The default endpoint resolution (`NEXT_PUBLIC_API_URL` → localhost →
|
|
5
|
+
* same-origin) covers Next.js consumers. Node-side scripts (cron
|
|
6
|
+
* workers, one-off org seeds, integration tests) usually cannot rely on
|
|
7
|
+
* environment variables and need a programmatic hook. Call
|
|
8
|
+
* {@link configureBPMClient} once at startup; subsequent
|
|
9
|
+
* `requestGraphQl` and REST auth calls honor the override.
|
|
10
|
+
*/
|
|
11
|
+
export interface BPMClientConfig {
|
|
12
|
+
/**
|
|
13
|
+
* Override the GraphQL endpoint URL. When provided, takes precedence
|
|
14
|
+
* over `NEXT_PUBLIC_API_URL` and the default localhost / same-origin
|
|
15
|
+
* resolution. Pass an absolute URL ending without `/graphql` to also
|
|
16
|
+
* derive the REST `/auth/*` base URL automatically, or pass the full
|
|
17
|
+
* `https://host/graphql` form to set the GraphQL endpoint directly.
|
|
18
|
+
*
|
|
19
|
+
* If you need different bases for GraphQL vs `/auth/*` (rare — most
|
|
20
|
+
* hosts colocate them), set both `baseUrl` and `authBaseUrl`.
|
|
21
|
+
*/
|
|
22
|
+
readonly baseUrl?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Override the REST `/auth/*` base URL independently of `baseUrl`.
|
|
25
|
+
* Most hosts colocate GraphQL and auth on the same origin; this knob
|
|
26
|
+
* exists for the rare split-origin deployment.
|
|
27
|
+
*/
|
|
28
|
+
readonly authBaseUrl?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Replace the global `fetch` implementation. Useful when running on a
|
|
31
|
+
* runtime without a global `fetch` (older Node versions, edge runtimes
|
|
32
|
+
* with custom polyfills) or when you want to inject a tracing wrapper.
|
|
33
|
+
*/
|
|
34
|
+
readonly fetch?: typeof fetch;
|
|
35
|
+
/**
|
|
36
|
+
* Additional headers merged into every outbound request. Use this to
|
|
37
|
+
* pass service tokens, tracing headers, or a server-side session
|
|
38
|
+
* cookie that the browser would normally send automatically.
|
|
39
|
+
*
|
|
40
|
+
* Note: `Content-Type` is set internally for GraphQL POSTs and
|
|
41
|
+
* cannot be overridden through this option.
|
|
42
|
+
*/
|
|
43
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Sets the active {@link BPMClientConfig}. Subsequent calls **replace**
|
|
47
|
+
* the previous configuration; pass `{}` to reset to environment-based
|
|
48
|
+
* defaults.
|
|
49
|
+
*
|
|
50
|
+
* Idiomatic call site is the very top of a Node worker's bootstrap:
|
|
51
|
+
*
|
|
52
|
+
* ```ts
|
|
53
|
+
* import { configureBPMClient } from '@rytass/bpm-core-client';
|
|
54
|
+
*
|
|
55
|
+
* configureBPMClient({
|
|
56
|
+
* baseUrl: 'https://api.shuttle.example.com',
|
|
57
|
+
* headers: { 'X-Service-Token': process.env.BPM_SYNC_TOKEN ?? '' },
|
|
58
|
+
* });
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* Browser consumers under Next.js typically do **not** need to call
|
|
62
|
+
* this — `NEXT_PUBLIC_API_URL` plus same-origin defaults cover the
|
|
63
|
+
* common case.
|
|
64
|
+
*/
|
|
65
|
+
export declare function configureBPMClient(config: BPMClientConfig): void;
|
|
66
|
+
/**
|
|
67
|
+
* Reads the active {@link BPMClientConfig}. Exposed primarily for tests
|
|
68
|
+
* and for inspecting the current override at runtime — consumers should
|
|
69
|
+
* use {@link configureBPMClient} to mutate, never reach in directly.
|
|
70
|
+
*/
|
|
71
|
+
export declare function readBPMClientConfig(): BPMClientConfig;
|
|
72
|
+
/**
|
|
73
|
+
* Resolves the effective `fetch` implementation honoring the active
|
|
74
|
+
* override, falling back to the global `fetch`.
|
|
75
|
+
*/
|
|
76
|
+
export declare function resolveBPMFetch(): typeof fetch;
|
|
77
|
+
/**
|
|
78
|
+
* Returns the headers configured via {@link configureBPMClient}.
|
|
79
|
+
* Internal transports merge these into every outbound request.
|
|
80
|
+
*/
|
|
81
|
+
export declare function readBPMConfiguredHeaders(): Readonly<Record<string, string>>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Programmatic configuration override for the BPM client transport.
|
|
4
|
+
*
|
|
5
|
+
* The default endpoint resolution (`NEXT_PUBLIC_API_URL` → localhost →
|
|
6
|
+
* same-origin) covers Next.js consumers. Node-side scripts (cron
|
|
7
|
+
* workers, one-off org seeds, integration tests) usually cannot rely on
|
|
8
|
+
* environment variables and need a programmatic hook. Call
|
|
9
|
+
* {@link configureBPMClient} once at startup; subsequent
|
|
10
|
+
* `requestGraphQl` and REST auth calls honor the override.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.configureBPMClient = configureBPMClient;
|
|
14
|
+
exports.readBPMClientConfig = readBPMClientConfig;
|
|
15
|
+
exports.resolveBPMFetch = resolveBPMFetch;
|
|
16
|
+
exports.readBPMConfiguredHeaders = readBPMConfiguredHeaders;
|
|
17
|
+
let currentConfig = {};
|
|
18
|
+
/**
|
|
19
|
+
* Sets the active {@link BPMClientConfig}. Subsequent calls **replace**
|
|
20
|
+
* the previous configuration; pass `{}` to reset to environment-based
|
|
21
|
+
* defaults.
|
|
22
|
+
*
|
|
23
|
+
* Idiomatic call site is the very top of a Node worker's bootstrap:
|
|
24
|
+
*
|
|
25
|
+
* ```ts
|
|
26
|
+
* import { configureBPMClient } from '@rytass/bpm-core-client';
|
|
27
|
+
*
|
|
28
|
+
* configureBPMClient({
|
|
29
|
+
* baseUrl: 'https://api.shuttle.example.com',
|
|
30
|
+
* headers: { 'X-Service-Token': process.env.BPM_SYNC_TOKEN ?? '' },
|
|
31
|
+
* });
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* Browser consumers under Next.js typically do **not** need to call
|
|
35
|
+
* this — `NEXT_PUBLIC_API_URL` plus same-origin defaults cover the
|
|
36
|
+
* common case.
|
|
37
|
+
*/
|
|
38
|
+
function configureBPMClient(config) {
|
|
39
|
+
currentConfig = { ...config };
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Reads the active {@link BPMClientConfig}. Exposed primarily for tests
|
|
43
|
+
* and for inspecting the current override at runtime — consumers should
|
|
44
|
+
* use {@link configureBPMClient} to mutate, never reach in directly.
|
|
45
|
+
*/
|
|
46
|
+
function readBPMClientConfig() {
|
|
47
|
+
return currentConfig;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Resolves the effective `fetch` implementation honoring the active
|
|
51
|
+
* override, falling back to the global `fetch`.
|
|
52
|
+
*/
|
|
53
|
+
function resolveBPMFetch() {
|
|
54
|
+
return currentConfig.fetch ?? globalThis.fetch;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Returns the headers configured via {@link configureBPMClient}.
|
|
58
|
+
* Internal transports merge these into every outbound request.
|
|
59
|
+
*/
|
|
60
|
+
function readBPMConfiguredHeaders() {
|
|
61
|
+
return currentConfig.headers ?? {};
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=client-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-config.js","sourceRoot":"","sources":["../../../../../libs/bpm-core-client/src/lib/client-config.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;AA8DH,gDAEC;AAOD,kDAEC;AAMD,0CAEC;AAMD,4DAEC;AAjDD,IAAI,aAAa,GAAoB,EAAE,CAAC;AAExC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,SAAgB,kBAAkB,CAAC,MAAuB;IACxD,aAAa,GAAG,EAAE,GAAG,MAAM,EAAE,CAAC;AAChC,CAAC;AAED;;;;GAIG;AACH,SAAgB,mBAAmB;IACjC,OAAO,aAAa,CAAC;AACvB,CAAC;AAED;;;GAGG;AACH,SAAgB,eAAe;IAC7B,OAAO,aAAa,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC;AACjD,CAAC;AAED;;;GAGG;AACH,SAAgB,wBAAwB;IACtC,OAAO,aAAa,CAAC,OAAO,IAAI,EAAE,CAAC;AACrC,CAAC"}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.requestGraphQl = requestGraphQl;
|
|
4
4
|
exports.readGraphQlEndpoint = readGraphQlEndpoint;
|
|
5
5
|
exports.resolveDefaultGraphQlEndpoint = resolveDefaultGraphQlEndpoint;
|
|
6
|
+
const client_config_1 = require("./client-config");
|
|
6
7
|
const LOCAL_GRAPHQL_ENDPOINT = 'http://localhost:17603/graphql';
|
|
7
8
|
const SAME_ORIGIN_GRAPHQL_ENDPOINT = '/graphql';
|
|
8
9
|
/**
|
|
@@ -32,7 +33,8 @@ const SAME_ORIGIN_GRAPHQL_ENDPOINT = '/graphql';
|
|
|
32
33
|
* ```
|
|
33
34
|
*/
|
|
34
35
|
async function requestGraphQl(query, variables) {
|
|
35
|
-
const
|
|
36
|
+
const fetchImpl = (0, client_config_1.resolveBPMFetch)();
|
|
37
|
+
const response = await fetchImpl(readGraphQlEndpoint(), {
|
|
36
38
|
body: JSON.stringify({ query, variables }),
|
|
37
39
|
credentials: 'include',
|
|
38
40
|
headers: buildGraphQlHeaders(),
|
|
@@ -61,6 +63,12 @@ async function requestGraphQl(query, variables) {
|
|
|
61
63
|
* runtimes such as Node SSR).
|
|
62
64
|
*/
|
|
63
65
|
function readGraphQlEndpoint() {
|
|
66
|
+
const configured = (0, client_config_1.readBPMClientConfig)().baseUrl?.trim();
|
|
67
|
+
if (configured) {
|
|
68
|
+
return configured.endsWith('/graphql')
|
|
69
|
+
? configured
|
|
70
|
+
: `${configured.replace(/\/$/, '')}/graphql`;
|
|
71
|
+
}
|
|
64
72
|
return (readOptionalPublicEnvValue(process.env.NEXT_PUBLIC_API_URL) ??
|
|
65
73
|
resolveDefaultGraphQlEndpoint(readBrowserHostname()));
|
|
66
74
|
}
|
|
@@ -77,6 +85,7 @@ function resolveDefaultGraphQlEndpoint(hostname) {
|
|
|
77
85
|
}
|
|
78
86
|
function buildGraphQlHeaders() {
|
|
79
87
|
return {
|
|
88
|
+
...(0, client_config_1.readBPMConfiguredHeaders)(),
|
|
80
89
|
'Content-Type': 'application/json',
|
|
81
90
|
};
|
|
82
91
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graphql-client.js","sourceRoot":"","sources":["../../../../../libs/bpm-core-client/src/lib/graphql-client.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"graphql-client.js","sourceRoot":"","sources":["../../../../../libs/bpm-core-client/src/lib/graphql-client.ts"],"names":[],"mappings":";;AA4CA,wCA2BC;AAYD,kDAWC;AAQD,sEAMC;AA5GD,mDAIyB;AAEzB,MAAM,sBAAsB,GAAG,gCAAgC,CAAC;AAChE,MAAM,4BAA4B,GAAG,UAAU,CAAC;AAWhD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACI,KAAK,UAAU,cAAc,CAClC,KAAa,EACb,SAA6C;IAE7C,MAAM,SAAS,GAAG,IAAA,+BAAe,GAAE,CAAC;IACpC,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,mBAAmB,EAAE,EAAE;QACtD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QAC1C,WAAW,EAAE,SAAS;QACtB,OAAO,EAAE,mBAAmB,EAAE;QAC9B,MAAM,EAAE,MAAM;KACf,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,oCAAoC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAA2B,CAAC;IAElE,IAAI,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3E,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO,OAAO,CAAC,IAAI,CAAC;AACtB,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,mBAAmB;IACjC,MAAM,UAAU,GAAG,IAAA,mCAAmB,GAAE,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;IACzD,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC;YACpC,CAAC,CAAC,UAAU;YACZ,CAAC,CAAC,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC;IACjD,CAAC;IACD,OAAO,CACL,0BAA0B,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;QAC3D,6BAA6B,CAAC,mBAAmB,EAAE,CAAC,CACrD,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAgB,6BAA6B,CAC3C,QAAuB;IAEvB,OAAO,WAAW,CAAC,QAAQ,CAAC;QAC1B,CAAC,CAAC,sBAAsB;QACxB,CAAC,CAAC,4BAA4B,CAAC;AACnC,CAAC;AAED,SAAS,mBAAmB;IAC1B,OAAO;QACL,GAAG,IAAA,wCAAwB,GAAE;QAC7B,cAAc,EAAE,kBAAkB;KACnC,CAAC;AACJ,CAAC;AAED,SAAS,0BAA0B,CAAC,KAAyB;IAC3D,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC;AAC/B,CAAC;AAED,SAAS,mBAAmB;IAC1B,OAAO,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;AACzE,CAAC;AAED,SAAS,WAAW,CAAC,QAAuB;IAC1C,OAAO,QAAQ,KAAK,WAAW,IAAI,QAAQ,KAAK,WAAW,CAAC;AAC9D,CAAC"}
|