@atproto/syntax 0.4.0 → 0.4.2

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 (58) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/LICENSE.txt +1 -1
  3. package/benchmark.js +208 -0
  4. package/dist/at-identifier.d.ts +5 -0
  5. package/dist/at-identifier.d.ts.map +1 -0
  6. package/dist/at-identifier.js +19 -0
  7. package/dist/at-identifier.js.map +1 -0
  8. package/dist/aturi.d.ts +8 -6
  9. package/dist/aturi.d.ts.map +1 -1
  10. package/dist/aturi.js +36 -45
  11. package/dist/aturi.js.map +1 -1
  12. package/dist/aturi_validation.d.ts +5 -2
  13. package/dist/aturi_validation.d.ts.map +1 -1
  14. package/dist/aturi_validation.js +54 -66
  15. package/dist/aturi_validation.js.map +1 -1
  16. package/dist/datetime.d.ts +11 -4
  17. package/dist/datetime.d.ts.map +1 -1
  18. package/dist/datetime.js +16 -16
  19. package/dist/datetime.js.map +1 -1
  20. package/dist/did.d.ts +3 -2
  21. package/dist/did.d.ts.map +1 -1
  22. package/dist/did.js +8 -8
  23. package/dist/did.js.map +1 -1
  24. package/dist/handle.d.ts +7 -6
  25. package/dist/handle.d.ts.map +1 -1
  26. package/dist/handle.js +28 -31
  27. package/dist/handle.js.map +1 -1
  28. package/dist/index.d.ts +8 -7
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +8 -7
  31. package/dist/index.js.map +1 -1
  32. package/dist/nsid.d.ts +30 -5
  33. package/dist/nsid.d.ts.map +1 -1
  34. package/dist/nsid.js +137 -47
  35. package/dist/nsid.js.map +1 -1
  36. package/dist/recordkey.d.ts +3 -2
  37. package/dist/recordkey.d.ts.map +1 -1
  38. package/dist/recordkey.js +33 -22
  39. package/dist/recordkey.js.map +1 -1
  40. package/dist/tid.d.ts +3 -2
  41. package/dist/tid.d.ts.map +1 -1
  42. package/dist/tid.js +7 -7
  43. package/dist/tid.js.map +1 -1
  44. package/package.json +1 -1
  45. package/src/at-identifier.ts +22 -0
  46. package/src/aturi.ts +59 -46
  47. package/src/aturi_validation.ts +62 -57
  48. package/src/datetime.ts +17 -4
  49. package/src/did.ts +5 -2
  50. package/src/handle.ts +23 -22
  51. package/src/index.ts +8 -7
  52. package/src/nsid.ts +146 -47
  53. package/src/recordkey.ts +40 -17
  54. package/src/tid.ts +4 -2
  55. package/tests/nsid.test.ts +117 -77
  56. package/tsconfig.build.json +1 -0
  57. package/tsconfig.build.tsbuildinfo +1 -1
  58. package/tsconfig.tests.tsbuildinfo +1 -1
package/src/nsid.ts CHANGED
@@ -6,35 +6,42 @@ number = "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" / "0"
6
6
  delim = "."
7
7
  segment = alpha *( alpha / number / "-" )
8
8
  authority = segment *( delim segment )
9
- name = alpha *( alpha )
9
+ name = alpha *( alpha / number )
10
10
  nsid = authority delim name
11
11
 
12
12
  */
13
13
 
