@reliantlabs/forge-web-runtime 0.13.3 → 0.13.4

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.
@@ -0,0 +1,61 @@
1
+ import type { DescField } from "@bufbuild/protobuf";
2
+ export interface NumRules {
3
+ const?: number;
4
+ lt?: number;
5
+ lte?: number;
6
+ gt?: number;
7
+ gte?: number;
8
+ in?: number[];
9
+ notIn?: number[];
10
+ }
11
+ export interface StrRules {
12
+ const?: string;
13
+ len?: number;
14
+ minLen?: number;
15
+ maxLen?: number;
16
+ pattern?: string;
17
+ prefix?: string;
18
+ suffix?: string;
19
+ contains?: string;
20
+ in?: string[];
21
+ notIn?: string[];
22
+ format?: StrFormat;
23
+ }
24
+ export type StrFormat = "email" | "hostname" | "ip" | "ipv4" | "ipv6" | "uri" | "address" | "uuid" | "tuuid" | "ulid" | "hostAndPort" | "ipPrefix";
25
+ export interface EnumRules {
26
+ const?: number;
27
+ in?: number[];
28
+ notIn?: number[];
29
+ }
30
+ export interface FieldRules {
31
+ bool?: boolean;
32
+ num?: NumRules;
33
+ str?: StrRules;
34
+ bytes?: {
35
+ len?: number;
36
+ minLen?: number;
37
+ maxLen?: number;
38
+ };
39
+ enm?: EnumRules;
40
+ repeated?: {
41
+ minItems?: number;
42
+ maxItems?: number;
43
+ items?: FieldRules;
44
+ };
45
+ map?: {
46
+ minPairs?: number;
47
+ maxPairs?: number;
48
+ keys?: FieldRules;
49
+ values?: FieldRules;
50
+ };
51
+ /** Seconds. */
52
+ duration?: NumRules;
53
+ /** Epoch milliseconds; `ltNow`/`gtNow` relative to the anchor. */
54
+ timestamp?: NumRules & {
55
+ ltNow?: boolean;
56
+ gtNow?: boolean;
57
+ withinMs?: number;
58
+ };
59
+ }
60
+ /** The field's protovalidate rules, or undefined when it declares none. */
61
+ export declare function rulesOf(field: DescField): FieldRules | undefined;
@@ -0,0 +1,333 @@
1
+ import { BinaryReader, WireType } from "@bufbuild/protobuf/wire";
2
+ // ── protovalidate rules, decoded from the embedded descriptor ───────────
3
+ //
4
+ // buf.validate.field is extension 1159 on FieldOptions. protobuf-es keeps an
5
+ // unregistered extension as an unknown field of the options message, so the
6
+ // rules are read from there with the wire reader. Field numbers follow
7
+ // buf/validate/validate.proto; numeric rule messages share one layout
8
+ // (const=1, lt=2, lte=3, gt=4, gte=5, in=6, not_in=7).
9
+ const VALIDATE_FIELD_EXT = 1159;
10
+ const STRING_FORMATS = {
11
+ 12: "email",
12
+ 13: "hostname",
13
+ 14: "ip",
14
+ 15: "ipv4",
15
+ 16: "ipv6",
16
+ 17: "uri",
17
+ 18: "uri",
18
+ 21: "address",
19
+ 22: "uuid",
20
+ 33: "tuuid",
21
+ 35: "ulid",
22
+ 32: "hostAndPort",
23
+ 26: "ipPrefix",
24
+ 27: "ipPrefix",
25
+ 28: "ipPrefix",
26
+ 29: "ipPrefix",
27
+ 30: "ipPrefix",
28
+ 31: "ipPrefix",
29
+ };
30
+ /** Read one numeric rule value of FieldRules type `t` (1 float … 12 sfixed64). */
31
+ function readNumber(r, t) {
32
+ switch (t) {
33
+ case 1:
34
+ return r.float();
35
+ case 2:
36
+ return r.double();
37
+ case 3:
38
+ return r.int32();
39
+ case 4:
40
+ return Number(r.int64());
41
+ case 5:
42
+ return r.uint32();
43
+ case 6:
44
+ return Number(r.uint64());
45
+ case 7:
46
+ return r.sint32();
47
+ case 8:
48
+ return Number(r.sint64());
49
+ case 9:
50
+ return r.fixed32();
51
+ case 10:
52
+ return Number(r.fixed64());
53
+ case 11:
54
+ return r.sfixed32();
55
+ default:
56
+ return Number(r.sfixed64());
57
+ }
58
+ }
59
+ /** Every value of a (possibly packed) repeated numeric field. */
60
+ function readRepeated(r, wire, read) {
61
+ if (wire !== WireType.LengthDelimited)
62
+ return [read(r)];
63
+ const sub = new BinaryReader(r.bytes());
64
+ const out = [];
65
+ while (sub.pos < sub.len)
66
+ out.push(read(sub));
67
+ return out;
68
+ }
69
+ function decodeNumRules(bytes, read) {
70
+ const r = new BinaryReader(bytes);
71
+ const out = {};
72
+ while (r.pos < r.len) {
73
+ const [no, wire] = r.tag();
74
+ switch (no) {
75
+ case 1:
76
+ out.const = read(r);
77
+ break;
78
+ case 2:
79
+ out.lt = read(r);
80
+ break;
81
+ case 3:
82
+ out.lte = read(r);
83
+ break;
84
+ case 4:
85
+ out.gt = read(r);
86
+ break;
87
+ case 5:
88
+ out.gte = read(r);
89
+ break;
90
+ case 6:
91
+ (out.in ??= []).push(...readRepeated(r, wire, read));
92
+ break;
93
+ case 7:
94
+ (out.notIn ??= []).push(...readRepeated(r, wire, read));
95
+ break;
96
+ default:
97
+ r.skip(wire, no);
98
+ }
99
+ }
100
+ return out;
101
+ }
102
+ function decodeStrRules(bytes) {
103
+ const r = new BinaryReader(bytes);
104
+ const out = {};
105
+ while (r.pos < r.len) {
106
+ const [no, wire] = r.tag();
107
+ const format = STRING_FORMATS[no];
108
+ if (format && wire === WireType.Varint) {
109
+ if (r.bool())
110
+ out.format = format;
111
+ continue;
112
+ }
113
+ switch (no) {
114
+ case 1:
115
+ out.const = r.string();
116
+ break;
117
+ case 19:
118
+ out.len = Number(r.uint64());
119
+ break;
120
+ case 2:
121
+ out.minLen = Number(r.uint64());
122
+ break;
123
+ case 3:
124
+ out.maxLen = Number(r.uint64());
125
+ break;
126
+ case 6:
127
+ out.pattern = r.string();
128
+ break;
129
+ case 7:
130
+ out.prefix = r.string();
131
+ break;
132
+ case 8:
133
+ out.suffix = r.string();
134
+ break;
135
+ case 9:
136
+ out.contains = r.string();
137
+ break;
138
+ case 10:
139
+ (out.in ??= []).push(r.string());
140
+ break;
141
+ case 11:
142
+ (out.notIn ??= []).push(r.string());
143
+ break;
144
+ default:
145
+ r.skip(wire, no);
146
+ }
147
+ }
148
+ return out;
149
+ }
150
+ /** google.protobuf.Duration / Timestamp bytes → seconds (fractional). */
151
+ function decodeSecondsNanos(bytes) {
152
+ const r = new BinaryReader(bytes);
153
+ let seconds = 0;
154
+ let nanos = 0;
155
+ while (r.pos < r.len) {
156
+ const [no, wire] = r.tag();
157
+ if (no === 1)
158
+ seconds = Number(r.int64());
159
+ else if (no === 2)
160
+ nanos = r.int32();
161
+ else
162
+ r.skip(wire, no);
163
+ }
164
+ return seconds + nanos / 1e9;
165
+ }
166
+ function decodeTimeRules(bytes, timestamp) {
167
+ // Duration and Timestamp rules share const=2, lt=3, lte=4, gt=5, gte=6.
168
+ const r = new BinaryReader(bytes);
169
+ const scale = timestamp ? 1000 : 1;
170
+ const out = {};
171
+ while (r.pos < r.len) {
172
+ const [no, wire] = r.tag();
173
+ const keys = {
174
+ 2: "const",
175
+ 3: "lt",
176
+ 4: "lte",
177
+ 5: "gt",
178
+ 6: "gte",
179
+ };
180
+ const key = keys[no];
181
+ if (key && wire === WireType.LengthDelimited) {
182
+ out[key] =
183
+ decodeSecondsNanos(r.bytes()) * scale;
184
+ }
185
+ else if (timestamp && no === 7) {
186
+ out.ltNow = r.bool();
187
+ }
188
+ else if (timestamp && no === 8) {
189
+ out.gtNow = r.bool();
190
+ }
191
+ else if (timestamp && no === 9) {
192
+ out.withinMs = decodeSecondsNanos(r.bytes()) * 1000;
193
+ }
194
+ else {
195
+ r.skip(wire, no);
196
+ }
197
+ }
198
+ return out;
199
+ }
200
+ function decodeFieldRules(bytes, into = {}) {
201
+ const r = new BinaryReader(bytes);
202
+ while (r.pos < r.len) {
203
+ const [no, wire] = r.tag();
204
+ if (no >= 1 && no <= 12 && wire === WireType.LengthDelimited) {
205
+ into.num = decodeNumRules(r.bytes(), (sub) => readNumber(sub, no));
206
+ continue;
207
+ }
208
+ switch (no) {
209
+ case 13: {
210
+ // BoolRules: const = 1.
211
+ const sub = new BinaryReader(r.bytes());
212
+ while (sub.pos < sub.len) {
213
+ const [n, w] = sub.tag();
214
+ if (n === 1)
215
+ into.bool = sub.bool();
216
+ else
217
+ sub.skip(w, n);
218
+ }
219
+ break;
220
+ }
221
+ case 14:
222
+ into.str = decodeStrRules(r.bytes());
223
+ break;
224
+ case 15: {
225
+ // BytesRules: len = 13, min_len = 2, max_len = 3.
226
+ const sub = new BinaryReader(r.bytes());
227
+ const b = {};
228
+ while (sub.pos < sub.len) {
229
+ const [n, w] = sub.tag();
230
+ if (n === 13)
231
+ b.len = Number(sub.uint64());
232
+ else if (n === 2)
233
+ b.minLen = Number(sub.uint64());
234
+ else if (n === 3)
235
+ b.maxLen = Number(sub.uint64());
236
+ else
237
+ sub.skip(w, n);
238
+ }
239
+ into.bytes = b;
240
+ break;
241
+ }
242
+ case 16: {
243
+ // EnumRules: const = 1, in = 3, not_in = 4.
244
+ const sub = new BinaryReader(r.bytes());
245
+ const e = {};
246
+ while (sub.pos < sub.len) {
247
+ const [n, w] = sub.tag();
248
+ if (n === 1)
249
+ e.const = sub.int32();
250
+ else if (n === 3)
251
+ (e.in ??= []).push(...readRepeated(sub, w, (x) => x.int32()));
252
+ else if (n === 4)
253
+ (e.notIn ??= []).push(...readRepeated(sub, w, (x) => x.int32()));
254
+ else
255
+ sub.skip(w, n);
256
+ }
257
+ into.enm = e;
258
+ break;
259
+ }
260
+ case 18: {
261
+ const sub = new BinaryReader(r.bytes());
262
+ const rep = {};
263
+ while (sub.pos < sub.len) {
264
+ const [n, w] = sub.tag();
265
+ if (n === 1)
266
+ rep.minItems = Number(sub.uint64());
267
+ else if (n === 2)
268
+ rep.maxItems = Number(sub.uint64());
269
+ else if (n === 4)
270
+ rep.items = decodeFieldRules(sub.bytes());
271
+ else
272
+ sub.skip(w, n);
273
+ }
274
+ into.repeated = rep;
275
+ break;
276
+ }
277
+ case 19: {
278
+ const sub = new BinaryReader(r.bytes());
279
+ const m = {};
280
+ while (sub.pos < sub.len) {
281
+ const [n, w] = sub.tag();
282
+ if (n === 1)
283
+ m.minPairs = Number(sub.uint64());
284
+ else if (n === 2)
285
+ m.maxPairs = Number(sub.uint64());
286
+ else if (n === 4)
287
+ m.keys = decodeFieldRules(sub.bytes());
288
+ else if (n === 5)
289
+ m.values = decodeFieldRules(sub.bytes());
290
+ else
291
+ sub.skip(w, n);
292
+ }
293
+ into.map = m;
294
+ break;
295
+ }
296
+ case 21:
297
+ into.duration = decodeTimeRules(r.bytes(), false);
298
+ break;
299
+ case 22:
300
+ into.timestamp = decodeTimeRules(r.bytes(), true);
301
+ break;
302
+ default:
303
+ r.skip(wire, no);
304
+ }
305
+ }
306
+ return into;
307
+ }
308
+ const rulesCache = new WeakMap();
309
+ /** The field's protovalidate rules, or undefined when it declares none. */
310
+ export function rulesOf(field) {
311
+ const cached = rulesCache.get(field);
312
+ if (cached !== undefined)
313
+ return cached ?? undefined;
314
+ let rules = null;
315
+ try {
316
+ const unknown = field.proto.options?.$unknown ?? [];
317
+ for (const u of unknown) {
318
+ if (u.no !== VALIDATE_FIELD_EXT ||
319
+ u.wireType !== WireType.LengthDelimited)
320
+ continue;
321
+ // An unknown field's data keeps its length prefix.
322
+ rules = decodeFieldRules(new BinaryReader(u.data).bytes(), rules ?? {});
323
+ }
324
+ }
325
+ catch {
326
+ // A rule set this decoder cannot read is a rule set it does not apply:
327
+ // the value stays the name-derived default rather than failing the RPC.
328
+ rules = null;
329
+ }
330
+ rulesCache.set(field, rules);
331
+ return rules ?? undefined;
332
+ }
333
+ //# sourceMappingURL=mock-rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-rules.js","sourceRoot":"","sources":["../src/mock-rules.ts"],"names":[],"mappings":"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","sourcesContent":["// Part of @reliantlabs/forge-web-runtime — the web twin of forge/pkg.\n//\n// protovalidate rules for the mock values (mock-values.ts), read straight\n// off the descriptor protoc-gen-es embeds in every `_pb.ts`: no buf.validate\n// TypeScript is needed in the app, and a vendored contract's rules arrive the\n// same way as the project's own.\nimport type { DescField } from \"@bufbuild/protobuf\";\nimport { BinaryReader, WireType } from \"@bufbuild/protobuf/wire\";\n\n// ── protovalidate rules, decoded from the embedded descriptor ───────────\n//\n// buf.validate.field is extension 1159 on FieldOptions. protobuf-es keeps an\n// unregistered extension as an unknown field of the options message, so the\n// rules are read from there with the wire reader. Field numbers follow\n// buf/validate/validate.proto; numeric rule messages share one layout\n// (const=1, lt=2, lte=3, gt=4, gte=5, in=6, not_in=7).\n\nconst VALIDATE_FIELD_EXT = 1159;\n\nexport interface NumRules {\n const?: number;\n lt?: number;\n lte?: number;\n gt?: number;\n gte?: number;\n in?: number[];\n notIn?: number[];\n}\n\nexport interface StrRules {\n const?: string;\n len?: number;\n minLen?: number;\n maxLen?: number;\n pattern?: string;\n prefix?: string;\n suffix?: string;\n contains?: string;\n in?: string[];\n notIn?: string[];\n format?: StrFormat;\n}\n\nexport type StrFormat =\n | \"email\"\n | \"hostname\"\n | \"ip\"\n | \"ipv4\"\n | \"ipv6\"\n | \"uri\"\n | \"address\"\n | \"uuid\"\n | \"tuuid\"\n | \"ulid\"\n | \"hostAndPort\"\n | \"ipPrefix\";\n\nexport interface EnumRules {\n const?: number;\n in?: number[];\n notIn?: number[];\n}\n\nexport interface FieldRules {\n bool?: boolean;\n num?: NumRules;\n str?: StrRules;\n bytes?: { len?: number; minLen?: number; maxLen?: number };\n enm?: EnumRules;\n repeated?: { minItems?: number; maxItems?: number; items?: FieldRules };\n map?: {\n minPairs?: number;\n maxPairs?: number;\n keys?: FieldRules;\n values?: FieldRules;\n };\n /** Seconds. */\n duration?: NumRules;\n /** Epoch milliseconds; `ltNow`/`gtNow` relative to the anchor. */\n timestamp?: NumRules & {\n ltNow?: boolean;\n gtNow?: boolean;\n withinMs?: number;\n };\n}\n\nconst STRING_FORMATS: Record<number, StrFormat> = {\n 12: \"email\",\n 13: \"hostname\",\n 14: \"ip\",\n 15: \"ipv4\",\n 16: \"ipv6\",\n 17: \"uri\",\n 18: \"uri\",\n 21: \"address\",\n 22: \"uuid\",\n 33: \"tuuid\",\n 35: \"ulid\",\n 32: \"hostAndPort\",\n 26: \"ipPrefix\",\n 27: \"ipPrefix\",\n 28: \"ipPrefix\",\n 29: \"ipPrefix\",\n 30: \"ipPrefix\",\n 31: \"ipPrefix\",\n};\n\n/** Read one numeric rule value of FieldRules type `t` (1 float … 12 sfixed64). */\nfunction readNumber(r: BinaryReader, t: number): number {\n switch (t) {\n case 1:\n return r.float();\n case 2:\n return r.double();\n case 3:\n return r.int32();\n case 4:\n return Number(r.int64());\n case 5:\n return r.uint32();\n case 6:\n return Number(r.uint64());\n case 7:\n return r.sint32();\n case 8:\n return Number(r.sint64());\n case 9:\n return r.fixed32();\n case 10:\n return Number(r.fixed64());\n case 11:\n return r.sfixed32();\n default:\n return Number(r.sfixed64());\n }\n}\n\n/** Every value of a (possibly packed) repeated numeric field. */\nfunction readRepeated(\n r: BinaryReader,\n wire: WireType,\n read: (r: BinaryReader) => number,\n): number[] {\n if (wire !== WireType.LengthDelimited) return [read(r)];\n const sub = new BinaryReader(r.bytes());\n const out: number[] = [];\n while (sub.pos < sub.len) out.push(read(sub));\n return out;\n}\n\nfunction decodeNumRules(\n bytes: Uint8Array,\n read: (r: BinaryReader) => number,\n): NumRules {\n const r = new BinaryReader(bytes);\n const out: NumRules = {};\n while (r.pos < r.len) {\n const [no, wire] = r.tag();\n switch (no) {\n case 1:\n out.const = read(r);\n break;\n case 2:\n out.lt = read(r);\n break;\n case 3:\n out.lte = read(r);\n break;\n case 4:\n out.gt = read(r);\n break;\n case 5:\n out.gte = read(r);\n break;\n case 6:\n (out.in ??= []).push(...readRepeated(r, wire, read));\n break;\n case 7:\n (out.notIn ??= []).push(...readRepeated(r, wire, read));\n break;\n default:\n r.skip(wire, no);\n }\n }\n return out;\n}\n\nfunction decodeStrRules(bytes: Uint8Array): StrRules {\n const r = new BinaryReader(bytes);\n const out: StrRules = {};\n while (r.pos < r.len) {\n const [no, wire] = r.tag();\n const format = STRING_FORMATS[no];\n if (format && wire === WireType.Varint) {\n if (r.bool()) out.format = format;\n continue;\n }\n switch (no) {\n case 1:\n out.const = r.string();\n break;\n case 19:\n out.len = Number(r.uint64());\n break;\n case 2:\n out.minLen = Number(r.uint64());\n break;\n case 3:\n out.maxLen = Number(r.uint64());\n break;\n case 6:\n out.pattern = r.string();\n break;\n case 7:\n out.prefix = r.string();\n break;\n case 8:\n out.suffix = r.string();\n break;\n case 9:\n out.contains = r.string();\n break;\n case 10:\n (out.in ??= []).push(r.string());\n break;\n case 11:\n (out.notIn ??= []).push(r.string());\n break;\n default:\n r.skip(wire, no);\n }\n }\n return out;\n}\n\n/** google.protobuf.Duration / Timestamp bytes → seconds (fractional). */\nfunction decodeSecondsNanos(bytes: Uint8Array): number {\n const r = new BinaryReader(bytes);\n let seconds = 0;\n let nanos = 0;\n while (r.pos < r.len) {\n const [no, wire] = r.tag();\n if (no === 1) seconds = Number(r.int64());\n else if (no === 2) nanos = r.int32();\n else r.skip(wire, no);\n }\n return seconds + nanos / 1e9;\n}\n\nfunction decodeTimeRules(\n bytes: Uint8Array,\n timestamp: boolean,\n): FieldRules[\"timestamp\"] {\n // Duration and Timestamp rules share const=2, lt=3, lte=4, gt=5, gte=6.\n const r = new BinaryReader(bytes);\n const scale = timestamp ? 1000 : 1;\n const out: NonNullable<FieldRules[\"timestamp\"]> = {};\n while (r.pos < r.len) {\n const [no, wire] = r.tag();\n const keys: Record<number, keyof NumRules> = {\n 2: \"const\",\n 3: \"lt\",\n 4: \"lte\",\n 5: \"gt\",\n 6: \"gte\",\n };\n const key = keys[no];\n if (key && wire === WireType.LengthDelimited) {\n (out as Record<string, number>)[key] =\n decodeSecondsNanos(r.bytes()) * scale;\n } else if (timestamp && no === 7) {\n out.ltNow = r.bool();\n } else if (timestamp && no === 8) {\n out.gtNow = r.bool();\n } else if (timestamp && no === 9) {\n out.withinMs = decodeSecondsNanos(r.bytes()) * 1000;\n } else {\n r.skip(wire, no);\n }\n }\n return out;\n}\n\nfunction decodeFieldRules(\n bytes: Uint8Array,\n into: FieldRules = {},\n): FieldRules {\n const r = new BinaryReader(bytes);\n while (r.pos < r.len) {\n const [no, wire] = r.tag();\n if (no >= 1 && no <= 12 && wire === WireType.LengthDelimited) {\n into.num = decodeNumRules(r.bytes(), (sub) => readNumber(sub, no));\n continue;\n }\n switch (no) {\n case 13: {\n // BoolRules: const = 1.\n const sub = new BinaryReader(r.bytes());\n while (sub.pos < sub.len) {\n const [n, w] = sub.tag();\n if (n === 1) into.bool = sub.bool();\n else sub.skip(w, n);\n }\n break;\n }\n case 14:\n into.str = decodeStrRules(r.bytes());\n break;\n case 15: {\n // BytesRules: len = 13, min_len = 2, max_len = 3.\n const sub = new BinaryReader(r.bytes());\n const b: NonNullable<FieldRules[\"bytes\"]> = {};\n while (sub.pos < sub.len) {\n const [n, w] = sub.tag();\n if (n === 13) b.len = Number(sub.uint64());\n else if (n === 2) b.minLen = Number(sub.uint64());\n else if (n === 3) b.maxLen = Number(sub.uint64());\n else sub.skip(w, n);\n }\n into.bytes = b;\n break;\n }\n case 16: {\n // EnumRules: const = 1, in = 3, not_in = 4.\n const sub = new BinaryReader(r.bytes());\n const e: EnumRules = {};\n while (sub.pos < sub.len) {\n const [n, w] = sub.tag();\n if (n === 1) e.const = sub.int32();\n else if (n === 3)\n (e.in ??= []).push(...readRepeated(sub, w, (x) => x.int32()));\n else if (n === 4)\n (e.notIn ??= []).push(...readRepeated(sub, w, (x) => x.int32()));\n else sub.skip(w, n);\n }\n into.enm = e;\n break;\n }\n case 18: {\n const sub = new BinaryReader(r.bytes());\n const rep: NonNullable<FieldRules[\"repeated\"]> = {};\n while (sub.pos < sub.len) {\n const [n, w] = sub.tag();\n if (n === 1) rep.minItems = Number(sub.uint64());\n else if (n === 2) rep.maxItems = Number(sub.uint64());\n else if (n === 4) rep.items = decodeFieldRules(sub.bytes());\n else sub.skip(w, n);\n }\n into.repeated = rep;\n break;\n }\n case 19: {\n const sub = new BinaryReader(r.bytes());\n const m: NonNullable<FieldRules[\"map\"]> = {};\n while (sub.pos < sub.len) {\n const [n, w] = sub.tag();\n if (n === 1) m.minPairs = Number(sub.uint64());\n else if (n === 2) m.maxPairs = Number(sub.uint64());\n else if (n === 4) m.keys = decodeFieldRules(sub.bytes());\n else if (n === 5) m.values = decodeFieldRules(sub.bytes());\n else sub.skip(w, n);\n }\n into.map = m;\n break;\n }\n case 21:\n into.duration = decodeTimeRules(r.bytes(), false);\n break;\n case 22:\n into.timestamp = decodeTimeRules(r.bytes(), true);\n break;\n default:\n r.skip(wire, no);\n }\n }\n return into;\n}\n\nconst rulesCache = new WeakMap<DescField, FieldRules | null>();\n\n/** The field's protovalidate rules, or undefined when it declares none. */\nexport function rulesOf(field: DescField): FieldRules | undefined {\n const cached = rulesCache.get(field);\n if (cached !== undefined) return cached ?? undefined;\n let rules: FieldRules | null = null;\n try {\n const unknown = field.proto.options?.$unknown ?? [];\n for (const u of unknown) {\n if (\n u.no !== VALIDATE_FIELD_EXT ||\n u.wireType !== WireType.LengthDelimited\n )\n continue;\n // An unknown field's data keeps its length prefix.\n rules = decodeFieldRules(new BinaryReader(u.data).bytes(), rules ?? {});\n }\n } catch {\n // A rule set this decoder cannot read is a rule set it does not apply:\n // the value stays the name-derived default rather than failing the RPC.\n rules = null;\n }\n rulesCache.set(field, rules);\n return rules ?? undefined;\n}\n"]}
@@ -1,5 +1,7 @@
1
1
  import { type DescMessage, type DescMethod } from "@bufbuild/protobuf";
