jxp 4.0.0 → 4.1.1

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 (44) hide show
  1. package/.env.sample +12 -0
  2. package/dist/libs/bulkwrite_guard.d.ts +1 -0
  3. package/dist/libs/bulkwrite_guard.d.ts.map +1 -1
  4. package/dist/libs/bulkwrite_guard.js +43 -0
  5. package/dist/libs/bulkwrite_guard.js.map +1 -1
  6. package/dist/libs/docs-auth.d.ts +25 -0
  7. package/dist/libs/docs-auth.d.ts.map +1 -0
  8. package/dist/libs/docs-auth.js +205 -0
  9. package/dist/libs/docs-auth.js.map +1 -0
  10. package/dist/libs/docs.js +26 -5
  11. package/dist/libs/docs.js.map +1 -1
  12. package/dist/libs/jxp.d.ts.map +1 -1
  13. package/dist/libs/jxp.js +118 -53
  14. package/dist/libs/jxp.js.map +1 -1
  15. package/dist/libs/load-config.d.ts.map +1 -1
  16. package/dist/libs/load-config.js +11 -0
  17. package/dist/libs/load-config.js.map +1 -1
  18. package/dist/libs/login_rate_limit.d.ts +16 -0
  19. package/dist/libs/login_rate_limit.d.ts.map +1 -0
  20. package/dist/libs/login_rate_limit.js +49 -0
  21. package/dist/libs/login_rate_limit.js.map +1 -0
  22. package/dist/libs/query_limits.js +9 -3
  23. package/dist/libs/query_limits.js.map +1 -1
  24. package/dist/libs/request_log.d.ts +44 -0
  25. package/dist/libs/request_log.d.ts.map +1 -0
  26. package/dist/libs/request_log.js +229 -0
  27. package/dist/libs/request_log.js.map +1 -0
  28. package/dist/libs/security.js +18 -9
  29. package/dist/libs/security.js.map +1 -1
  30. package/dist/models/test_model.js +1 -1
  31. package/dist/models/test_model.js.map +1 -1
  32. package/dist/types/jxp-config.d.ts +17 -0
  33. package/dist/types/jxp-config.d.ts.map +1 -1
  34. package/docs/bulk_writes.md +9 -2
  35. package/docs/changelog.md +76 -1
  36. package/docs/configuration.md +30 -0
  37. package/package.json +2 -2
  38. package/templates/assets/api-console.js +19 -1
  39. package/templates/assets/docs-login.js +66 -0
  40. package/templates/assets/docs.css +17 -0
  41. package/templates/index.pug +9 -4
  42. package/templates/layout.pug +8 -4
  43. package/templates/login.pug +39 -0
  44. package/templates/navbar.pug +18 -7
@@ -116,8 +116,26 @@
116
116
  }
117
117
  }
118
118
 
