@crvouga/mockingbird-service-flex 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-flex
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
 
@@ -1816,7 +1849,42 @@ var verifyOperations = (document2, handlers) => {
1816
1849
  }
1817
1850
  return problems;
1818
1851
  };
1819
- var honoPath = (template) => template.replace(/\{([^}]+)\}/g, ":$1");
1852
+ var escapePattern = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1853
+ var serviceRoute = (template) => {
1854
+ const names = [];
1855
+ let pattern = "", end = 0;
1856
+ for (const match of template.matchAll(/\{([^}]+)\}/g)) {
1857
+ pattern += `${escapePattern(template.slice(end, match.index))}([^/]+?)`;
1858
+ const name = match[1];
1859
+ if (!name)
1860
+ throw new Error(`Invalid OpenAPI route template: ${template}`);
1861
+ names.push(name);
1862
+ end = match.index + match[0].length;
1863
+ }
1864
+ pattern += escapePattern(template.slice(end));
1865
+ const matcher = new RegExp(`^${pattern}$`);
1866
+ const path = template.split("/").map((segment, index) => {
1867
+ if (!segment.includes("{"))
1868
+ return segment;
1869
+ const literal = /^\{([^}]+)\}$/.exec(segment);
1870
+ if (literal)
1871
+ return `:${literal[1]}`;
1872
+ let expression = "", offset = 0;
1873
+ for (const match of segment.matchAll(/\{[^}]+\}/g)) {
1874
+ expression += `${escapePattern(segment.slice(offset, match.index))}[^/]+?`;
1875
+ offset = match.index + match[0].length;
1876
+ }
1877
+ expression += escapePattern(segment.slice(offset));
1878
+ return `:mockingbirdSegment${index}{${expression}}`;
1879
+ }).join("/");
1880
+ return {
1881
+ path,
1882
+ params: (pathname) => {
1883
+ const values = matcher.exec(pathname);
1884
+ return Object.fromEntries(names.map((name, index) => [name, decodeURIComponent(values?.[index + 1] ?? "")]));
1885
+ }
1886
+ };
1887
+ };
1820
1888
  var routeOrder = (a, b) => {
1821
1889
  const sa = a.path.split("/");
1822
1890
  const sb = b.path.split("/");
@@ -1851,6 +1919,7 @@ var createService = (options) => {
1851
1919
  for (const operation of operations) {
1852
1920
  const metadata = operationMetadata(operation.operation);
1853
1921
  const handler = options.handlers[operation.operationId];
1922
+ const registeredRoute = serviceRoute(operation.path);
1854
1923
  const route = async (c) => {
1855
1924
  const request = c.req.raw;
1856
1925
  if (!metadata.supported || !handler) {
@@ -1860,7 +1929,7 @@ var createService = (options) => {
1860
1929
  const context = {
1861
1930
  request,
1862
1931
  url,
1863
- params: c.req.param(),
1932
+ params: registeredRoute.params(url.pathname),
1864
1933
  query: queryOf(url),
1865
1934
  body: await readBody(request),
1866
1935
  sqlite: options.sqlite,
@@ -1872,7 +1941,7 @@ var createService = (options) => {
1872
1941
  const short = await options.before?.(context);
1873
1942
  return withIssues(request, short ?? await handler(context));
1874
1943
  };
1875
- app.on(operation.method.toUpperCase(), honoPath(operation.path), route);
1944
+ app.on(operation.method.toUpperCase(), registeredRoute.path, route);
1876
1945
  }
1877
1946
  return {
1878
1947
  app,
@@ -2341,7 +2410,7 @@ var stateAdminRoutes = (routes) => {
2341
2410
  };
2342
2411
 
2343
2412
  // ../core/dist/version.js
2344
- var PACKAGE_VERSION = true ? "2.1.0" : UNRELEASED_VERSION;
2413
+ var PACKAGE_VERSION = true ? "2.2.0" : UNRELEASED_VERSION;
2345
2414
 
2346
2415
  // ../core/dist/signing.js
2347
2416
  var encoder = new TextEncoder();
@@ -6010,4 +6079,4 @@ export {
6010
6079
  FlexAPI,
6011
6080
  isNextActionType
6012
6081
  };
6013
- //# sourceMappingURL=chunk-RE5NFS34.js.map
6082
+ //# sourceMappingURL=chunk-CVS7T7YF.js.map