@mdbase-dev/connect-protocol 0.1.0-beta.30 → 0.1.0-beta.32
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/dist/application-authorization.d.ts +3 -1
- package/dist/application-authorization.js +21 -5
- package/dist/compatibility.d.ts +26 -0
- package/dist/compatibility.js +35 -0
- package/dist/connect-problems.generated.d.ts +151 -2
- package/dist/connect-problems.generated.js +161 -0
- package/dist/index.d.ts +25 -14
- package/dist/index.js +15 -4
- package/dist/mutation-fingerprint.d.ts +6 -0
- package/dist/mutation-fingerprint.js +116 -0
- package/dist/operations.d.ts +14 -1
- package/dist/operations.js +174 -1
- package/package.json +2 -2
- package/schemas/catalog.json +1 -1
- package/schemas/connect-problem.v1.schema.json +634 -32
- package/schemas/connect-problems.v1.catalog.json +78 -1
- package/schemas/connect-protocol.v1.schema.json +55 -12
- package/schemas/encrypted-relay.v2.schema.json +63 -0
- package/schemas/operation-catalog.v1.json +40 -0
package/dist/index.d.ts
CHANGED
|
@@ -7,20 +7,25 @@ import type { ApplicationAuthorizationProof } from "./application-authorization.
|
|
|
7
7
|
export * from "./connect-problems.generated.js";
|
|
8
8
|
export * from "./files.js";
|
|
9
9
|
export * from "./operations.js";
|
|
10
|
+
export * from "./mutation-fingerprint.js";
|
|
11
|
+
export * from "./compatibility.js";
|
|
10
12
|
export * from "./capabilities.js";
|
|
11
13
|
export * from "./application-authorization.js";
|
|
12
14
|
export * from "./type-packs.js";
|
|
13
15
|
export declare const CONTROL_PROTOCOL_VERSION: 1;
|
|
14
|
-
export
|
|
15
|
-
export declare const APPLICATION_AUTHORIZATION_PROTOCOL_VERSION: 2;
|
|
16
|
+
export { AUTHORIZATION_BINDING_PROTOCOL_VERSION as APPLICATION_AUTHORIZATION_PROTOCOL_VERSION } from "./compatibility.js";
|
|
16
17
|
export declare const LOOPBACK_PROTOCOL_VERSION: 1;
|
|
17
18
|
export declare const DEFAULT_LOOPBACK_PORT: 28485;
|
|
18
19
|
export declare const RELAY_ENCRYPTION_SUITE: "P256-HKDF-SHA256-AES256GCM";
|
|
20
|
+
export declare const GRANT_ENCRYPTION_PROTOCOL_VERSION: 1;
|
|
19
21
|
export declare const SYNC_PROTOCOL_VERSION: 1;
|
|
20
22
|
export declare const CONTRACT_SETUP_CAPABILITY: "contract-setup-v1";
|
|
21
23
|
export declare const FILE_RELAY_CAPABILITY: "file-relay-v1";
|
|
22
|
-
export declare const RELAY_REQUIRED_CAPABILITIES: readonly ["application-authorization-
|
|
23
|
-
export declare const
|
|
24
|
+
export declare const RELAY_REQUIRED_CAPABILITIES: readonly ["application-authorization-v3", "authorization-activation", "encrypted-relay", "policy-ack"];
|
|
25
|
+
export declare const MINIMUM_CONNECTOR_VERSION: "0.1.0-beta.32";
|
|
26
|
+
export declare const HOSTED_PROVIDER_REQUIRED_CAPABILITIES: readonly ["durable-mutation-journal-v1", "durable-file-lifecycle-v1"];
|
|
27
|
+
export declare const HOSTED_PROVIDER_CAPABILITIES: readonly ["durable-mutation-journal-v1", "durable-file-lifecycle-v1", "mutation-replay-after-credential-retirement-v1"];
|
|
28
|
+
export declare const RELAY_CAPABILITIES: readonly ["application-authorization-v3", "authorization-activation", "encrypted-relay", "policy-ack", "contract-setup-v1", "file-relay-v1"];
|
|
24
29
|
export declare const AUTHORITY_PROOF_VERSION: 1;
|
|
25
30
|
export declare const AUTHORITY_PROOF_ALGORITHM: "P256-SHA256";
|
|
26
31
|
export declare const AUTHORITY_PROOF_DOMAIN: "mdbase-authority-request-proof-v1";
|
|
@@ -42,7 +47,7 @@ export declare const CONNECT_SCHEMA_IDS: {
|
|
|
42
47
|
readonly dataContract: "https://mdbase.dev/schemas/v0.3/data-contract.schema.json";
|
|
43
48
|
readonly eventActionInterop: "https://mdbase.dev/schemas/interop/v0.1/profile.schema.json";
|
|
44
49
|
readonly protocol: "https://mdbase.dev/connect/schemas/connect-protocol.v1.json";
|
|
45
|
-
readonly encryptedRelay: "https://mdbase.dev/connect/schemas/encrypted-relay.
|
|
50
|
+
readonly encryptedRelay: "https://mdbase.dev/connect/schemas/encrypted-relay.v2.json";
|
|
46
51
|
readonly files: "https://mdbase.dev/connect/schemas/files.v1.json";
|
|
47
52
|
readonly sync: "https://mdbase.dev/connect/schemas/sync.v1.json";
|
|
48
53
|
};
|
|
@@ -171,7 +176,7 @@ export interface GrantScope {
|
|
|
171
176
|
}
|
|
172
177
|
export interface RelayOperationRequest {
|
|
173
178
|
type: "operation_request";
|
|
174
|
-
protocol_version:
|
|
179
|
+
protocol_version: 2;
|
|
175
180
|
request_id: string;
|
|
176
181
|
grant_id: string;
|
|
177
182
|
collection_id: string;
|
|
@@ -181,29 +186,29 @@ export interface RelayOperationRequest {
|
|
|
181
186
|
}
|
|
182
187
|
export type RelayOperationResponse = {
|
|
183
188
|
type: "operation_response";
|
|
184
|
-
protocol_version:
|
|
189
|
+
protocol_version: 2;
|
|
185
190
|
request_id: string;
|
|
186
191
|
ok: true;
|
|
187
192
|
result: unknown;
|
|
188
193
|
} | {
|
|
189
194
|
type: "operation_response";
|
|
190
|
-
protocol_version:
|
|
195
|
+
protocol_version: 2;
|
|
191
196
|
request_id: string;
|
|
192
197
|
ok: false;
|
|
193
198
|
problem: ConnectProblem;
|
|
194
199
|
};
|
|
195
200
|
export interface MdbaseOperationRequest<Input = unknown> {
|
|
196
|
-
protocol_version:
|
|
201
|
+
protocol_version: 2;
|
|
197
202
|
request_id: string;
|
|
198
203
|
input: Input;
|
|
199
204
|
}
|
|
200
205
|
export type MdbaseOperationResponse<Result = unknown> = {
|
|
201
|
-
protocol_version:
|
|
206
|
+
protocol_version: 2;
|
|
202
207
|
request_id: string;
|
|
203
208
|
ok: true;
|
|
204
209
|
result: Result;
|
|
205
210
|
} | {
|
|
206
|
-
protocol_version:
|
|
211
|
+
protocol_version: 2;
|
|
207
212
|
request_id: string;
|
|
208
213
|
ok: false;
|
|
209
214
|
problem: ConnectProblem;
|
|
@@ -232,7 +237,9 @@ export interface GrantPolicy {
|
|
|
232
237
|
application_authorization: ApplicationAuthorizationProof;
|
|
233
238
|
}
|
|
234
239
|
/** Presentation-only grant shape used outside a local authorization boundary. */
|
|
235
|
-
export type GrantSummary = Omit<GrantPolicy, "application_authorization"
|
|
240
|
+
export type GrantSummary = Omit<GrantPolicy, "application_authorization"> & {
|
|
241
|
+
contracts: import("./compatibility.js").ConnectContractRequirements;
|
|
242
|
+
};
|
|
236
243
|
export interface GrantEncryption {
|
|
237
244
|
protocol_version: 1;
|
|
238
245
|
suite: typeof RELAY_ENCRYPTION_SUITE;
|
|
@@ -244,7 +251,7 @@ export interface GrantEncryption {
|
|
|
244
251
|
connector_agreement_public_key: string;
|
|
245
252
|
}
|
|
246
253
|
export interface EncryptedRelayEnvelope {
|
|
247
|
-
protocol_version:
|
|
254
|
+
protocol_version: 2;
|
|
248
255
|
suite: typeof RELAY_ENCRYPTION_SUITE;
|
|
249
256
|
request_id: string;
|
|
250
257
|
grant_id: string;
|
|
@@ -490,18 +497,22 @@ export interface RelayHello {
|
|
|
490
497
|
protocol_version: 1;
|
|
491
498
|
connector_version: string;
|
|
492
499
|
capabilities: string[];
|
|
500
|
+
contract_support: import("./compatibility.js").ConnectContractSupport;
|
|
493
501
|
}
|
|
494
502
|
export interface RelayWelcome {
|
|
495
503
|
type: "relay_welcome";
|
|
496
504
|
protocol_version: 1;
|
|
497
505
|
session_id: string;
|
|
498
506
|
capabilities: string[];
|
|
507
|
+
contract_support: import("./compatibility.js").ConnectContractSupport;
|
|
499
508
|
}
|
|
500
509
|
export interface RelayIncompatible {
|
|
501
510
|
type: "relay_incompatible";
|
|
502
511
|
protocol_version: 1;
|
|
503
|
-
code: "connector_upgrade_required";
|
|
512
|
+
code: "connector_upgrade_required" | "transport_protocol_incompatible" | "authorization_binding_incompatible" | "capability_contract_incompatible" | "durable_mutation_unsupported";
|
|
504
513
|
message: string;
|
|
514
|
+
details?: import("./connect-problems.generated.js").ConnectProblemDetailsByCode["transport_protocol_incompatible" | "authorization_binding_incompatible" | "capability_contract_incompatible" | "durable_mutation_unsupported"];
|
|
515
|
+
minimum_connector_version: string;
|
|
505
516
|
update_url: string;
|
|
506
517
|
}
|
|
507
518
|
export interface RelayPolicyApplied {
|
package/dist/index.js
CHANGED
|
@@ -1,24 +1,35 @@
|
|
|
1
1
|
export * from "./connect-problems.generated.js";
|
|
2
2
|
export * from "./files.js";
|
|
3
3
|
export * from "./operations.js";
|
|
4
|
+
export * from "./mutation-fingerprint.js";
|
|
5
|
+
export * from "./compatibility.js";
|
|
4
6
|
export * from "./capabilities.js";
|
|
5
7
|
export * from "./application-authorization.js";
|
|
6
8
|
export * from "./type-packs.js";
|
|
7
9
|
export const CONTROL_PROTOCOL_VERSION = 1;
|
|
8
|
-
export
|
|
9
|
-
export const APPLICATION_AUTHORIZATION_PROTOCOL_VERSION = 2;
|
|
10
|
+
export { AUTHORIZATION_BINDING_PROTOCOL_VERSION as APPLICATION_AUTHORIZATION_PROTOCOL_VERSION } from "./compatibility.js";
|
|
10
11
|
export const LOOPBACK_PROTOCOL_VERSION = 1;
|
|
11
12
|
export const DEFAULT_LOOPBACK_PORT = 28_485;
|
|
12
13
|
export const RELAY_ENCRYPTION_SUITE = "P256-HKDF-SHA256-AES256GCM";
|
|
14
|
+
export const GRANT_ENCRYPTION_PROTOCOL_VERSION = 1;
|
|
13
15
|
export const SYNC_PROTOCOL_VERSION = 1;
|
|
14
16
|
export const CONTRACT_SETUP_CAPABILITY = "contract-setup-v1";
|
|
15
17
|
export const FILE_RELAY_CAPABILITY = "file-relay-v1";
|
|
16
18
|
export const RELAY_REQUIRED_CAPABILITIES = [
|
|
17
|
-
"application-authorization-
|
|
19
|
+
"application-authorization-v3",
|
|
18
20
|
"authorization-activation",
|
|
19
21
|
"encrypted-relay",
|
|
20
22
|
"policy-ack"
|
|
21
23
|
];
|
|
24
|
+
export const MINIMUM_CONNECTOR_VERSION = "0.1.0-beta.32";
|
|
25
|
+
export const HOSTED_PROVIDER_REQUIRED_CAPABILITIES = [
|
|
26
|
+
"durable-mutation-journal-v1",
|
|
27
|
+
"durable-file-lifecycle-v1"
|
|
28
|
+
];
|
|
29
|
+
export const HOSTED_PROVIDER_CAPABILITIES = [
|
|
30
|
+
...HOSTED_PROVIDER_REQUIRED_CAPABILITIES,
|
|
31
|
+
"mutation-replay-after-credential-retirement-v1"
|
|
32
|
+
];
|
|
22
33
|
export const RELAY_CAPABILITIES = [
|
|
23
34
|
...RELAY_REQUIRED_CAPABILITIES,
|
|
24
35
|
CONTRACT_SETUP_CAPABILITY,
|
|
@@ -62,7 +73,7 @@ export const CONNECT_SCHEMA_IDS = {
|
|
|
62
73
|
dataContract: "https://mdbase.dev/schemas/v0.3/data-contract.schema.json",
|
|
63
74
|
eventActionInterop: "https://mdbase.dev/schemas/interop/v0.1/profile.schema.json",
|
|
64
75
|
protocol: "https://mdbase.dev/connect/schemas/connect-protocol.v1.json",
|
|
65
|
-
encryptedRelay: "https://mdbase.dev/connect/schemas/encrypted-relay.
|
|
76
|
+
encryptedRelay: "https://mdbase.dev/connect/schemas/encrypted-relay.v2.json",
|
|
66
77
|
files: "https://mdbase.dev/connect/schemas/files.v1.json",
|
|
67
78
|
sync: "https://mdbase.dev/connect/schemas/sync.v1.json"
|
|
68
79
|
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type EncryptedOperation } from "./operations.js";
|
|
2
|
+
export declare const MUTATION_FINGERPRINT_SCHEMA_VERSION: 1;
|
|
3
|
+
export declare const MUTATION_FINGERPRINT_DOMAIN: "mdbase-connect mutation fingerprint v1\0";
|
|
4
|
+
export declare function canonicalMutationInput(input: unknown): string;
|
|
5
|
+
export declare function mutationFingerprintTranscript(operation: EncryptedOperation, input: unknown): Uint8Array<ArrayBuffer>;
|
|
6
|
+
export declare function mutationFingerprint(operation: EncryptedOperation, input: unknown): Promise<string>;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { mutationOperationIdentifier, operationInputSchemaVersion } from "./operations.js";
|
|
2
|
+
export const MUTATION_FINGERPRINT_SCHEMA_VERSION = 1;
|
|
3
|
+
export const MUTATION_FINGERPRINT_DOMAIN = "mdbase-connect mutation fingerprint v1\0";
|
|
4
|
+
const encoder = new TextEncoder();
|
|
5
|
+
export function canonicalMutationInput(input) {
|
|
6
|
+
return canonicalize(input, new Set());
|
|
7
|
+
}
|
|
8
|
+
export function mutationFingerprintTranscript(operation, input) {
|
|
9
|
+
const identifier = mutationOperationIdentifier(operation, input);
|
|
10
|
+
if (identifier === null)
|
|
11
|
+
throw new TypeError("The operation is not a canonical mutation.");
|
|
12
|
+
const identifierBytes = encoder.encode(identifier);
|
|
13
|
+
const inputBytes = encoder.encode(canonicalMutationInput(input));
|
|
14
|
+
const domainBytes = encoder.encode(MUTATION_FINGERPRINT_DOMAIN);
|
|
15
|
+
const transcript = new Uint8Array(domainBytes.length + 4 + 8 + identifierBytes.length + 4 + 8 + inputBytes.length);
|
|
16
|
+
const view = new DataView(transcript.buffer);
|
|
17
|
+
let offset = 0;
|
|
18
|
+
transcript.set(domainBytes, offset);
|
|
19
|
+
offset += domainBytes.length;
|
|
20
|
+
view.setUint32(offset, MUTATION_FINGERPRINT_SCHEMA_VERSION, false);
|
|
21
|
+
offset += 4;
|
|
22
|
+
offset = writeField(transcript, view, offset, identifierBytes);
|
|
23
|
+
view.setUint32(offset, operationInputSchemaVersion(operation, input), false);
|
|
24
|
+
offset += 4;
|
|
25
|
+
writeField(transcript, view, offset, inputBytes);
|
|
26
|
+
return transcript;
|
|
27
|
+
}
|
|
28
|
+
export async function mutationFingerprint(operation, input) {
|
|
29
|
+
const digest = new Uint8Array(await globalThis.crypto.subtle.digest("SHA-256", mutationFingerprintTranscript(operation, input).buffer));
|
|
30
|
+
return base64Url(digest);
|
|
31
|
+
}
|
|
32
|
+
function canonicalize(value, ancestors) {
|
|
33
|
+
if (value === null)
|
|
34
|
+
return "null";
|
|
35
|
+
if (value === true)
|
|
36
|
+
return "true";
|
|
37
|
+
if (value === false)
|
|
38
|
+
return "false";
|
|
39
|
+
if (typeof value === "string") {
|
|
40
|
+
assertUnicodeScalarString(value);
|
|
41
|
+
return JSON.stringify(value);
|
|
42
|
+
}
|
|
43
|
+
if (typeof value === "number") {
|
|
44
|
+
if (!Number.isFinite(value))
|
|
45
|
+
throw new TypeError("Mutation input numbers must be finite.");
|
|
46
|
+
return JSON.stringify(value);
|
|
47
|
+
}
|
|
48
|
+
if (typeof value !== "object") {
|
|
49
|
+
throw new TypeError(`Mutation input contains unsupported ${typeof value}.`);
|
|
50
|
+
}
|
|
51
|
+
if (ancestors.has(value))
|
|
52
|
+
throw new TypeError("Mutation input must not contain cycles.");
|
|
53
|
+
ancestors.add(value);
|
|
54
|
+
try {
|
|
55
|
+
if (Array.isArray(value)) {
|
|
56
|
+
if (Object.getOwnPropertySymbols(value).length > 0) {
|
|
57
|
+
throw new TypeError("Mutation input must not contain symbol properties.");
|
|
58
|
+
}
|
|
59
|
+
const children = [];
|
|
60
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
61
|
+
if (!Object.hasOwn(value, index))
|
|
62
|
+
throw new TypeError("Mutation input arrays must not be sparse.");
|
|
63
|
+
children.push(canonicalize(value[index], ancestors));
|
|
64
|
+
}
|
|
65
|
+
return `[${children.join(",")}]`;
|
|
66
|
+
}
|
|
67
|
+
const prototype = Object.getPrototypeOf(value);
|
|
68
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
69
|
+
throw new TypeError("Mutation input objects must be plain JSON objects.");
|
|
70
|
+
}
|
|
71
|
+
if (Object.getOwnPropertySymbols(value).length > 0) {
|
|
72
|
+
throw new TypeError("Mutation input must not contain symbol properties.");
|
|
73
|
+
}
|
|
74
|
+
const entries = Object.entries(value);
|
|
75
|
+
for (const [key] of entries)
|
|
76
|
+
assertUnicodeScalarString(key);
|
|
77
|
+
entries.sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0);
|
|
78
|
+
return `{${entries.map(([key, child]) => {
|
|
79
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
80
|
+
if (!descriptor || descriptor.get || descriptor.set) {
|
|
81
|
+
throw new TypeError("Mutation input must not contain accessor properties.");
|
|
82
|
+
}
|
|
83
|
+
return `${JSON.stringify(key)}:${canonicalize(child, ancestors)}`;
|
|
84
|
+
}).join(",")}}`;
|
|
85
|
+
}
|
|
86
|
+
finally {
|
|
87
|
+
ancestors.delete(value);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function assertUnicodeScalarString(value) {
|
|
91
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
92
|
+
const unit = value.charCodeAt(index);
|
|
93
|
+
if (unit >= 0xd800 && unit <= 0xdbff) {
|
|
94
|
+
const next = value.charCodeAt(index + 1);
|
|
95
|
+
if (!(next >= 0xdc00 && next <= 0xdfff)) {
|
|
96
|
+
throw new TypeError("Mutation input strings must not contain lone surrogates.");
|
|
97
|
+
}
|
|
98
|
+
index += 1;
|
|
99
|
+
}
|
|
100
|
+
else if (unit >= 0xdc00 && unit <= 0xdfff) {
|
|
101
|
+
throw new TypeError("Mutation input strings must not contain lone surrogates.");
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function writeField(transcript, view, offset, value) {
|
|
106
|
+
view.setBigUint64(offset, BigInt(value.length), false);
|
|
107
|
+
offset += 8;
|
|
108
|
+
transcript.set(value, offset);
|
|
109
|
+
return offset + value.length;
|
|
110
|
+
}
|
|
111
|
+
function base64Url(value) {
|
|
112
|
+
return btoa(String.fromCharCode(...value))
|
|
113
|
+
.replaceAll("+", "-")
|
|
114
|
+
.replaceAll("/", "_")
|
|
115
|
+
.replace(/=+$/u, "");
|
|
116
|
+
}
|
package/dist/operations.d.ts
CHANGED
|
@@ -1 +1,14 @@
|
|
|
1
|
-
export
|
|
1
|
+
export declare const OPERATION_CATALOG_VERSION: 1;
|
|
2
|
+
export declare const COLLECTION_OPERATIONS: readonly ["describe", "changes", "read", "query", "list_views", "execute_view", "read_view_source", "create_view_source", "update_view_source", "delete_view_source", "validate", "create", "update", "delete", "rename", "read_type", "create_type", "update_type", "assess_type_pack", "apply_type_pack", "list_timers", "put_timer", "cancel_timer", "reconcile_timers", "sync"];
|
|
3
|
+
export type CollectionOperation = typeof COLLECTION_OPERATIONS[number];
|
|
4
|
+
export declare const FILE_CONTROL_MESSAGE_TYPES: readonly ["list_files", "open_file_upload", "open_file_download", "move_file", "delete_file", "get_file_transfer_status", "commit_file_upload", "abort_file_transfer"];
|
|
5
|
+
export type FileControlMessageType = typeof FILE_CONTROL_MESSAGE_TYPES[number];
|
|
6
|
+
export type EncryptedOperation = CollectionOperation | "file_control";
|
|
7
|
+
export declare const MUTATING_OPERATION_IDENTIFIERS: readonly ["create_view_source", "update_view_source", "delete_view_source", "create", "update", "delete", "rename", "create_type", "update_type", "apply_type_pack", "put_timer", "cancel_timer", "reconcile_timers", "sync:mutate", "file_control:open_file_upload", "file_control:move_file", "file_control:delete_file", "file_control:commit_file_upload", "file_control:abort_file_transfer"];
|
|
8
|
+
export type MutationOperationIdentifier = typeof MUTATING_OPERATION_IDENTIFIERS[number];
|
|
9
|
+
export declare function isCollectionOperation(value: string): value is CollectionOperation;
|
|
10
|
+
export declare function areCollectionOperations(values: readonly string[]): values is readonly CollectionOperation[];
|
|
11
|
+
export declare function isFileControlMessageType(value: string): value is FileControlMessageType;
|
|
12
|
+
export declare function operationInputSchemaVersion(operation: EncryptedOperation, input: unknown): number;
|
|
13
|
+
export declare function mutationOperationIdentifier(operation: EncryptedOperation, input: unknown): MutationOperationIdentifier | null;
|
|
14
|
+
export declare function isMutatingOperation(operation: EncryptedOperation, input: unknown): boolean;
|
package/dist/operations.js
CHANGED
|
@@ -1 +1,174 @@
|
|
|
1
|
-
|
|
1
|
+
// Generated by scripts/generate-operation-catalog.mjs. Do not edit directly.
|
|
2
|
+
export const OPERATION_CATALOG_VERSION = 1;
|
|
3
|
+
export const COLLECTION_OPERATIONS = [
|
|
4
|
+
"describe",
|
|
5
|
+
"changes",
|
|
6
|
+
"read",
|
|
7
|
+
"query",
|
|
8
|
+
"list_views",
|
|
9
|
+
"execute_view",
|
|
10
|
+
"read_view_source",
|
|
11
|
+
"create_view_source",
|
|
12
|
+
"update_view_source",
|
|
13
|
+
"delete_view_source",
|
|
14
|
+
"validate",
|
|
15
|
+
"create",
|
|
16
|
+
"update",
|
|
17
|
+
"delete",
|
|
18
|
+
"rename",
|
|
19
|
+
"read_type",
|
|
20
|
+
"create_type",
|
|
21
|
+
"update_type",
|
|
22
|
+
"assess_type_pack",
|
|
23
|
+
"apply_type_pack",
|
|
24
|
+
"list_timers",
|
|
25
|
+
"put_timer",
|
|
26
|
+
"cancel_timer",
|
|
27
|
+
"reconcile_timers",
|
|
28
|
+
"sync"
|
|
29
|
+
];
|
|
30
|
+
export const FILE_CONTROL_MESSAGE_TYPES = [
|
|
31
|
+
"list_files",
|
|
32
|
+
"open_file_upload",
|
|
33
|
+
"open_file_download",
|
|
34
|
+
"move_file",
|
|
35
|
+
"delete_file",
|
|
36
|
+
"get_file_transfer_status",
|
|
37
|
+
"commit_file_upload",
|
|
38
|
+
"abort_file_transfer"
|
|
39
|
+
];
|
|
40
|
+
const COLLECTION_MUTATION_RULES = {
|
|
41
|
+
"describe": "never",
|
|
42
|
+
"changes": "never",
|
|
43
|
+
"read": "never",
|
|
44
|
+
"query": "never",
|
|
45
|
+
"list_views": "never",
|
|
46
|
+
"execute_view": "never",
|
|
47
|
+
"read_view_source": "never",
|
|
48
|
+
"create_view_source": "always",
|
|
49
|
+
"update_view_source": "always",
|
|
50
|
+
"delete_view_source": "always",
|
|
51
|
+
"validate": "never",
|
|
52
|
+
"create": "always",
|
|
53
|
+
"update": "always",
|
|
54
|
+
"delete": "always",
|
|
55
|
+
"rename": "always",
|
|
56
|
+
"read_type": "never",
|
|
57
|
+
"create_type": "always",
|
|
58
|
+
"update_type": "always",
|
|
59
|
+
"assess_type_pack": "never",
|
|
60
|
+
"apply_type_pack": "always",
|
|
61
|
+
"list_timers": "never",
|
|
62
|
+
"put_timer": "always",
|
|
63
|
+
"cancel_timer": "always",
|
|
64
|
+
"reconcile_timers": "always",
|
|
65
|
+
"sync": "sync_action"
|
|
66
|
+
};
|
|
67
|
+
const COLLECTION_INPUT_SCHEMA_VERSIONS = {
|
|
68
|
+
"describe": 1,
|
|
69
|
+
"changes": 1,
|
|
70
|
+
"read": 1,
|
|
71
|
+
"query": 1,
|
|
72
|
+
"list_views": 1,
|
|
73
|
+
"execute_view": 1,
|
|
74
|
+
"read_view_source": 1,
|
|
75
|
+
"create_view_source": 1,
|
|
76
|
+
"update_view_source": 1,
|
|
77
|
+
"delete_view_source": 1,
|
|
78
|
+
"validate": 1,
|
|
79
|
+
"create": 1,
|
|
80
|
+
"update": 1,
|
|
81
|
+
"delete": 1,
|
|
82
|
+
"rename": 1,
|
|
83
|
+
"read_type": 1,
|
|
84
|
+
"create_type": 1,
|
|
85
|
+
"update_type": 1,
|
|
86
|
+
"assess_type_pack": 1,
|
|
87
|
+
"apply_type_pack": 1,
|
|
88
|
+
"list_timers": 1,
|
|
89
|
+
"put_timer": 1,
|
|
90
|
+
"cancel_timer": 1,
|
|
91
|
+
"reconcile_timers": 1,
|
|
92
|
+
"sync": 1
|
|
93
|
+
};
|
|
94
|
+
const FILE_CONTROL_INPUT_SCHEMA_VERSIONS = {
|
|
95
|
+
"list_files": 1,
|
|
96
|
+
"open_file_upload": 1,
|
|
97
|
+
"open_file_download": 1,
|
|
98
|
+
"move_file": 1,
|
|
99
|
+
"delete_file": 1,
|
|
100
|
+
"get_file_transfer_status": 1,
|
|
101
|
+
"commit_file_upload": 1,
|
|
102
|
+
"abort_file_transfer": 1
|
|
103
|
+
};
|
|
104
|
+
const MUTATING_FILE_CONTROL_MESSAGE_TYPES = new Set([
|
|
105
|
+
"open_file_upload",
|
|
106
|
+
"move_file",
|
|
107
|
+
"delete_file",
|
|
108
|
+
"commit_file_upload",
|
|
109
|
+
"abort_file_transfer"
|
|
110
|
+
]);
|
|
111
|
+
export const MUTATING_OPERATION_IDENTIFIERS = [
|
|
112
|
+
"create_view_source",
|
|
113
|
+
"update_view_source",
|
|
114
|
+
"delete_view_source",
|
|
115
|
+
"create",
|
|
116
|
+
"update",
|
|
117
|
+
"delete",
|
|
118
|
+
"rename",
|
|
119
|
+
"create_type",
|
|
120
|
+
"update_type",
|
|
121
|
+
"apply_type_pack",
|
|
122
|
+
"put_timer",
|
|
123
|
+
"cancel_timer",
|
|
124
|
+
"reconcile_timers",
|
|
125
|
+
"sync:mutate",
|
|
126
|
+
"file_control:open_file_upload",
|
|
127
|
+
"file_control:move_file",
|
|
128
|
+
"file_control:delete_file",
|
|
129
|
+
"file_control:commit_file_upload",
|
|
130
|
+
"file_control:abort_file_transfer"
|
|
131
|
+
];
|
|
132
|
+
const COLLECTION_OPERATION_SET = new Set(COLLECTION_OPERATIONS);
|
|
133
|
+
const FILE_CONTROL_MESSAGE_TYPE_SET = new Set(FILE_CONTROL_MESSAGE_TYPES);
|
|
134
|
+
export function isCollectionOperation(value) {
|
|
135
|
+
return COLLECTION_OPERATION_SET.has(value);
|
|
136
|
+
}
|
|
137
|
+
export function areCollectionOperations(values) {
|
|
138
|
+
return values.every(isCollectionOperation);
|
|
139
|
+
}
|
|
140
|
+
export function isFileControlMessageType(value) {
|
|
141
|
+
return FILE_CONTROL_MESSAGE_TYPE_SET.has(value);
|
|
142
|
+
}
|
|
143
|
+
export function operationInputSchemaVersion(operation, input) {
|
|
144
|
+
if (operation === "file_control") {
|
|
145
|
+
const type = isObject(input) && typeof input.type === "string" ? input.type : "";
|
|
146
|
+
if (!isFileControlMessageType(type))
|
|
147
|
+
throw new Error(`Unknown file-control message: ${type}`);
|
|
148
|
+
return FILE_CONTROL_INPUT_SCHEMA_VERSIONS[type];
|
|
149
|
+
}
|
|
150
|
+
return COLLECTION_INPUT_SCHEMA_VERSIONS[operation];
|
|
151
|
+
}
|
|
152
|
+
export function mutationOperationIdentifier(operation, input) {
|
|
153
|
+
const object = isObject(input) ? input : {};
|
|
154
|
+
if (object.dry_run === true)
|
|
155
|
+
return null;
|
|
156
|
+
if (operation === "file_control") {
|
|
157
|
+
const type = typeof object.type === "string" ? object.type : "";
|
|
158
|
+
return MUTATING_FILE_CONTROL_MESSAGE_TYPES.has(type)
|
|
159
|
+
? `file_control:${type}`
|
|
160
|
+
: null;
|
|
161
|
+
}
|
|
162
|
+
const rule = COLLECTION_MUTATION_RULES[operation];
|
|
163
|
+
if (rule === "always")
|
|
164
|
+
return operation;
|
|
165
|
+
if (rule === "sync_action" && object.action === "mutate")
|
|
166
|
+
return "sync:mutate";
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
export function isMutatingOperation(operation, input) {
|
|
170
|
+
return mutationOperationIdentifier(operation, input) !== null;
|
|
171
|
+
}
|
|
172
|
+
function isObject(value) {
|
|
173
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
174
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mdbase-dev/connect-protocol",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.32",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
38
|
"build": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.json",
|
|
39
|
-
"test": "node --test test/*.test.mjs && node ../../scripts/generate-connect-problems.mjs --check",
|
|
39
|
+
"test": "node --test test/*.test.mjs && node ../../scripts/generate-connect-problems.mjs --check && node ../../scripts/generate-operation-catalog.mjs --check",
|
|
40
40
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
41
41
|
}
|
|
42
42
|
}
|
package/schemas/catalog.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"connect_protocol": "./connect-protocol.v1.schema.json",
|
|
8
8
|
"connect_problem": "./connect-problem.v1.schema.json",
|
|
9
9
|
"connect_problem_catalog": "./connect-problems.v1.catalog.json",
|
|
10
|
-
"encrypted_relay": "./encrypted-relay.
|
|
10
|
+
"encrypted_relay": "./encrypted-relay.v2.schema.json",
|
|
11
11
|
"files": "./files.v1.schema.json",
|
|
12
12
|
"notification_webhook": "./notification-webhook.v1.schema.json",
|
|
13
13
|
"sync": "./sync.v1.schema.json"
|