@atcute/oauth-types 0.1.0 → 1.0.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 (156) hide show
  1. package/README.md +6 -5
  2. package/dist/build-client-metadata.d.ts +18 -160
  3. package/dist/build-client-metadata.d.ts.map +1 -1
  4. package/dist/build-client-metadata.js +73 -3
  5. package/dist/build-client-metadata.js.map +1 -1
  6. package/dist/index.d.ts +31 -30
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +2 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/schemas/atcute-client-shared.d.ts +8 -0
  11. package/dist/schemas/atcute-client-shared.d.ts.map +1 -0
  12. package/dist/schemas/atcute-client-shared.js +15 -0
  13. package/dist/schemas/atcute-client-shared.js.map +1 -0
  14. package/dist/schemas/atcute-confidential-client-metadata.d.ts +228 -4
  15. package/dist/schemas/atcute-confidential-client-metadata.d.ts.map +1 -1
  16. package/dist/schemas/atcute-confidential-client-metadata.js +48 -88
  17. package/dist/schemas/atcute-confidential-client-metadata.js.map +1 -1
  18. package/dist/schemas/atcute-public-client-metadata.d.ts +95 -0
  19. package/dist/schemas/atcute-public-client-metadata.d.ts.map +1 -0
  20. package/dist/schemas/atcute-public-client-metadata.js +74 -0
  21. package/dist/schemas/atcute-public-client-metadata.js.map +1 -0
  22. package/dist/schemas/atproto-authorization-server-metadata.d.ts +786 -4
  23. package/dist/schemas/atproto-authorization-server-metadata.d.ts.map +1 -1
  24. package/dist/schemas/atproto-authorization-server-metadata.js +2 -18
  25. package/dist/schemas/atproto-authorization-server-metadata.js.map +1 -1
  26. package/dist/schemas/atproto-oauth-scope.d.ts +3 -3
  27. package/dist/schemas/atproto-oauth-scope.d.ts.map +1 -1
  28. package/dist/schemas/atproto-oauth-scope.js +2 -2
  29. package/dist/schemas/atproto-oauth-scope.js.map +1 -1
  30. package/dist/schemas/atproto-oauth-token-response.d.ts +17 -17
  31. package/dist/schemas/atproto-oauth-token-response.d.ts.map +1 -1
  32. package/dist/schemas/atproto-oauth-token-response.js +6 -6
  33. package/dist/schemas/atproto-oauth-token-response.js.map +1 -1
  34. package/dist/schemas/atproto-protected-resource-metadata.d.ts +100 -4
  35. package/dist/schemas/atproto-protected-resource-metadata.d.ts.map +1 -1
  36. package/dist/schemas/atproto-protected-resource-metadata.js +2 -11
  37. package/dist/schemas/atproto-protected-resource-metadata.js.map +1 -1
  38. package/dist/schemas/jwk.d.ts +4289 -42
  39. package/dist/schemas/jwk.d.ts.map +1 -1
  40. package/dist/schemas/jwk.js +58 -91
  41. package/dist/schemas/jwk.js.map +1 -1
  42. package/dist/schemas/jwks.d.ts +87 -42
  43. package/dist/schemas/jwks.d.ts.map +1 -1
  44. package/dist/schemas/jwks.js +13 -29
  45. package/dist/schemas/jwks.js.map +1 -1
  46. package/dist/schemas/oauth-authorization-details.d.ts +18 -18
  47. package/dist/schemas/oauth-authorization-details.d.ts.map +1 -1
  48. package/dist/schemas/oauth-authorization-details.js +7 -7
  49. package/dist/schemas/oauth-authorization-details.js.map +1 -1
  50. package/dist/schemas/oauth-authorization-server-metadata.d.ts +462 -48
  51. package/dist/schemas/oauth-authorization-server-metadata.d.ts.map +1 -1
  52. package/dist/schemas/oauth-authorization-server-metadata.js +46 -65
  53. package/dist/schemas/oauth-authorization-server-metadata.js.map +1 -1
  54. package/dist/schemas/oauth-client-id-discoverable.d.ts +2 -2
  55. package/dist/schemas/oauth-client-id-discoverable.d.ts.map +1 -1
  56. package/dist/schemas/oauth-client-id-discoverable.js +20 -22
  57. package/dist/schemas/oauth-client-id-discoverable.js.map +1 -1
  58. package/dist/schemas/oauth-client-id.d.ts +3 -3
  59. package/dist/schemas/oauth-client-id.d.ts.map +1 -1
  60. package/dist/schemas/oauth-client-id.js +2 -2
  61. package/dist/schemas/oauth-client-id.js.map +1 -1
  62. package/dist/schemas/oauth-client-metadata.d.ts +73 -51
  63. package/dist/schemas/oauth-client-metadata.d.ts.map +1 -1
  64. package/dist/schemas/oauth-client-metadata.js +33 -40
  65. package/dist/schemas/oauth-client-metadata.js.map +1 -1
  66. package/dist/schemas/oauth-code-challenge-method.d.ts +3 -3
  67. package/dist/schemas/oauth-code-challenge-method.d.ts.map +1 -1
  68. package/dist/schemas/oauth-code-challenge-method.js +2 -2
  69. package/dist/schemas/oauth-code-challenge-method.js.map +1 -1
  70. package/dist/schemas/oauth-endpoint-auth-method.d.ts +3 -3
  71. package/dist/schemas/oauth-endpoint-auth-method.d.ts.map +1 -1
  72. package/dist/schemas/oauth-endpoint-auth-method.js +10 -2
  73. package/dist/schemas/oauth-endpoint-auth-method.js.map +1 -1
  74. package/dist/schemas/oauth-grant-type.d.ts +3 -3
  75. package/dist/schemas/oauth-grant-type.d.ts.map +1 -1
  76. package/dist/schemas/oauth-grant-type.js +10 -3
  77. package/dist/schemas/oauth-grant-type.js.map +1 -1
  78. package/dist/schemas/oauth-issuer-identifier.d.ts +3 -3
  79. package/dist/schemas/oauth-issuer-identifier.d.ts.map +1 -1
  80. package/dist/schemas/oauth-issuer-identifier.js +16 -9
  81. package/dist/schemas/oauth-issuer-identifier.js.map +1 -1
  82. package/dist/schemas/oauth-par-response.d.ts +5 -5
  83. package/dist/schemas/oauth-par-response.d.ts.map +1 -1
  84. package/dist/schemas/oauth-par-response.js +3 -3
  85. package/dist/schemas/oauth-par-response.js.map +1 -1
  86. package/dist/schemas/oauth-prompt.d.ts +3 -3
  87. package/dist/schemas/oauth-prompt.d.ts.map +1 -1
  88. package/dist/schemas/oauth-prompt.js +2 -2
  89. package/dist/schemas/oauth-prompt.js.map +1 -1
  90. package/dist/schemas/oauth-protected-resource-metadata.d.ts +88 -16
  91. package/dist/schemas/oauth-protected-resource-metadata.d.ts.map +1 -1
  92. package/dist/schemas/oauth-protected-resource-metadata.js +14 -26
  93. package/dist/schemas/oauth-protected-resource-metadata.js.map +1 -1
  94. package/dist/schemas/oauth-redirect-uri.d.ts +5 -5
  95. package/dist/schemas/oauth-redirect-uri.d.ts.map +1 -1
  96. package/dist/schemas/oauth-redirect-uri.js +3 -16
  97. package/dist/schemas/oauth-redirect-uri.js.map +1 -1
  98. package/dist/schemas/oauth-response-mode.d.ts +3 -3
  99. package/dist/schemas/oauth-response-mode.d.ts.map +1 -1
  100. package/dist/schemas/oauth-response-mode.js +2 -2
  101. package/dist/schemas/oauth-response-mode.js.map +1 -1
  102. package/dist/schemas/oauth-response-type.d.ts +3 -3
  103. package/dist/schemas/oauth-response-type.d.ts.map +1 -1
  104. package/dist/schemas/oauth-response-type.js +13 -7
  105. package/dist/schemas/oauth-response-type.js.map +1 -1
  106. package/dist/schemas/oauth-scope.d.ts +3 -3
  107. package/dist/schemas/oauth-scope.d.ts.map +1 -1
  108. package/dist/schemas/oauth-scope.js +2 -2
  109. package/dist/schemas/oauth-scope.js.map +1 -1
  110. package/dist/schemas/oauth-token-response.d.ts +17 -17
  111. package/dist/schemas/oauth-token-response.d.ts.map +1 -1
  112. package/dist/schemas/oauth-token-response.js +7 -7
  113. package/dist/schemas/oauth-token-response.js.map +1 -1
  114. package/dist/schemas/oauth-token-type.d.ts +3 -3
  115. package/dist/schemas/oauth-token-type.d.ts.map +1 -1
  116. package/dist/schemas/oauth-token-type.js +8 -7
  117. package/dist/schemas/oauth-token-type.js.map +1 -1
  118. package/dist/schemas/uri.d.ts +7 -7
  119. package/dist/schemas/uri.d.ts.map +1 -1
  120. package/dist/schemas/uri.js +44 -44
  121. package/dist/schemas/uri.js.map +1 -1
  122. package/dist/schemas/utils.d.ts.map +1 -1
  123. package/dist/schemas/utils.js.map +1 -1
  124. package/dist/scope.d.ts.map +1 -1
  125. package/dist/scope.js.map +1 -1
  126. package/lib/build-client-metadata.ts +92 -6
  127. package/lib/index.ts +38 -30
  128. package/lib/schemas/atcute-client-shared.ts +25 -0
  129. package/lib/schemas/atcute-confidential-client-metadata.ts +81 -111
  130. package/lib/schemas/atcute-public-client-metadata.ts +101 -0
  131. package/lib/schemas/atproto-authorization-server-metadata.ts +22 -23
  132. package/lib/schemas/atproto-oauth-scope.ts +8 -5
  133. package/lib/schemas/atproto-oauth-token-response.ts +10 -9
  134. package/lib/schemas/atproto-protected-resource-metadata.ts +15 -15
  135. package/lib/schemas/jwk.ts +104 -120
  136. package/lib/schemas/jwks.ts +28 -40
  137. package/lib/schemas/oauth-authorization-details.ts +10 -10
  138. package/lib/schemas/oauth-authorization-server-metadata.ts +72 -74
  139. package/lib/schemas/oauth-client-id-discoverable.ts +43 -48
  140. package/lib/schemas/oauth-client-id.ts +3 -3
  141. package/lib/schemas/oauth-client-metadata.ts +45 -49
  142. package/lib/schemas/oauth-code-challenge-method.ts +3 -3
  143. package/lib/schemas/oauth-endpoint-auth-method.ts +11 -11
  144. package/lib/schemas/oauth-grant-type.ts +11 -11
  145. package/lib/schemas/oauth-issuer-identifier.ts +35 -27
  146. package/lib/schemas/oauth-par-response.ts +4 -4
  147. package/lib/schemas/oauth-prompt.ts +3 -9
  148. package/lib/schemas/oauth-protected-resource-metadata.ts +26 -35
  149. package/lib/schemas/oauth-redirect-uri.ts +15 -23
  150. package/lib/schemas/oauth-response-mode.ts +3 -7
  151. package/lib/schemas/oauth-response-type.ts +12 -12
  152. package/lib/schemas/oauth-scope.ts +3 -3
  153. package/lib/schemas/oauth-token-response.ts +10 -10
  154. package/lib/schemas/oauth-token-type.ts +16 -12
  155. package/lib/schemas/uri.ts +89 -76
  156. package/package.json +9 -8
