shipmail-cli 0.1.6 → 0.1.8
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/cli.js +256 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
} from "shipmail";
|
|
13
13
|
|
|
14
14
|
// src/version.ts
|
|
15
|
-
var VERSION = "0.1.
|
|
15
|
+
var VERSION = "0.1.8";
|
|
16
16
|
|
|
17
17
|
// src/cli.ts
|
|
18
18
|
var DEFAULT_BASE_URL = "https://shipmail.to/api/v1";
|
|
@@ -358,6 +358,17 @@ Usage:
|
|
|
358
358
|
shipmail audiences subscribers unsubscribe <audience-id> <subscriber-id>
|
|
359
359
|
shipmail audiences subscribers resubscribe <audience-id> <subscriber-id> --consent-source "Signup form"
|
|
360
360
|
shipmail audiences subscribers remove <audience-id> <subscriber-id>
|
|
361
|
+
shipmail calendar events list --mailbox hello@example.com --from 2026-08-01T00:00:00Z --to 2026-08-08T00:00:00Z [--expand true] [--limit 100]
|
|
362
|
+
shipmail calendar events create --mailbox hello@example.com --title "Sync" --start 2026-08-01T14:00:00 [--timezone Europe/Paris] [--duration PT30M] [--attendees JSON|@file] [--reminders JSON|@file]
|
|
363
|
+
shipmail calendar events get <event-id> --mailbox hello@example.com
|
|
364
|
+
shipmail calendar events update <event-id> --mailbox hello@example.com [--title "..."] [--start ...]
|
|
365
|
+
shipmail calendar events delete <event-id> --mailbox hello@example.com
|
|
366
|
+
shipmail calendar availability --mailbox hello@example.com --from 2026-08-03T00:00:00Z --to 2026-08-04T00:00:00Z [--duration 30] [--days 1,2,3,4,5] [--window-start 540] [--window-end 1020]
|
|
367
|
+
shipmail booking-pages list [--limit 25] [--cursor cur]
|
|
368
|
+
shipmail booking-pages create --name "Intro" --mailbox hello@example.com --slug intro --duration-minutes 30 --availability-days 1,2,3,4,5 --window-start-minutes 540 --window-end-minutes 1020 --timezone America/New_York
|
|
369
|
+
shipmail booking-pages get <id>
|
|
370
|
+
shipmail booking-pages update <id> [--name "..."] [--active false]
|
|
371
|
+
shipmail booking-pages delete <id>
|
|
361
372
|
|
|
362
373
|
Global options:
|
|
363
374
|
--api-key <key> API key. Defaults to SHIPMAIL_API_KEY.
|
|
@@ -693,6 +704,7 @@ async function runSuppressions(client, parsed, out) {
|
|
|
693
704
|
}
|
|
694
705
|
var SUBSCRIBER_STATUS_VALUES = [
|
|
695
706
|
"subscribed",
|
|
707
|
+
"pending",
|
|
696
708
|
"unsubscribed",
|
|
697
709
|
"bounced",
|
|
698
710
|
"complained",
|
|
@@ -974,6 +986,247 @@ async function runNewsletterAssets(client, parsed, out) {
|
|
|
974
986
|
}
|
|
975
987
|
throw new CliUsageError("Unknown newsletter-assets command.");
|
|
976
988
|
}
|
|
989
|
+
var CALENDAR_EVENT_STATUSES = [
|
|
990
|
+
"confirmed",
|
|
991
|
+
"tentative",
|
|
992
|
+
"cancelled"
|
|
993
|
+
];
|
|
994
|
+
var CALENDAR_FREE_BUSY_STATUSES = ["free", "busy"];
|
|
995
|
+
var CALENDAR_PRIVACIES = ["public", "private", "secret"];
|
|
996
|
+
function requireNumber(options, key) {
|
|
997
|
+
const value = getNumber(options, key);
|
|
998
|
+
if (value === void 0) throw new CliUsageError(`Missing --${key}.`);
|
|
999
|
+
return value;
|
|
1000
|
+
}
|
|
1001
|
+
function getIntList(options, key) {
|
|
1002
|
+
return getStringList(options, key).map((raw) => {
|
|
1003
|
+
const value = Number(raw);
|
|
1004
|
+
if (!Number.isInteger(value)) {
|
|
1005
|
+
throw new CliUsageError(`--${key} must be a comma-separated list of integers.`);
|
|
1006
|
+
}
|
|
1007
|
+
return value;
|
|
1008
|
+
});
|
|
1009
|
+
}
|
|
1010
|
+
function requireIntList(options, key) {
|
|
1011
|
+
const values = getIntList(options, key);
|
|
1012
|
+
if (values.length === 0) throw new CliUsageError(`Missing --${key}.`);
|
|
1013
|
+
return values;
|
|
1014
|
+
}
|
|
1015
|
+
function getEnum(options, key, allowed) {
|
|
1016
|
+
const value = getString(options, key);
|
|
1017
|
+
if (value === void 0) return void 0;
|
|
1018
|
+
const match = allowed.find((candidate) => candidate === value);
|
|
1019
|
+
if (match === void 0) {
|
|
1020
|
+
throw new CliUsageError(`--${key} must be one of: ${allowed.join(", ")}.`);
|
|
1021
|
+
}
|
|
1022
|
+
return match;
|
|
1023
|
+
}
|
|
1024
|
+
function isReminderArray(value) {
|
|
1025
|
+
return Array.isArray(value) && value.every(
|
|
1026
|
+
(item) => typeof item === "object" && item !== null && !Array.isArray(item) && Number.isInteger(item.minutes_before)
|
|
1027
|
+
);
|
|
1028
|
+
}
|
|
1029
|
+
async function readRemindersInput(value) {
|
|
1030
|
+
const parsed = await readJsonInput(value);
|
|
1031
|
+
if (parsed === void 0) return void 0;
|
|
1032
|
+
if (!isReminderArray(parsed)) {
|
|
1033
|
+
throw new CliUsageError("--reminders must be a JSON array of { minutes_before } objects.");
|
|
1034
|
+
}
|
|
1035
|
+
return parsed;
|
|
1036
|
+
}
|
|
1037
|
+
function isAttendeeArray(value) {
|
|
1038
|
+
return Array.isArray(value) && value.every((item) => {
|
|
1039
|
+
if (typeof item !== "object" || item === null || Array.isArray(item)) return false;
|
|
1040
|
+
const email = Reflect.get(item, "email");
|
|
1041
|
+
const name = Reflect.get(item, "name");
|
|
1042
|
+
return typeof email === "string" && (name === void 0 || typeof name === "string");
|
|
1043
|
+
});
|
|
1044
|
+
}
|
|
1045
|
+
async function readAttendeesInput(value) {
|
|
1046
|
+
const parsed = await readJsonInput(value);
|
|
1047
|
+
if (parsed === void 0) return void 0;
|
|
1048
|
+
if (!isAttendeeArray(parsed)) {
|
|
1049
|
+
throw new CliUsageError("--attendees must be a JSON array of { email, name? } objects.");
|
|
1050
|
+
}
|
|
1051
|
+
return parsed;
|
|
1052
|
+
}
|
|
1053
|
+
async function calendarEventFields(options) {
|
|
1054
|
+
const description = getString(options, "description");
|
|
1055
|
+
const timezone = getString(options, "timezone");
|
|
1056
|
+
const duration = getString(options, "duration");
|
|
1057
|
+
const allDay = getBoolean(options, "all-day");
|
|
1058
|
+
const location = getString(options, "location");
|
|
1059
|
+
const videoUrl = getString(options, "video-url");
|
|
1060
|
+
const color = getString(options, "color");
|
|
1061
|
+
const status = getEnum(options, "status", CALENDAR_EVENT_STATUSES);
|
|
1062
|
+
const freeBusyStatus = getEnum(options, "free-busy-status", CALENDAR_FREE_BUSY_STATUSES);
|
|
1063
|
+
const privacy = getEnum(options, "privacy", CALENDAR_PRIVACIES);
|
|
1064
|
+
const reminders = await readRemindersInput(getString(options, "reminders"));
|
|
1065
|
+
const attendees = await readAttendeesInput(getString(options, "attendees"));
|
|
1066
|
+
return {
|
|
1067
|
+
...description !== void 0 ? { description } : {},
|
|
1068
|
+
...timezone !== void 0 ? { timezone } : {},
|
|
1069
|
+
...duration !== void 0 ? { duration } : {},
|
|
1070
|
+
...allDay !== void 0 ? { all_day: allDay } : {},
|
|
1071
|
+
...location !== void 0 ? { location } : {},
|
|
1072
|
+
...videoUrl !== void 0 ? { video_url: videoUrl } : {},
|
|
1073
|
+
...color !== void 0 ? { color } : {},
|
|
1074
|
+
...status !== void 0 ? { status } : {},
|
|
1075
|
+
...freeBusyStatus !== void 0 ? { free_busy_status: freeBusyStatus } : {},
|
|
1076
|
+
...privacy !== void 0 ? { privacy } : {},
|
|
1077
|
+
...reminders !== void 0 ? { reminders } : {},
|
|
1078
|
+
...attendees !== void 0 ? { attendees } : {}
|
|
1079
|
+
};
|
|
1080
|
+
}
|
|
1081
|
+
async function runCalendarEvents(client, parsed, out) {
|
|
1082
|
+
const subcommand = parsed.positional[2];
|
|
1083
|
+
const options = parsed.options;
|
|
1084
|
+
if (subcommand === "list") {
|
|
1085
|
+
const params = {
|
|
1086
|
+
mailbox: getRequiredString(options, "mailbox"),
|
|
1087
|
+
from: getRequiredString(options, "from"),
|
|
1088
|
+
to: getRequiredString(options, "to"),
|
|
1089
|
+
expand: getBoolean(options, "expand"),
|
|
1090
|
+
calendar_id: getString(options, "calendar-id"),
|
|
1091
|
+
cursor: getString(options, "cursor"),
|
|
1092
|
+
limit: getNumber(options, "limit")
|
|
1093
|
+
};
|
|
1094
|
+
writeJson(out, await client.calendar.events.list(params));
|
|
1095
|
+
return;
|
|
1096
|
+
}
|
|
1097
|
+
if (subcommand === "create") {
|
|
1098
|
+
const params = {
|
|
1099
|
+
mailbox: getRequiredString(options, "mailbox"),
|
|
1100
|
+
title: getRequiredString(options, "title"),
|
|
1101
|
+
start: getRequiredString(options, "start"),
|
|
1102
|
+
calendar_id: getString(options, "calendar-id"),
|
|
1103
|
+
...await calendarEventFields(options)
|
|
1104
|
+
};
|
|
1105
|
+
writeJson(out, await client.calendar.events.create(params));
|
|
1106
|
+
return;
|
|
1107
|
+
}
|
|
1108
|
+
if (subcommand === "get") {
|
|
1109
|
+
const id = requirePositional(parsed.positional, 3, "event id");
|
|
1110
|
+
writeJson(
|
|
1111
|
+
out,
|
|
1112
|
+
await client.calendar.events.get(id, { mailbox: getRequiredString(options, "mailbox") })
|
|
1113
|
+
);
|
|
1114
|
+
return;
|
|
1115
|
+
}
|
|
1116
|
+
if (subcommand === "update") {
|
|
1117
|
+
const id = requirePositional(parsed.positional, 3, "event id");
|
|
1118
|
+
const params = {
|
|
1119
|
+
mailbox: getRequiredString(options, "mailbox"),
|
|
1120
|
+
title: getString(options, "title"),
|
|
1121
|
+
start: getString(options, "start"),
|
|
1122
|
+
...await calendarEventFields(options)
|
|
1123
|
+
};
|
|
1124
|
+
writeJson(out, await client.calendar.events.update(id, params));
|
|
1125
|
+
return;
|
|
1126
|
+
}
|
|
1127
|
+
if (subcommand === "delete") {
|
|
1128
|
+
const id = requirePositional(parsed.positional, 3, "event id");
|
|
1129
|
+
await client.calendar.events.delete(id, { mailbox: getRequiredString(options, "mailbox") });
|
|
1130
|
+
writeJson(out, { ok: true, id });
|
|
1131
|
+
return;
|
|
1132
|
+
}
|
|
1133
|
+
throw new CliUsageError("Unknown calendar events command.");
|
|
1134
|
+
}
|
|
1135
|
+
async function runCalendar(client, parsed, out) {
|
|
1136
|
+
const subcommand = parsed.positional[1];
|
|
1137
|
+
if (subcommand === "events") {
|
|
1138
|
+
await runCalendarEvents(client, parsed, out);
|
|
1139
|
+
return;
|
|
1140
|
+
}
|
|
1141
|
+
if (subcommand === "availability") {
|
|
1142
|
+
const options = parsed.options;
|
|
1143
|
+
const days = getIntList(options, "days");
|
|
1144
|
+
const params = {
|
|
1145
|
+
mailbox: getRequiredString(options, "mailbox"),
|
|
1146
|
+
from: getRequiredString(options, "from"),
|
|
1147
|
+
to: getRequiredString(options, "to"),
|
|
1148
|
+
duration: getNumber(options, "duration"),
|
|
1149
|
+
interval: getNumber(options, "interval"),
|
|
1150
|
+
timezone: getString(options, "timezone"),
|
|
1151
|
+
...days.length > 0 ? { days } : {},
|
|
1152
|
+
window_start: getNumber(options, "window-start"),
|
|
1153
|
+
window_end: getNumber(options, "window-end"),
|
|
1154
|
+
buffer: getNumber(options, "buffer"),
|
|
1155
|
+
minimum_notice: getNumber(options, "minimum-notice")
|
|
1156
|
+
};
|
|
1157
|
+
writeJson(out, await client.calendar.availability(params));
|
|
1158
|
+
return;
|
|
1159
|
+
}
|
|
1160
|
+
throw new CliUsageError("Unknown calendar command.");
|
|
1161
|
+
}
|
|
1162
|
+
async function runBookingPages(client, parsed, out) {
|
|
1163
|
+
const subcommand = parsed.positional[1];
|
|
1164
|
+
const options = parsed.options;
|
|
1165
|
+
if (subcommand === "list") {
|
|
1166
|
+
writeJson(
|
|
1167
|
+
out,
|
|
1168
|
+
await client.bookingPages.list({
|
|
1169
|
+
cursor: getString(options, "cursor"),
|
|
1170
|
+
limit: getNumber(options, "limit")
|
|
1171
|
+
})
|
|
1172
|
+
);
|
|
1173
|
+
return;
|
|
1174
|
+
}
|
|
1175
|
+
if (subcommand === "create") {
|
|
1176
|
+
const params = {
|
|
1177
|
+
name: getRequiredString(options, "name"),
|
|
1178
|
+
mailbox: getRequiredString(options, "mailbox"),
|
|
1179
|
+
slug: getRequiredString(options, "slug"),
|
|
1180
|
+
duration_minutes: requireNumber(options, "duration-minutes"),
|
|
1181
|
+
availability_days: requireIntList(options, "availability-days"),
|
|
1182
|
+
window_start_minutes: requireNumber(options, "window-start-minutes"),
|
|
1183
|
+
window_end_minutes: requireNumber(options, "window-end-minutes"),
|
|
1184
|
+
timezone: getRequiredString(options, "timezone"),
|
|
1185
|
+
description: getString(options, "description"),
|
|
1186
|
+
buffer_minutes: getNumber(options, "buffer-minutes"),
|
|
1187
|
+
minimum_notice_minutes: getNumber(options, "minimum-notice-minutes"),
|
|
1188
|
+
max_advance_days: getNumber(options, "max-advance-days"),
|
|
1189
|
+
active: getBoolean(options, "active")
|
|
1190
|
+
};
|
|
1191
|
+
writeJson(out, await client.bookingPages.create(params));
|
|
1192
|
+
return;
|
|
1193
|
+
}
|
|
1194
|
+
if (subcommand === "get") {
|
|
1195
|
+
writeJson(
|
|
1196
|
+
out,
|
|
1197
|
+
await client.bookingPages.get(requirePositional(parsed.positional, 2, "booking page id"))
|
|
1198
|
+
);
|
|
1199
|
+
return;
|
|
1200
|
+
}
|
|
1201
|
+
if (subcommand === "update") {
|
|
1202
|
+
const id = requirePositional(parsed.positional, 2, "booking page id");
|
|
1203
|
+
const days = getIntList(options, "availability-days");
|
|
1204
|
+
const params = {
|
|
1205
|
+
name: getString(options, "name"),
|
|
1206
|
+
mailbox: getString(options, "mailbox"),
|
|
1207
|
+
slug: getString(options, "slug"),
|
|
1208
|
+
duration_minutes: getNumber(options, "duration-minutes"),
|
|
1209
|
+
...days.length > 0 ? { availability_days: days } : {},
|
|
1210
|
+
window_start_minutes: getNumber(options, "window-start-minutes"),
|
|
1211
|
+
window_end_minutes: getNumber(options, "window-end-minutes"),
|
|
1212
|
+
timezone: getString(options, "timezone"),
|
|
1213
|
+
description: getString(options, "description"),
|
|
1214
|
+
buffer_minutes: getNumber(options, "buffer-minutes"),
|
|
1215
|
+
minimum_notice_minutes: getNumber(options, "minimum-notice-minutes"),
|
|
1216
|
+
max_advance_days: getNumber(options, "max-advance-days"),
|
|
1217
|
+
active: getBoolean(options, "active")
|
|
1218
|
+
};
|
|
1219
|
+
writeJson(out, await client.bookingPages.update(id, params));
|
|
1220
|
+
return;
|
|
1221
|
+
}
|
|
1222
|
+
if (subcommand === "delete") {
|
|
1223
|
+
const id = requirePositional(parsed.positional, 2, "booking page id");
|
|
1224
|
+
await client.bookingPages.delete(id);
|
|
1225
|
+
writeJson(out, { ok: true, id });
|
|
1226
|
+
return;
|
|
1227
|
+
}
|
|
1228
|
+
throw new CliUsageError("Unknown booking-pages command.");
|
|
1229
|
+
}
|
|
977
1230
|
function writeError(err, errOut) {
|
|
978
1231
|
if (err instanceof CliUsageError) {
|
|
979
1232
|
errOut.write(`Error: ${err.message}
|
|
@@ -1037,6 +1290,8 @@ async function runCli(argv, options = {}) {
|
|
|
1037
1290
|
else if (command === "newsletter-assets") await runNewsletterAssets(client, parsed, out);
|
|
1038
1291
|
else if (command === "newsletter-domains") await runNewsletterDomains(client, parsed, out);
|
|
1039
1292
|
else if (command === "audiences") await runAudiences(client, parsed, out);
|
|
1293
|
+
else if (command === "calendar") await runCalendar(client, parsed, out);
|
|
1294
|
+
else if (command === "booking-pages") await runBookingPages(client, parsed, out);
|
|
1040
1295
|
else throw new CliUsageError(`Unknown command: ${command}.`);
|
|
1041
1296
|
return 0;
|
|
1042
1297
|
} catch (err) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shipmail-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "Official CLI for the ShipMail API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"access": "public"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"shipmail": "0.1.
|
|
44
|
+
"shipmail": "0.1.31"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"tsup": "^8.4.0",
|