@atcute/lexicons 1.0.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.
Files changed (91) hide show
  1. package/LICENSE +17 -0
  2. package/README.md +11 -0
  3. package/dist/ambient.d.ts +8 -0
  4. package/dist/ambient.js +2 -0
  5. package/dist/ambient.js.map +1 -0
  6. package/dist/index.d.ts +16 -0
  7. package/dist/index.js +3 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/interfaces/blob.d.ts +20 -0
  10. package/dist/interfaces/blob.js +20 -0
  11. package/dist/interfaces/blob.js.map +1 -0
  12. package/dist/interfaces/bytes.d.ts +23 -0
  13. package/dist/interfaces/bytes.js +21 -0
  14. package/dist/interfaces/bytes.js.map +1 -0
  15. package/dist/interfaces/cid-link.d.ts +24 -0
  16. package/dist/interfaces/cid-link.js +13 -0
  17. package/dist/interfaces/cid-link.js.map +1 -0
  18. package/dist/interfaces/index.d.ts +3 -0
  19. package/dist/interfaces/index.js +4 -0
  20. package/dist/interfaces/index.js.map +1 -0
  21. package/dist/syntax/at-identifier.d.ts +8 -0
  22. package/dist/syntax/at-identifier.js +7 -0
  23. package/dist/syntax/at-identifier.js.map +1 -0
  24. package/dist/syntax/at-uri.d.ts +46 -0
  25. package/dist/syntax/at-uri.js +64 -0
  26. package/dist/syntax/at-uri.js.map +1 -0
  27. package/dist/syntax/cid.d.ts +5 -0
  28. package/dist/syntax/cid.js +10 -0
  29. package/dist/syntax/cid.js.map +1 -0
  30. package/dist/syntax/datetime.d.ts +2 -0
  31. package/dist/syntax/datetime.js +6 -0
  32. package/dist/syntax/datetime.js.map +1 -0
  33. package/dist/syntax/did.d.ts +9 -0
  34. package/dist/syntax/did.js +6 -0
  35. package/dist/syntax/did.js.map +1 -0
  36. package/dist/syntax/handle.d.ts +6 -0
  37. package/dist/syntax/handle.js +6 -0
  38. package/dist/syntax/handle.js.map +1 -0
  39. package/dist/syntax/index.d.ts +11 -0
  40. package/dist/syntax/index.js +12 -0
  41. package/dist/syntax/index.js.map +1 -0
  42. package/dist/syntax/language.d.ts +2 -0
  43. package/dist/syntax/language.js +6 -0
  44. package/dist/syntax/language.js.map +1 -0
  45. package/dist/syntax/nsid.d.ts +5 -0
  46. package/dist/syntax/nsid.js +6 -0
  47. package/dist/syntax/nsid.js.map +1 -0
  48. package/dist/syntax/record-key.d.ts +5 -0
  49. package/dist/syntax/record-key.js +6 -0
  50. package/dist/syntax/record-key.js.map +1 -0
  51. package/dist/syntax/tid.d.ts +5 -0
  52. package/dist/syntax/tid.js +6 -0
  53. package/dist/syntax/tid.js.map +1 -0
  54. package/dist/syntax/uri.d.ts +5 -0
  55. package/dist/syntax/uri.js +6 -0
  56. package/dist/syntax/uri.js.map +1 -0
  57. package/dist/types/brand.d.ts +13 -0
  58. package/dist/types/brand.js +2 -0
  59. package/dist/types/brand.js.map +1 -0
  60. package/dist/utils.d.ts +11 -0
  61. package/dist/utils.js +12 -0
  62. package/dist/utils.js.map +1 -0
  63. package/dist/validations/index.d.ts +409 -0
  64. package/dist/validations/index.js +1003 -0
  65. package/dist/validations/index.js.map +1 -0
  66. package/dist/validations/utils.d.ts +8 -0
  67. package/dist/validations/utils.js +54 -0
  68. package/dist/validations/utils.js.map +1 -0
  69. package/lib/ambient.ts +7 -0
  70. package/lib/index.ts +38 -0
  71. package/lib/interfaces/blob.ts +47 -0
  72. package/lib/interfaces/bytes.ts +45 -0
  73. package/lib/interfaces/cid-link.ts +36 -0
  74. package/lib/interfaces/index.ts +3 -0
  75. package/lib/syntax/at-identifier.ts +13 -0
  76. package/lib/syntax/at-uri.ts +117 -0
  77. package/lib/syntax/cid.ts +16 -0
  78. package/lib/syntax/datetime.ts +9 -0
  79. package/lib/syntax/did.ts +16 -0
  80. package/lib/syntax/handle.ts +13 -0
  81. package/lib/syntax/index.ts +11 -0
  82. package/lib/syntax/language.ts +9 -0
  83. package/lib/syntax/nsid.ts +12 -0
  84. package/lib/syntax/record-key.ts +11 -0
  85. package/lib/syntax/tid.ts +11 -0
  86. package/lib/syntax/uri.ts +11 -0
  87. package/lib/types/brand.ts +11 -0
  88. package/lib/utils.ts +15 -0
  89. package/lib/validations/index.ts +1749 -0
  90. package/lib/validations/utils.ts +62 -0
  91. package/package.json +35 -0
