@solvice/routing 0.0.0-stage → 0.1.0-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 +80 -2
- package/dist/index.d.ts +40 -0
- package/dist/index.js +41 -0
- package/dist/v3.d.ts +4138 -0
- package/dist/v3.js +5 -0
- package/package.json +39 -4
package/README.md
CHANGED
|
@@ -1,3 +1,81 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @solvice/routing
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
TypeScript client for the Solvice V3 Routing API. The request and response types
|
|
4
|
+
are generated from the API's OpenAPI spec, so they match the API field for field.
|
|
5
|
+
|
|
6
|
+
V3 is in beta until general availability. Until then this package is published
|
|
7
|
+
under the `beta` dist-tag as `0.x` prereleases, and any release may change types.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @solvice/routing@beta
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { createSolvice, SolviceError } from '@solvice/routing';
|
|
15
|
+
|
|
16
|
+
const solvice = createSolvice({ apiKey: process.env.SOLVICE_API_KEY! });
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
const solution = await solvice.solve(
|
|
20
|
+
{
|
|
21
|
+
problem: {
|
|
22
|
+
jobs: [{ id: 'delivery-1', location: [4.7005, 50.8798], service_duration_s: 300 }],
|
|
23
|
+
vehicles: [
|
|
24
|
+
{
|
|
25
|
+
id: 'truck-1',
|
|
26
|
+
shifts: [
|
|
27
|
+
{
|
|
28
|
+
id: 'mon',
|
|
29
|
+
from: '2026-04-01T08:00:00+02:00',
|
|
30
|
+
to: '2026-04-01T17:00:00+02:00',
|
|
31
|
+
start: { location: [4.3517, 50.8503] },
|
|
32
|
+
end: { location: [4.3517, 50.8503] },
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
},
|
|
38
|
+
options: { time_limit_s: 5 },
|
|
39
|
+
},
|
|
40
|
+
{ signal: AbortSignal.timeout(35_000) },
|
|
41
|
+
);
|
|
42
|
+
console.log(solution.routes);
|
|
43
|
+
} catch (err) {
|
|
44
|
+
if (!(err instanceof SolviceError)) throw err;
|
|
45
|
+
console.error(err.status, err.body?.errors);
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
| Method | Endpoint |
|
|
50
|
+
| --- | --- |
|
|
51
|
+
| `solve(request)` | `POST /v3/routing/solve` |
|
|
52
|
+
| `evaluate(request)` | `POST /v3/routing/evaluate` |
|
|
53
|
+
| `suggest(request)` | `POST /v3/routing/suggest` |
|
|
54
|
+
| `validate.solve(request)`, `validate.evaluate(request)`, `validate.suggest(request)` | the same three with `?validate_only=true` |
|
|
55
|
+
|
|
56
|
+
Any non-2xx response throws a `SolviceError` with the HTTP `status` and, when the
|
|
57
|
+
response carried one, the API's error `body`.
|
|
58
|
+
|
|
59
|
+
Every method takes a second argument, `{ signal, headers }`. The client sets no
|
|
60
|
+
timeout of its own: pass `AbortSignal.timeout(ms)` as `signal`, with a margin on
|
|
61
|
+
top of `options.time_limit_s`. It does not retry; pass your own `fetch` to
|
|
62
|
+
`createSolvice` to add that. `client` is the underlying
|
|
63
|
+
[openapi-fetch](https://openapi-ts.dev/openapi-fetch/) client.
|
|
64
|
+
|
|
65
|
+
Runs on Node.js 20 or later. Keep the API key on your server.
|
|
66
|
+
|
|
67
|
+
Documentation: <https://docs.solvice.io>
|
|
68
|
+
|
|
69
|
+
## Development
|
|
70
|
+
|
|
71
|
+
`src/v3.ts` is generated; do not edit it. After an API change:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
npm run generate # from mintlify/openapi.json
|
|
75
|
+
npm test # builds, typechecks tests/types.ts and examples/, runs the unit tests
|
|
76
|
+
npm run smoke # live calls; needs SOLVICE_API_KEY
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
To release, bump `version` to the next `0.x.y-beta.n` and run `npm run publish:beta`.
|
|
80
|
+
The explicit `--tag beta` matters: npm 11 ignores `publishConfig.tag` and would
|
|
81
|
+
move `latest` to the prerelease.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { components, paths } from "./v3.js";
|
|
2
|
+
export type { components, paths };
|
|
3
|
+
export type Schemas = components["schemas"];
|
|
4
|
+
export type SolveRequest = Schemas["SolveRequest"];
|
|
5
|
+
export type EvaluateRequest = Schemas["EvaluateRequest"];
|
|
6
|
+
export type SuggestRequest = Schemas["SuggestRequest"];
|
|
7
|
+
export type SolveResponse = Schemas["SolveResponse"];
|
|
8
|
+
export type SuggestResponse = Schemas["SuggestResponse"];
|
|
9
|
+
export type ValidateOnlyResponse = Schemas["ValidateOnlyResponse"];
|
|
10
|
+
export type ErrorBody = Schemas["ErrorBody"];
|
|
11
|
+
export interface SolviceOptions {
|
|
12
|
+
/** Sent as the `Authorization` header value, with no scheme prefix. */
|
|
13
|
+
apiKey: string;
|
|
14
|
+
baseUrl?: string;
|
|
15
|
+
fetch?: typeof globalThis.fetch;
|
|
16
|
+
}
|
|
17
|
+
/** Per-call options. The client sets no timeout: pass `AbortSignal.timeout(ms)` as `signal`. */
|
|
18
|
+
export interface RequestOptions {
|
|
19
|
+
signal?: AbortSignal;
|
|
20
|
+
headers?: Record<string, string>;
|
|
21
|
+
}
|
|
22
|
+
/** Any non-2xx response. `body` is absent when the response carried no JSON (401, 429). */
|
|
23
|
+
export declare class SolviceError extends Error {
|
|
24
|
+
readonly status: number;
|
|
25
|
+
readonly body?: ErrorBody | undefined;
|
|
26
|
+
constructor(status: number, body?: ErrorBody | undefined);
|
|
27
|
+
}
|
|
28
|
+
export declare function createSolvice({ apiKey, baseUrl, fetch }: SolviceOptions): {
|
|
29
|
+
solve: (body: SolveRequest, options?: RequestOptions) => Promise<SolveResponse>;
|
|
30
|
+
evaluate: (body: EvaluateRequest, options?: RequestOptions) => Promise<SolveResponse>;
|
|
31
|
+
suggest: (body: SuggestRequest, options?: RequestOptions) => Promise<SuggestResponse>;
|
|
32
|
+
/** The same requests with `?validate_only=true`: no matrix fetch, no search. */
|
|
33
|
+
validate: {
|
|
34
|
+
solve: (body: SolveRequest, options?: RequestOptions) => Promise<ValidateOnlyResponse>;
|
|
35
|
+
evaluate: (body: EvaluateRequest, options?: RequestOptions) => Promise<ValidateOnlyResponse>;
|
|
36
|
+
suggest: (body: SuggestRequest, options?: RequestOptions) => Promise<ValidateOnlyResponse>;
|
|
37
|
+
};
|
|
38
|
+
/** The underlying openapi-fetch client, for anything the methods above do not cover. */
|
|
39
|
+
client: import("openapi-fetch").Client<paths, `${string}/${string}`>;
|
|
40
|
+
};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import createClient from "openapi-fetch";
|
|
2
|
+
/** Any non-2xx response. `body` is absent when the response carried no JSON (401, 429). */
|
|
3
|
+
export class SolviceError extends Error {
|
|
4
|
+
status;
|
|
5
|
+
body;
|
|
6
|
+
constructor(status, body) {
|
|
7
|
+
super(body?.message ?? `Solvice API responded ${status}`);
|
|
8
|
+
this.status = status;
|
|
9
|
+
this.body = body;
|
|
10
|
+
this.name = "SolviceError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function unwrap({ data, error, response }) {
|
|
14
|
+
if (!response.ok) {
|
|
15
|
+
// openapi-fetch hands back the raw text when the error is not JSON.
|
|
16
|
+
throw new SolviceError(response.status, typeof error === "object" && error !== null ? error : undefined);
|
|
17
|
+
}
|
|
18
|
+
return data;
|
|
19
|
+
}
|
|
20
|
+
// The spec types every 200 as `Response | ValidateOnlyResponse` (#1626 H).
|
|
21
|
+
// Which one comes back is decided by `validate_only`, which each method below
|
|
22
|
+
// fixes, so these two pick the matching side of the union.
|
|
23
|
+
const result = (r) => unwrap(r);
|
|
24
|
+
const validation = (r) => unwrap(r);
|
|
25
|
+
const VALIDATE_ONLY = { query: { validate_only: true } };
|
|
26
|
+
export function createSolvice({ apiKey, baseUrl = "https://api.solvice.io", fetch }) {
|
|
27
|
+
const client = createClient({ baseUrl, headers: { Authorization: apiKey }, fetch });
|
|
28
|
+
return {
|
|
29
|
+
solve: async (body, options) => result(await client.POST("/v3/routing/solve", { body, ...options })),
|
|
30
|
+
evaluate: async (body, options) => result(await client.POST("/v3/routing/evaluate", { body, ...options })),
|
|
31
|
+
suggest: async (body, options) => result(await client.POST("/v3/routing/suggest", { body, ...options })),
|
|
32
|
+
/** The same requests with `?validate_only=true`: no matrix fetch, no search. */
|
|
33
|
+
validate: {
|
|
34
|
+
solve: async (body, options) => validation(await client.POST("/v3/routing/solve", { body, params: VALIDATE_ONLY, ...options })),
|
|
35
|
+
evaluate: async (body, options) => validation(await client.POST("/v3/routing/evaluate", { body, params: VALIDATE_ONLY, ...options })),
|
|
36
|
+
suggest: async (body, options) => validation(await client.POST("/v3/routing/suggest", { body, params: VALIDATE_ONLY, ...options })),
|
|
37
|
+
},
|
|
38
|
+
/** The underlying openapi-fetch client, for anything the methods above do not cover. */
|
|
39
|
+
client,
|
|
40
|
+
};
|
|
41
|
+
}
|