@atproto/syntax 0.5.3 → 0.6.0-next.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 (53) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/at-identifier.js +15 -23
  3. package/dist/at-identifier.js.map +1 -1
  4. package/dist/aturi.d.ts.map +1 -1
  5. package/dist/aturi.js +30 -32
  6. package/dist/aturi.js.map +1 -1
  7. package/dist/aturi_validation.d.ts +137 -4
  8. package/dist/aturi_validation.d.ts.map +1 -1
  9. package/dist/aturi_validation.js +172 -102
  10. package/dist/aturi_validation.js.map +1 -1
  11. package/dist/datetime.d.ts +5 -0
  12. package/dist/datetime.d.ts.map +1 -1
  13. package/dist/datetime.js +52 -38
  14. package/dist/datetime.js.map +1 -1
  15. package/dist/did.js +4 -11
  16. package/dist/did.js.map +1 -1
  17. package/dist/handle.js +13 -26
  18. package/dist/handle.js.map +1 -1
  19. package/dist/index.js +10 -13
  20. package/dist/index.js.map +1 -1
  21. package/dist/language.js +2 -6
  22. package/dist/language.js.map +1 -1
  23. package/dist/lib/result.d.ts +12 -0
  24. package/dist/lib/result.d.ts.map +1 -0
  25. package/dist/lib/result.js +7 -0
  26. package/dist/lib/result.js.map +1 -0
  27. package/dist/nsid.d.ts +3 -10
  28. package/dist/nsid.d.ts.map +1 -1
  29. package/dist/nsid.js +23 -82
  30. package/dist/nsid.js.map +1 -1
  31. package/dist/recordkey.js +3 -9
  32. package/dist/recordkey.js.map +1 -1
  33. package/dist/tid.js +3 -9
  34. package/dist/tid.js.map +1 -1
  35. package/dist/uri.js +1 -4
  36. package/dist/uri.js.map +1 -1
  37. package/package.json +12 -4
  38. package/src/aturi.ts +13 -7
  39. package/src/aturi_validation.ts +279 -110
  40. package/src/datetime.ts +41 -8
  41. package/src/lib/result.ts +11 -0
  42. package/src/nsid.ts +20 -56
  43. package/tests/aturi-string.test.ts +72 -40
  44. package/tests/aturi.test.ts +5 -5
  45. package/tests/datetime.test.ts +23 -1
  46. package/tests/did.test.ts +5 -1
  47. package/tests/handle.test.ts +1 -1
  48. package/tests/language.test.ts +1 -1
  49. package/tests/nsid.test.ts +1 -1
  50. package/tests/recordkey.test.ts +1 -1
  51. package/tests/tid.test.ts +1 -1
  52. package/tsconfig.build.tsbuildinfo +1 -1
  53. /package/{benchmark.js → benchmark.cjs} +0 -0
@@ -1,6 +1,10 @@
1
1
  import { readFileSync } from 'node:fs'
2
2
  import { describe, expect, test } from 'vitest'
3
- import { ensureValidAtUri, isValidAtUri } from '../src'
3
+ import {
4
+ InvalidAtUriError,
5
+ assertAtUriString,
6
+ isAtUriString,
7
+ } from '../src/index.js'
4
8
 