2
2
  import { ConnectError, type Transport } from "@connectrpc/connect";
3
+ import type { AnyServiceDefaults } from "./mock-values.js";
4
+ export { isServiceDefaults, mockFactory, mockService, mockValue, patch, serviceDefaults, type AnyServiceDefaults, type DefaultHandler, type MockFactory, type MockFactoryContext, type MockHandlers, type MockOverride, type MockOverrides, type MockRequest, type MockResult, type MockValueOptions, type PatchShape, type ServiceDefaults, } from "./mock-values.js";
3
5
  /**
4
6
  * The shape the generated scenario files satisfy. Structural on purpose: the
5
7
  * project's own `Scenario` type (src/mocks/scenario-types.ts) carries a
@@ -89,6 +91,12 @@ export interface CreateMockTransportOptions {
89
91
  scenario: MockScenario;
90
92
  /** Per-entity fixture dispatch. Omit for a scenario-only project. */
91
93
  entities?: readonly MockEntityDescriptor[];
94
+ /**
95
+ * Default handlers per service (`serviceDefaults(Service)`, one per
96
+ * generated `src/mocks/services/*_gen.ts`): the answer for any RPC that no
97
+ * scenario handler, passthrough or entity fixture took.
98
+ */
99
+ services?: readonly AnyServiceDefaults[];
92
100
  /**
93
101
  * Optional real Connect transport. When the active scenario declares
94
102
  * `passthrough: true`, any RPC not matched by a scenario handler is
@@ -29,14 +29,19 @@
29
29
  // ever sees a write — a public demo's guarantee.
30
30
  // 3. Otherwise RPCs not overridden fall through to the deterministic
31
31
  // per-entity fixtures described by the entity descriptors.
32
- // 4. Anything else rejects with Code.Unimplemented so callers see a
32
+ // 4. Then to the service DEFAULTS (`services`, see mock-values.ts): a
33
+ // deterministic, schema-valid response built from the RPC's descriptor,
34
+ // for any RPC of any service the app's generated TypeScript covers —
35
+ // custom reads, vendored contracts and streams included.
36
+ // 5. Anything else rejects with Code.Unimplemented so callers see a
33
37
  // clear error instead of a silent empty response.
34
38
  //
35
39
  // A fixture List answers the way the backend's generated CRUD List does
36
40
  // (pkg/crud HandleList), so a filtered table, a paged table and a "how many"
37
41
  // tile read the same against fixtures as against a server — see
38
42
  // `serveList` for the exact contract. Custom (non-CRUD) RPCs are not
39
- // interpreted at all; they stay hand-written scenario handlers.
43
+ // interpreted: their defaults are shape-valid sample data, and what a page
44
+ // needs to SAY is a scenario override (`mockService`, mock-values.ts).
40
45
  //
41
46
  // Imported through the "@reliantlabs/forge-web-runtime/mock-transport" subpath,
42
47
  // never the barrel: a production bundle must be able to shake the fixtures
@@ -46,6 +51,7 @@
46
51
  import { create, isMessage, ScalarType, } from "@bufbuild/protobuf";
47
52
  import { MethodOptions_IdempotencyLevel } from "@bufbuild/protobuf/wkt";
48
53
  import { Code, ConnectError, } from "@connectrpc/connect";
54
+ export { isServiceDefaults, mockFactory, mockService, mockValue, patch, serviceDefaults, } from "./mock-values.js";
49
55
  /**
50
56
  * Mutable session stores, keyed by descriptor identity.
51
57
  *
@@ -443,6 +449,25 @@ function buildFixtureTable(entities) {
443
449
  }
444
450
  return table;
445
451
  }
452
+ /**
453
+ * Compile service defaults into the same flat `${service}/${rpc}` → handler
454
+ * map the fixtures use. The first service object for a name wins, so an app
455
+ * that lists one twice (a hand-built list beside the generated one) keeps
456
+ * the earlier entry's options.
457
+ */
458
+ function buildDefaultsTable(services) {
459
+ const table = new Map();
460
+ for (const defaults of services) {
461
+ const service = defaults.$service;
462
+ for (const method of service.methods) {
463
+ const key = `${service.typeName}/${method.name}`;
464
+ const handler = defaults[method.localName];
465
+ if (handler && !table.has(key))
466
+ table.set(key, handler);
467
+ }
468
+ }
469
+ return table;
470
+ }
446
471
  /**
447
472
  * Create the mock transport.
448
473
  *
@@ -455,6 +480,7 @@ export function createMockTransport(options) {
455
480
  const passthrough = scenario.passthrough === true && fallback != null;
456
481
  const first = scenario.passthrough === "first" && fallback != null;
457
482
  const fixtures = buildFixtureTable(entities);
483
+ const defaults = buildDefaultsTable(options.services ?? []);
458
484
  const readsOnly = typeof readOnly === "function" ? readOnly : isRead;
459
485
  // 0) The read-only guard: before any dispatch, so a write never reaches a
460
486
  // handler, a fixture store or the backend.
@@ -550,15 +576,20 @@ export function createMockTransport(options) {
550
576
  const requestSchema = method.input;
551
577
  return makeUnaryResponse(method, fixture(input, requestSchema));
552
578
  }
553
- // 4) Nothing matched. Surface a clear error instead of hanging.
554
- return Promise.reject(new ConnectError(`mock-transport: no scenario handler or entity fixture for ${key}`, Code.Unimplemented));
579
+ // 4) The service's default: a schema-valid answer for any RPC.
580
+ const fallbackDefault = defaults.get(key);
581
+ if (fallbackDefault) {
582
+ return makeUnaryResponse(method, fallbackDefault(input));
583
+ }
584
+ // 5) Nothing matched. Surface a clear error instead of hanging.
585
+ return Promise.reject(new ConnectError(`mock-transport: no scenario handler, entity fixture or service default for ${key}`, Code.Unimplemented));
555
586
  },
556
587
  // Streaming: a scenario handler can return an array, iterable, async
557
588
  // iterable, or a Promise resolving to any of those. The transport adapts
558
- // it into the AsyncIterable<Response> shape Connect expects. If no
559
- // handler matches, reject with Unimplemented — base-fixture streaming is
560
- // intentionally not served (there is no canonical "list of N messages"
561
- // shape for an arbitrary streaming RPC).
589
+ // it into the AsyncIterable<Response> shape Connect expects. With no
590
+ // handler, the service default answers (a short deterministic stream for
591
+ // server and bidi streams, one message for client streams); with neither,
592
+ // reject with Unimplemented. Entity fixtures never stream.
562
593
  //
563
594
  // No explicit return-type annotation: the outer `const transport:
564
595
  // Transport` binding lets tsc infer the per-callback signature from
@@ -591,14 +622,15 @@ export function createMockTransport(options) {
591
622
  if (live)
592
623
  return live;
593
624
  }
594
- const handler = scenario.handlers[key];
625
+ const scenarioHandler = scenario.handlers[key];
626
+ // Passthrough mirrors the unary path: in hybrid mode, unmatched
627
+ // streaming RPCs go to the real backend, ahead of the defaults.
628
+ if (!scenarioHandler && passthrough) {
629
+ return fallback.stream(method, signal, timeoutMs, header, input, contextValues);
630
+ }
631
+ const handler = scenarioHandler ?? defaults.get(key);
595
632
  if (!handler) {
596
- // Passthrough mirrors the unary path: in hybrid mode, unmatched
597
- // streaming RPCs go to the real backend.
598
- if (passthrough) {
599
- return fallback.stream(method, signal, timeoutMs, header, input, contextValues);
600
- }
601
- return Promise.reject(new ConnectError(`mock-transport: no scenario handler for streaming RPC ${key}`, Code.Unimplemented));
633
+ return Promise.reject(new ConnectError(`mock-transport: no scenario handler or service default for streaming RPC ${key}`, Code.Unimplemented));
602
634
  }
603
635
  // Read the request stream eagerly into an array so the scenario handler
604
636
  // sees the full client-streaming payload. For server-stream and