@forumulate/cli 0.9.0 → 0.10.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 (224) hide show
  1. package/README.md +3 -3
  2. package/dist/api/args.d.ts.map +1 -1
  3. package/dist/api/args.js +1 -0
  4. package/dist/api/args.js.map +1 -1
  5. package/dist/api/command.d.ts +1 -1
  6. package/dist/api/command.d.ts.map +1 -1
  7. package/dist/api/command.js +86 -11
  8. package/dist/api/command.js.map +1 -1
  9. package/dist/api/http.d.ts +8 -0
  10. package/dist/api/http.d.ts.map +1 -1
  11. package/dist/api/http.js +3 -2
  12. package/dist/api/http.js.map +1 -1
  13. package/dist/api/live-spec.d.ts +48 -0
  14. package/dist/api/live-spec.d.ts.map +1 -0
  15. package/dist/api/live-spec.js +72 -0
  16. package/dist/api/live-spec.js.map +1 -0
  17. package/dist/api/operations.json +1 -1
  18. package/dist/api/request.d.ts.map +1 -1
  19. package/dist/api/request.js +25 -1
  20. package/dist/api/request.js.map +1 -1
  21. package/dist/api/send.d.ts +10 -1
  22. package/dist/api/send.d.ts.map +1 -1
  23. package/dist/api/send.js +14 -3
  24. package/dist/api/send.js.map +1 -1
  25. package/dist/api/slim.d.ts +14 -0
  26. package/dist/api/slim.d.ts.map +1 -0
  27. package/dist/api/slim.js +174 -0
  28. package/dist/api/slim.js.map +1 -0
  29. package/dist/cache-command.d.ts +12 -0
  30. package/dist/cache-command.d.ts.map +1 -0
  31. package/dist/cache-command.js +93 -0
  32. package/dist/cache-command.js.map +1 -0
  33. package/dist/check/command.d.ts +48 -0
  34. package/dist/check/command.d.ts.map +1 -0
  35. package/dist/check/command.js +256 -0
  36. package/dist/check/command.js.map +1 -0
  37. package/dist/check/external.d.ts +66 -0
  38. package/dist/check/external.d.ts.map +1 -0
  39. package/dist/check/external.js +177 -0
  40. package/dist/check/external.js.map +1 -0
  41. package/dist/check/markdown-links.d.ts +38 -0
  42. package/dist/check/markdown-links.d.ts.map +1 -0
  43. package/dist/check/markdown-links.js +166 -0
  44. package/dist/check/markdown-links.js.map +1 -0
  45. package/dist/cli.js +42 -7
  46. package/dist/cli.js.map +1 -1
  47. package/dist/commands/completion.d.ts.map +1 -1
  48. package/dist/commands/completion.js +1 -0
  49. package/dist/commands/completion.js.map +1 -1
  50. package/dist/commands/context.d.ts.map +1 -1
  51. package/dist/commands/context.js +6 -2
  52. package/dist/commands/context.js.map +1 -1
  53. package/dist/commands/groups-api.d.ts.map +1 -1
  54. package/dist/commands/groups-api.js +20 -2
  55. package/dist/commands/groups-api.js.map +1 -1
  56. package/dist/commands/groups-docs.d.ts.map +1 -1
  57. package/dist/commands/groups-docs.js +8 -2
  58. package/dist/commands/groups-docs.js.map +1 -1
  59. package/dist/commands/groups-jobs.d.ts +10 -0
  60. package/dist/commands/groups-jobs.d.ts.map +1 -0
  61. package/dist/commands/groups-jobs.js +89 -0
  62. package/dist/commands/groups-jobs.js.map +1 -0
  63. package/dist/commands/groups-org.d.ts.map +1 -1
  64. package/dist/commands/groups-org.js +59 -2
  65. package/dist/commands/groups-org.js.map +1 -1
  66. package/dist/commands/groups-site.d.ts.map +1 -1
  67. package/dist/commands/groups-site.js +33 -3
  68. package/dist/commands/groups-site.js.map +1 -1
  69. package/dist/commands/groups-spaces.d.ts.map +1 -1
  70. package/dist/commands/groups-spaces.js +11 -5
  71. package/dist/commands/groups-spaces.js.map +1 -1
  72. package/dist/commands/groups-types.d.ts.map +1 -1
  73. package/dist/commands/groups-types.js +74 -0
  74. package/dist/commands/groups-types.js.map +1 -1
  75. package/dist/commands/groups.d.ts.map +1 -1
  76. package/dist/commands/groups.js +2 -0
  77. package/dist/commands/groups.js.map +1 -1
  78. package/dist/commands/index.d.ts +9 -0
  79. package/dist/commands/index.d.ts.map +1 -1
  80. package/dist/commands/index.js +18 -3
  81. package/dist/commands/index.js.map +1 -1
  82. package/dist/commands/job-wait.d.ts +64 -0
  83. package/dist/commands/job-wait.d.ts.map +1 -0
  84. package/dist/commands/job-wait.js +91 -0
  85. package/dist/commands/job-wait.js.map +1 -0
  86. package/dist/commands/resource.d.ts +19 -0
  87. package/dist/commands/resource.d.ts.map +1 -1
  88. package/dist/commands/resource.js +65 -3
  89. package/dist/commands/resource.js.map +1 -1
  90. package/dist/content/library.d.ts +8 -0
  91. package/dist/content/library.d.ts.map +1 -1
  92. package/dist/content/library.js +10 -2
  93. package/dist/content/library.js.map +1 -1
  94. package/dist/credentials.d.ts +43 -4
  95. package/dist/credentials.d.ts.map +1 -1
  96. package/dist/credentials.js +67 -4
  97. package/dist/credentials.js.map +1 -1
  98. package/dist/doctor/address-checks.d.ts +56 -0
  99. package/dist/doctor/address-checks.d.ts.map +1 -0
  100. package/dist/doctor/address-checks.js +183 -0
  101. package/dist/doctor/address-checks.js.map +1 -0
  102. package/dist/doctor/boilerplate.d.ts +33 -0
  103. package/dist/doctor/boilerplate.d.ts.map +1 -0
  104. package/dist/doctor/boilerplate.js +78 -0
  105. package/dist/doctor/boilerplate.js.map +1 -0
  106. package/dist/doctor/command.d.ts +18 -0
  107. package/dist/doctor/command.d.ts.map +1 -0
  108. package/dist/doctor/command.js +234 -0
  109. package/dist/doctor/command.js.map +1 -0
  110. package/dist/doctor/crawl.d.ts +49 -0
  111. package/dist/doctor/crawl.d.ts.map +1 -0
  112. package/dist/doctor/crawl.js +210 -0
  113. package/dist/doctor/crawl.js.map +1 -0
  114. package/dist/doctor/extended.d.ts +52 -0
  115. package/dist/doctor/extended.d.ts.map +1 -0
  116. package/dist/doctor/extended.js +150 -0
  117. package/dist/doctor/extended.js.map +1 -0
  118. package/dist/doctor/page-checks.d.ts +42 -0
  119. package/dist/doctor/page-checks.d.ts.map +1 -0
  120. package/dist/doctor/page-checks.js +200 -0
  121. package/dist/doctor/page-checks.js.map +1 -0
  122. package/dist/doctor/probe.d.ts +63 -0
  123. package/dist/doctor/probe.d.ts.map +1 -0
  124. package/dist/doctor/probe.js +170 -0
  125. package/dist/doctor/probe.js.map +1 -0
  126. package/dist/doctor/reader-auth-atlas.d.ts +18 -0
  127. package/dist/doctor/reader-auth-atlas.d.ts.map +1 -0
  128. package/dist/doctor/reader-auth-atlas.js +50 -0
  129. package/dist/doctor/reader-auth-atlas.js.map +1 -0
  130. package/dist/doctor/robots-params.d.ts +36 -0
  131. package/dist/doctor/robots-params.d.ts.map +1 -0
  132. package/dist/doctor/robots-params.js +97 -0
  133. package/dist/doctor/robots-params.js.map +1 -0
  134. package/dist/doctor/site.d.ts +42 -0
  135. package/dist/doctor/site.d.ts.map +1 -0
  136. package/dist/doctor/site.js +82 -0
  137. package/dist/doctor/site.js.map +1 -0
  138. package/dist/doctor.d.ts +21 -0
  139. package/dist/doctor.d.ts.map +1 -1
  140. package/dist/doctor.js +94 -3
  141. package/dist/doctor.js.map +1 -1
  142. package/dist/exit-codes.d.ts +40 -0
  143. package/dist/exit-codes.d.ts.map +1 -0
  144. package/dist/exit-codes.js +66 -0
  145. package/dist/exit-codes.js.map +1 -0
  146. package/dist/help-commands.d.ts +13 -0
  147. package/dist/help-commands.d.ts.map +1 -0
  148. package/dist/help-commands.js +215 -0
  149. package/dist/help-commands.js.map +1 -0
  150. package/dist/help.d.ts +1 -1
  151. package/dist/help.d.ts.map +1 -1
  152. package/dist/help.js +57 -11
  153. package/dist/help.js.map +1 -1
  154. package/dist/io.d.ts +33 -0
  155. package/dist/io.d.ts.map +1 -0
  156. package/dist/io.js +81 -0
  157. package/dist/io.js.map +1 -0
  158. package/dist/preview-comment.d.ts +20 -0
  159. package/dist/preview-comment.d.ts.map +1 -0
  160. package/dist/preview-comment.js +88 -0
  161. package/dist/preview-comment.js.map +1 -0
  162. package/dist/publish/about.d.ts +23 -0
  163. package/dist/publish/about.d.ts.map +1 -0
  164. package/dist/publish/about.js +66 -0
  165. package/dist/publish/about.js.map +1 -0
  166. package/dist/publish/command.d.ts +20 -0
  167. package/dist/publish/command.d.ts.map +1 -1
  168. package/dist/publish/command.js +97 -4
  169. package/dist/publish/command.js.map +1 -1
  170. package/dist/publish/context.d.ts +8 -0
  171. package/dist/publish/context.d.ts.map +1 -1
  172. package/dist/publish/context.js.map +1 -1
  173. package/dist/publish/docs-apply.d.ts.map +1 -1
  174. package/dist/publish/docs-apply.js +13 -1
  175. package/dist/publish/docs-apply.js.map +1 -1
  176. package/dist/publish/extras.d.ts +10 -0
  177. package/dist/publish/extras.d.ts.map +1 -1
  178. package/dist/publish/extras.js +54 -2
  179. package/dist/publish/extras.js.map +1 -1
  180. package/dist/publish/manifest.d.ts.map +1 -1
  181. package/dist/publish/manifest.js +27 -2
  182. package/dist/publish/manifest.js.map +1 -1
  183. package/dist/publish/preview.d.ts +56 -0
  184. package/dist/publish/preview.d.ts.map +1 -0
  185. package/dist/publish/preview.js +133 -0
  186. package/dist/publish/preview.js.map +1 -0
  187. package/dist/publish/redirects.d.ts +13 -0
  188. package/dist/publish/redirects.d.ts.map +1 -0
  189. package/dist/publish/redirects.js +154 -0
  190. package/dist/publish/redirects.js.map +1 -0
  191. package/dist/publish/studio-edits.d.ts +25 -0
  192. package/dist/publish/studio-edits.d.ts.map +1 -0
  193. package/dist/publish/studio-edits.js +53 -0
  194. package/dist/publish/studio-edits.js.map +1 -0
  195. package/dist/publish/types.d.ts +22 -1
  196. package/dist/publish/types.d.ts.map +1 -1
  197. package/dist/publish-command.d.ts +55 -0
  198. package/dist/publish-command.d.ts.map +1 -0
  199. package/dist/publish-command.js +197 -0
  200. package/dist/publish-command.js.map +1 -0
  201. package/dist/run.d.ts +3 -10
  202. package/dist/run.d.ts.map +1 -1
  203. package/dist/run.js +122 -110
  204. package/dist/run.js.map +1 -1
  205. package/dist/translations/target.d.ts.map +1 -1
  206. package/dist/translations/target.js +2 -2
  207. package/dist/translations/target.js.map +1 -1
  208. package/dist/validate.d.ts +39 -0
  209. package/dist/validate.d.ts.map +1 -0
  210. package/dist/validate.js +166 -0
  211. package/dist/validate.js.map +1 -0
  212. package/dist/version.d.ts +8 -0
  213. package/dist/version.d.ts.map +1 -0
  214. package/dist/version.js +11 -0
  215. package/dist/version.js.map +1 -0
  216. package/dist/whoami.d.ts +41 -0
  217. package/dist/whoami.d.ts.map +1 -0
  218. package/dist/whoami.js +161 -0
  219. package/dist/whoami.js.map +1 -0
  220. package/package.json +2 -2
  221. package/dist/publish-dir.d.ts +0 -54
  222. package/dist/publish-dir.d.ts.map +0 -1
  223. package/dist/publish-dir.js +0 -119
  224. package/dist/publish-dir.js.map +0 -1
