@atproto/oauth-provider 0.16.5 → 0.17.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 (321) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/access-token/access-token-mode.js +2 -5
  3. package/dist/access-token/access-token-mode.js.map +1 -1
  4. package/dist/account/account-manager.js +25 -33
  5. package/dist/account/account-manager.js.map +1 -1
  6. package/dist/account/account-store.js +11 -32
  7. package/dist/account/account-store.js.map +1 -1
  8. package/dist/account/sign-in-data.js +9 -12
  9. package/dist/account/sign-in-data.js.map +1 -1
  10. package/dist/account/sign-up-input.js +14 -17
  11. package/dist/account/sign-up-input.js.map +1 -1
  12. package/dist/client/client-auth.js +1 -2
  13. package/dist/client/client-data.js +1 -2
  14. package/dist/client/client-id.js +2 -5
  15. package/dist/client/client-id.js.map +1 -1
  16. package/dist/client/client-info.js +1 -2
  17. package/dist/client/client-manager.js +86 -97
  18. package/dist/client/client-manager.js.map +1 -1
  19. package/dist/client/client-store.js +7 -26
  20. package/dist/client/client-store.js.map +1 -1
  21. package/dist/client/client-utils.js +10 -14
  22. package/dist/client/client-utils.js.map +1 -1
  23. package/dist/client/client.js +43 -53
  24. package/dist/client/client.js.map +1 -1
  25. package/dist/constants.js +28 -31
  26. package/dist/constants.js.map +1 -1
  27. package/dist/customization/branding.js +8 -11
  28. package/dist/customization/branding.js.map +1 -1
  29. package/dist/customization/build-customization-css.js +8 -11
  30. package/dist/customization/build-customization-css.js.map +1 -1
  31. package/dist/customization/build-customization-data.js +1 -4
  32. package/dist/customization/build-customization-data.js.map +1 -1
  33. package/dist/customization/colors.js +11 -14
  34. package/dist/customization/colors.js.map +1 -1
  35. package/dist/customization/customization.js +8 -11
  36. package/dist/customization/customization.js.map +1 -1
  37. package/dist/customization/links.js +7 -10
  38. package/dist/customization/links.js.map +1 -1
  39. package/dist/device/device-data.js +7 -10
  40. package/dist/device/device-data.js.map +1 -1
  41. package/dist/device/device-id.js +11 -16
  42. package/dist/device/device-id.js.map +1 -1
  43. package/dist/device/device-manager.js +32 -38
  44. package/dist/device/device-manager.js.map +1 -1
  45. package/dist/device/device-store.js +7 -25
  46. package/dist/device/device-store.js.map +1 -1
  47. package/dist/device/session-id.js +9 -13
  48. package/dist/device/session-id.js.map +1 -1
  49. package/dist/dpop/dpop-manager.d.ts +3 -3
  50. package/dist/dpop/dpop-manager.js +38 -43
  51. package/dist/dpop/dpop-manager.js.map +1 -1
  52. package/dist/dpop/dpop-nonce.d.ts +2 -2
  53. package/dist/dpop/dpop-nonce.d.ts.map +1 -1
  54. package/dist/dpop/dpop-nonce.js +14 -18
  55. package/dist/dpop/dpop-nonce.js.map +1 -1
  56. package/dist/dpop/dpop-proof.js +1 -2
  57. package/dist/errors/access-denied-error.js +2 -6
  58. package/dist/errors/access-denied-error.js.map +1 -1
  59. package/dist/errors/account-selection-required-error.js +2 -6
  60. package/dist/errors/account-selection-required-error.js.map +1 -1
  61. package/dist/errors/authorization-error.js +7 -12
  62. package/dist/errors/authorization-error.js.map +1 -1
  63. package/dist/errors/consent-required-error.js +2 -6
  64. package/dist/errors/consent-required-error.js.map +1 -1
  65. package/dist/errors/error-parser.js +14 -18
  66. package/dist/errors/error-parser.js.map +1 -1
  67. package/dist/errors/handle-unavailable-error.js +2 -7
  68. package/dist/errors/handle-unavailable-error.js.map +1 -1
  69. package/dist/errors/invalid-authorization-details-error.js +2 -6
  70. package/dist/errors/invalid-authorization-details-error.js.map +1 -1
  71. package/dist/errors/invalid-client-error.js +2 -6
  72. package/dist/errors/invalid-client-error.js.map +1 -1
  73. package/dist/errors/invalid-client-id-error.js +2 -6
  74. package/dist/errors/invalid-client-id-error.js.map +1 -1
  75. package/dist/errors/invalid-client-metadata-error.js +7 -11
  76. package/dist/errors/invalid-client-metadata-error.js.map +1 -1
  77. package/dist/errors/invalid-credentials-error.js +2 -7
  78. package/dist/errors/invalid-credentials-error.js.map +1 -1
  79. package/dist/errors/invalid-dpop-key-binding-error.js +2 -6
  80. package/dist/errors/invalid-dpop-key-binding-error.js.map +1 -1
  81. package/dist/errors/invalid-dpop-proof-error.js +2 -6
  82. package/dist/errors/invalid-dpop-proof-error.js.map +1 -1
  83. package/dist/errors/invalid-grant-error.js +2 -6
  84. package/dist/errors/invalid-grant-error.js.map +1 -1
  85. package/dist/errors/invalid-invite-code-error.d.ts +1 -1
  86. package/dist/errors/invalid-invite-code-error.d.ts.map +1 -1
  87. package/dist/errors/invalid-invite-code-error.js +2 -6
  88. package/dist/errors/invalid-invite-code-error.js.map +1 -1
  89. package/dist/errors/invalid-redirect-uri-error.js +2 -6
  90. package/dist/errors/invalid-redirect-uri-error.js.map +1 -1
  91. package/dist/errors/invalid-request-error.js +3 -7
  92. package/dist/errors/invalid-request-error.js.map +1 -1
  93. package/dist/errors/invalid-scope-error.js +2 -6
  94. package/dist/errors/invalid-scope-error.js.map +1 -1
  95. package/dist/errors/invalid-token-error.js +10 -15
  96. package/dist/errors/invalid-token-error.js.map +1 -1
  97. package/dist/errors/login-required-error.js +2 -6
  98. package/dist/errors/login-required-error.js.map +1 -1
  99. package/dist/errors/oauth-error.js +1 -9
  100. package/dist/errors/oauth-error.js.map +1 -1
  101. package/dist/errors/second-authentication-factor-required-error.js +2 -8
  102. package/dist/errors/second-authentication-factor-required-error.js.map +1 -1
  103. package/dist/errors/unauthorized-client-error.js +2 -6
  104. package/dist/errors/unauthorized-client-error.js.map +1 -1
  105. package/dist/errors/use-dpop-nonce-error.js +4 -8
  106. package/dist/errors/use-dpop-nonce-error.js.map +1 -1
  107. package/dist/errors/www-authenticate-error.js +4 -9
  108. package/dist/errors/www-authenticate-error.js.map +1 -1
  109. package/dist/index.js +14 -30
  110. package/dist/index.js.map +1 -1
  111. package/dist/lexicon/lexicon-data.js +1 -2
  112. package/dist/lexicon/lexicon-getter.js +6 -10
  113. package/dist/lexicon/lexicon-getter.js.map +1 -1
  114. package/dist/lexicon/lexicon-manager.js +10 -30
  115. package/dist/lexicon/lexicon-manager.js.map +1 -1
  116. package/dist/lexicon/lexicon-store.js +5 -10
  117. package/dist/lexicon/lexicon-store.js.map +1 -1
  118. package/dist/lib/csp/index.js +3 -8
  119. package/dist/lib/csp/index.js.map +1 -1
  120. package/dist/lib/hcaptcha.js +33 -43
  121. package/dist/lib/hcaptcha.js.map +1 -1
  122. package/dist/lib/html/build-document.js +19 -24
  123. package/dist/lib/html/build-document.js.map +1 -1
  124. package/dist/lib/html/escapers.js +10 -16
  125. package/dist/lib/html/escapers.js.map +1 -1
  126. package/dist/lib/html/html.js +1 -5
  127. package/dist/lib/html/html.js.map +1 -1
  128. package/dist/lib/html/hydration-data.js +6 -10
  129. package/dist/lib/html/hydration-data.js.map +1 -1
  130. package/dist/lib/html/index.js +3 -19
  131. package/dist/lib/html/index.js.map +1 -1
  132. package/dist/lib/html/tags.js +14 -23
  133. package/dist/lib/html/tags.js.map +1 -1
  134. package/dist/lib/html/util.js +1 -4
  135. package/dist/lib/html/util.js.map +1 -1
  136. package/dist/lib/http/accept.d.ts.map +1 -1
  137. package/dist/lib/http/accept.js +8 -8
  138. package/dist/lib/http/accept.js.map +1 -1
  139. package/dist/lib/http/context.js +1 -4
  140. package/dist/lib/http/context.js.map +1 -1
  141. package/dist/lib/http/headers.js +1 -4
  142. package/dist/lib/http/headers.js.map +1 -1
  143. package/dist/lib/http/index.js +10 -26
  144. package/dist/lib/http/index.js.map +1 -1
  145. package/dist/lib/http/method.js +1 -4
  146. package/dist/lib/http/method.js.map +1 -1
  147. package/dist/lib/http/middleware.js +11 -17
  148. package/dist/lib/http/middleware.js.map +1 -1
  149. package/dist/lib/http/parser.js +13 -20
  150. package/dist/lib/http/parser.js.map +1 -1
  151. package/dist/lib/http/path.js +1 -4
  152. package/dist/lib/http/path.js.map +1 -1
  153. package/dist/lib/http/request.d.ts.map +1 -1
  154. package/dist/lib/http/request.js +32 -47
  155. package/dist/lib/http/request.js.map +1 -1
  156. package/dist/lib/http/response.js +14 -27
  157. package/dist/lib/http/response.js.map +1 -1
  158. package/dist/lib/http/route.js +9 -12
  159. package/dist/lib/http/route.js.map +1 -1
  160. package/dist/lib/http/router.js +8 -13
  161. package/dist/lib/http/router.js.map +1 -1
  162. package/dist/lib/http/security-headers.js +10 -15
  163. package/dist/lib/http/security-headers.js.map +1 -1
  164. package/dist/lib/http/stream.js +12 -20
  165. package/dist/lib/http/stream.js.map +1 -1
  166. package/dist/lib/http/types.js +1 -2
  167. package/dist/lib/http/url.js +1 -4
  168. package/dist/lib/http/url.js.map +1 -1
  169. package/dist/lib/nsid.js +4 -8
  170. package/dist/lib/nsid.js.map +1 -1
  171. package/dist/lib/redis.js +4 -7
  172. package/dist/lib/redis.js.map +1 -1
  173. package/dist/lib/util/authorization-header.js +11 -15
  174. package/dist/lib/util/authorization-header.js.map +1 -1
  175. package/dist/lib/util/cast.js +3 -8
  176. package/dist/lib/util/cast.js.map +1 -1
  177. package/dist/lib/util/color.js +23 -32
  178. package/dist/lib/util/color.js.map +1 -1
  179. package/dist/lib/util/crypto.js +5 -10
  180. package/dist/lib/util/crypto.js.map +1 -1
  181. package/dist/lib/util/date.js +2 -6
  182. package/dist/lib/util/date.js.map +1 -1
  183. package/dist/lib/util/error.js +5 -8
  184. package/dist/lib/util/error.js.map +1 -1
  185. package/dist/lib/util/function.js +3 -8
  186. package/dist/lib/util/function.js.map +1 -1
  187. package/dist/lib/util/locale.js +3 -6
  188. package/dist/lib/util/locale.js.map +1 -1
  189. package/dist/lib/util/object.js +1 -4
  190. package/dist/lib/util/object.js.map +1 -1
  191. package/dist/lib/util/redirect-uri.js +3 -6
  192. package/dist/lib/util/redirect-uri.js.map +1 -1
  193. package/dist/lib/util/time.js +5 -9
  194. package/dist/lib/util/time.js.map +1 -1
  195. package/dist/lib/util/type.d.ts.map +1 -1
  196. package/dist/lib/util/type.js +1 -5
  197. package/dist/lib/util/type.js.map +1 -1
  198. package/dist/lib/util/ui8.js +3 -8
  199. package/dist/lib/util/ui8.js.map +1 -1
  200. package/dist/lib/util/well-known.js +1 -4
  201. package/dist/lib/util/well-known.js.map +1 -1
  202. package/dist/lib/util/zod-error.js +4 -8
  203. package/dist/lib/util/zod-error.js.map +1 -1
  204. package/dist/lib/write-form-redirect.js +9 -12
  205. package/dist/lib/write-form-redirect.js.map +1 -1
  206. package/dist/lib/write-html.js +12 -15
  207. package/dist/lib/write-html.js.map +1 -1
  208. package/dist/metadata/build-metadata.js +9 -12
  209. package/dist/metadata/build-metadata.js.map +1 -1
  210. package/dist/oauth-client.js +2 -18
  211. package/dist/oauth-client.js.map +1 -1
  212. package/dist/oauth-dpop.js +2 -18
  213. package/dist/oauth-dpop.js.map +1 -1
  214. package/dist/oauth-errors.js +24 -42
  215. package/dist/oauth-errors.js.map +1 -1
  216. package/dist/oauth-hooks.js +8 -15
  217. package/dist/oauth-hooks.js.map +1 -1
  218. package/dist/oauth-middleware.js +13 -16
  219. package/dist/oauth-middleware.js.map +1 -1
  220. package/dist/oauth-provider.js +108 -125
  221. package/dist/oauth-provider.js.map +1 -1
  222. package/dist/oauth-store.js +7 -23
  223. package/dist/oauth-store.js.map +1 -1
  224. package/dist/oauth-verifier.js +41 -53
  225. package/dist/oauth-verifier.js.map +1 -1
  226. package/dist/oidc/sub.js +2 -5
  227. package/dist/oidc/sub.js.map +1 -1
  228. package/dist/replay/replay-manager.js +6 -11
  229. package/dist/replay/replay-manager.js.map +1 -1
  230. package/dist/replay/replay-store-memory.js +5 -7
  231. package/dist/replay/replay-store-memory.js.map +1 -1
  232. package/dist/replay/replay-store-redis.js +3 -8
  233. package/dist/replay/replay-store-redis.js.map +1 -1
  234. package/dist/replay/replay-store.js +3 -8
  235. package/dist/replay/replay-store.js.map +1 -1
  236. package/dist/request/code.js +10 -15
  237. package/dist/request/code.js.map +1 -1
  238. package/dist/request/request-data.js +1 -5
  239. package/dist/request/request-data.js.map +1 -1
  240. package/dist/request/request-id.js +9 -13
  241. package/dist/request/request-id.js.map +1 -1
  242. package/dist/request/request-manager.js +61 -71
  243. package/dist/request/request-manager.js.map +1 -1
  244. package/dist/request/request-store.js +9 -27
  245. package/dist/request/request-store.js.map +1 -1
  246. package/dist/request/request-uri.js +17 -23
  247. package/dist/request/request-uri.js.map +1 -1
  248. package/dist/result/authorization-redirect-parameters.js +1 -2
  249. package/dist/result/authorization-result-authorize-page.js +1 -2
  250. package/dist/result/authorization-result-redirect.js +1 -2
  251. package/dist/router/assets/assets-manifest.d.ts.map +1 -1
  252. package/dist/router/assets/assets-manifest.js +14 -15
  253. package/dist/router/assets/assets-manifest.js.map +1 -1
  254. package/dist/router/assets/assets.d.ts.map +1 -1
  255. package/dist/router/assets/assets.js +25 -27
  256. package/dist/router/assets/assets.js.map +1 -1
  257. package/dist/router/assets/csrf.js +16 -25
  258. package/dist/router/assets/csrf.js.map +1 -1
  259. package/dist/router/assets/send-account-page.js +3 -6
  260. package/dist/router/assets/send-account-page.js.map +1 -1
  261. package/dist/router/assets/send-authorization-page.js +3 -6
  262. package/dist/router/assets/send-authorization-page.js.map +1 -1
  263. package/dist/router/assets/send-cookie-error-page.js +3 -6
  264. package/dist/router/assets/send-cookie-error-page.js.map +1 -1
  265. package/dist/router/assets/send-error-page.js +6 -9
  266. package/dist/router/assets/send-error-page.js.map +1 -1
  267. package/dist/router/assets/send-redirect.js +12 -20
  268. package/dist/router/assets/send-redirect.js.map +1 -1
  269. package/dist/router/create-account-page-middleware.js +11 -14
  270. package/dist/router/create-account-page-middleware.js.map +1 -1
  271. package/dist/router/create-api-middleware.js +83 -90
  272. package/dist/router/create-api-middleware.js.map +1 -1
  273. package/dist/router/create-authorization-page-middleware.js +43 -46
  274. package/dist/router/create-authorization-page-middleware.js.map +1 -1
  275. package/dist/router/create-oauth-middleware.js +31 -34
  276. package/dist/router/create-oauth-middleware.js.map +1 -1
  277. package/dist/router/error-handler.js +1 -2
  278. package/dist/router/middleware-options.js +1 -2
  279. package/dist/signer/access-token-payload.js +12 -15
  280. package/dist/signer/access-token-payload.js.map +1 -1
  281. package/dist/signer/api-token-payload.js +8 -11
  282. package/dist/signer/api-token-payload.js.map +1 -1
  283. package/dist/signer/signer.js +11 -17
  284. package/dist/signer/signer.js.map +1 -1
  285. package/dist/token/refresh-token.js +10 -15
  286. package/dist/token/refresh-token.js.map +1 -1
  287. package/dist/token/token-claims.js +1 -2
  288. package/dist/token/token-data.js +1 -2
  289. package/dist/token/token-id.js +10 -15
  290. package/dist/token/token-id.js.map +1 -1
  291. package/dist/token/token-manager.js +40 -51
  292. package/dist/token/token-manager.js.map +1 -1
  293. package/dist/token/token-store.js +7 -25
  294. package/dist/token/token-store.js.map +1 -1
  295. package/dist/types/authorization-response-error.js +8 -12
  296. package/dist/types/authorization-response-error.js.map +1 -1
  297. package/dist/types/color-hue.js +2 -5
  298. package/dist/types/color-hue.js.map +1 -1
  299. package/dist/types/email-otp.js +2 -5
  300. package/dist/types/email-otp.js.map +1 -1
  301. package/dist/types/email.js +6 -9
  302. package/dist/types/email.js.map +1 -1
  303. package/dist/types/handle.js +6 -9
  304. package/dist/types/handle.js.map +1 -1
  305. package/dist/types/invite-code.js +2 -5
  306. package/dist/types/invite-code.js.map +1 -1
  307. package/dist/types/par-response-error.js +5 -9
  308. package/dist/types/par-response-error.js.map +1 -1
  309. package/dist/types/password.js +3 -6
  310. package/dist/types/password.js.map +1 -1
  311. package/dist/types/rgb-color.js +7 -10
  312. package/dist/types/rgb-color.js.map +1 -1
  313. package/package.json +20 -22
  314. package/src/dpop/dpop-nonce.ts +1 -1
  315. package/src/errors/invalid-invite-code-error.ts +1 -1
  316. package/src/lib/http/accept.ts +4 -1
  317. package/src/lib/http/request.ts +4 -1
  318. package/src/lib/util/type.ts +0 -1
  319. package/src/router/assets/assets-manifest.ts +3 -1
  320. package/src/router/assets/assets.ts +2 -0
  321. package/tsconfig.build.tsbuildinfo +1 -1