@@ -1,16 +1,16 @@
1
- import * as v from '@badrap/valita';
1
+ import * as v from 'valibot';
2
2
 
3
- import { oauthIssuerIdentifierSchema } from './oauth-issuer-identifier.js';
4
- import { webUriSchema } from './uri.js';
3
+ import { oauthIssuerIdentifierSchema } from './oauth-issuer-identifier.ts';
4
+ import { webUriSchema } from './uri.ts';
5
5
 
6
- export const oauthBearerMethodSchema = v.union(v.literal('header'), v.literal('body'), v.literal('query'));
6
+ export const oauthBearerMethodSchema = v.picklist(['header', 'body', 'query']);
7
7
 
8
- export type OAuthBearerMethod = v.Infer<typeof oauthBearerMethodSchema>;
8
+ export type OAuthBearerMethod = v.InferOutput<typeof oauthBearerMethodSchema>;
9
9
 
10
10
  /**
11
11
  * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-3.2}
12
12
  */
13
- export const oauthProtectedResourceMetadataSchema = v.object({
13
+ export const oauthProtectedResourceMetadataSchema = v.looseObject({
14
14
  /**
15
15
  * REQUIRED. the protected resource's resource identifier, which is a URL that
16
16
  * uses the https scheme and has no query or fragment components.
@@ -22,68 +22,59 @@ export const oauthProtectedResourceMetadataSchema = v.object({
22
22
  * identifiers, as defined in RFC8414, for authorization servers that can be
23
23
  * used with this protected resource.
24
24
  */
25
- authorization_servers: v.array(oauthIssuerIdentifierSchema).optional(),
25
+ authorization_servers: v.optional(v.array(oauthIssuerIdentifierSchema)),
26
26
 
27
27
  /**
28
28
  * OPTIONAL. URL of the protected resource's JWK Set document.
29
29
  */
30
- jwks_uri: webUriSchema.optional(),
30
+ jwks_uri: v.optional(webUriSchema),
31
31
 
32
32
  /**
33
33
  * RECOMMENDED. JSON array containing a list of the OAuth 2.0 scope values that
34
34
  * are used in authorization requests to request access to this protected resource.
35
35
  */
36
- scopes_supported: v.array(v.string()).optional(),
36
+ scopes_supported: v.optional(v.array(v.string())),
37
37
 
38
38
  /**
39
39
  * OPTIONAL. JSON array containing a list of the supported methods of sending
40
40
  * an OAuth 2.0 Bearer Token to the protected resource.
41
41
  */
42
- bearer_methods_supported: v.array(oauthBearerMethodSchema).optional(),
42
+ bearer_methods_supported: v.optional(v.array(oauthBearerMethodSchema)),
43
43
 
44
44
  /**
45
45
  * OPTIONAL. JSON array containing a list of the JWS signing algorithms
46
46
  * supported by the protected resource for signing resource responses.
47
47
  */
48
- resource_signing_alg_values_supported: v.array(v.string()).optional(),
48
+ resource_signing_alg_values_supported: v.optional(v.array(v.string())),
49
49
 
50
50
  /**
51
51
  * OPTIONAL. URL of a page containing human-readable information that
52
52
  * developers might want or need to know when using the protected resource.
53
53
  */
54
- resource_documentation: webUriSchema.optional(),
54
+ resource_documentation: v.optional(webUriSchema),
55
55
 
56
56
  /**
57
57
  * OPTIONAL. URL that the protected resource provides to read about the
58
58
  * protected resource's requirements on how the client can use the data.
59
59
  */
60
- resource_policy_uri: webUriSchema.optional(),
60
+ resource_policy_uri: v.optional(webUriSchema),
61
61
 
62
62
  /**
63
63
  * OPTIONAL. URL that the protected resource provides to read about the
64
64
  * protected resource's terms of service.
65
65
  */
66
- resource_tos_uri: webUriSchema.optional(),
66
+ resource_tos_uri: v.optional(webUriSchema),
67
67
  });
68
68
 
69
- export const oauthProtectedResourceMetadataValidator = oauthProtectedResourceMetadataSchema.chain((data) => {
70
- const url = new URL(data.resource);
71
-
72
- if (url.search) {
73
- return v.err({
74
- message: `resource URL must not contain query parameters`,
75
- path: ['resource'],
76
- });
77
- }
78
-
79
- if (url.hash) {
80
- return v.err({
81
- message: `resource URL must not contain a fragment`,
82
- path: ['resource'],
83
- });
84
- }
85
-
86
- return v.ok(data);
87
- });
88
-
89
- export type OAuthProtectedResourceMetadata = v.Infer<typeof oauthProtectedResourceMetadataSchema>;
69
+ export const oauthProtectedResourceMetadataValidator = v.pipe(
70
+ oauthProtectedResourceMetadataSchema,
71
+ v.forward(
72
+ v.check((data) => {
73
+ const url = new URL(data.resource);
74
+ return !url.search && !url.hash;
75
+ }, `resource URL must not contain query parameters or a fragment`),
76
+ ['resource'],
77
+ ),
78
+ );
79
+
80
+ export type OAuthProtectedResourceMetadata = v.InferOutput<typeof oauthProtectedResourceMetadataSchema>;
@@ -1,6 +1,6 @@
1
- import * as v from '@badrap/valita';
1
+ import * as v from 'valibot';
2
2
 
3
- import { httpsUriSchema, loopbackUriSchema, privateUseUriSchema } from './uri.js';
3
+ import { httpsUriSchema, loopbackUriSchema, privateUseUriSchema } from './uri.ts';
4
4
 
5
5
  /**
6
6
  * this is a loopback URI with the additional restriction that the hostname
@@ -16,27 +16,19 @@ import { httpsUriSchema, loopbackUriSchema, privateUseUriSchema } from './uri.js
16
16
  * > than the loopback interface. It is also less susceptible to client-side
17
17
  * > firewalls and misconfigured host name resolution on the user's device.
18
18
  */
19
- export const loopbackRedirectUriSchema = loopbackUriSchema.chain((input) => {
20
- if (input.startsWith('http://localhost')) {
21
- return v.err(
22
- `use of "localhost" hostname is not allowed (RFC 8252), use a loopback IP such as "127.0.0.1" instead`,
23
- );
24
- }
25
- return v.ok(input);
26
- });
19
+ export const loopbackRedirectUriSchema = v.pipe(
20
+ loopbackUriSchema,
21
+ v.check(
22
+ (input) => !input.startsWith('http://localhost'),
23
+ `use of "localhost" hostname is not allowed (RFC 8252), use a loopback IP such as "127.0.0.1" instead`,
24
+ ),
25
+ );
27
26
 
28
- export type LoopbackRedirectUri = v.Infer<typeof loopbackRedirectUriSchema>;
27
+ export type LoopbackRedirectUri = v.InferOutput<typeof loopbackRedirectUriSchema>;
29
28
 
30
- export const oauthRedirectUriSchema = v.string().chain((input, options) => {
31
- if (input.startsWith('http://')) {
32
- return loopbackRedirectUriSchema.try(input, options);
33
- }
29
+ export const oauthRedirectUriSchema = v.union(
30
+ [loopbackRedirectUriSchema, httpsUriSchema, privateUseUriSchema],
31
+ `url must use http: loopback, https:, or a private-use scheme`,
32
+ );
34
33
 
35
- if (input.startsWith('https://')) {
36
- return httpsUriSchema.try(input, options);
37
- }
38
-
39
- return privateUseUriSchema.try(input, options);
40
- });
41
-
42
- export type OAuthRedirectUri = v.Infer<typeof oauthRedirectUriSchema>;
34
+ export type OAuthRedirectUri = v.InferOutput<typeof oauthRedirectUriSchema>;
@@ -1,9 +1,5 @@
1
- import * as v from '@badrap/valita';
1
+ import * as v from 'valibot';
2
2
 
3
- export const oauthResponseModeSchema = v.union(
4
- v.literal('query'),
5
- v.literal('fragment'),
6
- v.literal('form_post'),
7
- );
3
+ export const oauthResponseModeSchema = v.picklist(['query', 'fragment', 'form_post']);
8
4
 
9
- export type OAuthResponseMode = v.Infer<typeof oauthResponseModeSchema>;
5
+ export type OAuthResponseMode = v.InferOutput<typeof oauthResponseModeSchema>;
@@ -1,17 +1,17 @@
1
- import * as v from '@badrap/valita';
1
+ import * as v from 'valibot';
2
2
 
3
- export const oauthResponseTypeSchema = v.union(
3
+ export const oauthResponseTypeSchema = v.picklist([
4
4
  // OAuth2 (https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-10#section-4.1.1)
5
- v.literal('code'), // Authorization Code Grant
6
- v.literal('token'), // Implicit Grant
5
+ 'code', // Authorization Code Grant
6
+ 'token', // Implicit Grant
7
7
 
8
8
  // OIDC (https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html)
9
- v.literal('none'),
10
- v.literal('code id_token token'),
11
- v.literal('code id_token'),
12
- v.literal('code token'),
13
- v.literal('id_token token'),
14
- v.literal('id_token'),
15
- );
9
+ 'none',
10
+ 'code id_token token',
11
+ 'code id_token',
12
+ 'code token',
13
+ 'id_token token',
14
+ 'id_token',
15
+ ]);
16
16
 
17
- export type OAuthResponseType = v.Infer<typeof oauthResponseTypeSchema>;
17
+ export type OAuthResponseType = v.InferOutput<typeof oauthResponseTypeSchema>;
@@ -1,4 +1,4 @@
1
- import * as v from '@badrap/valita';
1
+ import * as v from 'valibot';
2
2
 
3
3
  // scope = scope-token *( SP scope-token )
4
4
  // scope-token = 1*( %x21 / %x23-5B / %x5D-7E )
@@ -13,6 +13,6 @@ export const isOAuthScope = (input: string): boolean => OAUTH_SCOPE_REGEXP.test(
13
13
  *
14
14
  * @see {@link https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-11#section-1.4.1}
15
15
  */
16
- export const oauthScopeSchema = v.string().assert(isOAuthScope, `invalid OAuth scope`);
16
+ export const oauthScopeSchema = v.pipe(v.string(), v.check(isOAuthScope, `invalid OAuth scope`));
17
17
 
18
- export type OAuthScope = v.Infer<typeof oauthScopeSchema>;
18
+ export type OAuthScope = v.InferOutput<typeof oauthScopeSchema>;
@@ -1,22 +1,22 @@
1
- import * as v from '@badrap/valita';
1
+ import * as v from 'valibot';
2
2
 
3
- import { oauthAuthorizationDetailsSchema } from './oauth-authorization-details.js';
4
- import { oauthTokenTypeSchema } from './oauth-token-type.js';
3
+ import { oauthAuthorizationDetailsSchema } from './oauth-authorization-details.ts';
4
+ import { oauthTokenTypeSchema } from './oauth-token-type.ts';
5
5
 
6
6
  /**
7
7
  * @see {@link https://www.rfc-editor.org/rfc/rfc6749.html#section-5.1 | RFC 6749 (OAuth2), Section 5.1}
8
8
  */
9
- export const oauthTokenResponseSchema = v.object({
9
+ export const oauthTokenResponseSchema = v.looseObject({
10
10
  // https://www.rfc-editor.org/rfc/rfc6749.html#section-5.1
11
11
  access_token: v.string(),
12
12
  token_type: oauthTokenTypeSchema,
13
- scope: v.string().optional(),
14
- refresh_token: v.string().optional(),
15
- expires_in: v.number().optional(),
13
+ scope: v.optional(v.string()),
14
+ refresh_token: v.optional(v.string()),
15
+ expires_in: v.optional(v.number()),
16
16
  // https://openid.net/specs/openid-connect-core-1_0.html#TokenResponse
17
- id_token: v.string().optional(),
17
+ id_token: v.optional(v.string()),
18
18
  // https://datatracker.ietf.org/doc/html/rfc9396#name-enriched-authorization-deta
19
- authorization_details: oauthAuthorizationDetailsSchema.optional(),
19
+ authorization_details: v.optional(oauthAuthorizationDetailsSchema),
20
20
  });
21
21
 
22
- export type OAuthTokenResponse = v.Infer<typeof oauthTokenResponseSchema>;
22
+ export type OAuthTokenResponse = v.InferOutput<typeof oauthTokenResponseSchema>;
@@ -1,15 +1,19 @@
1
- import * as v from '@badrap/valita';
1
+ import * as v from 'valibot';
2
2
 
3
3
  /** token type (case-insensitive input, normalized output) */
4
- export const oauthTokenTypeSchema = v.string().chain((input) => {
5
- const lower = input.toLowerCase();
6
- if (lower === 'dpop') {
7
- return v.ok('DPoP');
8
- }
9
- if (lower === 'bearer') {
10
- return v.ok('Bearer');
11
- }
12
- return v.err(`must be "DPoP" or "Bearer"`);
13
- });
4
+ export const oauthTokenTypeSchema = v.pipe(
5
+ v.string(),
6
+ v.rawTransform<string, 'DPoP' | 'Bearer'>(({ dataset, addIssue, NEVER }) => {
7
+ const lower = dataset.value.toLowerCase();
8
+ if (lower === 'dpop') {
9
+ return 'DPoP';
10
+ }
11
+ if (lower === 'bearer') {
12
+ return 'Bearer';
13
+ }
14
+ addIssue({ message: `must be "DPoP" or "Bearer"` });
15
+ return NEVER;
16
+ }),
17
+ );
14
18
 
15
- export type OAuthTokenType = v.Infer<typeof oauthTokenTypeSchema>;
19
+ export type OAuthTokenType = v.InferOutput<typeof oauthTokenTypeSchema>;
@@ -1,100 +1,113 @@
1
- import * as v from '@badrap/valita';
1
+ import * as v from 'valibot';
2
2
 
3
- import { isHostnameIP, isLocalHostname, isLoopbackHost } from './utils.js';
3
+ import { isHostnameIP, isLocalHostname, isLoopbackHost } from './utils.ts';
4
4
 
5
5
  /**
6
6
  * valid, but potentially dangerous URL (`data:`, `file:`, `javascript:`, etc.).
7
7
  *
8
8
  * any value that matches this schema is safe to parse using `new URL()`.
9
9
  */
10
- export const urlSchema = v.string().chain((input) => {
11
- if (input.includes(':') && URL.canParse(input)) {
12
- return v.ok(input);
13
- }
14
- return v.err(`must be a valid url`);
15
- });
10
+ export const urlSchema = v.pipe(
11
+ v.string(),
12
+ v.check((input) => input.includes(':') && URL.canParse(input), `must be a valid url`),
13
+ );
16
14
 
17
15
  /** loopback URL (http://localhost, http://127.0.0.1, http://[::1]) */
18
- export const loopbackUriSchema = urlSchema.chain((input) => {
19
- if (!input.startsWith('http://')) {
20
- return v.err(`loopback url must use http: protocol`);
21
- }
22
-
23
- const url = new URL(input);
24
- if (!isLoopbackHost(url.hostname)) {
25
- return v.err(`loopback url must use localhost, 127.0.0.1, or [::1] as hostname`);
26
- }
27
-
28
- return v.ok(input);
29
- });
16
+ export const loopbackUriSchema = v.pipe(
17
+ urlSchema,
18
+ v.rawCheck(({ dataset, addIssue }) => {
19
+ if (!dataset.typed) {
20
+ return;
21
+ }
22
+ const input = dataset.value;
23
+ if (!input.startsWith('http://')) {
24
+ addIssue({ message: `loopback url must use http: protocol` });
25
+ return;
26
+ }
27
+ if (!isLoopbackHost(new URL(input).hostname)) {
28
+ addIssue({ message: `loopback url must use localhost, 127.0.0.1, or [::1] as hostname` });
29
+ }
30
+ }),
31
+ );
30
32
 
31
33
  /** HTTPS URL with additional restrictions */
32
- export const httpsUriSchema = urlSchema.chain((input) => {
33
- if (!input.startsWith('https://')) {
34
- return v.err(`url must use https: protocol`);
35
- }
36
-
37
- const url = new URL(input);
38
-
39
- if (isLoopbackHost(url.hostname)) {
40
- return v.err(`https url must not use a loopback host`);
41
- }
42
-
43
- if (!isHostnameIP(url.hostname)) {
44
- if (!url.hostname.includes('.')) {
45
- return v.err(`domain name must contain at least two segments`);
34
+ export const httpsUriSchema = v.pipe(
35
+ urlSchema,
36
+ v.rawCheck(({ dataset, addIssue }) => {
37
+ if (!dataset.typed) {
38
+ return;
46
39
  }
47
- if (url.hostname.endsWith('.local')) {
48
- return v.err(`domain name must not end with .local`);
40
+ const input = dataset.value;
41
+ if (!input.startsWith('https://')) {
42
+ addIssue({ message: `url must use https: protocol` });
43
+ return;
49
44
  }
50
- }
51
45
 
52
- return v.ok(input);
53
- });
46
+ const url = new URL(input);
54
47
 
55
- /** web URL (either loopback http or https) */
56
- export const webUriSchema = urlSchema.chain((input, options) => {
57
- if (input.startsWith('http://')) {
58
- return loopbackUriSchema.try(input, options);
59
- }
48
+ if (isLoopbackHost(url.hostname)) {
49
+ addIssue({ message: `https url must not use a loopback host` });
50
+ return;
51
+ }
60
52
 
61
- if (input.startsWith('https://')) {
62
- return httpsUriSchema.try(input, options);
63
- }
53
+ if (!isHostnameIP(url.hostname)) {
54
+ if (!url.hostname.includes('.')) {
55
+ addIssue({ message: `domain name must contain at least two segments` });
56
+ return;
57
+ }
58
+ if (url.hostname.endsWith('.local')) {
59
+ addIssue({ message: `domain name must not end with .local` });
60
+ }
61
+ }
62
+ }),
63
+ );
64
64
 
65
- return v.err(`url must use http: or https: protocol`);
66
- });
65
+ /** web URL (either loopback http or https) */
66
+ export const webUriSchema = v.union(
67
+ [loopbackUriSchema, httpsUriSchema],
68
+ `url must use http: or https: protocol`,
69
+ );
67
70
 
68
71
  /** web URL with a non-local hostname */
69
- export const nonLocalWebUriSchema = webUriSchema.chain((input) => {
70
- const url = new URL(input);
71
- if (isLocalHostname(url.hostname)) {
72
- return v.err(`hostname is invalid`);
73
- }
74
- return v.ok(input);
75
- });
72
+ export const nonLocalWebUriSchema = v.pipe(
73
+ webUriSchema,
74
+ v.check((input) => !isLocalHostname(new URL(input).hostname), `hostname is invalid`),
75
+ );
76
76
 
77
77
  /** private-use URI scheme (e.g., com.example.app:/callback) */
78
- export const privateUseUriSchema = urlSchema.chain((input) => {
79
- const dotIdx = input.indexOf('.');
80
- const colonIdx = input.indexOf(':');
81
-
82
- if (dotIdx === -1 || colonIdx === -1 || dotIdx > colonIdx) {
83
- return v.err(`private-use uri scheme must contain a dot in the protocol`);
84
- }
85
-
86
- const url = new URL(input);
87
- const scheme = url.protocol.slice(0, -1);
88
- const domain = scheme.split('.').reverse().join('.');
78
+ export const privateUseUriSchema = v.pipe(
79
+ urlSchema,
80
+ v.rawCheck(({ dataset, addIssue }) => {
81
+ if (!dataset.typed) {
82
+ return;
83
+ }
84
+ const input = dataset.value;
89
85
 
90
- if (isLocalHostname(domain)) {
91
- return v.err(`private-use uri scheme must not be a local hostname`);
92
- }
86
+ const dotIdx = input.indexOf('.');
87
+ const colonIdx = input.indexOf(':');
88
+ if (dotIdx === -1 || colonIdx === -1 || dotIdx > colonIdx) {
89
+ addIssue({ message: `private-use uri scheme must contain a dot in the protocol` });
90
+ return;
91
+ }
93
92
 
94
- // RFC 8252: private-use URIs must use single slash after scheme
95
- if (url.href.startsWith(`${url.protocol}//`) || url.username || url.password || url.hostname || url.port) {
96
- return v.err(`private-use uri must be in the form scheme:/<path>`);
97
- }
93
+ const url = new URL(input);
94
+ const scheme = url.protocol.slice(0, -1);
95
+ // oxlint-disable-next-line unicorn/no-array-reverse -- split already clones
96
+ const domain = scheme.split('.').reverse().join('.');
97
+ if (isLocalHostname(domain)) {
98
+ addIssue({ message: `private-use uri scheme must not be a local hostname` });
99
+ return;
100
+ }
98
101
 
99
- return v.ok(input);
100
- });
102
+ // RFC 8252: private-use URIs must use single slash after scheme
103
+ if (
104
+ url.href.startsWith(`${url.protocol}//`) ||
105
+ url.username ||
106
+ url.password ||
107
+ url.hostname ||
108
+ url.port
109
+ ) {
110
+ addIssue({ message: `private-use uri must be in the form scheme:/<path>` });
111
+ }
112
+ }),
113
+ );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atcute/oauth-types",
3
- "version": "0.1.0",
3
+ "version": "1.0.0",
4
4
  "description": "OAuth types and schemas for AT Protocol",
5
5
  "license": "0BSD",
6
6
  "repository": {
@@ -11,7 +11,8 @@
11
11
  "dist/",
12
12
  "lib/",
13
13
  "!lib/**/*.bench.ts",
14
- "!lib/**/*.test.ts"
14
+ "!lib/**/*.test.ts",
15
+ "!dist/**/*.{test,bench}.*"
15
16
  ],
16
17
  "type": "module",
17
18
  "sideEffects": false,
@@ -22,16 +23,16 @@
22
23
  "access": "public"
23
24
  },
24
25
  "dependencies": {
25
- "@badrap/valita": "^0.4.6",
26
- "@atcute/identity": "^1.1.3",
27
- "@atcute/oauth-keyset": "^0.1.0",
28
- "@atcute/lexicons": "^1.2.7"
26
+ "valibot": "^1.4.0",
27
+ "@atcute/lexicons": "^2.0.0",
28
+ "@atcute/identity": "^2.0.0",
29
+ "@atcute/oauth-keyset": "^0.1.1"
29
30
  },
30
31
  "devDependencies": {
31
- "vitest": "^4.0.16"
32
+ "vitest": "^4.1.5"
32
33
  },
33
34
  "scripts": {
34
- "build": "tsgo --project tsconfig.build.json",
35
+ "build": "tsgo",
35
36
  "test": "vitest",
36
37
  "prepublish": "rm -rf dist; pnpm run build"
37
38
  }