jmap-kit 0.0.0 → 1.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/LICENSE +21 -0
- package/README.md +138 -3
- package/dist/src/capabilities/blob/blob.d.ts +83 -0
- package/dist/src/capabilities/blob/blob.js +98 -0
- package/dist/src/capabilities/blob/blob.js.map +1 -0
- package/dist/src/capabilities/blob/types.d.ts +212 -0
- package/dist/src/capabilities/blob/types.js +16 -0
- package/dist/src/capabilities/blob/types.js.map +1 -0
- package/dist/src/capabilities/blob-capability.d.ts +195 -0
- package/dist/src/capabilities/blob-capability.js +277 -0
- package/dist/src/capabilities/blob-capability.js.map +1 -0
- package/dist/src/capabilities/core/core.d.ts +47 -0
- package/dist/src/capabilities/core/core.js +59 -0
- package/dist/src/capabilities/core/core.js.map +1 -0
- package/dist/src/capabilities/core/types.d.ts +13 -0
- package/dist/src/capabilities/core/types.js +2 -0
- package/dist/src/capabilities/core/types.js.map +1 -0
- package/dist/src/capabilities/core-capability.d.ts +307 -0
- package/dist/src/capabilities/core-capability.js +344 -0
- package/dist/src/capabilities/core-capability.js.map +1 -0
- package/dist/src/capabilities/email/email.d.ts +124 -0
- package/dist/src/capabilities/email/email.js +136 -0
- package/dist/src/capabilities/email/email.js.map +1 -0
- package/dist/src/capabilities/email/types.d.ts +776 -0
- package/dist/src/capabilities/email/types.js +2 -0
- package/dist/src/capabilities/email/types.js.map +1 -0
- package/dist/src/capabilities/email-capability.d.ts +266 -0
- package/dist/src/capabilities/email-capability.js +241 -0
- package/dist/src/capabilities/email-capability.js.map +1 -0
- package/dist/src/capabilities/emailsubmission/emailsubmission.d.ts +95 -0
- package/dist/src/capabilities/emailsubmission/emailsubmission.js +107 -0
- package/dist/src/capabilities/emailsubmission/emailsubmission.js.map +1 -0
- package/dist/src/capabilities/emailsubmission/types.d.ts +256 -0
- package/dist/src/capabilities/emailsubmission/types.js +2 -0
- package/dist/src/capabilities/emailsubmission/types.js.map +1 -0
- package/dist/src/capabilities/example/example.d.ts +80 -0
- package/dist/src/capabilities/example/example.js +91 -0
- package/dist/src/capabilities/example/example.js.map +1 -0
- package/dist/src/capabilities/example/types.d.ts +33 -0
- package/dist/src/capabilities/example/types.js +2 -0
- package/dist/src/capabilities/example/types.js.map +1 -0
- package/dist/src/capabilities/identity/identity.d.ts +71 -0
- package/dist/src/capabilities/identity/identity.js +83 -0
- package/dist/src/capabilities/identity/identity.js.map +1 -0
- package/dist/src/capabilities/identity/types.d.ts +110 -0
- package/dist/src/capabilities/identity/types.js +2 -0
- package/dist/src/capabilities/identity/types.js.map +1 -0
- package/dist/src/capabilities/mailbox/mailbox.d.ts +91 -0
- package/dist/src/capabilities/mailbox/mailbox.js +103 -0
- package/dist/src/capabilities/mailbox/mailbox.js.map +1 -0
- package/dist/src/capabilities/mailbox/types.d.ts +248 -0
- package/dist/src/capabilities/mailbox/types.js +2 -0
- package/dist/src/capabilities/mailbox/types.js.map +1 -0
- package/dist/src/capabilities/maskedemail/maskedemail.d.ts +60 -0
- package/dist/src/capabilities/maskedemail/maskedemail.js +72 -0
- package/dist/src/capabilities/maskedemail/maskedemail.js.map +1 -0
- package/dist/src/capabilities/maskedemail/types.d.ts +67 -0
- package/dist/src/capabilities/maskedemail/types.js +4 -0
- package/dist/src/capabilities/maskedemail/types.js.map +1 -0
- package/dist/src/capabilities/maskedemail-capability.d.ts +112 -0
- package/dist/src/capabilities/maskedemail-capability.js +166 -0
- package/dist/src/capabilities/maskedemail-capability.js.map +1 -0
- package/dist/src/capabilities/searchsnippet/searchsnippet.d.ts +51 -0
- package/dist/src/capabilities/searchsnippet/searchsnippet.js +63 -0
- package/dist/src/capabilities/searchsnippet/searchsnippet.js.map +1 -0
- package/dist/src/capabilities/searchsnippet/types.d.ts +88 -0
- package/dist/src/capabilities/searchsnippet/types.js +2 -0
- package/dist/src/capabilities/searchsnippet/types.js.map +1 -0
- package/dist/src/capabilities/submission-capability.d.ts +89 -0
- package/dist/src/capabilities/submission-capability.js +75 -0
- package/dist/src/capabilities/submission-capability.js.map +1 -0
- package/dist/src/capabilities/thread/thread.d.ts +58 -0
- package/dist/src/capabilities/thread/thread.js +70 -0
- package/dist/src/capabilities/thread/thread.js.map +1 -0
- package/dist/src/capabilities/thread/types.d.ts +43 -0
- package/dist/src/capabilities/thread/types.js +2 -0
- package/dist/src/capabilities/thread/types.js.map +1 -0
- package/dist/src/capabilities/utils/assert-invocation-datatype.d.ts +7 -0
- package/dist/src/capabilities/utils/assert-invocation-datatype.js +13 -0
- package/dist/src/capabilities/utils/assert-invocation-datatype.js.map +1 -0
- package/dist/src/capabilities/utils/assert-invocation-method.d.ts +7 -0
- package/dist/src/capabilities/utils/assert-invocation-method.js +13 -0
- package/dist/src/capabilities/utils/assert-invocation-method.js.map +1 -0
- package/dist/src/capabilities/utils/assert-invocation.d.ts +7 -0
- package/dist/src/capabilities/utils/assert-invocation.js +22 -0
- package/dist/src/capabilities/utils/assert-invocation.js.map +1 -0
- package/dist/src/capabilities/utils/assert-non-nullish.d.ts +1 -0
- package/dist/src/capabilities/utils/assert-non-nullish.js +6 -0
- package/dist/src/capabilities/utils/assert-non-nullish.js.map +1 -0
- package/dist/src/capabilities/utils/create-readonly-account-validator.d.ts +49 -0
- package/dist/src/capabilities/utils/create-readonly-account-validator.js +80 -0
- package/dist/src/capabilities/utils/create-readonly-account-validator.js.map +1 -0
- package/dist/src/capabilities/vacationresponse/types.d.ts +100 -0
- package/dist/src/capabilities/vacationresponse/types.js +2 -0
- package/dist/src/capabilities/vacationresponse/types.js.map +1 -0
- package/dist/src/capabilities/vacationresponse/vacationresponse.d.ts +61 -0
- package/dist/src/capabilities/vacationresponse/vacationresponse.js +73 -0
- package/dist/src/capabilities/vacationresponse/vacationresponse.js.map +1 -0
- package/dist/src/capabilities/vacationresponse-capability.d.ts +65 -0
- package/dist/src/capabilities/vacationresponse-capability.js +68 -0
- package/dist/src/capabilities/vacationresponse-capability.js.map +1 -0
- package/dist/src/capability-registry/capability-registry.d.ts +148 -0
- package/dist/src/capability-registry/capability-registry.js +360 -0
- package/dist/src/capability-registry/capability-registry.js.map +1 -0
- package/dist/src/capability-registry/types.d.ts +385 -0
- package/dist/src/capability-registry/types.js +2 -0
- package/dist/src/capability-registry/types.js.map +1 -0
- package/dist/src/capability-registry/utils.d.ts +71 -0
- package/dist/src/capability-registry/utils.js +163 -0
- package/dist/src/capability-registry/utils.js.map +1 -0
- package/dist/src/common/registry.d.ts +366 -0
- package/dist/src/common/registry.js +321 -0
- package/dist/src/common/registry.js.map +1 -0
- package/dist/src/common/types.d.ts +338 -0
- package/dist/src/common/types.js +21 -0
- package/dist/src/common/types.js.map +1 -0
- package/dist/src/common/utils.d.ts +20 -0
- package/dist/src/common/utils.js +26 -0
- package/dist/src/common/utils.js.map +1 -0
- package/dist/src/index.d.ts +40 -0
- package/dist/src/index.js +33 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/invocation/arguments-proxy.d.ts +14 -0
- package/dist/src/invocation/arguments-proxy.js +37 -0
- package/dist/src/invocation/arguments-proxy.js.map +1 -0
- package/dist/src/invocation/error-invocation.d.ts +27 -0
- package/dist/src/invocation/error-invocation.js +39 -0
- package/dist/src/invocation/error-invocation.js.map +1 -0
- package/dist/src/invocation/invocation.d.ts +111 -0
- package/dist/src/invocation/invocation.js +158 -0
- package/dist/src/invocation/invocation.js.map +1 -0
- package/dist/src/invocation/result-reference.d.ts +86 -0
- package/dist/src/invocation/result-reference.js +118 -0
- package/dist/src/invocation/result-reference.js.map +1 -0
- package/dist/src/invocation/types.d.ts +637 -0
- package/dist/src/invocation/types.js +2 -0
- package/dist/src/invocation/types.js.map +1 -0
- package/dist/src/invocation/utils.d.ts +21 -0
- package/dist/src/invocation/utils.js +30 -0
- package/dist/src/invocation/utils.js.map +1 -0
- package/dist/src/invocation-factory/invocation-factory-manager.d.ts +20 -0
- package/dist/src/invocation-factory/invocation-factory-manager.js +50 -0
- package/dist/src/invocation-factory/invocation-factory-manager.js.map +1 -0
- package/dist/src/invocation-factory/invocation-list.d.ts +32 -0
- package/dist/src/invocation-factory/invocation-list.js +77 -0
- package/dist/src/invocation-factory/invocation-list.js.map +1 -0
- package/dist/src/invocation-factory/types.d.ts +11 -0
- package/dist/src/invocation-factory/types.js +2 -0
- package/dist/src/invocation-factory/types.js.map +1 -0
- package/dist/src/jmap-client/jmap-client.d.ts +252 -0
- package/dist/src/jmap-client/jmap-client.js +777 -0
- package/dist/src/jmap-client/jmap-client.js.map +1 -0
- package/dist/src/jmap-client/types.d.ts +427 -0
- package/dist/src/jmap-client/types.js +21 -0
- package/dist/src/jmap-client/types.js.map +1 -0
- package/dist/src/jmap-client/utils/abort-controller.d.ts +8 -0
- package/dist/src/jmap-client/utils/abort-controller.js +24 -0
- package/dist/src/jmap-client/utils/abort-controller.js.map +1 -0
- package/dist/src/jmap-client/utils/assert-connected.d.ts +7 -0
- package/dist/src/jmap-client/utils/assert-connected.js +11 -0
- package/dist/src/jmap-client/utils/assert-connected.js.map +1 -0
- package/dist/src/jmap-client/utils/deep-freeze.d.ts +7 -0
- package/dist/src/jmap-client/utils/deep-freeze.js +17 -0
- package/dist/src/jmap-client/utils/deep-freeze.js.map +1 -0
- package/dist/src/jmap-client/utils/emitter.d.ts +9 -0
- package/dist/src/jmap-client/utils/emitter.js +18 -0
- package/dist/src/jmap-client/utils/emitter.js.map +1 -0
- package/dist/src/jmap-client/utils/filter-session-capabilities.d.ts +22 -0
- package/dist/src/jmap-client/utils/filter-session-capabilities.js +40 -0
- package/dist/src/jmap-client/utils/filter-session-capabilities.js.map +1 -0
- package/dist/src/jmap-client/utils/jmap-request-error.d.ts +28 -0
- package/dist/src/jmap-client/utils/jmap-request-error.js +48 -0
- package/dist/src/jmap-client/utils/jmap-request-error.js.map +1 -0
- package/dist/src/jmap-client/utils/logger.d.ts +6 -0
- package/dist/src/jmap-client/utils/logger.js +22 -0
- package/dist/src/jmap-client/utils/logger.js.map +1 -0
- package/dist/src/jmap-client/utils/merge-headers.d.ts +11 -0
- package/dist/src/jmap-client/utils/merge-headers.js +40 -0
- package/dist/src/jmap-client/utils/merge-headers.js.map +1 -0
- package/dist/src/jmap-client/utils/template-utils.d.ts +27 -0
- package/dist/src/jmap-client/utils/template-utils.js +61 -0
- package/dist/src/jmap-client/utils/template-utils.js.map +1 -0
- package/dist/src/jmap-client/utils/track-utils.d.ts +19 -0
- package/dist/src/jmap-client/utils/track-utils.js +35 -0
- package/dist/src/jmap-client/utils/track-utils.js.map +1 -0
- package/dist/src/jmap-client/utils/transport.d.ts +12 -0
- package/dist/src/jmap-client/utils/transport.js +38 -0
- package/dist/src/jmap-client/utils/transport.js.map +1 -0
- package/dist/src/jmap-client/utils/validate-session.d.ts +19 -0
- package/dist/src/jmap-client/utils/validate-session.js +29 -0
- package/dist/src/jmap-client/utils/validate-session.js.map +1 -0
- package/dist/src/request-builder/request-builder.d.ts +95 -0
- package/dist/src/request-builder/request-builder.js +343 -0
- package/dist/src/request-builder/request-builder.js.map +1 -0
- package/dist/src/request-builder/types.d.ts +32 -0
- package/dist/src/request-builder/types.js +2 -0
- package/dist/src/request-builder/types.js.map +1 -0
- package/package.json +69 -3
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { ValidationPlugin } from "../capability-registry/types.js";
|
|
2
|
+
import { VACATIONRESPONSE_CAPABILITY_URI } from "../common/registry.js";
|
|
3
|
+
/**
|
|
4
|
+
* Validates that invocations using the VacationResponse capability have a valid accountId that
|
|
5
|
+
* supports the VacationResponse capability.
|
|
6
|
+
*
|
|
7
|
+
* This plugin performs three critical validation checks:
|
|
8
|
+
* 1. Verifies the invocation includes a valid `accountId` argument (non-empty string)
|
|
9
|
+
* 2. Confirms the account exists in the session's accounts collection
|
|
10
|
+
* 3. Ensures the account's `accountCapabilities` includes the VacationResponse capability URI
|
|
11
|
+
*
|
|
12
|
+
* This validation applies to all VacationResponse capability invocations (VacationResponse/get
|
|
13
|
+
* and VacationResponse/set) and implements the account capability checks described in
|
|
14
|
+
* RFC 8621 Section 1.3.3.
|
|
15
|
+
*
|
|
16
|
+
* @see {@link https://www.rfc-editor.org/rfc/rfc8621.html#section-1.3.3 | RFC 8621 Section 1.3.3: The VacationResponse Capability}
|
|
17
|
+
*/
|
|
18
|
+
export declare const vacationResponseAccountSupportPlugin: ValidationPlugin<"invocation">;
|
|
19
|
+
/**
|
|
20
|
+
* Defines the VacationResponse capability, including the VacationResponse invocations and
|
|
21
|
+
* validation plugins.
|
|
22
|
+
*
|
|
23
|
+
* Per RFC 8621 Section 1.3.3, the `urn:ietf:params:jmap:vacationresponse` capability represents
|
|
24
|
+
* support for the VacationResponse data type and associated API methods.
|
|
25
|
+
*
|
|
26
|
+
* Read-only account protection for VacationResponse/set is handled by Core's generic
|
|
27
|
+
* `preventSetOnReadOnlyAccountPlugin`.
|
|
28
|
+
*
|
|
29
|
+
* @see {@link https://www.rfc-editor.org/rfc/rfc8621.html#section-1.3.3 | RFC 8621 Section 1.3.3: The VacationResponse Capability}
|
|
30
|
+
*/
|
|
31
|
+
export declare const VacationResponseCapability: {
|
|
32
|
+
uri: "urn:ietf:params:jmap:vacationresponse";
|
|
33
|
+
invocations: {
|
|
34
|
+
VacationResponse: {
|
|
35
|
+
request: {
|
|
36
|
+
get: import("../index.js").InvocationFactory<import("./vacationresponse/types.js").VacationResponseGetRequestInvocationArgs, import("./vacationresponse/vacationresponse.js").VacationResponseInvocation<import("./vacationresponse/types.js").VacationResponseGetRequestInvocationArgs>>;
|
|
37
|
+
set: import("../index.js").InvocationFactory<import("./vacationresponse/types.js").VacationResponseSetRequestInvocationArgs, import("./vacationresponse/vacationresponse.js").VacationResponseInvocation<import("./vacationresponse/types.js").VacationResponseSetRequestInvocationArgs>>;
|
|
38
|
+
};
|
|
39
|
+
response: {
|
|
40
|
+
get: import("../index.js").InvocationFactory<import("./vacationresponse/types.js").VacationResponseGetResponseInvocationArgs, import("./vacationresponse/vacationresponse.js").VacationResponseInvocation<import("./vacationresponse/types.js").VacationResponseGetResponseInvocationArgs>>;
|
|
41
|
+
set: import("../index.js").InvocationFactory<import("./vacationresponse/types.js").VacationResponseSetResponseInvocationArgs, import("./vacationresponse/vacationresponse.js").VacationResponseInvocation<import("./vacationresponse/types.js").VacationResponseSetResponseInvocationArgs>>;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
validators: {
|
|
46
|
+
name: string;
|
|
47
|
+
hook: "invocation";
|
|
48
|
+
trigger: {
|
|
49
|
+
capabilityUri?: import("../index.js").JMAPCapability;
|
|
50
|
+
dataType?: import("../index.js").JMAPDataType;
|
|
51
|
+
method?: import("../index.js").JMAPMethodName;
|
|
52
|
+
};
|
|
53
|
+
validate(this: void, context: import("../capability-registry/types.js").BasePluginContext & {
|
|
54
|
+
invocation: import("../index.js").Invocation<import("../index.js").BaseInvocationArgs>;
|
|
55
|
+
}): import("../index.js").MaybePromise<import("../capability-registry/types.js").ValidationResult>;
|
|
56
|
+
}[];
|
|
57
|
+
};
|
|
58
|
+
declare module "../common/types.js" {
|
|
59
|
+
interface ServerCapabilityRegistry {
|
|
60
|
+
[VACATIONRESPONSE_CAPABILITY_URI]?: EmptyObject;
|
|
61
|
+
}
|
|
62
|
+
interface AccountCapabilityRegistry {
|
|
63
|
+
[VACATIONRESPONSE_CAPABILITY_URI]?: EmptyObject;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { VACATIONRESPONSE_CAPABILITY_URI } from "../common/registry.js";
|
|
2
|
+
import { VacationResponse } from "./vacationresponse/vacationresponse.js";
|
|
3
|
+
/**
|
|
4
|
+
* Validates that invocations using the VacationResponse capability have a valid accountId that
|
|
5
|
+
* supports the VacationResponse capability.
|
|
6
|
+
*
|
|
7
|
+
* This plugin performs three critical validation checks:
|
|
8
|
+
* 1. Verifies the invocation includes a valid `accountId` argument (non-empty string)
|
|
9
|
+
* 2. Confirms the account exists in the session's accounts collection
|
|
10
|
+
* 3. Ensures the account's `accountCapabilities` includes the VacationResponse capability URI
|
|
11
|
+
*
|
|
12
|
+
* This validation applies to all VacationResponse capability invocations (VacationResponse/get
|
|
13
|
+
* and VacationResponse/set) and implements the account capability checks described in
|
|
14
|
+
* RFC 8621 Section 1.3.3.
|
|
15
|
+
*
|
|
16
|
+
* @see {@link https://www.rfc-editor.org/rfc/rfc8621.html#section-1.3.3 | RFC 8621 Section 1.3.3: The VacationResponse Capability}
|
|
17
|
+
*/
|
|
18
|
+
export const vacationResponseAccountSupportPlugin = {
|
|
19
|
+
name: "vacationresponse-account-support",
|
|
20
|
+
hook: "invocation",
|
|
21
|
+
trigger: {
|
|
22
|
+
capabilityUri: VACATIONRESPONSE_CAPABILITY_URI,
|
|
23
|
+
},
|
|
24
|
+
validate(context) {
|
|
25
|
+
const { invocation, accounts } = context;
|
|
26
|
+
const accountId = invocation.getArgument("accountId");
|
|
27
|
+
if (typeof accountId !== "string" || accountId === "") {
|
|
28
|
+
return {
|
|
29
|
+
valid: false,
|
|
30
|
+
errors: [new Error(`Invocation is missing a valid accountId argument.`)],
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
const account = accounts[accountId];
|
|
34
|
+
if (!account) {
|
|
35
|
+
return {
|
|
36
|
+
valid: false,
|
|
37
|
+
errors: [new Error(`Account "${accountId}" does not exist.`)],
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
if (!account.accountCapabilities[VACATIONRESPONSE_CAPABILITY_URI]) {
|
|
41
|
+
return {
|
|
42
|
+
valid: false,
|
|
43
|
+
errors: [new Error(`Account "${accountId}" does not support the VacationResponse capability.`)],
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return { valid: true };
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Defines the VacationResponse capability, including the VacationResponse invocations and
|
|
51
|
+
* validation plugins.
|
|
52
|
+
*
|
|
53
|
+
* Per RFC 8621 Section 1.3.3, the `urn:ietf:params:jmap:vacationresponse` capability represents
|
|
54
|
+
* support for the VacationResponse data type and associated API methods.
|
|
55
|
+
*
|
|
56
|
+
* Read-only account protection for VacationResponse/set is handled by Core's generic
|
|
57
|
+
* `preventSetOnReadOnlyAccountPlugin`.
|
|
58
|
+
*
|
|
59
|
+
* @see {@link https://www.rfc-editor.org/rfc/rfc8621.html#section-1.3.3 | RFC 8621 Section 1.3.3: The VacationResponse Capability}
|
|
60
|
+
*/
|
|
61
|
+
export const VacationResponseCapability = {
|
|
62
|
+
uri: VACATIONRESPONSE_CAPABILITY_URI,
|
|
63
|
+
invocations: {
|
|
64
|
+
VacationResponse,
|
|
65
|
+
},
|
|
66
|
+
validators: [vacationResponseAccountSupportPlugin],
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=vacationresponse-capability.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vacationresponse-capability.js","sourceRoot":"","sources":["../../../src/capabilities/vacationresponse-capability.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,+BAA+B,EAAE,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAE1E;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,oCAAoC,GAAmC;IAChF,IAAI,EAAE,kCAAkC;IACxC,IAAI,EAAE,YAAY;IAClB,OAAO,EAAE;QACL,aAAa,EAAE,+BAA+B;KACjD;IACD,QAAQ,CAAC,OAAO;QACZ,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;QACzC,MAAM,SAAS,GAAG,UAAU,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;QACtD,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,KAAK,EAAE,EAAE,CAAC;YACpD,OAAO;gBACH,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,CAAC,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;aAC3E,CAAC;QACN,CAAC;QACD,MAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;QACpC,IAAI,CAAC,OAAO,EAAE,CAAC;YACX,OAAO;gBACH,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,CAAC,IAAI,KAAK,CAAC,YAAY,SAAS,mBAAmB,CAAC,CAAC;aAChE,CAAC;QACN,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,+BAA+B,CAAC,EAAE,CAAC;YAChE,OAAO;gBACH,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,CAAC,IAAI,KAAK,CAAC,YAAY,SAAS,qDAAqD,CAAC,CAAC;aAClG,CAAC;QACN,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;CACJ,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACtC,GAAG,EAAE,+BAA+B;IACpC,WAAW,EAAE;QACT,gBAAgB;KACnB;IACD,UAAU,EAAE,CAAC,oCAAoC,CAAC;CACtB,CAAC"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import type { JMAPCapability, JMAPDataType, JMAPMethodName } from "../common/types.js";
|
|
2
|
+
import type { GenericInvocationFactory, InvocationFactoryCollection } from "../invocation/types.js";
|
|
3
|
+
import type { ClientContext } from "../jmap-client/types.js";
|
|
4
|
+
import type { AccountCapabilityValidationResult, CapabilityDefinition, CapabilityRegistryInterface, PluginData, PluginLifecycleHook, ServerCapabilityValidationResult, TransformationPlugin, TransformerExecutionContext, ValidationPlugin, ValidationPluginLifecycleHook, ValidationResult, ValidatorExecutionContext } from "./types.js";
|
|
5
|
+
/**
|
|
6
|
+
* Registry for managing JMAP capabilities
|
|
7
|
+
*
|
|
8
|
+
* The registry stores capability definitions and provides methods to register,
|
|
9
|
+
* unregister, and query capabilities.
|
|
10
|
+
* The Core capability is always registered and cannot be unregistered.
|
|
11
|
+
*/
|
|
12
|
+
export declare class CapabilityRegistry implements CapabilityRegistryInterface {
|
|
13
|
+
#private;
|
|
14
|
+
/**
|
|
15
|
+
* Creates a new CapabilityRegistry
|
|
16
|
+
*
|
|
17
|
+
* @param coreCapability The Core capability definition that will always be registered
|
|
18
|
+
* @param options Integration options including logger
|
|
19
|
+
*/
|
|
20
|
+
constructor(coreCapability: CapabilityDefinition, { logger }: ClientContext);
|
|
21
|
+
/**
|
|
22
|
+
* Register a capability with the registry
|
|
23
|
+
*
|
|
24
|
+
* @param capability The capability definition to register
|
|
25
|
+
* @returns true if the capability was registered, false if it was already registered
|
|
26
|
+
*/
|
|
27
|
+
register(capability: CapabilityDefinition): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Check if a capability is registered
|
|
30
|
+
*
|
|
31
|
+
* @param uri The URI of the capability to check
|
|
32
|
+
* @returns true if the capability is registered, false otherwise
|
|
33
|
+
*/
|
|
34
|
+
has(uri: JMAPCapability): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Get a registered capability by URI
|
|
37
|
+
*
|
|
38
|
+
* @param uri The URI of the capability to get
|
|
39
|
+
* @returns The capability definition, or undefined if not registered
|
|
40
|
+
*/
|
|
41
|
+
get(uri: JMAPCapability): CapabilityDefinition | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* Get all registered capabilities
|
|
44
|
+
*
|
|
45
|
+
* @returns An array of all registered capability definitions
|
|
46
|
+
*/
|
|
47
|
+
getAll(): CapabilityDefinition[];
|
|
48
|
+
/**
|
|
49
|
+
* Get all registered validation plugins for a specific hook
|
|
50
|
+
*
|
|
51
|
+
* @param hook The lifecycle hook to get validators for
|
|
52
|
+
* @returns An array of validation plugins for the specified hook
|
|
53
|
+
*/
|
|
54
|
+
getValidatorsByHook<THook extends ValidationPluginLifecycleHook>(hook: THook): ValidationPlugin<THook>[];
|
|
55
|
+
/**
|
|
56
|
+
* Get all registered transformation plugins for a specific hook
|
|
57
|
+
*
|
|
58
|
+
* @param hook The lifecycle hook to get transformers for
|
|
59
|
+
* @returns An array of transformation plugins for the specified hook
|
|
60
|
+
*/
|
|
61
|
+
getTransformersByHook<THook extends Exclude<PluginLifecycleHook, "pre-build">>(hook: THook): TransformationPlugin<THook>[];
|
|
62
|
+
/**
|
|
63
|
+
* Execute validators for the specified hook type
|
|
64
|
+
*
|
|
65
|
+
* Validates the provided context data against all registered validation plugins
|
|
66
|
+
* for the specified hook type.
|
|
67
|
+
*
|
|
68
|
+
* @param execution The validation execution context containing hook type and context data
|
|
69
|
+
* @returns A ValidationResult indicating whether the validation was successful or failed with errors
|
|
70
|
+
*/
|
|
71
|
+
executeValidators<THook extends ValidationPluginLifecycleHook>({ hook, context, }: ValidatorExecutionContext<THook>): Promise<ValidationResult>;
|
|
72
|
+
/**
|
|
73
|
+
* Execute transformers for the pre-serialization hook
|
|
74
|
+
*
|
|
75
|
+
* @param options The transformer execution context containing hook type and context data
|
|
76
|
+
* @param options.hook The lifecycle hook to execute transformers for
|
|
77
|
+
* @param options.context The context data to transform
|
|
78
|
+
* @returns A Promise resolving to the transformed data
|
|
79
|
+
*/
|
|
80
|
+
executeBuildTransformers({ hook, context, }: TransformerExecutionContext<"pre-serialization">): Promise<PluginData<"pre-serialization">>;
|
|
81
|
+
/**
|
|
82
|
+
* Execute transformers for the post-serialization hook
|
|
83
|
+
*
|
|
84
|
+
* @param options The transformer execution context containing hook type and context data
|
|
85
|
+
* @param options.hook The lifecycle hook to execute transformers for
|
|
86
|
+
* @param options.context The context data to transform
|
|
87
|
+
* @returns A Promise resolving to the transformed data
|
|
88
|
+
*/
|
|
89
|
+
executeSerializationTransformers({ hook, context, }: TransformerExecutionContext<"post-serialization">): Promise<PluginData<"post-serialization">>;
|
|
90
|
+
/**
|
|
91
|
+
* Get the invocation factory collection for a specific data type
|
|
92
|
+
*
|
|
93
|
+
* @param dataType The JMAP data type to get factories for
|
|
94
|
+
* @returns The invocation factory collection for the data type, or undefined if not registered
|
|
95
|
+
*/
|
|
96
|
+
getInvocationFactoryByDataType(dataType: JMAPDataType): InvocationFactoryCollection | undefined;
|
|
97
|
+
/**
|
|
98
|
+
* Get a specific invocation request factory by data type and method name
|
|
99
|
+
*
|
|
100
|
+
* @param dataType The JMAP data type
|
|
101
|
+
* @param methodName The JMAP method name
|
|
102
|
+
* @returns The invocation request factory function, or undefined if not found
|
|
103
|
+
*/
|
|
104
|
+
getInvocationRequestFactory(dataType: JMAPDataType, methodName: JMAPMethodName): GenericInvocationFactory | undefined;
|
|
105
|
+
/**
|
|
106
|
+
* Get a specific invocation response factory by data type and method name
|
|
107
|
+
*
|
|
108
|
+
* @param dataType The JMAP data type
|
|
109
|
+
* @param methodName The JMAP method name
|
|
110
|
+
* @returns The invocation response factory function, or undefined if not found
|
|
111
|
+
*/
|
|
112
|
+
getInvocationResponseFactory(dataType: JMAPDataType, methodName: JMAPMethodName): GenericInvocationFactory | undefined;
|
|
113
|
+
/**
|
|
114
|
+
* Validate server capability data against registered capability schemas.
|
|
115
|
+
*
|
|
116
|
+
* @param capabilities The server capabilities object from the parsed JMAP session
|
|
117
|
+
* @returns An array of validation failures (empty if all capabilities are valid)
|
|
118
|
+
*/
|
|
119
|
+
validateServerCapabilities(capabilities: Record<string, unknown>): Promise<ServerCapabilityValidationResult[]>;
|
|
120
|
+
/**
|
|
121
|
+
* Validate account capability data against registered capability schemas.
|
|
122
|
+
*
|
|
123
|
+
* @param accounts The accounts object from the parsed JMAP session
|
|
124
|
+
* @returns An array of validation failures (empty if all account capabilities are valid)
|
|
125
|
+
*/
|
|
126
|
+
validateAccountCapabilities(accounts: Record<string, {
|
|
127
|
+
accountCapabilities: Record<string, unknown>;
|
|
128
|
+
}>): Promise<AccountCapabilityValidationResult[]>;
|
|
129
|
+
/**
|
|
130
|
+
* Validate a single capability definition's schemas against session data
|
|
131
|
+
* without requiring the capability to be registered.
|
|
132
|
+
*
|
|
133
|
+
* @param capability The capability definition to validate
|
|
134
|
+
* @param serverCapabilities The server capabilities from the session
|
|
135
|
+
* @param accounts The accounts from the session
|
|
136
|
+
* @returns An object containing arrays of server and account capability validation failures
|
|
137
|
+
*/
|
|
138
|
+
validateCapabilityDefinition(capability: CapabilityDefinition, serverCapabilities: Record<string, unknown>, accounts: Record<string, {
|
|
139
|
+
accountCapabilities: Record<string, unknown>;
|
|
140
|
+
}>): Promise<{
|
|
141
|
+
serverCapabilities: Extract<ServerCapabilityValidationResult, {
|
|
142
|
+
valid: false;
|
|
143
|
+
}>[];
|
|
144
|
+
accountCapabilities: Extract<AccountCapabilityValidationResult, {
|
|
145
|
+
valid: false;
|
|
146
|
+
}>[];
|
|
147
|
+
}>;
|
|
148
|
+
}
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
import { CORE_CAPABILITY_URI } from "../common/registry.js";
|
|
2
|
+
import { transformBuild, transformSerialization, validateInvocation, validateLifecycleHook, validateSerialization, } from "./utils.js";
|
|
3
|
+
/**
|
|
4
|
+
* Registry for managing JMAP capabilities
|
|
5
|
+
*
|
|
6
|
+
* The registry stores capability definitions and provides methods to register,
|
|
7
|
+
* unregister, and query capabilities.
|
|
8
|
+
* The Core capability is always registered and cannot be unregistered.
|
|
9
|
+
*/
|
|
10
|
+
export class CapabilityRegistry {
|
|
11
|
+
#capabilities = new Map();
|
|
12
|
+
#logger;
|
|
13
|
+
#validationPlugins = {
|
|
14
|
+
invocation: new Set(),
|
|
15
|
+
"pre-build": new Set(),
|
|
16
|
+
"pre-serialization": new Set(),
|
|
17
|
+
"post-serialization": new Set(),
|
|
18
|
+
};
|
|
19
|
+
#transformationPlugins = {
|
|
20
|
+
"pre-serialization": new Set(),
|
|
21
|
+
"post-serialization": new Set(),
|
|
22
|
+
};
|
|
23
|
+
#invocationFactories = new Map();
|
|
24
|
+
/**
|
|
25
|
+
* Creates a new CapabilityRegistry
|
|
26
|
+
*
|
|
27
|
+
* @param coreCapability The Core capability definition that will always be registered
|
|
28
|
+
* @param options Integration options including logger
|
|
29
|
+
*/
|
|
30
|
+
constructor(coreCapability, { logger }) {
|
|
31
|
+
if (coreCapability.uri !== CORE_CAPABILITY_URI) {
|
|
32
|
+
throw new Error(`Core capability URI mismatch: expected ${CORE_CAPABILITY_URI}, got ${coreCapability.uri}`);
|
|
33
|
+
}
|
|
34
|
+
this.#logger = logger;
|
|
35
|
+
this.#capabilities.set(CORE_CAPABILITY_URI, coreCapability);
|
|
36
|
+
this.#initializePluginMaps(coreCapability);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Initialise the plugin arrays with plugins from a capability
|
|
40
|
+
*
|
|
41
|
+
* @param capability The capability definition to add plugins from
|
|
42
|
+
*/
|
|
43
|
+
#initializePluginMaps(capability) {
|
|
44
|
+
this.#addValidatorsFromCapability(capability);
|
|
45
|
+
this.#addTransformersFromCapability(capability);
|
|
46
|
+
this.#addInvocationFactoriesFromCapability(capability);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Add validators from a capability to the validators arrays
|
|
50
|
+
*
|
|
51
|
+
* @param capability The capability definition to add validators from
|
|
52
|
+
*/
|
|
53
|
+
#addValidatorsFromCapability(capability) {
|
|
54
|
+
const validators = capability.validators ?? [];
|
|
55
|
+
// Sort validators by hook
|
|
56
|
+
for (const validator of validators) {
|
|
57
|
+
switch (validator.hook) {
|
|
58
|
+
case "pre-build": {
|
|
59
|
+
this.#logger.debug(`Adding pre-build validator: ${validator.name}`);
|
|
60
|
+
this.#validationPlugins["pre-build"].add(validator);
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
case "pre-serialization": {
|
|
64
|
+
this.#logger.debug(`Adding pre-serialization validator: ${validator.name}`);
|
|
65
|
+
this.#validationPlugins["pre-serialization"].add(validator);
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
case "post-serialization": {
|
|
69
|
+
this.#logger.debug(`Adding post-serialization validator: ${validator.name}`);
|
|
70
|
+
this.#validationPlugins["post-serialization"].add(validator);
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
case "invocation": {
|
|
74
|
+
this.#logger.debug(`Adding invocation validator: ${validator.name}`);
|
|
75
|
+
this.#validationPlugins.invocation.add(validator);
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Add transformers from a capability to the transformers arrays
|
|
83
|
+
*
|
|
84
|
+
* @param capability The capability definition to add transformers from
|
|
85
|
+
*/
|
|
86
|
+
#addTransformersFromCapability(capability) {
|
|
87
|
+
const transformers = capability.transformers ?? [];
|
|
88
|
+
// Sort transformers by hook
|
|
89
|
+
for (const transformer of transformers) {
|
|
90
|
+
if (transformer.hook === "pre-serialization") {
|
|
91
|
+
this.#transformationPlugins["pre-serialization"].add(transformer);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
this.#transformationPlugins["post-serialization"].add(transformer);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Add invocation factories from a capability to the invocation factory map
|
|
100
|
+
*
|
|
101
|
+
* This handles the special case where Blob data type methods can come from multiple capabilities.
|
|
102
|
+
* The Core capability includes Blob/copy, but other Blob methods may come from a separate
|
|
103
|
+
* Blob capability with a different URI.
|
|
104
|
+
*
|
|
105
|
+
* @param capability The capability definition to add invocation factories from
|
|
106
|
+
*/
|
|
107
|
+
#addInvocationFactoriesFromCapability(capability) {
|
|
108
|
+
for (const [dataType, factoryCollection] of Object.entries(capability.invocations)) {
|
|
109
|
+
if (!factoryCollection)
|
|
110
|
+
continue;
|
|
111
|
+
const typedDataType = dataType;
|
|
112
|
+
const existingCollection = this.#invocationFactories.get(typedDataType);
|
|
113
|
+
if (existingCollection) {
|
|
114
|
+
// Merge with existing collection (for cases like Blob methods from multiple capabilities)
|
|
115
|
+
this.#logger.debug(`Merging invocation factories for data type: ${dataType}`);
|
|
116
|
+
// Merge request factories
|
|
117
|
+
Object.assign(existingCollection.request, factoryCollection.request);
|
|
118
|
+
// Merge response factories
|
|
119
|
+
Object.assign(existingCollection.response, factoryCollection.response);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
// Add new collection (create shallow copy to maintain immutability)
|
|
123
|
+
this.#logger.debug(`Adding invocation factory collection for data type: ${dataType}`);
|
|
124
|
+
const collectionCopy = {
|
|
125
|
+
request: { ...factoryCollection.request },
|
|
126
|
+
response: { ...factoryCollection.response },
|
|
127
|
+
};
|
|
128
|
+
this.#invocationFactories.set(typedDataType, collectionCopy);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Register a capability with the registry
|
|
134
|
+
*
|
|
135
|
+
* @param capability The capability definition to register
|
|
136
|
+
* @returns true if the capability was registered, false if it was already registered
|
|
137
|
+
*/
|
|
138
|
+
register(capability) {
|
|
139
|
+
if (this.#capabilities.has(capability.uri)) {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
this.#capabilities.set(capability.uri, capability);
|
|
143
|
+
this.#initializePluginMaps(capability);
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Check if a capability is registered
|
|
148
|
+
*
|
|
149
|
+
* @param uri The URI of the capability to check
|
|
150
|
+
* @returns true if the capability is registered, false otherwise
|
|
151
|
+
*/
|
|
152
|
+
has(uri) {
|
|
153
|
+
return this.#capabilities.has(uri);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Get a registered capability by URI
|
|
157
|
+
*
|
|
158
|
+
* @param uri The URI of the capability to get
|
|
159
|
+
* @returns The capability definition, or undefined if not registered
|
|
160
|
+
*/
|
|
161
|
+
get(uri) {
|
|
162
|
+
return this.#capabilities.get(uri);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Get all registered capabilities
|
|
166
|
+
*
|
|
167
|
+
* @returns An array of all registered capability definitions
|
|
168
|
+
*/
|
|
169
|
+
getAll() {
|
|
170
|
+
return Array.from(this.#capabilities.values());
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Get all registered validation plugins for a specific hook
|
|
174
|
+
*
|
|
175
|
+
* @param hook The lifecycle hook to get validators for
|
|
176
|
+
* @returns An array of validation plugins for the specified hook
|
|
177
|
+
*/
|
|
178
|
+
getValidatorsByHook(hook) {
|
|
179
|
+
return Array.from(this.#validationPlugins[hook]);
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Get all registered transformation plugins for a specific hook
|
|
183
|
+
*
|
|
184
|
+
* @param hook The lifecycle hook to get transformers for
|
|
185
|
+
* @returns An array of transformation plugins for the specified hook
|
|
186
|
+
*/
|
|
187
|
+
getTransformersByHook(hook) {
|
|
188
|
+
return Array.from(this.#transformationPlugins[hook]);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Execute validators for the specified hook type
|
|
192
|
+
*
|
|
193
|
+
* Validates the provided context data against all registered validation plugins
|
|
194
|
+
* for the specified hook type.
|
|
195
|
+
*
|
|
196
|
+
* @param execution The validation execution context containing hook type and context data
|
|
197
|
+
* @returns A ValidationResult indicating whether the validation was successful or failed with errors
|
|
198
|
+
*/
|
|
199
|
+
executeValidators({ hook, context, }) {
|
|
200
|
+
// Check which hook type we're dealing with and call the appropriate method
|
|
201
|
+
if (hook === "invocation") {
|
|
202
|
+
const validators = this.getValidatorsByHook(hook);
|
|
203
|
+
return validateInvocation(context, validators);
|
|
204
|
+
}
|
|
205
|
+
else if (hook === "post-serialization") {
|
|
206
|
+
const validators = this.getValidatorsByHook(hook);
|
|
207
|
+
return validateSerialization(context, validators);
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
// For pre-build and pre-serialization hooks
|
|
211
|
+
const validators = this.getValidatorsByHook(hook);
|
|
212
|
+
return validateLifecycleHook(hook, context, validators);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Execute transformers for the pre-serialization hook
|
|
217
|
+
*
|
|
218
|
+
* @param options The transformer execution context containing hook type and context data
|
|
219
|
+
* @param options.hook The lifecycle hook to execute transformers for
|
|
220
|
+
* @param options.context The context data to transform
|
|
221
|
+
* @returns A Promise resolving to the transformed data
|
|
222
|
+
*/
|
|
223
|
+
executeBuildTransformers({ hook = "pre-serialization", context, }) {
|
|
224
|
+
const transformers = this.getTransformersByHook(hook);
|
|
225
|
+
return transformBuild(context, transformers);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Execute transformers for the post-serialization hook
|
|
229
|
+
*
|
|
230
|
+
* @param options The transformer execution context containing hook type and context data
|
|
231
|
+
* @param options.hook The lifecycle hook to execute transformers for
|
|
232
|
+
* @param options.context The context data to transform
|
|
233
|
+
* @returns A Promise resolving to the transformed data
|
|
234
|
+
*/
|
|
235
|
+
executeSerializationTransformers({ hook = "post-serialization", context, }) {
|
|
236
|
+
const transformers = this.getTransformersByHook(hook);
|
|
237
|
+
return transformSerialization(context, transformers);
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Get the invocation factory collection for a specific data type
|
|
241
|
+
*
|
|
242
|
+
* @param dataType The JMAP data type to get factories for
|
|
243
|
+
* @returns The invocation factory collection for the data type, or undefined if not registered
|
|
244
|
+
*/
|
|
245
|
+
getInvocationFactoryByDataType(dataType) {
|
|
246
|
+
return this.#invocationFactories.get(dataType);
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Get a specific invocation request factory by data type and method name
|
|
250
|
+
*
|
|
251
|
+
* @param dataType The JMAP data type
|
|
252
|
+
* @param methodName The JMAP method name
|
|
253
|
+
* @returns The invocation request factory function, or undefined if not found
|
|
254
|
+
*/
|
|
255
|
+
getInvocationRequestFactory(dataType, methodName) {
|
|
256
|
+
const collection = this.#invocationFactories.get(dataType);
|
|
257
|
+
if (!collection) {
|
|
258
|
+
return undefined;
|
|
259
|
+
}
|
|
260
|
+
return collection.request[methodName];
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Get a specific invocation response factory by data type and method name
|
|
264
|
+
*
|
|
265
|
+
* @param dataType The JMAP data type
|
|
266
|
+
* @param methodName The JMAP method name
|
|
267
|
+
* @returns The invocation response factory function, or undefined if not found
|
|
268
|
+
*/
|
|
269
|
+
getInvocationResponseFactory(dataType, methodName) {
|
|
270
|
+
const collection = this.#invocationFactories.get(dataType);
|
|
271
|
+
if (!collection) {
|
|
272
|
+
return undefined;
|
|
273
|
+
}
|
|
274
|
+
return collection.response[methodName];
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Validate server capability data against registered capability schemas.
|
|
278
|
+
*
|
|
279
|
+
* @param capabilities The server capabilities object from the parsed JMAP session
|
|
280
|
+
* @returns An array of validation failures (empty if all capabilities are valid)
|
|
281
|
+
*/
|
|
282
|
+
async validateServerCapabilities(capabilities) {
|
|
283
|
+
const pending = [];
|
|
284
|
+
for (const { uri, schema } of this.#capabilities.values()) {
|
|
285
|
+
if (!schema?.serverCapability || !(uri in capabilities))
|
|
286
|
+
continue;
|
|
287
|
+
pending.push(CapabilityRegistry.#validateWithStandardSchema(schema.serverCapability, capabilities[uri]).then((result) => ({ ...result, uri })));
|
|
288
|
+
}
|
|
289
|
+
return Promise.all(pending);
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Validate account capability data against registered capability schemas.
|
|
293
|
+
*
|
|
294
|
+
* @param accounts The accounts object from the parsed JMAP session
|
|
295
|
+
* @returns An array of validation failures (empty if all account capabilities are valid)
|
|
296
|
+
*/
|
|
297
|
+
async validateAccountCapabilities(accounts) {
|
|
298
|
+
const pending = [];
|
|
299
|
+
for (const { uri, schema } of this.#capabilities.values()) {
|
|
300
|
+
if (!schema?.accountCapability)
|
|
301
|
+
continue;
|
|
302
|
+
for (const [accountId, account] of Object.entries(accounts)) {
|
|
303
|
+
if (!(uri in account.accountCapabilities))
|
|
304
|
+
continue;
|
|
305
|
+
pending.push(CapabilityRegistry.#validateWithStandardSchema(schema.accountCapability, account.accountCapabilities[uri]).then((result) => ({ ...result, uri, accountId })));
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return Promise.all(pending);
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Validate a single capability definition's schemas against session data
|
|
312
|
+
* without requiring the capability to be registered.
|
|
313
|
+
*
|
|
314
|
+
* @param capability The capability definition to validate
|
|
315
|
+
* @param serverCapabilities The server capabilities from the session
|
|
316
|
+
* @param accounts The accounts from the session
|
|
317
|
+
* @returns An object containing arrays of server and account capability validation failures
|
|
318
|
+
*/
|
|
319
|
+
async validateCapabilityDefinition(capability, serverCapabilities, accounts) {
|
|
320
|
+
const serverFailures = [];
|
|
321
|
+
const accountFailures = [];
|
|
322
|
+
const { uri, schema } = capability;
|
|
323
|
+
// Validate server capability schema
|
|
324
|
+
if (schema?.serverCapability && uri in serverCapabilities) {
|
|
325
|
+
const result = await CapabilityRegistry.#validateWithStandardSchema(schema.serverCapability, serverCapabilities[uri]);
|
|
326
|
+
if (!result.valid) {
|
|
327
|
+
serverFailures.push({ ...result, uri });
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
// Validate account capability schema
|
|
331
|
+
if (schema?.accountCapability) {
|
|
332
|
+
for (const [accountId, account] of Object.entries(accounts)) {
|
|
333
|
+
if (!(uri in account.accountCapabilities))
|
|
334
|
+
continue;
|
|
335
|
+
const result = await CapabilityRegistry.#validateWithStandardSchema(schema.accountCapability, account.accountCapabilities[uri]);
|
|
336
|
+
if (!result.valid) {
|
|
337
|
+
accountFailures.push({ ...result, uri, accountId });
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return { serverCapabilities: serverFailures, accountCapabilities: accountFailures };
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Validate a value against a StandardSchema and return a ValidationResult.
|
|
345
|
+
*/
|
|
346
|
+
static async #validateWithStandardSchema(schema, value) {
|
|
347
|
+
const result = await schema["~standard"].validate(value);
|
|
348
|
+
if (result.issues) {
|
|
349
|
+
return {
|
|
350
|
+
valid: false,
|
|
351
|
+
errors: result.issues.map((issue) => {
|
|
352
|
+
const path = issue.path?.map((p) => (typeof p === "object" ? p.key : p)).join(".") ?? "";
|
|
353
|
+
return new Error(path ? `${path}: ${issue.message}` : issue.message);
|
|
354
|
+
}),
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
return { valid: true };
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
//# sourceMappingURL=capability-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability-registry.js","sourceRoot":"","sources":["../../../src/capability-registry/capability-registry.ts"],"names":[],"mappings":"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"}
|