5
9
  describe('valid interop', () => {
6
10
  for (const value of readLines(
@@ -10,13 +14,13 @@ describe('valid interop', () => {
10
14
  }
11
15
  })
12
16
 
13
- // describe('invalid interop', () => {
14
- // for (const value of readLines(
15
- // `${__dirname}/../../../interop-test-files/syntax/aturi_syntax_invalid.txt`,
16
- // )) {
17
- // testInvalid(value)
18
- // }
19
- // })
17
+ describe('invalid interop', () => {
18
+ for (const value of readLines(
19
+ `${__dirname}/../../../interop-test-files/syntax/aturi_syntax_invalid.txt`,
20
+ )) {
21
+ testInvalid(value)
22
+ }
23
+ })
20
24
 
21
25
  describe('custom cases', () => {
22
26
  describe('valid spec basics', () => {
@@ -65,6 +69,16 @@ describe('custom cases', () => {
65
69
  testInvalid('at://did:plc:asdf123/-com.atproto.feed.post')
66
70
  testInvalid('at://did:plc:asdf@123/com.atproto.feed.post')
67
71
 
72
+ testInvalid('at://did:plc:asdf123?a')
73
+ testInvalid('at://user.bsky.social?a=B')
74
+ testInvalid('at://did:plc:asdf123/com.atproto.feed.post?foo=bar')
75
+ testInvalid('at://did:plc:asdf123/com.atproto.feed.post/record?q=3')
76
+
77
+ testInvalid('at://did:plc:asdf123?a=b#/frag')
78
+ testInvalid('at://user.bsky.social?a=b#/frag')
79
+ testInvalid('at://did:plc:asdf123/com.atproto.feed.post?a=b#/frag')
80
+ testInvalid('at://did:plc:asdf123/com.atproto.feed.post/record?a=b#/frag')
81
+
68
82
  testInvalid('at://DID:plc:asdf123')
69
83
  testInvalid('at://user.bsky.123')
70
84
  testInvalid('at://bsky')
@@ -74,8 +88,11 @@ describe('custom cases', () => {
74
88
  })
75
89
 
76
90
  describe('very long strings', () => {
77
- testValid('at://did:plc:asdf123/com.atproto.feed.post/' + 'o'.repeat(800))
91
+ testValid('at://did:plc:asdf123/com.atproto.feed.post/' + 'o'.repeat(512))
92
+ testValid(`at://did:web:x${'.y'.repeat(100)}/com.atproto.feed.post/record`)
78
93
  testInvalid(`at://did:plc:${'o'.repeat(8200)}/com.atproto.feed.post/record`)
94
+ testInvalid('at://did:plc:asdf123/com.atproto.feed.post/' + 'o'.repeat(513))
95
+ testInvalid('at://did:plc:asdf123/com.atproto.feed.post/' + 'o'.repeat(800))
79
96
  })
80
97
 
81
98
  describe('invalid collection', () => {
@@ -107,36 +124,39 @@ describe('custom cases', () => {
107
124
  testValid('at://did:plc:asdf123/com.atproto.feed.post/asdf123')
108
125
  })
109
126
 
110
- describe('invalid trailing slash', () => {
111
- testInvalid('at://did:plc:asdf123/')
112
- testInvalid('at://user.bsky.social/')
113
- testInvalid('at://did:plc:asdf123/com.atproto.feed.post/')
114
- testInvalid('at://did:plc:asdf123/com.atproto.feed.post/record/')
115
- testInvalid('at://did:plc:asdf123/com.atproto.feed.post/record/#/frag')
127
+ describe('loosely valid trailing slash', () => {
128
+ testLoose('at://did:plc:asdf123/')
129
+ testLoose('at://user.bsky.social/')
130
+ testLoose('at://did:plc:asdf123/com.atproto.feed.post/')
131
+ testLoose('at://did:plc:asdf123/com.atproto.feed.post/record/')
132
+ testLoose('at://did:plc:asdf123/com.atproto.feed.post/record/#/frag')
116
133
  })
117
134
 
118
- describe('invalid record keys', () => {
119
- // is probably too permissive about URL encoding
120
- testValid('at://did:plc:asdf123/com.atproto.feed.post/%30')
121
- testValid('at://did:plc:asdf123/com.atproto.feed.post/%3')
122
- testValid('at://did:plc:asdf123/com.atproto.feed.post/%')
123
- testValid('at://did:plc:asdf123/com.atproto.feed.post/%zz')
124
- testValid('at://did:plc:asdf123/com.atproto.feed.post/%%%')
125
-
126
- // is very permissive about fragments
127
- testValid('at://did:plc:asdf123/com.atproto.feed.post/%23')
128
-
129
- testValid('at://did:plc:asdf123/com.atproto.feed.post/$@!*)(:,;~.sdf123')
130
- testValid("at://did:plc:asdf123/com.atproto.feed.post/~'sdf123")
131
-
132
- testValid('at://did:plc:asdf123/com.atproto.feed.post/$')
133
- testValid('at://did:plc:asdf123/com.atproto.feed.post/@')
134
- testValid('at://did:plc:asdf123/com.atproto.feed.post/!')
135
- testValid('at://did:plc:asdf123/com.atproto.feed.post/*')
136
- testValid('at://did:plc:asdf123/com.atproto.feed.post/(')
137
- testValid('at://did:plc:asdf123/com.atproto.feed.post/,')
138
- testValid('at://did:plc:asdf123/com.atproto.feed.post/;')
139
- testValid('at://did:plc:asdf123/com.atproto.feed.post/abc%30123')
135
+ describe('loosely valid record keys', () => {
136
+ testLoose('at://did:plc:asdf123/com.atproto.feed.post/%23')
137
+
138
+ testLoose('at://did:plc:asdf123/com.atproto.feed.post/$@!*)(:,;~.sdf123')
139
+ testLoose("at://did:plc:asdf123/com.atproto.feed.post/~'sdf123")
140
+
141
+ testLoose('at://did:plc:asdf123/com.atproto.feed.post/$')
142
+ testLoose('at://did:plc:asdf123/com.atproto.feed.post/@')
143
+ testLoose('at://did:plc:asdf123/com.atproto.feed.post/!')
144
+ testLoose('at://did:plc:asdf123/com.atproto.feed.post/*')
145
+ testLoose('at://did:plc:asdf123/com.atproto.feed.post/(')
146
+ testLoose('at://did:plc:asdf123/com.atproto.feed.post/,')
147
+ testLoose('at://did:plc:asdf123/com.atproto.feed.post/;')
148
+ testLoose('at://did:plc:asdf123/com.atproto.feed.post/abc%30123')
149
+
150
+ testLoose('at://did:plc:asdf123/com.atproto.feed.post/%30')
151
+ testLoose('at://did:plc:asdf123/com.atproto.feed.post/%3')
152
+ testLoose('at://did:plc:asdf123/com.atproto.feed.post/%')
153
+ testLoose('at://did:plc:asdf123/com.atproto.feed.post/%zz')
154
+ testLoose('at://did:plc:asdf123/com.atproto.feed.post/%%%')
155
+
156
+ testLoose('at://did:plc:asdf123/com.atproto.feed.post/[]')
157
+ testLoose('at://did:plc:asdf123/com.atproto.feed.post/foo[')
158
+ testLoose('at://did:plc:asdf123/com.atproto.feed.post/bar]')
159
+ testLoose('at://did:plc:asdf123/com.atproto.feed.post/[baz]')
140
160
  })
141
161
 
142
162
  describe('valid fragment', () => {
@@ -165,14 +185,26 @@ describe('custom cases', () => {
165
185
 
166
186
  function testValid(value: string) {
167
187
  test(value, () => {
168
- expect(isValidAtUri(value)).toBe(true)
169
- expect(() => ensureValidAtUri(value)).not.toThrow()
188
+ expect(isAtUriString(value)).toBe(true)
189
+ expect(isAtUriString(value, { strict: false })).toBe(true)
190
+ expect(() => assertAtUriString(value)).not.toThrow()
191
+ expect(() => assertAtUriString(value, { strict: false })).not.toThrow()
170
192
  })
171
193
  }
172
194
 
173
195
  function testInvalid(value: string) {
174
196
  test(value, () => {
175
- expect(isValidAtUri(value)).toBe(false)
197
+ expect(isAtUriString(value)).toBe(false)
198
+ expect(() => assertAtUriString(value)).toThrow(InvalidAtUriError)
199
+ })
200
+ }
201
+
202
+ function testLoose(value: string) {
203
+ test(value, () => {
204
+ expect(isAtUriString(value)).toBe(false)
205
+ expect(isAtUriString(value, { strict: false })).toBe(true)
206
+ expect(() => assertAtUriString(value)).toThrow()
207
+ expect(() => assertAtUriString(value, { strict: false })).not.toThrow()
176
208
  })
177
209
  }
178
210
 
@@ -1,6 +1,6 @@
1
1
  import { readFileSync } from 'node:fs'
2
2
  import { describe, expect, it, test } from 'vitest'
3
- import { AtUri } from '../src'
3
+ import { AtUri } from '../src/index.js'
4
4
 
5
5
  describe(AtUri, () => {
6
6
  describe('parses valid interop', () => {
@@ -294,16 +294,16 @@ describe(AtUri, () => {
294
294
 
295
295
  it('supports modifications', () => {
296
296
  const urip = new AtUri('at://foo.com')
297
- expect(urip.toString()).toBe('at://foo.com/')
297
+ expect(urip.toString()).toBe('at://foo.com')
298
298
 
299
299
  urip.host = 'bar.com'
300
- expect(urip.toString()).toBe('at://bar.com/')
300
+ expect(urip.toString()).toBe('at://bar.com')
301
301
  urip.host = 'did:web:localhost%3A1234'
302
- expect(urip.toString()).toBe('at://did:web:localhost%3A1234/')
302
+ expect(urip.toString()).toBe('at://did:web:localhost%3A1234')
303
303
  urip.host = 'foo.com'
304
304
 
305
305
  urip.pathname = '/'
306
- expect(urip.toString()).toBe('at://foo.com/')
306
+ expect(urip.toString()).toBe('at://foo.com')
307
307
  urip.pathname = '/foo'
308
308
  expect(urip.toString()).toBe('at://foo.com/foo')
309
309
  urip.pathname = 'foo'
@@ -6,7 +6,7 @@ import {
6
6
  isValidDatetime,
7
7
  normalizeDatetime,
8
8
  normalizeDatetimeAlways,
9
- } from '../src'
9
+ } from '../src/index.js'
10
10
 
11
11
  const interopValid = readLines(
12
12
  `${__dirname}/interop-files/datetime_syntax_valid.txt`,
@@ -128,9 +128,28 @@ describe(normalizeDatetime, () => {
128
128
  expect(normalizeDatetime('1985-04-12T10:20:50.1+01:00')).toEqual(
129
129
  '1985-04-12T09:20:50.100Z',
130
130
  )
131
+ expect(normalizeDatetime('Fri, 02 Jan 1999 12:34:56+1212')).toEqual(
132
+ '1999-01-02T00:22:56.000Z',
133
+ )
134
+ expect(normalizeDatetime('Fri, 02 Jan 1999 12:34:56Z')).toEqual(
135
+ '1999-01-02T12:34:56.000Z',
136
+ )
131
137
  expect(normalizeDatetime('Fri, 02 Jan 1999 12:34:56 GMT')).toEqual(
132
138
  '1999-01-02T12:34:56.000Z',
133
139
  )
140
+ expect(normalizeDatetime('Fri, 02 Jan 1999 12:34:56 PST')).toEqual(
141
+ '1999-01-02T20:34:56.000Z',
142
+ )
143
+ expect(normalizeDatetime('Fri, 02 Jan 1999 12:34:56 EST')).toEqual(
144
+ '1999-01-02T17:34:56.000Z',
145
+ )
146
+ // @NOTE "(Central European Standard Time)" is not used by "Date" to infer
147
+ // the right timezone offset, so these will be parsed as UTC
148
+ expect(
149
+ normalizeDatetime(
150
+ 'Fri, 02 Jan 1999 12:34:56 (Central European Standard Time)',
151
+ ),
152
+ ).toEqual('1999-01-02T12:34:56.000Z')
134
153
  expect(normalizeDatetime('0001-01-01T00:00:00+01:00')).toEqual(
135
154
  '0000-12-31T23:00:00.000Z',
136
155
  )
@@ -170,6 +189,9 @@ describe(normalizeDatetime, () => {
170
189
  expect(() => normalizeDatetime('1999-19-39T23:20:50.123Z')).toThrow(
171
190
  InvalidDatetimeError,
172
191
  )
192
+ expect(() => normalizeDatetime('Fri, 02 Jan 1999 12:34:56 AFT')).toThrow(
193
+ InvalidDatetimeError,
194
+ )
173
195
  expect(() => normalizeDatetime('-000001-12-31T23:00:00.000Z')).toThrow(
174
196
  InvalidDatetimeError,
175
197
  )
package/tests/did.test.ts CHANGED
@@ -1,7 +1,11 @@
1
1
  import * as fs from 'node:fs'
2
2
  import * as readline from 'node:readline'
3
3
  import { describe, expect, it } from 'vitest'
4
- import { InvalidDidError, ensureValidDid, ensureValidDidRegex } from '../src'
4
+ import {
5
+ InvalidDidError,
6
+ ensureValidDid,
7
+ ensureValidDidRegex,
8
+ } from '../src/index.js'
5
9
 
6
10
  describe('DID permissive validation', () => {
7
11
  const expectValid = (h: string) => {
@@ -6,7 +6,7 @@ import {
6
6
  ensureValidHandle,
7
7
  ensureValidHandleRegex,
8
8
  normalizeAndEnsureValidHandle,
9
- } from '../src'
9
+ } from '../src/index.js'
10
10
 
11
11
  describe('handle validation', () => {
12
12
  const expectValid = (h: string) => {
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, it } from 'vitest'
2
- import { isValidLanguage, parseLanguageString } from '../src'
2
+ import { isValidLanguage, parseLanguageString } from '../src/index.js'
3
3
 
4
4
  describe(isValidLanguage, () => {
5
5
  it('validates BCP 47', () => {
@@ -8,7 +8,7 @@ import {
8
8
  parseNsid,
9
9
  validateNsid,
10
10
  validateNsidRegex,
11
- } from '../src'
11
+ } from '../src/index.js'
12
12
 
13
13
  describe('NSID parsing & creation', () => {
14
14
  it('parses valid NSIDs', () => {
@@ -1,7 +1,7 @@
1
1
  import * as fs from 'node:fs'
2
2
  import * as readline from 'node:readline'
3
3
  import { describe, expect, it } from 'vitest'
4
- import { InvalidRecordKeyError, ensureValidRecordKey } from '../src'
4
+ import { InvalidRecordKeyError, ensureValidRecordKey } from '../src/index.js'
5
5
 
6
6
  describe('recordkey validation', () => {
7
7
  const expectValid = (r: string) => {
package/tests/tid.test.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as fs from 'node:fs'
2
2
  import * as readline from 'node:readline'
3
3
  import { describe, expect, it } from 'vitest'
4
- import { InvalidTidError, ensureValidTid } from '../src'
4
+ import { InvalidTidError, ensureValidTid } from '../src/index.js'
5
5
 
6
6
  describe('tid validation', () => {
7
7
  const expectValid = (t: string) => {
@@ -1 +1 @@
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/language.ts","./src/nsid.ts","./src/recordkey.ts","./src/tid.ts","./src/uri.ts"],"version":"5.8.2"}
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/language.ts","./src/nsid.ts","./src/recordkey.ts","./src/tid.ts","./src/uri.ts","./src/lib/result.ts"],"version":"6.0.3"}
File without changes