Skip to content

Commit d3da6c7

Browse files
committed
feat: update TwilioMessage schema to include enum for direction and status fields
1 parent d432953 commit d3da6c7

3 files changed

Lines changed: 72 additions & 38 deletions

File tree

actions/twilio-action/schemas/twilio-api-v2010-openapi.filtered.json

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,14 @@
4141
"description": "The number of segments that make up the complete message. SMS message bodies that exceed the [character limit](https://www.twilio.com/docs/glossary/what-sms-character-limit) are segmented and charged as multiple messages. Note: For messages sent via a Messaging Service, `num_segments` is initially `0`, since a sender hasn't yet been assigned."
4242
},
4343
"direction": {
44-
"type": "object",
45-
"additionalProperties": true
44+
"type": "string",
45+
"enum": [
46+
"inbound",
47+
"outbound-api",
48+
"outbound-call",
49+
"outbound-reply"
50+
],
51+
"description": "The direction of the message. Can be: `inbound` for incoming messages, `outbound-api` for messages created by the REST API, `outbound-call` for messages created during a call, or `outbound-reply` for messages created in response to an incoming message."
4652
},
4753
"from": {
4854
"type": "string",
@@ -90,9 +96,6 @@
9096
},
9197
"account_sid": {
9298
"type": "string",
93-
"minLength": 34,
94-
"maxLength": 34,
95-
"pattern": "^AC[0-9a-fA-F]{32}$",
9699
"nullable": true,
97100
"description": "The SID of the [Account](https://www.twilio.com/docs/iam/api/account) associated with the Message resource"
98101
},
@@ -102,22 +105,31 @@
102105
"description": "The number of media files associated with the Message resource."
103106
},
104107
"status": {
105-
"type": "object",
106-
"additionalProperties": true
108+
"type": "string",
109+
"enum": [
110+
"queued",
111+
"sending",
112+
"sent",
113+
"failed",
114+
"delivered",
115+
"undelivered",
116+
"receiving",
117+
"received",
118+
"accepted",
119+
"scheduled",
120+
"read",
121+
"partially_delivered",
122+
"canceled"
123+
],
124+
"description": "The status of the Message. Possible values: `accepted`, `scheduled`, `canceled`, `queued`, `sending`, `sent`, `failed`, `delivered`, `undelivered`, `receiving`, `received`, or `read` (WhatsApp only). For more information, See [detailed descriptions](https://www.twilio.com/docs/sms/api/message-resource#message-status-values)."
107125
},
108126
"messaging_service_sid": {
109127
"type": "string",
110-
"minLength": 34,
111-
"maxLength": 34,
112-
"pattern": "^MG[0-9a-fA-F]{32}$",
113128
"nullable": true,
114129
"description": "The SID of the [Messaging Service](https://www.twilio.com/docs/messaging/api/service-resource) associated with the Message resource. A unique default value is assigned if a Messaging Service is not used."
115130
},
116131
"sid": {
117132
"type": "string",
118-
"minLength": 34,
119-
"maxLength": 34,
120-
"pattern": "^(SM|MM)[0-9a-fA-F]{32}$",
121133
"nullable": true,
122134
"description": "The unique, Twilio-provided string that identifies the Message resource."
123135
},

actions/twilio-action/scripts/filterTwilioSpec.mjs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,23 @@
66
// - keeps `api.v2010.account.message`, re-exposed under the stable name
77
// `TwilioMessage` so the generated schema has a predictable identifier
88
// regardless of how openapi-zod-client would sanitize the dotted name
9-
// - replaces $refs to any other component with a permissive untyped object,
10-
// cutting the rest of the graph
9+
// - inlines $refs that point at scalar/enum components (e.g. the
10+
// `message_enum_direction` / `message_enum_status` string enums) so their
11+
// type and allowed values survive instead of collapsing to an empty object
12+
// - replaces every other ($ref to an object/array) component with a
13+
// permissive untyped object, cutting the rest of the graph
14+
// - drops `minLength` / `maxLength` / `pattern` string constraints: this is a
15+
// schema for *parsing Twilio responses*, so it stays lenient (Postel's law)
16+
// rather than rejecting a real response over an exact SID-format mismatch
1117
// Runs as part of "generate:twilio-schemas" right after the download.
1218
import {readFileSync, writeFileSync} from "node:fs";
1319