@@ -0,0 +1,170 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.attr = exports.DEFAULT_TIMEOUT_MS = void 0;
4
+ exports.makeGet = makeGet;
5
+ exports.pool = pool;
6
+ exports.follow = follow;
7
+ exports.tags = tags;
8
+ exports.canonicalOf = canonicalOf;
9
+ exports.metaOf = metaOf;
10
+ exports.htmlLang = htmlLang;
11
+ exports.decodeEntities = decodeEntities;
12
+ exports.hostOf = hostOf;
13
+ exports.sameUrl = sameUrl;
14
+ exports.describeProbe = describeProbe;
15
+ exports.check = check;
16
+ exports.some = some;
17
+ exports.DEFAULT_TIMEOUT_MS = 15_000;
18
+ function makeGet(opts) {
19
+ const timeoutMs = opts.timeoutMs ?? exports.DEFAULT_TIMEOUT_MS;
20
+ return async (url, headers = {}) => {
21
+ const ctl = typeof AbortController === 'function' ? new AbortController() : undefined;
22
+ const timer = ctl ? setTimeout(() => ctl.abort(), timeoutMs) : undefined;
23
+ try {
24
+ const res = await opts.fetchImpl(url, {
25
+ headers,
26
+ redirect: 'manual',
27
+ ...(ctl ? { signal: ctl.signal } : {}),
28
+ });
29
+ const text = await res.text();
30
+ return { ok: true, url, status: res.status, headers: res.headers, text };
31
+ }
32
+ catch (e) {
33
+ const aborted = e instanceof Error && e.name === 'AbortError';
34
+ return {
35
+ ok: false,
36
+ url,
37
+ error: aborted
38
+ ? `no answer within ${timeoutMs} ms`
39
+ : e instanceof Error
40
+ ? e.message
41
+ : String(e),
42
+ };
43
+ }
44
+ finally {
45
+ if (timer)
46
+ clearTimeout(timer);
47
+ }
48
+ };
49
+ }
50
+ /**
51
+ * Run `fn` over `items`, at most `limit` at a time, in input order.
52
+ *
53
+ * Bounded on purpose: the doctor runs from a laptop or a CI runner against a
54
+ * customer's production site, and a hundred simultaneous requests is how a
55
+ * health check becomes the incident it was meant to catch.
56
+ */
57
+ async function pool(items, limit, fn) {
58
+ const out = new Array(items.length);
59
+ let next = 0;
60
+ const workers = Array.from({ length: Math.max(1, Math.min(limit, items.length)) }, async () => {
61
+ while (next < items.length) {
62
+ const i = next++;
63
+ out[i] = await fn(items[i]);
64
+ }
65
+ });
66
+ await Promise.all(workers);
67
+ return out;
68
+ }
69
+ /** Follow redirects by hand (bounded), keeping every hop — the hops are what a check judges. */
70
+ async function follow(get, url, headers = {}, maxHops = 5) {
71
+ const hops = [];
72
+ let at = url;
73
+ for (let i = 0; i <= maxHops; i++) {
74
+ const p = await get(at, headers);
75
+ hops.push(p);
76
+ if (!p.ok || p.status < 300 || p.status >= 400)
77
+ return { hops, final: p };
78
+ const loc = p.headers.get('location');
79
+ if (!loc)
80
+ return { hops, final: p };
81
+ at = new URL(loc, at).toString();
82
+ }
83
+ return { hops, final: hops[hops.length - 1] };
84
+ }
85
+ /** One attribute's value from one tag's source, quoted or not. */
86
+ function attrOf(tag, name) {
87
+ const m = new RegExp(`\\b${name}\\s*=\\s*(?:"([^"]*)"|'([^']*)'|([^\\s>]+))`, 'i').exec(tag);
88
+ return m ? (m[1] ?? m[2] ?? m[3]) : undefined;
89
+ }
90
+ function tags(html, name) {
91
+ return html.match(new RegExp(`<${name}\\b[^>]*>`, 'gi')) ?? [];
92
+ }
93
+ exports.attr = attrOf;
94
+ /** `<link rel="canonical">`, absolute against `base`, or undefined. */
95
+ function canonicalOf(html, base) {
96
+ for (const t of tags(html, 'link')) {
97
+ const rel = (attrOf(t, 'rel') ?? '').toLowerCase().split(/\s+/);
98
+ if (!rel.includes('canonical'))
99
+ continue;
100
+ const href = attrOf(t, 'href');
101
+ if (!href)
102
+ continue;
103
+ try {
104
+ return new URL(decodeEntities(href), base).toString();
105
+ }
106
+ catch {
107
+ return href;
108
+ }
109
+ }
110
+ return undefined;
111
+ }
112
+ /** `<meta name|property=X content=…>`. */
113
+ function metaOf(html, key) {
114
+ for (const t of tags(html, 'meta')) {
115
+ const k = (attrOf(t, 'name') ?? attrOf(t, 'property') ?? '').toLowerCase();
116
+ if (k === key.toLowerCase())
117
+ return decodeEntities(attrOf(t, 'content') ?? '');
118
+ }
119
+ return undefined;
120
+ }
121
+ /** The document's declared language (`<html lang>`), lower-cased, or undefined. */
122
+ function htmlLang(html) {
123
+ const t = tags(html, 'html')[0];
124
+ return t ? attrOf(t, 'lang')?.toLowerCase() : undefined;
125
+ }
126
+ function decodeEntities(s) {
127
+ return s
128
+ .replace(/&amp;/g, '&')
129
+ .replace(/&quot;/g, '"')
130
+ .replace(/&#x27;|&#39;/g, "'")
131
+ .replace(/&lt;/g, '<')
132
+ .replace(/&gt;/g, '>');
133
+ }
134
+ function hostOf(href) {
135
+ try {
136
+ return new URL(href).host.toLowerCase();
137
+ }
138
+ catch {
139
+ return undefined;
140
+ }
141
+ }
142
+ /** Compare two URLs the way a search engine would: no fragment, no trailing slash. */
143
+ function sameUrl(a, b) {
144
+ if (!a || !b)
145
+ return false;
146
+ const norm = (u) => {
147
+ try {
148
+ const x = new URL(u);
149
+ x.hash = '';
150
+ return `${x.protocol}//${x.host.toLowerCase()}${x.pathname.replace(/\/+$/, '') || '/'}${x.search}`;
151
+ }
152
+ catch {
153
+ return u;
154
+ }
155
+ };
156
+ return norm(a) === norm(b);
157
+ }
158
+ function describeProbe(p) {
159
+ return p.ok ? `${p.status}` : p.error;
160
+ }
161
+ /** A check under construction: the shape `runDoctor` reports. */
162
+ function check(id, title, state, detail, matters = '') {
163
+ return { id, title, state, detail, matters };
164
+ }
165
+ /** At most `n` items of a list in a detail line, and how many were left out. */
166
+ function some(list, n = 5) {
167
+ const shown = list.slice(0, n).join('; ');
168
+ return list.length > n ? `${shown}; …and ${list.length - n} more` : shown;
169
+ }
170
+ //# sourceMappingURL=probe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"probe.js","sourceRoot":"","sources":["../../src/doctor/probe.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { Check } from '../conformance';
2
+ import type { Http } from '../api/http';
3
+ export declare const READER_AUTH_ATLAS_CHECK = "reader-auth-atlas";
4
+ /**
5
+ * `reader-auth-atlas` (FMU-X01): does this organization sign its readers in
6
+ * the recommended way?
7
+ *
8
+ * The rule is the API's, not the CLI's: `GET /orgs/{org}/reader-auth`
9
+ * answers `recommendations`, computed from the org's own configuration (an
10
+ * Atlas issuer on an `external_jwt` provider, a linked Atlas instance), and
11
+ * the manifest plan answers the same list. This prints what it says.
12
+ *
13
+ * Advice, like `robots-params`: a recommendation is a SKIP with the steps,
14
+ * never a FAIL, because signing readers in from your own app is a supported
15
+ * setup and a scheduled doctor must not fail CI over it.
16
+ */
17
+ export declare function readerAuthAtlasCheck(http: Http, org: string): Promise<Check>;
18
+ //# sourceMappingURL=reader-auth-atlas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reader-auth-atlas.d.ts","sourceRoot":"","sources":["../../src/doctor/reader-auth-atlas.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAGxC,eAAO,MAAM,uBAAuB,sBAAsB,CAAC;AAe3D;;;;;;;;;;;;GAYG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAsClF"}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.READER_AUTH_ATLAS_CHECK = void 0;
4
+ exports.readerAuthAtlasCheck = readerAuthAtlasCheck;
5
+ const probe_1 = require("./probe");
6
+ exports.READER_AUTH_ATLAS_CHECK = 'reader-auth-atlas';
7
+ const TITLE = 'Readers sign in with the Atlas reader provider when the organization uses Atlas';
8
+ const MATTERS = 'A hand-rolled external_jwt route is code you maintain that the Atlas provider does for you: Forumulate verifies Atlas’s own reader token and keys members on (iss, sub).';
9
+ /**
10
+ * `reader-auth-atlas` (FMU-X01): does this organization sign its readers in
11
+ * the recommended way?
12
+ *
13
+ * The rule is the API's, not the CLI's: `GET /orgs/{org}/reader-auth`
14
+ * answers `recommendations`, computed from the org's own configuration (an
15
+ * Atlas issuer on an `external_jwt` provider, a linked Atlas instance), and
16
+ * the manifest plan answers the same list. This prints what it says.
17
+ *
18
+ * Advice, like `robots-params`: a recommendation is a SKIP with the steps,
19
+ * never a FAIL, because signing readers in from your own app is a supported
20
+ * setup and a scheduled doctor must not fail CI over it.
21
+ */
22
+ async function readerAuthAtlasCheck(http, org) {
23
+ let body;
24
+ try {
25
+ body = (await http.send({ method: 'GET', path: `/orgs/${encodeURIComponent(org)}/reader-auth` }))
26
+ .data;
27
+ }
28
+ catch (e) {
29
+ const err = e;
30
+ return (0, probe_1.check)(exports.READER_AUTH_ATLAS_CHECK, TITLE, 'skip', `Could not read the organization's reader sign-in (${err.status ?? 'error'}): it needs a token with org.manage_settings.`, '');
31
+ }
32
+ const rec = (body.recommendations ?? []).find((r) => r.code === 'reader_auth.use_atlas');
33
+ if (!rec) {
34
+ const methods = (body.providers ?? []).map((p) => p.method);
35
+ return (0, probe_1.check)(exports.READER_AUTH_ATLAS_CHECK, TITLE, 'pass', methods.includes('atlas_byo')
36
+ ? 'atlas_byo is configured.'
37
+ : `Nothing to recommend${methods.length ? ` (${methods.join(', ')})` : ''}.`, '');
38
+ }
39
+ const lines = [
40
+ `Recommended — ${rec.message}`,
41
+ rec.relink
42
+ ? ` 1. Relink the members: POST /orgs/${org}/members/relink ${JSON.stringify({ from: rec.relink.from, to: rec.relink.to })} (dry run first; ?apply=true writes)`
43
+ : null,
44
+ ` ${rec.relink ? '2' : '1'}. Switch: PATCH /orgs/${org}/reader-auth ${JSON.stringify(rec.patch)}`,
45
+ ` or in a manifest (version 2): ${JSON.stringify(rec.manifest)}`,
46
+ rec.docs ? ` See ${rec.docs}` : null,
47
+ ].filter((l) => l !== null);
48
+ return (0, probe_1.check)(exports.READER_AUTH_ATLAS_CHECK, TITLE, 'skip', lines.join('\n'), MATTERS);
49
+ }
50
+ //# sourceMappingURL=reader-auth-atlas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reader-auth-atlas.js","sourceRoot":"","sources":["../../src/doctor/reader-auth-atlas.ts"],"names":[],"mappings":";;;AAgCA,oDAsCC;AApED,mCAAgC;AAEnB,QAAA,uBAAuB,GAAG,mBAAmB,CAAC;AAE3D,MAAM,KAAK,GAAG,iFAAiF,CAAC;AAChG,MAAM,OAAO,GACX,0KAA0K,CAAC;AAW7K;;;;;;;;;;;;GAYG;AACI,KAAK,UAAU,oBAAoB,CAAC,IAAU,EAAE,GAAW;IAChE,IAAI,IAA8E,CAAC;IACnF,IAAI,CAAC;QACH,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,kBAAkB,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC;aAC9F,IAAmB,CAAC;IACzB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,GAAG,GAAG,CAA0C,CAAC;QACvD,OAAO,IAAA,aAAK,EACV,+BAAuB,EACvB,KAAK,EACL,MAAM,EACN,qDAAqD,GAAG,CAAC,MAAM,IAAI,OAAO,+CAA+C,EACzH,EAAE,CACH,CAAC;IACJ,CAAC;IACD,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,uBAAuB,CAAC,CAAC;IACzF,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QAC5D,OAAO,IAAA,aAAK,EACV,+BAAuB,EACvB,KAAK,EACL,MAAM,EACN,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;YAC3B,CAAC,CAAC,0BAA0B;YAC5B,CAAC,CAAC,uBAAuB,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAC9E,EAAE,CACH,CAAC;IACJ,CAAC;IACD,MAAM,KAAK,GAAG;QACZ,iBAAiB,GAAG,CAAC,OAAO,EAAE;QAC9B,GAAG,CAAC,MAAM;YACR,CAAC,CAAC,uCAAuC,GAAG,mBAAmB,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,sCAAsC;YACjK,CAAC,CAAC,IAAI;QACR,KAAK,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,yBAAyB,GAAG,gBAAgB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;QAClG,sCAAsC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;QACpE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI;KACtC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;IACzC,OAAO,IAAA,aAAK,EAAC,+BAAuB,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;AAClF,CAAC"}
@@ -0,0 +1,36 @@
1
+ import type { Check } from '../conformance';
2
+ /**
3
+ * `robots-params`: the `Disallow` lines that keep crawlers off the re-cut
4
+ * addresses of a mounted space's lists (SEO spec §1, item 5).
5
+ *
6
+ * A reader page offers its sort, order, scope, period, filter, solved and
7
+ * range choices as GET forms, which crawlers do not submit — but an address
8
+ * already in a crawler's queue, a backlink, or another site's
9
+ * `?sort=name&order=desc` link still reaches it. Those copies say `noindex`
10
+ * (or name the uncut page as canonical), and are still a crawl each. The host's
11
+ * robots.txt is the one place that can say "do not even fetch these", and for
12
+ * a space mounted on somebody else's domain (`acme.com/community`) it is THEIR
13
+ * file — we cannot write it. So the doctor prints the lines to paste.
14
+ *
15
+ * Advisory, never a failure: a site that wants those copies crawled is making
16
+ * a choice. Passes once every line for this host is already in its robots.txt.
17
+ * Judged by HTTP alone, so it is the same for any host the doctor is pointed at.
18
+ */
19
+ /**
20
+ * The query keys a reader list is re-cut by — the web reader's
21
+ * `VARIANT_PARAMS` (apps/web/src/lib/reader-variant-robots.ts). Never `page`
22
+ * (a page of a list is a document of its own) and never a search.
23
+ */
24
+ export declare const VARIANT_PARAMS: readonly ["sort", "order", "scope", "period", "window", "filter", "solved", "range", "replies", "release"];
25
+ /**
26
+ * The lines for one mount. `*` and the `?` are robots wildcards (RFC 9309 §2.2.3
27
+ * — Google, Bing and every major crawler read them): `/community*?*sort=` is any
28
+ * address under the mount whose query names `sort`, first or not.
29
+ */
30
+ export declare function disallowLines(mountPath: string): string[];
31
+ /** The roots grouped by the origin whose robots.txt would carry them. */
32
+ export declare function linesByOrigin(roots: readonly string[]): Map<string, string[]>;
33
+ export declare function robotsParams(roots: readonly string[],
34
+ /** The origin whose robots.txt was read. */
35
+ origin: string, robots: string | undefined): Check;
36
+ //# sourceMappingURL=robots-params.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"robots-params.d.ts","sourceRoot":"","sources":["../../src/doctor/robots-params.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAG5C;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;GAIG;AACH,eAAO,MAAM,cAAc,4GAWjB,CAAC;AAEX;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAIzD;AAED,yEAAyE;AACzE,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAc7E;AAUD,wBAAgB,YAAY,CAC1B,KAAK,EAAE,SAAS,MAAM,EAAE;AACxB,4CAA4C;AAC5C,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GAAG,SAAS,GACzB,KAAK,CAuBP"}
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VARIANT_PARAMS = void 0;
4
+ exports.disallowLines = disallowLines;
5
+ exports.linesByOrigin = linesByOrigin;
6
+ exports.robotsParams = robotsParams;
7
+ const probe_1 = require("./probe");
8
+ /**
9
+ * `robots-params`: the `Disallow` lines that keep crawlers off the re-cut
10
+ * addresses of a mounted space's lists (SEO spec §1, item 5).
11
+ *
12
+ * A reader page offers its sort, order, scope, period, filter, solved and
13
+ * range choices as GET forms, which crawlers do not submit — but an address
14
+ * already in a crawler's queue, a backlink, or another site's
15
+ * `?sort=name&order=desc` link still reaches it. Those copies say `noindex`
16
+ * (or name the uncut page as canonical), and are still a crawl each. The host's
17
+ * robots.txt is the one place that can say "do not even fetch these", and for
18
+ * a space mounted on somebody else's domain (`acme.com/community`) it is THEIR
19
+ * file — we cannot write it. So the doctor prints the lines to paste.
20
+ *
21
+ * Advisory, never a failure: a site that wants those copies crawled is making
22
+ * a choice. Passes once every line for this host is already in its robots.txt.
23
+ * Judged by HTTP alone, so it is the same for any host the doctor is pointed at.
24
+ */
25
+ /**
26
+ * The query keys a reader list is re-cut by — the web reader's
27
+ * `VARIANT_PARAMS` (apps/web/src/lib/reader-variant-robots.ts). Never `page`
28
+ * (a page of a list is a document of its own) and never a search.
29
+ */
30
+ exports.VARIANT_PARAMS = [
31
+ 'sort',
32
+ 'order',
33
+ 'scope',
34
+ 'period',
35
+ 'window',
36
+ 'filter',
37
+ 'solved',
38
+ 'range',
39
+ 'replies',
40
+ 'release',
41
+ ];
42
+ /**
43
+ * The lines for one mount. `*` and the `?` are robots wildcards (RFC 9309 §2.2.3
44
+ * — Google, Bing and every major crawler read them): `/community*?*sort=` is any
45
+ * address under the mount whose query names `sort`, first or not.
46
+ */
47
+ function disallowLines(mountPath) {
48
+ const mount = mountPath.replace(/\/+$/, '');
49
+ const at = mount ? `${mount}*` : '/*';
50
+ return exports.VARIANT_PARAMS.map((p) => `Disallow: ${at}?*${p}=`);
51
+ }
52
+ /** The roots grouped by the origin whose robots.txt would carry them. */
53
+ function linesByOrigin(roots) {
54
+ const out = new Map();
55
+ for (const root of roots) {
56
+ let u;
57
+ try {
58
+ u = new URL(root);
59
+ }
60
+ catch {
61
+ continue;
62
+ }
63
+ const list = out.get(u.origin) ?? [];
64
+ for (const l of disallowLines(u.pathname))
65
+ if (!list.includes(l))
66
+ list.push(l);
67
+ out.set(u.origin, list);
68
+ }
69
+ return out;
70
+ }
71
+ /** Does robots.txt already say `line` (any case, any spacing after the colon)? */
72
+ function has(robots, line) {
73
+ const want = line.replace(/^disallow:\s*/i, '').trim();
74
+ return robots
75
+ .split(/\r?\n/)
76
+ .some((l) => /^\s*disallow:/i.test(l) && l.replace(/^\s*disallow:\s*/i, '').trim() === want);
77
+ }
78
+ function robotsParams(roots,
79
+ /** The origin whose robots.txt was read. */
80
+ origin, robots) {
81
+ const title = "robots.txt keeps crawlers off a space's sorted and filtered copies";
82
+ const byOrigin = linesByOrigin(roots);
83
+ if (!byOrigin.size)
84
+ return (0, probe_1.check)('robots-params', title, 'skip', 'No space root to suggest lines for.', '');
85
+ const ownLines = byOrigin.get(origin) ?? [];
86
+ const missing = robots === undefined ? ownLines : ownLines.filter((l) => !has(robots, l));
87
+ const others = [...byOrigin].filter(([o]) => o !== origin);
88
+ if (!missing.length && !others.length)
89
+ return (0, probe_1.check)('robots-params', title, 'pass', `All ${ownLines.length} lines are in ${origin}/robots.txt.`, '');
90
+ const block = (o, lines) => [`# ${o}/robots.txt`, 'User-agent: *', ...lines].map((l) => ` ${l}`).join('\n');
91
+ const parts = [
92
+ ...(missing.length ? [block(origin, missing)] : []),
93
+ ...others.map(([o, lines]) => block(o, lines)),
94
+ ];
95
+ return (0, probe_1.check)('robots-params', title, 'skip', `Suggested — add to the host's robots.txt (the pages already say noindex or name their canonical; this saves the crawl):\n${parts.join('\n')}`, "Every sorted, scoped or filtered copy of a list is a fetch a crawler spends instead of a page that can rank.");
96
+ }
97
+ //# sourceMappingURL=robots-params.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"robots-params.js","sourceRoot":"","sources":["../../src/doctor/robots-params.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import type { Http } from '../api/http';
2
+ import type { AddressSet } from './address-checks';
3
+ import type { Get } from './probe';
4
+ /**
5
+ * `doctor --site <slug|id>`: every address of every space on a site, from the API.
6
+ *
7
+ * From a URL alone the doctor sees one copy of a page. The defects that bit
8
+ * the integrator were in the OTHER copy — the platform address of a legal page
9
+ * naming itself canonical (FMU-B01) — which nobody opens because readers never
10
+ * get there. The API knows every address a space is served at (its
11
+ * `readerEndpoints`: the customer's domain first, then the platform's), so this
12
+ * asks it, and the checks then compare the copies.
13
+ */
14
+ export interface ReaderEndpoint {
15
+ url: string;
16
+ kind?: string;
17
+ primary?: boolean;
18
+ }
19
+ export interface ResolvedSpace {
20
+ id: string;
21
+ /** Primary first. */
22
+ endpoints: ReaderEndpoint[];
23
+ }
24
+ export interface ResolvedSite {
25
+ id: string;
26
+ slug?: string;
27
+ name?: string;
28
+ spaces: ResolvedSpace[];
29
+ /** The address the report is run against: the first space's primary root. */
30
+ url?: string;
31
+ /** Spaces whose addresses could not be read, and why. */
32
+ problems: string[];
33
+ }
34
+ export declare function resolveSite(http: Http, org: string, site: string): Promise<ResolvedSite>;
35
+ /**
36
+ * The address sets the two-address check compares: each space's ROOT at every
37
+ * address, and one real PAGE per space — the first its sitemap lists under the
38
+ * primary root — mapped onto every other address by its path below the root.
39
+ * A root alone would miss the legal-page defect, which only pages had.
40
+ */
41
+ export declare function addressSetsFor(get: Get, site: ResolvedSite): Promise<AddressSet[]>;
42
+ //# sourceMappingURL=site.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"site.d.ts","sourceRoot":"","sources":["../../src/doctor/site.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,SAAS,CAAC;AAEnC;;;;;;;;;GASG;AAEH,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,qBAAqB;IACrB,SAAS,EAAE,cAAc,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,6EAA6E;IAC7E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AASD,wBAAsB,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAwC9F;AAID;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CA2BxF"}
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveSite = resolveSite;
4
+ exports.addressSetsFor = addressSetsFor;
5
+ const crawl_1 = require("./crawl");
6
+ async function resolveSite(http, org, site) {
7
+ const enc = encodeURIComponent;
8
+ const { data } = await http.send({ method: 'GET', path: `/orgs/${enc(org)}/sites` });
9
+ const rows = (data.sites ??
10
+ data.data ??
11
+ []);
12
+ const row = rows.find((s) => s.id === site || s.slug === site);
13
+ if (!row) {
14
+ const known = rows.map((s) => s.slug ?? s.id).join(', ') || 'none';
15
+ throw Object.assign(new Error(`No site "${site}" in ${org}. Sites: ${known}.`), {
16
+ status: 404,
17
+ });
18
+ }
19
+ const spaces = [];
20
+ const problems = [];
21
+ for (const spaceId of row.spaceIds ?? []) {
22
+ try {
23
+ const res = await http.send({
24
+ method: 'GET',
25
+ path: `/orgs/${enc(org)}/spaces/${enc(spaceId)}/reader-auth`,
26
+ });
27
+ const endpoints = (res.data.readerEndpoints ?? []).filter((e) => typeof e.url === 'string' && /^https?:/.test(e.url));
28
+ // Primary first, whatever order the answer used.
29
+ endpoints.sort((a, b) => Number(!!b.primary) - Number(!!a.primary));
30
+ if (endpoints.length)
31
+ spaces.push({ id: spaceId, endpoints });
32
+ else
33
+ problems.push(`${spaceId}: no reader addresses (private, or not published)`);
34
+ }
35
+ catch (e) {
36
+ problems.push(`${spaceId}: ${e.message}`);
37
+ }
38
+ }
39
+ return {
40
+ id: row.id,
41
+ slug: row.slug,
42
+ name: row.name,
43
+ spaces,
44
+ url: spaces[0]?.endpoints[0]?.url,
45
+ problems,
46
+ };
47
+ }
48
+ const trim = (u) => u.replace(/\/+$/, '');
49
+ /**
50
+ * The address sets the two-address check compares: each space's ROOT at every
51
+ * address, and one real PAGE per space — the first its sitemap lists under the
52
+ * primary root — mapped onto every other address by its path below the root.
53
+ * A root alone would miss the legal-page defect, which only pages had.
54
+ */
55
+ async function addressSetsFor(get, site) {
56
+ const sets = [];
57
+ // One sitemap read per host: a site's spaces usually share one domain.
58
+ const urlsByOrigin = new Map();
59
+ for (const space of site.spaces) {
60
+ if (space.endpoints.length < 2)
61
+ continue;
62
+ const roots = space.endpoints.map((e) => trim(e.url));
63
+ const primary = roots[0];
64
+ sets.push({ expected: primary, urls: roots });
65
+ const origin = new URL(primary).origin;
66
+ if (!urlsByOrigin.has(origin)) {
67
+ const r = await get(`${origin}/robots.txt`);
68
+ const robots = r.ok && r.status === 200 ? r.text : '';
69
+ const { lists } = await (0, crawl_1.readSitemaps)(get, (0, crawl_1.sitemapsFromRobots)(robots, origin));
70
+ urlsByOrigin.set(origin, lists.flatMap((l) => l.urls));
71
+ }
72
+ const page = urlsByOrigin
73
+ .get(origin)
74
+ .find((u) => u.startsWith(`${primary}/`) && u.length > primary.length + 1);
75
+ if (!page)
76
+ continue;
77
+ const rest = page.slice(primary.length);
78
+ sets.push({ expected: page, urls: roots.map((r) => `${r}${rest}`) });
79
+ }
80
+ return sets;
81
+ }
82
+ //# sourceMappingURL=site.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"site.js","sourceRoot":"","sources":["../../src/doctor/site.ts"],"names":[],"mappings":";;AA8CA,kCAwCC;AAUD,wCA2BC;AAzHD,mCAA2D;AA4CpD,KAAK,UAAU,WAAW,CAAC,IAAU,EAAE,GAAW,EAAE,IAAY;IACrE,MAAM,GAAG,GAAG,kBAAkB,CAAC;IAC/B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;IACrF,MAAM,IAAI,GAAG,CAAE,IAAgD,CAAC,KAAK;QAClE,IAA6B,CAAC,IAAI;QACnC,EAAE,CAAc,CAAC;IACnB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IAC/D,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC;QACnE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,YAAY,IAAI,QAAQ,GAAG,YAAY,KAAK,GAAG,CAAC,EAAE;YAC9E,MAAM,EAAE,GAAG;SACZ,CAAC,CAAC;IACL,CAAC;IACD,MAAM,MAAM,GAAoB,EAAE,CAAC;IACnC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,OAAO,IAAI,GAAG,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;QACzC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC;gBAC1B,MAAM,EAAE,KAAK;gBACb,IAAI,EAAE,SAAS,GAAG,CAAC,GAAG,CAAC,WAAW,GAAG,CAAC,OAAO,CAAC,cAAc;aAC7D,CAAC,CAAC;YACH,MAAM,SAAS,GAAG,CACf,GAAG,CAAC,IAA+C,CAAC,eAAe,IAAI,EAAE,CAC3E,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACrE,iDAAiD;YACjD,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;YACpE,IAAI,SAAS,CAAC,MAAM;gBAAE,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;;gBACzD,QAAQ,CAAC,IAAI,CAAC,GAAG,OAAO,mDAAmD,CAAC,CAAC;QACpF,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,QAAQ,CAAC,IAAI,CAAC,GAAG,OAAO,KAAM,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IACD,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,MAAM;QACN,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG;QACjC,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAElD;;;;;GAKG;AACI,KAAK,UAAU,cAAc,CAAC,GAAQ,EAAE,IAAkB;IAC/D,MAAM,IAAI,GAAiB,EAAE,CAAC;IAC9B,uEAAuE;IACvE,MAAM,YAAY,GAAG,IAAI,GAAG,EAAoB,CAAC;IACjD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChC,IAAI,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;YAAE,SAAS;QACzC,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACtD,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;QACvC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAC9B,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,GAAG,MAAM,aAAa,CAAC,CAAC;YAC5C,MAAM,MAAM,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACtD,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAA,oBAAY,EAAC,GAAG,EAAE,IAAA,0BAAkB,EAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;YAC9E,YAAY,CAAC,GAAG,CACd,MAAM,EACN,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAC7B,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,GAAG,YAAY;aACtB,GAAG,CAAC,MAAM,CAAE;aACZ,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC7E,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;IACvE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
package/dist/doctor.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { Check } from './conformance';
2
+ import type { AddressSet } from './doctor/address-checks';
2
3
  /**
3
4
  * Everything that is wrong with a live site, from the outside.
4
5
  *
@@ -21,7 +22,27 @@ export interface DoctorInput {
21
22
  /** The API base, when it is not the same origin (defaults to the site's). */
22
23
  apiBase?: string;
23
24
  fetchImpl?: typeof fetch;
25
+ /**
26
+ * Only these check ids (`--only`). The single-page checks are cheap and run
27
+ * regardless, then are filtered; the site-wide ones (a sitemap crawl) are
28
+ * not started unless asked for.
29
+ */
30
+ only?: string[];
31
+ /** The platform's hostname, for the white-label and two-address checks. Default forumulate.com. */
32
+ platformHost?: string;
33
+ /** The platform's API base, for the primary-address lookup. Default `https://<platformHost>/api`. */
34
+ platformApi?: string;
35
+ /** Other addresses of the same page (`--also`, or looked up by `--site`). */
36
+ addressSets?: AddressSet[];
37
+ /** The space roots to check (`--site` knows them; otherwise derived from the URL). */
38
+ roots?: string[];
39
+ /** How many sitemap URLs to sample (`--limit`). */
40
+ limit?: number;
41
+ /** Per-request timeout. */
42
+ timeoutMs?: number;
24
43
  }
44
+ /** The single-page checks, in report order; the site-wide ones are `EXTENDED_CHECK_IDS`. */
45
+ export declare const BASE_CHECK_IDS: readonly ["health", "public-read", "canonical", "html-untouched", "cache-headers", "robots", "sitemap", "crawler-access", "feeds", "images"];
25
46
  export interface DoctorReport {
26
47
  url: string;
27
48
  checks: Check[];
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAE3C;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,WAAW;IAC1B,yEAAyE;IACzE,GAAG,EAAE,MAAM,CAAC;IACZ,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAKD,wBAAsB,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAiUzE;AAoCD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,kBAAkB,SAAS,CAAC"}
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAG1D;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,WAAW;IAC1B,yEAAyE;IACzE,GAAG,EAAE,MAAM,CAAC;IACZ,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,mGAAmG;IACnG,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qGAAqG;IACrG,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,sFAAsF;IACtF,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,4FAA4F;AAC5F,eAAO,MAAM,cAAc,8IAWjB,CAAC;AAEX,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAKD,wBAAsB,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CA2XzE;AAoCD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,kBAAkB,SAAS,CAAC"}