@ctxindex/profiles 0.1.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/LICENSE +21 -0
- package/README.md +16 -0
- package/dist/calendar-event.d.ts +119 -0
- package/dist/calendar-event.js +11 -0
- package/dist/chat-message.d.ts +51 -0
- package/dist/chat-message.js +11 -0
- package/dist/chunks/index-3sp1af8a.js +178 -0
- package/dist/chunks/index-e0nk6n94.js +132 -0
- package/dist/chunks/index-m7k8kdqj.js +95 -0
- package/dist/chunks/index-x7wy2y2c.js +191 -0
- package/dist/file.d.ts +25 -0
- package/dist/file.js +13 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +51 -0
- package/dist/mail-message.d.ts +94 -0
- package/dist/mail-message.js +25 -0
- package/package.json +54 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ctxindex contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# @ctxindex/profiles
|
|
2
|
+
|
|
3
|
+
Portable, versioned domain Profiles for ctxindex Resources.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { mailMessageProfile } from '@ctxindex/profiles/mail-message'
|
|
7
|
+
|
|
8
|
+
console.log(mailMessageProfile.id)
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
The package exports the complete Profile collection from `@ctxindex/profiles`
|
|
12
|
+
and dedicated `calendar-event`, `chat-message`, `mail-message`, and `file`
|
|
13
|
+
subpaths. Profile schemas use the tested Zod version shared with
|
|
14
|
+
`@ctxindex/extension-sdk`.
|
|
15
|
+
|
|
16
|
+
Licensed under MIT.
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const calendarEventSchema: z.ZodObject<{
|
|
3
|
+
provider: z.ZodString;
|
|
4
|
+
providerCalendarId: z.ZodString;
|
|
5
|
+
providerEventId: z.ZodString;
|
|
6
|
+
timing: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
7
|
+
kind: z.ZodLiteral<"timed">;
|
|
8
|
+
start: z.ZodISODateTime;
|
|
9
|
+
end: z.ZodISODateTime;
|
|
10
|
+
startTimeZone: z.ZodOptional<z.ZodString>;
|
|
11
|
+
endTimeZone: z.ZodOptional<z.ZodString>;
|
|
12
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
13
|
+
kind: z.ZodLiteral<"all-day">;
|
|
14
|
+
startDate: z.ZodISODate;
|
|
15
|
+
endDate: z.ZodISODate;
|
|
16
|
+
}, z.core.$strict>], "kind">;
|
|
17
|
+
title: z.ZodOptional<z.ZodString>;
|
|
18
|
+
description: z.ZodOptional<z.ZodString>;
|
|
19
|
+
location: z.ZodOptional<z.ZodString>;
|
|
20
|
+
status: z.ZodEnum<{
|
|
21
|
+
tentative: "tentative";
|
|
22
|
+
confirmed: "confirmed";
|
|
23
|
+
cancelled: "cancelled";
|
|
24
|
+
}>;
|
|
25
|
+
organizer: z.ZodOptional<z.ZodObject<{
|
|
26
|
+
displayName: z.ZodOptional<z.ZodString>;
|
|
27
|
+
email: z.ZodOptional<z.ZodString>;
|
|
28
|
+
self: z.ZodOptional<z.ZodBoolean>;
|
|
29
|
+
}, z.core.$strict>>;
|
|
30
|
+
attendees: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
31
|
+
responseStatus: z.ZodOptional<z.ZodEnum<{
|
|
32
|
+
none: "none";
|
|
33
|
+
"needs-action": "needs-action";
|
|
34
|
+
tentative: "tentative";
|
|
35
|
+
accepted: "accepted";
|
|
36
|
+
declined: "declined";
|
|
37
|
+
organizer: "organizer";
|
|
38
|
+
}>>;
|
|
39
|
+
displayName: z.ZodOptional<z.ZodString>;
|
|
40
|
+
email: z.ZodOptional<z.ZodString>;
|
|
41
|
+
self: z.ZodOptional<z.ZodBoolean>;
|
|
42
|
+
}, z.core.$strict>>>;
|
|
43
|
+
recurrenceRules: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
44
|
+
series: z.ZodOptional<z.ZodObject<{
|
|
45
|
+
providerEventId: z.ZodString;
|
|
46
|
+
ref: z.ZodString;
|
|
47
|
+
originalStart: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
48
|
+
kind: z.ZodLiteral<"timed">;
|
|
49
|
+
at: z.ZodISODateTime;
|
|
50
|
+
timeZone: z.ZodOptional<z.ZodString>;
|
|
51
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
52
|
+
kind: z.ZodLiteral<"all-day">;
|
|
53
|
+
date: z.ZodISODate;
|
|
54
|
+
}, z.core.$strict>], "kind">;
|
|
55
|
+
}, z.core.$strict>>;
|
|
56
|
+
providerUrl: z.ZodOptional<z.ZodURL>;
|
|
57
|
+
createdAt: z.ZodOptional<z.ZodISODateTime>;
|
|
58
|
+
updatedAt: z.ZodOptional<z.ZodISODateTime>;
|
|
59
|
+
}, z.core.$strict>;
|
|
60
|
+
export type CalendarEvent = z.infer<typeof calendarEventSchema>;
|
|
61
|
+
export declare function calendarEventRef(sourceId: string, opaqueEventId: string): string;
|
|
62
|
+
export declare const calendarEventProfile: import("@ctxindex/extension-sdk").ProfileDefinition<"calendar.event", 1, z.ZodObject<{
|
|
63
|
+
provider: z.ZodString;
|
|
64
|
+
providerCalendarId: z.ZodString;
|
|
65
|
+
providerEventId: z.ZodString;
|
|
66
|
+
timing: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
67
|
+
kind: z.ZodLiteral<"timed">;
|
|
68
|
+
start: z.ZodISODateTime;
|
|
69
|
+
end: z.ZodISODateTime;
|
|
70
|
+
startTimeZone: z.ZodOptional<z.ZodString>;
|
|
71
|
+
endTimeZone: z.ZodOptional<z.ZodString>;
|
|
72
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
73
|
+
kind: z.ZodLiteral<"all-day">;
|
|
74
|
+
startDate: z.ZodISODate;
|
|
75
|
+
endDate: z.ZodISODate;
|
|
76
|
+
}, z.core.$strict>], "kind">;
|
|
77
|
+
title: z.ZodOptional<z.ZodString>;
|
|
78
|
+
description: z.ZodOptional<z.ZodString>;
|
|
79
|
+
location: z.ZodOptional<z.ZodString>;
|
|
80
|
+
status: z.ZodEnum<{
|
|
81
|
+
tentative: "tentative";
|
|
82
|
+
confirmed: "confirmed";
|
|
83
|
+
cancelled: "cancelled";
|
|
84
|
+
}>;
|
|
85
|
+
organizer: z.ZodOptional<z.ZodObject<{
|
|
86
|
+
displayName: z.ZodOptional<z.ZodString>;
|
|
87
|
+
email: z.ZodOptional<z.ZodString>;
|
|
88
|
+
self: z.ZodOptional<z.ZodBoolean>;
|
|
89
|
+
}, z.core.$strict>>;
|
|
90
|
+
attendees: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
91
|
+
responseStatus: z.ZodOptional<z.ZodEnum<{
|
|
92
|
+
none: "none";
|
|
93
|
+
"needs-action": "needs-action";
|
|
94
|
+
tentative: "tentative";
|
|
95
|
+
accepted: "accepted";
|
|
96
|
+
declined: "declined";
|
|
97
|
+
organizer: "organizer";
|
|
98
|
+
}>>;
|
|
99
|
+
displayName: z.ZodOptional<z.ZodString>;
|
|
100
|
+
email: z.ZodOptional<z.ZodString>;
|
|
101
|
+
self: z.ZodOptional<z.ZodBoolean>;
|
|
102
|
+
}, z.core.$strict>>>;
|
|
103
|
+
recurrenceRules: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
104
|
+
series: z.ZodOptional<z.ZodObject<{
|
|
105
|
+
providerEventId: z.ZodString;
|
|
106
|
+
ref: z.ZodString;
|
|
107
|
+
originalStart: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
108
|
+
kind: z.ZodLiteral<"timed">;
|
|
109
|
+
at: z.ZodISODateTime;
|
|
110
|
+
timeZone: z.ZodOptional<z.ZodString>;
|
|
111
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
112
|
+
kind: z.ZodLiteral<"all-day">;
|
|
113
|
+
date: z.ZodISODate;
|
|
114
|
+
}, z.core.$strict>], "kind">;
|
|
115
|
+
}, z.core.$strict>>;
|
|
116
|
+
providerUrl: z.ZodOptional<z.ZodURL>;
|
|
117
|
+
createdAt: z.ZodOptional<z.ZodISODateTime>;
|
|
118
|
+
updatedAt: z.ZodOptional<z.ZodISODateTime>;
|
|
119
|
+
}, z.core.$strict>>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const chatMessageSchema: z.ZodObject<{
|
|
3
|
+
providerMessageId: z.ZodString;
|
|
4
|
+
conversationKey: z.ZodString;
|
|
5
|
+
sender: z.ZodObject<{
|
|
6
|
+
id: z.ZodString;
|
|
7
|
+
displayName: z.ZodOptional<z.ZodString>;
|
|
8
|
+
}, z.core.$strict>;
|
|
9
|
+
sentAt: z.ZodISODateTime;
|
|
10
|
+
editedAt: z.ZodOptional<z.ZodISODateTime>;
|
|
11
|
+
text: z.ZodOptional<z.ZodString>;
|
|
12
|
+
replyTo: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
13
|
+
ref: z.ZodString;
|
|
14
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
15
|
+
providerMessageId: z.ZodString;
|
|
16
|
+
conversationKey: z.ZodOptional<z.ZodString>;
|
|
17
|
+
}, z.core.$strict>]>>;
|
|
18
|
+
attachments: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
19
|
+
ref: z.ZodString;
|
|
20
|
+
filename: z.ZodOptional<z.ZodString>;
|
|
21
|
+
mediaType: z.ZodOptional<z.ZodString>;
|
|
22
|
+
byteSize: z.ZodOptional<z.ZodNumber>;
|
|
23
|
+
}, z.core.$strict>>>;
|
|
24
|
+
unread: z.ZodOptional<z.ZodBoolean>;
|
|
25
|
+
}, z.core.$strict>;
|
|
26
|
+
export type ChatMessage = z.infer<typeof chatMessageSchema>;
|
|
27
|
+
export declare function chatMessageNaturalKey(conversationKey: string, providerMessageId: string): string;
|
|
28
|
+
export declare const chatMessageProfile: import("@ctxindex/extension-sdk").ProfileDefinition<"chat.message", 1, z.ZodObject<{
|
|
29
|
+
providerMessageId: z.ZodString;
|
|
30
|
+
conversationKey: z.ZodString;
|
|
31
|
+
sender: z.ZodObject<{
|
|
32
|
+
id: z.ZodString;
|
|
33
|
+
displayName: z.ZodOptional<z.ZodString>;
|
|
34
|
+
}, z.core.$strict>;
|
|
35
|
+
sentAt: z.ZodISODateTime;
|
|
36
|
+
editedAt: z.ZodOptional<z.ZodISODateTime>;
|
|
37
|
+
text: z.ZodOptional<z.ZodString>;
|
|
38
|
+
replyTo: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
39
|
+
ref: z.ZodString;
|
|
40
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
41
|
+
providerMessageId: z.ZodString;
|
|
42
|
+
conversationKey: z.ZodOptional<z.ZodString>;
|
|
43
|
+
}, z.core.$strict>]>>;
|
|
44
|
+
attachments: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
45
|
+
ref: z.ZodString;
|
|
46
|
+
filename: z.ZodOptional<z.ZodString>;
|
|
47
|
+
mediaType: z.ZodOptional<z.ZodString>;
|
|
48
|
+
byteSize: z.ZodOptional<z.ZodNumber>;
|
|
49
|
+
}, z.core.$strict>>>;
|
|
50
|
+
unread: z.ZodOptional<z.ZodBoolean>;
|
|
51
|
+
}, z.core.$strict>>;
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/profiles/src/mail-message.ts
|
|
3
|
+
import { defineProfile } from "@ctxindex/extension-sdk";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
var artifactDescriptorSchema = z.object({
|
|
6
|
+
ref: z.string().min(1),
|
|
7
|
+
filename: z.string().optional(),
|
|
8
|
+
mediaType: z.string().optional(),
|
|
9
|
+
byteSize: z.number().int().nonnegative().optional()
|
|
10
|
+
}).strict();
|
|
11
|
+
var headerValueSchema = z.string().min(1).regex(/^[^\r\n]*$/);
|
|
12
|
+
var mailMessageDraftStandaloneContentShape = {
|
|
13
|
+
to: z.array(headerValueSchema).min(1),
|
|
14
|
+
cc: z.array(headerValueSchema).optional(),
|
|
15
|
+
bcc: z.array(headerValueSchema).optional(),
|
|
16
|
+
subject: z.string().regex(/^[^\r\n]*$/),
|
|
17
|
+
bodyText: z.string()
|
|
18
|
+
};
|
|
19
|
+
var mailMessageDraftAttachmentSchema = z.object({ ref: z.string().min(1) }).strict();
|
|
20
|
+
var MAX_DRAFT_ATTACHMENT_COUNT = 10;
|
|
21
|
+
var MAX_DRAFT_ATTACHMENT_BYTES = 2 * 1024 * 1024;
|
|
22
|
+
var draftAttachmentsSchema = z.array(mailMessageDraftAttachmentSchema).min(1).max(MAX_DRAFT_ATTACHMENT_COUNT).superRefine((attachments, context) => {
|
|
23
|
+
const seen = new Set;
|
|
24
|
+
for (const [index, attachment] of attachments.entries()) {
|
|
25
|
+
if (seen.has(attachment.ref))
|
|
26
|
+
context.addIssue({
|
|
27
|
+
code: "custom",
|
|
28
|
+
message: "Draft attachment Refs must be unique",
|
|
29
|
+
path: [index, "ref"]
|
|
30
|
+
});
|
|
31
|
+
seen.add(attachment.ref);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
var mailMessageDraftReplyContentShape = {
|
|
35
|
+
replyToRef: z.string().min(1),
|
|
36
|
+
bodyText: z.string()
|
|
37
|
+
};
|
|
38
|
+
var mailMessageDraftStandaloneCreateInputSchema = z.object({
|
|
39
|
+
...mailMessageDraftStandaloneContentShape,
|
|
40
|
+
attachments: draftAttachmentsSchema.optional()
|
|
41
|
+
}).strict();
|
|
42
|
+
var mailMessageDraftReplyCreateInputSchema = z.object({
|
|
43
|
+
...mailMessageDraftReplyContentShape,
|
|
44
|
+
attachments: draftAttachmentsSchema.optional()
|
|
45
|
+
}).strict();
|
|
46
|
+
var mailMessageDraftCreateInputSchema = z.union([
|
|
47
|
+
mailMessageDraftStandaloneCreateInputSchema,
|
|
48
|
+
mailMessageDraftReplyCreateInputSchema
|
|
49
|
+
]);
|
|
50
|
+
var mailMessageDraftStandaloneUpdateInputSchema = z.object({
|
|
51
|
+
ref: z.string().min(1),
|
|
52
|
+
...mailMessageDraftStandaloneContentShape
|
|
53
|
+
}).strict();
|
|
54
|
+
var mailMessageDraftReplyUpdateInputSchema = z.object({
|
|
55
|
+
ref: z.string().min(1),
|
|
56
|
+
...mailMessageDraftReplyContentShape
|
|
57
|
+
}).strict();
|
|
58
|
+
var mailMessageDraftUpdateInputSchema = z.union([
|
|
59
|
+
mailMessageDraftStandaloneUpdateInputSchema,
|
|
60
|
+
mailMessageDraftReplyUpdateInputSchema
|
|
61
|
+
]);
|
|
62
|
+
function sanitizeHeader(value) {
|
|
63
|
+
return value.replace(/[\r\n]+/g, " ");
|
|
64
|
+
}
|
|
65
|
+
function renderEml(payload) {
|
|
66
|
+
const headers = [];
|
|
67
|
+
const addHeader = (name, value) => {
|
|
68
|
+
if (value !== undefined)
|
|
69
|
+
headers.push(`${name}: ${sanitizeHeader(value)}`);
|
|
70
|
+
};
|
|
71
|
+
addHeader("From", payload.from?.map(sanitizeHeader).join(", "));
|
|
72
|
+
addHeader("To", payload.to?.map(sanitizeHeader).join(", "));
|
|
73
|
+
addHeader("Cc", payload.cc?.map(sanitizeHeader).join(", "));
|
|
74
|
+
addHeader("Bcc", payload.bcc?.map(sanitizeHeader).join(", "));
|
|
75
|
+
addHeader("Subject", payload.subject);
|
|
76
|
+
addHeader("Date", payload.date === undefined ? undefined : new Date(payload.date).toUTCString());
|
|
77
|
+
addHeader("Message-ID", payload.rfcMessageId);
|
|
78
|
+
addHeader("In-Reply-To", payload.inReplyTo);
|
|
79
|
+
headers.push("MIME-Version: 1.0", "Content-Type: text/plain; charset=utf-8", "Content-Transfer-Encoding: 8bit");
|
|
80
|
+
const body = (payload.bodyText ?? "").replace(/\r\n|\r|\n/g, `\r
|
|
81
|
+
`);
|
|
82
|
+
return `${headers.join(`\r
|
|
83
|
+
`)}\r
|
|
84
|
+
\r
|
|
85
|
+
${body}`;
|
|
86
|
+
}
|
|
87
|
+
var mailMessageSchema = z.object({
|
|
88
|
+
providerMessageId: z.string().min(1),
|
|
89
|
+
providerDraftId: z.string().min(1).optional(),
|
|
90
|
+
threadId: z.string().min(1).optional(),
|
|
91
|
+
conversationKey: z.string().min(1).optional(),
|
|
92
|
+
rfcMessageId: z.string().min(1).optional(),
|
|
93
|
+
inReplyTo: z.string().min(1).optional(),
|
|
94
|
+
references: z.array(z.string().min(1)).optional(),
|
|
95
|
+
replyTo: z.array(z.string().min(1)).optional(),
|
|
96
|
+
replyToRef: z.string().min(1).optional(),
|
|
97
|
+
subject: z.string().optional(),
|
|
98
|
+
from: z.array(z.string()).optional(),
|
|
99
|
+
to: z.array(z.string()).optional(),
|
|
100
|
+
cc: z.array(z.string()).optional(),
|
|
101
|
+
bcc: z.array(z.string()).optional(),
|
|
102
|
+
date: z.string().datetime().optional(),
|
|
103
|
+
snippet: z.string().optional(),
|
|
104
|
+
bodyText: z.string().optional(),
|
|
105
|
+
labels: z.array(z.string()).optional(),
|
|
106
|
+
unread: z.boolean().optional(),
|
|
107
|
+
attachments: z.array(artifactDescriptorSchema).optional(),
|
|
108
|
+
managedAttachmentRefs: z.array(z.string().min(1)).optional()
|
|
109
|
+
}).strict();
|
|
110
|
+
function deriveMailMessageReplyRecipient(payload) {
|
|
111
|
+
return payload.replyTo?.[0] ?? payload.from?.[0];
|
|
112
|
+
}
|
|
113
|
+
function deriveMailMessageReplySubject(subject) {
|
|
114
|
+
const base = (subject ?? "").replace(/^(?:\s*re\s*:\s*)+/i, "").trim();
|
|
115
|
+
return base ? `Re: ${base}` : "Re:";
|
|
116
|
+
}
|
|
117
|
+
function deriveMailMessageReplyReferences(references, rfcMessageId) {
|
|
118
|
+
return [...new Set([...references ?? [], rfcMessageId])];
|
|
119
|
+
}
|
|
120
|
+
var mailMessageProfile = defineProfile({
|
|
121
|
+
id: "mail.message",
|
|
122
|
+
version: 1,
|
|
123
|
+
schema: mailMessageSchema,
|
|
124
|
+
actions: {
|
|
125
|
+
"mail.message.draft.create": {
|
|
126
|
+
effect: "reversible",
|
|
127
|
+
input: mailMessageDraftCreateInputSchema,
|
|
128
|
+
output: { id: "mail.message", version: 1 }
|
|
129
|
+
},
|
|
130
|
+
"mail.message.draft.update": {
|
|
131
|
+
effect: "reversible",
|
|
132
|
+
input: mailMessageDraftUpdateInputSchema,
|
|
133
|
+
output: { id: "mail.message", version: 1 }
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
search: {
|
|
137
|
+
title: (payload) => payload.subject ?? null,
|
|
138
|
+
occurredAt: (payload) => payload.date === undefined ? null : new Date(payload.date),
|
|
139
|
+
chunks: (payload) => [
|
|
140
|
+
...payload.subject === undefined ? [] : [payload.subject],
|
|
141
|
+
...payload.from ?? [],
|
|
142
|
+
...payload.to ?? [],
|
|
143
|
+
...payload.snippet === undefined ? [] : [payload.snippet],
|
|
144
|
+
...payload.bodyText === undefined ? [] : [payload.bodyText]
|
|
145
|
+
],
|
|
146
|
+
fields: {
|
|
147
|
+
sender: {
|
|
148
|
+
type: "string[]",
|
|
149
|
+
extract: (payload) => payload.from ?? []
|
|
150
|
+
},
|
|
151
|
+
unread: {
|
|
152
|
+
type: "boolean",
|
|
153
|
+
extract: (payload) => payload.unread
|
|
154
|
+
},
|
|
155
|
+
rfcMessageId: {
|
|
156
|
+
type: "string",
|
|
157
|
+
extract: (payload) => payload.rfcMessageId
|
|
158
|
+
},
|
|
159
|
+
conversationKey: {
|
|
160
|
+
type: "string",
|
|
161
|
+
extract: (payload) => payload.conversationKey
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
artifacts: (payload) => [...payload.attachments ?? []],
|
|
166
|
+
relations: {
|
|
167
|
+
conversation: (payload) => payload.conversationKey ? { field: "conversationKey", value: payload.conversationKey } : undefined,
|
|
168
|
+
parent: (payload) => payload.inReplyTo ? { field: "rfcMessageId", value: payload.inReplyTo } : undefined
|
|
169
|
+
},
|
|
170
|
+
exports: {
|
|
171
|
+
eml: {
|
|
172
|
+
mediaType: "message/rfc822",
|
|
173
|
+
render: renderEml
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
export { mailMessageDraftAttachmentSchema, MAX_DRAFT_ATTACHMENT_COUNT, MAX_DRAFT_ATTACHMENT_BYTES, mailMessageDraftCreateInputSchema, mailMessageDraftUpdateInputSchema, mailMessageSchema, deriveMailMessageReplyRecipient, deriveMailMessageReplySubject, deriveMailMessageReplyReferences, mailMessageProfile };
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/profiles/src/chat-message.ts
|
|
3
|
+
import { defineProfile } from "@ctxindex/extension-sdk";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
var instantSchema = z.iso.datetime({ offset: true });
|
|
6
|
+
var conversationKeySchema = z.string().regex(/^[0-9A-HJKMNP-TV-Z]{26}:chat:.+$/);
|
|
7
|
+
var resourceRefSchema = z.string().regex(/^ctx:\/\/[0-9A-HJKMNP-TV-Z]{26}\/(?:[A-Za-z0-9\-._~!$&'()*+,;=:@/]|%[0-9A-F]{2})+$/).refine((ref) => {
|
|
8
|
+
const suffix = ref.slice(ref.indexOf("/", "ctx://".length) + 1);
|
|
9
|
+
return new TextEncoder().encode(suffix).length <= 16 * 1024;
|
|
10
|
+
}, "ctxindex Ref suffix exceeds 16 KiB");
|
|
11
|
+
var chatParticipantSchema = z.object({
|
|
12
|
+
id: z.string().min(1),
|
|
13
|
+
displayName: z.string().min(1).optional()
|
|
14
|
+
}).strict();
|
|
15
|
+
var chatAttachmentSchema = z.object({
|
|
16
|
+
ref: z.string().min(1),
|
|
17
|
+
filename: z.string().min(1).optional(),
|
|
18
|
+
mediaType: z.string().min(1).optional(),
|
|
19
|
+
byteSize: z.number().int().nonnegative().optional()
|
|
20
|
+
}).strict();
|
|
21
|
+
var chatReplyTargetSchema = z.union([
|
|
22
|
+
z.object({ ref: resourceRefSchema }).strict(),
|
|
23
|
+
z.object({
|
|
24
|
+
providerMessageId: z.string().min(1),
|
|
25
|
+
conversationKey: conversationKeySchema.optional()
|
|
26
|
+
}).strict()
|
|
27
|
+
]);
|
|
28
|
+
var chatMessageSchema = z.object({
|
|
29
|
+
providerMessageId: z.string().min(1),
|
|
30
|
+
conversationKey: conversationKeySchema,
|
|
31
|
+
sender: chatParticipantSchema,
|
|
32
|
+
sentAt: instantSchema,
|
|
33
|
+
editedAt: instantSchema.optional(),
|
|
34
|
+
text: z.string().min(1).optional(),
|
|
35
|
+
replyTo: chatReplyTargetSchema.optional(),
|
|
36
|
+
attachments: z.array(chatAttachmentSchema).min(1).optional(),
|
|
37
|
+
unread: z.boolean().optional()
|
|
38
|
+
}).strict().superRefine((message, context) => {
|
|
39
|
+
if (message.text === undefined && message.attachments === undefined) {
|
|
40
|
+
context.addIssue({
|
|
41
|
+
code: "custom",
|
|
42
|
+
message: "A chat message requires text or at least one attachment"
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
if (message.editedAt !== undefined && Date.parse(message.editedAt) < Date.parse(message.sentAt)) {
|
|
46
|
+
context.addIssue({
|
|
47
|
+
code: "custom",
|
|
48
|
+
message: "Chat message edit time must not precede sent time",
|
|
49
|
+
path: ["editedAt"]
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
function chatMessageNaturalKey(conversationKey, providerMessageId) {
|
|
54
|
+
return JSON.stringify([conversationKey, providerMessageId]);
|
|
55
|
+
}
|
|
56
|
+
function takeCodePoints(value, limit) {
|
|
57
|
+
return Array.from(value).slice(0, limit).join("");
|
|
58
|
+
}
|
|
59
|
+
function chatMessageTitle(message) {
|
|
60
|
+
const text = message.text?.replace(/\s+/g, " ").trim();
|
|
61
|
+
return takeCodePoints(text || message.attachments?.[0]?.filename || message.sender.displayName || message.sender.id, 120);
|
|
62
|
+
}
|
|
63
|
+
function chatMessageChunks(message) {
|
|
64
|
+
return [
|
|
65
|
+
message.text,
|
|
66
|
+
message.sender.displayName,
|
|
67
|
+
message.sender.id,
|
|
68
|
+
...(message.attachments ?? []).flatMap((attachment) => [
|
|
69
|
+
attachment.filename,
|
|
70
|
+
attachment.mediaType
|
|
71
|
+
])
|
|
72
|
+
].filter((value) => value !== undefined);
|
|
73
|
+
}
|
|
74
|
+
var chatMessageProfile = defineProfile({
|
|
75
|
+
id: "chat.message",
|
|
76
|
+
version: 1,
|
|
77
|
+
schema: chatMessageSchema,
|
|
78
|
+
search: {
|
|
79
|
+
title: chatMessageTitle,
|
|
80
|
+
occurredAt: (message) => new Date(message.sentAt),
|
|
81
|
+
chunks: chatMessageChunks,
|
|
82
|
+
fields: {
|
|
83
|
+
providerMessageId: {
|
|
84
|
+
type: "string",
|
|
85
|
+
extract: (message) => message.providerMessageId
|
|
86
|
+
},
|
|
87
|
+
messageKey: {
|
|
88
|
+
type: "string",
|
|
89
|
+
extract: (message) => chatMessageNaturalKey(message.conversationKey, message.providerMessageId)
|
|
90
|
+
},
|
|
91
|
+
conversationKey: {
|
|
92
|
+
type: "string",
|
|
93
|
+
extract: (message) => message.conversationKey
|
|
94
|
+
},
|
|
95
|
+
senderId: {
|
|
96
|
+
type: "string",
|
|
97
|
+
extract: (message) => message.sender.id
|
|
98
|
+
},
|
|
99
|
+
sentAt: {
|
|
100
|
+
type: "datetime",
|
|
101
|
+
extract: (message) => new Date(message.sentAt)
|
|
102
|
+
},
|
|
103
|
+
editedAt: {
|
|
104
|
+
type: "datetime",
|
|
105
|
+
extract: (message) => message.editedAt === undefined ? undefined : new Date(message.editedAt)
|
|
106
|
+
},
|
|
107
|
+
unread: {
|
|
108
|
+
type: "boolean",
|
|
109
|
+
extract: (message) => message.unread
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
relations: {
|
|
114
|
+
conversation: (message) => ({
|
|
115
|
+
field: "conversationKey",
|
|
116
|
+
value: message.conversationKey
|
|
117
|
+
}),
|
|
118
|
+
parent: (message) => {
|
|
119
|
+
if (message.replyTo === undefined)
|
|
120
|
+
return;
|
|
121
|
+
if ("ref" in message.replyTo)
|
|
122
|
+
return { ref: message.replyTo.ref };
|
|
123
|
+
return {
|
|
124
|
+
field: "messageKey",
|
|
125
|
+
value: chatMessageNaturalKey(message.replyTo.conversationKey ?? message.conversationKey, message.replyTo.providerMessageId)
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
artifacts: (message) => [...message.attachments ?? []]
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
export { chatMessageSchema, chatMessageNaturalKey, chatMessageProfile };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/profiles/src/file.ts
|
|
3
|
+
import { defineProfile } from "@ctxindex/extension-sdk";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
var CHUNK_TARGET = 1500;
|
|
6
|
+
var CHUNK_OVERLAP = 200;
|
|
7
|
+
var CHUNK_MAX = 3000;
|
|
8
|
+
function chunkText(text) {
|
|
9
|
+
if (!text.trim())
|
|
10
|
+
return [];
|
|
11
|
+
const chunks = [];
|
|
12
|
+
let offset = 0;
|
|
13
|
+
let index = 0;
|
|
14
|
+
while (offset < text.length) {
|
|
15
|
+
let end = Math.min(offset + CHUNK_TARGET, text.length);
|
|
16
|
+
if (end < text.length) {
|
|
17
|
+
const window = text.slice(offset, Math.min(offset + CHUNK_MAX, text.length));
|
|
18
|
+
const paragraphIndex = window.lastIndexOf(`
|
|
19
|
+
|
|
20
|
+
`);
|
|
21
|
+
if (paragraphIndex > CHUNK_TARGET / 2) {
|
|
22
|
+
end = offset + paragraphIndex + 2;
|
|
23
|
+
} else {
|
|
24
|
+
const headingIndex = window.lastIndexOf(`
|
|
25
|
+
#`);
|
|
26
|
+
if (headingIndex > CHUNK_TARGET / 2) {
|
|
27
|
+
end = offset + headingIndex + 1;
|
|
28
|
+
} else {
|
|
29
|
+
const newlineIndex = window.lastIndexOf(`
|
|
30
|
+
`);
|
|
31
|
+
if (newlineIndex > CHUNK_TARGET / 2) {
|
|
32
|
+
end = offset + newlineIndex + 1;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const content = text.slice(offset, end).trim();
|
|
38
|
+
if (content)
|
|
39
|
+
chunks.push({ index: index++, content });
|
|
40
|
+
if (end >= text.length)
|
|
41
|
+
break;
|
|
42
|
+
offset = Math.max(offset + 1, end - CHUNK_OVERLAP);
|
|
43
|
+
}
|
|
44
|
+
return chunks;
|
|
45
|
+
}
|
|
46
|
+
function isNormalizedRelativeFilePath(path) {
|
|
47
|
+
if (path.length === 0 || path.startsWith("/") || /^[A-Za-z]:[/]/.test(path) || path.includes("\\")) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
const segments = path.split("/");
|
|
51
|
+
return segments.every((segment) => segment.length > 0 && segment !== "." && segment !== "..");
|
|
52
|
+
}
|
|
53
|
+
function extensionOf(name) {
|
|
54
|
+
const dot = name.lastIndexOf(".");
|
|
55
|
+
return dot > 0 && dot < name.length - 1 ? name.slice(dot + 1) : undefined;
|
|
56
|
+
}
|
|
57
|
+
var fileSchema = z.object({
|
|
58
|
+
path: z.string().refine(isNormalizedRelativeFilePath),
|
|
59
|
+
name: z.string().min(1),
|
|
60
|
+
mediaType: z.string().min(1),
|
|
61
|
+
byteSize: z.number().int().nonnegative(),
|
|
62
|
+
modifiedAt: z.string().datetime(),
|
|
63
|
+
contentHash: z.string().regex(/^sha256:[0-9a-f]{64}$/),
|
|
64
|
+
text: z.string()
|
|
65
|
+
}).strict();
|
|
66
|
+
var fileProfile = defineProfile({
|
|
67
|
+
id: "file",
|
|
68
|
+
version: 1,
|
|
69
|
+
schema: fileSchema,
|
|
70
|
+
search: {
|
|
71
|
+
title: (payload) => payload.path,
|
|
72
|
+
occurredAt: (payload) => new Date(payload.modifiedAt),
|
|
73
|
+
chunks: (payload) => chunkText(payload.text).map(({ content }) => content),
|
|
74
|
+
fields: {
|
|
75
|
+
path: { type: "string", extract: (payload) => payload.path },
|
|
76
|
+
name: { type: "string", extract: (payload) => payload.name },
|
|
77
|
+
extension: {
|
|
78
|
+
type: "string",
|
|
79
|
+
extract: (payload) => extensionOf(payload.name)
|
|
80
|
+
},
|
|
81
|
+
mediaType: { type: "string", extract: (payload) => payload.mediaType },
|
|
82
|
+
size: { type: "number", extract: (payload) => payload.byteSize },
|
|
83
|
+
modifiedAt: {
|
|
84
|
+
type: "datetime",
|
|
85
|
+
extract: (payload) => new Date(payload.modifiedAt)
|
|
86
|
+
},
|
|
87
|
+
contentHash: {
|
|
88
|
+
type: "string",
|
|
89
|
+
extract: (payload) => payload.contentHash
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
export { chunkText, isNormalizedRelativeFilePath, fileSchema, fileProfile };
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/profiles/src/calendar-event.ts
|
|
3
|
+
import { defineProfile } from "@ctxindex/extension-sdk";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
var sourceIdPattern = /^[0-9A-HJKMNP-TV-Z]{26}$/;
|
|
6
|
+
var providerIdPattern = /^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)*$/;
|
|
7
|
+
var instantSchema = z.iso.datetime({ offset: true });
|
|
8
|
+
var dateSchema = z.iso.date();
|
|
9
|
+
var participantShape = {
|
|
10
|
+
displayName: z.string().min(1).optional(),
|
|
11
|
+
email: z.string().min(1).optional(),
|
|
12
|
+
self: z.boolean().optional()
|
|
13
|
+
};
|
|
14
|
+
var participantSchema = z.object(participantShape).strict().refine((participant) => participant.displayName !== undefined || participant.email !== undefined, "A participant requires a display name or email");
|
|
15
|
+
var attendeeSchema = z.object({
|
|
16
|
+
...participantShape,
|
|
17
|
+
responseStatus: z.enum([
|
|
18
|
+
"none",
|
|
19
|
+
"needs-action",
|
|
20
|
+
"tentative",
|
|
21
|
+
"accepted",
|
|
22
|
+
"declined",
|
|
23
|
+
"organizer"
|
|
24
|
+
]).optional()
|
|
25
|
+
}).strict().refine((participant) => participant.displayName !== undefined || participant.email !== undefined, "An attendee requires a display name or email");
|
|
26
|
+
var timedTimingSchema = z.object({
|
|
27
|
+
kind: z.literal("timed"),
|
|
28
|
+
start: instantSchema,
|
|
29
|
+
end: instantSchema,
|
|
30
|
+
startTimeZone: z.string().min(1).optional(),
|
|
31
|
+
endTimeZone: z.string().min(1).optional()
|
|
32
|
+
}).strict().refine((timing) => Date.parse(timing.end) > Date.parse(timing.start), "Timed event end must be after start");
|
|
33
|
+
var allDayTimingSchema = z.object({
|
|
34
|
+
kind: z.literal("all-day"),
|
|
35
|
+
startDate: dateSchema,
|
|
36
|
+
endDate: dateSchema
|
|
37
|
+
}).strict().refine((timing) => timing.endDate > timing.startDate, "All-day event end date must be after start date");
|
|
38
|
+
var occurrenceStartSchema = z.discriminatedUnion("kind", [
|
|
39
|
+
z.object({
|
|
40
|
+
kind: z.literal("timed"),
|
|
41
|
+
at: instantSchema,
|
|
42
|
+
timeZone: z.string().min(1).optional()
|
|
43
|
+
}).strict(),
|
|
44
|
+
z.object({ kind: z.literal("all-day"), date: dateSchema }).strict()
|
|
45
|
+
]);
|
|
46
|
+
function isCanonicalEventRef(value) {
|
|
47
|
+
const match = /^ctx:\/\/([^/]+)\/event\/([^/?#]+)$/.exec(value);
|
|
48
|
+
if (!match?.[1] || !match[2] || !sourceIdPattern.test(match[1]))
|
|
49
|
+
return false;
|
|
50
|
+
try {
|
|
51
|
+
return encodeURIComponent(decodeURIComponent(match[2])) === match[2];
|
|
52
|
+
} catch {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
var seriesSchema = z.object({
|
|
57
|
+
providerEventId: z.string().min(1),
|
|
58
|
+
ref: z.string().refine(isCanonicalEventRef, "Invalid calendar series Ref"),
|
|
59
|
+
originalStart: occurrenceStartSchema
|
|
60
|
+
}).strict();
|
|
61
|
+
var httpsUrlSchema = z.url().refine((value) => {
|
|
62
|
+
const url = new URL(value);
|
|
63
|
+
return url.protocol === "https:" && url.username === "" && url.password === "";
|
|
64
|
+
}, "Provider URL must be credential-free HTTPS");
|
|
65
|
+
var calendarEventSchema = z.object({
|
|
66
|
+
provider: z.string().regex(providerIdPattern),
|
|
67
|
+
providerCalendarId: z.string().min(1),
|
|
68
|
+
providerEventId: z.string().min(1),
|
|
69
|
+
timing: z.discriminatedUnion("kind", [
|
|
70
|
+
timedTimingSchema,
|
|
71
|
+
allDayTimingSchema
|
|
72
|
+
]),
|
|
73
|
+
title: z.string().min(1).optional(),
|
|
74
|
+
description: z.string().min(1).optional(),
|
|
75
|
+
location: z.string().min(1).optional(),
|
|
76
|
+
status: z.enum(["confirmed", "tentative", "cancelled"]),
|
|
77
|
+
organizer: participantSchema.optional(),
|
|
78
|
+
attendees: z.array(attendeeSchema).optional(),
|
|
79
|
+
recurrenceRules: z.array(z.string().min(1)).min(1).optional(),
|
|
80
|
+
series: seriesSchema.optional(),
|
|
81
|
+
providerUrl: httpsUrlSchema.optional(),
|
|
82
|
+
createdAt: instantSchema.optional(),
|
|
83
|
+
updatedAt: instantSchema.optional()
|
|
84
|
+
}).strict().refine((event) => event.createdAt === undefined || event.updatedAt === undefined || Date.parse(event.updatedAt) >= Date.parse(event.createdAt), "Calendar Event update time must not precede creation time");
|
|
85
|
+
function takeCodePoints(value, limit) {
|
|
86
|
+
return Array.from(value).slice(0, limit).join("");
|
|
87
|
+
}
|
|
88
|
+
function participantText(participant) {
|
|
89
|
+
if (participant.displayName && participant.email) {
|
|
90
|
+
return `${participant.displayName} <${participant.email}>`;
|
|
91
|
+
}
|
|
92
|
+
return participant.email ?? participant.displayName;
|
|
93
|
+
}
|
|
94
|
+
function participantIdentity(participant) {
|
|
95
|
+
return participant.email ?? participant.displayName;
|
|
96
|
+
}
|
|
97
|
+
function calendarEventSummary(event) {
|
|
98
|
+
const summary = event.description ?? event.location;
|
|
99
|
+
return summary === undefined ? null : takeCodePoints(summary, 500);
|
|
100
|
+
}
|
|
101
|
+
function calendarEventChunks(event) {
|
|
102
|
+
const people = [
|
|
103
|
+
...event.organizer === undefined ? [] : [participantText(event.organizer)],
|
|
104
|
+
...(event.attendees ?? []).map(participantText)
|
|
105
|
+
].join(`
|
|
106
|
+
`);
|
|
107
|
+
return [event.title, event.description, event.location, people].filter((value) => value !== undefined && value.length > 0).map((value) => takeCodePoints(value, 3000));
|
|
108
|
+
}
|
|
109
|
+
function calendarEventRef(sourceId, opaqueEventId) {
|
|
110
|
+
if (!sourceIdPattern.test(sourceId)) {
|
|
111
|
+
throw new TypeError("Calendar Event Ref requires an uppercase Source ULID");
|
|
112
|
+
}
|
|
113
|
+
if (opaqueEventId.length === 0) {
|
|
114
|
+
throw new TypeError("Calendar Event Ref requires a provider event id");
|
|
115
|
+
}
|
|
116
|
+
return `ctx://${sourceId}/event/${encodeURIComponent(opaqueEventId)}`;
|
|
117
|
+
}
|
|
118
|
+
var calendarEventProfile = defineProfile({
|
|
119
|
+
id: "calendar.event",
|
|
120
|
+
version: 1,
|
|
121
|
+
schema: calendarEventSchema,
|
|
122
|
+
search: {
|
|
123
|
+
title: (event) => event.title ?? null,
|
|
124
|
+
summary: calendarEventSummary,
|
|
125
|
+
occurredAt: (event) => event.timing.kind === "timed" ? new Date(event.timing.start) : null,
|
|
126
|
+
chunks: calendarEventChunks,
|
|
127
|
+
fields: {
|
|
128
|
+
provider: {
|
|
129
|
+
type: "string",
|
|
130
|
+
extract: (event) => event.provider
|
|
131
|
+
},
|
|
132
|
+
calendarId: {
|
|
133
|
+
type: "string",
|
|
134
|
+
extract: (event) => event.providerCalendarId
|
|
135
|
+
},
|
|
136
|
+
eventId: {
|
|
137
|
+
type: "string",
|
|
138
|
+
extract: (event) => event.providerEventId
|
|
139
|
+
},
|
|
140
|
+
title: {
|
|
141
|
+
type: "string",
|
|
142
|
+
extract: (event) => event.title
|
|
143
|
+
},
|
|
144
|
+
status: {
|
|
145
|
+
type: "string",
|
|
146
|
+
extract: (event) => event.status
|
|
147
|
+
},
|
|
148
|
+
allDay: {
|
|
149
|
+
type: "boolean",
|
|
150
|
+
extract: (event) => event.timing.kind === "all-day"
|
|
151
|
+
},
|
|
152
|
+
startsAt: {
|
|
153
|
+
type: "datetime",
|
|
154
|
+
extract: (event) => event.timing.kind === "timed" ? new Date(event.timing.start) : undefined
|
|
155
|
+
},
|
|
156
|
+
endsAt: {
|
|
157
|
+
type: "datetime",
|
|
158
|
+
extract: (event) => event.timing.kind === "timed" ? new Date(event.timing.end) : undefined
|
|
159
|
+
},
|
|
160
|
+
startDate: {
|
|
161
|
+
type: "string",
|
|
162
|
+
extract: (event) => event.timing.kind === "all-day" ? event.timing.startDate : undefined
|
|
163
|
+
},
|
|
164
|
+
endDate: {
|
|
165
|
+
type: "string",
|
|
166
|
+
extract: (event) => event.timing.kind === "all-day" ? event.timing.endDate : undefined
|
|
167
|
+
},
|
|
168
|
+
organizer: {
|
|
169
|
+
type: "string",
|
|
170
|
+
extract: (event) => event.organizer === undefined ? undefined : participantIdentity(event.organizer)
|
|
171
|
+
},
|
|
172
|
+
attendees: {
|
|
173
|
+
type: "string[]",
|
|
174
|
+
extract: (event) => (event.attendees ?? []).map(participantIdentity)
|
|
175
|
+
},
|
|
176
|
+
seriesEventId: {
|
|
177
|
+
type: "string",
|
|
178
|
+
extract: (event) => event.series?.providerEventId
|
|
179
|
+
},
|
|
180
|
+
updatedAt: {
|
|
181
|
+
type: "datetime",
|
|
182
|
+
extract: (event) => event.updatedAt === undefined ? undefined : new Date(event.updatedAt)
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
relations: {
|
|
187
|
+
series: (event) => event.series === undefined ? undefined : { ref: event.series.ref }
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
export { calendarEventSchema, calendarEventRef, calendarEventProfile };
|
package/dist/file.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export interface FileChunk {
|
|
3
|
+
index: number;
|
|
4
|
+
content: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function chunkText(text: string): FileChunk[];
|
|
7
|
+
export declare function isNormalizedRelativeFilePath(path: string): boolean;
|
|
8
|
+
export declare const fileSchema: z.ZodObject<{
|
|
9
|
+
path: z.ZodString;
|
|
10
|
+
name: z.ZodString;
|
|
11
|
+
mediaType: z.ZodString;
|
|
12
|
+
byteSize: z.ZodNumber;
|
|
13
|
+
modifiedAt: z.ZodString;
|
|
14
|
+
contentHash: z.ZodString;
|
|
15
|
+
text: z.ZodString;
|
|
16
|
+
}, z.core.$strict>;
|
|
17
|
+
export declare const fileProfile: import("@ctxindex/extension-sdk").ProfileDefinition<"file", 1, z.ZodObject<{
|
|
18
|
+
path: z.ZodString;
|
|
19
|
+
name: z.ZodString;
|
|
20
|
+
mediaType: z.ZodString;
|
|
21
|
+
byteSize: z.ZodNumber;
|
|
22
|
+
modifiedAt: z.ZodString;
|
|
23
|
+
contentHash: z.ZodString;
|
|
24
|
+
text: z.ZodString;
|
|
25
|
+
}, z.core.$strict>>;
|
package/dist/file.js
ADDED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type { CalendarEvent } from './calendar-event.js';
|
|
2
|
+
export { calendarEventProfile, calendarEventRef, calendarEventSchema, } from './calendar-event.js';
|
|
3
|
+
export type { ChatMessage } from './chat-message.js';
|
|
4
|
+
export { chatMessageNaturalKey, chatMessageProfile, chatMessageSchema, } from './chat-message.js';
|
|
5
|
+
export type { FileChunk } from './file.js';
|
|
6
|
+
export { chunkText, fileProfile, fileSchema, isNormalizedRelativeFilePath, } from './file.js';
|
|
7
|
+
export type { MailMessage } from './mail-message.js';
|
|
8
|
+
export { deriveMailMessageReplyRecipient, deriveMailMessageReplyReferences, deriveMailMessageReplySubject, MAX_DRAFT_ATTACHMENT_BYTES, MAX_DRAFT_ATTACHMENT_COUNT, mailMessageDraftAttachmentSchema, mailMessageDraftCreateInputSchema, mailMessageDraftUpdateInputSchema, mailMessageProfile, mailMessageSchema, } from './mail-message.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
calendarEventProfile,
|
|
4
|
+
calendarEventRef,
|
|
5
|
+
calendarEventSchema
|
|
6
|
+
} from "./chunks/index-x7wy2y2c.js";
|
|
7
|
+
import {
|
|
8
|
+
chatMessageNaturalKey,
|
|
9
|
+
chatMessageProfile,
|
|
10
|
+
chatMessageSchema
|
|
11
|
+
} from "./chunks/index-e0nk6n94.js";
|
|
12
|
+
import {
|
|
13
|
+
MAX_DRAFT_ATTACHMENT_BYTES,
|
|
14
|
+
MAX_DRAFT_ATTACHMENT_COUNT,
|
|
15
|
+
deriveMailMessageReplyRecipient,
|
|
16
|
+
deriveMailMessageReplyReferences,
|
|
17
|
+
deriveMailMessageReplySubject,
|
|
18
|
+
mailMessageDraftAttachmentSchema,
|
|
19
|
+
mailMessageDraftCreateInputSchema,
|
|
20
|
+
mailMessageDraftUpdateInputSchema,
|
|
21
|
+
mailMessageProfile,
|
|
22
|
+
mailMessageSchema
|
|
23
|
+
} from "./chunks/index-3sp1af8a.js";
|
|
24
|
+
import {
|
|
25
|
+
chunkText,
|
|
26
|
+
fileProfile,
|
|
27
|
+
fileSchema,
|
|
28
|
+
isNormalizedRelativeFilePath
|
|
29
|
+
} from "./chunks/index-m7k8kdqj.js";
|
|
30
|
+
export {
|
|
31
|
+
mailMessageSchema,
|
|
32
|
+
mailMessageProfile,
|
|
33
|
+
mailMessageDraftUpdateInputSchema,
|
|
34
|
+
mailMessageDraftCreateInputSchema,
|
|
35
|
+
mailMessageDraftAttachmentSchema,
|
|
36
|
+
isNormalizedRelativeFilePath,
|
|
37
|
+
fileSchema,
|
|
38
|
+
fileProfile,
|
|
39
|
+
deriveMailMessageReplySubject,
|
|
40
|
+
deriveMailMessageReplyReferences,
|
|
41
|
+
deriveMailMessageReplyRecipient,
|
|
42
|
+
chunkText,
|
|
43
|
+
chatMessageSchema,
|
|
44
|
+
chatMessageProfile,
|
|
45
|
+
chatMessageNaturalKey,
|
|
46
|
+
calendarEventSchema,
|
|
47
|
+
calendarEventRef,
|
|
48
|
+
calendarEventProfile,
|
|
49
|
+
MAX_DRAFT_ATTACHMENT_COUNT,
|
|
50
|
+
MAX_DRAFT_ATTACHMENT_BYTES
|
|
51
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const mailMessageDraftAttachmentSchema: z.ZodObject<{
|
|
3
|
+
ref: z.ZodString;
|
|
4
|
+
}, z.core.$strict>;
|
|
5
|
+
export declare const MAX_DRAFT_ATTACHMENT_COUNT = 10;
|
|
6
|
+
export declare const MAX_DRAFT_ATTACHMENT_BYTES: number;
|
|
7
|
+
export declare const mailMessageDraftCreateInputSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
8
|
+
attachments: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
9
|
+
ref: z.ZodString;
|
|
10
|
+
}, z.core.$strict>>>;
|
|
11
|
+
to: z.ZodArray<z.ZodString>;
|
|
12
|
+
cc: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
13
|
+
bcc: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
14
|
+
subject: z.ZodString;
|
|
15
|
+
bodyText: z.ZodString;
|
|
16
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
17
|
+
attachments: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
18
|
+
ref: z.ZodString;
|
|
19
|
+
}, z.core.$strict>>>;
|
|
20
|
+
replyToRef: z.ZodString;
|
|
21
|
+
bodyText: z.ZodString;
|
|
22
|
+
}, z.core.$strict>]>;
|
|
23
|
+
export declare const mailMessageDraftUpdateInputSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
24
|
+
to: z.ZodArray<z.ZodString>;
|
|
25
|
+
cc: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
26
|
+
bcc: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
27
|
+
subject: z.ZodString;
|
|
28
|
+
bodyText: z.ZodString;
|
|
29
|
+
ref: z.ZodString;
|
|
30
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
31
|
+
replyToRef: z.ZodString;
|
|
32
|
+
bodyText: z.ZodString;
|
|
33
|
+
ref: z.ZodString;
|
|
34
|
+
}, z.core.$strict>]>;
|
|
35
|
+
export declare const mailMessageSchema: z.ZodObject<{
|
|
36
|
+
providerMessageId: z.ZodString;
|
|
37
|
+
providerDraftId: z.ZodOptional<z.ZodString>;
|
|
38
|
+
threadId: z.ZodOptional<z.ZodString>;
|
|
39
|
+
conversationKey: z.ZodOptional<z.ZodString>;
|
|
40
|
+
rfcMessageId: z.ZodOptional<z.ZodString>;
|
|
41
|
+
inReplyTo: z.ZodOptional<z.ZodString>;
|
|
42
|
+
references: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
43
|
+
replyTo: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
44
|
+
replyToRef: z.ZodOptional<z.ZodString>;
|
|
45
|
+
subject: z.ZodOptional<z.ZodString>;
|
|
46
|
+
from: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
47
|
+
to: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
48
|
+
cc: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
49
|
+
bcc: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
50
|
+
date: z.ZodOptional<z.ZodString>;
|
|
51
|
+
snippet: z.ZodOptional<z.ZodString>;
|
|
52
|
+
bodyText: z.ZodOptional<z.ZodString>;
|
|
53
|
+
labels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
54
|
+
unread: z.ZodOptional<z.ZodBoolean>;
|
|
55
|
+
attachments: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
56
|
+
ref: z.ZodString;
|
|
57
|
+
filename: z.ZodOptional<z.ZodString>;
|
|
58
|
+
mediaType: z.ZodOptional<z.ZodString>;
|
|
59
|
+
byteSize: z.ZodOptional<z.ZodNumber>;
|
|
60
|
+
}, z.core.$strict>>>;
|
|
61
|
+
managedAttachmentRefs: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
62
|
+
}, z.core.$strict>;
|
|
63
|
+
export type MailMessage = z.infer<typeof mailMessageSchema>;
|
|
64
|
+
export declare function deriveMailMessageReplyRecipient(payload: MailMessage): string | undefined;
|
|
65
|
+
export declare function deriveMailMessageReplySubject(subject: string | undefined): string;
|
|
66
|
+
export declare function deriveMailMessageReplyReferences(references: readonly string[] | undefined, rfcMessageId: string): string[];
|
|
67
|
+
export declare const mailMessageProfile: import("@ctxindex/extension-sdk").ProfileDefinition<"mail.message", 1, z.ZodObject<{
|
|
68
|
+
providerMessageId: z.ZodString;
|
|
69
|
+
providerDraftId: z.ZodOptional<z.ZodString>;
|
|
70
|
+
threadId: z.ZodOptional<z.ZodString>;
|
|
71
|
+
conversationKey: z.ZodOptional<z.ZodString>;
|
|
72
|
+
rfcMessageId: z.ZodOptional<z.ZodString>;
|
|
73
|
+
inReplyTo: z.ZodOptional<z.ZodString>;
|
|
74
|
+
references: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
75
|
+
replyTo: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
76
|
+
replyToRef: z.ZodOptional<z.ZodString>;
|
|
77
|
+
subject: z.ZodOptional<z.ZodString>;
|
|
78
|
+
from: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
79
|
+
to: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
80
|
+
cc: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
81
|
+
bcc: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
82
|
+
date: z.ZodOptional<z.ZodString>;
|
|
83
|
+
snippet: z.ZodOptional<z.ZodString>;
|
|
84
|
+
bodyText: z.ZodOptional<z.ZodString>;
|
|
85
|
+
labels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
86
|
+
unread: z.ZodOptional<z.ZodBoolean>;
|
|
87
|
+
attachments: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
88
|
+
ref: z.ZodString;
|
|
89
|
+
filename: z.ZodOptional<z.ZodString>;
|
|
90
|
+
mediaType: z.ZodOptional<z.ZodString>;
|
|
91
|
+
byteSize: z.ZodOptional<z.ZodNumber>;
|
|
92
|
+
}, z.core.$strict>>>;
|
|
93
|
+
managedAttachmentRefs: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
94
|
+
}, z.core.$strict>>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
MAX_DRAFT_ATTACHMENT_BYTES,
|
|
4
|
+
MAX_DRAFT_ATTACHMENT_COUNT,
|
|
5
|
+
deriveMailMessageReplyRecipient,
|
|
6
|
+
deriveMailMessageReplyReferences,
|
|
7
|
+
deriveMailMessageReplySubject,
|
|
8
|
+
mailMessageDraftAttachmentSchema,
|
|
9
|
+
mailMessageDraftCreateInputSchema,
|
|
10
|
+
mailMessageDraftUpdateInputSchema,
|
|
11
|
+
mailMessageProfile,
|
|
12
|
+
mailMessageSchema
|
|
13
|
+
} from "./chunks/index-3sp1af8a.js";
|
|
14
|
+
export {
|
|
15
|
+
mailMessageSchema,
|
|
16
|
+
mailMessageProfile,
|
|
17
|
+
mailMessageDraftUpdateInputSchema,
|
|
18
|
+
mailMessageDraftCreateInputSchema,
|
|
19
|
+
mailMessageDraftAttachmentSchema,
|
|
20
|
+
deriveMailMessageReplySubject,
|
|
21
|
+
deriveMailMessageReplyReferences,
|
|
22
|
+
deriveMailMessageReplyRecipient,
|
|
23
|
+
MAX_DRAFT_ATTACHMENT_COUNT,
|
|
24
|
+
MAX_DRAFT_ATTACHMENT_BYTES
|
|
25
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ctxindex/profiles",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Portable domain Profiles for ctxindex Resources.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"homepage": "https://ctxindex.com",
|
|
7
|
+
"bugs": {
|
|
8
|
+
"url": "https://github.com/barisgit/ctxindex/issues"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./calendar-event": {
|
|
17
|
+
"types": "./dist/calendar-event.d.ts",
|
|
18
|
+
"import": "./dist/calendar-event.js"
|
|
19
|
+
},
|
|
20
|
+
"./chat-message": {
|
|
21
|
+
"types": "./dist/chat-message.d.ts",
|
|
22
|
+
"import": "./dist/chat-message.js"
|
|
23
|
+
},
|
|
24
|
+
"./mail-message": {
|
|
25
|
+
"types": "./dist/mail-message.d.ts",
|
|
26
|
+
"import": "./dist/mail-message.js"
|
|
27
|
+
},
|
|
28
|
+
"./file": {
|
|
29
|
+
"types": "./dist/file.d.ts",
|
|
30
|
+
"import": "./dist/file.js"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"dist",
|
|
35
|
+
"README.md",
|
|
36
|
+
"LICENSE"
|
|
37
|
+
],
|
|
38
|
+
"engines": {
|
|
39
|
+
"bun": "1.3.14"
|
|
40
|
+
},
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "git+https://github.com/barisgit/ctxindex.git",
|
|
44
|
+
"directory": "packages/profiles"
|
|
45
|
+
},
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public",
|
|
48
|
+
"registry": "https://registry.npmjs.org/"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@ctxindex/extension-sdk": "0.1.0",
|
|
52
|
+
"zod": "^4.4.3"
|
|
53
|
+
}
|
|
54
|
+
}
|