1420
const SOURCE_NAME = "api.v2010.account.message";
1521
const TARGET_NAME = "TwilioMessage";
1622

23+
// String validation constraints stripped for lenient response parsing.
24+
const DROPPED_VALIDATION_KEYS = new Set(["minLength", "maxLength", "pattern"]);
25+
1726
const input = new URL("../schemas/twilio-api-v2010-openapi.json", import.meta.url);
1827
const output = new URL("../schemas/twilio-api-v2010-openapi.filtered.json", import.meta.url);
1928

@@ -24,8 +33,9 @@ if (!(SOURCE_NAME in allSchemas)) {
2433
throw new Error(`Schema "${SOURCE_NAME}" not found in ${input}`);
2534
}
2635

27-
// Rewrite $refs: self-references point at the renamed schema, every other
28-
// component reference is stubbed out as an untyped object.
36+
// Rewrite $refs: self-references point at the renamed schema, references to
37+
// scalar/enum components are inlined (so enum values survive), and every other
38+
// (object/array) component reference is stubbed out as an untyped object.
2939
const rewriteRefs = (node) => {
3040
if (Array.isArray(node)) {
3141
return node.map(rewriteRefs);
@@ -38,10 +48,18 @@ const rewriteRefs = (node) => {
3848
if (match[1] === SOURCE_NAME) {
3949
return {$ref: `#/components/schemas/${TARGET_NAME}`};
4050
}
51+
const target = allSchemas[match[1]];
52+
if (target && target.type && target.type !== "object" && target.type !== "array") {
53+
return rewriteRefs(target);
54+
}
4155
return {type: "object", additionalProperties: true};
4256
}
4357
}
44-
return Object.fromEntries(Object.entries(node).map(([key, value]) => [key, rewriteRefs(value)]));
58+
return Object.fromEntries(
59+
Object.entries(node)
60+
.filter(([key]) => !DROPPED_VALIDATION_KEYS.has(key))
61+
.map(([key, value]) => [key, rewriteRefs(value)]),
62+
);
4563
}
4664
return node;
4765
};

actions/twilio-action/src/generated/twilio-schemas.ts

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,33 +4,37 @@ const TwilioMessage = z
44
.object({
55
body: z.string().nullable(),
66
num_segments: z.string().nullable(),
7-
direction: z.object({}).partial().passthrough(),
7+
direction: z.enum([
8+
"inbound",
9+
"outbound-api",
10+
"outbound-call",
11+
"outbound-reply",
12+
]),
813
from: z.string().nullable(),
914
to: z.string().nullable(),
1015
date_updated: z.string().nullable(),
1116
price: z.string().nullable(),
1217
error_message: z.string().nullable(),
1318
uri: z.string().nullable(),
14-
account_sid: z
15-
.string()
16-
.min(34)
17-
.max(34)
18-
.regex(/^AC[0-9a-fA-F]{32}$/)
19-
.nullable(),
19+
account_sid: z.string().nullable(),
2020
num_media: z.string().nullable(),
21-
status: z.object({}).partial().passthrough(),
22-
messaging_service_sid: z
23-
.string()
24-
.min(34)
25-
.max(34)
26-
.regex(/^MG[0-9a-fA-F]{32}$/)
27-
.nullable(),
28-
sid: z
29-
.string()
30-
.min(34)
31-
.max(34)
32-
.regex(/^(SM|MM)[0-9a-fA-F]{32}$/)
33-
.nullable(),
21+
status: z.enum([
22+
"queued",
23+
"sending",
24+
"sent",
25+
"failed",
26+
"delivered",
27+
"undelivered",
28+
"receiving",
29+
"received",
30+
"accepted",
31+
"scheduled",
32+
"read",
33+
"partially_delivered",
34+
"canceled",
35+
]),
36+
messaging_service_sid: z.string().nullable(),
37+
sid: z.string().nullable(),
3438
date_sent: z.string().nullable(),
3539
date_created: z.string().nullable(),
3640
error_code: z.number().int().nullable(),

0 commit comments

Comments
 (0)