@haverstack/wire-types 0.39.0 → 0.41.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.
- package/dist/auth.d.ts +67 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +34 -0
- package/dist/auth.js.map +1 -0
- package/dist/change-feed.d.ts +92 -0
- package/dist/change-feed.d.ts.map +1 -0
- package/dist/change-feed.js +69 -0
- package/dist/change-feed.js.map +1 -0
- package/dist/discovery.d.ts +73 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +74 -0
- package/dist/discovery.js.map +1 -0
- package/dist/errors.d.ts +68 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +151 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +22 -413
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -389
- package/dist/index.js.map +1 -1
- package/dist/installs.d.ts +37 -0
- package/dist/installs.d.ts.map +1 -0
- package/dist/installs.js +11 -0
- package/dist/installs.js.map +1 -0
- package/dist/journal.d.ts +50 -0
- package/dist/journal.d.ts.map +1 -0
- package/dist/journal.js +30 -0
- package/dist/journal.js.map +1 -0
- package/dist/records.d.ts +81 -0
- package/dist/records.d.ts.map +1 -0
- package/dist/records.js +76 -0
- package/dist/records.js.map +1 -0
- package/package.json +2 -2
package/dist/errors.js
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error responses
|
|
3
|
+
* -------------------------------------------------------
|
|
4
|
+
* The round-trip contract for core's typed error taxonomy: a server
|
|
5
|
+
* serializes a caught core error via serializeError(), and APIAdapter
|
|
6
|
+
* reconstructs the same class via deserializeError(). `code` is the
|
|
7
|
+
* authoritative discriminator; status is a transport hint. See
|
|
8
|
+
* docs/spec/wire-format.md § Error responses.
|
|
9
|
+
*/
|
|
10
|
+
import { StackError, StackValidationError, StackPermissionError, StackNotFoundError, StackConflictError, StackVersionConflictError, StackMigrationError, StackBadRequestError, StackSchemaDriftError, StackPayloadTooLargeError, StackTimeoutError, } from '@haverstack/core';
|
|
11
|
+
/** Canonical HTTP status for each wire error code. */
|
|
12
|
+
export const WIRE_ERROR_STATUS = {
|
|
13
|
+
bad_request: 400,
|
|
14
|
+
permission: 403,
|
|
15
|
+
not_found: 404,
|
|
16
|
+
conflict: 409,
|
|
17
|
+
// 412 (not 409): RFC 7232's status for a failed If-Match precondition,
|
|
18
|
+
// and distinct from 'conflict' — StackVersionConflictError is not a
|
|
19
|
+
// StackConflictError subtype (see its doc comment), so each code keeps
|
|
20
|
+
// its own unambiguous status, including for the status-only fallback
|
|
21
|
+
// below.
|
|
22
|
+
version_conflict: 412,
|
|
23
|
+
validation: 422,
|
|
24
|
+
/**
|
|
25
|
+
* StackMigrationError is thrown client-side and never by a server, so no
|
|
26
|
+
* response carries this code; it has a status because every code does.
|
|
27
|
+
* See docs/spec/wire-format.md § Error responses.
|
|
28
|
+
*/
|
|
29
|
+
migration: 500,
|
|
30
|
+
// Shares 409 with 'conflict', so a schema-drift response without a
|
|
31
|
+
// parseable body degrades to a generic StackConflictError in
|
|
32
|
+
// status-only reconstruction. See docs/spec/wire-format.md § Wire error
|
|
33
|
+
// body.
|
|
34
|
+
schema_drift: 409,
|
|
35
|
+
// 413 is unambiguous — no other wire code shares it — so status-only
|
|
36
|
+
// reconstruction (STATUS_TO_CODE below) recovers this class even from a
|
|
37
|
+
// bodyless response (e.g. a reverse proxy's own request-entity-too-large
|
|
38
|
+
// page, not the server's JSON error body).
|
|
39
|
+
payload_too_large: 413,
|
|
40
|
+
/**
|
|
41
|
+
* 503, not 408 or 504: the request arrived fine (408 says it didn't) and
|
|
42
|
+
* the server is not a gateway (504 says it is) — it declined to keep
|
|
43
|
+
* spending its own time on this one. Retryable, which is the part a
|
|
44
|
+
* client acts on, and the reason a query timeout must not reuse
|
|
45
|
+
* `bad_request`: that code means "malformed, retrying won't help."
|
|
46
|
+
*/
|
|
47
|
+
timeout: 503,
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Statuses that unambiguously imply a wire error code, for reconstructing
|
|
51
|
+
* an error from status alone when a response has no parseable wire error
|
|
52
|
+
* body. 500 is deliberately excluded — it would misclassify ordinary
|
|
53
|
+
* server bugs as StackMigrationError. See docs/spec/wire-format.md
|
|
54
|
+
* § Wire error body.
|
|
55
|
+
*/
|
|
56
|
+
export const STATUS_TO_CODE = {
|
|
57
|
+
400: 'bad_request',
|
|
58
|
+
403: 'permission',
|
|
59
|
+
404: 'not_found',
|
|
60
|
+
409: 'conflict',
|
|
61
|
+
412: 'version_conflict',
|
|
62
|
+
422: 'validation',
|
|
63
|
+
413: 'payload_too_large',
|
|
64
|
+
// 503 is deliberately excluded, for the same reason as 500: a bodyless
|
|
65
|
+
// 503 is a load balancer or a restarting process saying "not right now",
|
|
66
|
+
// and reporting that as StackTimeoutError would tell an app its query
|
|
67
|
+
// was too expensive when the server never saw it. The typed body is
|
|
68
|
+
// what distinguishes the two, so `timeout` only reconstructs from one.
|
|
69
|
+
};
|
|
70
|
+
const KNOWN_CODES = new Set(Object.keys(WIRE_ERROR_STATUS));
|
|
71
|
+
/** Whether `body` is `{ error: { code, message } }` with a code from `codes`. */
|
|
72
|
+
export function hasErrorBody(body, codes) {
|
|
73
|
+
if (!body || typeof body !== 'object')
|
|
74
|
+
return false;
|
|
75
|
+
const err = body.error;
|
|
76
|
+
if (!err || typeof err !== 'object')
|
|
77
|
+
return false;
|
|
78
|
+
const code = err.code;
|
|
79
|
+
const message = err.message;
|
|
80
|
+
return typeof code === 'string' && codes.has(code) && typeof message === 'string';
|
|
81
|
+
}
|
|
82
|
+
/** Type guard: does this parsed JSON body look like a WireError? */
|
|
83
|
+
export function isWireError(body) {
|
|
84
|
+
return hasErrorBody(body, KNOWN_CODES);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Convert a thrown core error into its wire response. Used by server
|
|
88
|
+
* implementations. Returns null for anything that isn't a StackError —
|
|
89
|
+
* callers fall back to their own generic error handling, so an ordinary bug
|
|
90
|
+
* stays a bare 500 rather than being dressed as a protocol error.
|
|
91
|
+
*/
|
|
92
|
+
export function serializeError(err) {
|
|
93
|
+
if (!(err instanceof StackError))
|
|
94
|
+
return null;
|
|
95
|
+
const error = { code: err.code, message: err.message };
|
|
96
|
+
// The three classes carrying structured payload still need instanceof: a
|
|
97
|
+
// literal `code` doesn't narrow a class type to its subclass in TypeScript.
|
|
98
|
+
// Order-independent, since these are leaves with no subtype relation.
|
|
99
|
+
if (err instanceof StackValidationError) {
|
|
100
|
+
error.details = err.errors;
|
|
101
|
+
}
|
|
102
|
+
else if (err instanceof StackVersionConflictError) {
|
|
103
|
+
error.versionConflict = {
|
|
104
|
+
recordId: err.recordId,
|
|
105
|
+
expectedVersion: err.expectedVersion,
|
|
106
|
+
actualVersion: err.actualVersion,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
else if (err instanceof StackSchemaDriftError) {
|
|
110
|
+
error.schemaDrift = { typeId: err.typeId, violations: err.violations };
|
|
111
|
+
}
|
|
112
|
+
return { status: WIRE_ERROR_STATUS[err.code], body: { error } };
|
|
113
|
+
}
|
|
114
|
+
/** Reconstruct the core error a WireError body describes. */
|
|
115
|
+
export function deserializeError(body) {
|
|
116
|
+
const { code, message, details, versionConflict, schemaDrift } = body.error;
|
|
117
|
+
switch (code) {
|
|
118
|
+
case 'validation':
|
|
119
|
+
// The header is the message's first line, kept so a reconstructed
|
|
120
|
+
// error still says what the server validated.
|
|
121
|
+
return new StackValidationError(details ?? [], message.split('\n')[0].replace(/:$/, ''));
|
|
122
|
+
case 'permission':
|
|
123
|
+
return new StackPermissionError(message);
|
|
124
|
+
case 'not_found':
|
|
125
|
+
return new StackNotFoundError(message);
|
|
126
|
+
case 'conflict':
|
|
127
|
+
return new StackConflictError(message);
|
|
128
|
+
case 'version_conflict':
|
|
129
|
+
return new StackVersionConflictError(message, versionConflict?.recordId ?? '', versionConflict?.expectedVersion ?? -1, versionConflict?.actualVersion ?? -1);
|
|
130
|
+
case 'bad_request':
|
|
131
|
+
return new StackBadRequestError(message);
|
|
132
|
+
case 'migration':
|
|
133
|
+
return new StackMigrationError(message);
|
|
134
|
+
case 'schema_drift':
|
|
135
|
+
return new StackSchemaDriftError(schemaDrift?.typeId ?? '', schemaDrift?.violations ?? []);
|
|
136
|
+
case 'payload_too_large':
|
|
137
|
+
return new StackPayloadTooLargeError(message);
|
|
138
|
+
case 'timeout':
|
|
139
|
+
return new StackTimeoutError(message);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Reconstruct a core error from an HTTP status alone (no usable wire error
|
|
144
|
+
* body). Returns null for statuses with no unambiguous code — callers
|
|
145
|
+
* should fall back to a generic adapter-level error.
|
|
146
|
+
*/
|
|
147
|
+
export function errorForStatus(status, message) {
|
|
148
|
+
const code = STATUS_TO_CODE[status];
|
|
149
|
+
return code ? deserializeError({ error: { code, message } }) : null;
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,421 +1,30 @@
|
|
|
1
|
-
import type { StackRecord, StackType, RecordVersion, AssociationChange, AssociationEdit, AuthorityAssociation, DataAssociation, ValidationError, SchemaDriftViolation, StackErrorCode, ChangeKind, ChangeActor, ChangeOp, RecordChange, RecordJournalEntry, StackCapabilities } from '@haverstack/core';
|
|
2
|
-
/** An Actor on the wire — the same two fields, spelled the same way. */
|
|
3
|
-
export type WireActor = {
|
|
4
|
-
subjectId: string;
|
|
5
|
-
principalId?: string;
|
|
6
|
-
};
|
|
7
|
-
export type WireRecord = {
|
|
8
|
-
id: string;
|
|
9
|
-
typeId: string;
|
|
10
|
-
createdAt: string;
|
|
11
|
-
updatedAt: string;
|
|
12
|
-
content: Record<string, unknown>;
|
|
13
|
-
version: number;
|
|
14
|
-
parentId?: string;
|
|
15
|
-
appId?: string;
|
|
16
|
-
createdBy?: WireActor;
|
|
17
|
-
updatedBy?: WireActor;
|
|
18
|
-
deletedAt?: string;
|
|
19
|
-
unlistedAt?: string;
|
|
20
|
-
permissions?: AuthorityAssociation[];
|
|
21
|
-
associations?: DataAssociation[];
|
|
22
|
-
};
|
|
23
1
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
export
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
};
|
|
37
|
-
export
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
};
|
|
47
|
-
/**
|
|
48
|
-
* `parentId` is spelled exactly as `WireRecord` spells it: absent is the
|
|
49
|
-
* root. A snapshot is state, not an instruction, so it takes the same
|
|
50
|
-
* shape the record it describes takes — `null` is an input spelling
|
|
51
|
-
* (a change set's `parentId`, a `parentId=null` filter) and never appears
|
|
52
|
-
* on a response. See docs/spec/wire-format.md § Versions.
|
|
53
|
-
*
|
|
54
|
-
* No `associations` field: association changes don't bump `version`,
|
|
55
|
-
* so no version ever snapshots the association set. See
|
|
56
|
-
* docs/spec/versioning.md § Version history.
|
|
57
|
-
*/
|
|
58
|
-
export type WireVersion = {
|
|
59
|
-
version: number;
|
|
60
|
-
typeId: string;
|
|
61
|
-
content: Record<string, unknown>;
|
|
62
|
-
updatedAt: string;
|
|
63
|
-
createdBy?: WireActor;
|
|
64
|
-
updatedBy?: WireActor;
|
|
65
|
-
};
|
|
66
|
-
export declare function serializeRecord(r: StackRecord): WireRecord;
|
|
67
|
-
export declare function serializeType(t: StackType): WireType;
|
|
68
|
-
export declare function serializeVersion(v: RecordVersion): WireVersion;
|
|
69
|
-
/**
|
|
70
|
-
* One journal entry as `GET /records/:id/journal` carries it. Every field
|
|
71
|
-
* a `RecordJournalEntry` holds, since the whole entry is what makes a
|
|
72
|
-
* change recoverable — an envelope with a verb, an actor and a delta, and
|
|
73
|
-
* no `content`, which lives on a snapshot.
|
|
74
|
-
*
|
|
75
|
-
* `seq` is a dense integer from 1, per record — never the change feed's
|
|
76
|
-
* opaque `cursor`, and nothing may be carried from one to the other. See
|
|
77
|
-
* docs/spec/wire-format.md § Journal.
|
|
78
|
-
*/
|
|
79
|
-
export type WireJournalEntry = {
|
|
80
|
-
seq: number;
|
|
81
|
-
at: string;
|
|
82
|
-
kind: ChangeKind;
|
|
83
|
-
ops: ChangeOp[];
|
|
84
|
-
version: number;
|
|
85
|
-
typeId: string;
|
|
86
|
-
parentId?: string;
|
|
87
|
-
actor?: WireChangeActor;
|
|
88
|
-
/**
|
|
89
|
-
* The container the move took the record out of — and the one field on
|
|
90
|
-
* any response where `null` is a value rather than an input spelling.
|
|
91
|
-
* Absent means this entry is not a reparent; present and `null` means it
|
|
92
|
-
* moved out of the root. Collapsing the two would lose which one
|
|
93
|
-
* happened, so the root sentinel travels here as it does on a request.
|
|
94
|
-
*/
|
|
95
|
-
previousParentId?: string | null;
|
|
96
|
-
/**
|
|
97
|
-
* One tagged edit per association the write moved, each carrying its own
|
|
98
|
-
* `previous` where it had one. Has no counterpart on the change feed,
|
|
99
|
-
* which reports what is true now across two flat lists.
|
|
100
|
-
*/
|
|
101
|
-
associations?: AssociationChange[];
|
|
102
|
-
};
|
|
103
|
-
/**
|
|
104
|
-
* The response envelope of `GET /records/:id/journal`.
|
|
105
|
-
*
|
|
106
|
-
* `cursor` is the only end-of-log signal, as it is on a query: a server
|
|
107
|
-
* may cap a page below the `limit` asked for, so a short page does not
|
|
108
|
-
* mean an exhausted log. It carries the `seq` to send as the next
|
|
109
|
-
* `afterSeq`, and is null once nothing follows.
|
|
110
|
-
*/
|
|
111
|
-
export type WireJournalResponse = {
|
|
112
|
-
entries: WireJournalEntry[];
|
|
113
|
-
cursor: number | null;
|
|
114
|
-
};
|
|
115
|
-
/**
|
|
116
|
-
* The response envelope of `GET /records/:id/versions`.
|
|
117
|
-
*
|
|
118
|
-
* `cursor` is the only end-of-history signal, as on the journal: a server
|
|
119
|
-
* may cap a page below the `limit` asked for. It carries the `version` to
|
|
120
|
-
* send as the next `beforeVersion`, and is null once nothing follows.
|
|
121
|
-
*/
|
|
122
|
-
export type WireVersionsResponse = {
|
|
123
|
-
versions: WireVersion[];
|
|
124
|
-
cursor: number | null;
|
|
125
|
-
};
|
|
126
|
-
export declare function serializeJournalEntry(e: RecordJournalEntry): WireJournalEntry;
|
|
2
|
+
* @haverstack/wire-types
|
|
3
|
+
* -------------------------------------------------------
|
|
4
|
+
* The HTTP wire format's shapes and the encodings between them and core's
|
|
5
|
+
* types, shared by `@haverstack/adapter-api` and any server implementation
|
|
6
|
+
* so both sides read the same contract. One module per endpoint group, the
|
|
7
|
+
* same split `@haverstack/conformance-fixtures` uses. See
|
|
8
|
+
* docs/spec/wire-format.md.
|
|
9
|
+
*/
|
|
10
|
+
export type { WireActor, WireChangeActor, WireRecord, WireQueryResponse, WireType, WireVersion, WireVersionsResponse, } from './records.js';
|
|
11
|
+
export { serializeChangeActor, serializeRecord, serializeType, serializeVersion, } from './records.js';
|
|
12
|
+
export type { WireJournalEntry, WireJournalResponse } from './journal.js';
|
|
13
|
+
export { serializeJournalEntry } from './journal.js';
|
|
14
|
+
export type { WireErrorCode, WireError } from './errors.js';
|
|
15
|
+
export { WIRE_ERROR_STATUS, STATUS_TO_CODE, isWireError, serializeError, deserializeError, errorForStatus, } from './errors.js';
|
|
16
|
+
export type { DiscoveryResponse, DiscoveryCapabilities } from './discovery.js';
|
|
17
|
+
export { WIRE_PROTOCOL_VERSION, normalizeCapabilities, parseProtocolVersion, isProtocolCompatible, } from './discovery.js';
|
|
18
|
+
export type { DiscoveryAuth, AuthMethod, WireAuthChallengeRequest, WireAuthTokenRequest, WireAuthChallengeResponse, WireAuthTokenResponse, WireAuthErrorCode, WireAuthError, } from './auth.js';
|
|
19
|
+
export { AUTH_METHOD_DID_CHALLENGE, supportsDidChallenge, WIRE_AUTH_ERROR_STATUS, isWireAuthError, isRetryableAuthError, } from './auth.js';
|
|
20
|
+
export type { DiscoveryChanges, ChangeTransport, WireRecordChange, WireReadyFrame, ChangeResetReason, WireResetFrame, } from './change-feed.js';
|
|
21
|
+
export { CHANGE_TRANSPORT_SSE, supportsChangeFeed, serializeChange, CHANGE_FRAME_READY, CHANGE_FRAME_RECORD, CHANGE_FRAME_RESET, isValidCursor, } from './change-feed.js';
|
|
22
|
+
export type { DiscoveryInstalls, WireInstallRequest, WireInstallResponse } from './installs.js';
|
|
23
|
+
export { supportsInstallRequests } from './installs.js';
|
|
127
24
|
/**
|
|
128
25
|
* Re-exported from `@haverstack/core/wire`, which decodes wire dates on the
|
|
129
26
|
* request side too — one definition, the same way `WireErrorCode` aliases
|
|
130
27
|
* core's `StackErrorCode` rather than restating it.
|
|
131
28
|
*/
|
|
132
29
|
export { parseDate } from '@haverstack/core/wire';
|
|
133
|
-
/**
|
|
134
|
-
* Alias of core's StackErrorCode: the vocabulary belongs with the classes
|
|
135
|
-
* that carry it, and StackError.code is typed by it, so re-declaring the
|
|
136
|
-
* union here would be a second copy to drift.
|
|
137
|
-
*/
|
|
138
|
-
export type WireErrorCode = StackErrorCode;
|
|
139
|
-
export type WireError = {
|
|
140
|
-
error: {
|
|
141
|
-
code: WireErrorCode;
|
|
142
|
-
message: string;
|
|
143
|
-
/** Field-level validation failures. Only present for code: 'validation'. */
|
|
144
|
-
details?: ValidationError[];
|
|
145
|
-
/** ifVersion/If-Match precondition state. Only present for code: 'version_conflict'. */
|
|
146
|
-
versionConflict?: {
|
|
147
|
-
recordId: string;
|
|
148
|
-
expectedVersion: number;
|
|
149
|
-
actualVersion: number;
|
|
150
|
-
};
|
|
151
|
-
/** The rejected defineType() call's target and violations. Only present for code: 'schema_drift'. */
|
|
152
|
-
schemaDrift?: {
|
|
153
|
-
typeId: string;
|
|
154
|
-
violations: SchemaDriftViolation[];
|
|
155
|
-
};
|
|
156
|
-
};
|
|
157
|
-
};
|
|
158
|
-
/** Canonical HTTP status for each wire error code. */
|
|
159
|
-
export declare const WIRE_ERROR_STATUS: Record<WireErrorCode, number>;
|
|
160
|
-
/**
|
|
161
|
-
* Statuses that unambiguously imply a wire error code, for reconstructing
|
|
162
|
-
* an error from status alone when a response has no parseable wire error
|
|
163
|
-
* body. 500 is deliberately excluded — it would misclassify ordinary
|
|
164
|
-
* server bugs as StackMigrationError. See docs/spec/wire-format.md
|
|
165
|
-
* § Wire error body.
|
|
166
|
-
*/
|
|
167
|
-
export declare const STATUS_TO_CODE: Partial<Record<number, WireErrorCode>>;
|
|
168
|
-
/** Type guard: does this parsed JSON body look like a WireError? */
|
|
169
|
-
export declare function isWireError(body: unknown): body is WireError;
|
|
170
|
-
/**
|
|
171
|
-
* Convert a thrown core error into its wire response. Used by server
|
|
172
|
-
* implementations. Returns null for anything that isn't a StackError —
|
|
173
|
-
* callers fall back to their own generic error handling, so an ordinary bug
|
|
174
|
-
* stays a bare 500 rather than being dressed as a protocol error.
|
|
175
|
-
*/
|
|
176
|
-
export declare function serializeError(err: unknown): {
|
|
177
|
-
status: number;
|
|
178
|
-
body: WireError;
|
|
179
|
-
} | null;
|
|
180
|
-
/** Reconstruct the core error a WireError body describes. */
|
|
181
|
-
export declare function deserializeError(body: WireError): Error;
|
|
182
|
-
/**
|
|
183
|
-
* Reconstruct a core error from an HTTP status alone (no usable wire error
|
|
184
|
-
* body). Returns null for statuses with no unambiguous code — callers
|
|
185
|
-
* should fall back to a generic adapter-level error.
|
|
186
|
-
*/
|
|
187
|
-
export declare function errorForStatus(status: number, message: string): Error | null;
|
|
188
|
-
/**
|
|
189
|
-
* The wire protocol this package describes. Bump the major when a change
|
|
190
|
-
* would make an older client read a response wrongly; bump the minor for
|
|
191
|
-
* additions an older client can ignore. See docs/spec/wire-format.md
|
|
192
|
-
* § Version negotiation.
|
|
193
|
-
*/
|
|
194
|
-
export declare const WIRE_PROTOCOL_VERSION = "1.0";
|
|
195
|
-
/** GET /.well-known/stack. See docs/spec/wire-format.md § Discovery. */
|
|
196
|
-
export type DiscoveryResponse = {
|
|
197
|
-
version: string;
|
|
198
|
-
entityId: string;
|
|
199
|
-
timezone?: string;
|
|
200
|
-
capabilities?: DiscoveryCapabilities;
|
|
201
|
-
auth?: DiscoveryAuth;
|
|
202
|
-
changes?: DiscoveryChanges;
|
|
203
|
-
};
|
|
204
|
-
/**
|
|
205
|
-
* `capabilities` as it arrives, before normalizeCapabilities() reads it: a
|
|
206
|
-
* foreign server may omit any part of it, and may name a reach or a sort
|
|
207
|
-
* field this client has never heard of. Typed loosely on exactly the
|
|
208
|
-
* fields where that can happen, so the runtime checks that place them are
|
|
209
|
-
* visible as checks rather than as casts.
|
|
210
|
-
* See docs/spec/wire-format.md § Discovery.
|
|
211
|
-
*/
|
|
212
|
-
export type DiscoveryCapabilities = {
|
|
213
|
-
filter?: {
|
|
214
|
-
content?: string;
|
|
215
|
-
contentPresent?: boolean;
|
|
216
|
-
search?: boolean;
|
|
217
|
-
};
|
|
218
|
-
sort?: {
|
|
219
|
-
fields?: string[];
|
|
220
|
-
contentField?: boolean;
|
|
221
|
-
};
|
|
222
|
-
limits?: {
|
|
223
|
-
attachmentBytes?: number | null;
|
|
224
|
-
contentBytes?: number | null;
|
|
225
|
-
};
|
|
226
|
-
};
|
|
227
|
-
/**
|
|
228
|
-
* Read a discovery response's capabilities, resolving anything absent,
|
|
229
|
-
* malformed or unrecognized to the least capable value it could stand for
|
|
230
|
-
* — one rule, applied once, rather than a default per key at each call
|
|
231
|
-
* site. Silence is never a claim in either direction: a client that read
|
|
232
|
-
* an omitted flag as support would send a query the server drops and
|
|
233
|
-
* present the unfiltered superset that comes back as a filtered result.
|
|
234
|
-
*
|
|
235
|
-
* A `null` limit is the one entry that reads as permissive, because it
|
|
236
|
-
* says only that this client cannot pre-check; the server's own ceiling
|
|
237
|
-
* still answers with a 413.
|
|
238
|
-
* See docs/spec/adapters.md § Adapter capabilities.
|
|
239
|
-
*/
|
|
240
|
-
export declare function normalizeCapabilities(capabilities: DiscoveryCapabilities | undefined): StackCapabilities;
|
|
241
|
-
/**
|
|
242
|
-
* How a token can be earned here. Optional, and absent means only whatever
|
|
243
|
-
* issuance scheme the server arranged out of band — a client holding a DID
|
|
244
|
-
* credential then has nothing to perform and is told so at open(), rather
|
|
245
|
-
* than discovering it as a 404 partway through a handshake.
|
|
246
|
-
*
|
|
247
|
-
* An object rather than a boolean because issuance is the surface most
|
|
248
|
-
* likely to grow one: a consent flow arrives as another entry here.
|
|
249
|
-
*/
|
|
250
|
-
export type DiscoveryAuth = {
|
|
251
|
-
methods: AuthMethod[];
|
|
252
|
-
};
|
|
253
|
-
/** The challenge–response handshake of docs/spec/wire-format.md § Authentication. */
|
|
254
|
-
export declare const AUTH_METHOD_DID_CHALLENGE = "did-challenge";
|
|
255
|
-
export type AuthMethod = typeof AUTH_METHOD_DID_CHALLENGE;
|
|
256
|
-
/** Whether a server advertises the DID challenge–response handshake. */
|
|
257
|
-
export declare function supportsDidChallenge(discovery: DiscoveryResponse): boolean;
|
|
258
|
-
/**
|
|
259
|
-
* The change feed a server offers, absent when it offers none. An object
|
|
260
|
-
* rather than a boolean for the same reason `auth` is one: this surface
|
|
261
|
-
* grows entries — another transport, batched frames — and the alternative
|
|
262
|
-
* is a boolean followed by three more of them.
|
|
263
|
-
*
|
|
264
|
-
* See docs/spec/change-feed.md.
|
|
265
|
-
*/
|
|
266
|
-
export type DiscoveryChanges = {
|
|
267
|
-
transports: ChangeTransport[];
|
|
268
|
-
/**
|
|
269
|
-
* Whether a resume cursor is honored. `false` is conformant and means
|
|
270
|
-
* every reconnect is answered with a `reset` frame.
|
|
271
|
-
*/
|
|
272
|
-
resume: boolean;
|
|
273
|
-
/** Whether `?include=record` is honored. Never honored for a purge. */
|
|
274
|
-
records: boolean;
|
|
275
|
-
};
|
|
276
|
-
/** Server→client streaming over `fetch`. The only transport in this version. */
|
|
277
|
-
export declare const CHANGE_TRANSPORT_SSE = "sse";
|
|
278
|
-
export type ChangeTransport = typeof CHANGE_TRANSPORT_SSE;
|
|
279
|
-
/**
|
|
280
|
-
* Whether a server offers a change feed this client can consume. A client
|
|
281
|
-
* checks this and fails locally rather than learning it as a 404 partway
|
|
282
|
-
* through a connection — the same reason `auth.methods` exists.
|
|
283
|
-
*/
|
|
284
|
-
export declare function supportsChangeFeed(discovery: DiscoveryResponse): boolean;
|
|
285
|
-
/** POST /auth/challenge request. */
|
|
286
|
-
export type AuthChallengeRequest = {
|
|
287
|
-
did: string;
|
|
288
|
-
};
|
|
289
|
-
/** POST /auth/challenge response. */
|
|
290
|
-
export type AuthChallengeResponse = {
|
|
291
|
-
/** Opaque, single-use, base64url-charset. Bound to the requested DID. */
|
|
292
|
-
nonce: string;
|
|
293
|
-
expiresAt: string;
|
|
294
|
-
};
|
|
295
|
-
/** POST /auth/token request. `signature` is base64url. */
|
|
296
|
-
export type AuthTokenRequest = {
|
|
297
|
-
did: string;
|
|
298
|
-
nonce: string;
|
|
299
|
-
signature: string;
|
|
300
|
-
};
|
|
301
|
-
/**
|
|
302
|
-
* POST /auth/token response. Both identities are always present, and this
|
|
303
|
-
* endpoint always reports them equal — a handshake proves key possession,
|
|
304
|
-
* which says nothing about whom that key may act for. The pair is reported
|
|
305
|
-
* anyway so an issuance path that does delegate needs no new shape.
|
|
306
|
-
* See docs/spec/wire-format.md § Authentication.
|
|
307
|
-
*/
|
|
308
|
-
export type AuthTokenResponse = {
|
|
309
|
-
token: string;
|
|
310
|
-
expiresAt?: string;
|
|
311
|
-
principalId: string;
|
|
312
|
-
subjectId: string;
|
|
313
|
-
};
|
|
314
|
-
/**
|
|
315
|
-
* Auth failures have their own vocabulary, deliberately outside
|
|
316
|
-
* WireErrorCode: no Stack operation has begun, so none of them is a
|
|
317
|
-
* StackError and none has a class to reconstruct. The split a client acts
|
|
318
|
-
* on is retryable versus fatal — a stale nonce warrants a fresh handshake,
|
|
319
|
-
* a rejected signature never will.
|
|
320
|
-
*/
|
|
321
|
-
export type WireAuthErrorCode = 'invalid_did' | 'unknown_nonce' | 'expired_nonce' | 'invalid_signature';
|
|
322
|
-
export type WireAuthError = {
|
|
323
|
-
error: {
|
|
324
|
-
code: WireAuthErrorCode;
|
|
325
|
-
message: string;
|
|
326
|
-
};
|
|
327
|
-
};
|
|
328
|
-
export declare const WIRE_AUTH_ERROR_STATUS: Record<WireAuthErrorCode, number>;
|
|
329
|
-
/** Type guard: does this parsed JSON body look like a WireAuthError? */
|
|
330
|
-
export declare function isWireAuthError(body: unknown): body is WireAuthError;
|
|
331
|
-
/** Whether retrying the handshake from a fresh nonce could succeed. */
|
|
332
|
-
export declare function isRetryableAuthError(code: WireAuthErrorCode): boolean;
|
|
333
|
-
/**
|
|
334
|
-
* One change, as a `record` frame carries it. The envelope describes the
|
|
335
|
-
* change and nothing else: the record's own provenance rides `record`,
|
|
336
|
-
* where a consumer that wants it asks for it. See docs/spec/events.md
|
|
337
|
-
* § Attribution.
|
|
338
|
-
*/
|
|
339
|
-
export type WireRecordChange = {
|
|
340
|
-
kind: ChangeKind;
|
|
341
|
-
/** Every aspect this version moved; never empty. See RecordChange.ops. */
|
|
342
|
-
ops: ChangeOp[];
|
|
343
|
-
recordId: string;
|
|
344
|
-
typeId: string;
|
|
345
|
-
version: number;
|
|
346
|
-
updatedAt: string;
|
|
347
|
-
parentId?: string;
|
|
348
|
-
actor?: WireChangeActor;
|
|
349
|
-
/** Present when `ops` includes `associate`. See RecordChange.associationsAdded. */
|
|
350
|
-
associationsAdded?: DataAssociation[];
|
|
351
|
-
/** Present when `ops` includes `dissociate`. See RecordChange.associationsRemoved. */
|
|
352
|
-
associationsRemoved?: DataAssociation[];
|
|
353
|
-
record?: WireRecord;
|
|
354
|
-
cursor?: string;
|
|
355
|
-
};
|
|
356
|
-
/** Who performed a change. Never who authored the record. */
|
|
357
|
-
export type WireChangeActor = WireActor & {
|
|
358
|
-
appId?: string;
|
|
359
|
-
};
|
|
360
|
-
/** Shared by a change frame and a journal entry — one actor encoding, not two. */
|
|
361
|
-
export declare function serializeChangeActor(actor: ChangeActor): WireChangeActor;
|
|
362
|
-
/**
|
|
363
|
-
* A change as a server frames it. A purge carries neither the record nor
|
|
364
|
-
* its parent, whatever the subscriber asked for: purge is the
|
|
365
|
-
* erasure primitive, and a frame carrying the body — or anything else
|
|
366
|
-
* pointing at it — hands every subscriber a permanent copy of what the
|
|
367
|
-
* stack has just destroyed.
|
|
368
|
-
*
|
|
369
|
-
* The rule lives here rather than at each call site because a server holds
|
|
370
|
-
* the purged record at that moment, for the readability check it can only
|
|
371
|
-
* make before the write, and so is in exactly the position to leak it. See
|
|
372
|
-
* docs/spec/events.md § Purged records carry nothing.
|
|
373
|
-
*/
|
|
374
|
-
export declare function serializeChange(c: RecordChange): WireRecordChange;
|
|
375
|
-
/**
|
|
376
|
-
* Frame names. Every frame carries one, and a client MUST ignore a name it
|
|
377
|
-
* does not recognize — which is what makes a new frame an additive, minor
|
|
378
|
-
* change rather than a break. See docs/spec/change-feed.md.
|
|
379
|
-
*/
|
|
380
|
-
export declare const CHANGE_FRAME_READY = "ready";
|
|
381
|
-
export declare const CHANGE_FRAME_RECORD = "record";
|
|
382
|
-
export declare const CHANGE_FRAME_RESET = "reset";
|
|
383
|
-
/**
|
|
384
|
-
* Sent first on every connection, before any change. It is what makes
|
|
385
|
-
* subscribe-then-query gap-free: everything after it is in the stream.
|
|
386
|
-
*/
|
|
387
|
-
export type WireReadyFrame = {
|
|
388
|
-
/** The head cursor. Absent from a server that mints none (`resume: false`). */
|
|
389
|
-
cursor?: string;
|
|
390
|
-
};
|
|
391
|
-
/**
|
|
392
|
-
* Why a cursor could not be honored. Informational — a client's repair is
|
|
393
|
-
* the same for all three, and it is reconciling by query.
|
|
394
|
-
*/
|
|
395
|
-
export type ChangeResetReason = 'cursor_expired' | 'not_supported' | 'overflow';
|
|
396
|
-
/** Your cursor cannot be honored; resynchronize by query. */
|
|
397
|
-
export type WireResetFrame = {
|
|
398
|
-
reason: ChangeResetReason;
|
|
399
|
-
};
|
|
400
|
-
/** Whether a cursor is framable: unreserved base64url characters only. */
|
|
401
|
-
export declare function isValidCursor(cursor: string): boolean;
|
|
402
|
-
/** Splits a MAJOR.MINOR protocol version. Returns null if it isn't one. */
|
|
403
|
-
export declare function parseProtocolVersion(version: string): {
|
|
404
|
-
major: number;
|
|
405
|
-
minor: number;
|
|
406
|
-
} | null;
|
|
407
|
-
/**
|
|
408
|
-
* Majors must match; minors never have to. A higher server minor is additive
|
|
409
|
-
* fields this client ignores, and a higher client minor is optional fields
|
|
410
|
-
* the server may omit — neither can make a response read wrongly, which is
|
|
411
|
-
* the only thing a major bump signals.
|
|
412
|
-
*/
|
|
413
|
-
export declare function isProtocolCompatible(version: string, against?: string): boolean;
|
|
414
|
-
/**
|
|
415
|
-
* The body of `POST /records/:id/associations` and `/permissions`: one
|
|
416
|
-
* list, applied as one write. See docs/spec/wire-format.md § Associations.
|
|
417
|
-
*/
|
|
418
|
-
export type WireAssociationEditsRequest = {
|
|
419
|
-
changes: AssociationEdit[];
|
|
420
|
-
};
|
|
421
30
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,YAAY,EACV,SAAS,EACT,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,QAAQ,EACR,WAAW,EACX,oBAAoB,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,aAAa,EACb,gBAAgB,GACjB,MAAM,cAAc,CAAC;AAEtB,YAAY,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAErD,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,cAAc,GACf,MAAM,aAAa,CAAC;AAErB,YAAY,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAC/E,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AAExB,YAAY,EACV,aAAa,EACb,UAAU,EACV,wBAAwB,EACxB,oBAAoB,EACpB,yBAAyB,EACzB,qBAAqB,EACrB,iBAAiB,EACjB,aAAa,GACd,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,yBAAyB,EACzB,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EACf,oBAAoB,GACrB,MAAM,WAAW,CAAC;AAEnB,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,cAAc,GACf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,aAAa,GACd,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAChG,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAExD;;;;GAIG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC"}
|