@krak-stack/registry 0.1.11 → 0.1.14
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/README.md +31 -2
- package/dist/components/ui/app-brand.d.ts +18 -13
- package/dist/components/ui/app-brand.js +48 -15
- package/dist/components/ui/code-block.js +10 -6
- package/dist/components/ui/copy-button.d.ts +1 -1
- package/dist/components/ui/copy-button.js +1 -1
- package/dist/components/ui/data-table.d.ts +1 -1
- package/dist/components/ui/data-table.js +21 -20
- package/dist/components/ui/effect-form.js +7 -6
- package/dist/components/ui/file-picker.js +2 -1
- package/dist/components/ui/form.js +17 -15
- package/dist/components/ui/google-map.d.ts +6 -10
- package/dist/components/ui/google-map.js +19 -14
- package/dist/components/ui/locale-switcher.js +7 -1
- package/dist/components/ui/sidebar-layout.js +19 -21
- package/dist/components/ui/theme-switcher.js +1 -1
- package/dist/lib/docs-core.js +165 -109
- package/dist/lib/documentation-toolkit.d.ts +140 -0
- package/dist/lib/{docs-ai.js → documentation-toolkit.js} +54 -63
- package/dist/lib/httpapi-cli.d.ts +6 -6
- package/dist/lib/httpapi-cli.js +75 -48
- package/dist/lib/httpapi-client.d.ts +8 -2
- package/dist/lib/httpapi-client.js +21 -9
- package/dist/lib/httpapi-helpers.d.ts +15 -21
- package/dist/lib/httpapi-helpers.js +38 -26
- package/dist/lib/httpapi-mcp.js +73 -50
- package/dist/lib/httpapi-toolkit.d.ts +20 -0
- package/dist/lib/{httpapi-ai.js → httpapi-toolkit.js} +123 -100
- package/dist/lib/seo.js +29 -17
- package/dist/lib/webfetch-toolkit.d.ts +45 -0
- package/dist/lib/webfetch-toolkit.js +276 -0
- package/dist/oxlint/anti-slop/index.js +1592 -0
- package/dist/services/agent/client/atom.d.ts +7 -7
- package/dist/services/agent/client/index.js +55 -54
- package/dist/services/agent/index.d.ts +71 -71
- package/dist/services/agent/index.js +38 -19
- package/dist/services/notification/channels/index.d.ts +11 -9
- package/dist/services/notification/channels/ses/index.d.ts +6 -6
- package/dist/services/notification/channels/ses/index.js +15 -11
- package/dist/services/notification/client/index.js +3 -2
- package/dist/services/notification/client/notification-menu.d.ts +9 -9
- package/dist/services/notification/index.d.ts +7 -6
- package/dist/services/notification/persistence/drizzle.js +214 -0
- package/dist/services/notification/persistence/index.js +227 -0
- package/dist/services/notification/persistence/schema.js +118 -0
- package/dist/services/notification/public.js +3 -2
- package/dist/services/s3/index.d.ts +2 -16
- package/dist/services/s3/index.js +12 -9
- package/package.json +33 -7
- package/dist/lib/docs-ai.d.ts +0 -142
- package/dist/lib/httpapi-ai.d.ts +0 -54
|
@@ -32,8 +32,8 @@ export type NotificationMenuState = {
|
|
|
32
32
|
open: boolean;
|
|
33
33
|
unreadCount: number;
|
|
34
34
|
};
|
|
35
|
-
type NotificationAction = (notificationIds: readonly string[]) => Promise<
|
|
36
|
-
export type NotificationMenuProps = {
|
|
35
|
+
type NotificationAction<Result = ErrorOptions["cause"]> = (notificationIds: readonly string[]) => Promise<Result> | Result | void;
|
|
36
|
+
export type NotificationMenuProps<ActionResult = ErrorOptions["cause"]> = {
|
|
37
37
|
className?: string | undefined;
|
|
38
38
|
defaultOpen?: boolean | undefined;
|
|
39
39
|
error?: boolean | undefined;
|
|
@@ -42,35 +42,35 @@ export type NotificationMenuProps = {
|
|
|
42
42
|
markReadOnOpen?: boolean | undefined;
|
|
43
43
|
messages?: Partial<NotificationMenuMessages> | undefined;
|
|
44
44
|
notifications: readonly NotificationItem[];
|
|
45
|
-
onArchive?: NotificationAction | undefined;
|
|
46
|
-
onMarkRead?: NotificationAction | undefined;
|
|
45
|
+
onArchive?: NotificationAction<ActionResult> | undefined;
|
|
46
|
+
onMarkRead?: NotificationAction<ActionResult> | undefined;
|
|
47
47
|
onNavigate?: ((notification: NotificationItem) => void) | undefined;
|
|
48
48
|
onOpenChange?: ((open: boolean) => void) | undefined;
|
|
49
49
|
open?: boolean | undefined;
|
|
50
50
|
renderItem?: ((notification: NotificationItem) => ReactNode) | undefined;
|
|
51
51
|
renderTrigger?: ((state: NotificationMenuState) => ReactElement) | undefined;
|
|
52
52
|
};
|
|
53
|
-
export declare function NotificationMenu({ className, defaultOpen, error, isLoading, locale, markReadOnOpen, messages: messageOverrides, notifications, onArchive, onMarkRead, onNavigate, onOpenChange, open: controlledOpen, renderItem, renderTrigger, }: NotificationMenuProps): import("react").JSX.Element;
|
|
53
|
+
export declare function NotificationMenu<ActionResult = ErrorOptions["cause"]>({ className, defaultOpen, error, isLoading, locale, markReadOnOpen, messages: messageOverrides, notifications, onArchive, onMarkRead, onNavigate, onOpenChange, open: controlledOpen, renderItem, renderTrigger, }: NotificationMenuProps<ActionResult>): import("react").JSX.Element;
|
|
54
54
|
export declare function NotificationMenuTrigger({ labels, unreadCount, }: {
|
|
55
55
|
labels?: NotificationMenuMessages | undefined;
|
|
56
56
|
unreadCount: number;
|
|
57
57
|
}): import("react").JSX.Element;
|
|
58
|
-
export declare function NotificationList({ error, isLoading, labels, locale, notifications, onArchive, onNavigate, renderItem, tab, }: {
|
|
58
|
+
export declare function NotificationList<ActionResult>({ error, isLoading, labels, locale, notifications, onArchive, onNavigate, renderItem, tab, }: {
|
|
59
59
|
error: boolean;
|
|
60
60
|
isLoading: boolean;
|
|
61
61
|
labels: NotificationMenuMessages;
|
|
62
62
|
locale: string;
|
|
63
63
|
notifications: readonly NotificationItem[];
|
|
64
|
-
onArchive?: NotificationAction | undefined;
|
|
64
|
+
onArchive?: NotificationAction<ActionResult> | undefined;
|
|
65
65
|
onNavigate?: ((notification: NotificationItem) => void) | undefined;
|
|
66
66
|
renderItem?: ((notification: NotificationItem) => ReactNode) | undefined;
|
|
67
67
|
tab: NotificationMenuTab;
|
|
68
68
|
}): import("react").JSX.Element;
|
|
69
|
-
export declare function NotificationListItem({ labels, locale, notification, onArchive, onNavigate, renderItem, }: {
|
|
69
|
+
export declare function NotificationListItem<ActionResult>({ labels, locale, notification, onArchive, onNavigate, renderItem, }: {
|
|
70
70
|
labels: NotificationMenuMessages;
|
|
71
71
|
locale: string;
|
|
72
72
|
notification: NotificationItem;
|
|
73
|
-
onArchive?: NotificationAction | undefined;
|
|
73
|
+
onArchive?: NotificationAction<ActionResult> | undefined;
|
|
74
74
|
onNavigate?: ((notification: NotificationItem) => void) | undefined;
|
|
75
75
|
renderItem?: ((notification: NotificationItem) => ReactNode) | undefined;
|
|
76
76
|
}): import("react").JSX.Element;
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { Context, Effect, Layer } from "effect";
|
|
2
|
-
import { NotificationChannelRegistry, type NotificationMessage, type
|
|
2
|
+
import { NotificationChannelRegistry, type NotificationMessage, type NotificationChannel } from "./channels/index.js";
|
|
3
3
|
import { NotificationSendError } from "./schema.js";
|
|
4
|
-
export interface
|
|
4
|
+
export interface NotificationServiceContract {
|
|
5
5
|
readonly send: (message: NotificationMessage) => Effect.Effect<void, NotificationSendError>;
|
|
6
6
|
}
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
/** @deprecated Use NotificationServiceContract. */
|
|
8
|
+
export { type NotificationServiceContract as NotificationServiceShape };
|
|
9
|
+
declare const NotificationService_base: Context.ServiceClass<NotificationService, "NotificationService", NotificationServiceContract> & {
|
|
10
|
+
readonly make: Effect.Effect<NotificationServiceContract, never, NotificationChannelRegistry>;
|
|
9
11
|
};
|
|
10
12
|
export declare class NotificationService extends NotificationService_base {
|
|
11
13
|
static readonly layer: Layer.Layer<NotificationService, never, NotificationChannelRegistry>;
|
|
12
|
-
static readonly makeLayer: (channels: ReadonlyArray<
|
|
14
|
+
static readonly makeLayer: (channels: ReadonlyArray<NotificationChannel>) => Layer.Layer<NotificationService, never, never>;
|
|
13
15
|
static readonly noopLayer: Layer.Layer<NotificationService, never, never>;
|
|
14
16
|
static readonly localLayer: Layer.Layer<NotificationService, never, never>;
|
|
15
17
|
}
|
|
16
|
-
export {};
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
// ../../src/services/notification/persistence/drizzle.ts
|
|
2
|
+
import { sql } from "drizzle-orm";
|
|
3
|
+
import {
|
|
4
|
+
boolean,
|
|
5
|
+
check,
|
|
6
|
+
index,
|
|
7
|
+
integer,
|
|
8
|
+
jsonb,
|
|
9
|
+
pgTable,
|
|
10
|
+
text,
|
|
11
|
+
timestamp,
|
|
12
|
+
uniqueIndex,
|
|
13
|
+
uuid
|
|
14
|
+
} from "drizzle-orm/pg-core";
|
|
15
|
+
|
|
16
|
+
// ../../src/services/notification/persistence/schema.ts
|
|
17
|
+
import { Schema } from "effect";
|
|
18
|
+
var NOTIFICATION_DELIVERY_PURPOSES = [
|
|
19
|
+
"transactional",
|
|
20
|
+
"notification"
|
|
21
|
+
];
|
|
22
|
+
var NOTIFICATION_DELIVERY_STATUSES = [
|
|
23
|
+
"queued",
|
|
24
|
+
"processing",
|
|
25
|
+
"sent",
|
|
26
|
+
"retrying",
|
|
27
|
+
"failed",
|
|
28
|
+
"suppressed",
|
|
29
|
+
"cancelled"
|
|
30
|
+
];
|
|
31
|
+
var NotificationDeliveryPurpose = Schema.Literals(NOTIFICATION_DELIVERY_PURPOSES).annotate({ identifier: "NotificationDeliveryPurpose" });
|
|
32
|
+
var NotificationDeliveryStatus = Schema.Literals(NOTIFICATION_DELIVERY_STATUSES).annotate({ identifier: "NotificationDeliveryStatus" });
|
|
33
|
+
var NotificationId = Schema.String.pipe(Schema.brand("NotificationId")).annotate({ identifier: "NotificationId" });
|
|
34
|
+
var NotificationSettingId = Schema.String.pipe(Schema.brand("NotificationSettingId")).annotate({ identifier: "NotificationSettingId" });
|
|
35
|
+
var NotificationDeliveryId = Schema.String.pipe(Schema.brand("NotificationDeliveryId")).annotate({ identifier: "NotificationDeliveryId" });
|
|
36
|
+
var InboxNotificationSchema = Schema.Struct({
|
|
37
|
+
id: NotificationId,
|
|
38
|
+
idempotencyKey: Schema.NonEmptyString,
|
|
39
|
+
recipientUserId: Schema.NonEmptyString,
|
|
40
|
+
organizationId: Schema.NullOr(Schema.NonEmptyString),
|
|
41
|
+
workspaceId: Schema.NullOr(Schema.NonEmptyString),
|
|
42
|
+
eventKey: Schema.NonEmptyString,
|
|
43
|
+
eventVersion: Schema.Int.pipe(Schema.check(Schema.isGreaterThan(0))),
|
|
44
|
+
locale: Schema.NonEmptyString,
|
|
45
|
+
title: Schema.NonEmptyString,
|
|
46
|
+
description: Schema.NullOr(Schema.String),
|
|
47
|
+
href: Schema.NullOr(Schema.String),
|
|
48
|
+
metadata: Schema.Json,
|
|
49
|
+
createdAt: Schema.Date,
|
|
50
|
+
readAt: Schema.NullOr(Schema.Date),
|
|
51
|
+
archivedAt: Schema.NullOr(Schema.Date)
|
|
52
|
+
}).annotate({ identifier: "InboxNotification" });
|
|
53
|
+
var NotificationSettingSchema = Schema.Struct({
|
|
54
|
+
id: NotificationSettingId,
|
|
55
|
+
recipientUserId: Schema.NonEmptyString,
|
|
56
|
+
organizationId: Schema.NullOr(Schema.NonEmptyString),
|
|
57
|
+
workspaceId: Schema.NullOr(Schema.NonEmptyString),
|
|
58
|
+
eventKey: Schema.NullOr(Schema.NonEmptyString),
|
|
59
|
+
channel: Schema.NonEmptyString,
|
|
60
|
+
enabled: Schema.Boolean,
|
|
61
|
+
createdAt: Schema.Date,
|
|
62
|
+
updatedAt: Schema.Date
|
|
63
|
+
}).annotate({ identifier: "NotificationSetting" });
|
|
64
|
+
var NotificationDeliverySchema = Schema.Struct({
|
|
65
|
+
id: NotificationDeliveryId,
|
|
66
|
+
notificationId: Schema.NullOr(NotificationId),
|
|
67
|
+
idempotencyKey: Schema.NonEmptyString,
|
|
68
|
+
recipientUserId: Schema.NullOr(Schema.NonEmptyString),
|
|
69
|
+
organizationId: Schema.NullOr(Schema.NonEmptyString),
|
|
70
|
+
workspaceId: Schema.NullOr(Schema.NonEmptyString),
|
|
71
|
+
eventKey: Schema.NonEmptyString,
|
|
72
|
+
eventVersion: Schema.Int.pipe(Schema.check(Schema.isGreaterThan(0))),
|
|
73
|
+
channel: Schema.NonEmptyString,
|
|
74
|
+
purpose: NotificationDeliveryPurpose,
|
|
75
|
+
template: Schema.NullOr(Schema.NonEmptyString),
|
|
76
|
+
recipientAddress: Schema.NonEmptyString,
|
|
77
|
+
recipientName: Schema.NullOr(Schema.NonEmptyString),
|
|
78
|
+
payloadVersion: Schema.Int.pipe(Schema.check(Schema.isGreaterThan(0))),
|
|
79
|
+
payload: Schema.Json,
|
|
80
|
+
status: NotificationDeliveryStatus,
|
|
81
|
+
attempts: Schema.Int.pipe(Schema.check(Schema.isGreaterThanOrEqualTo(0))),
|
|
82
|
+
maxAttempts: Schema.Int.pipe(Schema.check(Schema.isGreaterThan(0))),
|
|
83
|
+
provider: Schema.NullOr(Schema.NonEmptyString),
|
|
84
|
+
providerMessageId: Schema.NullOr(Schema.NonEmptyString),
|
|
85
|
+
errorMessage: Schema.NullOr(Schema.String),
|
|
86
|
+
scheduledFor: Schema.Date,
|
|
87
|
+
processingAt: Schema.NullOr(Schema.Date),
|
|
88
|
+
lastAttemptAt: Schema.NullOr(Schema.Date),
|
|
89
|
+
leaseExpiresAt: Schema.NullOr(Schema.Date),
|
|
90
|
+
claimedBy: Schema.NullOr(Schema.NonEmptyString),
|
|
91
|
+
sentAt: Schema.NullOr(Schema.Date),
|
|
92
|
+
failedAt: Schema.NullOr(Schema.Date),
|
|
93
|
+
suppressedAt: Schema.NullOr(Schema.Date),
|
|
94
|
+
cancelledAt: Schema.NullOr(Schema.Date),
|
|
95
|
+
createdAt: Schema.Date,
|
|
96
|
+
updatedAt: Schema.Date
|
|
97
|
+
}).annotate({ identifier: "NotificationDelivery" });
|
|
98
|
+
var EmailDeliveryPayloadV1 = Schema.Struct({
|
|
99
|
+
from: Schema.optional(Schema.NonEmptyString),
|
|
100
|
+
to: Schema.Union([
|
|
101
|
+
Schema.NonEmptyString,
|
|
102
|
+
Schema.NonEmptyArray(Schema.NonEmptyString)
|
|
103
|
+
]),
|
|
104
|
+
cc: Schema.optional(Schema.Array(Schema.NonEmptyString)),
|
|
105
|
+
bcc: Schema.optional(Schema.Array(Schema.NonEmptyString)),
|
|
106
|
+
replyTo: Schema.optional(Schema.Array(Schema.NonEmptyString)),
|
|
107
|
+
subject: Schema.NonEmptyString,
|
|
108
|
+
text: Schema.optional(Schema.NonEmptyString),
|
|
109
|
+
html: Schema.optional(Schema.NonEmptyString)
|
|
110
|
+
}).pipe(Schema.refine((payload) => payload.text !== undefined || payload.html !== undefined, { message: "Email delivery payload requires text or html" })).annotate({ identifier: "EmailDeliveryPayloadV1" });
|
|
111
|
+
var PersistedNotificationDeliveryPayload = Schema.Union([
|
|
112
|
+
Schema.Struct({
|
|
113
|
+
channel: Schema.Literal("email"),
|
|
114
|
+
payloadVersion: Schema.Literal(1),
|
|
115
|
+
payload: EmailDeliveryPayloadV1
|
|
116
|
+
})
|
|
117
|
+
]).annotate({ identifier: "PersistedNotificationDeliveryPayload" });
|
|
118
|
+
var decodeNotificationDeliveryPayload = Schema.decodeUnknownEffect(PersistedNotificationDeliveryPayload);
|
|
119
|
+
|
|
120
|
+
// ../../src/services/notification/persistence/drizzle.ts
|
|
121
|
+
var timestampWithTimezone = (name) => timestamp(name, { withTimezone: true });
|
|
122
|
+
var nonEmpty = (column) => sql`length(btrim(${column})) > 0`;
|
|
123
|
+
var notifications = pgTable("notifications", {
|
|
124
|
+
id: uuid("id").defaultRandom().primaryKey(),
|
|
125
|
+
idempotencyKey: text("idempotency_key").notNull(),
|
|
126
|
+
recipientUserId: text("recipient_user_id").notNull(),
|
|
127
|
+
organizationId: text("organization_id"),
|
|
128
|
+
workspaceId: text("workspace_id"),
|
|
129
|
+
eventKey: text("event_key").notNull(),
|
|
130
|
+
eventVersion: integer("event_version").default(1).notNull(),
|
|
131
|
+
locale: text("locale").notNull(),
|
|
132
|
+
title: text("title").notNull(),
|
|
133
|
+
description: text("description"),
|
|
134
|
+
href: text("href"),
|
|
135
|
+
metadata: jsonb("metadata").$type().default({}).notNull(),
|
|
136
|
+
createdAt: timestampWithTimezone("created_at").defaultNow().notNull(),
|
|
137
|
+
readAt: timestampWithTimezone("read_at"),
|
|
138
|
+
archivedAt: timestampWithTimezone("archived_at")
|
|
139
|
+
}, (table) => [
|
|
140
|
+
uniqueIndex("notifications_idempotency_key_uidx").on(table.idempotencyKey),
|
|
141
|
+
index("notifications_recipient_inbox_created_idx").on(table.recipientUserId, table.organizationId, table.workspaceId, table.archivedAt, table.createdAt),
|
|
142
|
+
index("notifications_recipient_unread_idx").on(table.recipientUserId, table.organizationId, table.workspaceId, table.readAt),
|
|
143
|
+
check("notifications_non_empty_fields_check", sql`${nonEmpty(table.idempotencyKey)} and ${nonEmpty(table.recipientUserId)} and ${nonEmpty(table.eventKey)} and ${nonEmpty(table.locale)} and ${nonEmpty(table.title)} and (${table.organizationId} is null or ${nonEmpty(table.organizationId)}) and (${table.workspaceId} is null or ${nonEmpty(table.workspaceId)})`),
|
|
144
|
+
check("notifications_event_version_check", sql`${table.eventVersion} > 0`)
|
|
145
|
+
]);
|
|
146
|
+
var notificationSettings = pgTable("notification_settings", {
|
|
147
|
+
id: uuid("id").defaultRandom().primaryKey(),
|
|
148
|
+
recipientUserId: text("recipient_user_id").notNull(),
|
|
149
|
+
organizationId: text("organization_id"),
|
|
150
|
+
workspaceId: text("workspace_id"),
|
|
151
|
+
eventKey: text("event_key"),
|
|
152
|
+
channel: text("channel").notNull(),
|
|
153
|
+
enabled: boolean("enabled").default(true).notNull(),
|
|
154
|
+
createdAt: timestampWithTimezone("created_at").defaultNow().notNull(),
|
|
155
|
+
updatedAt: timestampWithTimezone("updated_at").defaultNow().notNull()
|
|
156
|
+
}, (table) => [
|
|
157
|
+
uniqueIndex("notification_settings_scope_channel_uidx").on(table.recipientUserId, sql`coalesce(${table.organizationId}, '')`, sql`coalesce(${table.workspaceId}, '')`, sql`coalesce(${table.eventKey}, '')`, table.channel),
|
|
158
|
+
index("notification_settings_recipient_channel_idx").on(table.recipientUserId, table.channel),
|
|
159
|
+
check("notification_settings_non_empty_fields_check", sql`${nonEmpty(table.recipientUserId)} and ${nonEmpty(table.channel)} and (${table.organizationId} is null or ${nonEmpty(table.organizationId)}) and (${table.workspaceId} is null or ${nonEmpty(table.workspaceId)}) and (${table.eventKey} is null or ${nonEmpty(table.eventKey)})`)
|
|
160
|
+
]);
|
|
161
|
+
var notificationDeliveries = pgTable("notification_deliveries", {
|
|
162
|
+
id: uuid("id").defaultRandom().primaryKey(),
|
|
163
|
+
notificationId: uuid("notification_id").references(() => notifications.id, {
|
|
164
|
+
onDelete: "set null"
|
|
165
|
+
}),
|
|
166
|
+
idempotencyKey: text("idempotency_key").notNull(),
|
|
167
|
+
recipientUserId: text("recipient_user_id"),
|
|
168
|
+
organizationId: text("organization_id"),
|
|
169
|
+
workspaceId: text("workspace_id"),
|
|
170
|
+
eventKey: text("event_key").notNull(),
|
|
171
|
+
eventVersion: integer("event_version").default(1).notNull(),
|
|
172
|
+
channel: text("channel").notNull(),
|
|
173
|
+
purpose: text("purpose").notNull(),
|
|
174
|
+
template: text("template"),
|
|
175
|
+
recipientAddress: text("recipient_address").notNull(),
|
|
176
|
+
recipientName: text("recipient_name"),
|
|
177
|
+
payloadVersion: integer("payload_version").default(1).notNull(),
|
|
178
|
+
payload: jsonb("payload").$type().notNull(),
|
|
179
|
+
status: text("status").default("queued").notNull(),
|
|
180
|
+
attempts: integer("attempts").default(0).notNull(),
|
|
181
|
+
maxAttempts: integer("max_attempts").default(5).notNull(),
|
|
182
|
+
provider: text("provider"),
|
|
183
|
+
providerMessageId: text("provider_message_id"),
|
|
184
|
+
errorMessage: text("error_message"),
|
|
185
|
+
scheduledFor: timestampWithTimezone("scheduled_for").defaultNow().notNull(),
|
|
186
|
+
processingAt: timestampWithTimezone("processing_at"),
|
|
187
|
+
lastAttemptAt: timestampWithTimezone("last_attempt_at"),
|
|
188
|
+
leaseExpiresAt: timestampWithTimezone("lease_expires_at"),
|
|
189
|
+
claimedBy: text("claimed_by"),
|
|
190
|
+
sentAt: timestampWithTimezone("sent_at"),
|
|
191
|
+
failedAt: timestampWithTimezone("failed_at"),
|
|
192
|
+
suppressedAt: timestampWithTimezone("suppressed_at"),
|
|
193
|
+
cancelledAt: timestampWithTimezone("cancelled_at"),
|
|
194
|
+
createdAt: timestampWithTimezone("created_at").defaultNow().notNull(),
|
|
195
|
+
updatedAt: timestampWithTimezone("updated_at").defaultNow().notNull()
|
|
196
|
+
}, (table) => [
|
|
197
|
+
uniqueIndex("notification_deliveries_idempotency_key_uidx").on(table.idempotencyKey),
|
|
198
|
+
index("notification_deliveries_claim_idx").on(table.channel, table.status, table.scheduledFor),
|
|
199
|
+
index("notification_deliveries_notification_id_idx").on(table.notificationId),
|
|
200
|
+
index("notification_deliveries_recipient_address_idx").on(table.recipientAddress),
|
|
201
|
+
index("notification_deliveries_scope_created_idx").on(table.organizationId, table.workspaceId, table.createdAt),
|
|
202
|
+
index("notification_deliveries_template_idx").on(table.template),
|
|
203
|
+
check("notification_deliveries_non_empty_fields_check", sql`${nonEmpty(table.idempotencyKey)} and ${nonEmpty(table.eventKey)} and ${nonEmpty(table.channel)} and ${nonEmpty(table.recipientAddress)} and (${table.recipientUserId} is null or ${nonEmpty(table.recipientUserId)}) and (${table.organizationId} is null or ${nonEmpty(table.organizationId)}) and (${table.workspaceId} is null or ${nonEmpty(table.workspaceId)}) and (${table.template} is null or ${nonEmpty(table.template)}) and (${table.recipientName} is null or ${nonEmpty(table.recipientName)}) and (${table.provider} is null or ${nonEmpty(table.provider)}) and (${table.providerMessageId} is null or ${nonEmpty(table.providerMessageId)}) and (${table.claimedBy} is null or ${nonEmpty(table.claimedBy)})`),
|
|
204
|
+
check("notification_deliveries_purpose_check", sql`${table.purpose} in (${sql.join(NOTIFICATION_DELIVERY_PURPOSES.map((value) => sql`${value}`), sql`, `)})`),
|
|
205
|
+
check("notification_deliveries_status_check", sql`${table.status} in (${sql.join(NOTIFICATION_DELIVERY_STATUSES.map((value) => sql`${value}`), sql`, `)})`),
|
|
206
|
+
check("notification_deliveries_versions_check", sql`${table.eventVersion} > 0 and ${table.payloadVersion} > 0`),
|
|
207
|
+
check("notification_deliveries_attempts_check", sql`${table.attempts} >= 0 and ${table.maxAttempts} > 0 and ${table.attempts} <= ${table.maxAttempts}`),
|
|
208
|
+
check("notification_deliveries_lease_check", sql`(${table.claimedBy} is null and ${table.leaseExpiresAt} is null) or (${table.claimedBy} is not null and ${table.leaseExpiresAt} is not null)`)
|
|
209
|
+
]);
|
|
210
|
+
export {
|
|
211
|
+
notifications,
|
|
212
|
+
notificationSettings,
|
|
213
|
+
notificationDeliveries
|
|
214
|
+
};
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
// ../../src/services/notification/persistence/drizzle.ts
|
|
2
|
+
import { sql } from "drizzle-orm";
|
|
3
|
+
import {
|
|
4
|
+
boolean,
|
|
5
|
+
check,
|
|
6
|
+
index,
|
|
7
|
+
integer,
|
|
8
|
+
jsonb,
|
|
9
|
+
pgTable,
|
|
10
|
+
text,
|
|
11
|
+
timestamp,
|
|
12
|
+
uniqueIndex,
|
|
13
|
+
uuid
|
|
14
|
+
} from "drizzle-orm/pg-core";
|
|
15
|
+
|
|
16
|
+
// ../../src/services/notification/persistence/schema.ts
|
|
17
|
+
import { Schema } from "effect";
|
|
18
|
+
var NOTIFICATION_DELIVERY_PURPOSES = [
|
|
19
|
+
"transactional",
|
|
20
|
+
"notification"
|
|
21
|
+
];
|
|
22
|
+
var NOTIFICATION_DELIVERY_STATUSES = [
|
|
23
|
+
"queued",
|
|
24
|
+
"processing",
|
|
25
|
+
"sent",
|
|
26
|
+
"retrying",
|
|
27
|
+
"failed",
|
|
28
|
+
"suppressed",
|
|
29
|
+
"cancelled"
|
|
30
|
+
];
|
|
31
|
+
var NotificationDeliveryPurpose = Schema.Literals(NOTIFICATION_DELIVERY_PURPOSES).annotate({ identifier: "NotificationDeliveryPurpose" });
|
|
32
|
+
var NotificationDeliveryStatus = Schema.Literals(NOTIFICATION_DELIVERY_STATUSES).annotate({ identifier: "NotificationDeliveryStatus" });
|
|
33
|
+
var NotificationId = Schema.String.pipe(Schema.brand("NotificationId")).annotate({ identifier: "NotificationId" });
|
|
34
|
+
var NotificationSettingId = Schema.String.pipe(Schema.brand("NotificationSettingId")).annotate({ identifier: "NotificationSettingId" });
|
|
35
|
+
var NotificationDeliveryId = Schema.String.pipe(Schema.brand("NotificationDeliveryId")).annotate({ identifier: "NotificationDeliveryId" });
|
|
36
|
+
var InboxNotificationSchema = Schema.Struct({
|
|
37
|
+
id: NotificationId,
|
|
38
|
+
idempotencyKey: Schema.NonEmptyString,
|
|
39
|
+
recipientUserId: Schema.NonEmptyString,
|
|
40
|
+
organizationId: Schema.NullOr(Schema.NonEmptyString),
|
|
41
|
+
workspaceId: Schema.NullOr(Schema.NonEmptyString),
|
|
42
|
+
eventKey: Schema.NonEmptyString,
|
|
43
|
+
eventVersion: Schema.Int.pipe(Schema.check(Schema.isGreaterThan(0))),
|
|
44
|
+
locale: Schema.NonEmptyString,
|
|
45
|
+
title: Schema.NonEmptyString,
|
|
46
|
+
description: Schema.NullOr(Schema.String),
|
|
47
|
+
href: Schema.NullOr(Schema.String),
|
|
48
|
+
metadata: Schema.Json,
|
|
49
|
+
createdAt: Schema.Date,
|
|
50
|
+
readAt: Schema.NullOr(Schema.Date),
|
|
51
|
+
archivedAt: Schema.NullOr(Schema.Date)
|
|
52
|
+
}).annotate({ identifier: "InboxNotification" });
|
|
53
|
+
var NotificationSettingSchema = Schema.Struct({
|
|
54
|
+
id: NotificationSettingId,
|
|
55
|
+
recipientUserId: Schema.NonEmptyString,
|
|
56
|
+
organizationId: Schema.NullOr(Schema.NonEmptyString),
|
|
57
|
+
workspaceId: Schema.NullOr(Schema.NonEmptyString),
|
|
58
|
+
eventKey: Schema.NullOr(Schema.NonEmptyString),
|
|
59
|
+
channel: Schema.NonEmptyString,
|
|
60
|
+
enabled: Schema.Boolean,
|
|
61
|
+
createdAt: Schema.Date,
|
|
62
|
+
updatedAt: Schema.Date
|
|
63
|
+
}).annotate({ identifier: "NotificationSetting" });
|
|
64
|
+
var NotificationDeliverySchema = Schema.Struct({
|
|
65
|
+
id: NotificationDeliveryId,
|
|
66
|
+
notificationId: Schema.NullOr(NotificationId),
|
|
67
|
+
idempotencyKey: Schema.NonEmptyString,
|
|
68
|
+
recipientUserId: Schema.NullOr(Schema.NonEmptyString),
|
|
69
|
+
organizationId: Schema.NullOr(Schema.NonEmptyString),
|
|
70
|
+
workspaceId: Schema.NullOr(Schema.NonEmptyString),
|
|
71
|
+
eventKey: Schema.NonEmptyString,
|
|
72
|
+
eventVersion: Schema.Int.pipe(Schema.check(Schema.isGreaterThan(0))),
|
|
73
|
+
channel: Schema.NonEmptyString,
|
|
74
|
+
purpose: NotificationDeliveryPurpose,
|
|
75
|
+
template: Schema.NullOr(Schema.NonEmptyString),
|
|
76
|
+
recipientAddress: Schema.NonEmptyString,
|
|
77
|
+
recipientName: Schema.NullOr(Schema.NonEmptyString),
|
|
78
|
+
payloadVersion: Schema.Int.pipe(Schema.check(Schema.isGreaterThan(0))),
|
|
79
|
+
payload: Schema.Json,
|
|
80
|
+
status: NotificationDeliveryStatus,
|
|
81
|
+
attempts: Schema.Int.pipe(Schema.check(Schema.isGreaterThanOrEqualTo(0))),
|
|
82
|
+
maxAttempts: Schema.Int.pipe(Schema.check(Schema.isGreaterThan(0))),
|
|
83
|
+
provider: Schema.NullOr(Schema.NonEmptyString),
|
|
84
|
+
providerMessageId: Schema.NullOr(Schema.NonEmptyString),
|
|
85
|
+
errorMessage: Schema.NullOr(Schema.String),
|
|
86
|
+
scheduledFor: Schema.Date,
|
|
87
|
+
processingAt: Schema.NullOr(Schema.Date),
|
|
88
|
+
lastAttemptAt: Schema.NullOr(Schema.Date),
|
|
89
|
+
leaseExpiresAt: Schema.NullOr(Schema.Date),
|
|
90
|
+
claimedBy: Schema.NullOr(Schema.NonEmptyString),
|
|
91
|
+
sentAt: Schema.NullOr(Schema.Date),
|
|
92
|
+
failedAt: Schema.NullOr(Schema.Date),
|
|
93
|
+
suppressedAt: Schema.NullOr(Schema.Date),
|
|
94
|
+
cancelledAt: Schema.NullOr(Schema.Date),
|
|
95
|
+
createdAt: Schema.Date,
|
|
96
|
+
updatedAt: Schema.Date
|
|
97
|
+
}).annotate({ identifier: "NotificationDelivery" });
|
|
98
|
+
var EmailDeliveryPayloadV1 = Schema.Struct({
|
|
99
|
+
from: Schema.optional(Schema.NonEmptyString),
|
|
100
|
+
to: Schema.Union([
|
|
101
|
+
Schema.NonEmptyString,
|
|
102
|
+
Schema.NonEmptyArray(Schema.NonEmptyString)
|
|
103
|
+
]),
|
|
104
|
+
cc: Schema.optional(Schema.Array(Schema.NonEmptyString)),
|
|
105
|
+
bcc: Schema.optional(Schema.Array(Schema.NonEmptyString)),
|
|
106
|
+
replyTo: Schema.optional(Schema.Array(Schema.NonEmptyString)),
|
|
107
|
+
subject: Schema.NonEmptyString,
|
|
108
|
+
text: Schema.optional(Schema.NonEmptyString),
|
|
109
|
+
html: Schema.optional(Schema.NonEmptyString)
|
|
110
|
+
}).pipe(Schema.refine((payload) => payload.text !== undefined || payload.html !== undefined, { message: "Email delivery payload requires text or html" })).annotate({ identifier: "EmailDeliveryPayloadV1" });
|
|
111
|
+
var PersistedNotificationDeliveryPayload = Schema.Union([
|
|
112
|
+
Schema.Struct({
|
|
113
|
+
channel: Schema.Literal("email"),
|
|
114
|
+
payloadVersion: Schema.Literal(1),
|
|
115
|
+
payload: EmailDeliveryPayloadV1
|
|
116
|
+
})
|
|
117
|
+
]).annotate({ identifier: "PersistedNotificationDeliveryPayload" });
|
|
118
|
+
var decodeNotificationDeliveryPayload = Schema.decodeUnknownEffect(PersistedNotificationDeliveryPayload);
|
|
119
|
+
|
|
120
|
+
// ../../src/services/notification/persistence/drizzle.ts
|
|
121
|
+
var timestampWithTimezone = (name) => timestamp(name, { withTimezone: true });
|
|
122
|
+
var nonEmpty = (column) => sql`length(btrim(${column})) > 0`;
|
|
123
|
+
var notifications = pgTable("notifications", {
|
|
124
|
+
id: uuid("id").defaultRandom().primaryKey(),
|
|
125
|
+
idempotencyKey: text("idempotency_key").notNull(),
|
|
126
|
+
recipientUserId: text("recipient_user_id").notNull(),
|
|
127
|
+
organizationId: text("organization_id"),
|
|
128
|
+
workspaceId: text("workspace_id"),
|
|
129
|
+
eventKey: text("event_key").notNull(),
|
|
130
|
+
eventVersion: integer("event_version").default(1).notNull(),
|
|
131
|
+
locale: text("locale").notNull(),
|
|
132
|
+
title: text("title").notNull(),
|
|
133
|
+
description: text("description"),
|
|
134
|
+
href: text("href"),
|
|
135
|
+
metadata: jsonb("metadata").$type().default({}).notNull(),
|
|
136
|
+
createdAt: timestampWithTimezone("created_at").defaultNow().notNull(),
|
|
137
|
+
readAt: timestampWithTimezone("read_at"),
|
|
138
|
+
archivedAt: timestampWithTimezone("archived_at")
|
|
139
|
+
}, (table) => [
|
|
140
|
+
uniqueIndex("notifications_idempotency_key_uidx").on(table.idempotencyKey),
|
|
141
|
+
index("notifications_recipient_inbox_created_idx").on(table.recipientUserId, table.organizationId, table.workspaceId, table.archivedAt, table.createdAt),
|
|
142
|
+
index("notifications_recipient_unread_idx").on(table.recipientUserId, table.organizationId, table.workspaceId, table.readAt),
|
|
143
|
+
check("notifications_non_empty_fields_check", sql`${nonEmpty(table.idempotencyKey)} and ${nonEmpty(table.recipientUserId)} and ${nonEmpty(table.eventKey)} and ${nonEmpty(table.locale)} and ${nonEmpty(table.title)} and (${table.organizationId} is null or ${nonEmpty(table.organizationId)}) and (${table.workspaceId} is null or ${nonEmpty(table.workspaceId)})`),
|
|
144
|
+
check("notifications_event_version_check", sql`${table.eventVersion} > 0`)
|
|
145
|
+
]);
|
|
146
|
+
var notificationSettings = pgTable("notification_settings", {
|
|
147
|
+
id: uuid("id").defaultRandom().primaryKey(),
|
|
148
|
+
recipientUserId: text("recipient_user_id").notNull(),
|
|
149
|
+
organizationId: text("organization_id"),
|
|
150
|
+
workspaceId: text("workspace_id"),
|
|
151
|
+
eventKey: text("event_key"),
|
|
152
|
+
channel: text("channel").notNull(),
|
|
153
|
+
enabled: boolean("enabled").default(true).notNull(),
|
|
154
|
+
createdAt: timestampWithTimezone("created_at").defaultNow().notNull(),
|
|
155
|
+
updatedAt: timestampWithTimezone("updated_at").defaultNow().notNull()
|
|
156
|
+
}, (table) => [
|
|
157
|
+
uniqueIndex("notification_settings_scope_channel_uidx").on(table.recipientUserId, sql`coalesce(${table.organizationId}, '')`, sql`coalesce(${table.workspaceId}, '')`, sql`coalesce(${table.eventKey}, '')`, table.channel),
|
|
158
|
+
index("notification_settings_recipient_channel_idx").on(table.recipientUserId, table.channel),
|
|
159
|
+
check("notification_settings_non_empty_fields_check", sql`${nonEmpty(table.recipientUserId)} and ${nonEmpty(table.channel)} and (${table.organizationId} is null or ${nonEmpty(table.organizationId)}) and (${table.workspaceId} is null or ${nonEmpty(table.workspaceId)}) and (${table.eventKey} is null or ${nonEmpty(table.eventKey)})`)
|
|
160
|
+
]);
|
|
161
|
+
var notificationDeliveries = pgTable("notification_deliveries", {
|
|
162
|
+
id: uuid("id").defaultRandom().primaryKey(),
|
|
163
|
+
notificationId: uuid("notification_id").references(() => notifications.id, {
|
|
164
|
+
onDelete: "set null"
|
|
165
|
+
}),
|
|
166
|
+
idempotencyKey: text("idempotency_key").notNull(),
|
|
167
|
+
recipientUserId: text("recipient_user_id"),
|
|
168
|
+
organizationId: text("organization_id"),
|
|
169
|
+
workspaceId: text("workspace_id"),
|
|
170
|
+
eventKey: text("event_key").notNull(),
|
|
171
|
+
eventVersion: integer("event_version").default(1).notNull(),
|
|
172
|
+
channel: text("channel").notNull(),
|
|
173
|
+
purpose: text("purpose").notNull(),
|
|
174
|
+
template: text("template"),
|
|
175
|
+
recipientAddress: text("recipient_address").notNull(),
|
|
176
|
+
recipientName: text("recipient_name"),
|
|
177
|
+
payloadVersion: integer("payload_version").default(1).notNull(),
|
|
178
|
+
payload: jsonb("payload").$type().notNull(),
|
|
179
|
+
status: text("status").default("queued").notNull(),
|
|
180
|
+
attempts: integer("attempts").default(0).notNull(),
|
|
181
|
+
maxAttempts: integer("max_attempts").default(5).notNull(),
|
|
182
|
+
provider: text("provider"),
|
|
183
|
+
providerMessageId: text("provider_message_id"),
|
|
184
|
+
errorMessage: text("error_message"),
|
|
185
|
+
scheduledFor: timestampWithTimezone("scheduled_for").defaultNow().notNull(),
|
|
186
|
+
processingAt: timestampWithTimezone("processing_at"),
|
|
187
|
+
lastAttemptAt: timestampWithTimezone("last_attempt_at"),
|
|
188
|
+
leaseExpiresAt: timestampWithTimezone("lease_expires_at"),
|
|
189
|
+
claimedBy: text("claimed_by"),
|
|
190
|
+
sentAt: timestampWithTimezone("sent_at"),
|
|
191
|
+
failedAt: timestampWithTimezone("failed_at"),
|
|
192
|
+
suppressedAt: timestampWithTimezone("suppressed_at"),
|
|
193
|
+
cancelledAt: timestampWithTimezone("cancelled_at"),
|
|
194
|
+
createdAt: timestampWithTimezone("created_at").defaultNow().notNull(),
|
|
195
|
+
updatedAt: timestampWithTimezone("updated_at").defaultNow().notNull()
|
|
196
|
+
}, (table) => [
|
|
197
|
+
uniqueIndex("notification_deliveries_idempotency_key_uidx").on(table.idempotencyKey),
|
|
198
|
+
index("notification_deliveries_claim_idx").on(table.channel, table.status, table.scheduledFor),
|
|
199
|
+
index("notification_deliveries_notification_id_idx").on(table.notificationId),
|
|
200
|
+
index("notification_deliveries_recipient_address_idx").on(table.recipientAddress),
|
|
201
|
+
index("notification_deliveries_scope_created_idx").on(table.organizationId, table.workspaceId, table.createdAt),
|
|
202
|
+
index("notification_deliveries_template_idx").on(table.template),
|
|
203
|
+
check("notification_deliveries_non_empty_fields_check", sql`${nonEmpty(table.idempotencyKey)} and ${nonEmpty(table.eventKey)} and ${nonEmpty(table.channel)} and ${nonEmpty(table.recipientAddress)} and (${table.recipientUserId} is null or ${nonEmpty(table.recipientUserId)}) and (${table.organizationId} is null or ${nonEmpty(table.organizationId)}) and (${table.workspaceId} is null or ${nonEmpty(table.workspaceId)}) and (${table.template} is null or ${nonEmpty(table.template)}) and (${table.recipientName} is null or ${nonEmpty(table.recipientName)}) and (${table.provider} is null or ${nonEmpty(table.provider)}) and (${table.providerMessageId} is null or ${nonEmpty(table.providerMessageId)}) and (${table.claimedBy} is null or ${nonEmpty(table.claimedBy)})`),
|
|
204
|
+
check("notification_deliveries_purpose_check", sql`${table.purpose} in (${sql.join(NOTIFICATION_DELIVERY_PURPOSES.map((value) => sql`${value}`), sql`, `)})`),
|
|
205
|
+
check("notification_deliveries_status_check", sql`${table.status} in (${sql.join(NOTIFICATION_DELIVERY_STATUSES.map((value) => sql`${value}`), sql`, `)})`),
|
|
206
|
+
check("notification_deliveries_versions_check", sql`${table.eventVersion} > 0 and ${table.payloadVersion} > 0`),
|
|
207
|
+
check("notification_deliveries_attempts_check", sql`${table.attempts} >= 0 and ${table.maxAttempts} > 0 and ${table.attempts} <= ${table.maxAttempts}`),
|
|
208
|
+
check("notification_deliveries_lease_check", sql`(${table.claimedBy} is null and ${table.leaseExpiresAt} is null) or (${table.claimedBy} is not null and ${table.leaseExpiresAt} is not null)`)
|
|
209
|
+
]);
|
|
210
|
+
export {
|
|
211
|
+
notifications,
|
|
212
|
+
notificationSettings,
|
|
213
|
+
notificationDeliveries,
|
|
214
|
+
decodeNotificationDeliveryPayload,
|
|
215
|
+
PersistedNotificationDeliveryPayload,
|
|
216
|
+
NotificationSettingSchema,
|
|
217
|
+
NotificationSettingId,
|
|
218
|
+
NotificationId,
|
|
219
|
+
NotificationDeliveryStatus,
|
|
220
|
+
NotificationDeliverySchema,
|
|
221
|
+
NotificationDeliveryPurpose,
|
|
222
|
+
NotificationDeliveryId,
|
|
223
|
+
NOTIFICATION_DELIVERY_STATUSES,
|
|
224
|
+
NOTIFICATION_DELIVERY_PURPOSES,
|
|
225
|
+
InboxNotificationSchema,
|
|
226
|
+
EmailDeliveryPayloadV1
|
|
227
|
+
};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// ../../src/services/notification/persistence/schema.ts
|
|
2
|
+
import { Schema } from "effect";
|
|
3
|
+
var NOTIFICATION_DELIVERY_PURPOSES = [
|
|
4
|
+
"transactional",
|
|
5
|
+
"notification"
|
|
6
|
+
];
|
|
7
|
+
var NOTIFICATION_DELIVERY_STATUSES = [
|
|
8
|
+
"queued",
|
|
9
|
+
"processing",
|
|
10
|
+
"sent",
|
|
11
|
+
"retrying",
|
|
12
|
+
"failed",
|
|
13
|
+
"suppressed",
|
|
14
|
+
"cancelled"
|
|
15
|
+
];
|
|
16
|
+
var NotificationDeliveryPurpose = Schema.Literals(NOTIFICATION_DELIVERY_PURPOSES).annotate({ identifier: "NotificationDeliveryPurpose" });
|
|
17
|
+
var NotificationDeliveryStatus = Schema.Literals(NOTIFICATION_DELIVERY_STATUSES).annotate({ identifier: "NotificationDeliveryStatus" });
|
|
18
|
+
var NotificationId = Schema.String.pipe(Schema.brand("NotificationId")).annotate({ identifier: "NotificationId" });
|
|
19
|
+
var NotificationSettingId = Schema.String.pipe(Schema.brand("NotificationSettingId")).annotate({ identifier: "NotificationSettingId" });
|
|
20
|
+
var NotificationDeliveryId = Schema.String.pipe(Schema.brand("NotificationDeliveryId")).annotate({ identifier: "NotificationDeliveryId" });
|
|
21
|
+
var InboxNotificationSchema = Schema.Struct({
|
|
22
|
+
id: NotificationId,
|
|
23
|
+
idempotencyKey: Schema.NonEmptyString,
|
|
24
|
+
recipientUserId: Schema.NonEmptyString,
|
|
25
|
+
organizationId: Schema.NullOr(Schema.NonEmptyString),
|
|
26
|
+
workspaceId: Schema.NullOr(Schema.NonEmptyString),
|
|
27
|
+
eventKey: Schema.NonEmptyString,
|
|
28
|
+
eventVersion: Schema.Int.pipe(Schema.check(Schema.isGreaterThan(0))),
|
|
29
|
+
locale: Schema.NonEmptyString,
|
|
30
|
+
title: Schema.NonEmptyString,
|
|
31
|
+
description: Schema.NullOr(Schema.String),
|
|
32
|
+
href: Schema.NullOr(Schema.String),
|
|
33
|
+
metadata: Schema.Json,
|
|
34
|
+
createdAt: Schema.Date,
|
|
35
|
+
readAt: Schema.NullOr(Schema.Date),
|
|
36
|
+
archivedAt: Schema.NullOr(Schema.Date)
|
|
37
|
+
}).annotate({ identifier: "InboxNotification" });
|
|
38
|
+
var NotificationSettingSchema = Schema.Struct({
|
|
39
|
+
id: NotificationSettingId,
|
|
40
|
+
recipientUserId: Schema.NonEmptyString,
|
|
41
|
+
organizationId: Schema.NullOr(Schema.NonEmptyString),
|
|
42
|
+
workspaceId: Schema.NullOr(Schema.NonEmptyString),
|
|
43
|
+
eventKey: Schema.NullOr(Schema.NonEmptyString),
|
|
44
|
+
channel: Schema.NonEmptyString,
|
|
45
|
+
enabled: Schema.Boolean,
|
|
46
|
+
createdAt: Schema.Date,
|
|
47
|
+
updatedAt: Schema.Date
|
|
48
|
+
}).annotate({ identifier: "NotificationSetting" });
|
|
49
|
+
var NotificationDeliverySchema = Schema.Struct({
|
|
50
|
+
id: NotificationDeliveryId,
|
|
51
|
+
notificationId: Schema.NullOr(NotificationId),
|
|
52
|
+
idempotencyKey: Schema.NonEmptyString,
|
|
53
|
+
recipientUserId: Schema.NullOr(Schema.NonEmptyString),
|
|
54
|
+
organizationId: Schema.NullOr(Schema.NonEmptyString),
|
|
55
|
+
workspaceId: Schema.NullOr(Schema.NonEmptyString),
|
|
56
|
+
eventKey: Schema.NonEmptyString,
|
|
57
|
+
eventVersion: Schema.Int.pipe(Schema.check(Schema.isGreaterThan(0))),
|
|
58
|
+
channel: Schema.NonEmptyString,
|
|
59
|
+
purpose: NotificationDeliveryPurpose,
|
|
60
|
+
template: Schema.NullOr(Schema.NonEmptyString),
|
|
61
|
+
recipientAddress: Schema.NonEmptyString,
|
|
62
|
+
recipientName: Schema.NullOr(Schema.NonEmptyString),
|
|
63
|
+
payloadVersion: Schema.Int.pipe(Schema.check(Schema.isGreaterThan(0))),
|
|
64
|
+
payload: Schema.Json,
|
|
65
|
+
status: NotificationDeliveryStatus,
|
|
66
|
+
attempts: Schema.Int.pipe(Schema.check(Schema.isGreaterThanOrEqualTo(0))),
|
|
67
|
+
maxAttempts: Schema.Int.pipe(Schema.check(Schema.isGreaterThan(0))),
|
|
68
|
+
provider: Schema.NullOr(Schema.NonEmptyString),
|
|
69
|
+
providerMessageId: Schema.NullOr(Schema.NonEmptyString),
|
|
70
|
+
errorMessage: Schema.NullOr(Schema.String),
|
|
71
|
+
scheduledFor: Schema.Date,
|
|
72
|
+
processingAt: Schema.NullOr(Schema.Date),
|
|
73
|
+
lastAttemptAt: Schema.NullOr(Schema.Date),
|
|
74
|
+
leaseExpiresAt: Schema.NullOr(Schema.Date),
|
|
75
|
+
claimedBy: Schema.NullOr(Schema.NonEmptyString),
|
|
76
|
+
sentAt: Schema.NullOr(Schema.Date),
|
|
77
|
+
failedAt: Schema.NullOr(Schema.Date),
|
|
78
|
+
suppressedAt: Schema.NullOr(Schema.Date),
|
|
79
|
+
cancelledAt: Schema.NullOr(Schema.Date),
|
|
80
|
+
createdAt: Schema.Date,
|
|
81
|
+
updatedAt: Schema.Date
|
|
82
|
+
}).annotate({ identifier: "NotificationDelivery" });
|
|
83
|
+
var EmailDeliveryPayloadV1 = Schema.Struct({
|
|
84
|
+
from: Schema.optional(Schema.NonEmptyString),
|
|
85
|
+
to: Schema.Union([
|
|
86
|
+
Schema.NonEmptyString,
|
|
87
|
+
Schema.NonEmptyArray(Schema.NonEmptyString)
|
|
88
|
+
]),
|
|
89
|
+
cc: Schema.optional(Schema.Array(Schema.NonEmptyString)),
|
|
90
|
+
bcc: Schema.optional(Schema.Array(Schema.NonEmptyString)),
|
|
91
|
+
replyTo: Schema.optional(Schema.Array(Schema.NonEmptyString)),
|
|
92
|
+
subject: Schema.NonEmptyString,
|
|
93
|
+
text: Schema.optional(Schema.NonEmptyString),
|
|
94
|
+
html: Schema.optional(Schema.NonEmptyString)
|
|
95
|
+
}).pipe(Schema.refine((payload) => payload.text !== undefined || payload.html !== undefined, { message: "Email delivery payload requires text or html" })).annotate({ identifier: "EmailDeliveryPayloadV1" });
|
|
96
|
+
var PersistedNotificationDeliveryPayload = Schema.Union([
|
|
97
|
+
Schema.Struct({
|
|
98
|
+
channel: Schema.Literal("email"),
|
|
99
|
+
payloadVersion: Schema.Literal(1),
|
|
100
|
+
payload: EmailDeliveryPayloadV1
|
|
101
|
+
})
|
|
102
|
+
]).annotate({ identifier: "PersistedNotificationDeliveryPayload" });
|
|
103
|
+
var decodeNotificationDeliveryPayload = Schema.decodeUnknownEffect(PersistedNotificationDeliveryPayload);
|
|
104
|
+
export {
|
|
105
|
+
decodeNotificationDeliveryPayload,
|
|
106
|
+
PersistedNotificationDeliveryPayload,
|
|
107
|
+
NotificationSettingSchema,
|
|
108
|
+
NotificationSettingId,
|
|
109
|
+
NotificationId,
|
|
110
|
+
NotificationDeliveryStatus,
|
|
111
|
+
NotificationDeliverySchema,
|
|
112
|
+
NotificationDeliveryPurpose,
|
|
113
|
+
NotificationDeliveryId,
|
|
114
|
+
NOTIFICATION_DELIVERY_STATUSES,
|
|
115
|
+
NOTIFICATION_DELIVERY_PURPOSES,
|
|
116
|
+
InboxNotificationSchema,
|
|
117
|
+
EmailDeliveryPayloadV1
|
|
118
|
+
};
|