@marlinjai/mail-contract 0.21.0 → 0.22.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/dist/index.mjs CHANGED
@@ -3047,6 +3047,7 @@ var AUDIT_ACTIONS = [
3047
3047
  "domain_order.registered",
3048
3048
  "domain_order.ready",
3049
3049
  "domain_order.needs_attention",
3050
+ "domain_order.kind_changed",
3050
3051
  "domain_order.refunded",
3051
3052
  "domain_order.cancelled",
3052
3053
  // A1: automations
@@ -3974,6 +3975,292 @@ var SendingDomainUpdate = z15.object({ from_name: SenderFields.from_name.optiona
3974
3975
 
3975
3976
  // src/domains.ts
3976
3977
  import { z as z16 } from "zod";
3978
+
3979
+ // src/phone.ts
3980
+ var REGISTRY_PHONE = /^\+\d{1,3}\.\d{4,14}$/;
3981
+ var CALLING_CODE_OF_COUNTRY = {
3982
+ DE: "49",
3983
+ AT: "43",
3984
+ CH: "41",
3985
+ LI: "423",
3986
+ LU: "352",
3987
+ NL: "31",
3988
+ BE: "32",
3989
+ FR: "33",
3990
+ IT: "39",
3991
+ ES: "34",
3992
+ PT: "351",
3993
+ IE: "353",
3994
+ GB: "44",
3995
+ DK: "45",
3996
+ SE: "46",
3997
+ NO: "47",
3998
+ FI: "358",
3999
+ IS: "354",
4000
+ PL: "48",
4001
+ CZ: "420",
4002
+ SK: "421",
4003
+ HU: "36",
4004
+ SI: "386",
4005
+ HR: "385",
4006
+ RO: "40",
4007
+ BG: "359",
4008
+ GR: "30",
4009
+ CY: "357",
4010
+ MT: "356",
4011
+ EE: "372",
4012
+ LV: "371",
4013
+ LT: "370",
4014
+ US: "1",
4015
+ CA: "1",
4016
+ AU: "61",
4017
+ NZ: "64",
4018
+ TR: "90",
4019
+ IL: "972",
4020
+ AE: "971",
4021
+ IN: "91",
4022
+ JP: "81",
4023
+ CN: "86",
4024
+ SG: "65",
4025
+ ZA: "27",
4026
+ BR: "55",
4027
+ MX: "52",
4028
+ UA: "380",
4029
+ RS: "381"
4030
+ };
4031
+ var CALLING_CODES = /* @__PURE__ */ new Set([
4032
+ "1",
4033
+ "7",
4034
+ "20",
4035
+ "27",
4036
+ "30",
4037
+ "31",
4038
+ "32",
4039
+ "33",
4040
+ "34",
4041
+ "36",
4042
+ "39",
4043
+ "40",
4044
+ "41",
4045
+ "43",
4046
+ "44",
4047
+ "45",
4048
+ "46",
4049
+ "47",
4050
+ "48",
4051
+ "49",
4052
+ "51",
4053
+ "52",
4054
+ "53",
4055
+ "54",
4056
+ "55",
4057
+ "56",
4058
+ "57",
4059
+ "58",
4060
+ "60",
4061
+ "61",
4062
+ "62",
4063
+ "63",
4064
+ "64",
4065
+ "65",
4066
+ "66",
4067
+ "81",
4068
+ "82",
4069
+ "84",
4070
+ "86",
4071
+ "90",
4072
+ "91",
4073
+ "92",
4074
+ "93",
4075
+ "94",
4076
+ "95",
4077
+ "98",
4078
+ "211",
4079
+ "212",
4080
+ "213",
4081
+ "216",
4082
+ "218",
4083
+ "220",
4084
+ "221",
4085
+ "222",
4086
+ "223",
4087
+ "224",
4088
+ "225",
4089
+ "226",
4090
+ "227",
4091
+ "228",
4092
+ "229",
4093
+ "230",
4094
+ "231",
4095
+ "232",
4096
+ "233",
4097
+ "234",
4098
+ "235",
4099
+ "236",
4100
+ "237",
4101
+ "238",
4102
+ "239",
4103
+ "240",
4104
+ "241",
4105
+ "242",
4106
+ "243",
4107
+ "244",
4108
+ "245",
4109
+ "246",
4110
+ "247",
4111
+ "248",
4112
+ "249",
4113
+ "250",
4114
+ "251",
4115
+ "252",
4116
+ "253",
4117
+ "254",
4118
+ "255",
4119
+ "256",
4120
+ "257",
4121
+ "258",
4122
+ "260",
4123
+ "261",
4124
+ "262",
4125
+ "263",
4126
+ "264",
4127
+ "265",
4128
+ "266",
4129
+ "267",
4130
+ "268",
4131
+ "269",
4132
+ "290",
4133
+ "291",
4134
+ "297",
4135
+ "298",
4136
+ "299",
4137
+ "350",
4138
+ "351",
4139
+ "352",
4140
+ "353",
4141
+ "354",
4142
+ "355",
4143
+ "356",
4144
+ "357",
4145
+ "358",
4146
+ "359",
4147
+ "370",
4148
+ "371",
4149
+ "372",
4150
+ "373",
4151
+ "374",
4152
+ "375",
4153
+ "376",
4154
+ "377",
4155
+ "378",
4156
+ "379",
4157
+ "380",
4158
+ "381",
4159
+ "382",
4160
+ "383",
4161
+ "385",
4162
+ "386",
4163
+ "387",
4164
+ "389",
4165
+ "420",
4166
+ "421",
4167
+ "423",
4168
+ "500",
4169
+ "501",
4170
+ "502",
4171
+ "503",
4172
+ "504",
4173
+ "505",
4174
+ "506",
4175
+ "507",
4176
+ "508",
4177
+ "509",
4178
+ "590",
4179
+ "591",
4180
+ "592",
4181
+ "593",
4182
+ "594",
4183
+ "595",
4184
+ "596",
4185
+ "597",
4186
+ "598",
4187
+ "599",
4188
+ "670",
4189
+ "672",
4190
+ "673",
4191
+ "674",
4192
+ "675",
4193
+ "676",
4194
+ "677",
4195
+ "678",
4196
+ "679",
4197
+ "680",
4198
+ "681",
4199
+ "682",
4200
+ "683",
4201
+ "685",
4202
+ "686",
4203
+ "687",
4204
+ "688",
4205
+ "689",
4206
+ "690",
4207
+ "691",
4208
+ "692",
4209
+ "850",
4210
+ "852",
4211
+ "853",
4212
+ "855",
4213
+ "856",
4214
+ "880",
4215
+ "886",
4216
+ "960",
4217
+ "961",
4218
+ "962",
4219
+ "963",
4220
+ "964",
4221
+ "965",
4222
+ "966",
4223
+ "967",
4224
+ "968",
4225
+ "970",
4226
+ "971",
4227
+ "972",
4228
+ "973",
4229
+ "974",
4230
+ "975",
4231
+ "976",
4232
+ "977",
4233
+ "992",
4234
+ "993",
4235
+ "994",
4236
+ "995",
4237
+ "996",
4238
+ "998"
4239
+ ]);
4240
+ var KEEPS_LEADING_ZERO = /* @__PURE__ */ new Set(["39", "378", "379"]);
4241
+ function normalizePhone(raw, country) {
4242
+ const text = raw.trim();
4243
+ if (REGISTRY_PHONE.test(text)) return text;
4244
+ const compact = text.replace(/\(0\)/g, "").replace(/[\s\-./()]/g, "");
4245
+ let international;
4246
+ if (/^\+\d+$/.test(compact)) international = compact.slice(1);
4247
+ else if (/^00\d+$/.test(compact)) international = compact.slice(2);
4248
+ else if (/^0\d+$/.test(compact)) {
4249
+ const code = country ? CALLING_CODE_OF_COUNTRY[country.trim().toUpperCase()] : void 0;
4250
+ if (!code) return raw;
4251
+ return `+${code}.${KEEPS_LEADING_ZERO.has(code) ? compact : compact.slice(1)}`;
4252
+ } else return raw;
4253
+ for (const length of [1, 2, 3]) {
4254
+ const code = international.slice(0, length);
4255
+ if (CALLING_CODES.has(code)) {
4256
+ const rest = international.slice(length);
4257
+ return `+${code}.${KEEPS_LEADING_ZERO.has(code) ? rest : rest.replace(/^0/, "")}`;
4258
+ }
4259
+ }
4260
+ return raw;
4261
+ }
4262
+
4263
+ // src/domains.ts
3977
4264
  var DomainSearchQuery = z16.object({ q: z16.string().trim().min(1).max(63) });
3978
4265
  var DOMAIN_UNAVAILABLE_REASONS = ["taken", "extension_not_supported", "premium", "not_registrable"];
3979
4266
  var DomainUnavailableReason = z16.enum(DOMAIN_UNAVAILABLE_REASONS);
@@ -3995,20 +4282,27 @@ var DomainRegistrant = z16.object({
3995
4282
  name: z16.string().trim().min(3).max(120).regex(/\S+\s+\S+/, "must be a first and a last name"),
3996
4283
  organization: z16.string().trim().min(1).max(120).nullable().optional(),
3997
4284
  email: Email,
3998
- phone: z16.string().trim().regex(/^\+\d{1,3}\.\d{4,14}$/, "must be +<country code>.<number>, such as +49.3012345678"),
4285
+ phone: z16.string().trim().min(1).max(40),
3999
4286
  street: z16.string().trim().min(3).max(200),
4000
4287
  city: z16.string().trim().min(1).max(100),
4001
4288
  state: z16.string().trim().min(1).max(100),
4002
4289
  postal_code: z16.string().trim().min(2).max(20),
4003
4290
  country_code: z16.string().trim().toUpperCase().regex(/^[A-Z]{2}$/, "must be a two-letter country code such as DE")
4004
- });
4291
+ }).superRefine((holder, ctx) => {
4292
+ if (typeof holder.phone === "string" && !REGISTRY_PHONE.test(normalizePhone(holder.phone, holder.country_code))) {
4293
+ ctx.addIssue({ code: z16.ZodIssueCode.custom, path: ["phone"], message: "must be a phone number with its country code, such as +49 30 1234 5678" });
4294
+ }
4295
+ }).transform((holder) => ({ ...holder, phone: normalizePhone(holder.phone, holder.country_code) }));
4005
4296
  var MAX_DOMAIN_ORDERS_PER_DAY = 2;
4297
+ var DOMAIN_ORDER_KINDS = ["sending", "domain_only"];
4298
+ var DomainOrderKind = z16.enum(DOMAIN_ORDER_KINDS);
4006
4299
  var DomainOrderCreate = z16.object({
4007
4300
  domain: SendingDomainName,
4008
4301
  price_cents: z16.number().int().min(0),
4009
4302
  registrant: DomainRegistrant,
4010
- from_name: z16.string().trim().min(1).max(120),
4011
- from_local_part: z16.string().trim().toLowerCase().regex(/^[a-z0-9](?:[a-z0-9._+-]{0,62}[a-z0-9])?$/, "must be the part before the @, such as hello"),
4303
+ kind: DomainOrderKind.default("sending"),
4304
+ from_name: z16.string().trim().min(1).max(120).optional(),
4305
+ from_local_part: z16.string().trim().toLowerCase().regex(/^[a-z0-9](?:[a-z0-9._+-]{0,62}[a-z0-9])?$/, "must be the part before the @, such as hello").optional(),
4012
4306
  /**
4013
4307
  * Where Stripe returns to after paying, and after leaving the payment. The
4014
4308
  * service adds `domain_order=<order id>` to both, so the page coming back
@@ -4019,6 +4313,10 @@ var DomainOrderCreate = z16.object({
4019
4313
  cancel_url: z16.string().url(),
4020
4314
  /** The buyer accepted the terms of service (which cover bought domains) of this version. */
4021
4315
  accept_terms: AcceptTerms
4316
+ }).superRefine((order, ctx) => {
4317
+ if (order.kind !== "sending") return;
4318
+ if (!order.from_name) ctx.addIssue({ code: z16.ZodIssueCode.custom, path: ["from_name"], message: "is needed for a domain mail is sent from" });
4319
+ if (!order.from_local_part) ctx.addIssue({ code: z16.ZodIssueCode.custom, path: ["from_local_part"], message: "is needed for a domain mail is sent from" });
4022
4320
  });
4023
4321
  var DOMAIN_ORDER_STATES = [
4024
4322
  "awaiting_payment",
@@ -4041,8 +4339,10 @@ var DomainOrder = z16.object({
4041
4339
  /** Stripe's payment page while `awaiting_payment`; null otherwise. */
4042
4340
  checkout_url: z16.string().url().nullable(),
4043
4341
  registrant_name: z16.string(),
4044
- from_name: z16.string(),
4045
- from_email: Email,
4342
+ kind: DomainOrderKind,
4343
+ /** The sender, for a `sending` order; null for `domain_only`. */
4344
+ from_name: z16.string().nullable(),
4345
+ from_email: Email.nullable(),
4046
4346
  /** The sending domain once `ready`. */
4047
4347
  sending_domain_id: Id.nullable(),
4048
4348
  /** When the paid year ends, once registered. */
@@ -6330,6 +6630,7 @@ export {
6330
6630
  DOCUMENT_SCHEMA_VERSIONS,
6331
6631
  DOMAIN_BUYING_BLOCKS,
6332
6632
  DOMAIN_BUYING_NOT_CONFIGURED_REASON,
6633
+ DOMAIN_ORDER_KINDS,
6333
6634
  DOMAIN_ORDER_STATES,
6334
6635
  DOMAIN_PRICE_CHANGED_REASON,
6335
6636
  DOMAIN_UNAVAILABLE_REASONS,
@@ -6341,6 +6642,7 @@ export {
6341
6642
  DomainOffer,
6342
6643
  DomainOrder,
6343
6644
  DomainOrderCreate,
6645
+ DomainOrderKind,
6344
6646
  DomainOrderState,
6345
6647
  DomainRegistrant,
6346
6648
  DomainSearchQuery,
@@ -6554,6 +6856,7 @@ export {
6554
6856
  QuietHours,
6555
6857
  RECIPIENT_REJECTIONS,
6556
6858
  RECIPIENT_STATUSES,
6859
+ REGISTRY_PHONE,
6557
6860
  REQUEST_ID_HEADER,
6558
6861
  RESEND_EVENT_TYPES,
6559
6862
  RESERVED_MERGE_FIELDS,
@@ -6791,6 +7094,7 @@ export {
6791
7094
  missingInsertionTexts,
6792
7095
  missingRequiredMergeFields,
6793
7096
  normalizeChoiceKey,
7097
+ normalizePhone,
6794
7098
  nowSeconds,
6795
7099
  operationsWithAccess,
6796
7100
  ownEntry,
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.21.0",
6
+ "version": "0.22.0",
7
7
  "description": "The v1 API contract of the mail service: zod schemas and types for every request, response, error and webhook, the route table, and webhook signing helpers",
8
8
  "license": "MIT",
9
9
  "repository": {