@junejuly-lockstep/sdk 0.1.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/LICENSE +21 -0
- package/README.md +44 -0
- package/dist/errors.d.ts +28 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +41 -0
- package/dist/errors.js.map +1 -0
- package/dist/http.d.ts +53 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +121 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/ingest.d.ts +32 -0
- package/dist/ingest.d.ts.map +1 -0
- package/dist/ingest.js +60 -0
- package/dist/ingest.js.map +1 -0
- package/dist/session.d.ts +1092 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +185 -0
- package/dist/session.js.map +1 -0
- package/dist/testing.d.ts +15 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +29 -0
- package/dist/testing.js.map +1 -0
- package/package.json +60 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 JuneJuly Health
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# @junejuly-lockstep/sdk
|
|
2
|
+
|
|
3
|
+
A typed `fetch` client for the Lockstep platform API. Two clients:
|
|
4
|
+
|
|
5
|
+
- `createIngestClient` authenticates with a project API key (`lsk_...`, sent as a bearer token) and
|
|
6
|
+
covers the routes the reconciler uses: presigned uploads, baselines, `POST /api/ingest/runs` and
|
|
7
|
+
`POST /api/ingest/models`.
|
|
8
|
+
- `createSessionClient` rides the SPA's session cookie and covers the read and judgment API
|
|
9
|
+
(projects, journeys, board, cards, annotations, ops).
|
|
10
|
+
|
|
11
|
+
Every response is validated with the `@junejuly-lockstep/model` schemas before it is returned; failures
|
|
12
|
+
surface as `LockstepApiError` (HTTP status and body) or `LockstepNetworkError` (retries exhausted).
|
|
13
|
+
ESM only, Node 20.18 or newer (or any runtime with a global `fetch`). No side effects.
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pnpm add @junejuly-lockstep/sdk @junejuly-lockstep/model
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import { createIngestClient, LockstepApiError } from '@junejuly-lockstep/sdk';
|
|
25
|
+
|
|
26
|
+
const ingest = createIngestClient({
|
|
27
|
+
baseUrl: 'https://api.lockstep.example',
|
|
28
|
+
apiKey: process.env.LOCKSTEP_API_KEY!,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
const baselines = await ingest.getBaselines('FERN');
|
|
33
|
+
console.log(`${baselines.entries.length} approved baselines`);
|
|
34
|
+
} catch (err) {
|
|
35
|
+
if (err instanceof LockstepApiError) console.error(err.status, err.message);
|
|
36
|
+
else throw err;
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`@junejuly-lockstep/sdk/testing` exports `fakeFetch`, a recording `fetch` double for unit tests of code that
|
|
41
|
+
uses either client.
|
|
42
|
+
|
|
43
|
+
Published from the [Lockstep monorepo](https://github.com/JuneJulyHealth/lockstep)
|
|
44
|
+
(`packages/sdk`). Versioned in lockstep with `@junejuly-lockstep/model` and `@junejuly-lockstep/reconciler`.
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** Thrown for every non-2xx response (after retries) and for response bodies that fail schema validation. */
|
|
2
|
+
export declare class LockstepApiError extends Error {
|
|
3
|
+
readonly status: number;
|
|
4
|
+
readonly body: unknown;
|
|
5
|
+
readonly method: string;
|
|
6
|
+
readonly url: string;
|
|
7
|
+
/** Machine-readable error code from the API body when the body followed `ApiErrorBody`. */
|
|
8
|
+
readonly code: string | null;
|
|
9
|
+
constructor(args: {
|
|
10
|
+
status: number;
|
|
11
|
+
body: unknown;
|
|
12
|
+
method: string;
|
|
13
|
+
url: string;
|
|
14
|
+
message?: string;
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
/** Thrown when fetch itself rejects (DNS, connection refused, aborted) after retries. */
|
|
18
|
+
export declare class LockstepNetworkError extends Error {
|
|
19
|
+
readonly method: string;
|
|
20
|
+
readonly url: string;
|
|
21
|
+
readonly cause_: unknown;
|
|
22
|
+
constructor(args: {
|
|
23
|
+
method: string;
|
|
24
|
+
url: string;
|
|
25
|
+
cause: unknown;
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAEA,6GAA6G;AAC7G,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,2FAA2F;IAC3F,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;gBAEjB,IAAI,EAAE;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,OAAO,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB;CAkBF;AAED,yFAAyF;AACzF,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;gBAEb,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE;CAQlE"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ApiErrorBody } from '@junejuly-lockstep/model';
|
|
2
|
+
/** Thrown for every non-2xx response (after retries) and for response bodies that fail schema validation. */
|
|
3
|
+
export class LockstepApiError extends Error {
|
|
4
|
+
status;
|
|
5
|
+
body;
|
|
6
|
+
method;
|
|
7
|
+
url;
|
|
8
|
+
/** Machine-readable error code from the API body when the body followed `ApiErrorBody`. */
|
|
9
|
+
code;
|
|
10
|
+
constructor(args) {
|
|
11
|
+
const parsed = ApiErrorBody.safeParse(args.body);
|
|
12
|
+
const detail = parsed.success
|
|
13
|
+
? parsed.data.message
|
|
14
|
+
: typeof args.body === 'string'
|
|
15
|
+
? args.body
|
|
16
|
+
: '';
|
|
17
|
+
super(args.message ??
|
|
18
|
+
`${args.method} ${args.url} failed with ${args.status}${detail ? `: ${detail}` : ''}`);
|
|
19
|
+
this.name = 'LockstepApiError';
|
|
20
|
+
this.status = args.status;
|
|
21
|
+
this.body = args.body;
|
|
22
|
+
this.method = args.method;
|
|
23
|
+
this.url = args.url;
|
|
24
|
+
this.code = parsed.success ? parsed.data.error : null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/** Thrown when fetch itself rejects (DNS, connection refused, aborted) after retries. */
|
|
28
|
+
export class LockstepNetworkError extends Error {
|
|
29
|
+
method;
|
|
30
|
+
url;
|
|
31
|
+
cause_;
|
|
32
|
+
constructor(args) {
|
|
33
|
+
const reason = args.cause instanceof Error ? args.cause.message : String(args.cause);
|
|
34
|
+
super(`${args.method} ${args.url} could not be reached: ${reason}`);
|
|
35
|
+
this.name = 'LockstepNetworkError';
|
|
36
|
+
this.method = args.method;
|
|
37
|
+
this.url = args.url;
|
|
38
|
+
this.cause_ = args.cause;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAExD,6GAA6G;AAC7G,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAChC,MAAM,CAAS;IACf,IAAI,CAAU;IACd,MAAM,CAAS;IACf,GAAG,CAAS;IACrB,2FAA2F;IAClF,IAAI,CAAgB;IAE7B,YAAY,IAMX;QACC,MAAM,MAAM,GAAG,YAAY,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO;YAC3B,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO;YACrB,CAAC,CAAC,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ;gBAC7B,CAAC,CAAC,IAAI,CAAC,IAAI;gBACX,CAAC,CAAC,EAAE,CAAC;QACT,KAAK,CACH,IAAI,CAAC,OAAO;YACV,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,GAAG,gBAAgB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CACxF,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QACpB,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IACxD,CAAC;CACF;AAED,yFAAyF;AACzF,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IACpC,MAAM,CAAS;IACf,GAAG,CAAS;IACZ,MAAM,CAAU;IAEzB,YAAY,IAAqD;QAC/D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrF,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,GAAG,0BAA0B,MAAM,EAAE,CAAC,CAAC;QACpE,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QACpB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC;IAC3B,CAAC;CACF"}
|
package/dist/http.d.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { z } from 'zod';
|
|
2
|
+
export type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
|
|
3
|
+
export interface RetryPolicy {
|
|
4
|
+
/** Number of retries after the first attempt. Default 3 for idempotent GETs, 0 otherwise. */
|
|
5
|
+
retries: number;
|
|
6
|
+
/** Base delay in ms; attempt n waits base * 2^n. Default 250. */
|
|
7
|
+
baseDelayMs: number;
|
|
8
|
+
/** Injectable sleep for tests. */
|
|
9
|
+
sleep: (ms: number) => Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
export declare const DEFAULT_RETRY: RetryPolicy;
|
|
12
|
+
export interface HttpOptions {
|
|
13
|
+
baseUrl: string;
|
|
14
|
+
fetch?: FetchLike;
|
|
15
|
+
retry?: Partial<RetryPolicy>;
|
|
16
|
+
/** Headers added to every request. */
|
|
17
|
+
headers?: Record<string, string>;
|
|
18
|
+
/** Passed through to fetch (e.g. `credentials: 'include'`). */
|
|
19
|
+
init?: RequestInit;
|
|
20
|
+
}
|
|
21
|
+
export interface RequestSpec<T> {
|
|
22
|
+
method: 'GET' | 'POST' | 'PATCH' | 'DELETE';
|
|
23
|
+
path: string;
|
|
24
|
+
query?: Record<string, string | number | boolean | undefined>;
|
|
25
|
+
body?: unknown;
|
|
26
|
+
headers?: Record<string, string>;
|
|
27
|
+
/** Output schema; the input type is free so schemas with defaults work. */
|
|
28
|
+
schema: z.ZodType<T, z.ZodTypeDef, unknown>;
|
|
29
|
+
/** Override: retry even when not a GET, or disable retry on a GET. */
|
|
30
|
+
idempotent?: boolean;
|
|
31
|
+
/** `If-None-Match` value; a 304 resolves with `notModified: true`. */
|
|
32
|
+
etag?: string | null;
|
|
33
|
+
}
|
|
34
|
+
export interface Conditional<T> {
|
|
35
|
+
data: T | null;
|
|
36
|
+
etag: string | null;
|
|
37
|
+
notModified: boolean;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Join base, path and query. The base may be absolute (`https://api.example`) or relative
|
|
41
|
+
* (`''` or `/api-prefix`) for same-origin use in the SPA.
|
|
42
|
+
*/
|
|
43
|
+
export declare function joinUrl(baseUrl: string, path: string, query?: RequestSpec<unknown>['query']): string;
|
|
44
|
+
export declare function createHttp(options: HttpOptions): {
|
|
45
|
+
request: <T>(spec: RequestSpec<T>) => Promise<T>;
|
|
46
|
+
conditional: <T>(spec: RequestSpec<T>) => Promise<Conditional<T>>;
|
|
47
|
+
raw: <T>(spec: RequestSpec<T>) => Promise<{
|
|
48
|
+
response: Response;
|
|
49
|
+
url: string;
|
|
50
|
+
}>;
|
|
51
|
+
};
|
|
52
|
+
export type Http = ReturnType<typeof createHttp>;
|
|
53
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAG7B,MAAM,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEjF,MAAM,WAAW,WAAW;IAC1B,6FAA6F;IAC7F,OAAO,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,WAAW,EAAE,MAAM,CAAC;IACpB,kCAAkC;IAClC,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAED,eAAO,MAAM,aAAa,EAAE,WAI3B,CAAC;AAEF,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7B,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,+DAA+D;IAC/D,IAAI,CAAC,EAAE,WAAW,CAAC;CACpB;AAED,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;IAC9D,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,2EAA2E;IAC3E,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAC5C,sEAAsE;IACtE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,OAAO,CACrB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,GACpC,MAAM,CASR;AAMD,wBAAgB,UAAU,CAAC,OAAO,EAAE,WAAW;cAiFtB,CAAC,QAAQ,WAAW,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC,CAAC,CAAC;kBA7BhC,CAAC,QAAQ,WAAW,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;UAhDzD,CAAC,QAAQ,WAAW,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;EAmF1F;AAED,MAAM,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC"}
|
package/dist/http.js
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { LockstepApiError, LockstepNetworkError } from './errors.js';
|
|
2
|
+
export const DEFAULT_RETRY = {
|
|
3
|
+
retries: 3,
|
|
4
|
+
baseDelayMs: 250,
|
|
5
|
+
sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Join base, path and query. The base may be absolute (`https://api.example`) or relative
|
|
9
|
+
* (`''` or `/api-prefix`) for same-origin use in the SPA.
|
|
10
|
+
*/
|
|
11
|
+
export function joinUrl(baseUrl, path, query) {
|
|
12
|
+
const base = baseUrl.replace(/\/+$/, '');
|
|
13
|
+
const pathname = `${base}${path.startsWith('/') ? path : `/${path}`}`;
|
|
14
|
+
const params = new URLSearchParams();
|
|
15
|
+
for (const [k, v] of Object.entries(query ?? {})) {
|
|
16
|
+
if (v !== undefined)
|
|
17
|
+
params.set(k, String(v));
|
|
18
|
+
}
|
|
19
|
+
const qs = params.toString();
|
|
20
|
+
return qs ? `${pathname}?${qs}` : pathname;
|
|
21
|
+
}
|
|
22
|
+
function isRetryable(status) {
|
|
23
|
+
return status === 408 || status === 425 || status === 429 || status >= 500;
|
|
24
|
+
}
|
|
25
|
+
export function createHttp(options) {
|
|
26
|
+
const fetchImpl = options.fetch ?? ((input, init) => globalThis.fetch(input, init));
|
|
27
|
+
const retry = { ...DEFAULT_RETRY, ...options.retry };
|
|
28
|
+
async function raw(spec) {
|
|
29
|
+
const url = joinUrl(options.baseUrl, spec.path, spec.query);
|
|
30
|
+
const idempotent = spec.idempotent ?? spec.method === 'GET';
|
|
31
|
+
const maxAttempts = (idempotent ? retry.retries : 0) + 1;
|
|
32
|
+
const headers = {
|
|
33
|
+
accept: 'application/json',
|
|
34
|
+
...options.headers,
|
|
35
|
+
...spec.headers,
|
|
36
|
+
};
|
|
37
|
+
if (spec.body !== undefined)
|
|
38
|
+
headers['content-type'] = 'application/json';
|
|
39
|
+
if (spec.etag)
|
|
40
|
+
headers['if-none-match'] = spec.etag;
|
|
41
|
+
let lastError;
|
|
42
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
43
|
+
if (attempt > 0)
|
|
44
|
+
await retry.sleep(retry.baseDelayMs * 2 ** (attempt - 1));
|
|
45
|
+
try {
|
|
46
|
+
const response = await fetchImpl(url, {
|
|
47
|
+
...options.init,
|
|
48
|
+
method: spec.method,
|
|
49
|
+
headers,
|
|
50
|
+
body: spec.body === undefined ? undefined : JSON.stringify(spec.body),
|
|
51
|
+
});
|
|
52
|
+
if (response.ok ||
|
|
53
|
+
response.status === 304 ||
|
|
54
|
+
!isRetryable(response.status) ||
|
|
55
|
+
attempt === maxAttempts - 1) {
|
|
56
|
+
return { response, url };
|
|
57
|
+
}
|
|
58
|
+
lastError = new LockstepApiError({
|
|
59
|
+
status: response.status,
|
|
60
|
+
body: await readBody(response),
|
|
61
|
+
method: spec.method,
|
|
62
|
+
url,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
lastError = err;
|
|
67
|
+
if (attempt === maxAttempts - 1) {
|
|
68
|
+
throw new LockstepNetworkError({ method: spec.method, url, cause: err });
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
throw lastError instanceof Error
|
|
73
|
+
? lastError
|
|
74
|
+
: new LockstepNetworkError({ method: spec.method, url, cause: lastError });
|
|
75
|
+
}
|
|
76
|
+
async function conditional(spec) {
|
|
77
|
+
const { response, url } = await raw(spec);
|
|
78
|
+
const etag = response.headers.get('etag');
|
|
79
|
+
if (response.status === 304)
|
|
80
|
+
return { data: null, etag: etag ?? spec.etag ?? null, notModified: true };
|
|
81
|
+
if (!response.ok) {
|
|
82
|
+
throw new LockstepApiError({
|
|
83
|
+
status: response.status,
|
|
84
|
+
body: await readBody(response),
|
|
85
|
+
method: spec.method,
|
|
86
|
+
url,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
const body = await readBody(response);
|
|
90
|
+
const parsed = spec.schema.safeParse(body);
|
|
91
|
+
if (!parsed.success) {
|
|
92
|
+
throw new LockstepApiError({
|
|
93
|
+
status: response.status,
|
|
94
|
+
body,
|
|
95
|
+
method: spec.method,
|
|
96
|
+
url,
|
|
97
|
+
message: `${spec.method} ${url} returned a body that does not match the expected schema: ${parsed.error.issues
|
|
98
|
+
.map((i) => `${i.path.join('.') || '<root>'}: ${i.message}`)
|
|
99
|
+
.join('; ')}`,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return { data: parsed.data, etag, notModified: false };
|
|
103
|
+
}
|
|
104
|
+
async function request(spec) {
|
|
105
|
+
const result = await conditional({ ...spec, etag: null });
|
|
106
|
+
return result.data;
|
|
107
|
+
}
|
|
108
|
+
return { request, conditional, raw };
|
|
109
|
+
}
|
|
110
|
+
async function readBody(response) {
|
|
111
|
+
const text = await response.text();
|
|
112
|
+
if (!text)
|
|
113
|
+
return null;
|
|
114
|
+
try {
|
|
115
|
+
return JSON.parse(text);
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
return text;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=http.js.map
|
package/dist/http.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { LockstepApiError, LockstepNetworkError } from './errors.js';
|
|
2
|
+
export { createIngestClient, INGEST_ROUTES } from './ingest.js';
|
|
3
|
+
export type { IngestClient, IngestClientOptions } from './ingest.js';
|
|
4
|
+
export { createSessionClient, SESSION_ROUTES } from './session.js';
|
|
5
|
+
export type { ConditionalOptions, JudgmentAction, RunArtifactsResponse, SessionClient, SessionClientOptions, } from './session.js';
|
|
6
|
+
export { joinUrl, DEFAULT_RETRY } from './http.js';
|
|
7
|
+
export type { Conditional, FetchLike, RetryPolicy } from './http.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAChE,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnE,YAAY,EACV,kBAAkB,EAClB,cAAc,EACd,oBAAoB,EACpB,aAAa,EACb,oBAAoB,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACnD,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { LockstepApiError, LockstepNetworkError } from './errors.js';
|
|
2
|
+
export { createIngestClient, INGEST_ROUTES } from './ingest.js';
|
|
3
|
+
export { createSessionClient, SESSION_ROUTES } from './session.js';
|
|
4
|
+
export { joinUrl, DEFAULT_RETRY } from './http.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAQnE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/ingest.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { BaselineManifest, IngestRunResponse, ModelSyncPayload, ModelSyncResponse, PresignRequest, PresignResponse, RunPayload } from '@junejuly-lockstep/model';
|
|
2
|
+
import { type FetchLike, type RetryPolicy } from './http.js';
|
|
3
|
+
export interface IngestClientOptions {
|
|
4
|
+
/** Platform API origin, e.g. https://api.lockstep.example */
|
|
5
|
+
baseUrl: string;
|
|
6
|
+
/** Project API key, `lsk_...`. Sent as `Authorization: Bearer`. */
|
|
7
|
+
apiKey: string;
|
|
8
|
+
fetch?: FetchLike;
|
|
9
|
+
retry?: Partial<RetryPolicy>;
|
|
10
|
+
}
|
|
11
|
+
/** Routes the reconciler uses. Kept in one place so the API can be reconciled against them. */
|
|
12
|
+
export declare const INGEST_ROUTES: {
|
|
13
|
+
readonly presign: "/api/ingest/presign";
|
|
14
|
+
readonly runs: "/api/ingest/runs";
|
|
15
|
+
readonly baselines: "/api/ingest/baselines";
|
|
16
|
+
readonly models: "/api/ingest/models";
|
|
17
|
+
};
|
|
18
|
+
export interface IngestClient {
|
|
19
|
+
/** POST /api/ingest/presign: batch presigned PUT URLs (max 50 files per call). */
|
|
20
|
+
presign(req: PresignRequest): Promise<PresignResponse>;
|
|
21
|
+
/** GET /api/ingest/baselines?project=KEY: current approved baselines with presigned GET URLs. */
|
|
22
|
+
getBaselines(projectKey: string): Promise<BaselineManifest>;
|
|
23
|
+
/** POST /api/ingest/runs: the complete run payload. */
|
|
24
|
+
postRun(payload: RunPayload): Promise<IngestRunResponse>;
|
|
25
|
+
/**
|
|
26
|
+
* POST /api/ingest/models: parsed journey models and scenarios at a commit (M3 model sync, run
|
|
27
|
+
* by `lockstep sync-models` in client CI on push; the platform never evaluates journey files).
|
|
28
|
+
*/
|
|
29
|
+
syncModels(payload: ModelSyncPayload): Promise<ModelSyncResponse>;
|
|
30
|
+
}
|
|
31
|
+
export declare function createIngestClient(options: IngestClientOptions): IngestClient;
|
|
32
|
+
//# sourceMappingURL=ingest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingest.d.ts","sourceRoot":"","sources":["../src/ingest.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,UAAU,EACX,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAc,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAEzE,MAAM,WAAW,mBAAmB;IAClC,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;CAC9B;AAED,+FAA+F;AAC/F,eAAO,MAAM,aAAa;;;;;CAKhB,CAAC;AAEX,MAAM,WAAW,YAAY;IAC3B,kFAAkF;IAClF,OAAO,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IACvD,iGAAiG;IACjG,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC5D,uDAAuD;IACvD,OAAO,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACzD;;;OAGG;IACH,UAAU,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACnE;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,mBAAmB,GAAG,YAAY,CAiD7E"}
|
package/dist/ingest.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { BaselineManifest, IngestRunResponse, ModelSyncPayload, ModelSyncResponse, PresignRequest, PresignResponse, RunPayload, } from '@junejuly-lockstep/model';
|
|
2
|
+
import { createHttp } from './http.js';
|
|
3
|
+
/** Routes the reconciler uses. Kept in one place so the API can be reconciled against them. */
|
|
4
|
+
export const INGEST_ROUTES = {
|
|
5
|
+
presign: '/api/ingest/presign',
|
|
6
|
+
runs: '/api/ingest/runs',
|
|
7
|
+
baselines: '/api/ingest/baselines',
|
|
8
|
+
models: '/api/ingest/models',
|
|
9
|
+
};
|
|
10
|
+
export function createIngestClient(options) {
|
|
11
|
+
if (!options.apiKey)
|
|
12
|
+
throw new Error('createIngestClient: apiKey is required');
|
|
13
|
+
if (!options.apiKey.startsWith('lsk_')) {
|
|
14
|
+
throw new Error('createIngestClient: apiKey must be a project key starting with lsk_');
|
|
15
|
+
}
|
|
16
|
+
const http = createHttp({
|
|
17
|
+
baseUrl: options.baseUrl,
|
|
18
|
+
fetch: options.fetch,
|
|
19
|
+
retry: options.retry,
|
|
20
|
+
headers: { authorization: `Bearer ${options.apiKey}` },
|
|
21
|
+
});
|
|
22
|
+
return {
|
|
23
|
+
async presign(req) {
|
|
24
|
+
const body = PresignRequest.parse(req);
|
|
25
|
+
return http.request({
|
|
26
|
+
method: 'POST',
|
|
27
|
+
path: INGEST_ROUTES.presign,
|
|
28
|
+
body,
|
|
29
|
+
schema: PresignResponse,
|
|
30
|
+
});
|
|
31
|
+
},
|
|
32
|
+
async getBaselines(projectKey) {
|
|
33
|
+
return http.request({
|
|
34
|
+
method: 'GET',
|
|
35
|
+
path: INGEST_ROUTES.baselines,
|
|
36
|
+
query: { project: projectKey },
|
|
37
|
+
schema: BaselineManifest,
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
async postRun(payload) {
|
|
41
|
+
const body = RunPayload.parse(payload);
|
|
42
|
+
return http.request({
|
|
43
|
+
method: 'POST',
|
|
44
|
+
path: INGEST_ROUTES.runs,
|
|
45
|
+
body,
|
|
46
|
+
schema: IngestRunResponse,
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
async syncModels(payload) {
|
|
50
|
+
const body = ModelSyncPayload.parse(payload);
|
|
51
|
+
return http.request({
|
|
52
|
+
method: 'POST',
|
|
53
|
+
path: INGEST_ROUTES.models,
|
|
54
|
+
body,
|
|
55
|
+
schema: ModelSyncResponse,
|
|
56
|
+
});
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=ingest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingest.js","sourceRoot":"","sources":["../src/ingest.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,UAAU,GACX,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,UAAU,EAAoC,MAAM,WAAW,CAAC;AAWzE,+FAA+F;AAC/F,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,OAAO,EAAE,qBAAqB;IAC9B,IAAI,EAAE,kBAAkB;IACxB,SAAS,EAAE,uBAAuB;IAClC,MAAM,EAAE,oBAAoB;CACpB,CAAC;AAgBX,MAAM,UAAU,kBAAkB,CAAC,OAA4B;IAC7D,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC/E,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAC;IACzF,CAAC;IACD,MAAM,IAAI,GAAG,UAAU,CAAC;QACtB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,OAAO,CAAC,MAAM,EAAE,EAAE;KACvD,CAAC,CAAC;IAEH,OAAO;QACL,KAAK,CAAC,OAAO,CAAC,GAAG;YACf,MAAM,IAAI,GAAG,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACvC,OAAO,IAAI,CAAC,OAAO,CAAC;gBAClB,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,aAAa,CAAC,OAAO;gBAC3B,IAAI;gBACJ,MAAM,EAAE,eAAe;aACxB,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,YAAY,CAAC,UAAU;YAC3B,OAAO,IAAI,CAAC,OAAO,CAAC;gBAClB,MAAM,EAAE,KAAK;gBACb,IAAI,EAAE,aAAa,CAAC,SAAS;gBAC7B,KAAK,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE;gBAC9B,MAAM,EAAE,gBAAgB;aACzB,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,OAAO;YACnB,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACvC,OAAO,IAAI,CAAC,OAAO,CAAC;gBAClB,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,aAAa,CAAC,IAAI;gBACxB,IAAI;gBACJ,MAAM,EAAE,iBAAiB;aAC1B,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,UAAU,CAAC,OAAO;YACtB,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC7C,OAAO,IAAI,CAAC,OAAO,CAAC;gBAClB,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,aAAa,CAAC,MAAM;gBAC1B,IAAI;gBACJ,MAAM,EAAE,iBAAiB;aAC1B,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
|