@atproto/oauth-scopes 0.0.2 → 0.1.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 (169) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/atproto-oauth-scope.d.ts +12 -0
  3. package/dist/atproto-oauth-scope.d.ts.map +1 -0
  4. package/dist/atproto-oauth-scope.js +32 -0
  5. package/dist/atproto-oauth-scope.js.map +1 -0
  6. package/dist/index.d.ts +9 -13
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +9 -13
  9. package/dist/index.js.map +1 -1
  10. package/dist/lib/lexicon.d.ts +2 -0
  11. package/dist/lib/lexicon.d.ts.map +1 -0
  12. package/dist/lib/lexicon.js +3 -0
  13. package/dist/lib/lexicon.js.map +1 -0
  14. package/dist/lib/mime.d.ts +1 -1
  15. package/dist/lib/mime.d.ts.map +1 -1
  16. package/dist/lib/mime.js +2 -0
  17. package/dist/lib/mime.js.map +1 -1
  18. package/dist/lib/nsid.d.ts +2 -2
  19. package/dist/lib/nsid.d.ts.map +1 -1
  20. package/dist/lib/nsid.js +4 -6
  21. package/dist/lib/nsid.js.map +1 -1
  22. package/dist/lib/parser.d.ts +29 -0
  23. package/dist/lib/parser.d.ts.map +1 -0
  24. package/dist/lib/parser.js +152 -0
  25. package/dist/lib/parser.js.map +1 -0
  26. package/dist/lib/resource-permission.d.ts +10 -0
  27. package/dist/lib/resource-permission.d.ts.map +1 -0
  28. package/dist/lib/resource-permission.js +3 -0
  29. package/dist/lib/resource-permission.js.map +1 -0
  30. package/dist/lib/syntax-lexicon.d.ts +26 -0
  31. package/dist/lib/syntax-lexicon.d.ts.map +1 -0
  32. package/dist/lib/syntax-lexicon.js +58 -0
  33. package/dist/lib/syntax-lexicon.js.map +1 -0
  34. package/dist/lib/syntax-string.d.ts +16 -0
  35. package/dist/lib/syntax-string.d.ts.map +1 -0
  36. package/dist/lib/syntax-string.js +121 -0
  37. package/dist/lib/syntax-string.js.map +1 -0
  38. package/dist/lib/syntax.d.ts +23 -0
  39. package/dist/lib/syntax.d.ts.map +1 -0
  40. package/dist/lib/syntax.js +22 -0
  41. package/dist/lib/syntax.js.map +1 -0
  42. package/dist/lib/util.d.ts +4 -1
  43. package/dist/lib/util.d.ts.map +1 -1
  44. package/dist/lib/util.js +4 -12
  45. package/dist/lib/util.js.map +1 -1
  46. package/dist/scope-permissions-transition.d.ts +15 -0
  47. package/dist/scope-permissions-transition.d.ts.map +1 -0
  48. package/dist/{permission-set-transition.js → scope-permissions-transition.js} +5 -5
  49. package/dist/scope-permissions-transition.js.map +1 -0
  50. package/dist/scope-permissions.d.ts +22 -0
  51. package/dist/scope-permissions.d.ts.map +1 -0
  52. package/dist/{permission-set.js → scope-permissions.js} +20 -16
  53. package/dist/scope-permissions.js.map +1 -0
  54. package/dist/scopes/account-permission.d.ts +35 -0
  55. package/dist/scopes/account-permission.d.ts.map +1 -0
  56. package/dist/scopes/account-permission.js +71 -0
  57. package/dist/scopes/account-permission.js.map +1 -0
  58. package/dist/scopes/blob-permission.d.ts +27 -0
  59. package/dist/scopes/blob-permission.d.ts.map +1 -0
  60. package/dist/scopes/blob-permission.js +86 -0
  61. package/dist/scopes/blob-permission.js.map +1 -0
  62. package/dist/scopes/identity-permission.d.ts +25 -0
  63. package/dist/scopes/identity-permission.d.ts.map +1 -0
  64. package/dist/scopes/identity-permission.js +53 -0
  65. package/dist/scopes/identity-permission.js.map +1 -0
  66. package/dist/scopes/include-scope.d.ts +54 -0
  67. package/dist/scopes/include-scope.d.ts.map +1 -0
  68. package/dist/scopes/include-scope.js +156 -0
  69. package/dist/scopes/include-scope.js.map +1 -0
  70. package/dist/scopes/repo-permission.d.ts +40 -0
  71. package/dist/scopes/repo-permission.d.ts.map +1 -0
  72. package/dist/scopes/repo-permission.js +101 -0
  73. package/dist/scopes/repo-permission.js.map +1 -0
  74. package/dist/scopes/rpc-permission.d.ts +38 -0
  75. package/dist/scopes/rpc-permission.d.ts.map +1 -0
  76. package/dist/scopes/rpc-permission.js +81 -0
  77. package/dist/scopes/rpc-permission.js.map +1 -0
  78. package/dist/scopes-set.d.ts +12 -1
  79. package/dist/scopes-set.d.ts.map +1 -1
  80. package/dist/scopes-set.js +49 -3
  81. package/dist/scopes-set.js.map +1 -1
  82. package/package.json +7 -3
  83. package/src/atproto-oauth-scope.ts +43 -0
  84. package/src/index.ts +10 -14
  85. package/src/lib/lexicon.ts +1 -0
  86. package/src/lib/mime.ts +2 -1
  87. package/src/lib/nsid.ts +5 -6
  88. package/src/lib/parser.ts +176 -0
  89. package/src/lib/resource-permission.ts +10 -0
  90. package/src/lib/syntax-lexicon.ts +55 -0
  91. package/src/lib/syntax-string.test.ts +130 -0
  92. package/src/lib/syntax-string.ts +132 -0
  93. package/src/lib/syntax.test.ts +43 -0
  94. package/src/lib/syntax.ts +47 -0
  95. package/src/lib/util.ts +7 -12
  96. package/src/{permission-set-transition.test.ts → scope-permissions-transition.test.ts} +33 -20
  97. package/src/{permission-set-transition.ts → scope-permissions-transition.ts} +11 -11
  98. package/src/{permission-set.test.ts → scope-permissions.test.ts} +77 -35
  99. package/src/scope-permissions.ts +91 -0
  100. package/src/{resources/account-scope.test.ts → scopes/account-permission.test.ts} +45 -33
  101. package/src/scopes/account-permission.ts +75 -0
  102. package/src/{resources/blob-scope.test.ts → scopes/blob-permission.test.ts} +31 -23
  103. package/src/scopes/blob-permission.ts +105 -0
  104. package/src/{resources/identity-scope.test.ts → scopes/identity-permission.test.ts} +13 -13
  105. package/src/scopes/identity-permission.ts +54 -0
  106. package/src/scopes/include-scope.test.ts +626 -0
  107. package/src/scopes/include-scope.ts +168 -0
  108. package/src/{resources/repo-scope.test.ts → scopes/repo-permission.test.ts} +77 -65
  109. package/src/scopes/repo-permission.ts +111 -0
  110. package/src/scopes/rpc-permission.test.ts +323 -0
  111. package/src/scopes/rpc-permission.ts +85 -0
  112. package/src/scopes-set.test.ts +5 -5
  113. package/src/scopes-set.ts +79 -5
  114. package/tsconfig.build.tsbuildinfo +1 -1
  115. package/tsconfig.tests.tsbuildinfo +1 -1
  116. package/dist/lib/did.d.ts +0 -3
  117. package/dist/lib/did.d.ts.map +0 -1
  118. package/dist/lib/did.js +0 -6
  119. package/dist/lib/did.js.map +0 -1
  120. package/dist/parser.d.ts +0 -31
  121. package/dist/parser.d.ts.map +0 -1
  122. package/dist/parser.js +0 -118
  123. package/dist/parser.js.map +0 -1
  124. package/dist/permission-set-transition.d.ts +0 -15
  125. package/dist/permission-set-transition.d.ts.map +0 -1
  126. package/dist/permission-set-transition.js.map +0 -1
  127. package/dist/permission-set.d.ts +0 -22
  128. package/dist/permission-set.d.ts.map +0 -1
  129. package/dist/permission-set.js.map +0 -1
  130. package/dist/resources/account-scope.d.ts +0 -35
  131. package/dist/resources/account-scope.d.ts.map +0 -1
  132. package/dist/resources/account-scope.js +0 -60
  133. package/dist/resources/account-scope.js.map +0 -1
  134. package/dist/resources/blob-scope.d.ts +0 -25
  135. package/dist/resources/blob-scope.d.ts.map +0 -1
  136. package/dist/resources/blob-scope.js +0 -74
  137. package/dist/resources/blob-scope.js.map +0 -1
  138. package/dist/resources/identity-scope.d.ts +0 -25
  139. package/dist/resources/identity-scope.d.ts.map +0 -1
  140. package/dist/resources/identity-scope.js +0 -46
  141. package/dist/resources/identity-scope.js.map +0 -1
  142. package/dist/resources/repo-scope.d.ts +0 -37
  143. package/dist/resources/repo-scope.d.ts.map +0 -1
  144. package/dist/resources/repo-scope.js +0 -92
  145. package/dist/resources/repo-scope.js.map +0 -1
  146. package/dist/resources/rpc-scope.d.ts +0 -31
  147. package/dist/resources/rpc-scope.d.ts.map +0 -1
  148. package/dist/resources/rpc-scope.js +0 -74
  149. package/dist/resources/rpc-scope.js.map +0 -1
  150. package/dist/syntax.d.ts +0 -76
  151. package/dist/syntax.d.ts.map +0 -1
  152. package/dist/syntax.js +0 -249
  153. package/dist/syntax.js.map +0 -1
  154. package/dist/utilities.d.ts +0 -17
  155. package/dist/utilities.d.ts.map +0 -1
  156. package/dist/utilities.js +0 -108
  157. package/dist/utilities.js.map +0 -1
  158. package/src/lib/did.ts +0 -3
  159. package/src/parser.ts +0 -150
  160. package/src/permission-set.ts +0 -78
  161. package/src/resources/account-scope.ts +0 -66
  162. package/src/resources/blob-scope.ts +0 -86
  163. package/src/resources/identity-scope.ts +0 -49
  164. package/src/resources/repo-scope.ts +0 -101
  165. package/src/resources/rpc-scope.test.ts +0 -280
  166. package/src/resources/rpc-scope.ts +0 -77
  167. package/src/syntax.test.ts +0 -203
  168. package/src/syntax.ts +0 -325
  169. package/src/utilities.ts +0 -109
