@mapples/request 1.6.0-beta.20260921105308 → 1.6.0-beta.20260929074057

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 CHANGED
@@ -1,17 +1,23 @@
1
1
  # @mapples/request
2
2
 
3
- ## 1.6.0-beta.20260921105308
3
+ ## 1.6.0-beta.20260929074057
4
4
 
5
5
  ### Minor Changes
6
6
 
7
+ - 517b1d4: API responses move to their own `@mapples/state` context (`ApiStateContextProvider`, `useApiState`), so `api.*` bindings resolve inside a nested `StateProvider` — a list row, a scoped data state — the way `vars.*` does; `validateApiDocument` now rejects a state key outside the `api.` namespace (`STATE_KEY_NAMESPACE`, `API_NAMESPACE`) and no longer reads an environment variable's `{{name}}` as the path token `{name`; it also rejects a request name that can't be a binding-path segment (`REQUEST_NAME_INVALID`, `API_REQUEST_NAME_PATTERN`) and an empty path (`PATH_EMPTY`). `@mapples/request` performs calls through a pluggable `RequestTransport` (`transport` prop, `createFetchTransport`), which receives `auth` unresolved so a forwarding transport never holds a secret. The runtime no longer fails silently: an unknown `requestId`, a path token that resolves to nothing, an undefined `{{variable}}`, a relative path without a base URL and an unconfigured secret all throw (`onRequestError` receives the resolution errors), an unresolved `state` source is no longer sent as the string `N/A`, and `event` sources read the event's first argument instead of the `staticData`-merged payload. `RequestProvider` drops its `state` prop.
8
+ - 4a8f1d8: `RequestProvider` takes `previewSamples` and `autoRun`. With `previewSamples`, every request that has a `responseSample` publishes it as a settled response (`status: 200`) until a real one arrives, so an editor preview shows bound data before anything has run. With `autoRun`, entering `fetch` mode emits a `mapples:request` for every GET that needs nothing from a trigger — `isAutoRunnable` (new export): params are literals or app state, never `event` / `data` / `route.*` — once per switch, through the action bus like a pressed element. Responses now belong to the mode that produced them: changing `mode` clears them, so leaving `fetch` returns to the samples. Both props default to off; a shipped app behaves as before.
9
+ - 132e4a8: Routes carry a flow of their own: a `path` with `:token` params (`/product/:id`), an `onEnter` action emitted on every focus, and an access `guard` with a fallback route. Params travel on the navigate action as literals or value sources (`data` reads the pressed list row, `state` any binding), land in a new `route.*` state namespace the screen binds, and reach root-mounted handlers through `ActiveRouteProvider` — so a request bound to `route.id` loads the product page. `resolveValueSource` is shared by the request and navigation runtimes, and the new `data` source kind reads an action's resolved data. The navigate action form gets one source field per route param, the AI catalog `set_route_path` / `set_route_guard` / `set_route_on_enter` and `add_connection` params.
7
10
  - a6c5872: All `@mapples/*` runtime packages now share one version and are versioned and published together from `mapplesorg/mapples-kit`; `mapples-open-kit` is a read-only mirror of the source.
8
11
 
9
12
  ### Patch Changes
10
13
 
14
+ - Updated dependencies [132e4a8]
15
+ - Updated dependencies [517b1d4]
16
+ - Updated dependencies [132e4a8]
11
17
  - Updated dependencies [a6c5872]
12
- - @mapples/action@1.6.0-beta.20260921105308
13
- - @mapples/state@1.6.0-beta.20260921105308
14
- - @mapples/types@1.6.0-beta.20260921105308
18
+ - @mapples/types@1.6.0-beta.20260929074057
19
+ - @mapples/state@1.6.0-beta.20260929074057
20
+ - @mapples/action@1.6.0-beta.20260929074057
15
21
 
16
22
  ## 0.1.0
17
23
 
