@crvouga/mockingbird-service-prism 2.1.0 → 2.2.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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog — @crvouga/mockingbird-service-prism
2
2
 
3
+ ## 2.2.0 (2026-10-05)
4
+
5
+ ### Features
6
+
7
+ - add scripted local API mock ([4a76a11](https://github.com/crvouga/mockingbird/commit/4a76a114e2efad45934e0a93cf29576fd418e15c))
8
+
9
+ ### Fixes and improvements
10
+
11
+ - support embedded route parameters ([127cad9](https://github.com/crvouga/mockingbird/commit/127cad997ef106950c1b866070eea191ba54403f))
12
+
3
13
  ## 2.1.0 (2026-10-04)
4
14
 
5
15
  ### Features
@@ -12,10 +22,6 @@
12
22
  - fill the embedded viewport ([c1a35a4](https://github.com/crvouga/mockingbird/commit/c1a35a4789389ee9cd06c286d09bd47c4d06c71e))
13
23
  - make dialog cleanup immediate ([0c1a3c5](https://github.com/crvouga/mockingbird/commit/0c1a3c5b12584d50c19dcae595b951b8e5417b9c))
14
24
 
15
- ### Dependencies
16
-
17
- - `@crvouga/mockingbird-service-sqlite`
18
-
19
25
  ## 2.0.0 (2026-10-04)
20
26
 
21
27
  ### ⚠️ Breaking changes
@@ -1018,7 +1018,40 @@ var decodeBody = (contentType, bytes) => {
1018
1018
  return { kind: "bytes", value: bytes };
1019
1019
  };
1020
1020
  var readBody = async (message) => {
1021
- const bytes = new Uint8Array(await message.arrayBuffer());
1021
+ if (!(message instanceof Request) || !message.body) {
1022
+ if (message instanceof Request)
1023
+ message.signal.throwIfAborted();
1024
+ return decodeBody(message.headers.get("content-type"), new Uint8Array(await message.arrayBuffer()));
1025
+ }
1026
+ message.signal.throwIfAborted();
1027
+ const reader = message.body.getReader();
1028
+ const cancel = () => {
1029
+ void reader.cancel(message.signal.reason).catch(() => {
1030
+ });
1031
+ };
1032
+ message.signal.addEventListener("abort", cancel, { once: true });
1033
+ const chunks = [];
1034
+ let size = 0;
1035
+ try {
1036
+ for (; ; ) {
1037
+ message.signal.throwIfAborted();
1038
+ const { done, value } = await reader.read();
1039
+ message.signal.throwIfAborted();
1040
+ if (done)
1041
+ break;
1042
+ chunks.push(value);
1043
+ size += value.byteLength;
1044
+ }
1045
+ } finally {
1046
+ message.signal.removeEventListener("abort", cancel);
1047
+ reader.releaseLock();
1048
+ }
1049
+ const bytes = new Uint8Array(size);
1050
+ let offset = 0;
1051
+ for (const chunk of chunks) {
1052
+ bytes.set(chunk, offset);
1053
+ offset += chunk.byteLength;
1054
+ }
1022
1055
  return decodeBody(message.headers.get("content-type"), bytes);
1023
1056
  };
1024
1057
 
@@ -1756,7 +1789,42 @@ var verifyOperations = (document2, handlers) => {
1756
1789
  }
1757
1790
  return problems;
1758
1791
  };
1759
- var honoPath = (template) => template.replace(/\{([^}]+)\}/g, ":$1");
1792
+ var escapePattern = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1793
+ var serviceRoute = (template) => {
1794
+ const names = [];
1795
+ let pattern = "", end = 0;
1796
+ for (const match of template.matchAll(/\{([^}]+)\}/g)) {
1797
+ pattern += `${escapePattern(template.slice(end, match.index))}([^/]+?)`;
1798
+ const name = match[1];
1799
+ if (!name)
1800
+ throw new Error(`Invalid OpenAPI route template: ${template}`);
1801
+ names.push(name);
1802
+ end = match.index + match[0].length;
1803
+ }
1804
+ pattern += escapePattern(template.slice(end));
1805
+ const matcher = new RegExp(`^${pattern}$`);
1806
+ const path = template.split("/").map((segment, index) => {
1807
+ if (!segment.includes("{"))
1808
+ return segment;
1809
+ const literal = /^\{([^}]+)\}$/.exec(segment);
1810
+ if (literal)
1811
+ return `:${literal[1]}`;
1812
+ let expression = "", offset = 0;
1813
+ for (const match of segment.matchAll(/\{[^}]+\}/g)) {
1814
+ expression += `${escapePattern(segment.slice(offset, match.index))}[^/]+?`;
1815
+ offset = match.index + match[0].length;
1816
+ }
1817
+ expression += escapePattern(segment.slice(offset));
1818
+ return `:mockingbirdSegment${index}{${expression}}`;
1819
+ }).join("/");
1820
+ return {
1821
+ path,
1822
+ params: (pathname) => {
1823
+ const values = matcher.exec(pathname);
1824
+ return Object.fromEntries(names.map((name, index) => [name, decodeURIComponent(values?.[index + 1] ?? "")]));
1825
+ }
1826
+ };
1827
+ };
1760
1828
  var routeOrder = (a, b) => {
1761
1829
  const sa = a.path.split("/");
1762
1830
  const sb = b.path.split("/");
@@ -1791,6 +1859,7 @@ var createService = (options) => {
1791
1859
  for (const operation of operations) {
1792
1860
  const metadata = operationMetadata(operation.operation);
1793
1861
  const handler = options.handlers[operation.operationId];
1862
+ const registeredRoute = serviceRoute(operation.path);
1794
1863
  const route = async (c) => {
1795
1864
  const request = c.req.raw;
1796
1865
  if (!metadata.supported || !handler) {
@@ -1800,7 +1869,7 @@ var createService = (options) => {
1800
1869
  const context = {
1801
1870
  request,
1802
1871
  url,
1803
- params: c.req.param(),
1872
+ params: registeredRoute.params(url.pathname),
1804
1873
  query: queryOf(url),
1805
1874
  body: await readBody(request),
1806
1875
  sqlite: options.sqlite,
@@ -1812,7 +1881,7 @@ var createService = (options) => {
1812
1881
  const short = await options.before?.(context);
1813
1882
  return withIssues(request, short ?? await handler(context));
1814
1883
  };
1815
- app.on(operation.method.toUpperCase(), honoPath(operation.path), route);
1884
+ app.on(operation.method.toUpperCase(), registeredRoute.path, route);
1816
1885
  }
1817
1886
  return {
1818
1887
  app,
@@ -2281,7 +2350,7 @@ var stateAdminRoutes = (routes) => {
2281
2350
  };
2282
2351
 
2283
2352
  // ../core/dist/version.js
2284
- var PACKAGE_VERSION = true ? "2.1.0" : UNRELEASED_VERSION;
2353
+ var PACKAGE_VERSION = true ? "2.2.0" : UNRELEASED_VERSION;
2285
2354
 
2286
2355
  // ../core/dist/webhooks.js
2287
2356
  var json4 = (status, body) => new Response(JSON.stringify(body), {
@@ -3694,4 +3763,4 @@ export {
3694
3763
  scanResults,
3695
3764
  PrismAPI
3696
3765
  };
3697
- //# sourceMappingURL=chunk-BKLYZN3Q.js.map
3766
+ //# sourceMappingURL=chunk-3E7BNKAZ.js.map