@atproto/lex-schema 0.1.5 → 0.1.6

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 (263) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/core/$type.d.ts +2 -2
  3. package/dist/core/$type.d.ts.map +1 -1
  4. package/dist/core/$type.js.map +1 -1
  5. package/dist/core/record-key.d.ts +1 -1
  6. package/dist/core/record-key.d.ts.map +1 -1
  7. package/dist/core/record-key.js.map +1 -1
  8. package/dist/core/schema.d.ts +3 -2
  9. package/dist/core/schema.d.ts.map +1 -1
  10. package/dist/core/schema.js +1 -1
  11. package/dist/core/schema.js.map +1 -1
  12. package/dist/core/standard-schema.d.ts +2 -2
  13. package/dist/core/standard-schema.d.ts.map +1 -1
  14. package/dist/core/standard-schema.js.map +1 -1
  15. package/dist/core/string-format.d.ts +2 -2
  16. package/dist/core/string-format.d.ts.map +1 -1
  17. package/dist/core/string-format.js.map +1 -1
  18. package/dist/core/validation-error.d.ts +1 -1
  19. package/dist/core/validation-error.d.ts.map +1 -1
  20. package/dist/core/validation-error.js +1 -1
  21. package/dist/core/validation-error.js.map +1 -1
  22. package/dist/core/validator.d.ts +1 -1
  23. package/dist/core/validator.d.ts.map +1 -1
  24. package/dist/core/validator.js +1 -1
  25. package/dist/core/validator.js.map +1 -1
  26. package/dist/helpers.d.ts +2 -2
  27. package/dist/helpers.d.ts.map +1 -1
  28. package/dist/helpers.js +2 -2
  29. package/dist/helpers.js.map +1 -1
  30. package/dist/schema/array.d.ts +1 -1
  31. package/dist/schema/array.d.ts.map +1 -1
  32. package/dist/schema/array.js +1 -1
  33. package/dist/schema/array.js.map +1 -1
  34. package/dist/schema/blob.d.ts +1 -1
  35. package/dist/schema/blob.d.ts.map +1 -1
  36. package/dist/schema/blob.js +2 -2
  37. package/dist/schema/blob.js.map +1 -1
  38. package/dist/schema/boolean.js +1 -1
  39. package/dist/schema/boolean.js.map +1 -1
  40. package/dist/schema/bytes.js +1 -1
  41. package/dist/schema/bytes.js.map +1 -1
  42. package/dist/schema/cid.d.ts +1 -1
  43. package/dist/schema/cid.d.ts.map +1 -1
  44. package/dist/schema/cid.js +3 -3
  45. package/dist/schema/cid.js.map +1 -1
  46. package/dist/schema/custom.js +1 -1
  47. package/dist/schema/custom.js.map +1 -1
  48. package/dist/schema/dict.d.ts +1 -1
  49. package/dist/schema/dict.d.ts.map +1 -1
  50. package/dist/schema/dict.js +1 -1
  51. package/dist/schema/dict.js.map +1 -1
  52. package/dist/schema/discriminated-union.d.ts +1 -1
  53. package/dist/schema/discriminated-union.d.ts.map +1 -1
  54. package/dist/schema/discriminated-union.js +2 -1
  55. package/dist/schema/discriminated-union.js.map +1 -1
  56. package/dist/schema/enum.js +1 -1
  57. package/dist/schema/enum.js.map +1 -1
  58. package/dist/schema/integer.js +1 -1
  59. package/dist/schema/integer.js.map +1 -1
  60. package/dist/schema/intersection.d.ts +1 -1
  61. package/dist/schema/intersection.d.ts.map +1 -1
  62. package/dist/schema/intersection.js +3 -1
  63. package/dist/schema/intersection.js.map +1 -1
  64. package/dist/schema/lex-map.d.ts +1 -1
  65. package/dist/schema/lex-map.d.ts.map +1 -1
  66. package/dist/schema/lex-map.js +1 -1
  67. package/dist/schema/lex-map.js.map +1 -1
  68. package/dist/schema/lex-value.d.ts +1 -1
  69. package/dist/schema/lex-value.d.ts.map +1 -1
  70. package/dist/schema/lex-value.js +1 -1
  71. package/dist/schema/lex-value.js.map +1 -1
  72. package/dist/schema/literal.js +1 -1
  73. package/dist/schema/literal.js.map +1 -1
  74. package/dist/schema/never.js +1 -1
  75. package/dist/schema/never.js.map +1 -1
  76. package/dist/schema/null.js +1 -1
  77. package/dist/schema/null.js.map +1 -1
  78. package/dist/schema/nullable.d.ts +1 -1
  79. package/dist/schema/nullable.d.ts.map +1 -1
  80. package/dist/schema/nullable.js +1 -1
  81. package/dist/schema/nullable.js.map +1 -1
  82. package/dist/schema/object.d.ts +2 -1
  83. package/dist/schema/object.d.ts.map +1 -1
  84. package/dist/schema/object.js +1 -1
  85. package/dist/schema/object.js.map +1 -1
  86. package/dist/schema/optional.d.ts +2 -1
  87. package/dist/schema/optional.d.ts.map +1 -1
  88. package/dist/schema/optional.js +2 -1
  89. package/dist/schema/optional.js.map +1 -1
  90. package/dist/schema/params.d.ts +1 -1
  91. package/dist/schema/params.d.ts.map +1 -1
  92. package/dist/schema/params.js +1 -1
  93. package/dist/schema/params.js.map +1 -1
  94. package/dist/schema/payload.d.ts +3 -2
  95. package/dist/schema/payload.d.ts.map +1 -1
  96. package/dist/schema/payload.js +2 -1
  97. package/dist/schema/payload.js.map +1 -1
  98. package/dist/schema/permission-set.d.ts +1 -1
  99. package/dist/schema/permission-set.d.ts.map +1 -1
  100. package/dist/schema/permission-set.js +1 -0
  101. package/dist/schema/permission-set.js.map +1 -1
  102. package/dist/schema/permission.d.ts +1 -1
  103. package/dist/schema/permission.d.ts.map +1 -1
  104. package/dist/schema/permission.js.map +1 -1
  105. package/dist/schema/procedure.d.ts +1 -1
  106. package/dist/schema/procedure.d.ts.map +1 -1
  107. package/dist/schema/procedure.js +2 -0
  108. package/dist/schema/procedure.js.map +1 -1
  109. package/dist/schema/query.d.ts +1 -1
  110. package/dist/schema/query.d.ts.map +1 -1
  111. package/dist/schema/query.js +2 -0
  112. package/dist/schema/query.js.map +1 -1
  113. package/dist/schema/record.d.ts +2 -2
  114. package/dist/schema/record.d.ts.map +1 -1
  115. package/dist/schema/record.js +1 -1
  116. package/dist/schema/record.js.map +1 -1
  117. package/dist/schema/ref.d.ts +1 -1
  118. package/dist/schema/ref.d.ts.map +1 -1
  119. package/dist/schema/ref.js +1 -1
  120. package/dist/schema/ref.js.map +1 -1
  121. package/dist/schema/refine.d.ts +2 -2
  122. package/dist/schema/refine.d.ts.map +1 -1
  123. package/dist/schema/refine.js +1 -1
  124. package/dist/schema/refine.js.map +1 -1
  125. package/dist/schema/regexp.js +1 -1
  126. package/dist/schema/regexp.js.map +1 -1
  127. package/dist/schema/string.d.ts +2 -2
  128. package/dist/schema/string.d.ts.map +1 -1
  129. package/dist/schema/string.js +1 -1
  130. package/dist/schema/string.js.map +1 -1
  131. package/dist/schema/subscription.d.ts +3 -2
  132. package/dist/schema/subscription.d.ts.map +1 -1
  133. package/dist/schema/subscription.js +2 -0
  134. package/dist/schema/subscription.js.map +1 -1
  135. package/dist/schema/token.d.ts +1 -1
  136. package/dist/schema/token.d.ts.map +1 -1
  137. package/dist/schema/token.js +1 -1
  138. package/dist/schema/token.js.map +1 -1
  139. package/dist/schema/typed-object.d.ts +2 -2
  140. package/dist/schema/typed-object.d.ts.map +1 -1
  141. package/dist/schema/typed-object.js +1 -1
  142. package/dist/schema/typed-object.js.map +1 -1
  143. package/dist/schema/typed-ref.d.ts +1 -1
  144. package/dist/schema/typed-ref.d.ts.map +1 -1
  145. package/dist/schema/typed-ref.js +1 -1
  146. package/dist/schema/typed-ref.js.map +1 -1
  147. package/dist/schema/typed-union.d.ts +1 -1
  148. package/dist/schema/typed-union.d.ts.map +1 -1
  149. package/dist/schema/typed-union.js +3 -1
  150. package/dist/schema/typed-union.js.map +1 -1
  151. package/dist/schema/union.d.ts +1 -1
  152. package/dist/schema/union.d.ts.map +1 -1
  153. package/dist/schema/union.js +1 -1
  154. package/dist/schema/union.js.map +1 -1
  155. package/dist/schema/unknown.js +1 -1
  156. package/dist/schema/unknown.js.map +1 -1
  157. package/dist/schema/with-default.d.ts +1 -1
  158. package/dist/schema/with-default.d.ts.map +1 -1
  159. package/dist/schema/with-default.js +1 -1
  160. package/dist/schema/with-default.js.map +1 -1
  161. package/package.json +6 -10
  162. package/src/core/$type.test.ts +0 -24
  163. package/src/core/$type.ts +0 -199
  164. package/src/core/record-key.ts +0 -85
  165. package/src/core/result.ts +0 -15
  166. package/src/core/schema.ts +0 -412
  167. package/src/core/standard-schema.test.ts +0 -124
  168. package/src/core/standard-schema.ts +0 -31
  169. package/src/core/string-format.ts +0 -411
  170. package/src/core/types.ts +0 -120
  171. package/src/core/validation-error.ts +0 -134
  172. package/src/core/validation-issue.ts +0 -340
  173. package/src/core/validator.ts +0 -636
  174. package/src/core.ts +0 -9
  175. package/src/external.ts +0 -3
  176. package/src/helpers.test.ts +0 -694
  177. package/src/helpers.ts +0 -222
  178. package/src/index.ts +0 -3
  179. package/src/schema/array.test.ts +0 -251
  180. package/src/schema/array.ts +0 -126
  181. package/src/schema/blob.test.ts +0 -733
  182. package/src/schema/blob.ts +0 -150
  183. package/src/schema/boolean.test.ts +0 -118
  184. package/src/schema/boolean.ts +0 -46
  185. package/src/schema/bytes.test.ts +0 -227
  186. package/src/schema/bytes.ts +0 -81
  187. package/src/schema/cid.test.ts +0 -125
  188. package/src/schema/cid.ts +0 -69
  189. package/src/schema/custom.test.ts +0 -414
  190. package/src/schema/custom.ts +0 -106
  191. package/src/schema/dict.test.ts +0 -181
  192. package/src/schema/dict.ts +0 -122
  193. package/src/schema/discriminated-union.test.ts +0 -676
  194. package/src/schema/discriminated-union.ts +0 -196
  195. package/src/schema/enum.test.ts +0 -398
  196. package/src/schema/enum.ts +0 -77
  197. package/src/schema/integer.test.ts +0 -314
  198. package/src/schema/integer.ts +0 -86
  199. package/src/schema/intersection.test.ts +0 -33
  200. package/src/schema/intersection.ts +0 -113
  201. package/src/schema/lex-map.test.ts +0 -593
  202. package/src/schema/lex-map.ts +0 -63
  203. package/src/schema/lex-value.test.ts +0 -81
  204. package/src/schema/lex-value.ts +0 -86
  205. package/src/schema/literal.test.ts +0 -533
  206. package/src/schema/literal.ts +0 -70
  207. package/src/schema/never.test.ts +0 -175
  208. package/src/schema/never.ts +0 -56
  209. package/src/schema/null.test.ts +0 -80
  210. package/src/schema/null.ts +0 -49
  211. package/src/schema/nullable.test.ts +0 -470
  212. package/src/schema/nullable.ts +0 -74
  213. package/src/schema/object.test.ts +0 -69
  214. package/src/schema/object.ts +0 -136
  215. package/src/schema/optional.test.ts +0 -479
  216. package/src/schema/optional.ts +0 -92
  217. package/src/schema/params.test.ts +0 -1118
  218. package/src/schema/params.ts +0 -371
  219. package/src/schema/payload.test.ts +0 -340
  220. package/src/schema/payload.ts +0 -204
  221. package/src/schema/permission-set.test.ts +0 -613
  222. package/src/schema/permission-set.ts +0 -86
  223. package/src/schema/permission.test.ts +0 -537
  224. package/src/schema/permission.ts +0 -63
  225. package/src/schema/procedure.test.ts +0 -324
  226. package/src/schema/procedure.ts +0 -98
  227. package/src/schema/query.test.ts +0 -348
  228. package/src/schema/query.ts +0 -86
  229. package/src/schema/record.test.ts +0 -812
  230. package/src/schema/record.ts +0 -217
  231. package/src/schema/ref.test.ts +0 -349
  232. package/src/schema/ref.ts +0 -103
  233. package/src/schema/refine.test.ts +0 -579
  234. package/src/schema/refine.ts +0 -153
  235. package/src/schema/regexp.test.ts +0 -577
  236. package/src/schema/regexp.ts +0 -82
  237. package/src/schema/string.test.ts +0 -773
  238. package/src/schema/string.ts +0 -229
  239. package/src/schema/subscription.test.ts +0 -499
  240. package/src/schema/subscription.ts +0 -108
  241. package/src/schema/token.test.ts +0 -152
  242. package/src/schema/token.ts +0 -103
  243. package/src/schema/typed-object.test.ts +0 -745
  244. package/src/schema/typed-object.ts +0 -181
  245. package/src/schema/typed-ref.test.ts +0 -796
  246. package/src/schema/typed-ref.ts +0 -126
  247. package/src/schema/typed-union.test.ts +0 -355
  248. package/src/schema/typed-union.ts +0 -130
  249. package/src/schema/union.test.ts +0 -191
  250. package/src/schema/union.ts +0 -89
  251. package/src/schema/unknown.test.ts +0 -313
  252. package/src/schema/unknown.ts +0 -47
  253. package/src/schema/with-default.ts +0 -81
  254. package/src/schema.ts +0 -43
  255. package/src/util/array-agg.test.ts +0 -42
  256. package/src/util/array-agg.ts +0 -44
  257. package/src/util/assertion-util.ts +0 -1
  258. package/src/util/if-any.ts +0 -3
  259. package/src/util/lazy-property.ts +0 -14
  260. package/src/util/memoize.ts +0 -37
  261. package/tsconfig.build.json +0 -12
  262. package/tsconfig.json +0 -7
  263. package/tsconfig.tests.json +0 -8
