@remit/config-format 0.0.1 → 0.0.2
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/package.json
CHANGED
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"properties": {
|
|
42
42
|
"accountConfigId": {
|
|
43
43
|
"type": "string",
|
|
44
|
-
"
|
|
45
|
-
"
|
|
44
|
+
"minLength": 25,
|
|
45
|
+
"maxLength": 25
|
|
46
46
|
},
|
|
47
47
|
"instance": {
|
|
48
48
|
"type": "string"
|
|
@@ -59,6 +59,9 @@
|
|
|
59
59
|
"properties": {
|
|
60
60
|
"name": {
|
|
61
61
|
"type": "string"
|
|
62
|
+
},
|
|
63
|
+
"defaultComposerFormat": {
|
|
64
|
+
"type": "string"
|
|
62
65
|
}
|
|
63
66
|
},
|
|
64
67
|
"required": [
|
|
@@ -73,8 +76,8 @@
|
|
|
73
76
|
"properties": {
|
|
74
77
|
"accountId": {
|
|
75
78
|
"type": "string",
|
|
76
|
-
"
|
|
77
|
-
"
|
|
79
|
+
"minLength": 25,
|
|
80
|
+
"maxLength": 25
|
|
78
81
|
},
|
|
79
82
|
"email": {
|
|
80
83
|
"type": "string",
|
|
@@ -470,8 +473,8 @@
|
|
|
470
473
|
"properties": {
|
|
471
474
|
"accountId": {
|
|
472
475
|
"type": "string",
|
|
473
|
-
"
|
|
474
|
-
"
|
|
476
|
+
"minLength": 25,
|
|
477
|
+
"maxLength": 25
|
|
475
478
|
},
|
|
476
479
|
"folderPath": {
|
|
477
480
|
"type": "string",
|
|
@@ -506,8 +509,8 @@
|
|
|
506
509
|
},
|
|
507
510
|
"sourceMessageId": {
|
|
508
511
|
"type": "string",
|
|
509
|
-
"
|
|
510
|
-
"
|
|
512
|
+
"minLength": 25,
|
|
513
|
+
"maxLength": 25
|
|
511
514
|
}
|
|
512
515
|
},
|
|
513
516
|
"required": [
|
|
@@ -784,9 +787,6 @@
|
|
|
784
787
|
"density": {
|
|
785
788
|
"type": "string"
|
|
786
789
|
},
|
|
787
|
-
"defaultComposerFormat": {
|
|
788
|
-
"type": "string"
|
|
789
|
-
},
|
|
790
790
|
"savedSearches": {
|
|
791
791
|
"type": "array",
|
|
792
792
|
"items": {
|
|
@@ -811,7 +811,6 @@
|
|
|
811
811
|
"required": [
|
|
812
812
|
"theme",
|
|
813
813
|
"density",
|
|
814
|
-
"defaultComposerFormat",
|
|
815
814
|
"savedSearches"
|
|
816
815
|
],
|
|
817
816
|
"additionalProperties": false
|
package/src/document.test.ts
CHANGED
|
@@ -94,7 +94,7 @@ test("a filter names its label by name and its folder by account and path", () =
|
|
|
94
94
|
literalClauses: [{ field: FilterClauseField.ListId, value: "x.example" }],
|
|
95
95
|
actionLabelName: "Facturen",
|
|
96
96
|
actionFolder: {
|
|
97
|
-
accountId: "
|
|
97
|
+
accountId: "6f4c2c309a2c4a7f9f9f1f2c3",
|
|
98
98
|
folderPath: "INBOX.Facturen",
|
|
99
99
|
},
|
|
100
100
|
anchor: null,
|
|
@@ -108,7 +108,7 @@ test("a filter names its label by name and its folder by account and path", () =
|
|
|
108
108
|
assert.equal(
|
|
109
109
|
FilterSchema.safeParse({
|
|
110
110
|
...filter,
|
|
111
|
-
actionFolder: { mailboxId: "
|
|
111
|
+
actionFolder: { mailboxId: "6f4c2c309a2c4a7f9f9f1f2c3" },
|
|
112
112
|
}).success,
|
|
113
113
|
false,
|
|
114
114
|
);
|
|
@@ -126,7 +126,7 @@ test("a filter anchor carries its source text and no vector", () => {
|
|
|
126
126
|
anchor: {
|
|
127
127
|
sourceText: "the release note we file every month",
|
|
128
128
|
embeddingId: "amazon.titan-embed-text-v2:0@1024",
|
|
129
|
-
sourceMessageId: "
|
|
129
|
+
sourceMessageId: "2c9e4b117d5a4f609a315b8c0",
|
|
130
130
|
},
|
|
131
131
|
};
|
|
132
132
|
|
|
@@ -137,7 +137,7 @@ test("a filter anchor carries its source text and no vector", () => {
|
|
|
137
137
|
anchor: {
|
|
138
138
|
sourceText: "x",
|
|
139
139
|
embeddingId: "m@1",
|
|
140
|
-
sourceMessageId: "
|
|
140
|
+
sourceMessageId: "2c9e4b117d5a4f609a315b8c0",
|
|
141
141
|
anchorEmbedding: [0.1, 0.2],
|
|
142
142
|
},
|
|
143
143
|
}).success,
|
|
@@ -205,6 +205,46 @@ test("the reserved decisions slot is defined and empty", () => {
|
|
|
205
205
|
assert.equal(MessageDecisionsSchema.safeParse([{}]).success, false);
|
|
206
206
|
});
|
|
207
207
|
|
|
208
|
+
test("an id is the stored 25-character form, never the RFC 4122 spelling", () => {
|
|
209
|
+
// Every id in this database is a UUID re-encoded base36 to 25 characters,
|
|
210
|
+
// and `UUID` in the API contract means exactly that. A schema that took the
|
|
211
|
+
// dashed spelling would refuse every id a real export produces, so the
|
|
212
|
+
// dashed one has to fail here for the stored one to be the contract.
|
|
213
|
+
const account = goldenAccount();
|
|
214
|
+
account.accountId = "6f4c2c30-9a2c-4a7f-9f9f-1f2c3d4e5a6b";
|
|
215
|
+
|
|
216
|
+
assert.equal(AccountSchema.safeParse(account).success, false);
|
|
217
|
+
assert.equal(
|
|
218
|
+
AccountSchema.safeParse({
|
|
219
|
+
...goldenAccount(),
|
|
220
|
+
accountId: "6f4c2c309a2c4a7f9f9f1f2c3",
|
|
221
|
+
}).success,
|
|
222
|
+
true,
|
|
223
|
+
);
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
test("the composer format is a server setting, not a browser one", () => {
|
|
227
|
+
// It lives in an AccountSetting row the server owns and a database drop
|
|
228
|
+
// takes with it, so it rides `accountConfig`. Carrying it in the block the
|
|
229
|
+
// server ignores would have the file record it and the import discard it.
|
|
230
|
+
const source = readGoldenConfigDocument() as {
|
|
231
|
+
accountConfig: Record<string, unknown>;
|
|
232
|
+
clientPreferences: Record<string, unknown>;
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
assert.equal(source.accountConfig.defaultComposerFormat, "markdown");
|
|
236
|
+
assert.equal(
|
|
237
|
+
ReaderConfigDocumentSchema.safeParse({
|
|
238
|
+
...source,
|
|
239
|
+
clientPreferences: {
|
|
240
|
+
...source.clientPreferences,
|
|
241
|
+
defaultComposerFormat: "markdown",
|
|
242
|
+
},
|
|
243
|
+
}).success,
|
|
244
|
+
false,
|
|
245
|
+
);
|
|
246
|
+
});
|
|
247
|
+
|
|
208
248
|
test("the document schema refuses an unknown top-level section", () => {
|
|
209
249
|
const source = readGoldenConfigDocument() as Record<string, unknown>;
|
|
210
250
|
|
package/src/document.ts
CHANGED
|
@@ -11,7 +11,15 @@ import { z } from "zod/v4";
|
|
|
11
11
|
import { CONFIG_KIND, CURRENT_SCHEMA_VERSION } from "./version.js";
|
|
12
12
|
|
|
13
13
|
const NonEmpty = z.string().min(1);
|
|
14
|
-
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A reader identifier in the form it is stored and travels: a UUID re-encoded
|
|
17
|
+
* base36 to a fixed 25 characters, which is what the `UUID` scalar in the API
|
|
18
|
+
* contract means here and what every id in the database actually holds. The
|
|
19
|
+
* account id crosses verbatim — resynced message ids hash from it — so the file
|
|
20
|
+
* has to accept the stored spelling rather than the RFC 4122 one.
|
|
21
|
+
*/
|
|
22
|
+
const StoredId = z.string().length(25);
|
|
15
23
|
const IsoDateTime = z.iso.datetime({ offset: true });
|
|
16
24
|
const Port = z.int().min(1).max(65535);
|
|
17
25
|
const FlagTimestamp = z.int();
|
|
@@ -42,7 +50,7 @@ export const GeneratorSchema = z
|
|
|
42
50
|
*/
|
|
43
51
|
export const ProvenanceSchema = z
|
|
44
52
|
.strictObject({
|
|
45
|
-
accountConfigId:
|
|
53
|
+
accountConfigId: StoredId,
|
|
46
54
|
instance: z.string(),
|
|
47
55
|
})
|
|
48
56
|
.describe("The instance this file was exported from. Never applied.");
|
|
@@ -145,7 +153,7 @@ export const FolderOverrideSchema = z.strictObject({
|
|
|
145
153
|
});
|
|
146
154
|
|
|
147
155
|
export const AccountSchema = z.strictObject({
|
|
148
|
-
accountId:
|
|
156
|
+
accountId: StoredId,
|
|
149
157
|
email: NonEmpty,
|
|
150
158
|
username: NonEmpty,
|
|
151
159
|
authType: z.enum(AccountAuthType),
|
|
@@ -165,6 +173,13 @@ export const AccountSchema = z.strictObject({
|
|
|
165
173
|
|
|
166
174
|
export const AccountConfigSchema = z.strictObject({
|
|
167
175
|
name: z.string(),
|
|
176
|
+
/**
|
|
177
|
+
* Which body format the composer opens on. A server-held setting rather than
|
|
178
|
+
* a browser one — it is stored per configuration and travels with it, so a
|
|
179
|
+
* database drop loses it unless the file carries it. Optional because a
|
|
180
|
+
* configuration that has never been asked holds no row.
|
|
181
|
+
*/
|
|
182
|
+
defaultComposerFormat: z.string().optional(),
|
|
168
183
|
});
|
|
169
184
|
|
|
170
185
|
export const LabelSchema = z.strictObject({
|
|
@@ -187,12 +202,12 @@ export const FilterAnchorSchema = z.strictObject({
|
|
|
187
202
|
sourceText: z.string().min(1).max(512),
|
|
188
203
|
/** `<modelId>@<dimensions>` the vector was built with, for provenance. */
|
|
189
204
|
embeddingId: NonEmpty,
|
|
190
|
-
sourceMessageId:
|
|
205
|
+
sourceMessageId: StoredId,
|
|
191
206
|
});
|
|
192
207
|
|
|
193
208
|
/** A folder named the only way it can be named across instances. */
|
|
194
209
|
export const FolderRefSchema = z.strictObject({
|
|
195
|
-
accountId:
|
|
210
|
+
accountId: StoredId,
|
|
196
211
|
folderPath: ImapPath,
|
|
197
212
|
});
|
|
198
213
|
|
|
@@ -222,7 +237,6 @@ export const SavedSearchSchema = z.strictObject({
|
|
|
222
237
|
export const ClientPreferencesSchema = z.strictObject({
|
|
223
238
|
theme: z.string(),
|
|
224
239
|
density: z.string(),
|
|
225
|
-
defaultComposerFormat: z.string(),
|
|
226
240
|
savedSearches: z.array(SavedSearchSchema),
|
|
227
241
|
});
|
|
228
242
|
|
|
@@ -7,15 +7,16 @@
|
|
|
7
7
|
"exportedAt": "2026-08-27T09:15:00+02:00"
|
|
8
8
|
},
|
|
9
9
|
"provenance": {
|
|
10
|
-
"accountConfigId": "
|
|
10
|
+
"accountConfigId": "0d9c8b7a6e5f4d3cb2a10f9e8",
|
|
11
11
|
"instance": "reader.ischen.nl"
|
|
12
12
|
},
|
|
13
13
|
"accountConfig": {
|
|
14
|
-
"name": "Matthijs"
|
|
14
|
+
"name": "Matthijs",
|
|
15
|
+
"defaultComposerFormat": "markdown"
|
|
15
16
|
},
|
|
16
17
|
"accounts": [
|
|
17
18
|
{
|
|
18
|
-
"accountId": "
|
|
19
|
+
"accountId": "6f4c2c309a2c4a7f9f9f1f2c3",
|
|
19
20
|
"email": "matthijs@ischen.nl",
|
|
20
21
|
"username": "matthijs@ischen.nl",
|
|
21
22
|
"authType": "password",
|
|
@@ -63,7 +64,7 @@
|
|
|
63
64
|
"pinnedFolders": ["INBOX", "INBOX.Facturen"]
|
|
64
65
|
},
|
|
65
66
|
{
|
|
66
|
-
"accountId": "
|
|
67
|
+
"accountId": "b3a1d0c75e644f1b8c2a77e9d",
|
|
67
68
|
"email": "work@example.com",
|
|
68
69
|
"username": "work@example.com",
|
|
69
70
|
"authType": "oauthMicrosoft",
|
|
@@ -108,7 +109,7 @@
|
|
|
108
109
|
],
|
|
109
110
|
"actionLabelName": "Facturen",
|
|
110
111
|
"actionFolder": {
|
|
111
|
-
"accountId": "
|
|
112
|
+
"accountId": "6f4c2c309a2c4a7f9f9f1f2c3",
|
|
112
113
|
"folderPath": "INBOX.Facturen"
|
|
113
114
|
},
|
|
114
115
|
"anchor": null
|
|
@@ -124,7 +125,7 @@
|
|
|
124
125
|
"anchor": {
|
|
125
126
|
"sourceText": "We have shipped version 4.2 of the runtime; the changelog covers the new scheduler.",
|
|
126
127
|
"embeddingId": "amazon.titan-embed-text-v2:0@1024",
|
|
127
|
-
"sourceMessageId": "
|
|
128
|
+
"sourceMessageId": "2c9e4b117d5a4f609a315b8c0"
|
|
128
129
|
}
|
|
129
130
|
}
|
|
130
131
|
],
|
|
@@ -162,7 +163,6 @@
|
|
|
162
163
|
"clientPreferences": {
|
|
163
164
|
"theme": "dark",
|
|
164
165
|
"density": "comfortable",
|
|
165
|
-
"defaultComposerFormat": "markdown",
|
|
166
166
|
"savedSearches": [{ "name": "Unpaid invoices", "query": "label:Facturen is:unread" }]
|
|
167
167
|
},
|
|
168
168
|
"messageDecisions": []
|