mailschema 0.2.2 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -119
- package/bin/mailschema.js +42 -53
- package/dist/context.jsonld +50 -0
- package/dist/contract.schema.json +206 -0
- package/dist/core/artifacts.d.ts +11 -36
- package/dist/core/artifacts.js +21 -69
- package/dist/core/bundled.d.ts +4 -4
- package/dist/core/bundled.js +7 -7
- package/dist/core/contract.d.ts +59 -56
- package/dist/core/contract.js +224 -298
- package/dist/core/description.d.ts +45 -0
- package/dist/core/description.js +47 -0
- package/dist/core/implementation.d.ts +32 -0
- package/dist/core/implementation.js +25 -0
- package/dist/core/index.d.ts +7 -6
- package/dist/core/index.js +9 -9
- package/dist/core/json.d.ts +23 -0
- package/dist/core/{document.js → json.js} +61 -51
- package/dist/core/patterns.d.ts +12 -0
- package/dist/core/patterns.js +165 -0
- package/dist/core/sha256.d.ts +2 -0
- package/dist/core/sha256.js +59 -0
- package/dist/core.schema.json +210 -0
- package/dist/implementation.schema.json +173 -0
- package/dist/index.d.ts +4 -9
- package/dist/index.js +2 -14
- package/dist/profile.json +27 -0
- package/package.json +9 -10
- package/dist/contribution.schema.json +0 -874
- package/dist/core/binding.d.ts +0 -24
- package/dist/core/binding.js +0 -50
- package/dist/core/document.d.ts +0 -24
- package/dist/core/documents.d.ts +0 -68
- package/dist/core/documents.js +0 -145
- package/dist/core/limits.d.ts +0 -19
- package/dist/core/limits.js +0 -55
- package/dist/core/pointer.d.ts +0 -12
- package/dist/core/pointer.js +0 -48
- package/dist/core/schemas.d.ts +0 -21
- package/dist/core/schemas.js +0 -125
- package/dist/core/types.d.ts +0 -127
- package/dist/core/types.js +0 -2
- package/dist/forms-0.1.schema.json +0 -329
- package/dist/map-0.2.jsonld +0 -91
- package/dist/map-0.2.schema.json +0 -1033
- package/dist/map.d.ts +0 -8
- package/dist/map.js +0 -18
- package/dist/model.d.ts +0 -95
- package/dist/model.js +0 -5
- package/dist/type-contract-0.2.schema.json +0 -179
- package/dist/validation.d.ts +0 -15
- package/dist/validation.js +0 -64
package/dist/core/artifacts.js
CHANGED
|
@@ -1,78 +1,30 @@
|
|
|
1
|
-
//
|
|
1
|
+
// MAP 0.3's identifiers, limits and schema validation.
|
|
2
2
|
import Ajv2020 from 'ajv/dist/2020.js';
|
|
3
|
-
import
|
|
4
|
-
export
|
|
5
|
-
export const
|
|
6
|
-
export const
|
|
7
|
-
|
|
8
|
-
export const
|
|
9
|
-
export const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
]
|
|
3
|
+
import addFormats from 'ajv-formats';
|
|
4
|
+
export { coreSchema, contractSchema, implementationSchema } from "./bundled.js";
|
|
5
|
+
export const PROFILE = 'https://mailschema.org/profiles/map/0.3';
|
|
6
|
+
export const CONTEXT = 'https://mailschema.org/contexts/map-0.3.jsonld';
|
|
7
|
+
/** The Content-Type of the MIME part that carries a description. */
|
|
8
|
+
export const DESCRIPTION_MEDIA_TYPE = `application/ld+json; profile="${PROFILE}"`;
|
|
9
|
+
export const DESCRIPTION_MAX_BYTES = 65536;
|
|
10
|
+
export const CONTRACT_MAX_BYTES = 262144;
|
|
11
|
+
/** The namespace of the initial effect vocabulary. */
|
|
12
|
+
export const EFFECTS = 'https://mailschema.org/effects/';
|
|
13
|
+
/** The formats MAP schemas may assert. Every implementation checks exactly these. */
|
|
14
|
+
export const FORMATS = ['date', 'date-time', 'email', 'uri'];
|
|
15
15
|
/**
|
|
16
|
-
* JSON Schema 2020-12 as MAP reads it
|
|
17
|
-
*
|
|
18
|
-
*
|
|
16
|
+
* JSON Schema 2020-12 as MAP reads it: the listed formats asserted, and references resolved
|
|
17
|
+
* only within the schema, never over the network. MAP's own rules decide which keywords and
|
|
18
|
+
* formats a contract may use; the validator adds no checks of its own beyond the vocabulary.
|
|
19
19
|
* @internal
|
|
20
20
|
*/
|
|
21
21
|
export function createValidator() {
|
|
22
|
-
const ajv = new Ajv2020({
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
strictRequired: false,
|
|
26
|
-
validateFormats: false,
|
|
27
|
-
});
|
|
28
|
-
// HTML autofill field names label form fields; they are annotations, not assertions.
|
|
29
|
-
ajv.addKeyword({ keyword: 'autocomplete', schemaType: 'string' });
|
|
30
|
-
// Only JSON Schema 2020-12 vocabulary keywords. Ajv also reads OpenAPI's `nullable`,
|
|
31
|
-
// which admits a null other validators refuse, and the earlier `dependencies` and
|
|
32
|
-
// `definitions`; strict mode now refuses them as unknown.
|
|
22
|
+
const ajv = new Ajv2020({ allErrors: true, strict: false });
|
|
23
|
+
addFormats(ajv, [...FORMATS]);
|
|
24
|
+
// Ajv also reads OpenAPI's `nullable` and the earlier `dependencies` and `definitions`.
|
|
33
25
|
for (const keyword of ['nullable', 'dependencies', 'definitions'])
|
|
34
26
|
ajv.removeKeyword(keyword);
|
|
35
|
-
for (const schema of BUNDLED.values())
|
|
36
|
-
ajv.addSchema(schema);
|
|
37
27
|
return ajv;
|
|
38
28
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
export const definition = (schema, name) => core.getSchema(`${schema}#/$defs/${name}`);
|
|
42
|
-
/** Errors as `pointer message` lines, as the other MailSchema packages report them. */
|
|
43
|
-
export function errorList(errors, prefix = '') {
|
|
44
|
-
return (errors ?? [])
|
|
45
|
-
.slice(0, 100)
|
|
46
|
-
.map((error) => `${prefix + error.instancePath || '/'} ${error.message}${error.keyword === 'required' ? `: ${error.params.missingProperty}` : ''}`);
|
|
47
|
-
}
|
|
48
|
-
const errorsOf = (validate, value) => validate(value) ? [] : errorList(validate.errors);
|
|
49
|
-
const DOCUMENT = core.getSchema(CORE_SCHEMA);
|
|
50
|
-
const DEFINITIONS = Object.fromEntries(['description', 'request', 'result', 'problem'].map((name) => [
|
|
51
|
-
name,
|
|
52
|
-
definition(CORE_SCHEMA, name),
|
|
53
|
-
]));
|
|
54
|
-
const DATE_TIME = new RegExp(coreSchema.$defs.dateTime.pattern, 'u');
|
|
55
|
-
const REQUEST_ID = definition(CORE_SCHEMA, 'uuidUrn');
|
|
56
|
-
const CONTRACT = core.compile(contractFormat);
|
|
57
|
-
/** Checks a type contract against the contract format. */
|
|
58
|
-
export const contractFormatErrors = (contract) => errorsOf(CONTRACT, contract);
|
|
59
|
-
/** Checks any MAP 0.2 description, request, result or problem against the core schema. */
|
|
60
|
-
export const mapErrors = (document) => errorsOf(DOCUMENT, document);
|
|
61
|
-
/**
|
|
62
|
-
* Checks a description against the core description definition only. A description of a
|
|
63
|
-
* type the caller has no contract for can be checked this far.
|
|
64
|
-
*/
|
|
65
|
-
export const descriptionErrors = (description) => errorsOf(DEFINITIONS.description, description);
|
|
66
|
-
/** Checks a request against the core request definition. Its identifier stays free if it fails. */
|
|
67
|
-
export const requestErrors = (request) => errorsOf(DEFINITIONS.request, request);
|
|
68
|
-
/** Checks a result against the core result definition only. */
|
|
69
|
-
export const resultErrors = (result) => errorsOf(DEFINITIONS.result, result);
|
|
70
|
-
/** Checks a problem against the core problem definition, including its type, status and code. */
|
|
71
|
-
export const problemErrors = (problem) => errorsOf(DEFINITIONS.problem, problem);
|
|
72
|
-
/** Whether a value is a request identifier: the core UUID URN form. Only one names a result resource. */
|
|
73
|
-
export const isRequestId = (value) => REQUEST_ID(value);
|
|
74
|
-
/**
|
|
75
|
-
* Whether a deadline, a core date-time plus `afterSeconds`, has been reached. Anything but
|
|
76
|
-
* a core date-time counts as reached, so a mistake fails closed.
|
|
77
|
-
*/
|
|
78
|
-
export const reached = (now, deadline, afterSeconds = 0) => !(DATE_TIME.test(deadline) && now.getTime() < Date.parse(deadline) + afterSeconds * 1000);
|
|
29
|
+
/** Each validation error as its JSON Pointer and message. @internal */
|
|
30
|
+
export const schemaErrors = (errors, prefix = '') => (errors ?? []).map((error) => `${prefix + error.instancePath || '/'}: ${error.message}`);
|
package/dist/core/bundled.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import coreSchema from '../
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
export { coreSchema,
|
|
1
|
+
import coreSchema from '../core.schema.json';
|
|
2
|
+
import contractSchema from '../contract.schema.json';
|
|
3
|
+
import implementationSchema from '../implementation.schema.json';
|
|
4
|
+
export { coreSchema, contractSchema, implementationSchema };
|
package/dist/core/bundled.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
// The
|
|
2
|
-
// imports at the package's own copies; no other line differs between the
|
|
3
|
-
// the npm package.
|
|
4
|
-
import coreSchema from '../
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
export { coreSchema,
|
|
1
|
+
// The schemas the 0.3 profile record binds, by their canonical files. Package preparation
|
|
2
|
+
// points these three imports at the package's own copies; no other line differs between the
|
|
3
|
+
// repository and the npm package.
|
|
4
|
+
import coreSchema from '../core.schema.json' with { type: 'json' };
|
|
5
|
+
import contractSchema from '../contract.schema.json' with { type: 'json' };
|
|
6
|
+
import implementationSchema from '../implementation.schema.json' with { type: 'json' };
|
|
7
|
+
export { coreSchema, contractSchema, implementationSchema };
|
package/dist/core/contract.d.ts
CHANGED
|
@@ -1,66 +1,69 @@
|
|
|
1
|
-
import type
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { type Description } from './description.ts';
|
|
2
|
+
export interface Operation {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
semantics: string;
|
|
6
|
+
effects: string[];
|
|
7
|
+
bindings: ('credential' | 'capability')[];
|
|
8
|
+
actors: ('human' | 'agent')[];
|
|
9
|
+
exactTerms: boolean;
|
|
10
|
+
inputSchema: Record<string, unknown> | null;
|
|
11
|
+
outcomes: Record<string, string>;
|
|
12
|
+
capability?: {
|
|
13
|
+
kind: CapabilityKind;
|
|
14
|
+
maxLifetimeSeconds: number;
|
|
15
|
+
};
|
|
5
16
|
}
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
17
|
+
export interface ContractDocument {
|
|
18
|
+
id: string;
|
|
19
|
+
version: string;
|
|
20
|
+
profile: string;
|
|
21
|
+
name: string;
|
|
22
|
+
summary: string;
|
|
23
|
+
requirements: string[];
|
|
24
|
+
detailsSchema: Record<string, unknown>;
|
|
25
|
+
operations: Operation[];
|
|
26
|
+
}
|
|
27
|
+
export type CapabilityKind = keyof typeof CAPABILITY_KINDS;
|
|
28
|
+
/** The capability binding's kinds: the exact effects each declares and its longest lifetime. */
|
|
29
|
+
export declare const CAPABILITY_KINDS: {
|
|
30
|
+
readonly refusal: {
|
|
31
|
+
readonly effects: readonly ["refusal", "state"];
|
|
32
|
+
readonly maxLifetimeSeconds: 604800;
|
|
33
|
+
};
|
|
34
|
+
readonly 'protective-report': {
|
|
35
|
+
readonly effects: readonly ["protection", "state"];
|
|
36
|
+
readonly maxLifetimeSeconds: 259200;
|
|
37
|
+
};
|
|
38
|
+
readonly 'address-confirmation': {
|
|
39
|
+
readonly effects: readonly ["assertion", "state"];
|
|
40
|
+
readonly maxLifetimeSeconds: 86400;
|
|
41
|
+
};
|
|
13
42
|
};
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
* type. The Registry has already applied the contract rules, such as portable patterns, to
|
|
18
|
-
* the contract that digest names; loading refuses anything that would otherwise fail when a
|
|
19
|
-
* request arrives.
|
|
20
|
-
*/
|
|
43
|
+
/** Why the value is not a MAP 0.3 type contract, or no reasons. */
|
|
44
|
+
export declare function contractErrors(value: unknown): string[];
|
|
45
|
+
/** A valid contract with its digest and compiled schemas. */
|
|
21
46
|
export declare class Contract {
|
|
22
47
|
#private;
|
|
23
|
-
readonly document:
|
|
48
|
+
readonly document: ContractDocument;
|
|
49
|
+
/** `sha-256:` and the SHA-256 of the contract's RFC 8785 form. */
|
|
24
50
|
readonly digest: string;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
*/
|
|
30
|
-
constructor(contract: unknown, requestSchema: unknown, { digest: pinned, dependencies, }: {
|
|
31
|
-
digest: string;
|
|
32
|
-
dependencies?: Record<string, unknown>;
|
|
33
|
-
});
|
|
51
|
+
/** The contract, or InvalidDocument with every reason the value is not one. */
|
|
52
|
+
constructor(value: unknown);
|
|
53
|
+
/** The contract in the bytes or text, read as MAP JSON within the contract limit. */
|
|
54
|
+
static parse(input: string | Uint8Array): Contract;
|
|
34
55
|
get id(): string;
|
|
35
56
|
get version(): string;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Every rule a description must satisfy beyond the core schema, for the service that issues
|
|
43
|
-
* it and the client that receives it.
|
|
44
|
-
*/
|
|
45
|
-
descriptionErrors(description: unknown): string[];
|
|
46
|
-
/**
|
|
47
|
-
* The checks a service makes on a request once it has resolved the description it issued,
|
|
48
|
-
* compared the description digest and established the caller: the exact type, an offered
|
|
49
|
-
* operation the authority permits, and expiry. Undefined when they pass. The service then
|
|
50
|
-
* applies its own state (a decided interaction, a stale target) and `inputErrors`, in that
|
|
51
|
-
* order, before any effect.
|
|
52
|
-
*/
|
|
53
|
-
requestProblem(description: MapDescription, request: MapRequest, { now }: {
|
|
54
|
-
now: Date;
|
|
55
|
-
}): RequestProblem | undefined;
|
|
57
|
+
operation(id: string): Operation | undefined;
|
|
58
|
+
/** Why the details do not satisfy the contract's details schema, or no reasons. */
|
|
59
|
+
detailsErrors(details: unknown): string[];
|
|
60
|
+
/** Why the input is not acceptable for the operation, or no reasons. */
|
|
61
|
+
inputErrors(operationId: string, input: unknown): string[];
|
|
56
62
|
/**
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
63
|
+
* Why a valid description does not use this contract as it allows, or no reasons: it names
|
|
64
|
+
* this contract by identifier, version and digest; it offers only declared operations; a
|
|
65
|
+
* capability appears only where the contract permits one, at the service's origin and
|
|
66
|
+
* within the kind's lifetime; and its details satisfy the details schema.
|
|
60
67
|
*/
|
|
61
|
-
|
|
62
|
-
/** A request against the core request definition and this contract's request schema. */
|
|
63
|
-
requestErrors(request: unknown): string[];
|
|
64
|
-
/** The core result definition, then the output schema and reason the operation declares. */
|
|
65
|
-
resultErrors(result: unknown): string[];
|
|
68
|
+
descriptionErrors(description: Description): string[];
|
|
66
69
|
}
|