119
+ async function loadSessionApiKey() {
120
+ const access = document.documentElement.dataset.docsAccess;
121
+ if (access !== "protected") return;
122
+ try {
123
+ const res = await fetch("/docs/session", { credentials: "same-origin" });
124
+ if (!res.ok) return;
125
+ const data = await res.json();
126
+ if (!data.apikey) return;
127
+ const input = document.getElementById("docs-api-key");
128
+ if (input) input.value = data.apikey;
129
+ } catch {
130
+ /* ignore */
131
+ }
132
+ }
133
+
119
134
  document.addEventListener("DOMContentLoaded", function () {
120
- loadStoredKey();
135
+ const access = document.documentElement.dataset.docsAccess;
136
+ loadSessionApiKey().then(function () {
137
+ if (access !== "protected") loadStoredKey();
138
+ });
121
139
 
122
140
  const keyInput = document.getElementById("docs-api-key");
123
141
  const remember = document.getElementById("docs-remember-key");
@@ -0,0 +1,66 @@
1
+ (function () {
2
+ "use strict";
3
+
4
+ document.addEventListener("DOMContentLoaded", function () {
5
+ const form = document.getElementById("docs-login-form");
6
+ const errEl = document.getElementById("docs-login-error");
7
+ if (!form || !errEl) return;
8
+
9
+ form.addEventListener("submit", async function (e) {
10
+ e.preventDefault();
11
+ errEl.hidden = true;
12
+ const email = form.email.value.trim();
13
+ const password = form.password.value;
14
+ const next =
15
+ form.next && form.next.value && form.next.value.startsWith("/")
16
+ ? form.next.value
17
+ : "/docs/api";
18
+
19
+ try {
20
+ const loginRes = await fetch("/login", {
21
+ method: "POST",
22
+ headers: {
23
+ "Content-Type": "application/json",
24
+ Accept: "application/json",
25
+ },
26
+ body: JSON.stringify({ email, password }),
27
+ });
28
+ const loginBody = await loginRes.json().catch(function () {
29
+ return {};
30
+ });
31
+ if (loginRes.status === 429) {
32
+ errEl.textContent =
33
+ "Too many login attempts. Please wait a minute and try again.";
34
+ errEl.hidden = false;
35
+ return;
36
+ }
37
+ if (!loginRes.ok || !loginBody.apikey) {
38
+ errEl.textContent =
39
+ loginBody.message || "Incorrect email or password";
40
+ errEl.hidden = false;
41
+ return;
42
+ }
43
+
44
+ const sessRes = await fetch("/docs/session", {
45
+ method: "POST",
46
+ headers: {
47
+ "Content-Type": "application/json",
48
+ Accept: "application/json",
49
+ },
50
+ credentials: "same-origin",
51
+ body: JSON.stringify({ apikey: loginBody.apikey }),
52
+ });
53
+ if (!sessRes.ok) {
54
+ errEl.textContent = "Signed in but could not start docs session";
55
+ errEl.hidden = false;
56
+ return;
57
+ }
58
+
59
+ window.location.href = next;
60
+ } catch {
61
+ errEl.textContent = "Login request failed";
62
+ errEl.hidden = false;
63
+ }
64
+ });
65
+ });
66
+ })();
@@ -225,3 +225,20 @@ body.docs-body {
225
225
  .docs-security-note {
226
226
  font-size: 0.8rem;
227
227
  }
228
+
229
+ .docs-main-full {
230
+ max-width: 480px;
231
+ margin: 0 auto;
232
+ padding-top: 2rem;
233
+ }
234
+
235
+ .docs-login-wrap {
236
+ display: flex;
237
+ justify-content: center;
238
+ padding: 1rem 0 3rem;
239
+ }
240
+
241
+ .docs-login-card {
242
+ width: 100%;
243
+ max-width: 400px;
244
+ }
@@ -18,15 +18,20 @@ block content
18
18
  .card.h-100
19
19
  .card-header.fw-semibold Quick start
20
20
  .card-body
21
- p.mb-2 Authenticate with an API key header (optional for exploring docs; required for live calls):
21
+ p.mb-2 Authenticate with an API key header#{docs_access === 'public' ? ' (optional for exploring docs; required for live calls)' : ''}:
22
22
  pre.mb-3
23
23
  code.
24
24
  curl -H "X-API-Key: YOUR_KEY" \
25
25
  "#{base_url}/api/MODEL?limit=5"
26
26
  p.mb-0.small.text-muted
27
- | Set your key in the top bar to use
28
- strong Try it
29
- | panels on API resource pages. Keys are stored in the browser only when “Remember” is checked.
27
+ if docs_access === 'protected'
28
+ | After signing in, your API key is filled in automatically for
29
+ strong Try it
30
+ | panels on API resource pages.
31
+ else
32
+ | Set your key in the top bar to use
33
+ strong Try it
34
+ | panels on API resource pages. Keys are stored in the browser only when “Remember” is checked.
30
35
  .col-md-6
31
36
  .card.h-100
32
37
  .card-header.fw-semibold API at a glance
@@ -1,5 +1,5 @@
1
1
  doctype html
2
- html(lang="en")
2
+ html(lang="en" data-docs-access=docs_access)
3
3
  head
4
4
  meta(charset="utf-8")
5
5
  meta(name="viewport" content="width=device-width, initial-scale=1")
@@ -9,10 +9,14 @@ html(lang="en")
9
9
  link(rel="stylesheet" href="/docs/assets/docs.css")
10
10
  body.docs-body
11
11
  include navbar
12
- .docs-shell
13
- include sidebar
14
- main.docs-main
12
+ if hide_sidebar
13
+ main.docs-main.docs-main-full
15
14
  block content
15
+ else
16
+ .docs-shell
17
+ include sidebar
18
+ main.docs-main
19
+ block content
16
20
  script(src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous")
17
21
  script(src="/docs/assets/api-console.js" defer)
18
22
  block javascripts
@@ -0,0 +1,39 @@
1
+ extends layout
2
+
3
+ block content
4
+ .docs-login-wrap
5
+ .card.docs-login-card.shadow-sm
6
+ .card-body.p-4
7
+ h1.h4.mb-1 Sign in to explore the API
8
+ p.text-muted.small.mb-4
9
+ | Use your normal API account (
10
+ code POST /login
11
+ | ). Guides and this site stay open; model pages and “Try it” need a session.
12
+ #docs-login-error.alert.alert-danger(role="alert" hidden)
13
+ form#docs-login-form
14
+ input(type="hidden" name="next" value=docs_next)
15
+ .mb-3
16
+ label.form-label(for="docs-login-email") Email
17
+ input#docs-login-email.form-control(
18
+ type="email"
19
+ name="email"
20
+ value=docs_user_email
21
+ required
22
+ autocomplete="username"
23
+ )
24
+ .mb-3
25
+ label.form-label(for="docs-login-password") Password
26
+ input#docs-login-password.form-control(
27
+ type="password"
28
+ name="password"
29
+ required
30
+ autocomplete="current-password"
31
+ )
32
+ button.btn.btn-primary.w-100(type="submit") Sign in
33
+ p.mt-3.mb-0.small.text-muted
34
+ a(href="/") Back to home
35
+ | ·
36
+ a(href="/docs/md/api.md") Read API docs without signing in
37
+
38
+ block javascripts
39
+ script(src="/docs/assets/docs-login.js" defer)
@@ -5,10 +5,21 @@ header.docs-topbar.navbar.navbar-expand-lg.sticky-top
5
5
  a.docs-brand.navbar-brand.mb-0(href="/")= name
6
6
  span.badge.bg-secondary.ms-2.align-self-center v#{version}
7
7
  .ms-auto.d-flex.align-items-center.gap-2.flex-wrap
8
- .docs-api-key-wrap
9
- label.visually-hidden(for="docs-api-key") API Key
10
- input#docs-api-key.form-control.form-control-sm(type="password" placeholder="X-API-Key (optional)" autocomplete="off")
11
- .form-check.form-check-inline.mb-0.docs-security-note
12
- input#docs-remember-key.form-check-input(type="checkbox")
13
- label.form-check-label(for="docs-remember-key") Remember
14
- span.docs-security-note.text-muted.d-none.d-md-inline Dev only
8
+ if docs_access === 'protected' && !docs_authenticated
9
+ a.btn.btn-sm.btn-outline-primary(href="/docs/login?next=/docs/api") Explore API
10
+ if docs_access !== 'disabled' && (docs_access !== 'protected' || docs_authenticated)
11
+ .docs-api-key-wrap
12
+ label.visually-hidden(for="docs-api-key") API Key
13
+ input#docs-api-key.form-control.form-control-sm(
14
+ type="password"
15
+ placeholder=docs_access === 'protected' ? "X-API-Key" : "X-API-Key (optional)"
16
+ autocomplete="off"
17
+ )
18
+ .form-check.form-check-inline.mb-0.docs-security-note
19
+ input#docs-remember-key.form-check-input(type="checkbox")
20
+ label.form-check-label(for="docs-remember-key") Remember
21
+ if docs_access === 'protected'
22
+ form.d-inline(method="post" action="/docs/logout")
23
+ button.btn.btn-sm.btn-link.text-muted(type="submit") Sign out
24
+ else
25
+ span.docs-security-note.text-muted.d-none.d-md-inline Dev only