@voltro/protocol 0.81.0 → 0.82.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/CHANGELOG.md +1520 -6
- package/dist/apikey.d.ts +2 -2
- package/dist/index.d.ts +607 -65
- package/dist/index.js +881 -644
- package/dist/inspect.d.ts +67 -1
- package/dist/inspect.js +95 -61
- package/dist/jwt.d.ts +1 -1
- package/dist/rest.d.ts +40 -3
- package/dist/rest.js +191 -159
- package/dist/{restFormat-CzdGVkuB.js → restFormat-EZ8k9ZcQ.js} +38 -33
- package/dist/{scopes-CvU5QBQ4.js → scopes-Di756ENh.js} +126 -106
- package/dist/session.d.ts +11 -0
- package/dist/session.js +53 -52
- package/dist/sessionHeader-DriTZhmv.js +7 -0
- package/package.json +3 -3
package/dist/inspect.d.ts
CHANGED
|
@@ -2,9 +2,9 @@ import { ParseOptions } from 'effect/SchemaAST';
|
|
|
2
2
|
import { Schema } from 'effect';
|
|
3
3
|
|
|
4
4
|
export declare const decodeInspectBackfillInput: (u: unknown, overrideOptions?: ParseOptions) => {
|
|
5
|
-
readonly from: string;
|
|
6
5
|
readonly name: string;
|
|
7
6
|
readonly limit: number;
|
|
7
|
+
readonly from: string;
|
|
8
8
|
readonly to: string;
|
|
9
9
|
readonly requestId: string;
|
|
10
10
|
readonly confirm: boolean;
|
|
@@ -78,6 +78,72 @@ export declare type InspectReplicaSelection = {
|
|
|
78
78
|
readonly replicaIds: ReadonlyArray<string>;
|
|
79
79
|
};
|
|
80
80
|
|
|
81
|
+
export declare type InspectWorkflowExecutionObservation = typeof InspectWorkflowExecutionObservationSchema.Type;
|
|
82
|
+
|
|
83
|
+
/** A projection of engine evidence, not a run-row or recorder-entry claim.
|
|
84
|
+
* Deliberately excludes payloads, outputs, raw causes and journal identifiers. */
|
|
85
|
+
export declare const InspectWorkflowExecutionObservationSchema: Schema.Union<[Schema.Struct<{
|
|
86
|
+
kind: Schema.Literal<["not-observed"]>;
|
|
87
|
+
workflowName: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
88
|
+
executionId: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
89
|
+
}>, Schema.Struct<{
|
|
90
|
+
kind: Schema.Literal<["pending"]>;
|
|
91
|
+
workflowName: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
92
|
+
executionId: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
93
|
+
}>, Schema.Struct<{
|
|
94
|
+
kind: Schema.Literal<["delivery-failed"]>;
|
|
95
|
+
workflowName: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
96
|
+
executionId: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
97
|
+
}>, Schema.Struct<{
|
|
98
|
+
kind: Schema.Literal<["suspended"]>;
|
|
99
|
+
workflowName: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
100
|
+
executionId: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
101
|
+
}>, Schema.Struct<{
|
|
102
|
+
kind: Schema.Literal<["completed"]>;
|
|
103
|
+
outcome: Schema.Literal<["succeeded", "failed", "cancelled"]>;
|
|
104
|
+
workflowName: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
105
|
+
executionId: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
106
|
+
}>]>;
|
|
107
|
+
|
|
108
|
+
export declare type InspectWorkflowExecutionTarget = typeof InspectWorkflowExecutionTargetSchema.Type;
|
|
109
|
+
|
|
110
|
+
/** Read an existing execution identity; this is never a start command. */
|
|
111
|
+
export declare const InspectWorkflowExecutionTargetSchema: Schema.Struct<{
|
|
112
|
+
workflowName: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
113
|
+
executionId: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
114
|
+
}>;
|
|
115
|
+
|
|
116
|
+
export declare type InspectWorkflowQueuedStartObservation = typeof InspectWorkflowQueuedStartObservationSchema.Type;
|
|
117
|
+
|
|
118
|
+
/** Read-only admission evidence. Accepted means an execution exists, not that it succeeded. */
|
|
119
|
+
export declare const InspectWorkflowQueuedStartObservationSchema: Schema.Union<[Schema.Struct<{
|
|
120
|
+
kind: Schema.Literal<["pending"]>;
|
|
121
|
+
workflowName: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
122
|
+
receiptId: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
123
|
+
tenantId: Schema.NullOr<Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>>;
|
|
124
|
+
}>, Schema.Struct<{
|
|
125
|
+
kind: Schema.Literal<["accepted"]>;
|
|
126
|
+
executionId: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
127
|
+
workflowName: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
128
|
+
receiptId: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
129
|
+
tenantId: Schema.NullOr<Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>>;
|
|
130
|
+
}>, Schema.Struct<{
|
|
131
|
+
kind: Schema.Literal<["not-executed"]>;
|
|
132
|
+
reason: Schema.Literal<["dropped", "skipped", "superseded", "cancelled", "abandoned", "rejected"]>;
|
|
133
|
+
workflowName: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
134
|
+
receiptId: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
135
|
+
tenantId: Schema.NullOr<Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>>;
|
|
136
|
+
}>]>;
|
|
137
|
+
|
|
138
|
+
export declare type InspectWorkflowQueuedStartTarget = typeof InspectWorkflowQueuedStartTargetSchema.Type;
|
|
139
|
+
|
|
140
|
+
/** A caller receipt, never an execution or a reusable admission slot. */
|
|
141
|
+
export declare const InspectWorkflowQueuedStartTargetSchema: Schema.Struct<{
|
|
142
|
+
workflowName: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
143
|
+
receiptId: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
144
|
+
tenantId: Schema.NullOr<Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>>;
|
|
145
|
+
}>;
|
|
146
|
+
|
|
81
147
|
export declare class InvalidReplicaSelection extends Error {
|
|
82
148
|
readonly name = "InvalidReplicaSelection";
|
|
83
149
|
}
|
package/dist/inspect.js
CHANGED
|
@@ -1,85 +1,119 @@
|
|
|
1
1
|
import { Schema as e } from "effect";
|
|
2
|
-
//#region src/
|
|
3
|
-
var t = e.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
//#region src/inspectWorkflowQueuedStart.ts
|
|
3
|
+
var t = e.NonEmptyString.pipe(e.maxLength(1024), e.filter((e) => e.trim().length > 0 && !/[\u0000-\u001f\u007f]/.test(e))), n = e.Struct({
|
|
4
|
+
workflowName: t,
|
|
5
|
+
receiptId: t,
|
|
6
|
+
tenantId: e.NullOr(t)
|
|
7
|
+
}), r = n.fields, i = e.Union(e.Struct({
|
|
8
|
+
...r,
|
|
9
|
+
kind: e.Literal("pending")
|
|
10
|
+
}), e.Struct({
|
|
11
|
+
...r,
|
|
12
|
+
kind: e.Literal("accepted"),
|
|
13
|
+
executionId: t
|
|
14
|
+
}), e.Struct({
|
|
15
|
+
...r,
|
|
16
|
+
kind: e.Literal("not-executed"),
|
|
17
|
+
reason: e.Literal("dropped", "skipped", "superseded", "cancelled", "abandoned", "rejected")
|
|
18
|
+
})), a = e.String.pipe(e.filter((e) => Number.isFinite(Date.parse(e)))), o = e.String.pipe(e.minLength(1), e.maxLength(256)), s = e.Struct({
|
|
19
|
+
id: o,
|
|
20
|
+
name: o,
|
|
21
|
+
from: a,
|
|
22
|
+
to: a,
|
|
8
23
|
occurrences: e.Array(e.Number),
|
|
9
24
|
status: e.Literal("queued", "running", "completed", "interrupted"),
|
|
10
25
|
owner: e.NullOr(e.String),
|
|
11
|
-
createdAt:
|
|
12
|
-
updatedAt:
|
|
26
|
+
createdAt: a,
|
|
27
|
+
updatedAt: a,
|
|
13
28
|
cursor: e.Number,
|
|
14
29
|
activeIndex: e.NullOr(e.Number),
|
|
15
30
|
results: e.Array(e.Struct({
|
|
16
|
-
runId:
|
|
31
|
+
runId: o,
|
|
17
32
|
status: e.Literal("succeeded", "failed", "skipped", "missed")
|
|
18
33
|
})),
|
|
19
34
|
error: e.NullOr(e.String)
|
|
20
|
-
}),
|
|
21
|
-
requestId:
|
|
22
|
-
name:
|
|
23
|
-
from:
|
|
24
|
-
to:
|
|
35
|
+
}), c = e.Struct({
|
|
36
|
+
requestId: o,
|
|
37
|
+
name: o,
|
|
38
|
+
from: a,
|
|
39
|
+
to: a,
|
|
25
40
|
confirm: e.Boolean,
|
|
26
41
|
limit: e.Number.pipe(e.int(), e.between(1, 1e4))
|
|
27
|
-
}),
|
|
42
|
+
}), l = e.decodeUnknownSync(c), u = e.Union(e.Struct({
|
|
28
43
|
kind: e.Literal("accepted"),
|
|
29
|
-
request:
|
|
44
|
+
request: s
|
|
30
45
|
}), e.Struct({
|
|
31
46
|
kind: e.Literal("refused"),
|
|
32
|
-
name:
|
|
47
|
+
name: o,
|
|
33
48
|
occurrences: e.Number,
|
|
34
49
|
reason: e.String
|
|
35
|
-
})),
|
|
50
|
+
})), d = class extends Error {
|
|
36
51
|
name = "ScheduleBackfillRequestConflict";
|
|
37
|
-
},
|
|
52
|
+
}, f = e.NonEmptyString.pipe(e.maxLength(1024), e.filter((e) => e.trim().length > 0 && !/[\u0000-\u001f\u007f]/.test(e))), p = e.Struct({
|
|
53
|
+
workflowName: f,
|
|
54
|
+
executionId: f
|
|
55
|
+
}), m = p.fields, h = e.Union(e.Struct({
|
|
56
|
+
...m,
|
|
57
|
+
kind: e.Literal("not-observed")
|
|
58
|
+
}), e.Struct({
|
|
59
|
+
...m,
|
|
60
|
+
kind: e.Literal("pending")
|
|
61
|
+
}), e.Struct({
|
|
62
|
+
...m,
|
|
63
|
+
kind: e.Literal("delivery-failed")
|
|
64
|
+
}), e.Struct({
|
|
65
|
+
...m,
|
|
66
|
+
kind: e.Literal("suspended")
|
|
67
|
+
}), e.Struct({
|
|
68
|
+
...m,
|
|
69
|
+
kind: e.Literal("completed"),
|
|
70
|
+
outcome: e.Literal("succeeded", "failed", "cancelled")
|
|
71
|
+
})), g = (e) => typeof e == "object" && e && !Array.isArray(e) ? e : void 0, _ = (e) => Array.isArray(e) && e.every((e) => g(e) !== void 0) ? e : void 0, v = (e) => typeof e == "number" && Number.isFinite(e) ? e : 0, y = /* @__PURE__ */ new Set([
|
|
38
72
|
"counter",
|
|
39
73
|
"gauge",
|
|
40
74
|
"histogram",
|
|
41
75
|
"summary",
|
|
42
76
|
"frequency"
|
|
43
|
-
]),
|
|
44
|
-
let t =
|
|
45
|
-
return t?.every((e) => typeof e.name == "string" &&
|
|
46
|
-
},
|
|
47
|
-
let t =
|
|
77
|
+
]), b = (e) => {
|
|
78
|
+
let t = _(e);
|
|
79
|
+
return t?.every((e) => typeof e.name == "string" && y.has(String(e.type))) ? t : void 0;
|
|
80
|
+
}, x = (e) => {
|
|
81
|
+
let t = g(e), n = g(t?.data), r = _(n?.results);
|
|
48
82
|
if (!t || !n?.selection || !r) return e;
|
|
49
83
|
let i = r.filter((e) => e.status === "answered").map((e) => ({
|
|
50
84
|
replicaId: String(e.replicaId),
|
|
51
|
-
observation:
|
|
52
|
-
data:
|
|
85
|
+
observation: g(e.observation),
|
|
86
|
+
data: g(e.observation)?.data
|
|
53
87
|
}));
|
|
54
88
|
if (i.length === 0) throw Error("None of the selected replicas answered. Check replica availability and retry.");
|
|
55
89
|
let a = i.map((e) => ({
|
|
56
90
|
...e,
|
|
57
|
-
object:
|
|
58
|
-
})), o = (e) => a.reduce((t, n) => t +
|
|
91
|
+
object: g(e.data)
|
|
92
|
+
})), o = (e) => a.reduce((t, n) => t + v(n.object?.[e]), 0), s = Math.max(...i.map((e) => v(e.observation?.capturedAt))), c = {
|
|
59
93
|
capturedAt: s,
|
|
60
94
|
bufferSize: o("bufferSize"),
|
|
61
95
|
bufferCapacity: o("bufferCapacity")
|
|
62
|
-
},
|
|
63
|
-
if (a.every((e) =>
|
|
64
|
-
let e = a.flatMap((e) =>
|
|
96
|
+
}, l;
|
|
97
|
+
if (a.every((e) => _(e.object?.records))) {
|
|
98
|
+
let e = a.flatMap((e) => _(e.object?.records).map((t) => ({
|
|
65
99
|
...t,
|
|
66
100
|
fields: {
|
|
67
|
-
...
|
|
101
|
+
...g(t.fields),
|
|
68
102
|
"voltro.replica": e.replicaId
|
|
69
103
|
}
|
|
70
|
-
}))).sort((e, t) =>
|
|
71
|
-
|
|
72
|
-
...
|
|
104
|
+
}))).sort((e, t) => v(e.ts) - v(t.ts));
|
|
105
|
+
l = {
|
|
106
|
+
...c,
|
|
73
107
|
returned: e.length,
|
|
74
108
|
records: e
|
|
75
109
|
};
|
|
76
|
-
} else if (a.every((e) =>
|
|
110
|
+
} else if (a.every((e) => _(e.object?.traces))) {
|
|
77
111
|
let e = /* @__PURE__ */ new Map();
|
|
78
|
-
for (let t of a) for (let n of
|
|
79
|
-
let r = String(n.traceId), i = (
|
|
112
|
+
for (let t of a) for (let n of _(t.object?.traces)) {
|
|
113
|
+
let r = String(n.traceId), i = (_(n.spans) ?? []).map((e) => ({
|
|
80
114
|
...e,
|
|
81
115
|
attributes: {
|
|
82
|
-
...
|
|
116
|
+
...g(e.attributes),
|
|
83
117
|
"voltro.replica": t.replicaId
|
|
84
118
|
}
|
|
85
119
|
})), a = e.get(r) ?? [];
|
|
@@ -89,7 +123,7 @@ var t = e.String.pipe(e.filter((e) => Number.isFinite(Date.parse(e)))), n = e.St
|
|
|
89
123
|
}), e.set(r, a);
|
|
90
124
|
}
|
|
91
125
|
let t = [...e.values()].map((e) => {
|
|
92
|
-
let t = e.flatMap((e) =>
|
|
126
|
+
let t = e.flatMap((e) => _(e.spans) ?? []).sort((e, t) => v(e.startMs) - v(t.startMs)), n = [...e].sort((e, t) => v(e.startMs) - v(t.startMs))[0], r = Math.min(...e.map((e) => v(e.startMs))), i = Math.max(...e.map((e) => v(e.startMs) + v(e.durationMs)));
|
|
93
127
|
return {
|
|
94
128
|
...n,
|
|
95
129
|
startMs: r,
|
|
@@ -97,65 +131,65 @@ var t = e.String.pipe(e.filter((e) => Number.isFinite(Date.parse(e)))), n = e.St
|
|
|
97
131
|
spanCount: t.length,
|
|
98
132
|
hasError: e.some((e) => e.hasError === !0),
|
|
99
133
|
spans: t,
|
|
100
|
-
...e.some((e) => e.deliveryCount !== void 0) ? { deliveryCount: e.reduce((e, t) => e +
|
|
101
|
-
...e.some((e) => e.lastDeliveryMs !== void 0) ? { lastDeliveryMs: Math.max(...e.map((e) =>
|
|
134
|
+
...e.some((e) => e.deliveryCount !== void 0) ? { deliveryCount: e.reduce((e, t) => e + v(t.deliveryCount), 0) } : {},
|
|
135
|
+
...e.some((e) => e.lastDeliveryMs !== void 0) ? { lastDeliveryMs: Math.max(...e.map((e) => v(e.lastDeliveryMs))) } : {}
|
|
102
136
|
};
|
|
103
137
|
}).sort((e, t) => t.startMs - e.startMs);
|
|
104
|
-
|
|
105
|
-
...
|
|
138
|
+
l = {
|
|
139
|
+
...c,
|
|
106
140
|
returned: t.length,
|
|
107
141
|
traces: t
|
|
108
142
|
};
|
|
109
|
-
} else if (a.every((e) =>
|
|
143
|
+
} else if (a.every((e) => _(e.object?.buckets) && typeof e.object?.windowMs == "number")) l = {
|
|
110
144
|
capturedAt: s,
|
|
111
|
-
windowMs: Math.max(...a.map((e) =>
|
|
145
|
+
windowMs: Math.max(...a.map((e) => v(e.object?.windowMs))),
|
|
112
146
|
totalSamples: o("totalSamples"),
|
|
113
|
-
buckets: a.flatMap((e) =>
|
|
147
|
+
buckets: a.flatMap((e) => _(e.object?.buckets).map((t) => ({
|
|
114
148
|
...t,
|
|
115
149
|
tag: `${String(t.tag)} [${e.replicaId}]`
|
|
116
150
|
})))
|
|
117
151
|
};
|
|
118
|
-
else if (i.every((e) =>
|
|
152
|
+
else if (i.every((e) => b(e.data))) l = i.flatMap((e) => b(e.data).map((t) => ({
|
|
119
153
|
...t,
|
|
120
154
|
labels: {
|
|
121
|
-
...
|
|
155
|
+
...g(t.labels),
|
|
122
156
|
voltro_replica: e.replicaId
|
|
123
157
|
}
|
|
124
158
|
})));
|
|
125
|
-
else if (a.every((e) =>
|
|
159
|
+
else if (a.every((e) => b(e.object?.samples))) l = { samples: a.flatMap((e) => b(e.object?.samples).map((t) => ({
|
|
126
160
|
...t,
|
|
127
161
|
labels: {
|
|
128
|
-
...
|
|
162
|
+
...g(t.labels),
|
|
129
163
|
voltro_replica: e.replicaId
|
|
130
164
|
}
|
|
131
165
|
}))) };
|
|
132
|
-
else if (r.length === 1 && i.length === 1)
|
|
166
|
+
else if (r.length === 1 && i.length === 1) l = i[0].data;
|
|
133
167
|
else throw Error("This view must compare observations per replica; its values cannot be safely combined.");
|
|
134
168
|
return {
|
|
135
169
|
...t,
|
|
136
|
-
data:
|
|
170
|
+
data: l
|
|
137
171
|
};
|
|
138
|
-
},
|
|
172
|
+
}, S = class extends Error {
|
|
139
173
|
name = "InvalidReplicaSelection";
|
|
140
|
-
},
|
|
174
|
+
}, C = (e) => {
|
|
141
175
|
let t = e.getAll("replicas"), n = e.getAll("replica");
|
|
142
176
|
if (t.length !== 0 || n.length !== 0) {
|
|
143
|
-
if (t.length > 1 || t.length === 1 && t[0] !== "all" || t.length > 0 && n.length > 0) throw new
|
|
177
|
+
if (t.length > 1 || t.length === 1 && t[0] !== "all" || t.length > 0 && n.length > 0) throw new S("Choose all replicas or explicit replica IDs, not both.");
|
|
144
178
|
if (t[0] === "all") return { mode: "all" };
|
|
145
|
-
if (n.some((e) => e.trim().length === 0 || e.length > 512 || /[\u0000-\u001f\u007f]/.test(e))) throw new
|
|
179
|
+
if (n.some((e) => e.trim().length === 0 || e.length > 512 || /[\u0000-\u001f\u007f]/.test(e))) throw new S("Replica IDs must be nonempty and contain no control characters.");
|
|
146
180
|
return {
|
|
147
181
|
mode: "selected",
|
|
148
182
|
replicaIds: [...new Set(n)].sort()
|
|
149
183
|
};
|
|
150
184
|
}
|
|
151
|
-
},
|
|
185
|
+
}, w = (e, t) => {
|
|
152
186
|
let n = e.indexOf("#"), r = n < 0 ? "" : e.slice(n), i = n < 0 ? e : e.slice(0, n), a = i.indexOf("?"), o = a < 0 ? i : i.slice(0, a), s = new URLSearchParams(a < 0 ? "" : i.slice(a + 1));
|
|
153
187
|
if (s.delete("replica"), s.delete("replicas"), t.mode === "all") s.set("replicas", "all");
|
|
154
188
|
else {
|
|
155
|
-
if (t.replicaIds.length === 0) throw new
|
|
189
|
+
if (t.replicaIds.length === 0) throw new S("Select at least one replica.");
|
|
156
190
|
for (let e of [...new Set(t.replicaIds)].sort()) s.append("replica", e);
|
|
157
191
|
}
|
|
158
|
-
return
|
|
192
|
+
return C(s), `${o}?${s}${r}`;
|
|
159
193
|
};
|
|
160
194
|
//#endregion
|
|
161
|
-
export {
|
|
195
|
+
export { c as InspectBackfillInputSchema, s as InspectBackfillReceiptSchema, u as InspectBackfillResultSchema, h as InspectWorkflowExecutionObservationSchema, p as InspectWorkflowExecutionTargetSchema, i as InspectWorkflowQueuedStartObservationSchema, n as InspectWorkflowQueuedStartTargetSchema, S as InvalidReplicaSelection, d as ScheduleBackfillRequestConflict, l as decodeInspectBackfillInput, C as parseReplicaSelection, x as projectReplicaObservation, w as withReplicaSelection };
|
package/dist/jwt.d.ts
CHANGED
|
@@ -26,7 +26,7 @@ declare interface AuthStrategy {
|
|
|
26
26
|
readonly resolve: (input: AuthStrategyInput) => Promise<StrategyResolution> | StrategyResolution;
|
|
27
27
|
/**
|
|
28
28
|
* The bearer-token PREFIX this strategy claims, when it gates on one
|
|
29
|
-
* (`'sk_'`, `'
|
|
29
|
+
* (`'sk_'`, `'acme_'`). Declared so a collision is DETECTABLE.
|
|
30
30
|
*
|
|
31
31
|
* Two strategies claiming the same prefix is not a harmless duplicate: the
|
|
32
32
|
* chain is first-match-wins, so whichever runs first decides the Subject —
|
package/dist/rest.d.ts
CHANGED
|
@@ -440,7 +440,7 @@ declare interface NestedTargetFields<Input = unknown> {
|
|
|
440
440
|
/** Guard WHICH cached query entries this target patches: only entries whose
|
|
441
441
|
* CURRENT value satisfies the predicate. Pure + browser-safe. Prevents a
|
|
442
442
|
* patch from bleeding across sibling subscriptions that share a source table
|
|
443
|
-
* (the guard
|
|
443
|
+
* (the guard an app would otherwise hand-write as `roadmap.id === input.roadmapId`). Absent →
|
|
444
444
|
* every entry matching the target `table` is patched. */
|
|
445
445
|
readonly match?: ((value: unknown, input: Input) => boolean) | undefined;
|
|
446
446
|
}
|
|
@@ -799,7 +799,8 @@ export declare const problemTypeOf: (tag: string) => string;
|
|
|
799
799
|
* and the status `errorStatus` assigns (`422` by default, the status the
|
|
800
800
|
* OpenAPI projection already documents for a typed error); a plugin's
|
|
801
801
|
* cross-cutting error answers under the status the plugin names. Anything
|
|
802
|
-
* else is rethrown for the desugar's shared mapping (`ScopeError` → 403/401,
|
|
802
|
+
* else is rethrown for the desugar's shared mapping (`ScopeError` → 403/401,
|
|
803
|
+
* a resource guard's `NoSuchResource` → 404, a
|
|
803
804
|
* `status`-carrying error → itself, the rest → 500). The body is the tagged
|
|
804
805
|
* `{ error, …fields }` form; `projectedFailureFor` speaks the profile.
|
|
805
806
|
*/
|
|
@@ -986,6 +987,13 @@ declare interface PublicApiSpec {
|
|
|
986
987
|
* optional, the rest inherited. See `PublicApiProfileConfig`.
|
|
987
988
|
*/
|
|
988
989
|
readonly format?: PublicApiProfileConfig;
|
|
990
|
+
/**
|
|
991
|
+
* GET only: how long a CDN may keep a successful answer, and the tags it can
|
|
992
|
+
* purge it by (`Cache-Tag`, `Surrogate-Key`). A request with a credential is
|
|
993
|
+
* always answered `private` — see `RestCache`. `tags` receives the answer as
|
|
994
|
+
* it goes on the wire.
|
|
995
|
+
*/
|
|
996
|
+
readonly cache?: RestCache;
|
|
989
997
|
}
|
|
990
998
|
|
|
991
999
|
/**
|
|
@@ -1179,6 +1187,27 @@ export declare interface RestByteResponse {
|
|
|
1179
1187
|
readonly headers?: Readonly<Record<string, string | ReadonlyArray<string>>>;
|
|
1180
1188
|
}
|
|
1181
1189
|
|
|
1190
|
+
/**
|
|
1191
|
+
* Caching for a GET route's successful (200) answers.
|
|
1192
|
+
*
|
|
1193
|
+
* An anonymous request's answer is `public` for `maxAge` seconds (`max-age`
|
|
1194
|
+
* and `s-maxage`), `stale-while-revalidate` when set, and carries `tags` as
|
|
1195
|
+
* `Cache-Tag` (comma-separated) and `Surrogate-Key` (space-separated) — the
|
|
1196
|
+
* headers CDNs purge by. A request that carries a credential (`Authorization`
|
|
1197
|
+
* or a cookie) gets `private, no-cache` and no tags, whatever is declared:
|
|
1198
|
+
* what a key or a session may see must never land in a shared cache. Every
|
|
1199
|
+
* such answer says `Vary: Authorization, Cookie`. Errors are not affected.
|
|
1200
|
+
*/
|
|
1201
|
+
export declare interface RestCache {
|
|
1202
|
+
/** Seconds a cache may serve the answer without asking again. */
|
|
1203
|
+
readonly maxAge: number;
|
|
1204
|
+
/** Seconds after that a stale answer may still be served while the cache refetches. */
|
|
1205
|
+
readonly staleWhileRevalidate?: number;
|
|
1206
|
+
/** Purge tags from the answer as it goes on the wire, and the input.
|
|
1207
|
+
* A tag with whitespace or a comma is dropped (no header can carry it). */
|
|
1208
|
+
readonly tags?: (output: unknown, input: unknown) => ReadonlyArray<string>;
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1182
1211
|
export declare type RestDates = 'iso' | 'epoch-ms';
|
|
1183
1212
|
|
|
1184
1213
|
export declare type RestEnvelope = 'none' | 'data' | 'jsonapi';
|
|
@@ -1270,6 +1299,11 @@ export declare interface RestGuardRejection {
|
|
|
1270
1299
|
readonly message: string;
|
|
1271
1300
|
}
|
|
1272
1301
|
|
|
1302
|
+
/** What a REST handler may return: the decoded output, a `response(...)` with
|
|
1303
|
+
* its own status and headers, an `sse(...)` stream, or `bytes(...)` for a
|
|
1304
|
+
* non-JSON body (a file, an export, an XML document). */
|
|
1305
|
+
export declare type RestHandlerResult<O> = O | RestResponse<O> | RestStreamResponse | RestByteResponse;
|
|
1306
|
+
|
|
1273
1307
|
export declare type RestMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
|
|
1274
1308
|
|
|
1275
1309
|
export declare type RestNaming = 'camelCase' | 'snake_case';
|
|
@@ -1333,7 +1367,7 @@ export declare interface RestRouteDescriptor<I, O> {
|
|
|
1333
1367
|
/** Output schema. The handler returns the decoded `Type`; the desugar
|
|
1334
1368
|
* encodes it to JSON for the `200` response. */
|
|
1335
1369
|
readonly output: Schema.Schema<O, any, never>;
|
|
1336
|
-
readonly handler: (input: I, ctx: RestRouteContext) => Promise<
|
|
1370
|
+
readonly handler: (input: I, ctx: RestRouteContext) => Promise<RestHandlerResult<O>> | RestHandlerResult<O>;
|
|
1337
1371
|
readonly summary?: string;
|
|
1338
1372
|
readonly description?: string;
|
|
1339
1373
|
readonly example?: RestRouteExample;
|
|
@@ -1390,6 +1424,9 @@ export declare interface RestRouteDescriptor<I, O> {
|
|
|
1390
1424
|
* of the JSON), so it is correct across content-encodings — the
|
|
1391
1425
|
* transport's compression varies the bytes, not the representation. */
|
|
1392
1426
|
readonly etag?: boolean;
|
|
1427
|
+
/** GET only: how long a shared cache (a CDN) may keep a successful answer,
|
|
1428
|
+
* and the tags it can be purged by. See {@link RestCache}. */
|
|
1429
|
+
readonly cache?: RestCache;
|
|
1393
1430
|
}
|
|
1394
1431
|
|
|
1395
1432
|
/** Intentional non-2xx REST control flow with an application-defined JSON
|