@solvice/routing 0.17.2-beta.0 → 0.17.3-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -2
- package/dist/index.d.ts +25 -2
- package/dist/index.js +25 -1
- package/dist/runs.d.ts +4141 -0
- package/dist/runs.js +5 -0
- package/dist/v3.d.ts +66 -8
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -70,6 +70,36 @@ try {
|
|
|
70
70
|
| `evaluate(request)` | `POST /v3/routing/evaluate` |
|
|
71
71
|
| `suggest(request)` | `POST /v3/routing/suggest` |
|
|
72
72
|
| `validate.solve(request)`, `validate.evaluate(request)`, `validate.suggest(request)` | the same three sent to `/v3/routing/validate/solve`, `/evaluate`, `/suggest`: checked, not run |
|
|
73
|
+
| `runs.submit(request)` | `POST /v3/routing/runs`: answers at once with a `queued` run |
|
|
74
|
+
| `runs.get(id)` | `GET /v3/routing/runs/{id}`: poll the run's `status` |
|
|
75
|
+
| `runs.result(id)` | `GET /v3/routing/runs/{id}/result`: the plan of a `succeeded` run |
|
|
76
|
+
| `runs.cancel(id)` | `POST /v3/routing/runs/{id}/cancel` |
|
|
77
|
+
|
|
78
|
+
An async run takes the `solve` body and may search for up to 3,600 s
|
|
79
|
+
(`options.time_limit_s`). Submit it, poll until `status` is `succeeded`, `failed` or
|
|
80
|
+
`cancelled`, then read the plan:
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
import { createSolvice, type SolveRequest } from '@solvice/routing';
|
|
84
|
+
|
|
85
|
+
const solvice = createSolvice({ apiKey: process.env.SOLVICE_API_KEY! });
|
|
86
|
+
|
|
87
|
+
export async function solveInBackground(problem: SolveRequest['problem']) {
|
|
88
|
+
let run = await solvice.runs.submit({ problem, options: { time_limit_s: 600 } });
|
|
89
|
+
while (run.status === 'queued' || run.status === 'running') {
|
|
90
|
+
await new Promise((resolve) => setTimeout(resolve, 5000));
|
|
91
|
+
run = await solvice.runs.get(run.id);
|
|
92
|
+
}
|
|
93
|
+
if (run.status !== 'succeeded') {
|
|
94
|
+
throw new Error(`run ${run.id} ${run.status}: ${run.error?.message ?? 'no plan'}`);
|
|
95
|
+
}
|
|
96
|
+
return solvice.runs.result(run.id);
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The run endpoints are served by the API gateway, so their `404` and `409` errors are
|
|
101
|
+
not the API's error body: a `SolviceError` with no `body`, and `raw.message` starting
|
|
102
|
+
with a code (`not_found`, `run_not_finished`, `no_result`).
|
|
73
103
|
|
|
74
104
|
Any non-2xx response throws a `SolviceError` with the HTTP `status`, the
|
|
75
105
|
`response`, and, when the response carried one, the API's error `body`. A `401`
|
|
@@ -90,10 +120,10 @@ Documentation: <https://docs.solvice.io>
|
|
|
90
120
|
|
|
91
121
|
## Development
|
|
92
122
|
|
|
93
|
-
`src/v3.ts`
|
|
123
|
+
`src/v3.ts` and `src/runs.ts` are generated; do not edit them. After an API change:
|
|
94
124
|
|
|
95
125
|
```bash
|
|
96
|
-
npm run generate # from mintlify/openapi.json
|
|
126
|
+
npm run generate # v3.ts from mintlify/openapi.json, runs.ts from mintlify/openapi-runs.json
|
|
97
127
|
npm test # builds, typechecks tests/types.ts and examples/, runs the unit tests and the solve-response fixture check
|
|
98
128
|
npm run smoke # live calls; needs SOLVICE_API_KEY
|
|
99
129
|
```
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import type { components as runsComponents, paths as runsPaths } from "./runs.js";
|
|
1
2
|
import type { components, paths } from "./v3.js";
|
|
2
|
-
export type { components, paths };
|
|
3
|
+
export type { components, paths, runsComponents, runsPaths };
|
|
3
4
|
export type Schemas = components["schemas"];
|
|
4
5
|
export type SolveRequest = Schemas["SolveRequest"];
|
|
5
6
|
export type EvaluateRequest = Schemas["EvaluateRequest"];
|
|
@@ -8,6 +9,12 @@ export type SolveResponse = Schemas["SolveResponse"];
|
|
|
8
9
|
export type SuggestResponse = Schemas["SuggestResponse"];
|
|
9
10
|
export type ValidateResponse = Schemas["ValidateResponse"];
|
|
10
11
|
export type ErrorBody = Schemas["ErrorBody"];
|
|
12
|
+
export type RunSchemas = runsComponents["schemas"];
|
|
13
|
+
export type RunRequest = RunSchemas["RunRequest"];
|
|
14
|
+
export type Run = RunSchemas["Run"];
|
|
15
|
+
export type RunStatus = RunSchemas["RunStatus"];
|
|
16
|
+
/** The gateway's own error answer on `/v3/routing/runs*`: not an `ErrorBody`. */
|
|
17
|
+
export type GatewayError = RunSchemas["GatewayError"];
|
|
11
18
|
export interface SolviceOptions {
|
|
12
19
|
/** Sent as the `Authorization` header value, with no scheme prefix. */
|
|
13
20
|
apiKey: string;
|
|
@@ -51,6 +58,22 @@ export declare function createSolvice({ apiKey, baseUrl, fetch }: SolviceOptions
|
|
|
51
58
|
evaluate: (body: EvaluateRequest, options?: RequestOptions) => Promise<ValidateResponse>;
|
|
52
59
|
suggest: (body: SuggestRequest, options?: RequestOptions) => Promise<ValidateResponse>;
|
|
53
60
|
};
|
|
61
|
+
/**
|
|
62
|
+
* Async runs, served by the API gateway: `submit` answers at once and the
|
|
63
|
+
* search runs in the background for up to `options.time_limit_s` (3,600 s).
|
|
64
|
+
* Poll `get` until `status` is `succeeded`, `failed` or `cancelled`, then
|
|
65
|
+
* read the plan with `result`. A gateway error (`404`, `409`) is a
|
|
66
|
+
* `SolviceError` with no `body`; its `raw.message` starts with a code such
|
|
67
|
+
* as `not_found`, `run_not_finished` or `no_result`.
|
|
68
|
+
*/
|
|
69
|
+
runs: {
|
|
70
|
+
submit: (body: RunRequest, options?: RequestOptions) => Promise<Run>;
|
|
71
|
+
get: (id: string, options?: RequestOptions) => Promise<Run>;
|
|
72
|
+
/** The plan of a `succeeded` run; a run that is not finished, failed or cancelled answers `409`. */
|
|
73
|
+
result: (id: string, options?: RequestOptions) => Promise<SolveResponse>;
|
|
74
|
+
/** Cancels a `queued` or `running` run; a finished run comes back in its final state. */
|
|
75
|
+
cancel: (id: string, options?: RequestOptions) => Promise<Run>;
|
|
76
|
+
};
|
|
54
77
|
/** The underlying openapi-fetch client, for anything the methods above do not cover. */
|
|
55
|
-
client: import("openapi-fetch").Client<paths, `${string}/${string}`>;
|
|
78
|
+
client: import("openapi-fetch").Client<paths & runsPaths, `${string}/${string}`>;
|
|
56
79
|
};
|
package/dist/index.js
CHANGED
|
@@ -34,7 +34,15 @@ export class SolviceError extends Error {
|
|
|
34
34
|
const isRecord = (value) => typeof value === "object" && value !== null;
|
|
35
35
|
/** The API's error body has `status`, `code` and `message`; the gateway's `401` has `message` and `error`. */
|
|
36
36
|
const isErrorBody = (value) => isRecord(value) && "status" in value && "code" in value && "message" in value;
|
|
37
|
-
const gatewayMessage = (raw) =>
|
|
37
|
+
const gatewayMessage = (raw) => {
|
|
38
|
+
if (!isRecord(raw))
|
|
39
|
+
return undefined;
|
|
40
|
+
if (typeof raw.message === "string")
|
|
41
|
+
return raw.message;
|
|
42
|
+
// A malformed run id answers `{ error: "Invalid UUID string: ..." }` with no `message`;
|
|
43
|
+
// the bare `GATEWAY_ERROR` constant says less than the status line does.
|
|
44
|
+
return typeof raw.error === "string" && raw.error !== "GATEWAY_ERROR" ? raw.error : undefined;
|
|
45
|
+
};
|
|
38
46
|
function unwrap({ data, error, response }) {
|
|
39
47
|
if (!response.ok) {
|
|
40
48
|
// openapi-fetch hands back the raw text when the error is not JSON, and "" for no body.
|
|
@@ -55,6 +63,22 @@ export function createSolvice({ apiKey, baseUrl = "https://api.solvice.io", fetc
|
|
|
55
63
|
evaluate: async (body, options) => unwrap(await client.POST("/v3/routing/validate/evaluate", { body, ...options })),
|
|
56
64
|
suggest: async (body, options) => unwrap(await client.POST("/v3/routing/validate/suggest", { body, ...options })),
|
|
57
65
|
},
|
|
66
|
+
/**
|
|
67
|
+
* Async runs, served by the API gateway: `submit` answers at once and the
|
|
68
|
+
* search runs in the background for up to `options.time_limit_s` (3,600 s).
|
|
69
|
+
* Poll `get` until `status` is `succeeded`, `failed` or `cancelled`, then
|
|
70
|
+
* read the plan with `result`. A gateway error (`404`, `409`) is a
|
|
71
|
+
* `SolviceError` with no `body`; its `raw.message` starts with a code such
|
|
72
|
+
* as `not_found`, `run_not_finished` or `no_result`.
|
|
73
|
+
*/
|
|
74
|
+
runs: {
|
|
75
|
+
submit: async (body, options) => unwrap(await client.POST("/v3/routing/runs", { body, ...options })),
|
|
76
|
+
get: async (id, options) => unwrap(await client.GET("/v3/routing/runs/{id}", { params: { path: { id } }, ...options })),
|
|
77
|
+
/** The plan of a `succeeded` run; a run that is not finished, failed or cancelled answers `409`. */
|
|
78
|
+
result: async (id, options) => unwrap(await client.GET("/v3/routing/runs/{id}/result", { params: { path: { id } }, ...options })),
|
|
79
|
+
/** Cancels a `queued` or `running` run; a finished run comes back in its final state. */
|
|
80
|
+
cancel: async (id, options) => unwrap(await client.POST("/v3/routing/runs/{id}/cancel", { params: { path: { id } }, ...options })),
|
|
81
|
+
},
|
|
58
82
|
/** The underlying openapi-fetch client, for anything the methods above do not cover. */
|
|
59
83
|
client,
|
|
60
84
|
};
|