@@ -1,29 +1,10 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.LexiconManager = void 0;
18
- exports.nsidToPermissionScopes = nsidToPermissionScopes;
19
- const lex_resolver_1 = require("@atproto/lex-resolver");
20
- const oauth_scopes_1 = require("@atproto/oauth-scopes");
21
- const lexicon_getter_js_1 = require("./lexicon-getter.js");
22
- __exportStar(require("./lexicon-store.js"), exports);
23
- class LexiconManager {
24
- lexiconGetter;
1
+ import { LexResolverError } from '@atproto/lex-resolver';
2
+ import { IncludeScope } from '@atproto/oauth-scopes';
3
+ import { LexiconGetter } from './lexicon-getter.js';
4
+ export * from './lexicon-store.js';
5
+ export class LexiconManager {
25
6
  constructor(store, lexResolver) {
26
- this.lexiconGetter = new lexicon_getter_js_1.LexiconGetter(store, lexResolver);
7
+ this.lexiconGetter = new LexiconGetter(store, lexResolver);
27
8
  }
28
9
  async getPermissionSetsFromScope(scope) {
29
10
  const { includeScopes } = parseScope(scope);
@@ -63,22 +44,21 @@ class LexiconManager {
63
44
  async getPermissionSet(nsid) {
64
45
  const { lexicon } = await this.lexiconGetter.get(nsid);
65
46
  if (!lexicon) {
66
- throw lex_resolver_1.LexResolverError.from(nsid);
47
+ throw LexResolverError.from(nsid);
67
48
  }
68
49
  if (lexicon.defs.main?.type !== 'permission-set') {
69
50
  const description = 'Lexicon document is not a permission set';
70
- throw lex_resolver_1.LexResolverError.from(nsid, description);
51
+ throw LexResolverError.from(nsid, description);
71
52
  }
72
53
  return lexicon.defs.main;
73
54
  }
74
55
  }
75
- exports.LexiconManager = LexiconManager;
76
56
  function parseScope(scope) {
77
57
  const includeScopes = [];
78
58
  const otherScopes = [];
79
59
  if (scope) {
80
60
  for (const scopeValue of scope.split(' ')) {
81
- const parsed = oauth_scopes_1.IncludeScope.fromString(scopeValue);
61
+ const parsed = IncludeScope.fromString(scopeValue);
82
62
  if (parsed) {
83
63
  includeScopes.push(parsed);
84
64
  }
@@ -98,7 +78,7 @@ function extractNsids(includeScopes) {
98
78
  function extractNsid(nsidScope) {
99
79
  return nsidScope.nsid;
100
80
  }
101
- function nsidToPermissionScopes(includeScope) {
81
+ export function nsidToPermissionScopes(includeScope) {
102
82
  const permissionSet = this.get(includeScope.nsid);
103
83
  if (permissionSet)
104
84
  return includeScope.toScopes(permissionSet);
@@ -1 +1 @@
1
- {"version":3,"file":"lexicon-manager.js","sourceRoot":"","sources":["../../src/lexicon/lexicon-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import { LexiconPermissionSet } from '@atproto/lex-document'\nimport { LexResolver, LexResolverError } from '@atproto/lex-resolver'\nimport { IncludeScope, Nsid } from '@atproto/oauth-scopes'\nimport { LexiconGetter } from './lexicon-getter.js'\nimport { LexiconStore } from './lexicon-store.js'\n\nexport * from './lexicon-store.js'\n\nexport class LexiconManager {\n protected readonly lexiconGetter: LexiconGetter\n\n constructor(store: LexiconStore, lexResolver: LexResolver) {\n this.lexiconGetter = new LexiconGetter(store, lexResolver)\n }\n\n public async getPermissionSetsFromScope(scope?: string) {\n const { includeScopes } = parseScope(scope)\n return this.extractPermissionSets(includeScopes)\n }\n\n /**\n * Transforms a scope string from an authorization request into a scope\n * composed solely of granular permission scopes, transforming any NSID\n * into its corresponding permission scopes.\n */\n public async buildTokenScope(scope: string): Promise<string> {\n const { includeScopes, otherScopes } = parseScope(scope)\n\n // If the scope does not contain any \"include:<nsid>\" scopes, return it as-is.\n if (!includeScopes.length) return scope\n\n const permissionSets = await this.extractPermissionSets(includeScopes)\n\n return Array.from(includeScopes)\n .flatMap(nsidToPermissionScopes, permissionSets)\n .concat(otherScopes)\n .join(' ')\n }\n\n /**\n * Given a list of scope values, extract those that are NSIDs and return their\n * corresponding permission sets.\n */\n protected async extractPermissionSets(includeScopes: IncludeScope[]) {\n const nsids = extractNsids(includeScopes)\n return this.getPermissionSets(nsids)\n }\n\n protected async getPermissionSets(nsids: Set<Nsid>) {\n return new Map<string, LexiconPermissionSet>(\n await Promise.all(Array.from(nsids, this.getPermissionSetEntry, this)),\n )\n }\n\n protected async getPermissionSetEntry(\n nsid: Nsid,\n ): Promise<[nsid: Nsid, permissionSet: LexiconPermissionSet]> {\n const permissionSet = await this.getPermissionSet(nsid)\n return [nsid, permissionSet]\n }\n\n protected async getPermissionSet(nsid: Nsid): Promise<LexiconPermissionSet> {\n const { lexicon } = await this.lexiconGetter.get(nsid)\n\n if (!lexicon) {\n throw LexResolverError.from(nsid)\n }\n\n if (lexicon.defs.main?.type !== 'permission-set') {\n const description = 'Lexicon document is not a permission set'\n throw LexResolverError.from(nsid, description)\n }\n\n return lexicon.defs.main\n }\n}\n\nfunction parseScope(scope?: string) {\n const includeScopes: IncludeScope[] = []\n const otherScopes: string[] = []\n\n if (scope) {\n for (const scopeValue of scope.split(' ')) {\n const parsed = IncludeScope.fromString(scopeValue)\n if (parsed) {\n includeScopes.push(parsed)\n } else {\n otherScopes.push(scopeValue)\n }\n }\n }\n\n return {\n includeScopes,\n otherScopes,\n }\n}\n\nfunction extractNsids(includeScopes: IncludeScope[]): Set<Nsid> {\n return new Set(Array.from(includeScopes, extractNsid))\n}\n\nfunction extractNsid(nsidScope: IncludeScope): Nsid {\n return nsidScope.nsid\n}\n\nexport function nsidToPermissionScopes(\n this: Map<string, LexiconPermissionSet>,\n includeScope: IncludeScope,\n): string[] {\n const permissionSet = this.get(includeScope.nsid)\n if (permissionSet) return includeScope.toScopes(permissionSet)\n\n // Should never happen (mostly there for type safety & future proofing)\n throw new Error(`Missing permission set for NSID: ${includeScope.nsid}`)\n}\n"]}
1
+ {"version":3,"file":"lexicon-manager.js","sourceRoot":"","sources":["../../src/lexicon/lexicon-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import { LexiconPermissionSet } from '@atproto/lex-document'\nimport { LexResolver, LexResolverError } from '@atproto/lex-resolver'\nimport { IncludeScope, Nsid } from '@atproto/oauth-scopes'\nimport { LexiconGetter } from './lexicon-getter.js'\nimport { LexiconStore } from './lexicon-store.js'\n\nexport * from './lexicon-store.js'\n\nexport class LexiconManager {\n protected readonly lexiconGetter: LexiconGetter\n\n constructor(store: LexiconStore, lexResolver: LexResolver) {\n this.lexiconGetter = new LexiconGetter(store, lexResolver)\n }\n\n public async getPermissionSetsFromScope(scope?: string) {\n const { includeScopes } = parseScope(scope)\n return this.extractPermissionSets(includeScopes)\n }\n\n /**\n * Transforms a scope string from an authorization request into a scope\n * composed solely of granular permission scopes, transforming any NSID\n * into its corresponding permission scopes.\n */\n public async buildTokenScope(scope: string): Promise<string> {\n const { includeScopes, otherScopes } = parseScope(scope)\n\n // If the scope does not contain any \"include:<nsid>\" scopes, return it as-is.\n if (!includeScopes.length) return scope\n\n const permissionSets = await this.extractPermissionSets(includeScopes)\n\n return Array.from(includeScopes)\n .flatMap(nsidToPermissionScopes, permissionSets)\n .concat(otherScopes)\n .join(' ')\n }\n\n /**\n * Given a list of scope values, extract those that are NSIDs and return their\n * corresponding permission sets.\n */\n protected async extractPermissionSets(includeScopes: IncludeScope[]) {\n const nsids = extractNsids(includeScopes)\n return this.getPermissionSets(nsids)\n }\n\n protected async getPermissionSets(nsids: Set<Nsid>) {\n return new Map<string, LexiconPermissionSet>(\n await Promise.all(Array.from(nsids, this.getPermissionSetEntry, this)),\n )\n }\n\n protected async getPermissionSetEntry(\n nsid: Nsid,\n ): Promise<[nsid: Nsid, permissionSet: LexiconPermissionSet]> {\n const permissionSet = await this.getPermissionSet(nsid)\n return [nsid, permissionSet]\n }\n\n protected async getPermissionSet(nsid: Nsid): Promise<LexiconPermissionSet> {\n const { lexicon } = await this.lexiconGetter.get(nsid)\n\n if (!lexicon) {\n throw LexResolverError.from(nsid)\n }\n\n if (lexicon.defs.main?.type !== 'permission-set') {\n const description = 'Lexicon document is not a permission set'\n throw LexResolverError.from(nsid, description)\n }\n\n return lexicon.defs.main\n }\n}\n\nfunction parseScope(scope?: string) {\n const includeScopes: IncludeScope[] = []\n const otherScopes: string[] = []\n\n if (scope) {\n for (const scopeValue of scope.split(' ')) {\n const parsed = IncludeScope.fromString(scopeValue)\n if (parsed) {\n includeScopes.push(parsed)\n } else {\n otherScopes.push(scopeValue)\n }\n }\n }\n\n return {\n includeScopes,\n otherScopes,\n }\n}\n\nfunction extractNsids(includeScopes: IncludeScope[]): Set<Nsid> {\n return new Set(Array.from(includeScopes, extractNsid))\n}\n\nfunction extractNsid(nsidScope: IncludeScope): Nsid {\n return nsidScope.nsid\n}\n\nexport function nsidToPermissionScopes(\n this: Map<string, LexiconPermissionSet>,\n includeScope: IncludeScope,\n): string[] {\n const permissionSet = this.get(includeScope.nsid)\n if (permissionSet) return includeScope.toScopes(permissionSet)\n\n // Should never happen (mostly there for type safety & future proofing)\n throw new Error(`Missing permission set for NSID: ${includeScope.nsid}`)\n}\n"]}
@@ -1,21 +1,16 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isLexiconStore = void 0;
4
- exports.ifLexiconStore = ifLexiconStore;
5
- exports.asLexiconStore = asLexiconStore;
6
- const type_js_1 = require("../lib/util/type.js");
7
- exports.isLexiconStore = (0, type_js_1.buildInterfaceChecker)([
1
+ import { buildInterfaceChecker } from '../lib/util/type.js';
2
+ export const isLexiconStore = buildInterfaceChecker([
8
3
  'findLexicon',
9
4
  'storeLexicon',
10
5
  'deleteLexicon',
11
6
  ]);
12
- function ifLexiconStore(implementation) {
13
- if (implementation && (0, exports.isLexiconStore)(implementation)) {
7
+ export function ifLexiconStore(implementation) {
8
+ if (implementation && isLexiconStore(implementation)) {
14
9
  return implementation;
15
10
  }
16
11
  return undefined;
17
12
  }
18
- function asLexiconStore(implementation) {
13
+ export function asLexiconStore(implementation) {
19
14
  const store = ifLexiconStore(implementation);
20
15
  if (store)
21
16
  return store;
@@ -1 +1 @@
1
- {"version":3,"file":"lexicon-store.js","sourceRoot":"","sources":["../../src/lexicon/lexicon-store.ts"],"names":[],"mappings":";;;AAiBA,wCAQC;AAED,wCAOC;AAlCD,iDAAsE;AAWzD,QAAA,cAAc,GAAG,IAAA,+BAAqB,EAAe;IAChE,aAAa;IACb,cAAc;IACd,eAAe;CAChB,CAAC,CAAA;AAEF,SAAgB,cAAc,CAC5B,cAAkB;IAElB,IAAI,cAAc,IAAI,IAAA,sBAAc,EAAC,cAAc,CAAC,EAAE,CAAC;QACrD,OAAO,cAAc,CAAA;IACvB,CAAC;IAED,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,SAAgB,cAAc,CAC5B,cAAkB;IAElB,MAAM,KAAK,GAAG,cAAc,CAAC,cAAc,CAAC,CAAA;IAC5C,IAAI,KAAK;QAAE,OAAO,KAAK,CAAA;IAEvB,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;AACxD,CAAC","sourcesContent":["import { Awaitable, buildInterfaceChecker } from '../lib/util/type.js'\nimport { LexiconData, LexiconDocument } from './lexicon-data.js'\n\nexport type { Awaitable, LexiconData, LexiconDocument }\n\nexport interface LexiconStore {\n findLexicon(nsid: string): Awaitable<LexiconData | null>\n storeLexicon(nsid: string, data: LexiconData): Awaitable<void>\n deleteLexicon(nsid: string): Awaitable<void>\n}\n\nexport const isLexiconStore = buildInterfaceChecker<LexiconStore>([\n 'findLexicon',\n 'storeLexicon',\n 'deleteLexicon',\n])\n\nexport function ifLexiconStore<V extends Partial<LexiconStore>>(\n implementation?: V,\n): (V & LexiconStore) | undefined {\n if (implementation && isLexiconStore(implementation)) {\n return implementation\n }\n\n return undefined\n}\n\nexport function asLexiconStore<V extends Partial<LexiconStore>>(\n implementation?: V,\n): V & LexiconStore {\n const store = ifLexiconStore(implementation)\n if (store) return store\n\n throw new Error('Invalid LexiconStore implementation')\n}\n"]}
1
+ {"version":3,"file":"lexicon-store.js","sourceRoot":"","sources":["../../src/lexicon/lexicon-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAWtE,MAAM,CAAC,MAAM,cAAc,GAAG,qBAAqB,CAAe;IAChE,aAAa;IACb,cAAc;IACd,eAAe;CAChB,CAAC,CAAA;AAEF,MAAM,UAAU,cAAc,CAC5B,cAAkB;IAElB,IAAI,cAAc,IAAI,cAAc,CAAC,cAAc,CAAC,EAAE,CAAC;QACrD,OAAO,cAAc,CAAA;IACvB,CAAC;IAED,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,cAAkB;IAElB,MAAM,KAAK,GAAG,cAAc,CAAC,cAAc,CAAC,CAAA;IAC5C,IAAI,KAAK;QAAE,OAAO,KAAK,CAAA;IAEvB,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;AACxD,CAAC","sourcesContent":["import { Awaitable, buildInterfaceChecker } from '../lib/util/type.js'\nimport { LexiconData, LexiconDocument } from './lexicon-data.js'\n\nexport type { Awaitable, LexiconData, LexiconDocument }\n\nexport interface LexiconStore {\n findLexicon(nsid: string): Awaitable<LexiconData | null>\n storeLexicon(nsid: string, data: LexiconData): Awaitable<void>\n deleteLexicon(nsid: string): Awaitable<void>\n}\n\nexport const isLexiconStore = buildInterfaceChecker<LexiconStore>([\n 'findLexicon',\n 'storeLexicon',\n 'deleteLexicon',\n])\n\nexport function ifLexiconStore<V extends Partial<LexiconStore>>(\n implementation?: V,\n): (V & LexiconStore) | undefined {\n if (implementation && isLexiconStore(implementation)) {\n return implementation\n }\n\n return undefined\n}\n\nexport function asLexiconStore<V extends Partial<LexiconStore>>(\n implementation?: V,\n): V & LexiconStore {\n const store = ifLexiconStore(implementation)\n if (store) return store\n\n throw new Error('Invalid LexiconStore implementation')\n}\n"]}
@@ -1,8 +1,3 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.buildCsp = buildCsp;
4
- exports.mergeCsp = mergeCsp;
5
- exports.combineCsp = combineCsp;
6
1
  const STRING_DIRECTIVES = ['base-uri'];
7
2
  const BOOLEAN_DIRECTIVES = [
8
3
  'upgrade-insecure-requests',
@@ -19,7 +14,7 @@ const ARRAY_DIRECTIVES = [
19
14
  'style-src',
20
15
  ];
21
16
  const NONE = "'none'";
22
- function buildCsp(config) {
17
+ export function buildCsp(config) {
23
18
  const values = [];
24
19
  for (const name of BOOLEAN_DIRECTIVES) {
25
20
  if (config[name] === true)
@@ -37,10 +32,10 @@ function buildCsp(config) {
37
32
  }
38
33
  return values.join('; ');
39
34
  }
40
- function mergeCsp(...configs) {
35
+ export function mergeCsp(...configs) {
41
36
  return configs.filter((v) => v != null).reduce(combineCsp);
42
37
  }
43
- function combineCsp(a, b) {
38
+ export function combineCsp(a, b) {
44
39
  const result = {};
45
40
  for (const name of BOOLEAN_DIRECTIVES) {
46
41
  // @NOTE b (if defined) takes precedence
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/csp/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { CombinedTuple, Simplify } from '../util/type.js'\n\nexport type CspValue =\n | `data:`\n | `http:${string}`\n | `https:${string}`\n | `'none'`\n | `'self'`\n | `'sha256-${string}'`\n | `'nonce-${string}'`\n | `'unsafe-inline'`\n | `'unsafe-eval'`\n | `'strict-dynamic'`\n | `'report-sample'`\n | `'unsafe-hashes'`\n\nconst STRING_DIRECTIVES = ['base-uri'] as const\nconst BOOLEAN_DIRECTIVES = [\n 'upgrade-insecure-requests',\n 'block-all-mixed-content',\n] as const\nconst ARRAY_DIRECTIVES = [\n 'connect-src',\n 'default-src',\n 'form-action',\n 'frame-ancestors',\n 'frame-src',\n 'img-src',\n 'script-src',\n 'style-src',\n] as const\n\nexport type CspConfig = Simplify<\n {\n [K in (typeof BOOLEAN_DIRECTIVES)[number]]?: boolean\n } & {\n [K in (typeof STRING_DIRECTIVES)[number]]?: CspValue\n } & {\n [K in (typeof ARRAY_DIRECTIVES)[number]]?: Iterable<CspValue>\n }\n>\n\nconst NONE = \"'none'\"\n\nexport function buildCsp(config: CspConfig): string {\n const values: string[] = []\n\n for (const name of BOOLEAN_DIRECTIVES) {\n if (config[name] === true) values.push(name)\n }\n\n for (const name of STRING_DIRECTIVES) {\n if (config[name]) values.push(`${name} ${config[name]}`)\n }\n\n for (const name of ARRAY_DIRECTIVES) {\n // Remove duplicate values by using a Set\n const val = config[name] ? new Set(config[name]) : undefined\n if (val?.size) values.push(`${name} ${Array.from(val).join(' ')}`)\n }\n\n return values.join('; ')\n}\n\nexport function mergeCsp<C extends (CspConfig | null | undefined)[]>(\n ...configs: C\n) {\n return configs.filter((v) => v != null).reduce(combineCsp) as CombinedTuple<C>\n}\n\nexport function combineCsp(a: CspConfig, b: CspConfig): CspConfig {\n const result: CspConfig = {}\n\n for (const name of BOOLEAN_DIRECTIVES) {\n // @NOTE b (if defined) takes precedence\n const value = b[name] ?? a[name]\n if (value != null) result[name] = value\n }\n\n for (const name of STRING_DIRECTIVES) {\n if (a[name] || b[name]) {\n const aNotNone = a[name] === NONE ? undefined : a[name]\n const bNotNone = b[name] === NONE ? undefined : b[name]\n // @NOTE b takes precedence\n result[name] = bNotNone || aNotNone || NONE\n }\n }\n\n for (const name of ARRAY_DIRECTIVES) {\n if (a[name] && b[name]) {\n const set = new Set(a[name])\n if (b[name]) for (const value of b[name]) set.add(value)\n if (set.size > 1 && set.has(NONE)) set.delete(NONE)\n result[name] = [...set]\n } else if (a[name] || b[name]) {\n result[name] = a[name] || b[name]\n }\n }\n\n return result\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/csp/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { CombinedTuple, Simplify } from '../util/type.js'\n\nexport type CspValue =\n | `data:`\n | `http:${string}`\n | `https:${string}`\n | `'none'`\n | `'self'`\n | `'sha256-${string}'`\n | `'nonce-${string}'`\n | `'unsafe-inline'`\n | `'unsafe-eval'`\n | `'strict-dynamic'`\n | `'report-sample'`\n | `'unsafe-hashes'`\n\nconst STRING_DIRECTIVES = ['base-uri'] as const\nconst BOOLEAN_DIRECTIVES = [\n 'upgrade-insecure-requests',\n 'block-all-mixed-content',\n] as const\nconst ARRAY_DIRECTIVES = [\n 'connect-src',\n 'default-src',\n 'form-action',\n 'frame-ancestors',\n 'frame-src',\n 'img-src',\n 'script-src',\n 'style-src',\n] as const\n\nexport type CspConfig = Simplify<\n {\n [K in (typeof BOOLEAN_DIRECTIVES)[number]]?: boolean\n } & {\n [K in (typeof STRING_DIRECTIVES)[number]]?: CspValue\n } & {\n [K in (typeof ARRAY_DIRECTIVES)[number]]?: Iterable<CspValue>\n }\n>\n\nconst NONE = \"'none'\"\n\nexport function buildCsp(config: CspConfig): string {\n const values: string[] = []\n\n for (const name of BOOLEAN_DIRECTIVES) {\n if (config[name] === true) values.push(name)\n }\n\n for (const name of STRING_DIRECTIVES) {\n if (config[name]) values.push(`${name} ${config[name]}`)\n }\n\n for (const name of ARRAY_DIRECTIVES) {\n // Remove duplicate values by using a Set\n const val = config[name] ? new Set(config[name]) : undefined\n if (val?.size) values.push(`${name} ${Array.from(val).join(' ')}`)\n }\n\n return values.join('; ')\n}\n\nexport function mergeCsp<C extends (CspConfig | null | undefined)[]>(\n ...configs: C\n) {\n return configs.filter((v) => v != null).reduce(combineCsp) as CombinedTuple<C>\n}\n\nexport function combineCsp(a: CspConfig, b: CspConfig): CspConfig {\n const result: CspConfig = {}\n\n for (const name of BOOLEAN_DIRECTIVES) {\n // @NOTE b (if defined) takes precedence\n const value = b[name] ?? a[name]\n if (value != null) result[name] = value\n }\n\n for (const name of STRING_DIRECTIVES) {\n if (a[name] || b[name]) {\n const aNotNone = a[name] === NONE ? undefined : a[name]\n const bNotNone = b[name] === NONE ? undefined : b[name]\n // @NOTE b takes precedence\n result[name] = bNotNone || aNotNone || NONE\n }\n }\n\n for (const name of ARRAY_DIRECTIVES) {\n if (a[name] && b[name]) {\n const set = new Set(a[name])\n if (b[name]) for (const value of b[name]) set.add(value)\n if (set.size > 1 && set.has(NONE)) set.delete(NONE)\n result[name] = [...set]\n } else if (a[name] || b[name]) {\n result[name] = a[name] || b[name]\n }\n }\n\n return result\n}\n"]}
@@ -1,24 +1,21 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.HCaptchaVerifyError = exports.HCaptchaClient = exports.hcaptchaVerifyResultSchema = exports.hcaptchaConfigSchema = exports.hcaptchaTokenSchema = void 0;
4
- const node_crypto_1 = require("node:crypto");
5
- const zod_1 = require("zod");
6
- const fetch_1 = require("@atproto-labs/fetch");
7
- const pipe_1 = require("@atproto-labs/pipe");
8
- exports.hcaptchaTokenSchema = zod_1.z.string().min(1);
9
- exports.hcaptchaConfigSchema = zod_1.z.object({
1
+ import { createHash } from 'node:crypto';
2
+ import { z } from 'zod';
3
+ import { bindFetch, fetchJsonProcessor, fetchJsonZodProcessor, fetchOkProcessor, } from '@atproto-labs/fetch';
4
+ import { pipe } from '@atproto-labs/pipe';
5
+ export const hcaptchaTokenSchema = z.string().min(1);
6
+ export const hcaptchaConfigSchema = z.object({
10
7
  /**
11
8
  * The hCaptcha site key to use for the sign-up form.
12
9
  */
13
- siteKey: zod_1.z.string().min(1),
10
+ siteKey: z.string().min(1),
14
11
  /**
15
12
  * The hCaptcha secret key to use for the sign-up form.
16
13
  */
17
- secretKey: zod_1.z.string().min(1),
14
+ secretKey: z.string().min(1),
18
15
  /**
19
16
  * A salt to use when hashing client tokens.
20
17
  */
21
- tokenSalt: zod_1.z.string().min(1),
18
+ tokenSalt: z.string().min(1),
22
19
  /**
23
20
  * The risk score above which the user is considered a threat and will be
24
21
  * denied access. This will be ignored if the enterprise features are not
@@ -26,92 +23,89 @@ exports.hcaptchaConfigSchema = zod_1.z.object({
26
23
  *
27
24
  * Note: Score values ranges from 0.0 (no risk) to 1.0 (confirmed threat).
28
25
  */
29
- scoreThreshold: zod_1.z.number().optional(),
26
+ scoreThreshold: z.number().optional(),
30
27
  });
31
28
  /**
32
29
  * @see {@link https://docs.hcaptcha.com/#verify-the-user-response-server-side hCaptcha API}
33
30
  */
34
- exports.hcaptchaVerifyResultSchema = zod_1.z.object({
31
+ export const hcaptchaVerifyResultSchema = z.object({
35
32
  /**
36
33
  * is the passcode valid, and does it meet security criteria you specified, e.g. sitekey?
37
34
  */
38
- success: zod_1.z.boolean(),
35
+ success: z.boolean(),
39
36
  /**
40
37
  * timestamp of the challenge (ISO format yyyy-MM-dd'T'HH:mm:ssZZ)
41
38
  */
42
- challenge_ts: zod_1.z.string(),
39
+ challenge_ts: z.string(),
43
40
  /**
44
41
  * the hostname of the site where the challenge was passed
45
42
  */
46
- hostname: zod_1.z.string().nullable(),
43
+ hostname: z.string().nullable(),
47
44
  /**
48
45
  * optional: any error codes returned by the hCaptcha API.
49
46
  * @see {@link https://docs.hcaptcha.com/#siteverify-error-codes-table}
50
47
  */
51
- 'error-codes': zod_1.z.array(zod_1.z.string()).optional(),
48
+ 'error-codes': z.array(z.string()).optional(),
52
49
  /**
53
50
  * ENTERPRISE feature: a score denoting malicious activity. Value ranges from
54
51
  * 0.0 (no risk) to 1.0 (confirmed threat).
55
52
  */
56
- score: zod_1.z.number().optional(),
53
+ score: z.number().optional(),
57
54
  /**
58
55
  * ENTERPRISE feature: reason(s) for score.
59
56
  */
60
- score_reason: zod_1.z.array(zod_1.z.string()).optional(),
57
+ score_reason: z.array(z.string()).optional(),
61
58
  /**
62
59
  * sitekey of the request
63
60
  */
64
- sitekey: zod_1.z.string().optional(),
61
+ sitekey: z.string().optional(),
65
62
  /**
66
63
  * obj of form: {'ip_device': 1, .. etc}
67
64
  */
68
- behavior_counts: zod_1.z.record(zod_1.z.unknown()).optional(),
65
+ behavior_counts: z.record(z.unknown()).optional(),
69
66
  /**
70
67
  * how similar is this? (0.0 - 1.0, -1 on err)
71
68
  */
72
- similarity: zod_1.z.number().optional(),
69
+ similarity: z.number().optional(),
73
70
  /**
74
71
  * count of similar_tokens not processed
75
72
  */
76
- similarity_failures: zod_1.z.number().optional(),
73
+ similarity_failures: z.number().optional(),
77
74
  /**
78
75
  * array of strings for any similarity errors
79
76
  */
80
- similarity_error_details: zod_1.z.array(zod_1.z.string()).optional(),
77
+ similarity_error_details: z.array(z.string()).optional(),
81
78
  /**
82
79
  * encoded clientID
83
80
  */
84
- scoped_uid_0: zod_1.z.string().optional(),
81
+ scoped_uid_0: z.string().optional(),
85
82
  /**
86
83
  * encoded IP
87
84
  */
88
- scoped_uid_1: zod_1.z.string().optional(),
85
+ scoped_uid_1: z.string().optional(),
89
86
  /**
90
87
  * encoded IP (APT)
91
88
  */
92
- scoped_uid_2: zod_1.z.string().optional(),
89
+ scoped_uid_2: z.string().optional(),
93
90
  /**
94
91
  * Risk Insights (APT + RI)
95
92
  */
96
- risk_insights: zod_1.z.record(zod_1.z.unknown()).optional(),
93
+ risk_insights: z.record(z.unknown()).optional(),
97
94
  /**
98
95
  * Advanced Threat Signatures (APT)
99
96
  */
100
- sigs: zod_1.z.record(zod_1.z.unknown()).optional(),
97
+ sigs: z.record(z.unknown()).optional(),
101
98
  /**
102
99
  * tags added via Rules
103
100
  */
104
- tags: zod_1.z.array(zod_1.z.string()).optional(),
101
+ tags: z.array(z.string()).optional(),
105
102
  });
106
- const fetchSuccessHandler = (0, pipe_1.pipe)((0, fetch_1.fetchOkProcessor)(), (0, fetch_1.fetchJsonProcessor)(), (0, fetch_1.fetchJsonZodProcessor)(exports.hcaptchaVerifyResultSchema));
107
- class HCaptchaClient {
108
- hostname;
109
- config;
110
- fetch;
103
+ const fetchSuccessHandler = pipe(fetchOkProcessor(), fetchJsonProcessor(), fetchJsonZodProcessor(hcaptchaVerifyResultSchema));
104
+ export class HCaptchaClient {
111
105
  constructor(hostname, config, fetch = globalThis.fetch) {
112
106
  this.hostname = hostname;
113
107
  this.config = config;
114
- this.fetch = (0, fetch_1.bindFetch)(fetch);
108
+ this.fetch = bindFetch(fetch);
115
109
  }
116
110
  async verify(behaviorType, response, remoteip, clientTokens) {
117
111
  return this.fetch('https://api.hcaptcha.com/siteverify', {
@@ -158,21 +152,17 @@ class HCaptchaClient {
158
152
  };
159
153
  }
160
154
  hashToken(value) {
161
- const hash = (0, node_crypto_1.createHash)('sha256');
155
+ const hash = createHash('sha256');
162
156
  hash.update(this.config.tokenSalt);
163
157
  hash.update(value);
164
158
  return hash.digest().toString('base64');
165
159
  }
166
160
  }
167
- exports.HCaptchaClient = HCaptchaClient;
168
- class HCaptchaVerifyError extends Error {
169
- result;
170
- tokens;
161
+ export class HCaptchaVerifyError extends Error {
171
162
  constructor(result, tokens, message) {
172
163
  super(message);
173
164
  this.result = result;
174
165
  this.tokens = tokens;
175
166
  }
176
167
  }
177
- exports.HCaptchaVerifyError = HCaptchaVerifyError;
178
168
  //# sourceMappingURL=hcaptcha.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"hcaptcha.js","sourceRoot":"","sources":["../../src/lib/hcaptcha.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from 'node:crypto'\nimport { z } from 'zod'\nimport {\n Fetch,\n FetchBound,\n bindFetch,\n fetchJsonProcessor,\n fetchJsonZodProcessor,\n fetchOkProcessor,\n} from '@atproto-labs/fetch'\nimport { pipe } from '@atproto-labs/pipe'\n\nexport const hcaptchaTokenSchema = z.string().min(1)\nexport type HcaptchaToken = z.infer<typeof hcaptchaTokenSchema>\n\nexport const hcaptchaConfigSchema = z.object({\n /**\n * The hCaptcha site key to use for the sign-up form.\n */\n siteKey: z.string().min(1),\n /**\n * The hCaptcha secret key to use for the sign-up form.\n */\n secretKey: z.string().min(1),\n /**\n * A salt to use when hashing client tokens.\n */\n tokenSalt: z.string().min(1),\n /**\n * The risk score above which the user is considered a threat and will be\n * denied access. This will be ignored if the enterprise features are not\n * available.\n *\n * Note: Score values ranges from 0.0 (no risk) to 1.0 (confirmed threat).\n */\n scoreThreshold: z.number().optional(),\n})\nexport type HcaptchaConfig = z.infer<typeof hcaptchaConfigSchema>\n\n/**\n * @see {@link https://docs.hcaptcha.com/#verify-the-user-response-server-side hCaptcha API}\n */\nexport const hcaptchaVerifyResultSchema = z.object({\n /**\n * is the passcode valid, and does it meet security criteria you specified, e.g. sitekey?\n */\n success: z.boolean(),\n /**\n * timestamp of the challenge (ISO format yyyy-MM-dd'T'HH:mm:ssZZ)\n */\n challenge_ts: z.string(),\n /**\n * the hostname of the site where the challenge was passed\n */\n hostname: z.string().nullable(),\n /**\n * optional: any error codes returned by the hCaptcha API.\n * @see {@link https://docs.hcaptcha.com/#siteverify-error-codes-table}\n */\n 'error-codes': z.array(z.string()).optional(),\n /**\n * ENTERPRISE feature: a score denoting malicious activity. Value ranges from\n * 0.0 (no risk) to 1.0 (confirmed threat).\n */\n score: z.number().optional(),\n /**\n * ENTERPRISE feature: reason(s) for score.\n */\n score_reason: z.array(z.string()).optional(),\n /**\n * sitekey of the request\n */\n sitekey: z.string().optional(),\n /**\n * obj of form: {'ip_device': 1, .. etc}\n */\n behavior_counts: z.record(z.unknown()).optional(),\n /**\n * how similar is this? (0.0 - 1.0, -1 on err)\n */\n similarity: z.number().optional(),\n /**\n * count of similar_tokens not processed\n */\n similarity_failures: z.number().optional(),\n /**\n * array of strings for any similarity errors\n */\n similarity_error_details: z.array(z.string()).optional(),\n /**\n * encoded clientID\n */\n scoped_uid_0: z.string().optional(),\n /**\n * encoded IP\n */\n scoped_uid_1: z.string().optional(),\n /**\n * encoded IP (APT)\n */\n scoped_uid_2: z.string().optional(),\n /**\n * Risk Insights (APT + RI)\n */\n risk_insights: z.record(z.unknown()).optional(),\n /**\n * Advanced Threat Signatures (APT)\n */\n sigs: z.record(z.unknown()).optional(),\n /**\n * tags added via Rules\n */\n tags: z.array(z.string()).optional(),\n})\n\nexport type HcaptchaVerifyResult = z.infer<typeof hcaptchaVerifyResultSchema>\n\nexport type HcaptchaClientTokens = {\n hashedIp: string\n hashedHandle: string\n hashedUserAgent?: string\n}\n\nconst fetchSuccessHandler = pipe(\n fetchOkProcessor(),\n fetchJsonProcessor(),\n fetchJsonZodProcessor(hcaptchaVerifyResultSchema),\n)\n\nexport class HCaptchaClient {\n protected readonly fetch: FetchBound\n constructor(\n readonly hostname: string,\n readonly config: HcaptchaConfig,\n fetch: Fetch = globalThis.fetch,\n ) {\n this.fetch = bindFetch(fetch)\n }\n\n public async verify(\n behaviorType: 'login' | 'signup',\n response: string,\n remoteip: string,\n clientTokens: HcaptchaClientTokens,\n ) {\n return this.fetch('https://api.hcaptcha.com/siteverify', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n secret: this.config.secretKey,\n sitekey: this.config.siteKey,\n behavior_type: behaviorType,\n response,\n remoteip,\n client_tokens: JSON.stringify(clientTokens),\n }).toString(),\n }).then(fetchSuccessHandler)\n }\n\n public checkVerifyResult(\n result: HcaptchaVerifyResult,\n tokens: HcaptchaClientTokens,\n ): void {\n const { success, score } = result\n\n if (success !== true) {\n throw new HCaptchaVerifyError(\n result,\n tokens,\n 'Expected success to be true',\n )\n }\n\n // https://docs.hcaptcha.com/#verify-the-user-response-server-side\n\n // Please [...] note that the hostname field is derived from the user's\n // browser, and should not be used for authentication of any kind; it is\n // primarily useful as a statistical metric. Additionally, in the event that\n // your site experiences unusually high challenge traffic, the hostname\n // field may be returned as \"not-provided\" rather than the usual value; all\n // other fields will return their normal values.\n\n if (\n // Ignore if enterprise feature is not enabled\n score != null &&\n // Ignore if disabled through config\n this.config.scoreThreshold != null &&\n score >= this.config.scoreThreshold\n ) {\n throw new HCaptchaVerifyError(\n result,\n tokens,\n `Score ${score} is above the threshold ${this.config.scoreThreshold}`,\n )\n }\n }\n\n public buildClientTokens(\n remoteip: string,\n handle: string,\n userAgent?: string,\n ): HcaptchaClientTokens {\n return {\n hashedIp: this.hashToken(remoteip),\n hashedHandle: this.hashToken(handle),\n hashedUserAgent: userAgent ? this.hashToken(userAgent) : undefined,\n }\n }\n\n protected hashToken(value: string) {\n const hash = createHash('sha256')\n hash.update(this.config.tokenSalt)\n hash.update(value)\n return hash.digest().toString('base64')\n }\n}\n\nexport class HCaptchaVerifyError extends Error {\n constructor(\n readonly result: HcaptchaVerifyResult,\n readonly tokens: HcaptchaClientTokens,\n message?: string,\n ) {\n super(message)\n }\n}\n"]}
1
+ {"version":3,"file":"hcaptcha.js","sourceRoot":"","sources":["../../src/lib/hcaptcha.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from 'node:crypto'\nimport { z } from 'zod'\nimport {\n Fetch,\n FetchBound,\n bindFetch,\n fetchJsonProcessor,\n fetchJsonZodProcessor,\n fetchOkProcessor,\n} from '@atproto-labs/fetch'\nimport { pipe } from '@atproto-labs/pipe'\n\nexport const hcaptchaTokenSchema = z.string().min(1)\nexport type HcaptchaToken = z.infer<typeof hcaptchaTokenSchema>\n\nexport const hcaptchaConfigSchema = z.object({\n /**\n * The hCaptcha site key to use for the sign-up form.\n */\n siteKey: z.string().min(1),\n /**\n * The hCaptcha secret key to use for the sign-up form.\n */\n secretKey: z.string().min(1),\n /**\n * A salt to use when hashing client tokens.\n */\n tokenSalt: z.string().min(1),\n /**\n * The risk score above which the user is considered a threat and will be\n * denied access. This will be ignored if the enterprise features are not\n * available.\n *\n * Note: Score values ranges from 0.0 (no risk) to 1.0 (confirmed threat).\n */\n scoreThreshold: z.number().optional(),\n})\nexport type HcaptchaConfig = z.infer<typeof hcaptchaConfigSchema>\n\n/**\n * @see {@link https://docs.hcaptcha.com/#verify-the-user-response-server-side hCaptcha API}\n */\nexport const hcaptchaVerifyResultSchema = z.object({\n /**\n * is the passcode valid, and does it meet security criteria you specified, e.g. sitekey?\n */\n success: z.boolean(),\n /**\n * timestamp of the challenge (ISO format yyyy-MM-dd'T'HH:mm:ssZZ)\n */\n challenge_ts: z.string(),\n /**\n * the hostname of the site where the challenge was passed\n */\n hostname: z.string().nullable(),\n /**\n * optional: any error codes returned by the hCaptcha API.\n * @see {@link https://docs.hcaptcha.com/#siteverify-error-codes-table}\n */\n 'error-codes': z.array(z.string()).optional(),\n /**\n * ENTERPRISE feature: a score denoting malicious activity. Value ranges from\n * 0.0 (no risk) to 1.0 (confirmed threat).\n */\n score: z.number().optional(),\n /**\n * ENTERPRISE feature: reason(s) for score.\n */\n score_reason: z.array(z.string()).optional(),\n /**\n * sitekey of the request\n */\n sitekey: z.string().optional(),\n /**\n * obj of form: {'ip_device': 1, .. etc}\n */\n behavior_counts: z.record(z.unknown()).optional(),\n /**\n * how similar is this? (0.0 - 1.0, -1 on err)\n */\n similarity: z.number().optional(),\n /**\n * count of similar_tokens not processed\n */\n similarity_failures: z.number().optional(),\n /**\n * array of strings for any similarity errors\n */\n similarity_error_details: z.array(z.string()).optional(),\n /**\n * encoded clientID\n */\n scoped_uid_0: z.string().optional(),\n /**\n * encoded IP\n */\n scoped_uid_1: z.string().optional(),\n /**\n * encoded IP (APT)\n */\n scoped_uid_2: z.string().optional(),\n /**\n * Risk Insights (APT + RI)\n */\n risk_insights: z.record(z.unknown()).optional(),\n /**\n * Advanced Threat Signatures (APT)\n */\n sigs: z.record(z.unknown()).optional(),\n /**\n * tags added via Rules\n */\n tags: z.array(z.string()).optional(),\n})\n\nexport type HcaptchaVerifyResult = z.infer<typeof hcaptchaVerifyResultSchema>\n\nexport type HcaptchaClientTokens = {\n hashedIp: string\n hashedHandle: string\n hashedUserAgent?: string\n}\n\nconst fetchSuccessHandler = pipe(\n fetchOkProcessor(),\n fetchJsonProcessor(),\n fetchJsonZodProcessor(hcaptchaVerifyResultSchema),\n)\n\nexport class HCaptchaClient {\n protected readonly fetch: FetchBound\n constructor(\n readonly hostname: string,\n readonly config: HcaptchaConfig,\n fetch: Fetch = globalThis.fetch,\n ) {\n this.fetch = bindFetch(fetch)\n }\n\n public async verify(\n behaviorType: 'login' | 'signup',\n response: string,\n remoteip: string,\n clientTokens: HcaptchaClientTokens,\n ) {\n return this.fetch('https://api.hcaptcha.com/siteverify', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n secret: this.config.secretKey,\n sitekey: this.config.siteKey,\n behavior_type: behaviorType,\n response,\n remoteip,\n client_tokens: JSON.stringify(clientTokens),\n }).toString(),\n }).then(fetchSuccessHandler)\n }\n\n public checkVerifyResult(\n result: HcaptchaVerifyResult,\n tokens: HcaptchaClientTokens,\n ): void {\n const { success, score } = result\n\n if (success !== true) {\n throw new HCaptchaVerifyError(\n result,\n tokens,\n 'Expected success to be true',\n )\n }\n\n // https://docs.hcaptcha.com/#verify-the-user-response-server-side\n\n // Please [...] note that the hostname field is derived from the user's\n // browser, and should not be used for authentication of any kind; it is\n // primarily useful as a statistical metric. Additionally, in the event that\n // your site experiences unusually high challenge traffic, the hostname\n // field may be returned as \"not-provided\" rather than the usual value; all\n // other fields will return their normal values.\n\n if (\n // Ignore if enterprise feature is not enabled\n score != null &&\n // Ignore if disabled through config\n this.config.scoreThreshold != null &&\n score >= this.config.scoreThreshold\n ) {\n throw new HCaptchaVerifyError(\n result,\n tokens,\n `Score ${score} is above the threshold ${this.config.scoreThreshold}`,\n )\n }\n }\n\n public buildClientTokens(\n remoteip: string,\n handle: string,\n userAgent?: string,\n ): HcaptchaClientTokens {\n return {\n hashedIp: this.hashToken(remoteip),\n hashedHandle: this.hashToken(handle),\n hashedUserAgent: userAgent ? this.hashToken(userAgent) : undefined,\n }\n }\n\n protected hashToken(value: string) {\n const hash = createHash('sha256')\n hash.update(this.config.tokenSalt)\n hash.update(value)\n return hash.digest().toString('base64')\n }\n}\n\nexport class HCaptchaVerifyError extends Error {\n constructor(\n readonly result: HcaptchaVerifyResult,\n readonly tokens: HcaptchaClientTokens,\n message?: string,\n ) {\n super(message)\n }\n}\n"]}
@@ -1,8 +1,5 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.buildDocument = exports.isLinkRel = void 0;
4
- const html_js_1 = require("./html.js");
5
- const tags_js_1 = require("./tags.js");
1
+ import { Html } from './html.js';
2
+ import { html } from './tags.js';
6
3
  /**
7
4
  * @see {@link https://developer.mozilla.org/fr/docs/Web/HTML/Attributes/rel}
8
5
  */
@@ -31,18 +28,17 @@ const ALLOWED_LINK_REL_VALUES = Object.freeze([
31
28
  'stylesheet',
32
29
  'terms-of-service',
33
30
  ]);
34
- const isLinkRel = (rel) => ALLOWED_LINK_REL_VALUES.includes(rel);
35
- exports.isLinkRel = isLinkRel;
36
- const defaultViewport = (0, tags_js_1.html) `<meta
31
+ export const isLinkRel = (rel) => ALLOWED_LINK_REL_VALUES.includes(rel);
32
+ const defaultViewport = html `<meta
37
33
  name="viewport"
38
34
  content="width=device-width, initial-scale=1.0"
39
35
  />`;
40
- const buildDocument = ({ htmlAttrs, head, title, body, bodyAttrs, base, meta, links, preloads, scripts, styles, }) => (0, tags_js_1.html) `<!doctype html>
36
+ export const buildDocument = ({ htmlAttrs, head, title, body, bodyAttrs, base, meta, links, preloads, scripts, styles, }) => html `<!doctype html>
41
37
  <html${attrsToHtml(htmlAttrs)}>
42
38
  <head>
43
39
  <meta charset="UTF-8" />
44
- ${title && (0, tags_js_1.html) `<title>${title}</title>`}
45
- ${base && (0, tags_js_1.html) `<base href="${base.href}" />`}
40
+ ${title && html `<title>${title}</title>`}
41
+ ${base && html `<base href="${base.href}" />`}
46
42
  ${meta?.some(isViewportMeta) ? null : defaultViewport}
47
43
  ${meta?.map(metaToHtml)}
48
44
  ${preloads?.map(linkPreload)}
@@ -52,15 +48,14 @@ const buildDocument = ({ htmlAttrs, head, title, body, bodyAttrs, base, meta, li
52
48
  </head>
53
49
  <body${attrsToHtml(bodyAttrs)}>${body}${scripts?.map(scriptToHtml)}</body>
54
50
  </html>`;
55
- exports.buildDocument = buildDocument;
56
51
  function isViewportMeta(attrs) {
57
52
  return 'name' in attrs && attrs.name === 'viewport';
58
53
  }
59
54
  function linkToHtml(attrs) {
60
- return (0, tags_js_1.html) `<link${attrsToHtml(attrs)} />`;
55
+ return html `<link${attrsToHtml(attrs)} />`;
61
56
  }
62
57
  function metaToHtml(attrs) {
63
- return (0, tags_js_1.html) `<meta${attrsToHtml(attrs)} />`;
58
+ return html `<meta${attrsToHtml(attrs)} />`;
64
59
  }
65
60
  function* attrsToHtml(attrs) {
66
61
  if (attrs) {
@@ -70,36 +65,36 @@ function* attrsToHtml(attrs) {
70
65
  else if (value === false)
71
66
  continue;
72
67
  else if (value === true)
73
- yield (0, tags_js_1.html) ` ${name}`;
68
+ yield html ` ${name}`;
74
69
  else
75
- yield (0, tags_js_1.html) ` ${name}="${value}"`;
70
+ yield html ` ${name}="${value}"`;
76
71
  }
77
72
  }
78
73
  }
79
74
  function linkPreload(asset) {
80
75
  const [path] = asset.url.split('?', 2);
81
76
  if (path.endsWith('.js')) {
82
- return (0, tags_js_1.html) `<link rel="modulepreload" href="${asset.url}" />`;
77
+ return html `<link rel="modulepreload" href="${asset.url}" />`;
83
78
  }
84
79
  if (path.endsWith('.css')) {
85
- return (0, tags_js_1.html) `<link rel="preload" href="${asset.url}" as="style" />`;
80
+ return html `<link rel="preload" href="${asset.url}" as="style" />`;
86
81
  }
87
82
  return undefined;
88
83
  }
89
84
  function scriptToHtml(script) {
90
85
  if (script == null)
91
86
  return undefined;
92
- return script instanceof html_js_1.Html
87
+ return script instanceof Html
93
88
  ? // prettier-ignore
94
- (0, tags_js_1.html) `<script>${script}</script>` // hash validity requires no space around the content
95
- : (0, tags_js_1.html) `<script type="module" src="${script.url}"></script>`;
89
+ html `<script>${script}</script>` // hash validity requires no space around the content
90
+ : html `<script type="module" src="${script.url}"></script>`;
96
91
  }
97
92
  function styleToHtml(style) {
98
93
  if (style == null)
99
94
  return undefined;
100
- return style instanceof html_js_1.Html
95
+ return style instanceof Html
101
96
  ? // prettier-ignore
102
- (0, tags_js_1.html) `<style>${style}</style>` // hash validity requires no space around the content
103
- : (0, tags_js_1.html) `<link rel="stylesheet" href="${style.url}" />`;
97
+ html `<style>${style}</style>` // hash validity requires no space around the content
98
+ : html `<link rel="stylesheet" href="${style.url}" />`;
104
99
  }
105
100
  //# sourceMappingURL=build-document.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"build-document.js","sourceRoot":"","sources":["../../../src/lib/html/build-document.ts"],"names":[],"mappings":"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","sourcesContent":["import { HtmlValue } from './escapers.js'\nimport { Html } from './html.js'\nimport { html } from './tags.js'\n\nexport type AssetRef = {\n url: string\n}\n\nexport type Attrs = Record<string, boolean | string | undefined>\n\n/**\n * @see {@link https://developer.mozilla.org/fr/docs/Web/HTML/Attributes/rel}\n */\nconst ALLOWED_LINK_REL_VALUES = Object.freeze([\n 'alternate',\n 'author',\n 'canonical',\n 'dns-prefetch',\n 'external',\n 'expect',\n 'help',\n 'icon',\n 'license',\n 'manifest',\n 'me',\n 'modulepreload',\n 'next',\n 'pingback',\n 'preconnect',\n 'prefetch',\n 'preload',\n 'prerender',\n 'prev',\n 'privacy-policy',\n 'search',\n 'stylesheet',\n 'terms-of-service',\n] as const)\nexport type LinkRel = (typeof ALLOWED_LINK_REL_VALUES)[number]\nexport const isLinkRel = (rel: unknown): rel is LinkRel =>\n (ALLOWED_LINK_REL_VALUES as readonly unknown[]).includes(rel)\n\nexport type LinkAttrs = Attrs & {\n href: string\n rel: LinkRel\n}\nexport type MetaAttrs =\n | { name: string; content: string }\n | { 'http-equiv': string; content: string }\n\nconst defaultViewport = html`<meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1.0\"\n/>`\n\nexport type BuildDocumentOptions = {\n htmlAttrs?: Attrs\n base?: URL\n meta?: readonly MetaAttrs[]\n links?: readonly LinkAttrs[]\n preloads?: readonly AssetRef[]\n head?: HtmlValue\n title?: HtmlValue\n scripts?: readonly (Html | AssetRef | undefined)[]\n styles?: readonly (Html | AssetRef | undefined)[]\n body?: HtmlValue\n bodyAttrs?: Attrs\n}\n\nexport const buildDocument = ({\n htmlAttrs,\n head,\n title,\n body,\n bodyAttrs,\n base,\n meta,\n links,\n preloads,\n scripts,\n styles,\n}: BuildDocumentOptions) => html`<!doctype html>\n<html${attrsToHtml(htmlAttrs)}>\n <head>\n <meta charset=\"UTF-8\" />\n ${title && html`<title>${title}</title>`}\n ${base && html`<base href=\"${base.href}\" />`}\n ${meta?.some(isViewportMeta) ? null : defaultViewport}\n ${meta?.map(metaToHtml)}\n ${preloads?.map(linkPreload)}\n ${links?.map(linkToHtml)}\n ${head}\n ${styles?.map(styleToHtml)}\n </head>\n <body${attrsToHtml(bodyAttrs)}>${body}${scripts?.map(scriptToHtml)}</body>\n</html>`\n\nfunction isViewportMeta<T extends MetaAttrs>(\n attrs: T,\n): attrs is T & { name: 'viewport' } {\n return 'name' in attrs && attrs.name === 'viewport'\n}\n\nfunction linkToHtml(attrs: LinkAttrs) {\n return html`<link${attrsToHtml(attrs)} />`\n}\n\nfunction metaToHtml(attrs: MetaAttrs) {\n return html`<meta${attrsToHtml(attrs)} />`\n}\n\nfunction* attrsToHtml(attrs?: Attrs) {\n if (attrs) {\n for (const [name, value] of Object.entries(attrs)) {\n if (value == null) continue\n else if (value === false) continue\n else if (value === true) yield html` ${name}`\n else yield html` ${name}=\"${value}\"`\n }\n }\n}\n\nfunction linkPreload(asset: AssetRef) {\n const [path] = asset.url.split('?', 2)\n\n if (path.endsWith('.js')) {\n return html`<link rel=\"modulepreload\" href=\"${asset.url}\" />`\n }\n\n if (path.endsWith('.css')) {\n return html`<link rel=\"preload\" href=\"${asset.url}\" as=\"style\" />`\n }\n\n return undefined\n}\n\nfunction scriptToHtml(script?: Html | AssetRef): Html | undefined {\n if (script == null) return undefined\n return script instanceof Html\n ? // prettier-ignore\n html`<script>${script}</script>` // hash validity requires no space around the content\n : html`<script type=\"module\" src=\"${script.url}\"></script>`\n}\n\nfunction styleToHtml(style?: Html | AssetRef): Html | undefined {\n if (style == null) return undefined\n return style instanceof Html\n ? // prettier-ignore\n html`<style>${style}</style>` // hash validity requires no space around the content\n : html`<link rel=\"stylesheet\" href=\"${style.url}\" />`\n}\n"]}
1
+ {"version":3,"file":"build-document.js","sourceRoot":"","sources":["../../../src/lib/html/build-document.ts"],"names":[],"mappings":"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","sourcesContent":["import { HtmlValue } from './escapers.js'\nimport { Html } from './html.js'\nimport { html } from './tags.js'\n\nexport type AssetRef = {\n url: string\n}\n\nexport type Attrs = Record<string, boolean | string | undefined>\n\n/**\n * @see {@link https://developer.mozilla.org/fr/docs/Web/HTML/Attributes/rel}\n */\nconst ALLOWED_LINK_REL_VALUES = Object.freeze([\n 'alternate',\n 'author',\n 'canonical',\n 'dns-prefetch',\n 'external',\n 'expect',\n 'help',\n 'icon',\n 'license',\n 'manifest',\n 'me',\n 'modulepreload',\n 'next',\n 'pingback',\n 'preconnect',\n 'prefetch',\n 'preload',\n 'prerender',\n 'prev',\n 'privacy-policy',\n 'search',\n 'stylesheet',\n 'terms-of-service',\n] as const)\nexport type LinkRel = (typeof ALLOWED_LINK_REL_VALUES)[number]\nexport const isLinkRel = (rel: unknown): rel is LinkRel =>\n (ALLOWED_LINK_REL_VALUES as readonly unknown[]).includes(rel)\n\nexport type LinkAttrs = Attrs & {\n href: string\n rel: LinkRel\n}\nexport type MetaAttrs =\n | { name: string; content: string }\n | { 'http-equiv': string; content: string }\n\nconst defaultViewport = html`<meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1.0\"\n/>`\n\nexport type BuildDocumentOptions = {\n htmlAttrs?: Attrs\n base?: URL\n meta?: readonly MetaAttrs[]\n links?: readonly LinkAttrs[]\n preloads?: readonly AssetRef[]\n head?: HtmlValue\n title?: HtmlValue\n scripts?: readonly (Html | AssetRef | undefined)[]\n styles?: readonly (Html | AssetRef | undefined)[]\n body?: HtmlValue\n bodyAttrs?: Attrs\n}\n\nexport const buildDocument = ({\n htmlAttrs,\n head,\n title,\n body,\n bodyAttrs,\n base,\n meta,\n links,\n preloads,\n scripts,\n styles,\n}: BuildDocumentOptions) => html`<!doctype html>\n<html${attrsToHtml(htmlAttrs)}>\n <head>\n <meta charset=\"UTF-8\" />\n ${title && html`<title>${title}</title>`}\n ${base && html`<base href=\"${base.href}\" />`}\n ${meta?.some(isViewportMeta) ? null : defaultViewport}\n ${meta?.map(metaToHtml)}\n ${preloads?.map(linkPreload)}\n ${links?.map(linkToHtml)}\n ${head}\n ${styles?.map(styleToHtml)}\n </head>\n <body${attrsToHtml(bodyAttrs)}>${body}${scripts?.map(scriptToHtml)}</body>\n</html>`\n\nfunction isViewportMeta<T extends MetaAttrs>(\n attrs: T,\n): attrs is T & { name: 'viewport' } {\n return 'name' in attrs && attrs.name === 'viewport'\n}\n\nfunction linkToHtml(attrs: LinkAttrs) {\n return html`<link${attrsToHtml(attrs)} />`\n}\n\nfunction metaToHtml(attrs: MetaAttrs) {\n return html`<meta${attrsToHtml(attrs)} />`\n}\n\nfunction* attrsToHtml(attrs?: Attrs) {\n if (attrs) {\n for (const [name, value] of Object.entries(attrs)) {\n if (value == null) continue\n else if (value === false) continue\n else if (value === true) yield html` ${name}`\n else yield html` ${name}=\"${value}\"`\n }\n }\n}\n\nfunction linkPreload(asset: AssetRef) {\n const [path] = asset.url.split('?', 2)\n\n if (path.endsWith('.js')) {\n return html`<link rel=\"modulepreload\" href=\"${asset.url}\" />`\n }\n\n if (path.endsWith('.css')) {\n return html`<link rel=\"preload\" href=\"${asset.url}\" as=\"style\" />`\n }\n\n return undefined\n}\n\nfunction scriptToHtml(script?: Html | AssetRef): Html | undefined {\n if (script == null) return undefined\n return script instanceof Html\n ? // prettier-ignore\n html`<script>${script}</script>` // hash validity requires no space around the content\n : html`<script type=\"module\" src=\"${script.url}\"></script>`\n}\n\nfunction styleToHtml(style?: Html | AssetRef): Html | undefined {\n if (style == null) return undefined\n return style instanceof Html\n ? // prettier-ignore\n html`<style>${style}</style>` // hash validity requires no space around the content\n : html`<link rel=\"stylesheet\" href=\"${style.url}\" />`\n}\n"]}
@@ -1,29 +1,23 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.javascriptEscaper = javascriptEscaper;
4
- exports.jsonEscaper = jsonEscaper;
5
- exports.cssEscaper = cssEscaper;
6
- exports.htmlEscaper = htmlEscaper;
7
- const html_js_1 = require("./html.js");
8
- const util_js_1 = require("./util.js");
9
- function* javascriptEscaper(code) {
1
+ import { Html } from './html.js';
2
+ import { stringReplacer } from './util.js';
3
+ export function* javascriptEscaper(code) {
10
4
  // "</script>" can only appear in javascript strings, so we can safely escape
11
5
  // the "<" without breaking the javascript.
12
- yield* (0, util_js_1.stringReplacer)(code, '</script>', '\\u003c/script>');
6
+ yield* stringReplacer(code, '</script>', '\\u003c/script>');
13
7
  }
14
- function* jsonEscaper(value) {
8
+ export function* jsonEscaper(value) {
15
9
  // https://redux.js.org/usage/server-rendering#security-considerations
16
10
  const json = JSON.stringify(value);
17
11
  if (json === undefined)
18
12
  throw new TypeError('Cannot serialize to JSON');
19
13
  // "<" can only appear in JSON strings, so we can safely escape it without
20
14
  // breaking the JSON.
21
- yield* (0, util_js_1.stringReplacer)(json, '<', '\\u003c');
15
+ yield* stringReplacer(json, '<', '\\u003c');
22
16
  }
23
- function* cssEscaper(css) {
24
- yield* (0, util_js_1.stringReplacer)(css, '</style>', '\\u003c/style>');
17
+ export function* cssEscaper(css) {
18
+ yield* stringReplacer(css, '</style>', '\\u003c/style>');
25
19
  }
26
- function* htmlEscaper(htmlFragments, values) {
20
+ export function* htmlEscaper(htmlFragments, values) {
27
21
  for (let i = 0; i < htmlFragments.length; i++) {
28
22
  yield htmlFragments[i];
29
23
  const value = values[i];
@@ -41,7 +35,7 @@ function* htmlVariableToFragments(value) {
41
35
  else if (typeof value === 'string') {
42
36
  yield encode(value);
43
37
  }
44
- else if (value instanceof html_js_1.Html) {
38
+ else if (value instanceof Html) {
45
39
  yield value;
46
40
  }
47
41
  else {