@crvouga/mockingbird-service-twilio 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,17 @@
1
1
  # Changelog — @crvouga/mockingbird-service-twilio
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
+ - list Messages with SDK pagination ([d5cff54](https://github.com/crvouga/mockingbird/commit/d5cff5444878cdcd0177eddd5b8c598a7564478e))
9
+
10
+ ### Fixes and improvements
11
+
12
+ - support embedded route parameters ([127cad9](https://github.com/crvouga/mockingbird/commit/127cad997ef106950c1b866070eea191ba54403f))
13
+ - preserve namespace URLs after main sync ([62a15ce](https://github.com/crvouga/mockingbird/commit/62a15ce9bd453069bde69e3a30c91efc01f8871b))
14
+
3
15
  ## 2.1.0 (2026-10-04)
4
16
 
5
17
  ### Features
@@ -12,10 +24,6 @@
12
24
  - fill the embedded viewport ([c1a35a4](https://github.com/crvouga/mockingbird/commit/c1a35a4789389ee9cd06c286d09bd47c4d06c71e))
13
25
  - make dialog cleanup immediate ([0c1a3c5](https://github.com/crvouga/mockingbird/commit/0c1a3c5b12584d50c19dcae595b951b8e5417b9c))
14
26
 
15
- ### Dependencies
16
-
17
- - `@crvouga/mockingbird-service-sqlite`
18
-
19
27
  ## 2.0.0 (2026-10-04)
20
28
 
21
29
  ### ⚠️ Breaking changes
package/README.md CHANGED
@@ -92,6 +92,7 @@ const { code, sid, status } = (await latest.json()) as { code: string; sid: stri
92
92
  | `GET` / `POST /verify/v2/Services/{VA}/Verifications/{VE}` | Fetches a verification, or sets `Status=canceled\|approved` on one. |
93
93
  | `POST /api/2010-04-01/Accounts/{AC}/Messages.json` | `To`, `Body` or `MediaUrl`, and `From` or `MessagingServiceSid`. Returns 201 with an `SM…` sid (`MM…` with media) and RFC 2822 dates. `MessagingServiceSid` alone is status `accepted`, `from: null`, `num_segments: "0"` (a sender is not chosen yet). `From` alone is status `queued`. Both are kept and the status is `queued` (Twilio queues on a specific sender). There is no idempotency key: the same body creates another sid. Errors: 21604 (no To), 21602 (no Body), 21603 (no From), 21211 (invalid To), 21617 (over 1600 characters). The message is recorded in the outbox. |
94
94
  | `GET /api/2010-04-01/Accounts/{AC}/Messages/{SM}.json` | Reads a message back. |
95
+ | `GET /api/2010-04-01/Accounts/{AC}/Messages.json` | Newest-first Message resources for that account. `PageSize` defaults to 50 (1–1000), `PageToken` follows `next_page_uri`/`previous_page_uri`; `Page` is client state. Links keep the vendor path without `/api`, so apply the normal product-prefix rewrite. `To` and `From` filter stored resources. |
95
96
  | `GET /api/2010-04-01/Accounts/{AC}/Recordings/{RE}.wav` | The recording as a RIFF WAV. With `RequestedChannels=2` you get both channels. Otherwise a dual-channel recording is mixed down to mono, as Twilio does. |
96
97
  | `GET` / `DELETE /api/2010-04-01/Accounts/{AC}/Recordings/{RE}.json` | Metadata, or a delete (204; a second delete is 404, which our consumer tolerates). |
97
98
 
@@ -145,6 +146,7 @@ can also come from the `x-mockingbird-namespace` header or a `/__admin/ns/<name>
145
146
 
146
147
  - Delivery: messages stay `queued`/`accepted`, no status callbacks are sent (our consumer sets no
147
148
  `statusCallback`), and no voice calls, conferences or media streams happen.
149
+ - Message collection `DateSent` filters (messages are never sent by the mock).
148
150
  - Paid Lookup data packages (`Fields=line_type_intelligence`, `caller_name`, …) are always
149
151
  `null`.
150
152
  - Verify channels other than SMS are accepted and recorded, but nothing is delivered. Verify
package/SUPPORT.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  Generated from `openapi.yaml`; do not edit by hand.
4
4
 
5
- - operations in spec: **10**
6
- - supported by the mock: **10**
7
- - parity enabled: **10**
5
+ - operations in spec: **11**
6
+ - supported by the mock: **11**
7
+ - parity enabled: **11**
8
8
 
9
9
  | operationId | route | mock | parity | notes |
10
10
  | --- | --- | --- | --- | --- |
@@ -13,6 +13,7 @@ Generated from `openapi.yaml`; do not edit by hand.
13
13
  | `FetchVerification` | `GET /verify/v2/Services/{ServiceSid}/Verifications/{Sid}` | ✅ supported | ✅ | |
14
14
  | `UpdateVerification` | `POST /verify/v2/Services/{ServiceSid}/Verifications/{Sid}` | ✅ supported | ⚠️ unsafe (opt-in) | |
15
15
  | `CreateVerificationCheck` | `POST /verify/v2/Services/{ServiceSid}/VerificationCheck` | ✅ supported | ⚠️ unsafe (opt-in) | |
16
+ | `ListMessages` | `GET /api/2010-04-01/Accounts/{AccountSid}/Messages.json` | ✅ supported | ✅ | |
16
17
  | `CreateMessage` | `POST /api/2010-04-01/Accounts/{AccountSid}/Messages.json` | ✅ supported | ⚠️ unsafe (opt-in) | |
17
18
  | `FetchMessage` | `GET /api/2010-04-01/Accounts/{AccountSid}/Messages/{Sid}.json` | ✅ supported | ✅ | |
18
19
  | `FetchRecordingMedia` | `GET /api/2010-04-01/Accounts/{AccountSid}/Recordings/{Sid}.wav` | ✅ supported | ✅ | |
@@ -3,7 +3,7 @@ import {
3
3
  createRuntime,
4
4
  parseDuration,
5
5
  resolveAdminPrefix
6
- } from "./chunk-I5WWNGOK.js";
6
+ } from "./chunk-JTHJGMYU.js";
7
7
 
8
8
  // ../../adapters/node/dist/cli.js
9
9
  import { readFile as readFile2 } from "node:fs/promises";
@@ -876,4 +876,4 @@ export {
876
876
  createServer2 as createServer,
877
877
  serveTarget
878
878
  };
879
- //# sourceMappingURL=chunk-WLSA4EV6.js.map
879
+ //# sourceMappingURL=chunk-GTSJHMZV.js.map
@@ -838,7 +838,40 @@ var decodeBody = (contentType, bytes) => {
838
838
  return { kind: "bytes", value: bytes };
839
839
  };
840
840
  var readBody = async (message) => {
841
- const bytes = new Uint8Array(await message.arrayBuffer());
841
+ if (!(message instanceof Request) || !message.body) {
842
+ if (message instanceof Request)
843
+ message.signal.throwIfAborted();
844
+ return decodeBody(message.headers.get("content-type"), new Uint8Array(await message.arrayBuffer()));
845
+ }
846
+ message.signal.throwIfAborted();
847
+ const reader = message.body.getReader();
848
+ const cancel = () => {
849
+ void reader.cancel(message.signal.reason).catch(() => {
850
+ });
851
+ };
852
+ message.signal.addEventListener("abort", cancel, { once: true });
853
+ const chunks = [];
854
+ let size = 0;
855
+ try {
856
+ for (; ; ) {
857
+ message.signal.throwIfAborted();
858
+ const { done, value } = await reader.read();
859
+ message.signal.throwIfAborted();
860
+ if (done)
861
+ break;
862
+ chunks.push(value);
863
+ size += value.byteLength;
864
+ }
865
+ } finally {
866
+ message.signal.removeEventListener("abort", cancel);
867
+ reader.releaseLock();
868
+ }
869
+ const bytes = new Uint8Array(size);
870
+ let offset = 0;
871
+ for (const chunk of chunks) {
872
+ bytes.set(chunk, offset);
873
+ offset += chunk.byteLength;
874
+ }
842
875
  return decodeBody(message.headers.get("content-type"), bytes);
843
876
  };
844
877
 
@@ -1572,7 +1605,42 @@ var verifyOperations = (document2, handlers) => {
1572
1605
  }
1573
1606
  return problems;
1574
1607
  };
1575
- var honoPath = (template) => template.replace(/\{([^}]+)\}/g, ":$1");
1608
+ var escapePattern = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1609
+ var serviceRoute = (template) => {
1610
+ const names = [];
1611
+ let pattern = "", end = 0;
1612
+ for (const match of template.matchAll(/\{([^}]+)\}/g)) {
1613
+ pattern += `${escapePattern(template.slice(end, match.index))}([^/]+?)`;
1614
+ const name = match[1];
1615
+ if (!name)
1616
+ throw new Error(`Invalid OpenAPI route template: ${template}`);
1617
+ names.push(name);
1618
+ end = match.index + match[0].length;
1619
+ }
1620
+ pattern += escapePattern(template.slice(end));
1621
+ const matcher = new RegExp(`^${pattern}$`);
1622
+ const path = template.split("/").map((segment, index) => {
1623
+ if (!segment.includes("{"))
1624
+ return segment;
1625
+ const literal = /^\{([^}]+)\}$/.exec(segment);
1626
+ if (literal)
1627
+ return `:${literal[1]}`;
1628
+ let expression = "", offset = 0;
1629
+ for (const match of segment.matchAll(/\{[^}]+\}/g)) {
1630
+ expression += `${escapePattern(segment.slice(offset, match.index))}[^/]+?`;
1631
+ offset = match.index + match[0].length;
1632
+ }
1633
+ expression += escapePattern(segment.slice(offset));
1634
+ return `:mockingbirdSegment${index}{${expression}}`;
1635
+ }).join("/");
1636
+ return {
1637
+ path,
1638
+ params: (pathname) => {
1639
+ const values = matcher.exec(pathname);
1640
+ return Object.fromEntries(names.map((name, index) => [name, decodeURIComponent(values?.[index + 1] ?? "")]));
1641
+ }
1642
+ };
1643
+ };
1576
1644
  var routeOrder = (a, b) => {
1577
1645
  const sa = a.path.split("/");
1578
1646
  const sb = b.path.split("/");
@@ -1607,6 +1675,7 @@ var createService = (options) => {
1607
1675
  for (const operation of operations) {
1608
1676
  const metadata = operationMetadata(operation.operation);
1609
1677
  const handler = options.handlers[operation.operationId];
1678
+ const registeredRoute = serviceRoute(operation.path);
1610
1679
  const route = async (c) => {
1611
1680
  const request = c.req.raw;
1612
1681
  if (!metadata.supported || !handler) {
@@ -1616,7 +1685,7 @@ var createService = (options) => {
1616
1685
  const context = {
1617
1686
  request,
1618
1687
  url,
1619
- params: c.req.param(),
1688
+ params: registeredRoute.params(url.pathname),
1620
1689
  query: queryOf(url),
1621
1690
  body: await readBody(request),
1622
1691
  sqlite: options.sqlite,
@@ -1628,7 +1697,7 @@ var createService = (options) => {
1628
1697
  const short = await options.before?.(context);
1629
1698
  return withIssues(request, short ?? await handler(context));
1630
1699
  };
1631
- app.on(operation.method.toUpperCase(), honoPath(operation.path), route);
1700
+ app.on(operation.method.toUpperCase(), registeredRoute.path, route);
1632
1701
  }
1633
1702
  return {
1634
1703
  app,
@@ -2097,7 +2166,7 @@ var stateAdminRoutes = (routes) => {
2097
2166
  };
2098
2167
 
2099
2168
  // ../core/dist/version.js
2100
- var PACKAGE_VERSION = true ? "2.1.0" : UNRELEASED_VERSION;
2169
+ var PACKAGE_VERSION = true ? "2.2.0" : UNRELEASED_VERSION;
2101
2170
 
2102
2171
  // ../core/dist/signing.js
2103
2172
  var encoder = new TextEncoder();
@@ -3283,9 +3352,9 @@ var presetRoutes = (presets, runtime, adminPrefix) => ({
3283
3352
  });
3284
3353
 
3285
3354
  // src/generated/openapi.ts
3286
- var document = JSON.parse(`{"openapi":"3.1.0","info":{"title":"Twilio Verify, Lookup, Messaging and Recordings (Mockingbird subset)","description":"Stateful mock subset of Twilio, served on one port. Each product keeps its own host upstream\\n(api.twilio.com, verify.twilio.com, lookups.twilio.com); the mock routes by that host carried\\nas a path prefix (\`/api/\u2026\`, \`/verify/\u2026\`, \`/lookups/\u2026\`), which is what a custom twilio-node\\n\`httpClient\` produces when it rewrites \`https://<product>.twilio.com/<path>\` to\\n\`{mock}/<product>/<path>\`. Hand-authored from Twilio's published API reference, trimmed to\\nwhat our consumer calls, and checked against live Lookup v2 responses.\\n","version":"2010-04-01","x-mockingbird-upstream":{"note":"Trimmed from Twilio's public API reference (twilio-oai) to the operations our consumer calls (twilio.service.ts, twilio-conversation-sms.adapter.ts, notification-dispatcher channels/sms.ts, twilio-recording-http.adapter.ts); Lookup v2 shapes verified against the live API."}},"servers":[{"url":"https://api.twilio.com","description":"Every product on one origin, routed by the /api, /verify or /lookups prefix."}],"security":[{"basicAuth":[]}],"paths":{"/lookups/v2/PhoneNumbers/{PhoneNumber}":{"parameters":[{"name":"PhoneNumber","in":"path","required":true,"description":"E.164 (\`+12025550123\`) or national format; formatting characters are ignored.","schema":{"type":"string","minLength":1,"maxLength":24,"pattern":"^[+]?[0-9 ()-]{1,20}$","examples":["+12025550123","+13105550142","2025550199","+15550100","+442079460123"]}},{"name":"CountryCode","in":"query","required":false,"description":"ISO-3166 alpha-2 region used to parse a national-format number.","schema":{"type":"string","enum":["US","CA","GB"]}},{"name":"Fields","in":"query","required":false,"description":"Paid data packages (line_type_intelligence, caller_name, \u2026); the mock answers null for every package.","schema":{"type":"string","x-mockingbird-unsupported":{"reason":"Data packages cost money upstream and our consumer never requests them."}}}],"get":{"operationId":"FetchPhoneNumber","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Lookup result (also for invalid numbers, with \`valid:false\` and \`validation_errors\`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PhoneNumber"}}}},"401":{"description":"Bad credentials (code 20003)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/verify/v2/Services/{ServiceSid}/Verifications":{"parameters":[{"$ref":"#/components/parameters/ServiceSid"}],"post":{"operationId":"CreateVerification","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":false}},"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["To","Channel"],"properties":{"To":{"type":"string","description":"E.164 phone number (or an email address for Channel=email).","pattern":"^[+][1-9][0-9]{7,14}$","examples":["+12025550123","+13105550142","+14155550100"]},"Channel":{"type":"string","enum":["sms","call","email","whatsapp","sna","auto"]},"CustomCode":{"type":"string","pattern":"^[0-9]{4,10}$"},"Locale":{"type":"string","maxLength":10}}}}}},"responses":{"201":{"description":"Verification started (or the pending one re-sent)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Verification"}}}},"400":{"description":"Invalid parameter (code 60200)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Bad credentials (code 20003)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown Verify service (code 20404)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Max send attempts reached (code 60203)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/verify/v2/Services/{ServiceSid}/Verifications/{Sid}":{"parameters":[{"$ref":"#/components/parameters/ServiceSid"},{"name":"Sid","in":"path","required":true,"description":"The verification sid (\`VE\u2026\`).","schema":{"type":"string","x-mockingbird-resource-ref":{"type":"verification","missing":"VE00000000000000000000000000000000"}}}],"get":{"operationId":"FetchVerification","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"The verification","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Verification"}}}},"401":{"description":"Bad credentials (code 20003)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown or expired verification (code 20404)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"UpdateVerification","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":false}},"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["Status"],"properties":{"Status":{"type":"string","enum":["canceled","approved"]}}}}}},"responses":{"200":{"description":"The updated verification","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Verification"}}}},"400":{"description":"Invalid parameter (code 60200)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Bad credentials (code 20003)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown, expired or no longer pending verification (code 20404)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/verify/v2/Services/{ServiceSid}/VerificationCheck":{"parameters":[{"$ref":"#/components/parameters/ServiceSid"}],"post":{"operationId":"CreateVerificationCheck","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":false}},"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["Code"],"properties":{"Code":{"type":"string","pattern":"^[0-9]{4,10}$","examples":["000000","123456"]},"To":{"type":"string","pattern":"^[+][1-9][0-9]{7,14}$","examples":["+12025550123","+13105550142"]},"VerificationSid":{"type":"string","x-mockingbird-resource-ref":{"type":"verification","missing":"VE00000000000000000000000000000000"}}}}}}},"responses":{"200":{"description":"Check result; \`status\` is \`approved\` only for the right code","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationCheck"}}}},"400":{"description":"Invalid parameter (code 60200)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Bad credentials (code 20003)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No pending verification (missing, approved, canceled or expired; code 20404)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Max check attempts reached (code 60202)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/2010-04-01/Accounts/{AccountSid}/Messages.json":{"parameters":[{"$ref":"#/components/parameters/AccountSid"}],"post":{"operationId":"CreateMessage","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":false}},"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["To"],"properties":{"To":{"type":"string","pattern":"^[+][1-9][0-9]{7,14}$","examples":["+12025550123","+13105550142"]},"Body":{"type":"string","maxLength":1600},"From":{"type":"string","pattern":"^[+][1-9][0-9]{7,14}$","examples":["+15005550006"]},"MessagingServiceSid":{"type":"string","pattern":"^MG[0-9a-f]{32}$"},"MediaUrl":{"type":"string","format":"uri"},"StatusCallback":{"type":"string","format":"uri"}}}}}},"responses":{"201":{"description":"Message accepted (\`queued\`, or \`accepted\` through a Messaging Service)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}}},"400":{"description":"Invalid request (21211 bad To, 21602 no Body, 21603 no From, 21604 no To, 21617 too long)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Bad credentials (code 20003)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Malformed account sid (code 20404)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/2010-04-01/Accounts/{AccountSid}/Messages/{Sid}.json":{"parameters":[{"$ref":"#/components/parameters/AccountSid"},{"name":"Sid","in":"path","required":true,"schema":{"type":"string","x-mockingbird-resource-ref":{"type":"message","missing":"SM00000000000000000000000000000000"}}}],"get":{"operationId":"FetchMessage","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"The message","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}}},"401":{"description":"Bad credentials (code 20003)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown message (code 20404)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/2010-04-01/Accounts/{AccountSid}/Recordings/{Sid}.wav":{"parameters":[{"$ref":"#/components/parameters/AccountSid"},{"$ref":"#/components/parameters/RecordingSid"},{"name":"RequestedChannels","in":"query","required":false,"description":"2 returns a dual-channel recording as two channels; otherwise it is mixed down to mono.","schema":{"type":"integer","enum":[1,2]}}],"get":{"operationId":"FetchRecordingMedia","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"RIFF WAV (PCM)","content":{"audio/x-wav":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Bad credentials (code 20003)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown or deleted recording (code 20404)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/2010-04-01/Accounts/{AccountSid}/Recordings/{Sid}.json":{"parameters":[{"$ref":"#/components/parameters/AccountSid"},{"$ref":"#/components/parameters/RecordingSid"}],"get":{"operationId":"FetchRecording","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Recording metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Recording"}}}},"401":{"description":"Bad credentials (code 20003)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown or deleted recording (code 20404)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"DeleteRecording","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":false}},"responses":{"204":{"description":"Deleted"},"401":{"description":"Bad credentials (code 20003)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown or already deleted recording (code 20404; our consumer tolerates it)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"basicAuth":{"type":"http","scheme":"basic","description":"AccountSid (or an SK API key sid) as the username, AuthToken (or key secret) as the password."}},"parameters":{"ServiceSid":{"name":"ServiceSid","in":"path","required":true,"description":"The Verify service sid (\`VA\u2026\`).","schema":{"type":"string","pattern":"^VA[0-9a-f]{32}$","examples":["VA0123456789abcdef0123456789abcdef"]}},"AccountSid":{"name":"AccountSid","in":"path","required":true,"schema":{"type":"string","pattern":"^AC[0-9a-f]{32}$","examples":["AC33333333333333333333333333333333"]}},"RecordingSid":{"name":"Sid","in":"path","required":true,"description":"The recording sid (\`RE\u2026\`).","schema":{"type":"string","x-mockingbird-resource-ref":{"type":"recording","missing":"RE00000000000000000000000000000000"}}}},"schemas":{"Error":{"type":"object","required":["code","message","more_info","status"],"properties":{"code":{"type":"integer"},"message":{"type":"string"},"more_info":{"type":"string"},"status":{"type":"integer"}}},"PhoneNumber":{"type":"object","required":["calling_country_code","country_code","phone_number","national_format","valid","validation_errors","url"],"properties":{"calling_country_code":{"type":["string","null"]},"country_code":{"type":["string","null"]},"phone_number":{"type":"string"},"national_format":{"type":["string","null"]},"valid":{"type":"boolean"},"validation_errors":{"type":"array","items":{"type":"string","enum":["TOO_SHORT","TOO_LONG","INVALID_BUT_POSSIBLE","INVALID_COUNTRY_CODE","INVALID_LENGTH","NOT_A_NUMBER"]}},"caller_name":{"type":["object","null"]},"sim_swap":{"type":["object","null"]},"call_forwarding":{"type":["object","null"]},"line_status":{"type":["object","null"]},"line_type_intelligence":{"type":["object","null"]},"identity_match":{"type":["object","null"]},"reassigned_number":{"type":["object","null"]},"sms_pumping_risk":{"type":["object","null"]},"phone_number_quality_score":{"type":["object","null"]},"pre_fill":{"type":["object","null"]},"url":{"type":"string"}}},"SendCodeAttempt":{"type":"object","required":["attempt_sid","channel","time"],"properties":{"attempt_sid":{"type":"string","x-mockingbird-volatile":{"kind":"id"}},"channel":{"type":"string"},"time":{"type":"string","x-mockingbird-volatile":{"kind":"timestamp"}}}},"Verification":{"type":"object","required":["sid","service_sid","account_sid","to","channel","status","valid","date_created","date_updated","send_code_attempts","url"],"properties":{"sid":{"type":"string","x-mockingbird-resource":{"type":"verification","identity":true},"x-mockingbird-volatile":{"kind":"id"}},"service_sid":{"type":"string"},"account_sid":{"type":"string"},"to":{"type":"string"},"channel":{"type":"string"},"status":{"type":"string","enum":["pending","approved","canceled","expired"]},"valid":{"type":"boolean"},"lookup":{"type":["object","null"]},"amount":{"type":["string","null"]},"payee":{"type":["string","null"]},"send_code_attempts":{"type":"array","items":{"$ref":"#/components/schemas/SendCodeAttempt"}},"sna":{"type":["object","null"]},"date_created":{"type":"string","x-mockingbird-volatile":{"kind":"timestamp"}},"date_updated":{"type":"string","x-mockingbird-volatile":{"kind":"timestamp"}},"url":{"type":"string","x-mockingbird-volatile":{"kind":"url"}}}},"VerificationCheck":{"type":"object","required":["sid","service_sid","account_sid","to","channel","status","valid","date_created","date_updated"],"properties":{"sid":{"type":"string","x-mockingbird-volatile":{"kind":"id"}},"service_sid":{"type":"string"},"account_sid":{"type":"string"},"to":{"type":"string"},"channel":{"type":"string"},"status":{"type":"string","enum":["pending","approved","canceled","expired"]},"valid":{"type":"boolean"},"amount":{"type":["string","null"]},"payee":{"type":["string","null"]},"sna_attempts_error_codes":{"type":"array","items":{"type":"object"}},"date_created":{"type":"string","x-mockingbird-volatile":{"kind":"timestamp"}},"date_updated":{"type":"string","x-mockingbird-volatile":{"kind":"timestamp"}}}},"Message":{"type":"object","required":["sid","account_sid","to","from","body","status","direction","num_segments","num_media","api_version","date_created","date_updated","uri"],"properties":{"sid":{"type":"string","x-mockingbird-resource":{"type":"message","identity":true},"x-mockingbird-volatile":{"kind":"id"}},"account_sid":{"type":"string"},"api_version":{"type":"string"},"body":{"type":"string"},"to":{"type":"string"},"from":{"type":["string","null"]},"messaging_service_sid":{"type":["string","null"]},"status":{"type":"string","enum":["queued","accepted","sending","sent","delivered","undelivered","failed","received"]},"direction":{"type":"string"},"num_segments":{"type":"string"},"num_media":{"type":"string"},"price":{"type":["string","null"]},"price_unit":{"type":["string","null"]},"error_code":{"type":["integer","null"]},"error_message":{"type":["string","null"]},"date_created":{"type":"string","x-mockingbird-volatile":{"kind":"timestamp"}},"date_updated":{"type":"string","x-mockingbird-volatile":{"kind":"timestamp"}},"date_sent":{"type":["string","null"],"x-mockingbird-volatile":{"kind":"timestamp"}},"uri":{"type":"string","x-mockingbird-volatile":{"kind":"url"}},"subresource_uris":{"type":"object","x-mockingbird-volatile":{"kind":"url"}}}},"Recording":{"type":"object","required":["sid","account_sid","call_sid","status","channels","duration","uri","media_url","date_created"],"properties":{"sid":{"type":"string","x-mockingbird-resource":{"type":"recording","identity":true}},"account_sid":{"type":"string"},"api_version":{"type":"string"},"call_sid":{"type":"string"},"status":{"type":"string"},"channels":{"type":"integer"},"duration":{"type":"string"},"source":{"type":"string"},"price":{"type":["string","null"]},"price_unit":{"type":["string","null"]},"error_code":{"type":["integer","null"]},"start_time":{"type":"string"},"date_created":{"type":"string"},"date_updated":{"type":"string"},"uri":{"type":"string"},"media_url":{"type":"string"}}}}}}`);
3287
- var operationIds = ["FetchPhoneNumber", "CreateVerification", "FetchVerification", "UpdateVerification", "CreateVerificationCheck", "CreateMessage", "FetchMessage", "FetchRecordingMedia", "FetchRecording", "DeleteRecording"];
3288
- var supportedOperationIds = ["FetchPhoneNumber", "CreateVerification", "FetchVerification", "UpdateVerification", "CreateVerificationCheck", "CreateMessage", "FetchMessage", "FetchRecordingMedia", "FetchRecording", "DeleteRecording"];
3355
+ var document = JSON.parse(`{"openapi":"3.1.0","info":{"title":"Twilio Verify, Lookup, Messaging and Recordings (Mockingbird subset)","description":"Stateful mock subset of Twilio, served on one port. Each product keeps its own host upstream\\n(api.twilio.com, verify.twilio.com, lookups.twilio.com); the mock routes by that host carried\\nas a path prefix (\`/api/\u2026\`, \`/verify/\u2026\`, \`/lookups/\u2026\`), which is what a custom twilio-node\\n\`httpClient\` produces when it rewrites \`https://<product>.twilio.com/<path>\` to\\n\`{mock}/<product>/<path>\`. Hand-authored from Twilio's published API reference, trimmed to\\nwhat our consumer calls, and checked against live Lookup v2 responses.\\n","version":"2010-04-01","x-mockingbird-upstream":{"note":"Trimmed from Twilio's public API reference (twilio-oai) to the operations our consumer calls (twilio.service.ts, twilio-conversation-sms.adapter.ts, notification-dispatcher channels/sms.ts, twilio-recording-http.adapter.ts); Lookup v2 shapes verified against the live API."}},"servers":[{"url":"https://api.twilio.com","description":"Every product on one origin, routed by the /api, /verify or /lookups prefix."}],"security":[{"basicAuth":[]}],"paths":{"/lookups/v2/PhoneNumbers/{PhoneNumber}":{"parameters":[{"name":"PhoneNumber","in":"path","required":true,"description":"E.164 (\`+12025550123\`) or national format; formatting characters are ignored.","schema":{"type":"string","minLength":1,"maxLength":24,"pattern":"^[+]?[0-9 ()-]{1,20}$","examples":["+12025550123","+13105550142","2025550199","+15550100","+442079460123"]}},{"name":"CountryCode","in":"query","required":false,"description":"ISO-3166 alpha-2 region used to parse a national-format number.","schema":{"type":"string","enum":["US","CA","GB"]}},{"name":"Fields","in":"query","required":false,"description":"Paid data packages (line_type_intelligence, caller_name, \u2026); the mock answers null for every package.","schema":{"type":"string","x-mockingbird-unsupported":{"reason":"Data packages cost money upstream and our consumer never requests them."}}}],"get":{"operationId":"FetchPhoneNumber","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Lookup result (also for invalid numbers, with \`valid:false\` and \`validation_errors\`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PhoneNumber"}}}},"401":{"description":"Bad credentials (code 20003)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/verify/v2/Services/{ServiceSid}/Verifications":{"parameters":[{"$ref":"#/components/parameters/ServiceSid"}],"post":{"operationId":"CreateVerification","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":false}},"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["To","Channel"],"properties":{"To":{"type":"string","description":"E.164 phone number (or an email address for Channel=email).","pattern":"^[+][1-9][0-9]{7,14}$","examples":["+12025550123","+13105550142","+14155550100"]},"Channel":{"type":"string","enum":["sms","call","email","whatsapp","sna","auto"]},"CustomCode":{"type":"string","pattern":"^[0-9]{4,10}$"},"Locale":{"type":"string","maxLength":10}}}}}},"responses":{"201":{"description":"Verification started (or the pending one re-sent)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Verification"}}}},"400":{"description":"Invalid parameter (code 60200)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Bad credentials (code 20003)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown Verify service (code 20404)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Max send attempts reached (code 60203)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/verify/v2/Services/{ServiceSid}/Verifications/{Sid}":{"parameters":[{"$ref":"#/components/parameters/ServiceSid"},{"name":"Sid","in":"path","required":true,"description":"The verification sid (\`VE\u2026\`).","schema":{"type":"string","x-mockingbird-resource-ref":{"type":"verification","missing":"VE00000000000000000000000000000000"}}}],"get":{"operationId":"FetchVerification","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"The verification","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Verification"}}}},"401":{"description":"Bad credentials (code 20003)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown or expired verification (code 20404)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"UpdateVerification","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":false}},"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["Status"],"properties":{"Status":{"type":"string","enum":["canceled","approved"]}}}}}},"responses":{"200":{"description":"The updated verification","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Verification"}}}},"400":{"description":"Invalid parameter (code 60200)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Bad credentials (code 20003)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown, expired or no longer pending verification (code 20404)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/verify/v2/Services/{ServiceSid}/VerificationCheck":{"parameters":[{"$ref":"#/components/parameters/ServiceSid"}],"post":{"operationId":"CreateVerificationCheck","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":false}},"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["Code"],"properties":{"Code":{"type":"string","pattern":"^[0-9]{4,10}$","examples":["000000","123456"]},"To":{"type":"string","pattern":"^[+][1-9][0-9]{7,14}$","examples":["+12025550123","+13105550142"]},"VerificationSid":{"type":"string","x-mockingbird-resource-ref":{"type":"verification","missing":"VE00000000000000000000000000000000"}}}}}}},"responses":{"200":{"description":"Check result; \`status\` is \`approved\` only for the right code","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationCheck"}}}},"400":{"description":"Invalid parameter (code 60200)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Bad credentials (code 20003)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No pending verification (missing, approved, canceled or expired; code 20404)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Max check attempts reached (code 60202)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/2010-04-01/Accounts/{AccountSid}/Messages.json":{"parameters":[{"$ref":"#/components/parameters/AccountSid"}],"get":{"operationId":"ListMessages","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"parameters":[{"name":"PageSize","in":"query","schema":{"type":"integer","minimum":1,"maximum":1000}},{"name":"Page","in":"query","schema":{"type":"integer","minimum":0}},{"name":"PageToken","in":"query","schema":{"type":"string"}},{"name":"To","in":"query","schema":{"type":"string"}},{"name":"From","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Message resources in newest-first order","content":{"application/json":{"schema":{"type":"object","required":["messages","page","page_size","start","end","uri","first_page_uri","next_page_uri","previous_page_uri"],"properties":{"messages":{"type":"array","items":{"$ref":"#/components/schemas/Message"}},"page":{"type":"integer"},"page_size":{"type":"integer"},"start":{"type":"integer"},"end":{"type":"integer"},"uri":{"type":"string","x-mockingbird-volatile":{"kind":"url"}},"first_page_uri":{"type":"string","x-mockingbird-volatile":{"kind":"url"}},"next_page_uri":{"type":["string","null"],"x-mockingbird-volatile":{"kind":"url"}},"previous_page_uri":{"type":["string","null"],"x-mockingbird-volatile":{"kind":"url"}}}}}}},"400":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"CreateMessage","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":false}},"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["To"],"properties":{"To":{"type":"string","pattern":"^[+][1-9][0-9]{7,14}$","examples":["+12025550123","+13105550142"]},"Body":{"type":"string","maxLength":1600},"From":{"type":"string","pattern":"^[+][1-9][0-9]{7,14}$","examples":["+15005550006"]},"MessagingServiceSid":{"type":"string","pattern":"^MG[0-9a-f]{32}$"},"MediaUrl":{"type":"string","format":"uri"},"StatusCallback":{"type":"string","format":"uri"}}}}}},"responses":{"201":{"description":"Message accepted (\`queued\`, or \`accepted\` through a Messaging Service)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}}},"400":{"description":"Invalid request (21211 bad To, 21602 no Body, 21603 no From, 21604 no To, 21617 too long)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Bad credentials (code 20003)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Malformed account sid (code 20404)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/2010-04-01/Accounts/{AccountSid}/Messages/{Sid}.json":{"parameters":[{"$ref":"#/components/parameters/AccountSid"},{"name":"Sid","in":"path","required":true,"schema":{"type":"string","x-mockingbird-resource-ref":{"type":"message","missing":"SM00000000000000000000000000000000"}}}],"get":{"operationId":"FetchMessage","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"The message","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}}},"401":{"description":"Bad credentials (code 20003)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown message (code 20404)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/2010-04-01/Accounts/{AccountSid}/Recordings/{Sid}.wav":{"parameters":[{"$ref":"#/components/parameters/AccountSid"},{"$ref":"#/components/parameters/RecordingSid"},{"name":"RequestedChannels","in":"query","required":false,"description":"2 returns a dual-channel recording as two channels; otherwise it is mixed down to mono.","schema":{"type":"integer","enum":[1,2]}}],"get":{"operationId":"FetchRecordingMedia","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"RIFF WAV (PCM)","content":{"audio/x-wav":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Bad credentials (code 20003)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown or deleted recording (code 20404)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/2010-04-01/Accounts/{AccountSid}/Recordings/{Sid}.json":{"parameters":[{"$ref":"#/components/parameters/AccountSid"},{"$ref":"#/components/parameters/RecordingSid"}],"get":{"operationId":"FetchRecording","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Recording metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Recording"}}}},"401":{"description":"Bad credentials (code 20003)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown or deleted recording (code 20404)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"DeleteRecording","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":false}},"responses":{"204":{"description":"Deleted"},"401":{"description":"Bad credentials (code 20003)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown or already deleted recording (code 20404; our consumer tolerates it)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"basicAuth":{"type":"http","scheme":"basic","description":"AccountSid (or an SK API key sid) as the username, AuthToken (or key secret) as the password."}},"parameters":{"ServiceSid":{"name":"ServiceSid","in":"path","required":true,"description":"The Verify service sid (\`VA\u2026\`).","schema":{"type":"string","pattern":"^VA[0-9a-f]{32}$","examples":["VA0123456789abcdef0123456789abcdef"]}},"AccountSid":{"name":"AccountSid","in":"path","required":true,"schema":{"type":"string","pattern":"^AC[0-9a-f]{32}$","examples":["AC33333333333333333333333333333333"]}},"RecordingSid":{"name":"Sid","in":"path","required":true,"description":"The recording sid (\`RE\u2026\`).","schema":{"type":"string","x-mockingbird-resource-ref":{"type":"recording","missing":"RE00000000000000000000000000000000"}}}},"schemas":{"Error":{"type":"object","required":["code","message","more_info","status"],"properties":{"code":{"type":"integer"},"message":{"type":"string"},"more_info":{"type":"string"},"status":{"type":"integer"}}},"PhoneNumber":{"type":"object","required":["calling_country_code","country_code","phone_number","national_format","valid","validation_errors","url"],"properties":{"calling_country_code":{"type":["string","null"]},"country_code":{"type":["string","null"]},"phone_number":{"type":"string"},"national_format":{"type":["string","null"]},"valid":{"type":"boolean"},"validation_errors":{"type":"array","items":{"type":"string","enum":["TOO_SHORT","TOO_LONG","INVALID_BUT_POSSIBLE","INVALID_COUNTRY_CODE","INVALID_LENGTH","NOT_A_NUMBER"]}},"caller_name":{"type":["object","null"]},"sim_swap":{"type":["object","null"]},"call_forwarding":{"type":["object","null"]},"line_status":{"type":["object","null"]},"line_type_intelligence":{"type":["object","null"]},"identity_match":{"type":["object","null"]},"reassigned_number":{"type":["object","null"]},"sms_pumping_risk":{"type":["object","null"]},"phone_number_quality_score":{"type":["object","null"]},"pre_fill":{"type":["object","null"]},"url":{"type":"string"}}},"SendCodeAttempt":{"type":"object","required":["attempt_sid","channel","time"],"properties":{"attempt_sid":{"type":"string","x-mockingbird-volatile":{"kind":"id"}},"channel":{"type":"string"},"time":{"type":"string","x-mockingbird-volatile":{"kind":"timestamp"}}}},"Verification":{"type":"object","required":["sid","service_sid","account_sid","to","channel","status","valid","date_created","date_updated","send_code_attempts","url"],"properties":{"sid":{"type":"string","x-mockingbird-resource":{"type":"verification","identity":true},"x-mockingbird-volatile":{"kind":"id"}},"service_sid":{"type":"string"},"account_sid":{"type":"string"},"to":{"type":"string"},"channel":{"type":"string"},"status":{"type":"string","enum":["pending","approved","canceled","expired"]},"valid":{"type":"boolean"},"lookup":{"type":["object","null"]},"amount":{"type":["string","null"]},"payee":{"type":["string","null"]},"send_code_attempts":{"type":"array","items":{"$ref":"#/components/schemas/SendCodeAttempt"}},"sna":{"type":["object","null"]},"date_created":{"type":"string","x-mockingbird-volatile":{"kind":"timestamp"}},"date_updated":{"type":"string","x-mockingbird-volatile":{"kind":"timestamp"}},"url":{"type":"string","x-mockingbird-volatile":{"kind":"url"}}}},"VerificationCheck":{"type":"object","required":["sid","service_sid","account_sid","to","channel","status","valid","date_created","date_updated"],"properties":{"sid":{"type":"string","x-mockingbird-volatile":{"kind":"id"}},"service_sid":{"type":"string"},"account_sid":{"type":"string"},"to":{"type":"string"},"channel":{"type":"string"},"status":{"type":"string","enum":["pending","approved","canceled","expired"]},"valid":{"type":"boolean"},"amount":{"type":["string","null"]},"payee":{"type":["string","null"]},"sna_attempts_error_codes":{"type":"array","items":{"type":"object"}},"date_created":{"type":"string","x-mockingbird-volatile":{"kind":"timestamp"}},"date_updated":{"type":"string","x-mockingbird-volatile":{"kind":"timestamp"}}}},"Message":{"type":"object","required":["sid","account_sid","to","from","body","status","direction","num_segments","num_media","api_version","date_created","date_updated","uri"],"properties":{"sid":{"type":"string","x-mockingbird-resource":{"type":"message","identity":true},"x-mockingbird-volatile":{"kind":"id"}},"account_sid":{"type":"string"},"api_version":{"type":"string"},"body":{"type":"string"},"to":{"type":"string"},"from":{"type":["string","null"]},"messaging_service_sid":{"type":["string","null"]},"status":{"type":"string","enum":["queued","accepted","sending","sent","delivered","undelivered","failed","received"]},"direction":{"type":"string"},"num_segments":{"type":"string"},"num_media":{"type":"string"},"price":{"type":["string","null"]},"price_unit":{"type":["string","null"]},"error_code":{"type":["integer","null"]},"error_message":{"type":["string","null"]},"date_created":{"type":"string","x-mockingbird-volatile":{"kind":"timestamp"}},"date_updated":{"type":"string","x-mockingbird-volatile":{"kind":"timestamp"}},"date_sent":{"type":["string","null"],"x-mockingbird-volatile":{"kind":"timestamp"}},"uri":{"type":"string","x-mockingbird-volatile":{"kind":"url"}},"subresource_uris":{"type":"object","x-mockingbird-volatile":{"kind":"url"}}}},"Recording":{"type":"object","required":["sid","account_sid","call_sid","status","channels","duration","uri","media_url","date_created"],"properties":{"sid":{"type":"string","x-mockingbird-resource":{"type":"recording","identity":true}},"account_sid":{"type":"string"},"api_version":{"type":"string"},"call_sid":{"type":"string"},"status":{"type":"string"},"channels":{"type":"integer"},"duration":{"type":"string"},"source":{"type":"string"},"price":{"type":["string","null"]},"price_unit":{"type":["string","null"]},"error_code":{"type":["integer","null"]},"start_time":{"type":"string"},"date_created":{"type":"string"},"date_updated":{"type":"string"},"uri":{"type":"string"},"media_url":{"type":"string"}}}}}}`);
3356
+ var operationIds = ["FetchPhoneNumber", "CreateVerification", "FetchVerification", "UpdateVerification", "CreateVerificationCheck", "ListMessages", "CreateMessage", "FetchMessage", "FetchRecordingMedia", "FetchRecording", "DeleteRecording"];
3357
+ var supportedOperationIds = ["FetchPhoneNumber", "CreateVerification", "FetchVerification", "UpdateVerification", "CreateVerificationCheck", "ListMessages", "CreateMessage", "FetchMessage", "FetchRecordingMedia", "FetchRecording", "DeleteRecording"];
3289
3358
 
3290
3359
  // src/phone.ts
3291
3360
  import {
@@ -4089,6 +4158,7 @@ var TwilioAPI = class {
4089
4158
  UpdateVerification: (context) => this.updateVerification(context),
4090
4159
  CreateVerificationCheck: (context) => this.createVerificationCheck(context),
4091
4160
  CreateMessage: (context) => this.createMessage(context),
4161
+ ListMessages: (context) => this.listMessages(context),
4092
4162
  FetchMessage: (context) => this.fetchMessage(context),
4093
4163
  FetchRecordingMedia: (context) => this.fetchRecordingMedia(context),
4094
4164
  FetchRecording: (context) => this.fetchRecording(context),
@@ -4480,6 +4550,50 @@ var TwilioAPI = class {
4480
4550
  }
4481
4551
  return annotateResponse(jsonRes(200, message), { ids: { messageSid: message.sid } });
4482
4552
  }
4553
+ listMessages(context) {
4554
+ const accountSid = this.requireAccount(context);
4555
+ const query = context.url.searchParams;
4556
+ const pageSize = Number(query.get("PageSize") ?? 50);
4557
+ const page = Number(query.get("Page") ?? 0);
4558
+ if (pageSize > 1e3) throw fail2(400, 20007, "Page size too large");
4559
+ if (!Number.isSafeInteger(pageSize) || pageSize < 1 || !Number.isSafeInteger(page) || page < 0) {
4560
+ throw fail2(400, 400, "Invalid paging parameters");
4561
+ }
4562
+ const records = this.state.messages.list({ order: "newest" }).map((row) => row.value).filter((message) => message.account_sid === accountSid).filter(
4563
+ (message) => (!query.has("To") || message.to === query.get("To")) && (!query.has("From") || message.from === query.get("From"))
4564
+ );
4565
+ let start = 0;
4566
+ const token = query.get("PageToken");
4567
+ if (token !== null) {
4568
+ const match = /^(PA|PB)((?:SM|MM)[0-9a-f]{32})$/i.exec(token);
4569
+ const index = match ? records.findIndex((message) => message.sid === match[2]) : -1;
4570
+ if (!match || index < 0) throw fail2(400, 21481, "Invalid PageToken");
4571
+ start = match[1]?.toUpperCase() === "PA" ? index + 1 : Math.max(0, index - pageSize);
4572
+ }
4573
+ const messages = records.slice(start, start + pageSize);
4574
+ const path = `/2010-04-01/Accounts/${accountSid}/Messages.json`;
4575
+ const uri = (number, cursor) => {
4576
+ const params = new URLSearchParams(query);
4577
+ params.set("PageSize", String(pageSize));
4578
+ params.set("Page", String(number));
4579
+ params.delete("PageToken");
4580
+ if (cursor) params.set("PageToken", cursor);
4581
+ return `${path}?${params}`;
4582
+ };
4583
+ const last = messages.at(-1);
4584
+ const first = messages[0];
4585
+ return jsonRes(200, {
4586
+ messages,
4587
+ page,
4588
+ page_size: pageSize,
4589
+ start,
4590
+ end: start + messages.length - 1,
4591
+ uri: uri(page, token ?? void 0),
4592
+ first_page_uri: uri(0),
4593
+ next_page_uri: last && start + messages.length < records.length ? uri(page + 1, `PA${last.sid}`) : null,
4594
+ previous_page_uri: first && start > 0 ? uri(Math.max(0, page - 1), `PB${first.sid}`) : null
4595
+ });
4596
+ }
4483
4597
  // ---- Recordings ----------------------------------------------------------------------------
4484
4598
  findRecording(context) {
4485
4599
  this.requireAccount(context);
@@ -4612,4 +4726,4 @@ export {
4612
4726
  twilioError,
4613
4727
  TwilioAPI
4614
4728
  };
4615
- //# sourceMappingURL=chunk-I5WWNGOK.js.map
4729
+ //# sourceMappingURL=chunk-JTHJGMYU.js.map