14
+ export type NsidString = `${string}.${string}.${string}`
15
+
14
16
  export class NSID {
15
- segments: string[] = []
17
+ readonly segments: readonly string[]
16
18
 
17
- static parse(nsid: string): NSID {
18
- return new NSID(nsid)
19
+ static parse(input: string): NSID {
20
+ return new NSID(input)
19
21
  }
20
22
 
21
23
  static create(authority: string, name: string): NSID {
22
- const segments = [...authority.split('.').reverse(), name].join('.')
23
- return new NSID(segments)
24
+ const input = [...authority.split('.').reverse(), name].join('.')
25
+ return new NSID(input)
26
+ }
27
+
28
+ static isValid(nsid: string) {
29
+ return isValidNsid(nsid)
24
30
  }
25
31
 
26
- static isValid(nsid: string): boolean {
27
- try {
28
- NSID.parse(nsid)
29
- return true
30
- } catch (e) {
31
- return false
32
+ static from(input: { toString: () => string }): NSID {
33
+ if (input instanceof NSID) {
34
+ // No need to clone, NSID is immutable
35
+ return input
32
36
  }
37
+ if (Array.isArray(input)) {
38
+ return new NSID((input as string[]).join('.'))
39
+ }
40
+ return new NSID(String(input))
33
41
  }
34
42
 
35
43
  constructor(nsid: string) {
36
- ensureValidNsid(nsid)
37
- this.segments = nsid.split('.')
44
+ this.segments = parseNsid(nsid)
38
45
  }
39
46
 
40
47
  get authority() {
@@ -53,60 +60,152 @@ export class NSID {
53
60
  }
54
61
  }
55
62
 
63
+ export function ensureValidNsid(nsid: string): asserts nsid is NsidString {
64
+ const result = validateNsid(nsid)
65
+ if (!result.success) throw new InvalidNsidError(result.message)
66
+ }
67
+
68
+ export function parseNsid(nsid: string): string[] {
69
+ const result = validateNsid(nsid)
70
+ if (!result.success) throw new InvalidNsidError(result.message)
71
+ return result.value
72
+ }
73
+
74
+ export function isValidNsid(nsid: string): nsid is NsidString {
75
+ // Since the regex version is more performant for valid NSIDs, we use it when
76
+ // we don't care about error details.
77
+ return validateNsidRegex(nsid).success
78
+ }
79
+
80
+ type ValidateResult<T> =
81
+ | { success: true; value: T }
82
+ | { success: false; message: string }
83
+
56
84
  // Human readable constraints on NSID:
57
85
  // - a valid domain in reversed notation
58
86
  // - followed by an additional period-separated name, which is camel-case letters
59
- export const ensureValidNsid = (nsid: string): void => {
60
- const toCheck = nsid
61
-
62
- // check that all chars are boring ASCII
63
- if (!/^[a-zA-Z0-9.-]*$/.test(toCheck)) {
64
- throw new InvalidNsidError(
65
- 'Disallowed characters in NSID (ASCII letters, digits, dashes, periods only)',
66
- )
87
+ export function validateNsid(input: string): ValidateResult<string[]> {
88
+ if (input.length > 253 + 1 + 63) {
89
+ return {
90
+ success: false,
91
+ message: 'NSID is too long (317 chars max)',
92
+ }
67
93
  }
68
-
69
- if (toCheck.length > 253 + 1 + 63) {
70
- throw new InvalidNsidError('NSID is too long (317 chars max)')
94
+ if (hasDisallowedCharacters(input)) {
95
+ return {
96
+ success: false,
97
+ message:
98
+ 'Disallowed characters in NSID (ASCII letters, digits, dashes, periods only)',
99
+ }
71
100
  }
72
- const labels = toCheck.split('.')
73
- if (labels.length < 3) {
74
- throw new InvalidNsidError('NSID needs at least three parts')
101
+ const segments = input.split('.')
102
+ if (segments.length < 3) {
103
+ return {
104
+ success: false,
105
+ message: 'NSID needs at least three parts',
106
+ }
75
107
  }
76
- for (let i = 0; i < labels.length; i++) {
77
- const l = labels[i]
108
+ for (const l of segments) {
78
109
  if (l.length < 1) {
79
- throw new InvalidNsidError('NSID parts can not be empty')
110
+ return {
111
+ success: false,
112
+ message: 'NSID parts can not be empty',
113
+ }
80
114
  }
81
115
  if (l.length > 63) {
82
- throw new InvalidNsidError('NSID part too long (max 63 chars)')
116
+ return {
117
+ success: false,
118
+ message: 'NSID part too long (max 63 chars)',
119
+ }
83
120
  }
84
- if (l.endsWith('-') || l.startsWith('-')) {
85
- throw new InvalidNsidError('NSID parts can not start or end with hyphen')
121
+ if (startsWithHyphen(l) || endsWithHyphen(l)) {
122
+ return {
123
+ success: false,
124
+ message: 'NSID parts can not start or end with hyphen',
125
+ }
86
126
  }
87
- if (/^[0-9]/.test(l) && i === 0) {
88
- throw new InvalidNsidError('NSID first part may not start with a digit')
127
+ }
128
+ if (startsWithNumber(segments[0])) {
129
+ return {
130
+ success: false,
131
+ message: 'NSID first part may not start with a digit',
89
132
  }
90
- if (!/^[a-zA-Z][a-zA-Z0-9]*$/.test(l) && i + 1 === labels.length) {
91
- throw new InvalidNsidError(
133
+ }
134
+ if (!isValidIdentifier(segments[segments.length - 1])) {
135
+ return {
136
+ success: false,
137
+ message:
92
138
  'NSID name part must be only letters and digits (and no leading digit)',
93
- )
94
139
  }
95
140
  }
141
+ return {
142
+ success: true,
143
+ value: segments,
144
+ }
145
+ }
146
+
147
+ function hasDisallowedCharacters(v: string) {
148
+ return !/^[a-zA-Z0-9.-]*$/.test(v)
149
+ }
150
+
151
+ function startsWithNumber(v: string) {
152
+ const charCode = v.charCodeAt(0)
153
+ return charCode >= 48 && charCode <= 57
96
154
  }
97
155
 
98
- export const ensureValidNsidRegex = (nsid: string): void => {
99
- // simple regex to enforce most constraints via just regex and length.
100
- // hand wrote this regex based on above constraints
156
+ function startsWithHyphen(v: string) {
157
+ return v.charCodeAt(0) === 45 /* - */
158
+ }
159
+
160
+ function endsWithHyphen(v: string) {
161
+ return v.charCodeAt(v.length - 1) === 45 /* - */
162
+ }
163
+
164
+ function isValidIdentifier(v: string) {
165
+ // Note, since we already know that "v" only contains [a-zA-Z0-9-], we can
166
+ // simplify the following regex by checking only the first char and presence
167
+ // of "-".
168
+
169
+ // return /^[a-zA-Z][a-zA-Z0-9]*$/.test(v)
170
+ return !startsWithNumber(v) && !v.includes('-')
171
+ }
172
+
173
+ /**
174
+ * @deprecated Use {@link ensureValidNsid} if you care about error details,
175
+ * {@link parseNsid}/{@link NSID.parse} if you need the parsed segments, or
176
+ * {@link isValidNsid} if you just want a boolean.
177
+ */
178
+ export function ensureValidNsidRegex(nsid: string): asserts nsid is NsidString {
179
+ const result = validateNsidRegex(nsid)
180
+ if (!result.success) throw new InvalidNsidError(result.message)
181
+ }
182
+
183
+ /**
184
+ * Regexp based validation that behaves identically to the previous code but
185
+ * provides less detailed error messages (while being 20% to 50% faster).
186
+ */
187
+ export function validateNsidRegex(value: string): ValidateResult<NsidString> {
188
+ if (value.length > 253 + 1 + 63) {
189
+ return {
190
+ success: false,
191
+ message: 'NSID is too long (317 chars max)',
192
+ }
193
+ }
194
+
101
195
  if (
102
- !/^[a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(\.[a-zA-Z]([a-zA-Z0-9]{0,62})?)$/.test(
103
- nsid,
196
+ !/^[a-zA-Z](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?:\.[a-zA-Z](?:[a-zA-Z0-9]{0,62})?)$/.test(
197
+ value,
104
198
  )
105
199
  ) {
106
- throw new InvalidNsidError("NSID didn't validate via regex")
200
+ return {
201
+ success: false,
202
+ message: "NSID didn't validate via regex",
203
+ }
107
204
  }
108
- if (nsid.length > 253 + 1 + 63) {
109
- throw new InvalidNsidError('NSID is too long (317 chars max)')
205
+
206
+ return {
207
+ success: true,
208
+ value: value as NsidString,
110
209
  }
111
210
  }
112
211
 
package/src/recordkey.ts CHANGED
@@ -1,26 +1,49 @@
1
- export const ensureValidRecordKey = (rkey: string): void => {
2
- if (rkey.length > 512 || rkey.length < 1) {
3
- throw new InvalidRecordKeyError('record key must be 1 to 512 characters')
1
+ export type RecordKeyString = string
2
+
3
+ const RECORD_KEY_MAX_LENGTH = 512
4
+ const RECORD_KEY_MIN_LENGTH = 1
5
+ const RECORD_KEY_INVALID_VALUES = new Set(['.', '..'])
6
+ const RECORD_KEY_REGEX = /^[a-zA-Z0-9_~.:-]{1,512}$/
7
+
8
+ // https://atproto.com/specs/record-key#record-key-syntax
9
+ // Regardless of the type, Record Keys must fulfill some baseline syntax constraints:
10
+ // - restricted to a subset of ASCII characters -- the allowed characters are
11
+ // alphanumeric (A-Za-z0-9), period, dash, underscore, colon, or tilde (.-_:~)
12
+ // - must have at least 1 and at most 512 characters
13
+ // - the specific record key values . and .. are not allowed
14
+ // - must be a permissible part of repository MST path string (the above
15
+ // constraints satisfy this condition)
16
+ // - must be permissible to include in a path component of a URI (following
17
+ // RFC-3986, section 3.3). The above constraints satisfy this condition, by
18
+ // matching the "unreserved" characters allowed in generic URI paths.
19
+
20
+ export function ensureValidRecordKey(
21
+ rkey: string,
22
+ ): asserts rkey is RecordKeyString {
23
+ if (
24
+ rkey.length > RECORD_KEY_MAX_LENGTH ||
25
+ rkey.length < RECORD_KEY_MIN_LENGTH
26
+ ) {
27
+ throw new InvalidRecordKeyError(
28
+ `record key must be ${RECORD_KEY_MIN_LENGTH} to ${RECORD_KEY_MAX_LENGTH} characters`,
29
+ )
30
+ }
31
+ if (RECORD_KEY_INVALID_VALUES.has(rkey)) {
32
+ throw new InvalidRecordKeyError('record key can not be "." or ".."')
4
33
  }
5
34
  // simple regex to enforce most constraints via just regex and length.
6
- if (!/^[a-zA-Z0-9_~.:-]{1,512}$/.test(rkey)) {
35
+ if (!RECORD_KEY_REGEX.test(rkey)) {
7
36
  throw new InvalidRecordKeyError('record key syntax not valid (regex)')
8
37
  }
9
- if (rkey === '.' || rkey === '..')
10
- throw new InvalidRecordKeyError('record key can not be "." or ".."')
11
38
  }
12
39
 
13
- export const isValidRecordKey = (rkey: string): boolean => {
14
- try {
15
- ensureValidRecordKey(rkey)
16
- } catch (err) {
17
- if (err instanceof InvalidRecordKeyError) {
18
- return false
19
- }
20
- throw err
21
- }
22
-
23
- return true
40
+ export function isValidRecordKey(rkey: string): rkey is RecordKeyString {
41
+ return (
42
+ rkey.length >= RECORD_KEY_MIN_LENGTH &&
43
+ rkey.length <= RECORD_KEY_MAX_LENGTH &&
44
+ RECORD_KEY_REGEX.test(rkey) &&
45
+ !RECORD_KEY_INVALID_VALUES.has(rkey)
46
+ )
24
47
  }
25
48
 
26
49
  export class InvalidRecordKeyError extends Error {}
package/src/tid.ts CHANGED
@@ -1,7 +1,9 @@
1
+ export type TidString = string
2
+
1
3
  const TID_LENGTH = 13
2
4
  const TID_REGEX = /^[234567abcdefghij][234567abcdefghijklmnopqrstuvwxyz]{12}$/
3
5
 
4
- export const ensureValidTid = (tid: string): void => {
6
+ export function ensureValidTid(tid: string): asserts tid is TidString {
5
7
  if (tid.length !== TID_LENGTH) {
6
8
  throw new InvalidTidError(`TID must be ${TID_LENGTH} characters`)
7
9
  }
@@ -11,7 +13,7 @@ export const ensureValidTid = (tid: string): void => {
11
13
  }
12
14
  }
13
15
 
14
- export const isValidTid = (tid: string): boolean => {
16
+ export function isValidTid(tid: string): tid is TidString {
15
17
  return tid.length === TID_LENGTH && TID_REGEX.test(tid)
16
18
  }
17
19
 
@@ -1,10 +1,12 @@
1
1
  import * as fs from 'node:fs'
2
- import * as readline from 'node:readline'
3
2
  import {
4
3
  InvalidNsidError,
5
4
  NSID,
6
5
  ensureValidNsid,
7
- ensureValidNsidRegex,
6
+ isValidNsid,
7
+ parseNsid,
8
+ validateNsid,
9
+ validateNsidRegex,
8
10
  } from '../src'
9
11
 
10
12
  describe('NSID parsing & creation', () => {
@@ -39,12 +41,30 @@ describe('NSID parsing & creation', () => {
39
41
 
40
42
  describe('NSID validation', () => {
41
43
  const expectValid = (h: string) => {
44
+ expect(isValidNsid(h)).toBe(true)
42
45
  ensureValidNsid(h)
43
- ensureValidNsidRegex(h)
46
+ expect(parseNsid(h)).toEqual(h.split('.'))
47
+ expect(validateNsidRegex(h)).toMatchObject({
48
+ success: true,
49
+ value: expect.any(String),
50
+ })
51
+ expect(validateNsid(h)).toMatchObject({
52
+ success: true,
53
+ value: expect.any(Array),
54
+ })
44
55
  }
45
56
  const expectInvalid = (h: string) => {
57
+ expect(isValidNsid(h)).toBe(false)
58
+ expect(() => parseNsid(h)).toThrow(InvalidNsidError)
46
59
  expect(() => ensureValidNsid(h)).toThrow(InvalidNsidError)
47
- expect(() => ensureValidNsidRegex(h)).toThrow(InvalidNsidError)
60
+ expect(validateNsidRegex(h)).toMatchObject({
61
+ success: false,
62
+ message: expect.any(String),
63
+ })
64
+ expect(validateNsid(h)).toMatchObject({
65
+ success: false,
66
+ message: expect.any(String),
67
+ })
48
68
  }
49
69
 
50
70
  it('enforces spec details', () => {
@@ -68,91 +88,111 @@ describe('NSID validation', () => {
68
88
  const tooLongOverall = 'com.' + 'middle.'.repeat(50) + 'foo'
69
89
  expect(tooLongOverall.length).toBe(357)
70
90
  expectInvalid(tooLongOverall)
71
-
72
- expectValid('com.example.fooBar')
73
- expectValid('net.users.bob.ping')
74
- expectValid('a.b.c')
75
- expectValid('m.xn--masekowski-d0b.pl')
76
- expectValid('one.two.three')
77
- expectValid('one.two.three.four-and.FiVe')
78
- expectValid('one.2.three')
79
- expectValid('a-0.b-1.c')
80
- expectValid('a0.b1.cc')
81
- expectValid('cn.8.lex.stuff')
82
- expectValid('test.12345.record')
83
- expectValid('a01.thing.record')
84
- expectValid('a.0.c')
85
- expectValid('xn--fiqs8s.xn--fiqa61au8b7zsevnm8ak20mc4a87e.record.two')
86
- expectValid('a0.b1.c3')
87
- expectValid('com.example.f00')
88
-
89
- expectInvalid('com.example.foo.*')
90
- expectInvalid('com.example.foo.blah*')
91
- expectInvalid('com.example.foo.*blah')
92
- expectInvalid('com.exa💩ple.thing')
93
- expectInvalid('a-0.b-1.c-3')
94
- expectInvalid('a-0.b-1.c-o')
95
- expectInvalid('1.0.0.127.record')
96
- expectInvalid('0two.example.foo')
97
- expectInvalid('example.com')
98
- expectInvalid('com.example')
99
- expectInvalid('a.')
100
- expectInvalid('.one.two.three')
101
- expectInvalid('one.two.three ')
102
- expectInvalid('one.two..three')
103
- expectInvalid('one .two.three')
104
- expectInvalid(' one.two.three')
105
- expectInvalid('com.exa💩ple.thing')
106
- expectInvalid('com.atproto.feed.p@st')
107
- expectInvalid('com.atproto.feed.p_st')
108
- expectInvalid('com.atproto.feed.p*st')
109
- expectInvalid('com.atproto.feed.po#t')
110
- expectInvalid('com.atproto.feed.p!ot')
111
- expectInvalid('com.example-.foo')
112
91
  })
113
92
 
114
- it('allows onion (Tor) NSIDs', () => {
115
- expectValid('onion.expyuzz4wqqyqhjn.spec.getThing')
116
- expectValid(
93
+ describe('valid NSIDs', () => {
94
+ for (const validNsid of [
95
+ 'com.example.foo',
96
+ 'o'.repeat(63) + '.foo.bar',
97
+ 'com.' + 'o'.repeat(63) + '.foo',
98
+ 'com.example.' + 'o'.repeat(63),
99
+ 'com.' + 'middle.'.repeat(40) + 'foo',
100
+
101
+ 'a-0.b-1.c',
102
+ 'a.0.c',
103
+ 'a.b.c',
104
+ 'a0.b1.c3',
105
+ 'a0.b1.cc',
106
+ 'a01.thing.record',
107
+ 'cn.8.lex.stuff',
108
+ 'com.example.f00',
109
+ 'com.example.fooBar',
110
+ 'm.xn--masekowski-d0b.pl',
111
+ 'net.users.bob.ping',
112
+ 'one.2.three',
113
+ 'one.two.three',
114
+ 'one.two.three.four-and.FiVe',
115
+ 'onion.2gzyxa5ihm7nsggfxnu52rck2vv4rvmdlkiu3zzui5du4xyclen53wid.lex.deleteThing',
116
+ 'onion.expyuzz4wqqyqhjn.spec.getThing',
117
117
  'onion.g2zyxa5ihm7nsggfxnu52rck2vv4rvmdlkiu3zzui5du4xyclen53wid.lex.deleteThing',
118
- )
118
+ 'org.4chan.lex.getThing',
119
+ 'test.12345.record',
120
+ 'xn--fiqs8s.xn--fiqa61au8b7zsevnm8ak20mc4a87e.record.two',
121
+ ]) {
122
+ it(validNsid, () => {
123
+ expectValid(validNsid)
124
+ })
125
+ }
119
126
  })
120
127
 
121
- it('allows starting-with-numeric segments (same as domains)', () => {
122
- expectValid('org.4chan.lex.getThing')
123
- expectValid('cn.8.lex.stuff')
124
- expectValid(
125
- 'onion.2gzyxa5ihm7nsggfxnu52rck2vv4rvmdlkiu3zzui5du4xyclen53wid.lex.deleteThing',
126
- )
128
+ describe('invalid NSIDs', () => {
129
+ for (const invalidNsid of [
130
+ 'o'.repeat(64) + '.foo.bar',
131
+ 'com.' + 'o'.repeat(64) + '.foo',
132
+ 'com.example.' + 'o'.repeat(64),
133
+ 'com.' + 'middle.'.repeat(50) + 'foo',
134
+ 'com.example.foo.*',
135
+ 'com.example.foo.blah*',
136
+ 'com.example.foo.*blah',
137
+ 'com.exa💩ple.thing',
138
+ 'a-0.b-1.c-3',
139
+ 'a-0.b-1.c-o',
140
+ '1.0.0.127.record',
141
+ '0two.example.foo',
142
+ 'example.com',
143
+ 'com.example',
144
+ 'a.',
145
+ '.one.two.three',
146
+ 'one.two.three ',
147
+ 'one.two..three',
148
+ 'one .two.three',
149
+ ' one.two.three',
150
+ 'com.atproto.feed.p@st',
151
+ 'com.atproto.feed.p_st',
152
+ 'com.atproto.feed.p*st',
153
+ 'com.atproto.feed.po#t',
154
+ 'com.atproto.feed.p!ot',
155
+ 'com.example-.foo',
156
+ 'com.-example.foo',
157
+ 'com.example.0foo',
158
+ 'com.example.f-o',
159
+ ]) {
160
+ it(invalidNsid, () => {
161
+ expect(validateNsid(invalidNsid)).toMatchObject({
162
+ success: false,
163
+ message: expect.any(String),
164
+ })
165
+ })
166
+ }
127
167
  })
128
168
 
129
- it('conforms to interop valid NSIDs', () => {
130
- const lineReader = readline.createInterface({
131
- input: fs.createReadStream(
132
- `${__dirname}/interop-files/nsid_syntax_valid.txt`,
133
- ),
134
- terminal: false,
135
- })
136
- lineReader.on('line', (line) => {
169
+ describe('conforms to interop valid NSIDs', () => {
170
+ for (const line of fs
171
+ .readFileSync(`${__dirname}/interop-files/nsid_syntax_valid.txt`)
172
+ .toString()
173
+ .split('\n')) {
137
174
  if (line.startsWith('#') || line.length === 0) {
138
- return
175
+ continue
139
176
  }
140
- expectValid(line)
141
- })
177
+
178
+ it(line, () => {
179
+ expectValid(line)
180
+ })
181
+ }
142
182
  })
143
183
 
144
- it('conforms to interop invalid NSIDs', () => {
145
- const lineReader = readline.createInterface({
146
- input: fs.createReadStream(
147
- `${__dirname}/interop-files/nsid_syntax_invalid.txt`,
148
- ),
149
- terminal: false,
150
- })
151
- lineReader.on('line', (line) => {
184
+ describe('conforms to interop invalid NSIDs', () => {
185
+ for (const line of fs
186
+ .readFileSync(`${__dirname}/interop-files/nsid_syntax_invalid.txt`)
187
+ .toString()
188
+ .split('\n')) {
152
189
  if (line.startsWith('#') || line.length === 0) {
153
- return
190
+ continue
154
191
  }
155
- expectInvalid(line)
156
- })
192
+
193
+ it(line, () => {
194
+ expectInvalid(line)
195
+ })
196
+ }
157
197
  })
158
198
  })
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "extends": "../../tsconfig/isomorphic.json",
3
3
  "compilerOptions": {
4
+ "noImplicitAny": true,
4
5
  "rootDir": "./src",
5
6
  "outDir": "./dist"
6
7
  },
@@ -1 +1 @@
1
- {"root":["./src/aturi.ts","./src/aturi_validation.ts","./src/datetime.ts","./src/did.ts","./src/handle.ts","./src/index.ts","./src/nsid.ts","./src/recordkey.ts","./src/tid.ts"],"version":"5.6.3"}
1
+ {"root":["./src/at-identifier.ts","./src/aturi.ts","./src/aturi_validation.ts","./src/datetime.ts","./src/did.ts","./src/handle.ts","./src/index.ts","./src/nsid.ts","./src/recordkey.ts","./src/tid.ts"],"version":"5.8.2"}
@@ -1 +1 @@
1
- {"root":["./tests/aturi.test.ts","./tests/datetime.test.ts","./tests/did.test.ts","./tests/handle.test.ts","./tests/nsid.test.ts","./tests/recordkey.test.ts","./tests/tid.test.ts"],"version":"5.6.3"}
1
+ {"root":["./tests/aturi.test.ts","./tests/datetime.test.ts","./tests/did.test.ts","./tests/handle.test.ts","./tests/nsid.test.ts","./tests/recordkey.test.ts","./tests/tid.test.ts"],"version":"5.8.3"}