@robbeverhelst/do 1.285.0 → 1.286.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/do.js +271 -1
- package/package.json +1 -1
package/dist/do.js
CHANGED
|
@@ -5096,6 +5096,67 @@ var seatingProposals = pgTable("seating_proposals", {
|
|
|
5096
5096
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
|
|
5097
5097
|
}, (t) => [index("seating_proposals_list_idx").on(t.guestListId)]);
|
|
5098
5098
|
|
|
5099
|
+
// ../../packages/schema/src/db/mail.ts
|
|
5100
|
+
var mailCampaignStatus = pgEnum("mail_campaign_status", [
|
|
5101
|
+
"draft",
|
|
5102
|
+
"sending",
|
|
5103
|
+
"sent",
|
|
5104
|
+
"cancelled"
|
|
5105
|
+
]);
|
|
5106
|
+
var mailDeliveryStatus = pgEnum("mail_delivery_status", [
|
|
5107
|
+
"queued",
|
|
5108
|
+
"sending",
|
|
5109
|
+
"sent",
|
|
5110
|
+
"delivered",
|
|
5111
|
+
"bounced",
|
|
5112
|
+
"failed",
|
|
5113
|
+
"skipped"
|
|
5114
|
+
]);
|
|
5115
|
+
var mailCampaigns = pgTable("mail_campaigns", {
|
|
5116
|
+
id: text("id").primaryKey(),
|
|
5117
|
+
tenantId: text("tenant_id").notNull().references(() => tenants.id),
|
|
5118
|
+
guestListId: text("guest_list_id").references(() => guestLists.id, { onDelete: "cascade" }),
|
|
5119
|
+
kind: text("kind").notNull().default("message"),
|
|
5120
|
+
template: text("template").notNull(),
|
|
5121
|
+
data: jsonb("data").$type().notNull().default({}),
|
|
5122
|
+
replyTo: text("reply_to"),
|
|
5123
|
+
status: mailCampaignStatus("status").notNull().default("draft"),
|
|
5124
|
+
createdByUserId: text("created_by_user_id").references(() => users.id),
|
|
5125
|
+
testSentAt: timestamp("test_sent_at", { withTimezone: true }),
|
|
5126
|
+
startedAt: timestamp("started_at", { withTimezone: true }),
|
|
5127
|
+
finishedAt: timestamp("finished_at", { withTimezone: true }),
|
|
5128
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
5129
|
+
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
5130
|
+
}, (t) => [
|
|
5131
|
+
index("mail_campaigns_tenant_idx").on(t.tenantId),
|
|
5132
|
+
index("mail_campaigns_status_idx").on(t.status)
|
|
5133
|
+
]);
|
|
5134
|
+
var mailDeliveries = pgTable("mail_deliveries", {
|
|
5135
|
+
id: text("id").primaryKey(),
|
|
5136
|
+
tenantId: text("tenant_id").notNull().references(() => tenants.id),
|
|
5137
|
+
campaignId: text("campaign_id").notNull().references(() => mailCampaigns.id, { onDelete: "cascade" }),
|
|
5138
|
+
contactId: text("contact_id").references(() => contacts.id),
|
|
5139
|
+
householdId: text("household_id").references(() => households.id),
|
|
5140
|
+
toEmail: text("to_email").notNull(),
|
|
5141
|
+
language: text("language").notNull().default("nl"),
|
|
5142
|
+
data: jsonb("data").$type().notNull().default({}),
|
|
5143
|
+
status: mailDeliveryStatus("status").notNull().default("queued"),
|
|
5144
|
+
transport: text("transport"),
|
|
5145
|
+
providerMessageId: text("provider_message_id"),
|
|
5146
|
+
attempts: integer("attempts").notNull().default(0),
|
|
5147
|
+
error: text("error"),
|
|
5148
|
+
sentAt: timestamp("sent_at", { withTimezone: true }),
|
|
5149
|
+
deliveredAt: timestamp("delivered_at", { withTimezone: true }),
|
|
5150
|
+
bouncedAt: timestamp("bounced_at", { withTimezone: true }),
|
|
5151
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
|
|
5152
|
+
}, (t) => [
|
|
5153
|
+
index("mail_deliveries_campaign_status_idx").on(t.campaignId, t.status),
|
|
5154
|
+
index("mail_deliveries_sent_at_idx").on(t.sentAt),
|
|
5155
|
+
index("mail_deliveries_household_idx").on(t.householdId),
|
|
5156
|
+
uniqueIndex("mail_deliveries_provider_message_uniq").on(t.providerMessageId),
|
|
5157
|
+
uniqueIndex("mail_deliveries_campaign_email_uniq").on(t.campaignId, t.toEmail)
|
|
5158
|
+
]);
|
|
5159
|
+
|
|
5099
5160
|
// ../../packages/schema/src/db/calendar.ts
|
|
5100
5161
|
var calendarLinkPurpose = pgEnum("calendar_link_purpose", ["block", "deadline"]);
|
|
5101
5162
|
var calendarEventLinks = pgTable("calendar_event_links", {
|
|
@@ -26739,6 +26800,124 @@ var thankYouViewSchema = object({
|
|
|
26739
26800
|
thanked: array(thankYouGiftSchema)
|
|
26740
26801
|
});
|
|
26741
26802
|
|
|
26803
|
+
// ../../packages/schema/src/contracts/mail.ts
|
|
26804
|
+
var MAIL_LANGUAGES = ["nl", "pt"];
|
|
26805
|
+
var mailLanguageSchema = _enum2(MAIL_LANGUAGES);
|
|
26806
|
+
var MAIL_CAMPAIGN_STATUSES = ["draft", "sending", "sent", "cancelled"];
|
|
26807
|
+
var mailCampaignStatusSchema = _enum2(MAIL_CAMPAIGN_STATUSES);
|
|
26808
|
+
var MAIL_DELIVERY_STATUSES = [
|
|
26809
|
+
"queued",
|
|
26810
|
+
"sending",
|
|
26811
|
+
"sent",
|
|
26812
|
+
"delivered",
|
|
26813
|
+
"bounced",
|
|
26814
|
+
"failed",
|
|
26815
|
+
"skipped"
|
|
26816
|
+
];
|
|
26817
|
+
var mailDeliveryStatusSchema = _enum2(MAIL_DELIVERY_STATUSES);
|
|
26818
|
+
var mailCampaignSchema = createSelectSchema(mailCampaigns, {
|
|
26819
|
+
data: record(string2(), unknown()),
|
|
26820
|
+
testSentAt: exports_coerce.date().nullable().default(null),
|
|
26821
|
+
startedAt: exports_coerce.date().nullable(),
|
|
26822
|
+
finishedAt: exports_coerce.date().nullable(),
|
|
26823
|
+
createdAt: exports_coerce.date(),
|
|
26824
|
+
updatedAt: exports_coerce.date()
|
|
26825
|
+
});
|
|
26826
|
+
var mailDeliverySchema = createSelectSchema(mailDeliveries, {
|
|
26827
|
+
data: record(string2(), unknown()),
|
|
26828
|
+
sentAt: exports_coerce.date().nullable(),
|
|
26829
|
+
deliveredAt: exports_coerce.date().nullable(),
|
|
26830
|
+
bouncedAt: exports_coerce.date().nullable(),
|
|
26831
|
+
createdAt: exports_coerce.date()
|
|
26832
|
+
});
|
|
26833
|
+
var mailFooterSchema = object({
|
|
26834
|
+
deleteBy: keyDateDaySchema.optional(),
|
|
26835
|
+
contact: email2().max(320).optional()
|
|
26836
|
+
}).strict();
|
|
26837
|
+
var lineSchema = string2().trim().min(1).max(2000);
|
|
26838
|
+
var mailMessageCopySchema = object({
|
|
26839
|
+
subject: string2().trim().min(1).max(200),
|
|
26840
|
+
heading: string2().trim().min(1).max(200),
|
|
26841
|
+
paragraphs: array(lineSchema).max(20).default([]),
|
|
26842
|
+
button: object({ label: string2().trim().min(1).max(80), url: url() }).strict().nullish()
|
|
26843
|
+
}).strict();
|
|
26844
|
+
var mailMessageDataSchema = object({
|
|
26845
|
+
nl: mailMessageCopySchema,
|
|
26846
|
+
pt: mailMessageCopySchema.optional(),
|
|
26847
|
+
footer: mailFooterSchema.optional()
|
|
26848
|
+
}).strict();
|
|
26849
|
+
var mailProviderEventSchema = looseObject({
|
|
26850
|
+
type: string2().min(1),
|
|
26851
|
+
created_at: string2().optional(),
|
|
26852
|
+
data: looseObject({
|
|
26853
|
+
email_id: string2().min(1),
|
|
26854
|
+
to: array(string2()).optional(),
|
|
26855
|
+
bounce: looseObject({
|
|
26856
|
+
type: string2().optional(),
|
|
26857
|
+
message: string2().optional()
|
|
26858
|
+
}).optional()
|
|
26859
|
+
})
|
|
26860
|
+
});
|
|
26861
|
+
var MAIL_CAMPAIGN_KINDS = ["message", "save_the_date", "invitation"];
|
|
26862
|
+
var mailCampaignKindSchema = _enum2(MAIL_CAMPAIGN_KINDS);
|
|
26863
|
+
var MAIL_TEMPLATES = ["message"];
|
|
26864
|
+
var mailTemplateSchema = _enum2(MAIL_TEMPLATES);
|
|
26865
|
+
var mailTemplateDataSchemas = {
|
|
26866
|
+
message: mailMessageDataSchema
|
|
26867
|
+
};
|
|
26868
|
+
function mailTemplateDataError(template, data) {
|
|
26869
|
+
const parsed = mailTemplateDataSchemas[template].safeParse(data);
|
|
26870
|
+
return parsed.success ? null : parsed.error.issues[0]?.message ?? "invalid data";
|
|
26871
|
+
}
|
|
26872
|
+
var replyToSchema = email2().max(320);
|
|
26873
|
+
var createMailCampaignInputSchema = object({
|
|
26874
|
+
id: ulidSchema,
|
|
26875
|
+
guestListId: ulidSchema,
|
|
26876
|
+
kind: mailCampaignKindSchema.default("message"),
|
|
26877
|
+
template: mailTemplateSchema.default("message"),
|
|
26878
|
+
data: record(string2(), unknown()),
|
|
26879
|
+
replyTo: replyToSchema.nullish()
|
|
26880
|
+
}).strict().superRefine((input, ctx) => {
|
|
26881
|
+
const error = mailTemplateDataError(input.template, input.data);
|
|
26882
|
+
if (error)
|
|
26883
|
+
ctx.addIssue({ code: "custom", path: ["data"], message: error });
|
|
26884
|
+
});
|
|
26885
|
+
var updateMailCampaignInputSchema = object({
|
|
26886
|
+
kind: mailCampaignKindSchema.optional(),
|
|
26887
|
+
data: record(string2(), unknown()).optional(),
|
|
26888
|
+
replyTo: replyToSchema.nullish()
|
|
26889
|
+
}).strict();
|
|
26890
|
+
var mailCampaignsQuerySchema = object({ guestListId: ulidSchema }).strict();
|
|
26891
|
+
var mailPreviewQuerySchema = object({ language: mailLanguageSchema.default("nl") }).strict();
|
|
26892
|
+
var mailPreviewSchema = object({
|
|
26893
|
+
language: mailLanguageSchema,
|
|
26894
|
+
subject: string2(),
|
|
26895
|
+
html: string2(),
|
|
26896
|
+
text: string2()
|
|
26897
|
+
});
|
|
26898
|
+
var mailTestResultSchema = object({ to: array(string2()) });
|
|
26899
|
+
var sendMailCampaignInputSchema = object({ households: number2().int().positive() }).strict();
|
|
26900
|
+
var householdMailStatusSchema = _enum2([
|
|
26901
|
+
"queued",
|
|
26902
|
+
"sent",
|
|
26903
|
+
"delivered",
|
|
26904
|
+
"bounced",
|
|
26905
|
+
"failed",
|
|
26906
|
+
"skipped"
|
|
26907
|
+
]);
|
|
26908
|
+
var mailRecipientHouseholdSchema = object({
|
|
26909
|
+
householdId: string2().nullable(),
|
|
26910
|
+
name: string2(),
|
|
26911
|
+
language: mailLanguageSchema,
|
|
26912
|
+
addresses: number2().int().nonnegative(),
|
|
26913
|
+
status: householdMailStatusSchema.nullable()
|
|
26914
|
+
});
|
|
26915
|
+
var mailCampaignViewSchema = mailCampaignSchema.extend({
|
|
26916
|
+
households: array(mailRecipientHouseholdSchema),
|
|
26917
|
+
counts: partialRecord(mailDeliveryStatusSchema, number2().int().nonnegative()),
|
|
26918
|
+
readyToSend: boolean3()
|
|
26919
|
+
});
|
|
26920
|
+
|
|
26742
26921
|
// ../../packages/schema/src/contracts/calendar.ts
|
|
26743
26922
|
var calendarEventLinkSchema = createSelectSchema(calendarEventLinks, {
|
|
26744
26923
|
createdAt: exports_coerce.date(),
|
|
@@ -28439,7 +28618,7 @@ function parseCapture2(input, now) {
|
|
|
28439
28618
|
|
|
28440
28619
|
// src/meta.ts
|
|
28441
28620
|
var CLI_NAME = "do";
|
|
28442
|
-
var VERSION = "1.
|
|
28621
|
+
var VERSION = "1.286.0";
|
|
28443
28622
|
var API_PREFIX = "/api/v1";
|
|
28444
28623
|
var DEFAULT_API_URL = "http://localhost:3001";
|
|
28445
28624
|
|
|
@@ -33828,6 +34007,61 @@ var COMMAND_SPECS = [
|
|
|
33828
34007
|
scopes: ["contacts:write"],
|
|
33829
34008
|
returns: "SeatingProposal"
|
|
33830
34009
|
},
|
|
34010
|
+
{
|
|
34011
|
+
path: ["mail-campaigns", "list"],
|
|
34012
|
+
summary: "A guest list's mail campaigns (save-the-dates, invitations), newest first.",
|
|
34013
|
+
args: [],
|
|
34014
|
+
flags: [{ name: "list", type: "string", description: "The guest list's id (required)." }],
|
|
34015
|
+
scopes: ["contacts:read"],
|
|
34016
|
+
returns: "MailCampaignView",
|
|
34017
|
+
notes: "Each campaign carries the households it reaches (a draft: who it would go to) with their status, its mails by status, and readyToSend."
|
|
34018
|
+
},
|
|
34019
|
+
{
|
|
34020
|
+
path: ["mail-campaigns", "get"],
|
|
34021
|
+
summary: "One mail campaign, with its households and how far it got.",
|
|
34022
|
+
args: [{ name: "id", required: true, description: "The campaign's id." }],
|
|
34023
|
+
flags: [],
|
|
34024
|
+
scopes: ["contacts:read"],
|
|
34025
|
+
returns: "MailCampaignView"
|
|
34026
|
+
},
|
|
34027
|
+
{
|
|
34028
|
+
path: ["mail-campaigns", "create"],
|
|
34029
|
+
summary: "Draft a mail campaign for a guest list; nothing is sent.",
|
|
34030
|
+
args: [],
|
|
34031
|
+
flags: [
|
|
34032
|
+
{
|
|
34033
|
+
name: "data",
|
|
34034
|
+
type: "string",
|
|
34035
|
+
description: 'JSON CreateMailCampaignInput, e.g. {"guestListId":"01\u2026","kind":"save_the_date","template":"message","data":{"nl":{"subject":"\u2026","heading":"\u2026","paragraphs":["\u2026"]},"pt":{\u2026},"footer":{"deleteBy":"2027-12-31"}},"replyTo":"hallo@example.com"}'
|
|
34036
|
+
}
|
|
34037
|
+
],
|
|
34038
|
+
scopes: ["contacts:write"],
|
|
34039
|
+
returns: "MailCampaignView",
|
|
34040
|
+
notes: "Drafting only: a member previews it, sends a test to the Space's members and sends it from the Mail tab. An agent can never test or send."
|
|
34041
|
+
},
|
|
34042
|
+
{
|
|
34043
|
+
path: ["mail-campaigns", "update"],
|
|
34044
|
+
summary: "Edit a draft campaign (its copy, kind or reply address).",
|
|
34045
|
+
args: [{ name: "id", required: true, description: "The campaign's id." }],
|
|
34046
|
+
flags: [
|
|
34047
|
+
{
|
|
34048
|
+
name: "data",
|
|
34049
|
+
type: "string",
|
|
34050
|
+
description: 'JSON UpdateMailCampaignInput, e.g. {"data":{"nl":{\u2026}}}'
|
|
34051
|
+
}
|
|
34052
|
+
],
|
|
34053
|
+
scopes: ["contacts:write"],
|
|
34054
|
+
returns: "MailCampaignView",
|
|
34055
|
+
notes: "Only a draft changes (409 otherwise); an edit makes the last test stale."
|
|
34056
|
+
},
|
|
34057
|
+
{
|
|
34058
|
+
path: ["mail-campaigns", "preview"],
|
|
34059
|
+
summary: "Draw a campaign's mail as its first household would get it.",
|
|
34060
|
+
args: [{ name: "id", required: true, description: "The campaign's id." }],
|
|
34061
|
+
flags: [{ name: "language", type: "string", description: "nl (default) or pt." }],
|
|
34062
|
+
scopes: ["contacts:read"],
|
|
34063
|
+
returns: "MailPreview"
|
|
34064
|
+
},
|
|
33831
34065
|
{
|
|
33832
34066
|
path: ["guest-lists", "thank-you"],
|
|
33833
34067
|
summary: "The gifts for the event: the cards still to send, then the ones sent.",
|
|
@@ -39006,6 +39240,42 @@ var HANDLERS = {
|
|
|
39006
39240
|
render: renderRecord
|
|
39007
39241
|
};
|
|
39008
39242
|
},
|
|
39243
|
+
"mail-campaigns list": async ({ flags, requireClient }) => {
|
|
39244
|
+
const list = flagString(flags, "list");
|
|
39245
|
+
if (!list)
|
|
39246
|
+
throw usageError("mail-campaigns list needs --list <guest list id>");
|
|
39247
|
+
parseInput(mailCampaignsQuerySchema, { guestListId: list });
|
|
39248
|
+
return {
|
|
39249
|
+
data: await requireClient().get("/mail-campaigns", { query: { guestListId: list } }),
|
|
39250
|
+
render: renderRecord
|
|
39251
|
+
};
|
|
39252
|
+
},
|
|
39253
|
+
"mail-campaigns get": async ({ args, requireClient }) => {
|
|
39254
|
+
const id = requireArg(args, 0, "campaign id");
|
|
39255
|
+
return { data: await requireClient().get(`/mail-campaigns/${id}`), render: renderRecord };
|
|
39256
|
+
},
|
|
39257
|
+
"mail-campaigns create": async ({ flags, requireClient }) => {
|
|
39258
|
+
const body = parseInput(createMailCampaignInputSchema, { id: ulid3(), ...readDataFlag(flags) });
|
|
39259
|
+
return { data: await requireClient().post("/mail-campaigns", body), render: renderRecord };
|
|
39260
|
+
},
|
|
39261
|
+
"mail-campaigns update": async ({ args, flags, requireClient }) => {
|
|
39262
|
+
const id = requireArg(args, 0, "campaign id");
|
|
39263
|
+
const body = parseInput(updateMailCampaignInputSchema, readDataFlag(flags));
|
|
39264
|
+
return {
|
|
39265
|
+
data: await requireClient().patch(`/mail-campaigns/${id}`, body),
|
|
39266
|
+
render: renderRecord
|
|
39267
|
+
};
|
|
39268
|
+
},
|
|
39269
|
+
"mail-campaigns preview": async ({ args, flags, requireClient }) => {
|
|
39270
|
+
const id = requireArg(args, 0, "campaign id");
|
|
39271
|
+
const query = parseInput(mailPreviewQuerySchema, {
|
|
39272
|
+
language: flagString(flags, "language") ?? "nl"
|
|
39273
|
+
});
|
|
39274
|
+
return {
|
|
39275
|
+
data: await requireClient().get(`/mail-campaigns/${id}/preview`, { query }),
|
|
39276
|
+
render: renderRecord
|
|
39277
|
+
};
|
|
39278
|
+
},
|
|
39009
39279
|
"guest-lists thank-you": async ({ args, requireClient }) => {
|
|
39010
39280
|
const id = requireArg(args, 0, "guest list id");
|
|
39011
39281
|
return {
|
package/package.json
CHANGED