package/src/syntax.ts DELETED
@@ -1,325 +0,0 @@
1
- import { minIdx, toRecord } from './lib/util'
2
-
3
- export type NeArray<T> = [T, ...T[]]
4
-
5
- /**
6
- * Non-empty readonly array
7
- */
8
- export type NeRoArray<T> = readonly [T, ...T[]]
9
-
10
- export type ScopeForResource<R extends string> =
11
- | R
12
- | `${R}:${string}`
13
- | `${R}?${string}`
14
-
15
- export type ResourceSyntaxJson<R extends string = string> = {
16
- resource: R
17
- positional?: string
18
- params?: Record<string, undefined | string | NeRoArray<string>>
19
- }
20
-
21
- /**
22
- * Allows to quickly check if a scope is for a specific resource.
23
- */
24
- export function isScopeForResource<R extends string>(
25
- scope: string,
26
- resource: R,
27
- ): scope is ScopeForResource<R> {
28
- if (!scope.startsWith(resource)) return false
29
- if (scope.length === resource.length) return true
30
-
31
- const nextCharCode = scope.charCodeAt(resource.length)
32
- return nextCharCode === 0x3a /* : */ || nextCharCode === 0x3f /* ? */
33
- }
34
-
35
- /**
36
- * Utility class to parse and interpret the resource scope syntax used in
37
- * atproto oauth scopes.
38
- * The syntax is defined as follows:
39
- * ```nbf
40
- * scope := resource [':' positional] ['?' params]
41
- * params := param ['&' param]*
42
- * param := name '=' value
43
- * ```
44
- * Where "positional" can be used as short-hand (i.e. not used in combination
45
- * with) for a specific parameter.
46
- */
47
- export class ResourceSyntax<R extends string = string> {
48
- constructor(
49
- public readonly resource: R,
50
- public readonly positional?: string,
51
- public readonly params?: Readonly<URLSearchParams>,
52
- ) {}
53
-
54
- is<T extends string>(resource: T): this is ResourceSyntax<T> {
55
- return this.resource === (resource as string)
56
- }
57
-
58
- containsParamsOtherThan(allowedParam: readonly string[]): boolean {
59
- const { params } = this
60
- if (params) {
61
- for (const key of params.keys()) {
62
- if (!allowedParam.includes(key)) return true
63
- }
64
- }
65
-
66
- return false
67
- }
68
-
69
- /**
70
- * Retrieve the value of a parameter that only allows a single value. If the
71
- * parameter is not found, it will return `undefined`. If the syntax is
72
- * incorrect (i.e. the parameter has multiple values), it will return `null`.
73
- */
74
- getSingle(name: string, isPositional = false): string | undefined | null {
75
- const { params } = this
76
- const values =
77
- params != null && params.has(name)
78
- ? (params.getAll(name) as [string, ...string[]])
79
- : undefined
80
-
81
- if (!values) {
82
- // No named parameter found, use positional parameter
83
- if (isPositional) return this.positional
84
-
85
- return undefined
86
- }
87
-
88
- if (values.length !== 1) {
89
- // Single value expected
90
- return null
91
- }
92
-
93
- if (isPositional && this.positional !== undefined) {
94
- // Positional parameter cannot be used with named parameters
95
- return null
96
- }
97
-
98
- return values[0]
99
- }
100
-
101
- /**
102
- * Retrieve the values of a parameter that allows multiple values. If the
103
- * parameter is not found, it will return `undefined`. If the syntax is
104
- * incorrect (i.e. there is bot a positional and named parameter), it will
105
- * return `null`.
106
- */
107
- getMulti(name: string, isPositional?: false): NeRoArray<string> | undefined
108
- getMulti(
109
- name: string,
110
- isPositional: boolean, // Only if this arg is true, will this method return null
111
- ): NeRoArray<string> | null | undefined
112
- getMulti(
113
- name: string,
114
- isPositional = false,
115
- ): NeRoArray<string> | null | undefined {
116
- const { params } = this
117
- const values =
118
- params != null && params.has(name)
119
- ? (params.getAll(name) as [string, ...string[]])
120
- : undefined
121
-
122
- if (!values) {
123
- // No named parameter found, use positional parameter
124
-
125
- if (isPositional && this.positional !== undefined) {
126
- return [this.positional]
127
- }
128
-
129
- return undefined
130
- }
131
-
132
- if (isPositional && this.positional !== undefined) {
133
- // @NOTE we *could* return [this.positional, ...values] here but the
134
- // atproto scope syntax forbids use of both positional and named
135
- // parameters.
136
- return null
137
- }
138
-
139
- return values
140
- }
141
-
142
- toString(): ScopeForResource<R> {
143
- return encodeScope(this.resource, this.positional, this.params)
144
- }
145
-
146
- toJSON(): ResourceSyntaxJson<R> {
147
- return {
148
- resource: this.resource,
149
- positional: this.positional,
150
- params: this.params?.size ? toRecord(this.params) : undefined,
151
- }
152
- }
153
-
154
- static fromString<R extends string>(
155
- scope: R | `${R}:${string}` | `${R}?${string}`,
156
- ): ResourceSyntax<R> {
157
- const paramIdx = scope.indexOf('?')
158
- const colonIdx = scope.indexOf(':')
159
-
160
- const resourceEnd = minIdx(paramIdx, colonIdx)
161
-
162
- const resource = (
163
- resourceEnd !== -1 ? scope.slice(0, resourceEnd) : scope
164
- ) as R
165
-
166
- const positional =
167
- colonIdx !== -1
168
- ? // There is a positional parameter, extract it
169
- paramIdx === -1
170
- ? decodeURIComponent(scope.slice(colonIdx + 1))
171
- : colonIdx < paramIdx
172
- ? decodeURIComponent(scope.slice(colonIdx + 1, paramIdx))
173
- : undefined
174
- : undefined
175
-
176
- const params =
177
- paramIdx !== -1 // There is a query string
178
- ? paramIdx === scope.length - 1
179
- ? undefined // The query string is empty
180
- : new URLSearchParams(scope.slice(paramIdx + 1))
181
- : undefined
182
-
183
- return new ResourceSyntax(resource, positional, params)
184
- }
185
- }
186
-
187
- /**
188
- * Format a scope string for a resource with parameters
189
- * as a positional parameter, if possible (if it has only one value).
190
- * @param resource - The resource name (e.g. `rpc`, `repo`, etc.)
191
- * @param inputParams - The list of parameters.
192
- * @param positionalName - The name of the parameter that should be used as
193
- * positional parameter.
194
- */
195
- export function formatScope<R extends string>(
196
- resource: R,
197
- inputParams: Iterable<
198
- [name: string, value: undefined | string | NeRoArray<string>]
199
- >,
200
- positionalName?: string,
201
- ): ScopeForResource<R> {
202
- const queryParams = new URLSearchParams()
203
-
204
- let positionalValue: string | undefined = undefined
205
-
206
- for (const [name, value] of inputParams) {
207
- if (value === undefined) continue
208
-
209
- const setPositional =
210
- name === positionalName && positionalValue === undefined
211
-
212
- if (typeof value === 'string') {
213
- if (setPositional) {
214
- positionalValue = value
215
- } else {
216
- queryParams.append(name, value)
217
- }
218
- } else {
219
- // value is "readonly [string, ...string[]]"
220
- if (value.length === 0) {
221
- // This should never happen (because "value" is supposed to be a
222
- // non-empty array). Because some scope default to "*" (allow
223
- // everything) when a parameter is not specified, we'd rather be safe
224
- // here.
225
- throw new Error(
226
- `Invalid scope: parameter "${name}" cannot be an empty array`,
227
- )
228
- } else if (setPositional && value.length === 1) {
229
- positionalValue = value[0]!
230
- } else {
231
- for (const v of value) {
232
- queryParams.append(name, v)
233
- }
234
- }
235
- }
236
- }
237
-
238
- // Fool-proof: If the input iterable defines multiple times the same
239
- // positional parameter (name), and it ended up being used as both positional
240
- // and query param, move the positional value to the query params.
241
- if (positionalValue !== undefined && queryParams.has(positionalName!)) {
242
- queryParams.append(positionalName!, positionalValue)
243
- positionalValue = undefined
244
- }
245
-
246
- return encodeScope(resource, positionalValue, queryParams)
247
- }
248
-
249
- export function encodeScope<R extends string>(
250
- resource: R,
251
- positional?: string,
252
- params?: Readonly<URLSearchParams>,
253
- ): ScopeForResource<R> {
254
- let scope: string = resource
255
-
256
- if (positional !== undefined) {
257
- scope += `:${encodeScopeComponent(positional)}`
258
- }
259
-
260
- if (params?.size) {
261
- scope += `?${normalizeScopeComponent(params.toString())}`
262
- }
263
-
264
- return scope as ScopeForResource<R>
265
- }
266
-
267
- /**
268
- * Set of characters that are allowed in scope components without encoding. This
269
- * is used to normalize scope components.
270
- */
271
- export const ALLOWED_SCOPE_CHARS = new Set(
272
- // @NOTE This list must not contain "?" or "&" as it would interfere with
273
- // query string parsing.
274
- [':', '/', '+', ',', '@', '%'],
275
- )
276
-
277
- export function encodeScopeComponent(value: string): string {
278
- return normalizeScopeComponent(encodeURIComponent(value))
279
- }
280
-
281
- const NORMALIZABLE_CHARS_MAP = new Map(
282
- Array.from(
283
- ALLOWED_SCOPE_CHARS,
284
- (c) => [encodeURIComponent(c), c] as const,
285
- ).filter(
286
- ([encoded, c]) =>
287
- // Make sure that any char added to ALLOWED_SCOPE_CHARS that is a char
288
- // that indeed needs encoding. Also, the normalizeScopeComponent only
289
- // supports three-character percent-encoded sequences.
290
- encoded !== c && encoded.length === 3 && encoded.startsWith('%'),
291
- ),
292
- )
293
-
294
- /**
295
- * Assumes a properly url-encoded string.
296
- */
297
- export function normalizeScopeComponent(value: string): string {
298
- // No need to read the last two characters since percent encoded characters
299
- // are always three characters long.
300
- let end = value.length - 2
301
-
302
- for (let i = 0; i < end; i++) {
303
- // Check if the character is a percent-encoded character
304
- if (value.charCodeAt(i) === 0x25 /* % */) {
305
- // Read the next encoded char. Current version only supports
306
- // three-character percent-encoded sequences.
307
- const encodedChar = value.slice(i, i + 3)
308
-
309
- // Check if the encoded character is in the normalization map
310
- const normalizedChar = NORMALIZABLE_CHARS_MAP.get(encodedChar)
311
- if (normalizedChar) {
312
- // Replace the encoded character with its normalized version
313
- value = `${value.slice(0, i)}${normalizedChar}${value.slice(i + encodedChar.length)}`
314
-
315
- // Adjust index to account for the length change
316
- i += normalizedChar.length - 1
317
-
318
- // Adjust end index since we replaced encoded char with normalized char
319
- end -= encodedChar.length - normalizedChar.length
320
- }
321
- }
322
- }
323
-
324
- return value
325
- }
package/src/utilities.ts DELETED
@@ -1,109 +0,0 @@
1
- import { AccountScope, AccountScopeMatch } from './resources/account-scope.js'
2
- import { BlobScope, BlobScopeMatch } from './resources/blob-scope.js'
3
- import {
4
- IdentityScope,
5
- IdentityScopeMatch,
6
- } from './resources/identity-scope.js'
7
- import { RepoScope, RepoScopeMatch } from './resources/repo-scope.js'
8
- import { RpcScope, RpcScopeMatch } from './resources/rpc-scope.js'
9
- import { ResourceSyntax, isScopeForResource } from './syntax.js'
10
-
11
- export type ScopeMatchingOptionsByResource = {
12
- account: AccountScopeMatch
13
- identity: IdentityScopeMatch
14
- repo: RepoScopeMatch
15
- rpc: RpcScopeMatch
16
- blob: BlobScopeMatch
17
- }
18
-
19
- export function isValidAtprotoOauthScope(value: string) {
20
- if (value === 'atproto') return true
21
- if (value === 'transition:email') return true
22
- if (value === 'transition:generic') return true
23
- if (value === 'transition:chat.bsky') return true
24
-
25
- const syntax = ResourceSyntax.fromString(value)
26
- if (syntax.resource === 'repo') {
27
- return RepoScope.fromSyntax(syntax) != null
28
- } else if (syntax.resource === 'rpc') {
29
- return RpcScope.fromSyntax(syntax) != null
30
- } else if (syntax.resource === 'account') {
31
- return AccountScope.fromSyntax(syntax) != null
32
- } else if (syntax.resource === 'identity') {
33
- return IdentityScope.fromSyntax(syntax) != null
34
- } else if (syntax.resource === 'blob') {
35
- return BlobScope.fromSyntax(syntax) != null
36
- }
37
-
38
- return false
39
- }
40
-
41
- export function parseScope(string: string) {
42
- const syntax = ResourceSyntax.fromString(string)
43
- if (syntax.is('account')) return AccountScope.fromSyntax(syntax)
44
- if (syntax.is('identity')) return IdentityScope.fromSyntax(syntax)
45
- if (syntax.is('repo')) return RepoScope.fromSyntax(syntax)
46
- if (syntax.is('rpc')) return RpcScope.fromSyntax(syntax)
47
- if (syntax.is('blob')) return BlobScope.fromSyntax(syntax)
48
- return null
49
- }
50
-
51
- export function scopeNeededFor<R extends keyof ScopeMatchingOptionsByResource>(
52
- resource: R,
53
- options: ScopeMatchingOptionsByResource[R],
54
- ): string {
55
- switch (resource) {
56
- case 'account':
57
- return AccountScope.scopeNeededFor(options as AccountScopeMatch)
58
- case 'identity':
59
- return IdentityScope.scopeNeededFor(options as IdentityScopeMatch)
60
- case 'repo':
61
- return RepoScope.scopeNeededFor(options as RepoScopeMatch)
62
- case 'rpc':
63
- return RpcScope.scopeNeededFor(options as RpcScopeMatch)
64
- case 'blob':
65
- return BlobScope.scopeNeededFor(options as BlobScopeMatch)
66
- }
67
- }
68
-
69
- export function scopeMatches<R extends keyof ScopeMatchingOptionsByResource>(
70
- scope: string,
71
- resource: R,
72
- options: ScopeMatchingOptionsByResource[R],
73
- ): boolean {
74
- // Optimization: Do not try parsing the scope if it does not match the
75
- // resource prefix.
76
- if (!isScopeForResource(scope, resource)) return false
77
-
78
- // @NOTE we might want to cache the parsed scopes though, in practice, a
79
- // single scope is unlikely to be parsed multiple times during a single
80
- // request.
81
- if (resource === 'rpc') {
82
- const rpcScope = RpcScope.fromString(scope)
83
- if (rpcScope?.matches(options as RpcScopeMatch)) {
84
- return true
85
- }
86
- } else if (resource === 'account') {
87
- const accountScope = AccountScope.fromString(scope)
88
- if (accountScope?.matches(options as AccountScopeMatch)) {
89
- return true
90
- }
91
- } else if (resource === 'identity') {
92
- const identityScope = IdentityScope.fromString(scope)
93
- if (identityScope?.matches(options as IdentityScopeMatch)) {
94
- return true
95
- }
96
- } else if (resource === 'repo') {
97
- const repoScope = RepoScope.fromString(scope)
98
- if (repoScope?.matches(options as RepoScopeMatch)) {
99
- return true
100
- }
101
- } else if (resource === 'blob') {
102
- const blobScope = BlobScope.fromString(scope)
103
- if (blobScope?.matches(options as BlobScopeMatch)) {
104
- return true
105
- }
106
- }
107
-
108
- return false
109
- }