@atproto/lex-schema 0.0.8 → 0.0.10

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