@push.rocks/smartjmap 1.0.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.
@@ -0,0 +1,2 @@
1
+ export * from './classes.jmapclient.js';
2
+ export * from './classes.jmapserver.js';
@@ -0,0 +1,3 @@
1
+ export * from './classes.jmapclient.js';
2
+ export * from './classes.jmapserver.js';
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLHlCQUF5QixDQUFDO0FBQ3hDLGNBQWMseUJBQXlCLENBQUMifQ==
@@ -0,0 +1,4 @@
1
+ import * as events from 'node:events';
2
+ import * as http from 'node:http';
3
+ import * as net from 'node:net';
4
+ export { events, http, net, };
@@ -0,0 +1,6 @@
1
+ // node native
2
+ import * as events from 'node:events';
3
+ import * as http from 'node:http';
4
+ import * as net from 'node:net';
5
+ export { events, http, net, };
6
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRqbWFwLnBsdWdpbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGptYXAucGx1Z2lucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjO0FBQ2QsT0FBTyxLQUFLLE1BQU0sTUFBTSxhQUFhLENBQUM7QUFDdEMsT0FBTyxLQUFLLElBQUksTUFBTSxXQUFXLENBQUM7QUFDbEMsT0FBTyxLQUFLLEdBQUcsTUFBTSxVQUFVLENBQUM7QUFFaEMsT0FBTyxFQUNMLE1BQU0sRUFDTixJQUFJLEVBQ0osR0FBRyxHQUNKLENBQUEifQ==
package/license ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2026 Task Venture Capital GmbH <hello@task.vc>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
package/npmextra.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "@git.zone/cli": {
3
+ "projectType": "npm",
4
+ "module": {
5
+ "githost": "code.foss.global",
6
+ "gitscope": "push.rocks",
7
+ "gitrepo": "smartjmap",
8
+ "shortDescription": "JMAP client for mail (RFC 8620/8621)",
9
+ "description": "A TypeScript JMAP client for reading, sending, and watching mail via the JSON Meta Application Protocol (RFC 8620/8621), with a bundled test server for offline testing.",
10
+ "npmPackagename": "@push.rocks/smartjmap",
11
+ "license": "MIT",
12
+ "projectDomain": "push.rocks",
13
+ "keywords": [
14
+ "jmap",
15
+ "email",
16
+ "mail",
17
+ "rfc8620",
18
+ "rfc8621",
19
+ "fastmail",
20
+ "stalwart",
21
+ "json",
22
+ "http",
23
+ "client",
24
+ "typescript",
25
+ "event-driven",
26
+ "push",
27
+ "eventsource",
28
+ "message processing"
29
+ ]
30
+ }
31
+ },
32
+ "@ship.zone/szci": {
33
+ "npmGlobalTools": [],
34
+ "npmRegistryUrl": "registry.npmjs.org"
35
+ },
36
+ "@git.zone/tsdoc": {
37
+ "legal": "\n## License and Legal Information\n\nThis repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository. \n\n**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.\n\n### Trademarks\n\nThis project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.\n\n### Company Information\n\nTask Venture Capital GmbH \nRegistered at District court Bremen HRB 35230 HB, Germany\n\nFor any legal inquiries or if you require further information, please contact us via email at hello@task.vc.\n\nBy using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.\n"
38
+ }
39
+ }
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@push.rocks/smartjmap",
3
+ "version": "1.0.0",
4
+ "private": false,
5
+ "description": "A TypeScript JMAP client for reading, sending, and watching mail via the JSON Meta Application Protocol (RFC 8620/8621), with a bundled test server for offline testing.",
6
+ "exports": {
7
+ ".": "./dist_ts/index.js"
8
+ },
9
+ "main": "dist_ts/index.js",
10
+ "typings": "dist_ts/index.d.ts",
11
+ "type": "module",
12
+ "author": "Task Venture Capital GmbH <hello@task.vc>",
13
+ "license": "MIT",
14
+ "devDependencies": {
15
+ "@git.zone/tsbuild": "^4.4.0",
16
+ "@git.zone/tsrun": "^2.0.3",
17
+ "@git.zone/tstest": "^3.6.3",
18
+ "@types/node": "^25.6.0"
19
+ },
20
+ "dependencies": {},
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://code.foss.global/push.rocks/smartjmap.git"
24
+ },
25
+ "bugs": {
26
+ "url": "https://code.foss.global/push.rocks/smartjmap/issues"
27
+ },
28
+ "homepage": "https://code.foss.global/push.rocks/smartjmap#readme",
29
+ "browserslist": [
30
+ "last 1 chrome versions"
31
+ ],
32
+ "files": [
33
+ "ts/**/*",
34
+ "ts_web/**/*",
35
+ "dist/**/*",
36
+ "dist_*/**/*",
37
+ "dist_ts/**/*",
38
+ "dist_ts_web/**/*",
39
+ "assets/**/*",
40
+ "cli.js",
41
+ ".smartconfig.json",
42
+ "license",
43
+ "npmextra.json",
44
+ "readme.md"
45
+ ],
46
+ "keywords": [
47
+ "jmap",
48
+ "email",
49
+ "mail",
50
+ "rfc8620",
51
+ "rfc8621",
52
+ "fastmail",
53
+ "stalwart",
54
+ "json",
55
+ "http",
56
+ "client",
57
+ "typescript",
58
+ "event-driven",
59
+ "push",
60
+ "eventsource",
61
+ "message processing"
62
+ ],
63
+ "scripts": {
64
+ "test": "tstest test/",
65
+ "build": "tsbuild --web",
66
+ "buildDocs": "tsdoc"
67
+ }
68
+ }
@@ -0,0 +1,34 @@
1
+ # Project Readme Hints
2
+
3
+ Design notes for @push.rocks/smartjmap.
4
+
5
+ ## HTTP layer
6
+
7
+ - Zero runtime dependencies: global `fetch` (Node.js 18+ floor; developed against @types/node 25). smartrequest would add no value for plain JSON-over-HTTP.
8
+ - SSE is parsed by hand over a fetch body stream (~50 lines in `runEventStream`). The global `EventSource` was rejected deliberately: it is only default-enabled from Node 22.3 and, more importantly, the WHATWG EventSource API cannot send the `Authorization` header JMAP requires.
9
+
10
+ ## Watching semantics
11
+
12
+ - `connect()`: session GET → capability/account validation → mailbox resolution (role match on the lowercased mailbox name, e.g. 'INBOX' → role 'inbox', falling back to case-insensitive name match) → Email state snapshot → 'connected' → initial sweep (Email/query + Email/get, emitted oldest-first) → event stream.
13
+ - The Email state is snapshotted *before* the initial sweep and `fetchDeltas()` runs once right after the SSE stream is established, so mail arriving between connect and stream establishment is not lost; `seenEmailIds` deduplicates the overlap.
14
+ - Event stream errors/end → silent fallback to `Email/changes` polling on `pollIntervalMs`. `cannotCalculateChanges` → full re-query resync.
15
+ - `connect()` emits 'error' instead of throwing (mirrors smartimap). Unlike smartimap, the same instance may call `connect()` again — JMAP is stateless HTTP.
16
+ - `disconnect()` aborts the SSE fetch and clears the poll timer; the connect-failure path also tears both down, so no handles leak either way.
17
+
18
+ ## RFC subset covered (1.0.0)
19
+
20
+ - RFC 8620: session resource, method calls/responses, `error` method responses, RFC 7807 problem details, `#creationId` back-references (client-side use; server resolves them in EmailSubmission/set), download URL template expansion, event source (SSE StateChange).
21
+ - RFC 8621: Mailbox/get(+query on server), Email/query, Email/get with `fetchAllBodyValues`, Email/changes, Email/set (create/update with keyword patches/destroy), Identity/get, EmailSubmission/set.
22
+
23
+ ## Known gaps
24
+
25
+ - No upload endpoint / Blob upload (`uploadUrl` is advertised by the test server but not implemented), so `sendEmail` supports text/html bodies but not attachments.
26
+ - No Thread/*, SearchSnippet/*, VacationResponse/*, Mailbox/set, Mailbox/changes, EmailSubmission onSuccessUpdateEmail, or result references (`resultOf`) — the client issues explicit-id calls instead.
27
+ - `Email/get` on the test server ignores the `properties` projection and always returns the full superset; `Email/query` supports only `inMailbox`/`subject`/`text` filters and `receivedAt` sorting.
28
+ - The client requests event-source pushes with `types=*` and reacts to Email state changes only; Mailbox counters are not tracked incrementally.
29
+ - Initial-sweep race: an email created between the Email/query and Email/get of the sweep is picked up by the following delta fetch, not the sweep itself (dedupe prevents double emission).
30
+
31
+ ## By-design unbounded state (accepted)
32
+
33
+ - Client: `seenEmailIds` retains every emitted email id for the instance lifetime — required for dedupe across reconnects and sweep/delta overlap; on a very long-lived, high-volume connection this grows without a pruning hook. Recreate the client to reset it.
34
+ - Test server (in-memory helper, not production code): the per-account change log grows one entry per mutation (needed by `Email/changes`), destroyed emails leave their blobs in the blob store, and request bodies are buffered without enforcing the advertised `maxSizeRequest`.
package/readme.md ADDED
@@ -0,0 +1,287 @@
1
+ # @push.rocks/smartjmap
2
+
3
+ A TypeScript JMAP client for reading, sending, and watching mail via the JSON Meta Application Protocol (RFC 8620/8621), with a bundled test server for offline testing.
4
+
5
+ ## Install
6
+
7
+ To install `@push.rocks/smartjmap`, use pnpm (or npm):
8
+
9
+ ```sh
10
+ pnpm install @push.rocks/smartjmap
11
+ ```
12
+
13
+ The package has zero runtime dependencies — it uses the global `fetch` available in Node.js 18+.
14
+
15
+ ## Usage
16
+
17
+ `@push.rocks/smartjmap` connects to any JMAP server (Fastmail, Stalwart, Cyrus, ...), watches a mailbox for new mail in an event-driven way, and exposes the common mail operations: querying, reading, flagging, sending, and blob downloads.
18
+
19
+ ### Importing the Required Modules
20
+
21
+ ```typescript
22
+ import { JmapClient, type IJmapClientConfig } from '@push.rocks/smartjmap';
23
+ ```
24
+
25
+ ### Configuration Object
26
+
27
+ Point the client at the JMAP session resource — most servers expose it at the autodiscovery path `https://host/.well-known/jmap`. All URLs inside the session (API endpoint, download URL, event source) are resolved relative to this URL automatically.
28
+
29
+ ```typescript
30
+ const jmapConfig: IJmapClientConfig = {
31
+ sessionUrl: 'https://jmap.example.com/.well-known/jmap',
32
+ auth: {
33
+ accessToken: 'my-api-token',
34
+ },
35
+ mailbox: 'INBOX', // default: resolved via Mailbox role 'inbox', falling back to a name match
36
+ pollIntervalMs: 30000, // fallback polling cadence when the event stream is unavailable
37
+ };
38
+ ```
39
+
40
+ ### Authentication: Bearer and Basic
41
+
42
+ The `auth` option accepts exactly one of two shapes:
43
+
44
+ ```typescript
45
+ import { JmapClient } from '@push.rocks/smartjmap';
46
+
47
+ // Bearer token (OAuth2 access token or server API token)
48
+ const bearerClient = new JmapClient({
49
+ sessionUrl: 'https://jmap.example.com/.well-known/jmap',
50
+ auth: {
51
+ accessToken: 'my-api-token',
52
+ },
53
+ });
54
+
55
+ // Basic auth (username + password)
56
+ const basicClient = new JmapClient({
57
+ sessionUrl: 'https://jmap.example.com/.well-known/jmap',
58
+ auth: {
59
+ user: 'user@example.com',
60
+ pass: 'password123',
61
+ },
62
+ });
63
+ ```
64
+
65
+ Passing both shapes at once (or neither) throws at construction time.
66
+
67
+ ### Connecting and Handling Events
68
+
69
+ `connect()` fetches and validates the JMAP session (the `urn:ietf:params:jmap:core` and `urn:ietf:params:jmap:mail` capabilities are required), resolves the target mailbox, and emits `connected`. It then emits a `message` event for every email currently in the mailbox and keeps watching for new mail: it prefers the JMAP event source (Server-Sent Events, RFC 8620 §7.3) and falls back to polling `Email/changes` on `pollIntervalMs` when the event stream is unavailable.
70
+
71
+ ```typescript
72
+ import { JmapClient, type ISmartJmapMessage } from '@push.rocks/smartjmap';
73
+
74
+ const jmapClient = new JmapClient({
75
+ sessionUrl: 'https://jmap.example.com/.well-known/jmap',
76
+ auth: { accessToken: 'my-api-token' },
77
+ });
78
+
79
+ jmapClient.on('connected', () => {
80
+ console.log('Connected to the JMAP server');
81
+ });
82
+
83
+ jmapClient.on('message', (message: ISmartJmapMessage) => {
84
+ console.log('From:', message.from[0]?.email);
85
+ console.log('Subject:', message.subject);
86
+ console.log('Text:', message.textBody);
87
+ });
88
+
89
+ jmapClient.on('error', (error: Error) => {
90
+ console.error('JMAP error:', error);
91
+ });
92
+
93
+ jmapClient.on('disconnected', () => {
94
+ console.log('Disconnected');
95
+ });
96
+
97
+ await jmapClient.connect();
98
+ ```
99
+
100
+ ### The Message Shape
101
+
102
+ Every `message` event (and the query/get helpers) delivers an `ISmartJmapMessage` with resolved bodies:
103
+
104
+ ```typescript
105
+ jmapClient.on('message', (message: ISmartJmapMessage) => {
106
+ message.id; // JMAP Email id
107
+ message.blobId; // blob id of the raw RFC 5322 message
108
+ message.threadId; // JMAP Thread id
109
+ message.mailboxIds; // { [mailboxId]: true }
110
+ message.keywords; // { '$seen': true, ... }
111
+ message.from; // IJmapEmailAddress[]
112
+ message.to; // IJmapEmailAddress[] (cc, bcc, replyTo likewise)
113
+ message.subject; // string | undefined
114
+ message.receivedAt; // ISO date string
115
+ message.textBody; // plain-text body, resolved from bodyValues
116
+ message.htmlBody; // HTML body, undefined when the email has no text/html part
117
+ message.attachments; // IJmapAttachment[]: { blobId, name, type, size }
118
+ message.raw; // the full raw JMAP Email object
119
+ });
120
+ ```
121
+
122
+ ### Querying and Reading Mail
123
+
124
+ ```typescript
125
+ // All mailboxes of the account
126
+ const mailboxes = await jmapClient.getMailboxes();
127
+
128
+ // Emails in the watched mailbox, newest first (default filter)
129
+ const messages = await jmapClient.queryEmails();
130
+
131
+ // Custom JMAP filter (RFC 8621 §4.4.1) and limit
132
+ const invoices = await jmapClient.queryEmails({ subject: 'Invoice' }, 10);
133
+
134
+ // Single email with all body values fetched (fetchAllBodyValues)
135
+ const message = await jmapClient.getEmail(messages[0].id);
136
+ ```
137
+
138
+ ### Flags and Keywords
139
+
140
+ ```typescript
141
+ // Convenience: set the $seen keyword
142
+ await jmapClient.markSeen(message.id);
143
+
144
+ // Replace the full keywords object
145
+ await jmapClient.setKeywords(message.id, { $seen: true, $flagged: true });
146
+ ```
147
+
148
+ ### Sending Mail
149
+
150
+ `sendEmail` looks up the account's identities via `Identity/get`, creates the email via `Email/set` (stored in the mailbox with role `sent`, falling back to `drafts`, then the watched mailbox), and submits it via `EmailSubmission/set`:
151
+
152
+ ```typescript
153
+ const result = await jmapClient.sendEmail({
154
+ to: [{ email: 'friend@example.com' }],
155
+ subject: 'Hello from JMAP',
156
+ textBody: 'Plain-text content',
157
+ htmlBody: '<p>HTML content</p>', // optional
158
+ });
159
+ console.log(result.emailId, result.submissionId);
160
+ ```
161
+
162
+ When `from` is omitted, the first identity of the account is used.
163
+
164
+ ### Downloading Blobs
165
+
166
+ Raw messages and attachments are blobs; download them via the session's download URL template:
167
+
168
+ ```typescript
169
+ // the raw RFC 5322 message
170
+ const rawBytes = await jmapClient.downloadBlob(message.blobId, 'message/rfc822', 'message.eml');
171
+
172
+ // an attachment
173
+ for (const attachment of message.attachments) {
174
+ const bytes = await jmapClient.downloadBlob(attachment.blobId, attachment.type, attachment.name);
175
+ console.log(attachment.name, bytes.length);
176
+ }
177
+ ```
178
+
179
+ ### Raw JMAP Method Calls
180
+
181
+ For anything not covered by the helpers, `request` sends raw JMAP method calls (RFC 8620 §3.2) and returns the method responses:
182
+
183
+ ```typescript
184
+ const methodResponses = await jmapClient.request([
185
+ ['Mailbox/query', { accountId: 'account-id', filter: { role: 'archive' } }, 'q0'],
186
+ ]);
187
+ ```
188
+
189
+ ### Disconnecting
190
+
191
+ ```typescript
192
+ await jmapClient.disconnect();
193
+ ```
194
+
195
+ `disconnect()` tears down the event stream and any polling timer — no handles are left open — and emits `disconnected`.
196
+
197
+ ### The Bundled Test Server
198
+
199
+ `JmapServer` is a minimal in-memory JMAP server for offline tests. It serves the session resource at `/.well-known/jmap` (and `/jmap/session`), the API at `/jmap/api`, blob downloads, and StateChange pushes via SSE at `/jmap/eventsource`. It validates Bearer and Basic auth and answers unauthenticated requests with `401` + `WWW-Authenticate`.
200
+
201
+ ```typescript
202
+ import { JmapClient, JmapServer } from '@push.rocks/smartjmap';
203
+
204
+ const jmapServer = new JmapServer();
205
+ jmapServer.addUser('testuser', 'testpass');
206
+ jmapServer.addBearerToken('testuser', 'test-token');
207
+ jmapServer.createMailbox('testuser', 'INBOX', 'inbox');
208
+ jmapServer.addEmail('testuser', 'INBOX', {
209
+ from: { email: 'alice@example.com' },
210
+ to: { email: 'testuser@example.com' },
211
+ subject: 'Welcome',
212
+ textBody: 'Hello from the test server!',
213
+ });
214
+
215
+ const port = await jmapServer.start(0); // resolves with the bound port
216
+
217
+ const client = new JmapClient({
218
+ sessionUrl: `http://127.0.0.1:${port}/.well-known/jmap`,
219
+ auth: { accessToken: 'test-token' },
220
+ });
221
+ client.on('message', (message) => console.log(message.subject));
222
+ await client.connect();
223
+
224
+ // Emails added while a client is connected are pushed via SSE:
225
+ jmapServer.addEmail('testuser', 'INBOX', {
226
+ from: { email: 'bob@example.com' },
227
+ to: { email: 'testuser@example.com' },
228
+ subject: 'Live push',
229
+ textBody: 'Delivered through the event stream.',
230
+ });
231
+
232
+ await client.disconnect();
233
+ await jmapServer.stop(); // closes the server and destroys open connections
234
+ ```
235
+
236
+ The dispatched methods are `Core/echo`, `Mailbox/get`, `Mailbox/query`, `Email/get`, `Email/query`, `Email/changes`, `Email/set`, `Identity/get`, and `EmailSubmission/set` — enough for every public `JmapClient` method to run offline.
237
+
238
+ ### Error Handling
239
+
240
+ `connect()` never throws; failures (unreachable host, wrong credentials, missing capabilities) are emitted as `error` events, and the instance holds no open sockets or timers afterwards. HTTP problem details (RFC 7807) and JMAP method-level errors are surfaced as `JmapError` with `httpStatus`, `problemType`, `problemDetail`, `jmapErrorType`, and `jmapErrorDescription` fields.
241
+
242
+ Because JMAP is stateless HTTP, the same client instance can reconnect — call `connect()` again after a failure. Already-emitted messages are deduplicated, so a reconnect does not re-emit mail the client has already seen. While connected, the client recovers on its own: if the event stream drops, it silently falls back to `Email/changes` polling, and a `cannotCalculateChanges` response triggers a full re-query.
243
+
244
+ ```typescript
245
+ import { JmapClient, JmapError } from '@push.rocks/smartjmap';
246
+
247
+ const client = new JmapClient({
248
+ sessionUrl: 'https://jmap.example.com/.well-known/jmap',
249
+ auth: { accessToken: 'my-api-token' },
250
+ });
251
+
252
+ client.on('error', (error: Error) => {
253
+ if (error instanceof JmapError && error.httpStatus === 401) {
254
+ console.error('Credentials rejected — refresh the token before reconnecting.');
255
+ return;
256
+ }
257
+ console.error('JMAP error, retrying in 10s:', error.message);
258
+ setTimeout(() => {
259
+ client.connect().catch(console.error);
260
+ }, 10000);
261
+ });
262
+
263
+ await client.connect();
264
+ ```
265
+
266
+ ## Issue Reporting and Security
267
+
268
+ For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly.
269
+
270
+ ## License and Legal Information
271
+
272
+ This repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository.
273
+
274
+ **Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
275
+
276
+ ### Trademarks
277
+
278
+ This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.
279
+
280
+ ### Company Information
281
+
282
+ Task Venture Capital GmbH
283
+ Registered at District court Bremen HRB 35230 HB, Germany
284
+
285
+ For any legal inquiries or if you require further information, please contact us via email at hello@task.vc.
286
+
287
+ By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
@@ -0,0 +1,8 @@
1
+ /**
2
+ * autocreated commitinfo by @push.rocks/commitinfo
3
+ */
4
+ export const commitinfo = {
5
+ name: '@push.rocks/smartjmap',
6
+ version: '1.0.0',
7
+ description: 'A TypeScript JMAP client for reading, sending, and watching mail via the JSON Meta Application Protocol (RFC 8620/8621), with a bundled test server for offline testing.'
8
+ }