package/README.md ADDED
@@ -0,0 +1,96 @@
1
+ # @mapples/request
2
+
3
+ Runtime for the Mapples `ApiDocument`: executes `mapples:request` actions, publishes each response as bindable state, and chains follow-up actions on the action bus.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @mapples/request
9
+ # or
10
+ yarn add @mapples/request
11
+ ```
12
+
13
+ Peer dependencies: `@mapples/action`, `@mapples/state`, `@mapples/types`, `lodash`, `react`, `rxjs`.
14
+
15
+ ## Usage
16
+
17
+ Mount the provider inside an `ActionProvider`, with the handler as a child:
18
+
19
+ ```tsx
20
+ import ActionProvider from '@mapples/action';
21
+ import { RequestActionHandler, RequestProvider } from '@mapples/request';
22
+
23
+ const App = () => (
24
+ <ActionProvider>
25
+ <RequestProvider document={apiDocument} mode="fetch" secrets={secrets}>
26
+ <RequestActionHandler />
27
+ {/* Your app components */}
28
+ </RequestProvider>
29
+ </ActionProvider>
30
+ );
31
+ ```
32
+
33
+ An element runs a request by emitting a `mapples:request` action:
34
+
35
+ ```ts
36
+ {
37
+ type: 'mapples:request',
38
+ staticData: {
39
+ requestId: '<id from the ApiDocument>',
40
+ onSuccess: { type: 'mapples:navigate', data: { routeName: 'Home' } },
41
+ onError: { type: 'mapples:navigate', data: { routeName: 'Error' } },
42
+ },
43
+ }
44
+ ```
45
+
46
+ ## Response state
47
+
48
+ A request's response lands under its state key — `api.<name>` by default, always inside the `api.` namespace:
49
+
50
+ | Binding | Value |
51
+ | -------------------- | ------------------------------------------- |
52
+ | `api.<name>.loading` | `true` while the request is in flight |
53
+ | `api.<name>.data` | The parsed JSON body (`null` when not JSON) |
54
+ | `api.<name>.error` | `HTTP <status>` or the failure message |
55
+ | `api.<name>.status` | The HTTP status |
56
+
57
+ Response state lives in its own context, so `api.*` bindings resolve the same anywhere in the tree — a nested `StateProvider` (a list row, a scoped data state) doesn't shadow them.
58
+
59
+ ## Value sources
60
+
61
+ Path tokens, query parameters and JSON body leaves take an `ApiValueSource`:
62
+
63
+ - `{ kind: 'static', value }` — a literal.
64
+ - `{ kind: 'state', dataProp }` — a `@mapples/state` path, resolved where the handler is mounted (`vars.*`, `api.*`, root data state).
65
+ - `{ kind: 'event', path? }` — the triggering event's first argument (form values, input text); `path` narrows into it.
66
+ - `{ kind: 'data', path? }` — the action's resolved data (`Action.payload.data`): the pressed list row when the element's action binds `(this)`, or the route's params when a screen's `onEnter` runs the request; `path` narrows into it. The way a row-scoped value reaches a request — a `state` source resolves where the handler is mounted, above the list.
67
+
68
+ A request a screen runs on enter (`RouteNode.onEnter`) binds its path token to the route param: `{ kind: 'state', dataProp: 'route.id' }` for `/product/:id` → `GET /products/{id}`. The resolver is `resolveValueSource` from `@mapples/state`, shared with the navigation runtime's route params.
69
+
70
+ ## Modes
71
+
72
+ - `sample` (default) resolves the request's `responseSample` after a short delay. No call is made and the url is not resolved.
73
+ - `fetch` performs the call through the transport.
74
+
75
+ ## Transport
76
+
77
+ `fetch` mode calls a `RequestTransport`. The default is a direct `fetch` that resolves `auth.secretRef` against the `secrets` prop. Supply your own to route calls elsewhere — a backend proxy, for example — without the runtime knowing about it:
78
+
79
+ ```tsx
80
+ const transport: RequestTransport = async (request) => {
81
+ // request: { requestId, method, url, headers, body?, auth? }
82
+ return { status, ok, headers, data };
83
+ };
84
+
85
+ <RequestProvider document={apiDocument} mode="fetch" transport={transport} />;
86
+ ```
87
+
88
+ `auth` reaches the transport unresolved (it carries the secret's name), so a forwarding transport never holds the secret's value.
89
+
90
+ ## Errors
91
+
92
+ Nothing fails silently:
93
+
94
+ - A `mapples:request` action with an unknown `requestId`, a path token that resolves to nothing, an undefined `{{variable}}`, or a relative path with no environment base URL throws. Pass `onRequestError` to receive those; without it they surface as uncaught errors.
95
+ - A secret that isn't configured rejects the call — the request never goes out unauthenticated.
96
+ - A rejected transport sets `api.<name>.error`, emits `onError`, and never emits `onSuccess`.
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Bridges the `@mapples/action` store to request execution: subscribes to
3
3
  * emitted actions, resolves `mapples:request` actions into commands, executes
4
- * them (sample or real fetch), stores responses via the surrounding
4
+ * them (sample, or the runtime's transport), stores responses via the surrounding
5
5
  * `RequestProvider`, and re-emits `onSuccess`/`onError` follow-up actions
6
6
  * (e.g. `mapples:navigate`) onto the same bus. Renders nothing.
7
7
  *
@@ -1 +1 @@
1
- {"version":3,"file":"RequestActionHandler.d.ts","sourceRoot":"","sources":["../src/RequestActionHandler.tsx"],"names":[],"mappings":"AAWA;;;;;;;;GAQG;AACH,QAAA,MAAM,oBAAoB,YAuFzB,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
1
+ {"version":3,"file":"RequestActionHandler.d.ts","sourceRoot":"","sources":["../src/RequestActionHandler.tsx"],"names":[],"mappings":"AAiBA;;;;;;;;GAQG;AACH,QAAA,MAAM,oBAAoB,YA8GzB,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
@@ -1,14 +1,15 @@
1
- import { useEffect } from 'react';
1
+ import { useEffect, useRef } from 'react';
2
2
  import { useActionStore } from '@mapples/action';
3
3
  import { useDataState } from '@mapples/state';
4
- import { toRequestCommand } from './actionCommands';
4
+ import { isAutoRunnable, toRequestCommand, toTransportRequest, } from './actionCommands';
5
+ import { RequestActionType } from './constants';
5
6
  import { useRequestRuntime } from './RequestProvider';
6
7
  /** Artificial latency for sample mode so loading states are visible. */
7
8
  const SAMPLE_DELAY_MS = 500;
8
9
  /**
9
10
  * Bridges the `@mapples/action` store to request execution: subscribes to
10
11
  * emitted actions, resolves `mapples:request` actions into commands, executes
11
- * them (sample or real fetch), stores responses via the surrounding
12
+ * them (sample, or the runtime's transport), stores responses via the surrounding
12
13
  * `RequestProvider`, and re-emits `onSuccess`/`onError` follow-up actions
13
14
  * (e.g. `mapples:navigate`) onto the same bus. Renders nothing.
14
15
  *
@@ -21,7 +22,7 @@ const RequestActionHandler = () => {
21
22
  useEffect(() => {
22
23
  if (!runtime?.document)
23
24
  return;
24
- const { document, mode, secrets, setResponse } = runtime;
25
+ const { document, mode, transport, onRequestError, setResponse } = runtime;
25
26
  const emitFollowUp = (followUp) => {
26
27
  if (!followUp?.type)
27
28
  return;
@@ -45,33 +46,21 @@ const RequestActionHandler = () => {
45
46
  return;
46
47
  }
47
48
  try {
48
- const response = await fetch(command.url, {
49
- method: command.method,
50
- headers: command.headers,
51
- body: command.body !== undefined
52
- ? JSON.stringify(command.body)
53
- : undefined,
54
- });
55
- // Only bodies that declare JSON are parsed. A body that claims JSON and
56
- // fails to parse is a broken server contract, so the parse error is left
57
- // to reach the handler below instead of quietly becoming `null` data.
58
- const contentType = response.headers.get('content-type') ?? '';
59
- const data = contentType.includes('json')
60
- ? await response.json()
61
- : null;
49
+ const response = await transport(toTransportRequest(command));
62
50
  setResponse(command.stateKey, {
63
51
  loading: false,
64
- data,
52
+ data: response.data,
65
53
  status: response.status,
66
54
  error: response.ok ? undefined : `HTTP ${response.status}`,
67
55
  });
68
56
  emitFollowUp(response.ok ? command.onSuccess : command.onError);
69
57
  }
70
58
  catch (error) {
71
- // A network/CORS/parse failure is a failed request. It is reported as
72
- // one: no sample data is substituted for the real response, and only
73
- // the configured error follow-up runs — never `onSuccess`, which would
74
- // advance the flow as if the request had worked.
59
+ // A rejected transport (network, CORS, parse, an unconfigured secret)
60
+ // is a failed request. It is reported as one: no sample data is
61
+ // substituted for the real response, and only the configured error
62
+ // follow-up runs — never `onSuccess`, which would advance the flow as
63
+ // if the request had worked.
75
64
  setResponse(command.stateKey, {
76
65
  loading: false,
77
66
  data: null,
@@ -81,16 +70,56 @@ const RequestActionHandler = () => {
81
70
  }
82
71
  };
83
72
  const subscription = actionStore.subscribe((action) => {
84
- const command = toRequestCommand(action, document, {
85
- getStateValue: (path) => getValue({ key: path, active: true }),
86
- secrets,
87
- });
73
+ let command;
74
+ try {
75
+ command = toRequestCommand(action, document, {
76
+ // `null`, not `getValue`'s display default: an unresolved source
77
+ // must not go out as the literal string "N/A".
78
+ getStateValue: (path) => getValue({ key: path, active: true }, null),
79
+ sample: mode === 'sample',
80
+ });
81
+ }
82
+ catch (error) {
83
+ // The action named a request that can't be built. The host surfaces
84
+ // it; with no host handler it stays an uncaught error.
85
+ if (!onRequestError)
86
+ throw error;
87
+ onRequestError(error, action);
88
+ return;
89
+ }
88
90
  if (!command)
89
91
  return;
90
92
  void execute(command);
91
93
  });
92
94
  return () => subscription.unsubscribe();
93
95
  }, [actionStore, getValue, runtime]);
96
+ // Entering `fetch` mode runs the auto-runnable GETs once, through the bus
97
+ // so they take the same path as a pressed element. Declared after the
98
+ // subscription so it is in place when these are emitted; the ref keeps a
99
+ // document edit (a new runtime value) from running them again.
100
+ const mode = runtime?.mode;
101
+ const autoRun = !!runtime?.autoRun && !!runtime.document;
102
+ const ranForMode = useRef(null);
103
+ useEffect(() => {
104
+ if (!autoRun || mode !== 'fetch') {
105
+ ranForMode.current = null;
106
+ return;
107
+ }
108
+ if (ranForMode.current === mode)
109
+ return;
110
+ ranForMode.current = mode;
111
+ for (const request of Object.values(runtime.document.requests)) {
112
+ if (!isAutoRunnable(request))
113
+ continue;
114
+ actionStore.next({
115
+ time: Date.now(),
116
+ type: RequestActionType.Execute,
117
+ payload: { data: { requestId: request.id } },
118
+ });
119
+ }
120
+ // Only a mode change (or the runtime becoming able to run) re-runs them.
121
+ // eslint-disable-next-line react-hooks/exhaustive-deps
122
+ }, [actionStore, autoRun, mode]);
94
123
  return null;
95
124
  };
96
125
  export default RequestActionHandler;
@@ -1 +1 @@
1
- {"version":3,"file":"RequestActionHandler.js","sourceRoot":"","sources":["../src/RequestActionHandler.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"RequestActionHandler.js","sourceRoot":"","sources":["../src/RequestActionHandler.tsx"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { FC, PropsWithChildren } from 'react';
2
- import { ApiDocument } from '@mapples/types';
2
+ import { Action, ApiDocument } from '@mapples/types';
3
+ import { RequestTransport } from './transport';
3
4
  /** Per-request response state, exposed to bindings under the state key. */
4
5
  export interface ResponseState {
5
6
  loading: boolean;
@@ -11,23 +12,51 @@ export type RequestExecutionMode = 'sample' | 'fetch';
11
12
  export interface RequestRuntimeContextType {
12
13
  document: ApiDocument | null;
13
14
  mode: RequestExecutionMode;
14
- secrets?: Record<string, string>;
15
+ transport: RequestTransport;
16
+ onRequestError?: (error: Error, action: Action) => void;
17
+ /** See {@link RequestProviderProps.autoRun}. */
18
+ autoRun: boolean;
15
19
  setResponse: (stateKey: string, state: ResponseState) => void;
16
20
  }
17
21
  export declare const useRequestRuntime: () => RequestRuntimeContextType | null;
18
22
  export interface RequestProviderProps {
19
23
  document?: ApiDocument | null;
20
- /** Base state the responses are merged over. */
21
- state?: object;
22
24
  /** `sample` resolves `responseSample`s; `fetch` performs real requests. */
23
25
  mode?: RequestExecutionMode;
26
+ /**
27
+ * Performs the call in `fetch` mode. Defaults to a direct `fetch` resolving
28
+ * auth against {@link secrets}; a host that must not call third parties
29
+ * itself (a browser editor behind CORS) routes through its own backend here.
30
+ */
31
+ transport?: RequestTransport;
32
+ /** Secrets by `secretRef` for the default transport — never stored. */
24
33
  secrets?: Record<string, string>;
34
+ /**
35
+ * Receives a `mapples:request` action that could not become a request (an
36
+ * unknown request id, an unbound path token). Without it the error is
37
+ * thrown from the action subscription.
38
+ */
39
+ onRequestError?: (error: Error, action: Action) => void;
40
+ /**
41
+ * Seed every request that has a `responseSample` with it, as a settled
42
+ * response, until a real one arrives — so an editor preview shows bound
43
+ * data before any request has run. Off in a shipped app: a sample is
44
+ * design-time data, not a response.
45
+ */
46
+ previewSamples?: boolean;
47
+ /**
48
+ * In `fetch` mode, run every GET request that needs nothing from a
49
+ * triggering action once when the runtime enters `fetch` mode (see
50
+ * `isAutoRunnable`) — the editor's "Live data" switch.
51
+ */
52
+ autoRun?: boolean;
25
53
  }
26
54
  /**
27
- * Holds API response state and republishes it through `@mapples/state`, so
28
- * bindings like `api.login.data.user.name` and conditions like
29
- * `api.login.loading::eq::true` resolve with zero changes to the state
30
- * package. Pair with `RequestActionHandler` (rendered as a child) to execute
55
+ * Holds API response state and publishes it through the `@mapples/state` API
56
+ * context, so bindings like `api.login.data.user.name` and conditions like
57
+ * `api.login.loading::eq::true` resolve anywhere in the tree — a nested
58
+ * `StateProvider` (a frame's data state, a list row) doesn't shadow them.
59
+ * Pair with `RequestActionHandler` (rendered as a child) to execute
31
60
  * `mapples:request` actions.
32
61
  */
33
62
  declare const RequestProvider: FC<PropsWithChildren<RequestProviderProps>>;
@@ -1 +1 @@
1
- {"version":3,"file":"RequestProvider.d.ts","sourceRoot":"","sources":["../src/RequestProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,EAAE,EACF,iBAAiB,EAKlB,MAAM,OAAO,CAAC;AAGf,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C,2EAA2E;AAC3E,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEtD,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAC;IAC7B,IAAI,EAAE,oBAAoB,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;CAC/D;AAMD,eAAO,MAAM,iBAAiB,wCAA0C,CAAC;AAEzE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC9B,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED;;;;;;GAMG;AACH,QAAA,MAAM,eAAe,EAAE,EAAE,CAAC,iBAAiB,CAAC,oBAAoB,CAAC,CAoChE,CAAC;AAEF,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"RequestProvider.d.ts","sourceRoot":"","sources":["../src/RequestProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,EAAE,EACF,iBAAiB,EAKlB,MAAM,OAAO,CAAC;AAGf,OAAO,EACL,MAAM,EAEN,WAAW,EAEZ,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAwB,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAErE,2EAA2E;AAC3E,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEtD,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAC;IAC7B,IAAI,EAAE,oBAAoB,CAAC;IAC3B,SAAS,EAAE,gBAAgB,CAAC;IAC5B,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxD,gDAAgD;IAChD,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;CAC/D;AAMD,eAAO,MAAM,iBAAiB,wCAA0C,CAAC;AAEzE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC9B,2EAA2E;IAC3E,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B;;;;OAIG;IACH,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxD;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAID;;;;;;;GAOG;AACH,QAAA,MAAM,eAAe,EAAE,EAAE,CAAC,iBAAiB,CAAC,oBAAoB,CAAC,CAgFhE,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -1,32 +1,71 @@
1
1
  import { createContext, useCallback, useContext, useMemo, useState, } from 'react';
2
- import StateProvider from '@mapples/state';
3
- import { cloneDeep, set } from 'lodash';
2
+ import { ApiStateContextProvider } from '@mapples/state';
3
+ import { API_NAMESPACE, apiRequestStateKey, } from '@mapples/types';
4
+ import { set } from 'lodash';
5
+ import { createFetchTransport } from './transport';
4
6
  const RequestRuntimeContext = createContext(null);
5
7
  export const useRequestRuntime = () => useContext(RequestRuntimeContext);
8
+ const STATE_KEY_PREFIX = `${API_NAMESPACE}.`;
6
9
  /**
7
- * Holds API response state and republishes it through `@mapples/state`, so
8
- * bindings like `api.login.data.user.name` and conditions like
9
- * `api.login.loading::eq::true` resolve with zero changes to the state
10
- * package. Pair with `RequestActionHandler` (rendered as a child) to execute
10
+ * Holds API response state and publishes it through the `@mapples/state` API
11
+ * context, so bindings like `api.login.data.user.name` and conditions like
12
+ * `api.login.loading::eq::true` resolve anywhere in the tree — a nested
13
+ * `StateProvider` (a frame's data state, a list row) doesn't shadow them.
14
+ * Pair with `RequestActionHandler` (rendered as a child) to execute
11
15
  * `mapples:request` actions.
12
16
  */
13
- const RequestProvider = ({ children, document = null, state, mode = 'sample', secrets, }) => {
17
+ const RequestProvider = ({ children, document = null, mode = 'sample', transport, secrets, onRequestError, previewSamples = false, autoRun = false, }) => {
14
18
  const [responses, setResponses] = useState({});
19
+ // Responses belong to the mode that produced them: leaving `fetch` must not
20
+ // keep showing live data as if it were the preview, nor the reverse.
21
+ const [responsesMode, setResponsesMode] = useState(mode);
22
+ if (mode !== responsesMode) {
23
+ setResponsesMode(mode);
24
+ setResponses({});
25
+ }
15
26
  const setResponse = useCallback((stateKey, response) => {
16
27
  setResponses((prev) => ({ ...prev, [stateKey]: response }));
17
28
  }, []);
18
- // State keys are dot paths (`api.login`) — expand them into the nested
19
- // object shape @mapples/state resolves against.
20
- const mergedState = useMemo(() => {
21
- const result = cloneDeep(state ?? {});
22
- for (const [stateKey, response] of Object.entries(responses)) {
23
- set(result, stateKey, response);
29
+ // State keys are dot paths under the namespace (`api.login`) — expand the
30
+ // remainder into the nested object shape bindings resolve against.
31
+ const apiState = useMemo(() => {
32
+ const samples = {};
33
+ if (previewSamples && document) {
34
+ for (const request of Object.values(document.requests)) {
35
+ if (request.responseSample === undefined)
36
+ continue;
37
+ samples[apiRequestStateKey(request)] = {
38
+ loading: false,
39
+ data: request.responseSample,
40
+ status: 200,
41
+ };
42
+ }
43
+ }
44
+ const result = {};
45
+ for (const [stateKey, response] of Object.entries({
46
+ ...samples,
47
+ ...responses,
48
+ })) {
49
+ if (!stateKey.startsWith(STATE_KEY_PREFIX)) {
50
+ throw new Error(`State key "${stateKey}" is outside the "${API_NAMESPACE}" namespace`);
51
+ }
52
+ set(result, stateKey.slice(STATE_KEY_PREFIX.length), response);
24
53
  }
25
54
  return result;
26
- }, [responses, state]);
27
- const contextValue = useMemo(() => ({ document, mode, secrets, setResponse }), [document, mode, secrets, setResponse]);
55
+ }, [document, previewSamples, responses]);
56
+ const resolvedTransport = useMemo(() => transport ?? createFetchTransport(secrets), [transport, secrets]);
57
+ const contextValue = useMemo(() => ({
58
+ document,
59
+ mode,
60
+ transport: resolvedTransport,
61
+ onRequestError,
62
+ autoRun,
63
+ setResponse,
64
+ }), [document, mode, resolvedTransport, onRequestError, autoRun, setResponse]);
28
65
  return (<RequestRuntimeContext value={contextValue}>
29
- <StateProvider state={mergedState}>{children}</StateProvider>
66
+ <ApiStateContextProvider value={apiState}>
67
+ {children}
68
+ </ApiStateContextProvider>
30
69
  </RequestRuntimeContext>);
31
70
  };
32
71
  export default RequestProvider;
@@ -1 +1 @@
1
- {"version":3,"file":"RequestProvider.js","sourceRoot":"","sources":["../src/RequestProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EAGb,WAAW,EACX,UAAU,EACV,OAAO,EACP,QAAQ,GACT,MAAM,OAAO,CAAC;AAEf,OAAO,aAAa,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAmBxC,MAAM,qBAAqB,GAAG,aAAa,CACzC,IAAI,CACL,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,qBAAqB,CAAC,CAAC;AAWzE;;;;;;GAMG;AACH,MAAM,eAAe,GAAgD,CAAC,EACpE,QAAQ,EACR,QAAQ,GAAG,IAAI,EACf,KAAK,EACL,IAAI,GAAG,QAAQ,EACf,OAAO,GACR,EAAE,EAAE;IACH,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAgC,EAAE,CAAC,CAAC;IAE9E,MAAM,WAAW,GAAG,WAAW,CAC7B,CAAC,QAAgB,EAAE,QAAuB,EAAE,EAAE;QAC5C,YAAY,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC9D,CAAC,EACD,EAAE,CACH,CAAC;IAEF,uEAAuE;IACvE,gDAAgD;IAChD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE;QAC/B,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;QACtC,KAAK,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7D,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAClC,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;IAEvB,MAAM,YAAY,GAAG,OAAO,CAC1B,GAAG,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,EAChD,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,CAAC,CACvC,CAAC;IAEF,OAAO,CACL,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CACzC;MAAA,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,aAAa,CAC9D;IAAA,EAAE,qBAAqB,CAAC,CACzB,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"RequestProvider.js","sourceRoot":"","sources":["../src/RequestProvider.tsx"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
- import { Action, ApiDocument, HttpMethod } from '@mapples/types';
1
+ import { Action, ApiDocument, ApiRequest, HttpMethod } from '@mapples/types';
2
+ import { TransportAuth, TransportRequest } from './transport';
2
3
  /** A follow-up action re-emitted after the request settles. */
3
4
  export interface FollowUpAction {
4
5
  type: string;
@@ -12,6 +13,8 @@ export interface RequestCommand {
12
13
  method: HttpMethod;
13
14
  headers: Record<string, string>;
14
15
  body?: unknown;
16
+ /** Left unresolved: the transport that performs the call owns the secret. */
17
+ auth?: TransportAuth;
15
18
  responseSample?: unknown;
16
19
  onSuccess?: FollowUpAction;
17
20
  onError?: FollowUpAction;
@@ -20,13 +23,27 @@ export interface RequestCommand {
20
23
  export interface RequestResolutionContext {
21
24
  /** Resolves `state`-kind value sources (a `@mapples/state` lookup). */
22
25
  getStateValue?: (path: string) => unknown;
23
- /** Secrets by `secretRef`, resolved by the host — never stored. */
24
- secrets?: Record<string, string>;
26
+ /**
27
+ * Sample execution never performs the call, so the url is left as the
28
+ * request's unresolved path: a preview must not fail on a value that only
29
+ * exists at runtime (a path token bound to a list row, say).
30
+ */
31
+ sample?: boolean;
25
32
  }
26
33
  /**
27
- * Maps a `mapples:request` action to an executable {@link RequestCommand} —
28
- * pure and unit-testable; returns null for anything else or when the request
29
- * id doesn't resolve.
34
+ * Maps a `mapples:request` action to an executable {@link RequestCommand}.
35
+ * Pure. Returns null for any other action type; a `mapples:request` action
36
+ * that names no request, or one the document doesn't hold, throws — a press
37
+ * that silently does nothing is a wiring defect nobody can see.
30
38
  */
31
39
  export declare const toRequestCommand: (action: Action, document: ApiDocument, context?: RequestResolutionContext) => RequestCommand | null;
40
+ /** The part of a {@link RequestCommand} a transport performs. */
41
+ export declare const toTransportRequest: (command: RequestCommand) => TransportRequest;
42
+ /**
43
+ * Whether a request can run with no triggering action: a GET whose params
44
+ * are all literals or app state. An `event` / `data` source only exists when
45
+ * an element fires the request, and `route.*` only once a screen is entered,
46
+ * so those wait for their trigger.
47
+ */
48
+ export declare const isAutoRunnable: (request: ApiRequest) => boolean;
32
49
  //# sourceMappingURL=actionCommands.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"actionCommands.d.ts","sourceRoot":"","sources":["../src/actionCommands.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,WAAW,EAIX,UAAU,EACX,MAAM,gBAAgB,CAAC;AAKxB,+DAA+D;AAC/D,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,kDAAkD;AAClD,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,OAAO,CAAC,EAAE,cAAc,CAAC;CAC1B;AAED,yDAAyD;AACzD,MAAM,WAAW,wBAAwB;IACvC,uEAAuE;IACvE,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IAC1C,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AA2FD;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,MAAM,EACd,UAAU,WAAW,EACrB,UAAS,wBAA6B,KACrC,cAAc,GAAG,IAiEnB,CAAC"}
1
+ {"version":3,"file":"actionCommands.d.ts","sourceRoot":"","sources":["../src/actionCommands.ts"],"names":[],"mappings":"AACA,OAAO,EACL,MAAM,EACN,WAAW,EACX,UAAU,EAGV,UAAU,EACX,MAAM,gBAAgB,CAAC;AAIxB,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE9D,+DAA+D;AAC/D,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,kDAAkD;AAClD,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,6EAA6E;IAC7E,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,OAAO,CAAC,EAAE,cAAc,CAAC;CAC1B;AAED,yDAAyD;AACzD,MAAM,WAAW,wBAAwB;IACvC,uEAAuE;IACvE,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IAC1C;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAsGD;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,MAAM,EACd,UAAU,WAAW,EACrB,UAAS,wBAA6B,KACrC,cAAc,GAAG,IA2EnB,CAAC;AAEF,iEAAiE;AACjE,eAAO,MAAM,kBAAkB,GAC7B,SAAS,cAAc,KACtB,gBAOD,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,SAAS,UAAU,KAAG,OAMlD,CAAC"}
@@ -1,20 +1,8 @@
1
+ import { isValueSource, resolveValueSource } from '@mapples/state';
1
2
  import { apiRequestStateKey, } from '@mapples/types';
2
- import { get, isPlainObject } from 'lodash';
3
+ import { isPlainObject } from 'lodash';
3
4
  import { RequestActionType } from './constants';
4
- const isValueSource = (value) => isPlainObject(value) &&
5
- ['static', 'state', 'event'].includes(value.kind ?? '');
6
- const resolveSource = (source, action, context) => {
7
- switch (source.kind) {
8
- case 'static':
9
- return source.value;
10
- case 'state':
11
- return context.getStateValue?.(source.dataProp);
12
- case 'event': {
13
- const payload = action.payload?.data;
14
- return source.path ? get(payload, source.path) : payload;
15
- }
16
- }
17
- };
5
+ const resolveSource = (source, action, context) => resolveValueSource(source, action, context.getStateValue);
18
6
  const resolveTemplate = (template, action, context) => {
19
7
  if (isValueSource(template)) {
20
8
  return resolveSource(template, action, context);
@@ -31,25 +19,46 @@ const resolveTemplate = (template, action, context) => {
31
19
  }
32
20
  return template;
33
21
  };
34
- /** Interpolates `{{variable}}` templates from environment variables. */
35
- const interpolate = (input, variables) => input.replace(/\{\{([^}]+)\}\}/g, (match, name) => {
22
+ /**
23
+ * Interpolates `{{variable}}` templates from environment variables. A
24
+ * variable the environment doesn't define throws: left in place it would go
25
+ * out as a literal `{{name}}` in the url or a header.
26
+ */
27
+ const interpolate = (input, variables) => input.replace(/\{\{([^}]+)\}\}/g, (_match, name) => {
36
28
  const value = variables?.[name.trim()];
37
- return value !== undefined ? value : match;
29
+ if (value === undefined) {
30
+ throw new Error(`Environment variable "${name.trim()}" is not defined`);
31
+ }
32
+ return value;
38
33
  });
39
34
  const buildUrl = (request, baseUrl, variables, action, context) => {
40
35
  let path = interpolate(request.path, variables);
41
36
  const query = [];
42
37
  for (const [key, source] of Object.entries(request.params ?? {})) {
43
38
  const value = resolveSource(source, action, context);
44
- const encoded = encodeURIComponent(String(value ?? ''));
45
- if (path.includes(`{${key}}`)) {
39
+ const isPathToken = path.includes(`{${key}}`);
40
+ if (value === undefined || value === null) {
41
+ // `/users/` is a different endpoint from `/users/{id}`: a path token
42
+ // that resolves to nothing fails the request. A query parameter with no
43
+ // value is simply left out.
44
+ if (isPathToken) {
45
+ throw new Error(`Path token "{${key}}" of API request "${request.name}" resolved to nothing`);
46
+ }
47
+ continue;
48
+ }
49
+ const encoded = encodeURIComponent(String(value));
50
+ if (isPathToken) {
46
51
  path = path.replaceAll(`{${key}}`, encoded);
47
52
  }
48
53
  else {
49
54
  query.push(`${encodeURIComponent(key)}=${encoded}`);
50
55
  }
51
56
  }
52
- const absolute = /^https?:\/\//i.test(path)
57
+ const isAbsolute = /^https?:\/\//i.test(path);
58
+ if (!isAbsolute && !baseUrl) {
59
+ throw new Error(`API request "${request.name}" has a relative path and no environment base URL`);
60
+ }
61
+ const absolute = isAbsolute
53
62
  ? path
54
63
  : `${interpolate(baseUrl, variables).replace(/\/$/, '')}${path.startsWith('/') ? '' : '/'}${path}`;
55
64
  return query.length > 0
@@ -57,19 +66,22 @@ const buildUrl = (request, baseUrl, variables, action, context) => {
57
66
  : absolute;
58
67
  };
59
68
  /**
60
- * Maps a `mapples:request` action to an executable {@link RequestCommand} —
61
- * pure and unit-testable; returns null for anything else or when the request
62
- * id doesn't resolve.
69
+ * Maps a `mapples:request` action to an executable {@link RequestCommand}.
70
+ * Pure. Returns null for any other action type; a `mapples:request` action
71
+ * that names no request, or one the document doesn't hold, throws — a press
72
+ * that silently does nothing is a wiring defect nobody can see.
63
73
  */
64
74
  export const toRequestCommand = (action, document, context = {}) => {
65
75
  if (action.type !== RequestActionType.Execute)
66
76
  return null;
67
77
  const data = (action.payload?.data ?? {});
68
- if (!data.requestId)
69
- return null;
78
+ if (!data.requestId) {
79
+ throw new Error(`A "${RequestActionType.Execute}" action has no requestId`);
80
+ }
70
81
  const request = document.requests[data.requestId];
71
- if (!request)
72
- return null;
82
+ if (!request) {
83
+ throw new Error(`API request "${data.requestId}" is not in the document`);
84
+ }
73
85
  const environment = (document.activeEnvironmentId
74
86
  ? document.environments[document.activeEnvironmentId]
75
87
  : undefined) ?? Object.values(document.environments)[0];
@@ -78,19 +90,21 @@ export const toRequestCommand = (action, document, context = {}) => {
78
90
  ...environment?.headers,
79
91
  ...request.headers,
80
92
  };
81
- for (const [key, value] of Object.entries(headers)) {
82
- headers[key] = interpolate(value, variables);
93
+ if (!context.sample) {
94
+ for (const [key, value] of Object.entries(headers)) {
95
+ headers[key] = interpolate(value, variables);
96
+ }
83
97
  }
84
- if (request.auth && request.auth.kind !== 'none' && request.auth.secretRef) {
85
- const secret = context.secrets?.[request.auth.secretRef];
86
- if (secret !== undefined) {
87
- if (request.auth.kind === 'bearer') {
88
- headers.Authorization = `Bearer ${secret}`;
89
- }
90
- else {
91
- headers[request.auth.header ?? 'Authorization'] = secret;
92
- }
98
+ let auth;
99
+ if (request.auth && request.auth.kind !== 'none') {
100
+ if (!request.auth.secretRef) {
101
+ throw new Error(`API request "${request.name}" auth has no secretRef`);
93
102
  }
103
+ auth = {
104
+ kind: request.auth.kind,
105
+ header: request.auth.header,
106
+ secretRef: request.auth.secretRef,
107
+ };
94
108
  }
95
109
  const body = request.body
96
110
  ? resolveTemplate(request.body.template, action, context)
@@ -101,13 +115,34 @@ export const toRequestCommand = (action, document, context = {}) => {
101
115
  return {
102
116
  requestId: request.id,
103
117
  stateKey: apiRequestStateKey(request),
104
- url: buildUrl(request, environment?.baseUrl ?? '', variables, action, context),
118
+ url: context.sample
119
+ ? request.path
120
+ : buildUrl(request, environment?.baseUrl ?? '', variables, action, context),
105
121
  method: request.method,
106
122
  headers,
107
123
  body,
124
+ auth,
108
125
  responseSample: request.responseSample,
109
126
  onSuccess: data.onSuccess,
110
127
  onError: data.onError,
111
128
  };
112
129
  };
130
+ /** The part of a {@link RequestCommand} a transport performs. */
131
+ export const toTransportRequest = (command) => ({
132
+ requestId: command.requestId,
133
+ method: command.method,
134
+ url: command.url,
135
+ headers: command.headers,
136
+ body: command.body,
137
+ auth: command.auth,
138
+ });
139
+ /**
140
+ * Whether a request can run with no triggering action: a GET whose params
141
+ * are all literals or app state. An `event` / `data` source only exists when
142
+ * an element fires the request, and `route.*` only once a screen is entered,
143
+ * so those wait for their trigger.
144
+ */
145
+ export const isAutoRunnable = (request) => request.method === 'GET' &&
146
+ Object.values(request.params ?? {}).every((source) => source.kind === 'static' ||
147
+ (source.kind === 'state' && !source.dataProp.startsWith('route.')));
113
148
  //# sourceMappingURL=actionCommands.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"actionCommands.js","sourceRoot":"","sources":["../src/actionCommands.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"actionCommands.js","sourceRoot":"","sources":["../src/actionCommands.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,12 +1,15 @@
1
1
  /**
2
2
  * @fileoverview Runtime for the Mapples `ApiDocument`: executes
3
- * `mapples:request` actions (sample or real fetch), publishes responses into
4
- * `@mapples/state`, and chains follow-up actions on the action bus.
3
+ * `mapples:request` actions (sample, or a real call through a pluggable
4
+ * transport), publishes responses into the `@mapples/state` API context, and
5
+ * chains follow-up actions on the action bus.
5
6
  */
6
7
  export { default as RequestProvider } from './RequestProvider';
7
8
  export { useRequestRuntime } from './RequestProvider';
8
9
  export type { RequestExecutionMode, RequestProviderProps, RequestRuntimeContextType, ResponseState, } from './RequestProvider';
9
10
  export { default as RequestActionHandler } from './RequestActionHandler';
11
+ export { createFetchTransport } from './transport';
12
+ export type { RequestTransport, TransportAuth, TransportRequest, TransportResponse, } from './transport';
10
13
  export * from './actionCommands';
11
14
  export * from './constants';
12
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,YAAY,EACV,oBAAoB,EACpB,oBAAoB,EACpB,yBAAyB,EACzB,aAAa,GACd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAEzE,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,YAAY,EACV,oBAAoB,EACpB,oBAAoB,EACpB,yBAAyB,EACzB,aAAa,GACd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAEzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,YAAY,EACV,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,aAAa,CAAC;AAErB,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -1,11 +1,13 @@
1
1
  /**
2
2
  * @fileoverview Runtime for the Mapples `ApiDocument`: executes
3
- * `mapples:request` actions (sample or real fetch), publishes responses into
4
- * `@mapples/state`, and chains follow-up actions on the action bus.
3
+ * `mapples:request` actions (sample, or a real call through a pluggable
4
+ * transport), publishes responses into the `@mapples/state` API context, and
5
+ * chains follow-up actions on the action bus.
5
6
  */
6
7
  export { default as RequestProvider } from './RequestProvider';
7
8
  export { useRequestRuntime } from './RequestProvider';
8
9
  export { default as RequestActionHandler } from './RequestActionHandler';
10
+ export { createFetchTransport } from './transport';
9
11
  export * from './actionCommands';
10
12
  export * from './constants';
11
13
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAOtD,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAEzE,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAOtD,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAEzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAQnD,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC"}
@@ -0,0 +1,43 @@
1
+ import { HttpMethod } from '@mapples/types';
2
+ /** Auth a transport applies to the outgoing request. */
3
+ export interface TransportAuth {
4
+ kind: 'bearer' | 'header';
5
+ /** Header name for `kind: 'header'` (defaults to `Authorization`). */
6
+ header?: string;
7
+ /** Name of the secret; the transport owns the lookup. */
8
+ secretRef: string;
9
+ }
10
+ /**
11
+ * A resolved request as a transport receives it. `auth` still carries the
12
+ * secret's *name*: whoever performs the call resolves it, so a transport that
13
+ * forwards to a server never holds the secret's value.
14
+ */
15
+ export interface TransportRequest {
16
+ requestId: string;
17
+ method: HttpMethod;
18
+ url: string;
19
+ headers: Record<string, string>;
20
+ body?: unknown;
21
+ auth?: TransportAuth;
22
+ }
23
+ export interface TransportResponse {
24
+ status: number;
25
+ /** Whether the status is in the 2xx range. */
26
+ ok: boolean;
27
+ headers: Record<string, string>;
28
+ /** The parsed body; `null` when the response declares no JSON. */
29
+ data: unknown;
30
+ }
31
+ /**
32
+ * Performs one request. A rejection is a failed request (network, CORS, an
33
+ * unconfigured secret, an unparsable JSON body) — an HTTP error status is
34
+ * not: it resolves with `ok: false`.
35
+ */
36
+ export type RequestTransport = (request: TransportRequest) => Promise<TransportResponse>;
37
+ /**
38
+ * The default transport: a direct `fetch`, with `auth` resolved against the
39
+ * host-supplied `secrets`. A request whose secret is not configured throws
40
+ * rather than going out unauthenticated.
41
+ */
42
+ export declare const createFetchTransport: (secrets?: Record<string, string>) => RequestTransport;
43
+ //# sourceMappingURL=transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,wDAAwD;AACxD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC1B,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,UAAU,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,aAAa,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,kEAAkE;IAClE,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAC7B,OAAO,EAAE,gBAAgB,KACtB,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAEhC;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,GAC9B,UAAU,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAG,gBAwCnC,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * The default transport: a direct `fetch`, with `auth` resolved against the
3
+ * host-supplied `secrets`. A request whose secret is not configured throws
4
+ * rather than going out unauthenticated.
5
+ */
6
+ export const createFetchTransport = (secrets) => async (request) => {
7
+ const headers = { ...request.headers };
8
+ if (request.auth) {
9
+ const secret = secrets?.[request.auth.secretRef];
10
+ if (secret === undefined) {
11
+ throw new Error(`Secret "${request.auth.secretRef}" is not configured`);
12
+ }
13
+ if (request.auth.kind === 'bearer') {
14
+ headers.Authorization = `Bearer ${secret}`;
15
+ }
16
+ else {
17
+ headers[request.auth.header ?? 'Authorization'] = secret;
18
+ }
19
+ }
20
+ const response = await fetch(request.url, {
21
+ method: request.method,
22
+ headers,
23
+ body: request.body !== undefined ? JSON.stringify(request.body) : undefined,
24
+ });
25
+ // Only bodies that declare JSON are parsed. A body that claims JSON and
26
+ // fails to parse is a broken server contract, so the parse error is left
27
+ // to reject instead of quietly becoming `null` data.
28
+ const contentType = response.headers.get('content-type') ?? '';
29
+ const data = contentType.includes('json') ? await response.json() : null;
30
+ const responseHeaders = {};
31
+ response.headers.forEach((value, key) => {
32
+ responseHeaders[key] = value;
33
+ });
34
+ return {
35
+ status: response.status,
36
+ ok: response.ok,
37
+ headers: responseHeaders,
38
+ data,
39
+ };
40
+ };
41
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AA2CA;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAC/B,CAAC,OAAgC,EAAoB,EAAE,CACvD,KAAK,EAAE,OAAO,EAAE,EAAE;IAChB,MAAM,OAAO,GAAG,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAEvC,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACjD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,WAAW,OAAO,CAAC,IAAI,CAAC,SAAS,qBAAqB,CAAC,CAAC;QAC1E,CAAC;QACD,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACnC,OAAO,CAAC,aAAa,GAAG,UAAU,MAAM,EAAE,CAAC;QAC7C,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,eAAe,CAAC,GAAG,MAAM,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACxC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,OAAO;QACP,IAAI,EACF,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;KACxE,CAAC,CAAC;IAEH,wEAAwE;IACxE,yEAAyE;IACzE,qDAAqD;IACrD,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;IAC/D,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAEzE,MAAM,eAAe,GAA2B,EAAE,CAAC;IACnD,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACtC,eAAe,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,EAAE,EAAE,QAAQ,CAAC,EAAE;QACf,OAAO,EAAE,eAAe;QACxB,IAAI;KACL,CAAC;AACJ,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mapples/request",
3
- "version": "1.6.0-beta.20260921105308",
3
+ "version": "1.6.0-beta.20260929074057",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "scripts": {