@@ -0,0 +1,1003 @@
1
+ import * as syntax from '../syntax/index.js';
2
+ import { _isBytesWrapper } from '../interfaces/bytes.js';
3
+ import * as interfaces from '../interfaces/index.js';
4
+ import { assert } from '../utils.js';
5
+ import { getGraphemeLength, getUtf8Length, isArray, isObject, lazy, lazyProperty } from './utils.js';
6
+ // #__NO_SIDE_EFFECTS__
7
+ const joinIssues = (left, right) => {
8
+ return left ? { ok: false, code: 'join', left, right } : right;
9
+ };
10
+ // #__NO_SIDE_EFFECTS__
11
+ const prependPath = (key, tree) => {
12
+ return { ok: false, code: 'prepend', key, tree };
13
+ };
14
+ // None set
15
+ export const FLAG_EMPTY = 0;
16
+ // Don't continue validation if an error is encountered
17
+ export const FLAG_ABORT_EARLY = 1 << 0;
18
+ // #region Schema runner
19
+ const cloneIssueWithPath = (issue, path) => {
20
+ const { ok: _ok, ...clone } = issue;
21
+ return { ...clone, path };
22
+ };
23
+ const collectIssues = (tree, path = [], issues = []) => {
24
+ for (;;) {
25
+ switch (tree.code) {
26
+ case 'join': {
27
+ collectIssues(tree.left, path.slice(), issues);
28
+ tree = tree.right;
29
+ continue;
30
+ }
31
+ case 'prepend': {
32
+ path.push(tree.key);
33
+ tree = tree.tree;
34
+ continue;
35
+ }
36
+ default: {
37
+ issues.push(cloneIssueWithPath(tree, path));
38
+ return issues;
39
+ }
40
+ }
41
+ }
42
+ };
43
+ const countIssues = (tree) => {
44
+ let count = 0;
45
+ for (;;) {
46
+ switch (tree.code) {
47
+ case 'join': {
48
+ count += countIssues(tree.left);
49
+ tree = tree.right;
50
+ continue;
51
+ }
52
+ case 'prepend': {
53
+ tree = tree.tree;
54
+ continue;
55
+ }
56
+ default: {
57
+ return count + 1;
58
+ }
59
+ }
60
+ }
61
+ };
62
+ const separatedList = (list, sep) => {
63
+ switch (list.length) {
64
+ case 0: {
65
+ return `nothing`;
66
+ }
67
+ case 1: {
68
+ return list[0];
69
+ }
70
+ default: {
71
+ return `${list.slice(0, -1).join(', ')} ${sep} ${list[list.length - 1]}`;
72
+ }
73
+ }
74
+ };
75
+ const formatLiteral = (value) => {
76
+ return JSON.stringify(value);
77
+ };
78
+ const formatRangeMessage = (type, unit, min, max) => {
79
+ let message = `${type} `;
80
+ if (min > 0) {
81
+ if (max === min) {
82
+ message += `${min}`;
83
+ }
84
+ else if (max !== Infinity) {
85
+ message += `between ${min} and ${max}`;
86
+ }
87
+ else {
88
+ message += `at least ${min}`;
89
+ }
90
+ }
91
+ else {
92
+ message += `at most ${max}`;
93
+ }
94
+ message += ` ${unit}(s)`;
95
+ return message;
96
+ };
97
+ const formatIssueTree = (tree) => {
98
+ let path = '';
99
+ let count = 0;
100
+ for (;;) {
101
+ switch (tree.code) {
102
+ case 'join': {
103
+ count += countIssues(tree.right);
104
+ tree = tree.left;
105
+ continue;
106
+ }
107
+ case 'prepend': {
108
+ path += `.${tree.key}`;
109
+ tree = tree.tree;
110
+ continue;
111
+ }
112
+ }
113
+ break;
114
+ }
115
+ let message;
116
+ switch (tree.code) {
117
+ case 'missing_value': {
118
+ message = `missing value`;
119
+ break;
120
+ }
121
+ case 'invalid_literal': {
122
+ message = `expected ${separatedList(tree.expected.map(formatLiteral), 'or')}`;
123
+ break;
124
+ }
125
+ case 'invalid_type': {
126
+ message = `expected ${tree.expected}`;
127
+ break;
128
+ }
129
+ case 'invalid_variant': {
130
+ message = `expected ${separatedList(tree.expected, 'or')}`;
131
+ break;
132
+ }
133
+ case 'invalid_integer_range': {
134
+ const min = tree.min;
135
+ const max = tree.max;
136
+ message = `expected an integer `;
137
+ if (min > 0) {
138
+ if (max === min) {
139
+ message += `of exactly ${min}`;
140
+ }
141
+ else if (max !== Infinity) {
142
+ message += `between ${min} and ${max}`;
143
+ }
144
+ else {
145
+ message += `of at least ${min}`;
146
+ }
147
+ }
148
+ else {
149
+ message += `of at most ${max}`;
150
+ }
151
+ break;
152
+ }
153
+ case 'invalid_string_format': {
154
+ message = `expected a ${tree.expected} formatted string`;
155
+ break;
156
+ }
157
+ case 'invalid_string_graphemes': {
158
+ message = formatRangeMessage('a string', 'grapheme', tree.minGraphemes, tree.maxGraphemes);
159
+ break;
160
+ }
161
+ case 'invalid_string_length': {
162
+ message = formatRangeMessage('a string', 'character', tree.minLength, tree.maxLength);
163
+ break;
164
+ }
165
+ case 'invalid_array_length': {
166
+ message = formatRangeMessage('an array', 'item', tree.minLength, tree.maxLength);
167
+ break;
168
+ }
169
+ case 'invalid_bytes_size': {
170
+ message = formatRangeMessage('a byte array', 'byte', tree.minSize, tree.maxSize);
171
+ break;
172
+ }
173
+ }
174
+ let msg = `${tree.code} at ${path ?? '.'} (${message})`;
175
+ if (count > 0) {
176
+ msg += ` (+${count} other issue(s))`;
177
+ }
178
+ return msg;
179
+ };
180
+ export class ValidationError extends Error {
181
+ name = 'ValidationError';
182
+ #issueTree;
183
+ constructor(issueTree) {
184
+ super();
185
+ this.#issueTree = issueTree;
186
+ }
187
+ get message() {
188
+ return formatIssueTree(this.#issueTree);
189
+ }
190
+ get issues() {
191
+ return collectIssues(this.#issueTree);
192
+ }
193
+ }
194
+ class ErrImpl {
195
+ ok = false;
196
+ #issueTree;
197
+ constructor(issueTree) {
198
+ this.#issueTree = issueTree;
199
+ }
200
+ get message() {
201
+ return formatIssueTree(this.#issueTree);
202
+ }
203
+ get issues() {
204
+ return collectIssues(this.#issueTree);
205
+ }
206
+ throw() {
207
+ throw new ValidationError(this.#issueTree);
208
+ }
209
+ }
210
+ // #__NO_SIDE_EFFECTS__
211
+ export const is = (schema, input) => {
212
+ const r = schema['~run'](input, FLAG_ABORT_EARLY);
213
+ return r === undefined || r.ok;
214
+ };
215
+ // #__NO_SIDE_EFFECTS__
216
+ export const safeParse = (schema, input) => {
217
+ const r = schema['~run'](input, FLAG_EMPTY);
218
+ if (r === undefined) {
219
+ return { ok: true, value: input };
220
+ }
221
+ if (r.ok) {
222
+ return r;
223
+ }
224
+ return new ErrImpl(r);
225
+ };
226
+ export const parse = (schema, input) => {
227
+ const r = schema['~run'](input, FLAG_EMPTY);
228
+ if (r === undefined) {
229
+ return input;
230
+ }
231
+ if (r.ok) {
232
+ return r.value;
233
+ }
234
+ throw new ValidationError(r);
235
+ };
236
+ export const constrain = (base, constraints) => {
237
+ const len = constraints.length;
238
+ return {
239
+ ...base,
240
+ constraints: constraints,
241
+ '~run'(input, flags) {
242
+ let result = base['~run'](input, flags);
243
+ let current;
244
+ if (result === undefined) {
245
+ current = input;
246
+ }
247
+ else if (result.ok) {
248
+ current = result.value;
249
+ }
250
+ else {
251
+ return result;
252
+ }
253
+ for (let idx = 0; idx < len; idx++) {
254
+ const r = constraints[idx]['~run'](current, flags);
255
+ if (r !== undefined) {
256
+ if (r.ok) {
257
+ current = r.value;
258
+ if (result === undefined || result.ok) {
259
+ result = r;
260
+ }
261
+ }
262
+ else {
263
+ if (flags & FLAG_ABORT_EARLY) {
264
+ return r;
265
+ }
266
+ else if (result === undefined || result.ok) {
267
+ result = r;
268
+ }
269
+ else {
270
+ result = joinIssues(result, r);
271
+ }
272
+ }
273
+ }
274
+ }
275
+ return result;
276
+ },
277
+ };
278
+ };
279
+ // #__NO_SIDE_EFFECTS__
280
+ export const literal = (value) => {
281
+ const issue = {
282
+ ok: false,
283
+ code: 'invalid_literal',
284
+ expected: [value],
285
+ };
286
+ return {
287
+ kind: 'schema',
288
+ type: 'literal',
289
+ expected: value,
290
+ '~run'(input, _flags) {
291
+ if (input !== value) {
292
+ return issue;
293
+ }
294
+ return undefined;
295
+ },
296
+ };
297
+ };
298
+ // #__NO_SIDE_EFFECTS__
299
+ export const literalEnum = (values) => {
300
+ const issue = {
301
+ ok: false,
302
+ code: 'invalid_literal',
303
+ expected: values,
304
+ };
305
+ return {
306
+ kind: 'schema',
307
+ type: 'literal_enum',
308
+ expected: values,
309
+ '~run'(input, _flags) {
310
+ if (!values.includes(input)) {
311
+ return issue;
312
+ }
313
+ return undefined;
314
+ },
315
+ };
316
+ };
317
+ const ISSUE_TYPE_BOOLEAN = {
318
+ ok: false,
319
+ code: 'invalid_type',
320
+ expected: 'boolean',
321
+ };
322
+ const BOOLEAN_SCHEMA = {
323
+ kind: 'schema',
324
+ type: 'boolean',
325
+ '~run'(input, _flags) {
326
+ if (typeof input !== 'boolean') {
327
+ return ISSUE_TYPE_BOOLEAN;
328
+ }
329
+ return undefined;
330
+ },
331
+ };
332
+ // #__NO_SIDE_EFFECTS__
333
+ export const boolean = () => {
334
+ return BOOLEAN_SCHEMA;
335
+ };
336
+ const ISSUE_TYPE_INTEGER = {
337
+ ok: false,
338
+ code: 'invalid_type',
339
+ expected: 'integer',
340
+ };
341
+ const INTEGER_SCHEMA = {
342
+ kind: 'schema',
343
+ type: 'integer',
344
+ '~run'(input, _flags) {
345
+ if (typeof input !== 'number') {
346
+ return ISSUE_TYPE_INTEGER;
347
+ }
348
+ if (input < 0 || !Number.isSafeInteger(input)) {
349
+ return ISSUE_TYPE_INTEGER;
350
+ }
351
+ return undefined;
352
+ },
353
+ };
354
+ // #__NO_SIDE_EFFECTS__
355
+ export const integer = () => {
356
+ return INTEGER_SCHEMA;
357
+ };
358
+ // #__NO_SIDE_EFFECTS__
359
+ export const integerRange = (min, max = Infinity) => {
360
+ const issue = {
361
+ ok: false,
362
+ code: 'invalid_integer_range',
363
+ min: min,
364
+ max: max,
365
+ };
366
+ return {
367
+ kind: 'constraint',
368
+ type: 'integer_range',
369
+ min: min,
370
+ max: max,
371
+ '~run'(input, _flags) {
372
+ if (input < min) {
373
+ return issue;
374
+ }
375
+ if (input > max) {
376
+ return issue;
377
+ }
378
+ return undefined;
379
+ },
380
+ };
381
+ };
382
+ const ISSUE_TYPE_STRING = {
383
+ ok: false,
384
+ code: 'invalid_type',
385
+ expected: 'string',
386
+ };
387
+ const STRING_SINGLETON = {
388
+ kind: 'schema',
389
+ type: 'string',
390
+ format: null,
391
+ '~run'(input, _flags) {
392
+ if (typeof input !== 'string') {
393
+ return ISSUE_TYPE_STRING;
394
+ }
395
+ return undefined;
396
+ },
397
+ };
398
+ // #__NO_SIDE_EFFECTS__
399
+ export const string = () => {
400
+ return STRING_SINGLETON;
401
+ };
402
+ // #__NO_SIDE_EFFECTS__
403
+ const _formattedString = (format, validate) => {
404
+ const issue = {
405
+ ok: false,
406
+ code: 'invalid_string_format',
407
+ expected: format,
408
+ };
409
+ const schema = {
410
+ kind: 'schema',
411
+ type: 'string',
412
+ format: format,
413
+ '~run'(input, _flags) {
414
+ if (typeof input !== 'string') {
415
+ return ISSUE_TYPE_STRING;
416
+ }
417
+ if (!validate(input)) {
418
+ return issue;
419
+ }
420
+ return undefined;
421
+ },
422
+ };
423
+ return () => schema;
424
+ };
425
+ // prettier-ignore
426
+ export const actorIdentifierString = /*#__PURE__*/ _formattedString('at-identifier', syntax.isActorIdentifier);
427
+ export const resourceUriString = /*#__PURE__*/ _formattedString('at-uri', syntax.isResourceUri);
428
+ export const cidString = /*#__PURE__*/ _formattedString('cid', syntax.isCid);
429
+ export const datetimeString = /*#__PURE__*/ _formattedString('datetime', syntax.isDatetime);
430
+ export const didString = /*#__PURE__*/ _formattedString('did', syntax.isDid);
431
+ export const handleString = /*#__PURE__*/ _formattedString('handle', syntax.isHandle);
432
+ export const languageCodeString = /*#__PURE__*/ _formattedString('language', syntax.isLanguageCode);
433
+ export const nsidString = /*#__PURE__*/ _formattedString('nsid', syntax.isNsid);
434
+ export const recordKeyString = /*#__PURE__*/ _formattedString('record-key', syntax.isRecordKey);
435
+ export const tidString = /*#__PURE__*/ _formattedString('tid', syntax.isTid);
436
+ export const genericUriString = /*#__PURE__*/ _formattedString('uri', syntax.isGenericUri);
437
+ // #__NO_SIDE_EFFECTS__
438
+ export const stringLength = (minLength, maxLength = Infinity) => {
439
+ const issue = {
440
+ ok: false,
441
+ code: 'invalid_string_length',
442
+ minLength: minLength,
443
+ maxLength: maxLength,
444
+ };
445
+ return {
446
+ kind: 'constraint',
447
+ type: 'string_length',
448
+ minLength: minLength,
449
+ maxLength: maxLength,
450
+ '~run'(input, _flags) {
451
+ // UTF-8 conversion can be expensive, so we're going to do some safe naive
452
+ // checks where we assume an upper-bound of the UTF-16 to UTF-8 conversion
453
+ const maybeUtf8Len = input.length * 3;
454
+ // fail early if we're still less than minimum length
455
+ if (maybeUtf8Len < minLength) {
456
+ return issue;
457
+ }
458
+ // skip if we're still within maximum length
459
+ if (maybeUtf8Len <= maxLength) {
460
+ return undefined;
461
+ }
462
+ const utf8Len = getUtf8Length(input);
463
+ if (utf8Len < minLength) {
464
+ return issue;
465
+ }
466
+ if (utf8Len > maxLength) {
467
+ return issue;
468
+ }
469
+ return undefined;
470
+ },
471
+ };
472
+ };
473
+ export const stringGraphemes = (minGraphemes, maxGraphemes = Infinity) => {
474
+ const issue = {
475
+ ok: false,
476
+ code: 'invalid_string_graphemes',
477
+ minGraphemes: minGraphemes,
478
+ maxGraphemes: maxGraphemes,
479
+ };
480
+ return {
481
+ kind: 'constraint',
482
+ type: 'string_graphemes',
483
+ minGraphemes: minGraphemes,
484
+ maxGraphemes: maxGraphemes,
485
+ '~run'(input, _flags) {
486
+ // grapheme conversion is expensive, so we're going to do some safe naive
487
+ // checks where we assume 1 UTF-16 character = 1 grapheme.
488
+ const utf16Len = input.length;
489
+ // fail early if UTF-16 length is less than grapheme length
490
+ if (utf16Len < minGraphemes) {
491
+ return issue;
492
+ }
493
+ // skip if we're still within maximum constraint
494
+ if (utf16Len <= maxGraphemes) {
495
+ return undefined;
496
+ }
497
+ const graphemeLen = getGraphemeLength(input);
498
+ if (graphemeLen < minGraphemes) {
499
+ return issue;
500
+ }
501
+ if (graphemeLen > maxGraphemes) {
502
+ return issue;
503
+ }
504
+ return undefined;
505
+ },
506
+ };
507
+ };
508
+ const ISSUE_EXPECTED_BLOB = {
509
+ ok: false,
510
+ code: 'invalid_type',
511
+ expected: 'blob',
512
+ };
513
+ const BLOB_SCHEMA = {
514
+ kind: 'schema',
515
+ type: 'blob',
516
+ '~run'(input, _flags) {
517
+ if (typeof input !== 'object' || input === null) {
518
+ return ISSUE_EXPECTED_BLOB;
519
+ }
520
+ if (interfaces.isBlob(input)) {
521
+ return undefined;
522
+ }
523
+ if (interfaces.isLegacyBlob(input)) {
524
+ const blob = {
525
+ $type: 'blob',
526
+ mimeType: input.mimeType,
527
+ ref: { $link: input.cid },
528
+ size: -1,
529
+ };
530
+ return { ok: true, value: blob };
531
+ }
532
+ return ISSUE_EXPECTED_BLOB;
533
+ },
534
+ };
535
+ // #__NO_SIDE_EFFECTS__
536
+ export const blob = () => {
537
+ return BLOB_SCHEMA;
538
+ };
539
+ const ISSUE_EXPECTED_BYTES = {
540
+ ok: false,
541
+ code: 'invalid_type',
542
+ expected: 'bytes',
543
+ };
544
+ const BYTES_SCHEMA = {
545
+ kind: 'schema',
546
+ type: 'bytes',
547
+ '~run'(input, _flags) {
548
+ if (!interfaces.isBytes(input)) {
549
+ return ISSUE_EXPECTED_BYTES;
550
+ }
551
+ return undefined;
552
+ },
553
+ };
554
+ // #__NO_SIDE_EFFECTS__
555
+ export const bytes = () => {
556
+ return BYTES_SCHEMA;
557
+ };
558
+ // #__NO_SIDE_EFFECTS__
559
+ export const bytesSize = (minSize, maxSize = Infinity) => {
560
+ const issue = {
561
+ ok: false,
562
+ code: 'invalid_bytes_size',
563
+ minSize: minSize,
564
+ maxSize: maxSize,
565
+ };
566
+ return {
567
+ kind: 'constraint',
568
+ type: 'bytes_size',
569
+ minSize: minSize,
570
+ maxSize: maxSize,
571
+ '~run'(input, _flags) {
572
+ let size;
573
+ if (_isBytesWrapper(input)) {
574
+ size = input.buf.length;
575
+ }
576
+ else {
577
+ const str = input.$bytes;
578
+ let bytes = str.length;
579
+ if (str.charCodeAt(bytes - 1) === 0x3d) {
580
+ bytes--;
581
+ }
582
+ if (bytes > 1 && str.charCodeAt(bytes - 1) === 0x3d) {
583
+ bytes--;
584
+ }
585
+ size = (bytes * 3) >>> 2;
586
+ }
587
+ if (size < minSize) {
588
+ return issue;
589
+ }
590
+ if (size > maxSize) {
591
+ return issue;
592
+ }
593
+ return undefined;
594
+ },
595
+ };
596
+ };
597
+ const ISSUE_EXPECTED_CID_LINK = {
598
+ ok: false,
599
+ code: 'invalid_type',
600
+ expected: 'cid-link',
601
+ };
602
+ const CID_LINK_SCHEMA = {
603
+ kind: 'schema',
604
+ type: 'cid_link',
605
+ '~run'(input, _flags) {
606
+ if (!interfaces.isCidLink(input)) {
607
+ return ISSUE_EXPECTED_CID_LINK;
608
+ }
609
+ return undefined;
610
+ },
611
+ };
612
+ // #__NO_SIDE_EFFECTS__
613
+ export const cidLink = () => {
614
+ return CID_LINK_SCHEMA;
615
+ };
616
+ // #__NO_SIDE_EFFECTS__
617
+ export const nullable = (wrapped) => {
618
+ return {
619
+ kind: 'schema',
620
+ type: 'nullable',
621
+ wrapped: wrapped,
622
+ '~run'(input, flags) {
623
+ if (input === null) {
624
+ return undefined;
625
+ }
626
+ return wrapped['~run'](input, flags);
627
+ },
628
+ };
629
+ };
630
+ // #__NO_SIDE_EFFECTS__
631
+ export const optional = (wrapped, defaultValue) => {
632
+ return {
633
+ kind: 'schema',
634
+ type: 'optional',
635
+ wrapped: wrapped,
636
+ default: defaultValue,
637
+ '~run'(input, flags) {
638
+ if (input === undefined) {
639
+ if (defaultValue === undefined) {
640
+ return undefined;
641
+ }
642
+ const value = typeof defaultValue === 'function' ? defaultValue() : defaultValue;
643
+ return { ok: true, value };
644
+ }
645
+ return wrapped['~run'](input, flags);
646
+ },
647
+ };
648
+ };
649
+ const isOptionalSchema = (schema) => {
650
+ return schema.type === 'optional';
651
+ };
652
+ const ISSUE_TYPE_ARRAY = {
653
+ ok: false,
654
+ code: 'invalid_type',
655
+ expected: 'array',
656
+ };
657
+ // #__NO_SIDE_EFFECTS__
658
+ export const array = (item) => {
659
+ const resolvedShape = lazy(() => {
660
+ return typeof item === 'function' ? item() : item;
661
+ });
662
+ return {
663
+ kind: 'schema',
664
+ type: 'array',
665
+ get item() {
666
+ return lazyProperty(this, 'item', resolvedShape.value);
667
+ },
668
+ get '~run'() {
669
+ const shape = resolvedShape.value;
670
+ const matcher = (input, flags) => {
671
+ if (!isArray(input)) {
672
+ return ISSUE_TYPE_ARRAY;
673
+ }
674
+ let issues;
675
+ let output;
676
+ for (let idx = 0, len = input.length; idx < len; idx++) {
677
+ const val = input[idx];
678
+ const r = shape['~run'](val, flags);
679
+ if (r !== undefined) {
680
+ if (r.ok) {
681
+ if (output === undefined) {
682
+ output = input.slice();
683
+ }
684
+ output[idx] = r.value;
685
+ }
686
+ else {
687
+ issues = joinIssues(issues, prependPath(idx, r));
688
+ if (flags & FLAG_ABORT_EARLY) {
689
+ return issues;
690
+ }
691
+ }
692
+ }
693
+ }
694
+ if (issues !== undefined) {
695
+ return issues;
696
+ }
697
+ if (output !== undefined) {
698
+ return { ok: true, value: output };
699
+ }
700
+ return undefined;
701
+ };
702
+ return lazyProperty(this, '~run', matcher);
703
+ },
704
+ };
705
+ };
706
+ // #__NO_SIDE_EFFECTS__
707
+ export const arrayLength = (minLength, maxLength = Infinity) => {
708
+ const issue = {
709
+ ok: false,
710
+ code: 'invalid_array_length',
711
+ minLength: minLength,
712
+ maxLength: maxLength,
713
+ };
714
+ return {
715
+ kind: 'constraint',
716
+ type: 'array_length',
717
+ minLength: minLength,
718
+ maxLength: maxLength,
719
+ '~run'(input, _flags) {
720
+ const length = input.length;
721
+ if (length < minLength) {
722
+ return issue;
723
+ }
724
+ if (length > maxLength) {
725
+ return issue;
726
+ }
727
+ return undefined;
728
+ },
729
+ };
730
+ };
731
+ const ISSUE_TYPE_OBJECT = {
732
+ ok: false,
733
+ code: 'invalid_type',
734
+ expected: 'object',
735
+ };
736
+ const ISSUE_MISSING = {
737
+ ok: false,
738
+ code: 'missing_value',
739
+ };
740
+ const set = (obj, key, value) => {
741
+ if (key === '__proto__') {
742
+ Object.defineProperty(obj, key, { value });
743
+ }
744
+ else {
745
+ obj[key] = value;
746
+ }
747
+ };
748
+ // #__NO_SIDE_EFFECTS__
749
+ export const object = (shape) => {
750
+ const resolvedEntries = lazy(() => {
751
+ const resolved = [];
752
+ for (const key in shape) {
753
+ const schema = shape[key];
754
+ resolved.push({
755
+ key: key,
756
+ schema: schema,
757
+ optional: isOptionalSchema(schema),
758
+ missing: prependPath(key, ISSUE_MISSING),
759
+ });
760
+ }
761
+ return resolved;
762
+ });
763
+ return {
764
+ kind: 'schema',
765
+ type: 'object',
766
+ get shape() {
767
+ // if we just return the shape as is then it wouldn't be the same exact
768
+ // shape when getters are present.
769
+ const resolved = resolvedEntries.value;
770
+ const obj = {};
771
+ for (const entry of resolved) {
772
+ obj[entry.key] = entry.schema;
773
+ }
774
+ return lazyProperty(this, 'shape', obj);
775
+ },
776
+ get '~run'() {
777
+ const shape = resolvedEntries.value;
778
+ const len = shape.length;
779
+ const matcher = (input, flags) => {
780
+ if (!isObject(input)) {
781
+ return ISSUE_TYPE_OBJECT;
782
+ }
783
+ let issues;
784
+ let output;
785
+ for (let idx = 0; idx < len; idx++) {
786
+ const entry = shape[idx];
787
+ const key = entry.key;
788
+ const value = input[key];
789
+ if (value === undefined && !(key in input)) {
790
+ if (!entry.optional) {
791
+ issues = joinIssues(issues, entry.missing);
792
+ if (flags & FLAG_ABORT_EARLY) {
793
+ return issues;
794
+ }
795
+ continue;
796
+ }
797
+ }
798
+ const r = entry.schema['~run'](value, flags);
799
+ if (r === undefined) {
800
+ if (output !== undefined) {
801
+ /*#__INLINE__*/ set(output, key, value);
802
+ }
803
+ }
804
+ else if (r.ok) {
805
+ if (output === undefined) {
806
+ output = { ...input };
807
+ }
808
+ /*#__INLINE__*/ set(output, key, value);
809
+ }
810
+ else {
811
+ issues = joinIssues(issues, prependPath(key, r));
812
+ if (flags & FLAG_ABORT_EARLY) {
813
+ return issues;
814
+ }
815
+ }
816
+ }
817
+ if (issues !== undefined) {
818
+ return issues;
819
+ }
820
+ if (output !== undefined) {
821
+ return { ok: true, value: output };
822
+ }
823
+ return undefined;
824
+ };
825
+ return lazyProperty(this, '~run', matcher);
826
+ },
827
+ };
828
+ };
829
+ // #__NO_SIDE_EFFECTS__
830
+ export const record = (key, object) => {
831
+ const validatedObject = lazy(() => {
832
+ const shape = object.shape;
833
+ let t = shape.$type;
834
+ assert(t !== undefined, `expected $type in record to be defined`);
835
+ if (t.type === 'optional') {
836
+ t = t.wrapped;
837
+ }
838
+ assert(t.type === 'literal' && typeof t.expected === 'string', `expected $type to be a string literal`);
839
+ return object;
840
+ });
841
+ return {
842
+ kind: 'schema',
843
+ type: 'record',
844
+ key: key,
845
+ get object() {
846
+ return lazyProperty(this, 'object', validatedObject.value);
847
+ },
848
+ get '~run'() {
849
+ const object = validatedObject.value;
850
+ const matcher = (input, flags) => {
851
+ return object['~run'](input, flags);
852
+ };
853
+ return lazyProperty(this, '~run', matcher);
854
+ },
855
+ };
856
+ };
857
+ const ISSUE_VARIANT_MISSING = /*#__PURE__*/ prependPath('$type', {
858
+ ok: false,
859
+ code: 'missing_value',
860
+ });
861
+ const ISSUE_VARIANT_TYPE = /*#__PURE__*/ prependPath('$type', {
862
+ ok: false,
863
+ code: 'invalid_type',
864
+ expected: 'string',
865
+ });
866
+ // #__NO_SIDE_EFFECTS__
867
+ export const variant = (members, closed = false) => {
868
+ return {
869
+ kind: 'schema',
870
+ type: 'variant',
871
+ members: members,
872
+ closed: closed,
873
+ get '~run'() {
874
+ const map = Object.fromEntries(members.map((member, idx) => {
875
+ const shape = member.shape;
876
+ let t = shape.$type;
877
+ assert(t !== undefined, `expected $type in variant member #${idx} to be defined`);
878
+ if (t.type === 'optional') {
879
+ t = t.wrapped;
880
+ }
881
+ assert(t.type === 'literal' && typeof t.expected === 'string', `expected $type in variant member #${idx} to be a string literal`);
882
+ return [t.expected, member];
883
+ }));
884
+ const issue = {
885
+ ok: false,
886
+ code: 'invalid_variant',
887
+ expected: Object.keys(map),
888
+ };
889
+ const matcher = (input, flags) => {
890
+ if (!isObject(input)) {
891
+ return ISSUE_TYPE_OBJECT;
892
+ }
893
+ if (!('$type' in input)) {
894
+ return ISSUE_VARIANT_MISSING;
895
+ }
896
+ const type = input.$type;
897
+ if (typeof type !== 'string') {
898
+ return ISSUE_VARIANT_TYPE;
899
+ }
900
+ if (!(type in map)) {
901
+ if (closed) {
902
+ return issue;
903
+ }
904
+ return undefined;
905
+ }
906
+ const schema = map[type];
907
+ return schema['~run'](input, flags);
908
+ };
909
+ return lazyProperty(this, '~run', matcher);
910
+ },
911
+ };
912
+ };
913
+ const ISSUE_TYPE_UNKNOWN = {
914
+ ok: false,
915
+ code: 'invalid_type',
916
+ expected: 'unknown',
917
+ };
918
+ const UNKNOWN_SCHEMA = {
919
+ kind: 'schema',
920
+ type: 'unknown',
921
+ '~run'(input, _flags) {
922
+ if (typeof input !== 'object' || input === null) {
923
+ return ISSUE_TYPE_UNKNOWN;
924
+ }
925
+ return undefined;
926
+ },
927
+ };
928
+ // #__NO_SIDE_EFFECTS__
929
+ export const unknown = () => {
930
+ return UNKNOWN_SCHEMA;
931
+ };
932
+ // #__NO_SIDE_EFFECTS__
933
+ export const procedure = (nsid, options) => {
934
+ // `schema` can be a getter, and we'd have to resolve that getter.
935
+ return {
936
+ kind: 'metadata',
937
+ type: 'xrpc_procedure',
938
+ nsid: nsid,
939
+ params: options.params,
940
+ get input() {
941
+ let val = options.input;
942
+ switch (val?.type) {
943
+ case 'lex': {
944
+ val = {
945
+ type: 'lex',
946
+ schema: val.schema,
947
+ };
948
+ break;
949
+ }
950
+ }
951
+ return lazyProperty(this, 'input', val);
952
+ },
953
+ get output() {
954
+ let val = options.output;
955
+ switch (val?.type) {
956
+ case 'lex': {
957
+ val = {
958
+ type: 'lex',
959
+ schema: val.schema,
960
+ };
961
+ break;
962
+ }
963
+ }
964
+ return lazyProperty(this, 'output', val);
965
+ },
966
+ };
967
+ };
968
+ // #__NO_SIDE_EFFECTS__
969
+ export const query = (nsid, options) => {
970
+ // `schema` can be a getter, and we'd have to resolve that getter.
971
+ return {
972
+ kind: 'metadata',
973
+ type: 'xrpc_query',
974
+ nsid: nsid,
975
+ params: options.params,
976
+ get output() {
977
+ let val = options.output;
978
+ switch (val?.type) {
979
+ case 'lex': {
980
+ val = {
981
+ type: 'lex',
982
+ schema: val.schema,
983
+ };
984
+ }
985
+ }
986
+ return lazyProperty(this, 'output', val);
987
+ },
988
+ };
989
+ };
990
+ // #__NO_SIDE_EFFECTS__
991
+ export const subscription = (nsid, options) => {
992
+ // `message` can be a getter, and we'd have to resolve that getter.
993
+ return {
994
+ kind: 'metadata',
995
+ type: 'xrpc_subscription',
996
+ nsid: nsid,
997
+ params: options.params,
998
+ get message() {
999
+ return lazyProperty(this, 'message', options.message);
1000
+ },
1001
+ };
1002
+ };
1003
+ //# sourceMappingURL=index.js.map