@kensio/simnaril 0.1.2 → 0.1.4
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 +2 -0
- package/dist/api.d.ts +2 -2
- package/dist/bearer-token-error.d.ts +6 -0
- package/dist/bearer-token-error.d.ts.map +1 -0
- package/dist/bearer-token-error.js +15 -0
- package/dist/bearer-token-error.js.map +1 -0
- package/dist/environment.d.ts +2 -1
- package/dist/environment.d.ts.map +1 -1
- package/dist/environment.js +16 -7
- package/dist/environment.js.map +1 -1
- package/dist/http/operation-router.d.ts.map +1 -1
- package/dist/http/operation-router.js +11 -0
- package/dist/http/operation-router.js.map +1 -1
- package/dist/http/replay-idempotent-requests.d.ts +9 -0
- package/dist/http/replay-idempotent-requests.d.ts.map +1 -0
- package/dist/http/replay-idempotent-requests.js +46 -0
- package/dist/http/replay-idempotent-requests.js.map +1 -0
- package/dist/http/require-bearer-token.d.ts +12 -0
- package/dist/http/require-bearer-token.d.ts.map +1 -0
- package/dist/http/require-bearer-token.js +26 -0
- package/dist/http/require-bearer-token.js.map +1 -0
- package/dist/http/route.d.ts.map +1 -1
- package/dist/http/route.js +20 -9
- package/dist/http/route.js.map +1 -1
- package/dist/idempotency-key-reused-error.d.ts +7 -0
- package/dist/idempotency-key-reused-error.d.ts.map +1 -0
- package/dist/idempotency-key-reused-error.js +12 -0
- package/dist/idempotency-key-reused-error.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/unclaimed-origin-error.d.ts +1 -1
- package/dist/unclaimed-origin-error.d.ts.map +1 -1
- package/dist/unclaimed-origin-error.js +5 -2
- package/dist/unclaimed-origin-error.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -35,5 +35,7 @@ Simnaril requires Node.js 24 or later.
|
|
|
35
35
|
- [Request bodies](docs/request-bodies/README.md)
|
|
36
36
|
- [Custom operations](docs/custom-operations/README.md)
|
|
37
37
|
- [Middleware](docs/middleware/README.md)
|
|
38
|
+
- [Idempotent requests](docs/idempotent-requests/README.md)
|
|
38
39
|
- [Webhooks](docs/webhooks/README.md)
|
|
39
40
|
- [Composing a simulation](docs/composing-a-simulation/README.md)
|
|
41
|
+
- [Check a simulation against the real service](docs/checking-against-real-service/README.md)
|
package/dist/api.d.ts
CHANGED
|
@@ -19,8 +19,8 @@ export interface SimApiProps {
|
|
|
19
19
|
/**
|
|
20
20
|
* How a thrown error becomes a response.
|
|
21
21
|
*
|
|
22
|
-
* Runs before
|
|
23
|
-
*
|
|
22
|
+
* Runs before Simnaril's supplied error mappings. Declining an error with
|
|
23
|
+
* `undefined` leaves it to those mappings.
|
|
24
24
|
*/
|
|
25
25
|
formatError?: ErrorFormatter;
|
|
26
26
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Reports missing, malformed or unexpected bearer credentials. */
|
|
2
|
+
export declare class BearerTokenError extends Error {
|
|
3
|
+
readonly reason: "missing" | "malformed" | "mismatch";
|
|
4
|
+
constructor(reason: BearerTokenError["reason"]);
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=bearer-token-error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bearer-token-error.d.ts","sourceRoot":"","sources":["../src/bearer-token-error.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,UAAU,CAAC;IAEtD,YAAY,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,EAW7C;CACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Reports missing, malformed or unexpected bearer credentials. */
|
|
2
|
+
export class BearerTokenError extends Error {
|
|
3
|
+
reason;
|
|
4
|
+
constructor(reason) {
|
|
5
|
+
const messages = {
|
|
6
|
+
missing: "An Authorization header with a bearer token is required.",
|
|
7
|
+
malformed: "Expected an Authorization header containing one bearer token.",
|
|
8
|
+
mismatch: "The bearer token does not match the expected token.",
|
|
9
|
+
};
|
|
10
|
+
super(messages[reason]);
|
|
11
|
+
this.name = "BearerTokenError";
|
|
12
|
+
this.reason = reason;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=bearer-token-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bearer-token-error.js","sourceRoot":"","sources":["../src/bearer-token-error.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAChC,MAAM,CAAuC;IAEtD,YAAY,MAAkC;QAC5C,MAAM,QAAQ,GAAG;YACf,OAAO,EAAE,0DAA0D;YACnE,SAAS,EACP,+DAA+D;YACjE,QAAQ,EAAE,qDAAqD;SAChE,CAAC;QAEF,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF"}
|
package/dist/environment.d.ts
CHANGED
|
@@ -4,8 +4,9 @@ export interface SimService {
|
|
|
4
4
|
}
|
|
5
5
|
/** Selects what an environment does with requests outside every simulation. */
|
|
6
6
|
export type UnhandledRequestPolicy = "error" | "passthrough";
|
|
7
|
-
/** Configures
|
|
7
|
+
/** Configures a simulated environment. */
|
|
8
8
|
export interface SimEnvironmentProps {
|
|
9
|
+
name?: string;
|
|
9
10
|
unhandledRequest?: UnhandledRequestPolicy;
|
|
10
11
|
}
|
|
11
12
|
/** Routes HTTP requests to the simulated services registered with it. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../src/environment.ts"],"names":[],"mappings":"AAQA,uDAAuD;AACvD,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;CAC5D;AAED,+EAA+E;AAC/E,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,aAAa,CAAC;AAE7D,
|
|
1
|
+
{"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../src/environment.ts"],"names":[],"mappings":"AAQA,uDAAuD;AACvD,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;CAC5D;AAED,+EAA+E;AAC/E,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,aAAa,CAAC;AAE7D,0CAA0C;AAC1C,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,sBAAsB,CAAC;CAC3C;AAED,yEAAyE;AACzE,qBAAa,cAAe,YAAW,UAAU;;IAO/C,YAAY,KAAK,GAAE,mBAAwB,EAM1C;IAED,yEAAyE;IACzE,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,EAAE,OAAO,EAAE,UAAU,GAAG,IAAI,CA0BxD;IAED,yDAAyD;IACzD,OAAO,IAAI,IAAI,CAWd;IAED,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAEvB;CAoCF"}
|
package/dist/environment.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { interceptHttpRequests, } from "./http/interception.js";
|
|
2
2
|
import { UnclaimedOriginError } from "./unclaimed-origin-error.js";
|
|
3
|
-
const activeOrigins = new
|
|
3
|
+
const activeOrigins = new Map();
|
|
4
4
|
/** Routes HTTP requests to the simulated services registered with it. */
|
|
5
5
|
export class SimEnvironment {
|
|
6
6
|
#services = new Map();
|
|
7
7
|
#interception;
|
|
8
|
+
#name;
|
|
8
9
|
#unhandledRequest;
|
|
9
10
|
#disposed = false;
|
|
10
11
|
constructor(props = {}) {
|
|
12
|
+
this.#name = props.name;
|
|
11
13
|
this.#unhandledRequest = props.unhandledRequest ?? "error";
|
|
12
14
|
this.#interception = interceptHttpRequests((request) => this.#handle(request));
|
|
13
15
|
}
|
|
@@ -15,16 +17,18 @@ export class SimEnvironment {
|
|
|
15
17
|
register(origin, service) {
|
|
16
18
|
const normalizedOrigin = this.#normalizeOrigin(origin);
|
|
17
19
|
if (this.#disposed) {
|
|
18
|
-
throw new Error(`Cannot register ${normalizedOrigin} with a disposed
|
|
20
|
+
throw new Error(`Cannot register ${normalizedOrigin} with a disposed ${this.#description()}.`);
|
|
19
21
|
}
|
|
20
22
|
if (this.#services.has(normalizedOrigin)) {
|
|
21
|
-
|
|
23
|
+
const environment = this.#name === undefined ? "" : ` in ${this.#description()}`;
|
|
24
|
+
throw new Error(`A simulated service is already registered for ${normalizedOrigin}${environment}.`);
|
|
22
25
|
}
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
const activeEnvironment = activeOrigins.get(normalizedOrigin);
|
|
27
|
+
if (activeEnvironment !== undefined) {
|
|
28
|
+
throw new Error(`Another active ${activeEnvironment.#description()} is already registered for ${normalizedOrigin}.`);
|
|
25
29
|
}
|
|
26
30
|
this.#services.set(normalizedOrigin, service);
|
|
27
|
-
activeOrigins.
|
|
31
|
+
activeOrigins.set(normalizedOrigin, this);
|
|
28
32
|
}
|
|
29
33
|
/** Stops this environment from intercepting requests. */
|
|
30
34
|
dispose() {
|
|
@@ -50,7 +54,12 @@ export class SimEnvironment {
|
|
|
50
54
|
if (activeOrigins.has(origin) || this.#unhandledRequest === "passthrough") {
|
|
51
55
|
return undefined;
|
|
52
56
|
}
|
|
53
|
-
throw new UnclaimedOriginError(request);
|
|
57
|
+
throw new UnclaimedOriginError(request, this.#name);
|
|
58
|
+
}
|
|
59
|
+
#description() {
|
|
60
|
+
return this.#name === undefined
|
|
61
|
+
? "SimEnvironment"
|
|
62
|
+
: `SimEnvironment (${this.#name})`;
|
|
54
63
|
}
|
|
55
64
|
#normalizeOrigin(origin) {
|
|
56
65
|
const url = new URL(origin);
|
package/dist/environment.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"environment.js","sourceRoot":"","sources":["../src/environment.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,GAEtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAEnE,MAAM,aAAa,GAAG,IAAI,GAAG,
|
|
1
|
+
{"version":3,"file":"environment.js","sourceRoot":"","sources":["../src/environment.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operation-router.d.ts","sourceRoot":"","sources":["../../src/http/operation-router.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"operation-router.d.ts","sourceRoot":"","sources":["../../src/http/operation-router.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EAEd,MAAM,gBAAgB,CAAC;AAIxB,oEAAoE;AACpE,qBAAa,eAAe;;IAM1B,YAAY,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,cAAc,EAGxD;IAED,GAAG,CAAC,UAAU,EAAE,cAAc,GAAG,IAAI,CAEpC;IAED,QAAQ,CAAC,SAAS,EAAE,aAAa,GAAG,IAAI,CAEvC;IAEK,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CA0BhD;CAoEF"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { BearerTokenError } from "../bearer-token-error.js";
|
|
1
2
|
import { DuplicateEntityError } from "../duplicate-entity-error.js";
|
|
2
3
|
import { EntityNotFoundError } from "../entity-not-found-error.js";
|
|
4
|
+
import { IdempotencyKeyReusedError } from "../idempotency-key-reused-error.js";
|
|
3
5
|
import { UnimplementedRouteError } from "../unimplemented-route-error.js";
|
|
4
6
|
import { runHttpOperation, runMiddleware } from "./operation-pipeline.js";
|
|
5
7
|
/** Selects and runs registered operations for one simulated API. */
|
|
@@ -65,12 +67,21 @@ export class OperationRouter {
|
|
|
65
67
|
if (formatted !== undefined) {
|
|
66
68
|
return formatted;
|
|
67
69
|
}
|
|
70
|
+
if (error instanceof BearerTokenError) {
|
|
71
|
+
return Response.json({ error: error.message }, {
|
|
72
|
+
status: 401,
|
|
73
|
+
headers: { "WWW-Authenticate": "Bearer" },
|
|
74
|
+
});
|
|
75
|
+
}
|
|
68
76
|
if (error instanceof EntityNotFoundError) {
|
|
69
77
|
return Response.json({ error: error.message }, { status: 404 });
|
|
70
78
|
}
|
|
71
79
|
if (error instanceof DuplicateEntityError) {
|
|
72
80
|
return Response.json({ error: error.message }, { status: 409 });
|
|
73
81
|
}
|
|
82
|
+
if (error instanceof IdempotencyKeyReusedError) {
|
|
83
|
+
return Response.json({ error: error.message }, { status: 422 });
|
|
84
|
+
}
|
|
74
85
|
throw error;
|
|
75
86
|
}
|
|
76
87
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operation-router.js","sourceRoot":"","sources":["../../src/http/operation-router.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"operation-router.js","sourceRoot":"","sources":["../../src/http/operation-router.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { HttpMiddleware } from "./operation.js";
|
|
2
|
+
/** Configures idempotent request replay. */
|
|
3
|
+
export interface ReplayIdempotentRequestsProps {
|
|
4
|
+
/** The request header carrying the key. `Idempotency-Key` by default. */
|
|
5
|
+
headerName?: string;
|
|
6
|
+
}
|
|
7
|
+
/** Replays the first completed response for each idempotency key. */
|
|
8
|
+
export declare function replayIdempotentRequests(props?: ReplayIdempotentRequestsProps): HttpMiddleware;
|
|
9
|
+
//# sourceMappingURL=replay-idempotent-requests.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replay-idempotent-requests.d.ts","sourceRoot":"","sources":["../../src/http/replay-idempotent-requests.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,4CAA4C;AAC5C,MAAM,WAAW,6BAA6B;IAC5C,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAiDD,qEAAqE;AACrE,wBAAgB,wBAAwB,CACtC,KAAK,GAAE,6BAAkC,GACxC,cAAc,CA0BhB"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { IdempotencyKeyReusedError } from "../idempotency-key-reused-error.js";
|
|
2
|
+
const readBody = async (request) => request.body === null
|
|
3
|
+
? new Uint8Array()
|
|
4
|
+
: new Uint8Array(await request.clone().arrayBuffer());
|
|
5
|
+
const bodyEquals = (first, second) => {
|
|
6
|
+
if (first.byteLength !== second.byteLength) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
return first.every((byte, index) => byte === second[index]);
|
|
10
|
+
};
|
|
11
|
+
const fingerprintRequest = async (request) => {
|
|
12
|
+
const url = new URL(request.url);
|
|
13
|
+
return {
|
|
14
|
+
body: await readBody(request),
|
|
15
|
+
method: request.method,
|
|
16
|
+
pathname: url.pathname,
|
|
17
|
+
search: url.search,
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
const fingerprintEquals = (first, second) => first.method === second.method &&
|
|
21
|
+
first.pathname === second.pathname &&
|
|
22
|
+
first.search === second.search &&
|
|
23
|
+
bodyEquals(first.body, second.body);
|
|
24
|
+
/** Replays the first completed response for each idempotency key. */
|
|
25
|
+
export function replayIdempotentRequests(props = {}) {
|
|
26
|
+
const headerName = props.headerName ?? "Idempotency-Key";
|
|
27
|
+
const answered = new Map();
|
|
28
|
+
return async ({ request }, next) => {
|
|
29
|
+
const key = request.headers.get(headerName);
|
|
30
|
+
if (key === null) {
|
|
31
|
+
return next();
|
|
32
|
+
}
|
|
33
|
+
const fingerprint = await fingerprintRequest(request);
|
|
34
|
+
const held = answered.get(key);
|
|
35
|
+
if (held !== undefined) {
|
|
36
|
+
if (!fingerprintEquals(held.fingerprint, fingerprint)) {
|
|
37
|
+
throw new IdempotencyKeyReusedError(key, headerName);
|
|
38
|
+
}
|
|
39
|
+
return held.response.clone();
|
|
40
|
+
}
|
|
41
|
+
const response = await next();
|
|
42
|
+
answered.set(key, { fingerprint, response: response.clone() });
|
|
43
|
+
return response;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=replay-idempotent-requests.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replay-idempotent-requests.js","sourceRoot":"","sources":["../../src/http/replay-idempotent-requests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AAqB/E,MAAM,QAAQ,GAAG,KAAK,EAAE,OAAgB,EAAuB,EAAE,CAC/D,OAAO,CAAC,IAAI,KAAK,IAAI;IACnB,CAAC,CAAC,IAAI,UAAU,EAAE;IAClB,CAAC,CAAC,IAAI,UAAU,CAAC,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;AAE1D,MAAM,UAAU,GAAG,CAAC,KAAiB,EAAE,MAAkB,EAAW,EAAE;IACpE,IAAI,KAAK,CAAC,UAAU,KAAK,MAAM,CAAC,UAAU,EAAE,CAAC;QAC3C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,KAAK,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AAC9D,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,KAAK,EAC9B,OAAgB,EACa,EAAE;IAC/B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAEjC,OAAO;QACL,IAAI,EAAE,MAAM,QAAQ,CAAC,OAAO,CAAC;QAC7B,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,MAAM,EAAE,GAAG,CAAC,MAAM;KACnB,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CACxB,KAAyB,EACzB,MAA0B,EACjB,EAAE,CACX,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM;IAC9B,KAAK,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ;IAClC,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM;IAC9B,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;AAEtC,qEAAqE;AACrE,MAAM,UAAU,wBAAwB,CACtC,KAAK,GAAkC,EAAE;IAEzC,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,IAAI,iBAAiB,CAAC;IACzD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA2B,CAAC;IAEpD,OAAO,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,EAAE;QACjC,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAE5C,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACjB,OAAO,IAAI,EAAE,CAAC;QAChB,CAAC;QAED,MAAM,WAAW,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAE/B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC;gBACtD,MAAM,IAAI,yBAAyB,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;YACvD,CAAC;YAED,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QAC/B,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,IAAI,EAAE,CAAC;QAC9B,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC/D,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ErrorFormatter } from "./error-formatter.js";
|
|
2
|
+
import type { HttpMiddleware } from "./operation.js";
|
|
3
|
+
/** Configures bearer authentication for the operations using this middleware. */
|
|
4
|
+
export interface RequireBearerTokenProps {
|
|
5
|
+
/** The exact, case-sensitive token accepted by this simulated service. */
|
|
6
|
+
token: string;
|
|
7
|
+
/** Formats a refusal. Returning undefined leaves it to the API's error handling. */
|
|
8
|
+
formatError?: ErrorFormatter;
|
|
9
|
+
}
|
|
10
|
+
/** Requires the configured bearer token before running an operation. */
|
|
11
|
+
export declare function requireBearerToken(props: RequireBearerTokenProps): HttpMiddleware;
|
|
12
|
+
//# sourceMappingURL=require-bearer-token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require-bearer-token.d.ts","sourceRoot":"","sources":["../../src/http/require-bearer-token.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,iFAAiF;AACjF,MAAM,WAAW,uBAAuB;IACtC,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,oFAAoF;IACpF,WAAW,CAAC,EAAE,cAAc,CAAC;CAC9B;AAED,wEAAwE;AACxE,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,uBAAuB,GAC7B,cAAc,CAgChB"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { BearerTokenError } from "../bearer-token-error.js";
|
|
2
|
+
/** Requires the configured bearer token before running an operation. */
|
|
3
|
+
export function requireBearerToken(props) {
|
|
4
|
+
const { token, formatError } = props;
|
|
5
|
+
return ({ request }, next) => {
|
|
6
|
+
const authorization = request.headers.get("authorization");
|
|
7
|
+
// RFC 6750 section 2.1 permits ASCII token characters and one or more spaces.
|
|
8
|
+
// https://www.rfc-editor.org/rfc/rfc6750.html#section-2.1
|
|
9
|
+
const credentials = /^([A-Za-z]+) +([A-Za-z\d._~+/-]+=*)$/u.exec(authorization ?? "");
|
|
10
|
+
const suppliedToken = credentials?.[1]?.toLowerCase() === "bearer" ? credentials[2] : undefined;
|
|
11
|
+
if (suppliedToken !== undefined && suppliedToken === token) {
|
|
12
|
+
return next();
|
|
13
|
+
}
|
|
14
|
+
const error = new BearerTokenError(authorization === null
|
|
15
|
+
? "missing"
|
|
16
|
+
: suppliedToken === undefined
|
|
17
|
+
? "malformed"
|
|
18
|
+
: "mismatch");
|
|
19
|
+
const formatted = formatError?.(error);
|
|
20
|
+
if (formatted !== undefined) {
|
|
21
|
+
return formatted;
|
|
22
|
+
}
|
|
23
|
+
throw error;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=require-bearer-token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require-bearer-token.js","sourceRoot":"","sources":["../../src/http/require-bearer-token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAY5D,wEAAwE;AACxE,MAAM,UAAU,kBAAkB,CAChC,KAA8B;IAE9B,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,KAAK,CAAC;IAErC,OAAO,CAAC,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,EAAE;QAC3B,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAC3D,8EAA8E;QAC9E,0DAA0D;QAC1D,MAAM,WAAW,GAAG,uCAAuC,CAAC,IAAI,CAC9D,aAAa,IAAI,EAAE,CACpB,CAAC;QACF,MAAM,aAAa,GACjB,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAE5E,IAAI,aAAa,KAAK,SAAS,IAAI,aAAa,KAAK,KAAK,EAAE,CAAC;YAC3D,OAAO,IAAI,EAAE,CAAC;QAChB,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,gBAAgB,CAChC,aAAa,KAAK,IAAI;YACpB,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,aAAa,KAAK,SAAS;gBAC3B,CAAC,CAAC,WAAW;gBACb,CAAC,CAAC,UAAU,CACjB,CAAC;QACF,MAAM,SAAS,GAAG,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC;QAEvC,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,KAAK,CAAC;IACd,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/http/route.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../src/http/route.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,UAAU,GAAG,SAAS,CAAC;IACpD,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,gEAAgE;AAChE,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,kBAAkB,GAAE,SAAS,MAAM,EAAO,GACzC,aAAa,
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../src/http/route.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,UAAU,GAAG,SAAS,CAAC;IACpD,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,gEAAgE;AAChE,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,kBAAkB,GAAE,SAAS,MAAM,EAAO,GACzC,aAAa,CAgGf;AAED,6DAA6D;AAC7D,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAexD;AAED,gDAAgD;AAChD,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAMtD"}
|
package/dist/http/route.js
CHANGED
|
@@ -3,30 +3,36 @@ export function compileRoute(path, requiredParameters = []) {
|
|
|
3
3
|
validateOperationPath(path);
|
|
4
4
|
const segments = path === "/" ? [] : path.slice(1).split("/");
|
|
5
5
|
const parameterNames = new Set();
|
|
6
|
+
const parameters = new Map();
|
|
7
|
+
let suffixLength = 0;
|
|
6
8
|
for (const segment of segments) {
|
|
7
9
|
if (!segment.startsWith(":")) {
|
|
8
10
|
continue;
|
|
9
11
|
}
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
+
const parsed = /^:([A-Za-z_][A-Za-z\d_]*)(:[A-Za-z_][A-Za-z\d_]*)?$/u.exec(segment);
|
|
13
|
+
const name = parsed?.[1];
|
|
14
|
+
if (name === undefined) {
|
|
12
15
|
throw new TypeError(`Expected a named path parameter such as ":id", received "${segment}".`);
|
|
13
16
|
}
|
|
14
17
|
if (parameterNames.has(name)) {
|
|
15
18
|
throw new TypeError(`Path parameter ":${name}" appears more than once.`);
|
|
16
19
|
}
|
|
20
|
+
const suffix = parsed?.[2] ?? "";
|
|
17
21
|
parameterNames.add(name);
|
|
22
|
+
parameters.set(segment, { name, suffix });
|
|
23
|
+
suffixLength += suffix.length;
|
|
18
24
|
}
|
|
19
25
|
for (const name of requiredParameters) {
|
|
20
26
|
if (!parameterNames.has(name)) {
|
|
21
27
|
throw new TypeError(`Operation path "${path}" must include path parameter ":${name}".`);
|
|
22
28
|
}
|
|
23
29
|
}
|
|
24
|
-
const literalSegments = segments.filter((segment) => !
|
|
25
|
-
const literalLength = segments
|
|
26
|
-
.filter((segment) => !segment.startsWith(":"))
|
|
27
|
-
.join("/").length;
|
|
30
|
+
const literalSegments = segments.filter((segment) => !parameters.has(segment));
|
|
28
31
|
return {
|
|
29
|
-
specificity: literalSegments
|
|
32
|
+
specificity: literalSegments.length * 1_000_000 +
|
|
33
|
+
segments.length * 1000 +
|
|
34
|
+
literalSegments.join("/").length +
|
|
35
|
+
suffixLength,
|
|
30
36
|
match: (pathname) => {
|
|
31
37
|
const candidateSegments = pathname === "/" ? [] : pathname.slice(1).split("/");
|
|
32
38
|
if (candidateSegments.length !== segments.length) {
|
|
@@ -38,14 +44,19 @@ export function compileRoute(path, requiredParameters = []) {
|
|
|
38
44
|
if (candidate.length === 0) {
|
|
39
45
|
return undefined;
|
|
40
46
|
}
|
|
41
|
-
|
|
47
|
+
const parameter = parameters.get(segment);
|
|
48
|
+
if (parameter === undefined) {
|
|
42
49
|
if (candidate !== segment) {
|
|
43
50
|
return undefined;
|
|
44
51
|
}
|
|
45
52
|
continue;
|
|
46
53
|
}
|
|
54
|
+
if (!candidate.endsWith(parameter.suffix) ||
|
|
55
|
+
candidate.length <= parameter.suffix.length) {
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
47
58
|
try {
|
|
48
|
-
params[
|
|
59
|
+
params[parameter.name] = decodeURIComponent(candidate.slice(0, candidate.length - parameter.suffix.length));
|
|
49
60
|
}
|
|
50
61
|
catch {
|
|
51
62
|
return undefined;
|
package/dist/http/route.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../src/http/route.ts"],"names":[],"mappings":"AASA,gEAAgE;AAChE,MAAM,UAAU,YAAY,CAC1B,IAAY,EACZ,kBAAkB,GAAsB,EAAE;IAE1C,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAC5B,MAAM,QAAQ,GAAG,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9D,MAAM,cAAc,GAAG,IAAI,GAAG,EAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../src/http/route.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Reports an idempotency key reused for a different HTTP request. */
|
|
2
|
+
export declare class IdempotencyKeyReusedError extends Error {
|
|
3
|
+
readonly headerName: string;
|
|
4
|
+
readonly key: string;
|
|
5
|
+
constructor(key: string, headerName?: string);
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=idempotency-key-reused-error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idempotency-key-reused-error.d.ts","sourceRoot":"","sources":["../src/idempotency-key-reused-error.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAErB,YAAY,GAAG,EAAE,MAAM,EAAE,UAAU,SAAoB,EAOtD;CACF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Reports an idempotency key reused for a different HTTP request. */
|
|
2
|
+
export class IdempotencyKeyReusedError extends Error {
|
|
3
|
+
headerName;
|
|
4
|
+
key;
|
|
5
|
+
constructor(key, headerName = "Idempotency-Key") {
|
|
6
|
+
super(`${headerName} value "${key}" has already been used for a different request.`);
|
|
7
|
+
this.name = "IdempotencyKeyReusedError";
|
|
8
|
+
this.headerName = headerName;
|
|
9
|
+
this.key = key;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=idempotency-key-reused-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idempotency-key-reused-error.js","sourceRoot":"","sources":["../src/idempotency-key-reused-error.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IACzC,UAAU,CAAS;IACnB,GAAG,CAAS;IAErB,YAAY,GAAW,EAAE,UAAU,GAAG,iBAAiB;QACrD,KAAK,CACH,GAAG,UAAU,WAAW,GAAG,kDAAkD,CAC9E,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;QACxC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,CAAC;CACF"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
export { SimApi, type SimApiProps, type SimApiResourceProps } from "./api.js";
|
|
2
2
|
export { SimEnvironment, type SimEnvironmentProps, type SimService, type UnhandledRequestPolicy, } from "./environment.js";
|
|
3
|
+
export { BearerTokenError } from "./bearer-token-error.js";
|
|
4
|
+
export { requireBearerToken, type RequireBearerTokenProps, } from "./http/require-bearer-token.js";
|
|
3
5
|
export { DuplicateEntityError } from "./duplicate-entity-error.js";
|
|
4
6
|
export { EntityNotFoundError } from "./entity-not-found-error.js";
|
|
7
|
+
export { IdempotencyKeyReusedError } from "./idempotency-key-reused-error.js";
|
|
8
|
+
export { replayIdempotentRequests, type ReplayIdempotentRequestsProps, } from "./http/replay-idempotent-requests.js";
|
|
5
9
|
export type { HttpMiddleware, HttpOperationContext, RawHttpOperation, SemanticOperationContext, SemanticOperationOverride, } from "./http/operation.js";
|
|
6
10
|
export { SemanticOperation } from "./http/operation.js";
|
|
7
11
|
export { decodeForm } from "./http/decode-form.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,KAAK,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAC9E,OAAO,EACL,cAAc,EACd,KAAK,mBAAmB,EACxB,KAAK,UAAU,EACf,KAAK,sBAAsB,GAC5B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,YAAY,EACV,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EAChB,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,YAAY,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,YAAY,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EACV,eAAe,EACf,sBAAsB,EACtB,kCAAkC,EAClC,yBAAyB,EACzB,4BAA4B,EAC5B,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EACL,WAAW,EACX,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,GAC3B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,KAAK,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAC9E,OAAO,EACL,cAAc,EACd,KAAK,mBAAmB,EACxB,KAAK,UAAU,EACf,KAAK,sBAAsB,GAC5B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EACL,kBAAkB,EAClB,KAAK,uBAAuB,GAC7B,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EACL,wBAAwB,EACxB,KAAK,6BAA6B,GACnC,MAAM,sCAAsC,CAAC;AAC9C,YAAY,EACV,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EAChB,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,YAAY,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,YAAY,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EACV,eAAe,EACf,sBAAsB,EACtB,kCAAkC,EAClC,yBAAyB,EACzB,4BAA4B,EAC5B,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EACL,WAAW,EACX,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,GAC3B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
export { SimApi } from "./api.js";
|
|
2
2
|
export { SimEnvironment, } from "./environment.js";
|
|
3
|
+
export { BearerTokenError } from "./bearer-token-error.js";
|
|
4
|
+
export { requireBearerToken, } from "./http/require-bearer-token.js";
|
|
3
5
|
export { DuplicateEntityError } from "./duplicate-entity-error.js";
|
|
4
6
|
export { EntityNotFoundError } from "./entity-not-found-error.js";
|
|
7
|
+
export { IdempotencyKeyReusedError } from "./idempotency-key-reused-error.js";
|
|
8
|
+
export { replayIdempotentRequests, } from "./http/replay-idempotent-requests.js";
|
|
5
9
|
export { SemanticOperation } from "./http/operation.js";
|
|
6
10
|
export { decodeForm } from "./http/decode-form.js";
|
|
7
11
|
export { requirePathParameter } from "./http/path-parameter.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAA8C,MAAM,UAAU,CAAC;AAC9E,OAAO,EACL,cAAc,GAIf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAA8C,MAAM,UAAU,CAAC;AAC9E,OAAO,EACL,cAAc,GAIf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EACL,kBAAkB,GAEnB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EACL,wBAAwB,GAEzB,MAAM,sCAAsC,CAAC;AAQ9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAEhE,OAAO,EAAE,UAAU,EAAuB,MAAM,2BAA2B,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAUlD,OAAO,EAAE,WAAW,EAAyB,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EACL,WAAW,GAKZ,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC"}
|
|
@@ -3,6 +3,6 @@ export declare class UnclaimedOriginError extends Error {
|
|
|
3
3
|
readonly method: string;
|
|
4
4
|
readonly origin: string;
|
|
5
5
|
readonly url: string;
|
|
6
|
-
constructor(request: Request);
|
|
6
|
+
constructor(request: Request, environmentName?: string);
|
|
7
7
|
}
|
|
8
8
|
//# sourceMappingURL=unclaimed-origin-error.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unclaimed-origin-error.d.ts","sourceRoot":"","sources":["../src/unclaimed-origin-error.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAErB,YAAY,OAAO,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"unclaimed-origin-error.d.ts","sourceRoot":"","sources":["../src/unclaimed-origin-error.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAErB,YAAY,OAAO,EAAE,OAAO,EAAE,eAAe,CAAC,EAAE,MAAM,EAerD;CACF"}
|
|
@@ -3,10 +3,13 @@ export class UnclaimedOriginError extends Error {
|
|
|
3
3
|
method;
|
|
4
4
|
origin;
|
|
5
5
|
url;
|
|
6
|
-
constructor(request) {
|
|
6
|
+
constructor(request, environmentName) {
|
|
7
7
|
const url = new URL(request.url);
|
|
8
8
|
const method = request.method.toUpperCase();
|
|
9
|
-
|
|
9
|
+
const environment = environmentName === undefined
|
|
10
|
+
? "SimEnvironment"
|
|
11
|
+
: `SimEnvironment (${environmentName})`;
|
|
12
|
+
super(`${method} ${request.url} reached ${environment}, but no simulated service is registered for origin ${url.origin}.`);
|
|
10
13
|
this.name = "UnclaimedOriginError";
|
|
11
14
|
this.method = method;
|
|
12
15
|
this.origin = url.origin;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unclaimed-origin-error.js","sourceRoot":"","sources":["../src/unclaimed-origin-error.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IACpC,MAAM,CAAS;IACf,MAAM,CAAS;IACf,GAAG,CAAS;IAErB,YAAY,OAAgB;
|
|
1
|
+
{"version":3,"file":"unclaimed-origin-error.js","sourceRoot":"","sources":["../src/unclaimed-origin-error.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IACpC,MAAM,CAAS;IACf,MAAM,CAAS;IACf,GAAG,CAAS;IAErB,YAAY,OAAgB,EAAE,eAAwB;QACpD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;QAC5C,MAAM,WAAW,GACf,eAAe,KAAK,SAAS;YAC3B,CAAC,CAAC,gBAAgB;YAClB,CAAC,CAAC,mBAAmB,eAAe,GAAG,CAAC;QAE5C,KAAK,CACH,GAAG,MAAM,IAAI,OAAO,CAAC,GAAG,YAAY,WAAW,uDAAuD,GAAG,CAAC,MAAM,GAAG,CACpH,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;QACzB,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IACzB,CAAC;CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kensio/simnaril",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "In-process simulation of third-party HTTP services",
|
|
5
5
|
"repository": "https://github.com/KensioSoftware/simnaril",
|
|
6
6
|
"bugs": "https://github.com/KensioSoftware/simnaril/issues",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"@vitest/coverage-v8": "^4.1.11",
|
|
51
51
|
"conventional-changelog-conventionalcommits": "9.3.1",
|
|
52
52
|
"fta-cli": "^3.0.0",
|
|
53
|
-
"oxfmt": "^0.
|
|
53
|
+
"oxfmt": "^0.66.0",
|
|
54
54
|
"oxlint": "^1.80.0",
|
|
55
55
|
"oxlint-tsgolint": "^7.0.2001",
|
|
56
56
|
"semantic-release": "25.0.9",
|