@@ -1,537 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
- import { permission } from './permission.js'
3
-
4
- describe('Permission', () => {
5
- describe('basic construction', () => {
6
- it('creates a perm with resource and empty options', () => {
7
- const perm = permission('read', {})
8
- expect(perm.resource).toBe('read')
9
- expect(perm.options).toEqual({})
10
- })
11
-
12
- it('creates a perm with resource and options', () => {
13
- const options = { limit: 100 }
14
- const perm = permission('read', options)
15
- expect(perm.resource).toBe('read')
16
- expect(perm.options).toEqual({ limit: 100 })
17
- })
18
-
19
- it('preserves the options object reference', () => {
20
- const options = { limit: 100 }
21
- const perm = permission('read', options)
22
- expect(perm.options).toBe(options)
23
- })
24
-
25
- it('preserves resource as const literal type', () => {
26
- const perm = permission('read' as const, {})
27
- expect(perm.resource).toBe('read')
28
- })
29
- })
30
-
31
- describe('resource strings', () => {
32
- it('handles simple resource names', () => {
33
- const perm = permission('read', {})
34
- expect(perm.resource).toBe('read')
35
- })
36
-
37
- it('handles namespaced resource names', () => {
38
- const perm = permission('com.example.read', {})
39
- expect(perm.resource).toBe('com.example.read')
40
- })
41
-
42
- it('handles resource names with dashes', () => {
43
- const perm = permission('read-posts', {})
44
- expect(perm.resource).toBe('read-posts')
45
- })
46
-
47
- it('handles resource names with underscores', () => {
48
- const perm = permission('read_posts', {})
49
- expect(perm.resource).toBe('read_posts')
50
- })
51
-
52
- it('handles resource names with colons', () => {
53
- const perm = permission('posts:read', {})
54
- expect(perm.resource).toBe('posts:read')
55
- })
56
-
57
- it('handles resource names with slashes', () => {
58
- const perm = permission('posts/read', {})
59
- expect(perm.resource).toBe('posts/read')
60
- })
61
-
62
- it('handles resource names with wildcards', () => {
63
- const perm = permission('posts:*', {})
64
- expect(perm.resource).toBe('posts:*')
65
- })
66
-
67
- it('handles empty resource string', () => {
68
- const perm = permission('', {})
69
- expect(perm.resource).toBe('')
70
- })
71
-
72
- it('handles very long resource strings', () => {
73
- const longResource = 'com.example.service.'.repeat(50) + 'read'
74
- const perm = permission(longResource, {})
75
- expect(perm.resource).toBe(longResource)
76
- })
77
-
78
- it('handles resource strings with unicode characters', () => {
79
- const perm = permission('リソース', {})
80
- expect(perm.resource).toBe('リソース')
81
- })
82
-
83
- it('handles resource strings with special characters', () => {
84
- const perm = permission('resource@#$%', {})
85
- expect(perm.resource).toBe('resource@#$%')
86
- })
87
- })
88
-
89
- describe('options with string parameters', () => {
90
- it('accepts empty options object', () => {
91
- const perm = permission('read', {})
92
- expect(perm.options).toEqual({})
93
- })
94
-
95
- it('accepts options with string value', () => {
96
- const perm = permission('read', { format: 'json' })
97
- expect(perm.options).toEqual({ format: 'json' })
98
- })
99
-
100
- it('accepts options with multiple string values', () => {
101
- const perm = permission('read', {
102
- format: 'json',
103
- encoding: 'utf-8',
104
- })
105
- expect(perm.options).toEqual({ format: 'json', encoding: 'utf-8' })
106
- })
107
-
108
- it('accepts options with empty string value', () => {
109
- const perm = permission('read', { filter: '' })
110
- expect(perm.options).toEqual({ filter: '' })
111
- })
112
-
113
- it('accepts options with very long string values', () => {
114
- const longString = 'value'.repeat(1000)
115
- const perm = permission('read', { data: longString })
116
- expect(perm.options.data).toBe(longString)
117
- })
118
- })
119
-
120
- describe('options with integer parameters', () => {
121
- it('accepts options with positive integer', () => {
122
- const perm = permission('read', { limit: 100 })
123
- expect(perm.options).toEqual({ limit: 100 })
124
- })
125
-
126
- it('accepts options with zero', () => {
127
- const perm = permission('read', { offset: 0 })
128
- expect(perm.options).toEqual({ offset: 0 })
129
- })
130
-
131
- it('accepts options with negative integer', () => {
132
- const perm = permission('read', { delta: -50 })
133
- expect(perm.options).toEqual({ delta: -50 })
134
- })
135
-
136
- it('accepts options with multiple integers', () => {
137
- const perm = permission('read', {
138
- limit: 100,
139
- offset: 20,
140
- maxRetries: 3,
141
- })
142
- expect(perm.options).toEqual({
143
- limit: 100,
144
- offset: 20,
145
- maxRetries: 3,
146
- })
147
- })
148
-
149
- it('accepts options with large integers', () => {
150
- const perm = permission('read', { maxSize: 2147483647 })
151
- expect(perm.options).toEqual({ maxSize: 2147483647 })
152
- })
153
- })
154
-
155
- describe('options with boolean parameters', () => {
156
- it('accepts options with true boolean', () => {
157
- const perm = permission('read', { includeDeleted: true })
158
- expect(perm.options).toEqual({ includeDeleted: true })
159
- })
160
-
161
- it('accepts options with false boolean', () => {
162
- const perm = permission('read', { includeDeleted: false })
163
- expect(perm.options).toEqual({ includeDeleted: false })
164
- })
165
-
166
- it('accepts options with multiple booleans', () => {
167
- const perm = permission('read', {
168
- includeDeleted: true,
169
- includeDrafts: false,
170
- includeArchived: true,
171
- })
172
- expect(perm.options).toEqual({
173
- includeDeleted: true,
174
- includeDrafts: false,
175
- includeArchived: true,
176
- })
177
- })
178
- })
179
-
180
- describe('options with array parameters', () => {
181
- it('accepts options with string array', () => {
182
- const perm = permission('read', { fields: ['id', 'name'] })
183
- expect(perm.options).toEqual({ fields: ['id', 'name'] })
184
- })
185
-
186
- it('accepts options with integer array', () => {
187
- const perm = permission('read', { ids: [1, 2, 3] })
188
- expect(perm.options).toEqual({ ids: [1, 2, 3] })
189
- })
190
-
191
- it('accepts options with boolean array', () => {
192
- const perm = permission('read', { flags: [true, false, true] })
193
- expect(perm.options).toEqual({ flags: [true, false, true] })
194
- })
195
-
196
- it('accepts options with empty array', () => {
197
- const perm = permission('read', { fields: [] })
198
- expect(perm.options).toEqual({ fields: [] })
199
- })
200
-
201
- it('preserves array reference in options', () => {
202
- const fields = ['id', 'name']
203
- const perm = permission('read', { fields })
204
- expect(perm.options.fields).toBe(fields)
205
- })
206
- })
207
-
208
- describe('options with mixed parameter types', () => {
209
- it('accepts options with string, integer, and boolean', () => {
210
- const perm = permission('read', {
211
- format: 'json',
212
- limit: 100,
213
- includeDeleted: true,
214
- })
215
- expect(perm.options).toEqual({
216
- format: 'json',
217
- limit: 100,
218
- includeDeleted: true,
219
- })
220
- })
221
-
222
- it('accepts options with all parameter types', () => {
223
- const perm = permission('read', {
224
- format: 'json',
225
- limit: 100,
226
- includeDeleted: true,
227
- fields: ['id', 'name'],
228
- })
229
- expect(perm.options).toEqual({
230
- format: 'json',
231
- limit: 100,
232
- includeDeleted: true,
233
- fields: ['id', 'name'],
234
- })
235
- })
236
-
237
- it('accepts options with many parameters', () => {
238
- const perm = permission('read', {
239
- param1: 'value1',
240
- param2: 'value2',
241
- param3: 'value3',
242
- param4: 123,
243
- param5: 456,
244
- param6: true,
245
- param7: false,
246
- param8: ['a', 'b'],
247
- })
248
- expect(perm.options).toEqual({
249
- param1: 'value1',
250
- param2: 'value2',
251
- param3: 'value3',
252
- param4: 123,
253
- param5: 456,
254
- param6: true,
255
- param7: false,
256
- param8: ['a', 'b'],
257
- })
258
- })
259
- })
260
-
261
- describe('options with undefined values', () => {
262
- it('accepts options with undefined values', () => {
263
- const perm = permission('read', {
264
- optionalParam: undefined,
265
- })
266
- expect(perm.options).toEqual({ optionalParam: undefined })
267
- })
268
-
269
- it('accepts options with mix of defined and undefined values', () => {
270
- const perm = permission('read', {
271
- required: 'value',
272
- optional: undefined,
273
- })
274
- expect(perm.options).toEqual({
275
- required: 'value',
276
- optional: undefined,
277
- })
278
- })
279
-
280
- it('preserves undefined in options object', () => {
281
- const options = { param: undefined }
282
- const perm = permission('read', options)
283
- expect('param' in perm.options).toBe(true)
284
- expect(perm.options.param).toBeUndefined()
285
- })
286
- })
287
-
288
- describe('multiple perm instances', () => {
289
- it('creates independent instances', () => {
290
- const perm1 = permission('read', { limit: 100 })
291
- const perm2 = permission('write', { format: 'json' })
292
-
293
- expect(perm1.resource).toBe('read')
294
- expect(perm2.resource).toBe('write')
295
- expect(perm1.options).toEqual({ limit: 100 })
296
- expect(perm2.options).toEqual({ format: 'json' })
297
- })
298
-
299
- it('instances with same values are not equal', () => {
300
- const perm1 = permission('read', { limit: 100 })
301
- const perm2 = permission('read', { limit: 100 })
302
-
303
- expect(perm1).not.toBe(perm2)
304
- expect(perm1.resource).toBe(perm2.resource)
305
- expect(perm1.options).not.toBe(perm2.options)
306
- expect(perm1.options).toEqual(perm2.options)
307
- })
308
-
309
- it('instances sharing options object reference', () => {
310
- const options = { limit: 100 }
311
- const perm1 = permission('read', options)
312
- const perm2 = permission('write', options)
313
-
314
- expect(perm1.options).toBe(perm2.options)
315
- expect(perm1.options).toBe(options)
316
- expect(perm2.options).toBe(options)
317
- })
318
- })
319
-
320
- describe('common perm patterns', () => {
321
- it('creates read perm', () => {
322
- const perm = permission('read', {})
323
- expect(perm.resource).toBe('read')
324
- })
325
-
326
- it('creates write perm', () => {
327
- const perm = permission('write', {})
328
- expect(perm.resource).toBe('write')
329
- })
330
-
331
- it('creates delete perm', () => {
332
- const perm = permission('delete', {})
333
- expect(perm.resource).toBe('delete')
334
- })
335
-
336
- it('creates admin perm', () => {
337
- const perm = permission('admin', {})
338
- expect(perm.resource).toBe('admin')
339
- })
340
-
341
- it('creates scoped resource perm', () => {
342
- const perm = permission('posts:read', { limit: 50 })
343
- expect(perm.resource).toBe('posts:read')
344
- expect(perm.options).toEqual({ limit: 50 })
345
- })
346
-
347
- it('creates namespaced perm', () => {
348
- const perm = permission('com.example.posts.read', {
349
- includeDeleted: false,
350
- })
351
- expect(perm.resource).toBe('com.example.posts.read')
352
- expect(perm.options).toEqual({ includeDeleted: false })
353
- })
354
-
355
- it('creates CRUD perms', () => {
356
- const create = permission('create', {})
357
- const read = permission('read', {})
358
- const update = permission('update', {})
359
- const deleteP = permission('delete', {})
360
-
361
- expect(create.resource).toBe('create')
362
- expect(read.resource).toBe('read')
363
- expect(update.resource).toBe('update')
364
- expect(deleteP.resource).toBe('delete')
365
- })
366
-
367
- it('creates perm with scope and filters', () => {
368
- const perm = permission('posts:read', {
369
- scope: 'public',
370
- limit: 100,
371
- includeDeleted: false,
372
- })
373
- expect(perm.resource).toBe('posts:read')
374
- expect(perm.options).toEqual({
375
- scope: 'public',
376
- limit: 100,
377
- includeDeleted: false,
378
- })
379
- })
380
- })
381
-
382
- describe('edge cases', () => {
383
- it('handles perm with all parameter types in options', () => {
384
- const perm = permission('complex', {
385
- stringParam: 'value',
386
- intParam: 42,
387
- boolParam: true,
388
- arrayParam: [1, 2, 3],
389
- undefinedParam: undefined,
390
- })
391
-
392
- expect(perm.options.stringParam).toBe('value')
393
- expect(perm.options.intParam).toBe(42)
394
- expect(perm.options.boolParam).toBe(true)
395
- expect(perm.options.arrayParam).toEqual([1, 2, 3])
396
- expect(perm.options.undefinedParam).toBeUndefined()
397
- })
398
-
399
- it('handles resource with whitespace', () => {
400
- const perm = permission('read posts', {})
401
- expect(perm.resource).toBe('read posts')
402
- })
403
-
404
- it('handles resource with leading/trailing whitespace', () => {
405
- const perm = permission(' read ', {})
406
- expect(perm.resource).toBe(' read ')
407
- })
408
-
409
- it('handles options with numeric string keys', () => {
410
- const perm = permission('read', { '123': 'value' })
411
- expect(perm.options['123']).toBe('value')
412
- })
413
-
414
- it('handles options with special character keys', () => {
415
- const perm = permission('read', { 'key-name': 'value' })
416
- expect(perm.options['key-name']).toBe('value')
417
- })
418
- })
419
-
420
- describe('type safety', () => {
421
- it('preserves resource type as literal', () => {
422
- const perm = permission('read' as const, {})
423
- // At compile time, TypeScript should infer the type as 'read'
424
- expect(perm.resource).toBe('read')
425
- })
426
-
427
- it('preserves options type', () => {
428
- const options = { limit: 100 } as const
429
- const perm = permission('read', options)
430
- // At compile time, TypeScript should infer the exact type
431
- expect(perm.options.limit).toBe(100)
432
- })
433
-
434
- it('handles generic string resource type', () => {
435
- const resource: string = 'dynamic'
436
- const perm = permission(resource, {})
437
- expect(perm.resource).toBe('dynamic')
438
- })
439
-
440
- it('handles union resource types', () => {
441
- type ResourceType = 'read' | 'write' | 'delete'
442
- const resource: ResourceType = 'read'
443
- const perm = permission(resource, {})
444
- expect(perm.resource).toBe('read')
445
- })
446
- })
447
-
448
- describe('constructor behavior', () => {
449
- it('requires both resource and options arguments', () => {
450
- // TypeScript enforces this at compile time
451
- const perm = permission('read', {})
452
- expect(perm.resource).toBeDefined()
453
- expect(perm.options).toBeDefined()
454
- })
455
-
456
- it('does not modify input options object', () => {
457
- const options = { limit: 100 }
458
- const originalOptions = { ...options }
459
- permission('read', options)
460
- expect(options).toEqual(originalOptions)
461
- })
462
-
463
- it('accepts options as object literal', () => {
464
- const perm = permission('read', { limit: 100 })
465
- expect(perm.options).toEqual({ limit: 100 })
466
- })
467
-
468
- it('accepts options as variable', () => {
469
- const options = { limit: 100 }
470
- const perm = permission('read', options)
471
- expect(perm.options).toEqual({ limit: 100 })
472
- })
473
-
474
- it('accepts resource as string literal', () => {
475
- const perm = permission('read', {})
476
- expect(perm.resource).toBe('read')
477
- })
478
-
479
- it('accepts resource as variable', () => {
480
- const resource = 'read'
481
- const perm = permission(resource, {})
482
- expect(perm.resource).toBe('read')
483
- })
484
- })
485
-
486
- describe('object enumeration', () => {
487
- it('enumerates all properties', () => {
488
- const perm = permission('read', { limit: 100 })
489
- const keys = Object.keys(perm)
490
- expect(keys).toContain('resource')
491
- expect(keys).toContain('options')
492
- })
493
-
494
- it('can be spread into object', () => {
495
- const perm = permission('read', { limit: 100 })
496
- const spread = { ...perm }
497
- expect(spread.resource).toBe('read')
498
- expect(spread.options).toEqual({ limit: 100 })
499
- })
500
- })
501
-
502
- describe('JSON serialization', () => {
503
- it('can be JSON stringified', () => {
504
- const perm = permission('read', { limit: 100 })
505
- const json = JSON.stringify(perm)
506
- const parsed = JSON.parse(json)
507
- expect(parsed.resource).toBe('read')
508
- expect(parsed.options).toEqual({ limit: 100 })
509
- })
510
-
511
- it('handles complex options in JSON', () => {
512
- const perm = permission('read', {
513
- fields: ['id', 'name'],
514
- limit: 100,
515
- includeDeleted: false,
516
- })
517
- const json = JSON.stringify(perm)
518
- const parsed = JSON.parse(json)
519
- expect(parsed.options).toEqual({
520
- fields: ['id', 'name'],
521
- limit: 100,
522
- includeDeleted: false,
523
- })
524
- })
525
-
526
- it('preserves undefined in JSON serialization', () => {
527
- const perm = permission('read', {
528
- defined: 'value',
529
- undefined: undefined,
530
- })
531
- // JSON.stringify removes undefined values by default
532
- const json = JSON.stringify(perm)
533
- const parsed = JSON.parse(json)
534
- expect('undefined' in parsed.options).toBe(false)
535
- })
536
- })
537
- })
@@ -1,63 +0,0 @@
1
- import { Params } from './params.js'
2
-
3
- /**
4
- * Type alias for permission options (same as Params).
5
- */
6
- export type PermissionOptions = Params
7
-
8
- /**
9
- * Represents a single permission in an AT Protocol permission set.
10
- *
11
- * Permissions define access rights to specific resources with optional
12
- * parameters for fine-grained control.
13
- *
14
- * @template TResource - The resource identifier string type
15
- * @template TOptions - The options type (must be valid Params)
16
- *
17
- * @example
18
- * ```ts
19
- * const readPermission = new Permission('read', { collection: 'app.bsky.feed.post' })
20
- * ```
21
- */
22
- export class Permission<
23
- const TResource extends string = any,
24
- const TOptions extends PermissionOptions = any,
25
- > {
26
- constructor(
27
- readonly resource: TResource,
28
- readonly options: TOptions,
29
- ) {}
30
- }
31
-
32
- /**
33
- * Creates a permission definition for AT Protocol authorization.
34
- *
35
- * Permissions specify what resources an application can access.
36
- * Used in permission sets to define OAuth scopes.
37
- *
38
- * @param resource - The resource identifier (e.g., 'read', 'write', 'admin')
39
- * @param options - Optional parameters for the permission
40
- * @returns A new {@link Permission} instance
41
- *
42
- * @example
43
- * ```ts
44
- * // Simple permission
45
- * const readPermission = l.permission('read')
46
- *
47
- * // Permission with options
48
- * const writePostsPermission = l.permission('write', {
49
- * collection: 'app.bsky.feed.post',
50
- * })
51
- *
52
- * // Multiple permissions with different scopes
53
- * const readProfile = l.permission('read', { collection: 'app.bsky.actor.profile' })
54
- * const readFeed = l.permission('read', { collection: 'app.bsky.feed.*' })
55
- * ```
56
- */
57
- /*@__NO_SIDE_EFFECTS__*/
58
- export function permission<
59
- const R extends string,
60
- const O extends PermissionOptions,
61
- >(resource: R, options: PermissionOptions & O = {} as O) {
62
- return new Permission<R, O>(resource, options)
63
- }