@salesforce/b2c-tooling-sdk 1.17.0 → 1.18.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 (70) hide show
  1. package/data/content-schemas/componenttype.json +79 -17
  2. package/data/content-schemas/pagetype.json +4 -0
  3. package/data/guides/enrichment.json +11264 -0
  4. package/data/guides/index.json +15166 -0
  5. package/data/job-steps/index.json +71 -1
  6. package/data/job-steps/job-steps.json +1 -1
  7. package/data/script-api/index.json +2145 -37
  8. package/data/tooling/index.json +222 -0
  9. package/data/xsd/index.json +1 -1
  10. package/dist/esm/auth/client-credentials.d.ts +27 -0
  11. package/dist/esm/auth/client-credentials.js +60 -0
  12. package/dist/esm/auth/client-credentials.js.map +1 -0
  13. package/dist/esm/auth/index.d.ts +1 -0
  14. package/dist/esm/auth/index.js +2 -0
  15. package/dist/esm/auth/index.js.map +1 -1
  16. package/dist/esm/auth/oauth.js +2 -1
  17. package/dist/esm/auth/oauth.js.map +1 -1
  18. package/dist/esm/cli/base-command.d.ts +40 -0
  19. package/dist/esm/cli/base-command.js +66 -5
  20. package/dist/esm/cli/base-command.js.map +1 -1
  21. package/dist/esm/cli/index.d.ts +2 -2
  22. package/dist/esm/cli/index.js +1 -1
  23. package/dist/esm/cli/index.js.map +1 -1
  24. package/dist/esm/cli/instance-command.d.ts +1 -1
  25. package/dist/esm/cli/instance-command.js +5 -3
  26. package/dist/esm/cli/instance-command.js.map +1 -1
  27. package/dist/esm/cli/oauth-command.d.ts +1 -1
  28. package/dist/esm/cli/oauth-command.js +5 -3
  29. package/dist/esm/cli/oauth-command.js.map +1 -1
  30. package/dist/esm/cli/ods-command.d.ts +1 -1
  31. package/dist/esm/cli/webdav-command.d.ts +1 -1
  32. package/dist/esm/config/sources/env-source.js +1 -0
  33. package/dist/esm/config/sources/env-source.js.map +1 -1
  34. package/dist/esm/discovery/detector.d.ts +0 -5
  35. package/dist/esm/discovery/detector.js +24 -3
  36. package/dist/esm/discovery/detector.js.map +1 -1
  37. package/dist/esm/discovery/index.d.ts +1 -0
  38. package/dist/esm/discovery/index.js +1 -0
  39. package/dist/esm/discovery/index.js.map +1 -1
  40. package/dist/esm/discovery/patterns/index.d.ts +4 -2
  41. package/dist/esm/discovery/patterns/index.js +9 -3
  42. package/dist/esm/discovery/patterns/index.js.map +1 -1
  43. package/dist/esm/discovery/patterns/pwa-kit.d.ts +12 -0
  44. package/dist/esm/discovery/patterns/pwa-kit.js +18 -7
  45. package/dist/esm/discovery/patterns/pwa-kit.js.map +1 -1
  46. package/dist/esm/discovery/patterns/sfra.d.ts +5 -4
  47. package/dist/esm/discovery/patterns/sfra.js +1 -1
  48. package/dist/esm/discovery/patterns/sfra.js.map +1 -1
  49. package/dist/esm/discovery/patterns/storefront-next.js +18 -2
  50. package/dist/esm/discovery/patterns/storefront-next.js.map +1 -1
  51. package/dist/esm/discovery/types.d.ts +13 -4
  52. package/dist/esm/discovery/types.js +11 -1
  53. package/dist/esm/discovery/types.js.map +1 -1
  54. package/dist/esm/docs/index.d.ts +3 -3
  55. package/dist/esm/docs/index.js +1 -1
  56. package/dist/esm/docs/index.js.map +1 -1
  57. package/dist/esm/docs/search.d.ts +111 -38
  58. package/dist/esm/docs/search.js +402 -81
  59. package/dist/esm/docs/search.js.map +1 -1
  60. package/dist/esm/docs/types.d.ts +56 -6
  61. package/dist/esm/docs/types.js +2 -0
  62. package/dist/esm/docs/types.js.map +1 -1
  63. package/dist/esm/slas/token.d.ts +9 -2
  64. package/dist/esm/slas/token.js +25 -29
  65. package/dist/esm/slas/token.js.map +1 -1
  66. package/dist/esm/telemetry/telemetry.d.ts +1 -0
  67. package/dist/esm/telemetry/telemetry.js +32 -0
  68. package/dist/esm/telemetry/telemetry.js.map +1 -1
  69. package/dist/esm/telemetry/types.d.ts +6 -0
  70. package/package.json +7 -2
@@ -5,18 +5,168 @@
5
5
  */
6
6
  import * as fs from 'node:fs';
7
7
  import * as path from 'node:path';
8
- import Fuse from 'fuse.js';
9
- import { JOB_STEPS_DATA_DIR, SCRIPT_API_DATA_DIR } from './types.js';
10
- // Singleton cache for loaded index and Fuse instance
8
+ import MiniSearch from 'minisearch';
9
+ import { getLogger } from '../logging/logger.js';
10
+ import { GUIDES_DATA_DIR, JOB_STEPS_DATA_DIR, SCRIPT_API_DATA_DIR, TOOLING_DATA_DIR, } from './types.js';
11
+ /**
12
+ * The bundled corpora, loaded (and combined) in priority order. Earlier corpora
13
+ * win on id collisions. Each directory holds an `index.json` ({@link SearchIndex})
14
+ * and, for corpora whose content ships in the package, the referenced files.
15
+ */
16
+ const CORPUS_DIRS = [SCRIPT_API_DATA_DIR, JOB_STEPS_DATA_DIR, GUIDES_DATA_DIR, TOOLING_DATA_DIR];
17
+ /** Multiplier applied to a detected workspace's relevant categories. */
18
+ const WORKSPACE_BOOST = 1.4;
19
+ /**
20
+ * Timeout (ms) for fetching an online-only guide's content. Without a bound a
21
+ * stalled connection hangs the caller indefinitely (observed hanging Windows CI
22
+ * for 6h); on timeout we fall back to the indexed offline summary instead.
23
+ */
24
+ const ONLINE_FETCH_TIMEOUT_MS = 10_000;
25
+ /**
26
+ * Multiplier applied to a COMPETING storefront framework's guides when a
27
+ * workspace is known — i.e. the storefront-framework guide categories that are
28
+ * NOT relevant to the detected workspace (e.g. `sfnext`/`sfra` for a PWA Kit
29
+ * project). These are mutually exclusive storefront implementations, so their
30
+ * how-to guides are usually the wrong answer for a different storefront. Kept
31
+ * as a de-boost (not a hard filter) so the docs still surface, just demoted —
32
+ * a strong exact-title match (e.g. an "SEO and Metadata" sfnext guide) should
33
+ * not outrank the current storefront's own guide for the same query.
34
+ */
35
+ const COMPETING_STOREFRONT_PENALTY = 0.3;
36
+ /**
37
+ * The storefront-FRAMEWORK guide categories: one per mutually-exclusive
38
+ * storefront implementation. Only these are de-boosted when they belong to a
39
+ * different storefront than the detected workspace. Reference/platform corpora
40
+ * (`script-api`, `job-step`, `commerce-api`, `b2c-commerce`, `tooling`) are
41
+ * never treated as "competing" — they apply across storefronts.
42
+ */
43
+ const STOREFRONT_FRAMEWORK_CATEGORIES = ['sfra', 'pwa-kit-managed-runtime', 'sfnext'];
44
+ /**
45
+ * Canonical per-category metadata, keyed by {@link DocCategory}. Insertion order
46
+ * defines the display order in {@link DOC_CATEGORIES}. `alwaysRelevant` marks the
47
+ * categories that are boosted whenever ANY workspace is detected, regardless of
48
+ * which framework it is (general platform docs + this tooling's own docs).
49
+ *
50
+ * Typed `Record<DocCategory, …>`, so adding a new `DocCategory` to the union in
51
+ * `types.ts` is a compile error until it is listed here (keeps the category list
52
+ * and its metadata from drifting).
53
+ */
54
+ const CATEGORY_TAXONOMY = {
55
+ 'script-api': {},
56
+ 'job-step': {},
57
+ 'commerce-api': {},
58
+ 'pwa-kit-managed-runtime': {},
59
+ sfnext: {},
60
+ sfra: {},
61
+ 'b2c-commerce': { alwaysRelevant: true },
62
+ tooling: { alwaysRelevant: true },
63
+ };
64
+ /**
65
+ * The canonical list of documentation categories, in a stable display order.
66
+ * Exported so the CLI and MCP surfaces validate against a single source of truth
67
+ * instead of maintaining their own copies. Derived from {@link CATEGORY_TAXONOMY}.
68
+ */
69
+ export const DOC_CATEGORIES = Object.keys(CATEGORY_TAXONOMY);
70
+ /** Categories relevant to every detected workspace. Derived from {@link CATEGORY_TAXONOMY}. */
71
+ const ALWAYS_RELEVANT = DOC_CATEGORIES.filter((c) => CATEGORY_TAXONOMY[c].alwaysRelevant);
72
+ /**
73
+ * Maps each workspace marker to the doc categories it makes relevant. The final
74
+ * relevant set for a workspace is {@link ALWAYS_RELEVANT} plus the union of the
75
+ * markers' categories (merged, never summed — a category shared by two markers
76
+ * is still boosted once).
77
+ *
78
+ * `sfra` is a refinement of `cartridges`: an SFRA project detects as both, so it
79
+ * gets the cartridge categories (Script API, job steps) AND the `sfra` guides. A
80
+ * non-SFRA cartridge project (custom APIs, or a PWA Kit / Storefront Next repo
81
+ * that also ships cartridges) gets the cartridge categories but NOT `sfra`.
82
+ *
83
+ * Typed `Record<ProjectType, …>`, so adding a new workspace marker is a compile
84
+ * error until its categories are declared here.
85
+ */
86
+ const WORKSPACE_CATEGORIES = {
87
+ cartridges: ['script-api', 'job-step'],
88
+ sfra: ['sfra'],
89
+ 'pwa-kit-v3': ['pwa-kit-managed-runtime', 'commerce-api'],
90
+ 'storefront-next': ['sfnext', 'commerce-api'],
91
+ };
92
+ /**
93
+ * Parses and validates a user-supplied set of documentation categories into a
94
+ * "topics" allowlist that bounds the entire available corpus (see
95
+ * {@link SearchDocsOptions.enabledCategories}). Accepts a comma-separated string
96
+ * or an array; names are trimmed and lower-cased.
97
+ *
98
+ * Unknown names are dropped (and reported via `onInvalid`, if provided). Returns
99
+ * `undefined` when the input is empty or contains no valid categories, which
100
+ * means "no restriction" — matching the tolerant behavior of the MCP `--toolsets`
101
+ * flag, so a typo yields a warning and the full corpus rather than a dead tool.
102
+ *
103
+ * @param input - Comma-separated category names, or an array of names
104
+ * @param onInvalid - Optional callback invoked with any unrecognized names
105
+ * @returns The validated, de-duplicated categories, or `undefined` for no restriction
106
+ */
107
+ export function resolveEnabledCategories(input, onInvalid) {
108
+ if (input == undefined)
109
+ return undefined;
110
+ const raw = Array.isArray(input) ? input : String(input).split(',');
111
+ const names = raw.map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0);
112
+ if (names.length === 0)
113
+ return undefined;
114
+ const known = new Set(DOC_CATEGORIES);
115
+ const valid = [];
116
+ const invalid = [];
117
+ for (const name of names) {
118
+ if (known.has(name))
119
+ valid.push(name);
120
+ else
121
+ invalid.push(name);
122
+ }
123
+ if (invalid.length > 0)
124
+ onInvalid?.(invalid);
125
+ return valid.length > 0 ? [...new Set(valid)] : undefined;
126
+ }
127
+ /** Normalizes a workspace option to an array of project-type markers. */
128
+ function toWorkspaceList(workspace) {
129
+ if (!workspace)
130
+ return undefined;
131
+ const list = Array.isArray(workspace) ? workspace : [workspace];
132
+ return list.length ? list : undefined;
133
+ }
134
+ /**
135
+ * Computes the set of doc categories relevant to the given workspace marker(s):
136
+ * the always-relevant categories plus the union of each marker's categories
137
+ * (merged, not summed).
138
+ */
139
+ export function categoriesForWorkspace(workspace) {
140
+ const list = toWorkspaceList(workspace) ?? [];
141
+ const set = new Set(ALWAYS_RELEVANT);
142
+ for (const marker of list) {
143
+ for (const cat of WORKSPACE_CATEGORIES[marker] ?? [])
144
+ set.add(cat);
145
+ }
146
+ return [...set];
147
+ }
148
+ // Singleton caches for the combined index and the MiniSearch instance.
11
149
  let cachedIndex = null;
12
- let cachedFuse = null;
13
- // Maps each entry id to the absolute data directory that holds its file. This
14
- // lets a single combined index span multiple bundled corpora (Script API docs
15
- // and the standard job-step reference) without changing the public DocEntry shape.
150
+ let cachedMiniSearch = null;
151
+ // Maps each entry id to the absolute data directory that holds its bundled file.
152
+ // Lets a single combined index span multiple bundled corpora without changing
153
+ // the public DocEntry shape. Online-only entries (guides) are not recorded here.
16
154
  const entryDataDir = new Map();
155
+ // Maps each entry id to its full DocEntry, for O(1) lookup on read.
156
+ const entryById = new Map();
157
+ /**
158
+ * Projects a stored entry to the shape returned to callers. Drops `headings`,
159
+ * which exists only to feed the search index (a long ` • `-joined string with
160
+ * no triage value) and would otherwise bloat search/list payloads for agents.
161
+ */
162
+ function publicEntry(entry) {
163
+ const { headings: _headings, ...rest } = entry;
164
+ return rest;
165
+ }
17
166
  /**
18
167
  * Loads one bundled index.json from the given directory, returning its entries
19
- * and recording the directory for each entry id. Missing indexes are ignored.
168
+ * and recording the directory for each id that ships its content on disk.
169
+ * Missing indexes are ignored so a not-yet-generated corpus is simply absent.
20
170
  */
21
171
  function loadCorpus(dataDir) {
22
172
  const indexPath = path.join(dataDir, 'index.json');
@@ -25,135 +175,306 @@ function loadCorpus(dataDir) {
25
175
  }
26
176
  const parsed = JSON.parse(fs.readFileSync(indexPath, 'utf-8'));
27
177
  for (const entry of parsed.entries) {
28
- // First corpus wins on id collision (Script API is loaded first).
29
- if (!entryDataDir.has(entry.id)) {
178
+ if (entryById.has(entry.id))
179
+ continue; // first corpus wins on id collision
180
+ entryById.set(entry.id, entry);
181
+ // Only record a data dir for entries whose content is bundled on disk.
182
+ if (entry.filePath) {
30
183
  entryDataDir.set(entry.id, dataDir);
31
184
  }
32
185
  }
33
186
  return parsed.entries;
34
187
  }
35
188
  /**
36
- * Loads the pre-built search index from the bundled data directories.
189
+ * Loads the combined search index from every bundled corpus directory.
37
190
  *
38
- * Combines the Script API documentation corpus with the standard job-step
39
- * reference so both are searchable through the same functions.
191
+ * Combines the Script API reference, standard job steps, Developer Center
192
+ * guides, and this project's own docs so all are searchable through the same
193
+ * functions. Corpora that have not been generated are skipped.
40
194
  *
41
195
  * @returns The combined search index with all documentation entries
42
- * @throws Error if the Script API index file cannot be read
43
196
  */
44
197
  export function loadSearchIndex() {
45
198
  if (cachedIndex)
46
199
  return cachedIndex;
47
200
  entryDataDir.clear();
48
- const scriptApiEntries = loadCorpus(SCRIPT_API_DATA_DIR);
49
- const jobStepEntries = loadCorpus(JOB_STEPS_DATA_DIR);
201
+ entryById.clear();
202
+ const entries = [];
203
+ const perCorpus = {};
204
+ for (const dir of CORPUS_DIRS) {
205
+ const loaded = loadCorpus(dir);
206
+ perCorpus[path.basename(dir)] = loaded.length;
207
+ entries.push(...loaded);
208
+ }
209
+ getLogger().debug({ total: entries.length, perCorpus }, 'Loaded combined documentation search index');
50
210
  cachedIndex = {
51
- version: '1.0.0',
211
+ version: '2.0.0',
52
212
  generatedAt: new Date(0).toISOString(),
53
- entries: [...scriptApiEntries, ...jobStepEntries],
213
+ entries,
54
214
  };
55
215
  return cachedIndex;
56
216
  }
57
217
  /**
58
- * Gets or creates the Fuse.js search instance.
218
+ * Gets or creates the MiniSearch instance over the combined index.
219
+ *
220
+ * MiniSearch gives tokenized, BM25-style ranking with field boosting — far
221
+ * better recall on prose (Developer Center guides) than a title-only fuzzy
222
+ * match, while still returning class-name lookups (e.g. "ProductMgr") first.
59
223
  */
60
- function getFuseInstance() {
61
- if (cachedFuse)
62
- return cachedFuse;
224
+ function getMiniSearch() {
225
+ if (cachedMiniSearch)
226
+ return cachedMiniSearch;
63
227
  const index = loadSearchIndex();
64
- cachedFuse = new Fuse(index.entries, {
65
- keys: [
66
- { name: 'title', weight: 0.5 },
67
- { name: 'id', weight: 0.5 },
68
- ],
69
- threshold: 0.4,
70
- includeScore: true,
71
- minMatchCharLength: 2,
72
- ignoreLocation: true,
228
+ const ms = new MiniSearch({
229
+ idField: 'id',
230
+ fields: ['title', 'id', 'headings', 'keywords', 'summary'],
231
+ // We look entries up in entryById on read, so nothing extra needs storing.
232
+ storeFields: ['category'],
233
+ searchOptions: {
234
+ boost: { title: 3, id: 2.5, keywords: 2, headings: 2, summary: 1.5 },
235
+ fuzzy: 0.2,
236
+ prefix: true,
237
+ // OR-combine: relevance ranking surfaces the best (near-AND) matches first
238
+ // while still finding prose docs from natural-language queries whose
239
+ // stopwords ("how", "the") are not indexed. Verified best recall in eval.
240
+ // NOTE: the per-document category boost is applied per-search in
241
+ // searchDocs (it depends on runtime workspace context), not baked here.
242
+ },
73
243
  });
74
- return cachedFuse;
244
+ ms.addAll(index.entries.map((e) => ({
245
+ id: e.id,
246
+ title: e.title ?? '',
247
+ category: e.category ?? '',
248
+ headings: e.headings ?? '',
249
+ summary: e.summary ?? '',
250
+ keywords: Array.isArray(e.keywords) ? e.keywords.join(' ') : '',
251
+ })));
252
+ getLogger().debug({ documentCount: index.entries.length }, 'Built MiniSearch index for documentation search');
253
+ cachedMiniSearch = ms;
254
+ return ms;
255
+ }
256
+ /** Intersects two category lists; `undefined` on either side means "no constraint on that side". */
257
+ function intersectCategories(a, b) {
258
+ if (!a)
259
+ return b ? [...b] : undefined;
260
+ if (!b)
261
+ return [...a];
262
+ const bSet = new Set(b);
263
+ return a.filter((c) => bSet.has(c));
75
264
  }
76
265
  /**
77
- * Searches the documentation index with fuzzy matching.
266
+ * Searches the combined documentation index.
267
+ *
268
+ * Higher scores are better. Results carry the full {@link DocEntry} (including
269
+ * `category`, `summary`, `keywords`, and `url` when available) so callers can
270
+ * triage matches without a follow-up read.
271
+ *
272
+ * When `workspace` is provided, the categories relevant to those markers (e.g.
273
+ * `sfra` for an SFRA project, `script-api`/`job-step` for any cartridge project,
274
+ * `pwa-kit-managed-runtime`/`commerce-api` for PWA Kit, `sfnext`/`commerce-api`
275
+ * for Storefront Next — plus the always-relevant docs) are boosted. It only ever
276
+ * reorders results; use `category`/`enabledCategories` to hard-scope.
78
277
  *
79
278
  * @param query - The search query string
80
- * @param limit - Maximum number of results to return (default: 20)
81
- * @returns Array of search results sorted by relevance
279
+ * @param limitOrOptions - Result limit (number) or {@link SearchDocsOptions}
280
+ * @returns Array of search results sorted by relevance (best first)
82
281
  *
83
282
  * @example
84
283
  * ```typescript
85
- * const results = searchDocs('ProductMgr');
86
- * results.forEach(r => console.log(r.entry.id, r.score));
284
+ * // Favor the current workspace's docs (nothing hidden)
285
+ * searchDocs('deploy bundle', {workspace: 'pwa-kit-v3'});
286
+ * // Hard-scope to one category instead
287
+ * searchDocs('components', {category: 'sfnext'});
87
288
  * ```
88
289
  */
89
- export function searchDocs(query, limit = 20) {
90
- const fuse = getFuseInstance();
91
- const results = fuse.search(query, { limit });
92
- return results.map((r) => ({
93
- entry: r.item,
94
- score: r.score ?? 0,
95
- }));
290
+ export function searchDocs(query, limitOrOptions) {
291
+ const opts = typeof limitOrOptions === 'number' ? { limit: limitOrOptions } : (limitOrOptions ?? {});
292
+ const limit = opts.limit ?? 20;
293
+ const workspaces = toWorkspaceList(opts.workspace);
294
+ // Only an explicit category is a hard filter now; a workspace never hides docs.
295
+ const explicit = opts.category ? (Array.isArray(opts.category) ? opts.category : [opts.category]) : undefined;
296
+ // The launch-time allowlist bounds the whole corpus; the per-query category
297
+ // narrows within it. Their intersection is the effective hard filter.
298
+ const filterCategories = intersectCategories(opts.enabledCategories, explicit);
299
+ // A known workspace boosts its relevant categories, and DE-BOOSTS the guides
300
+ // of competing storefront frameworks (a different storefront's how-to guides
301
+ // are usually the wrong answer). Neither hides anything — both only reweight.
302
+ const boostSet = workspaces ? new Set(categoriesForWorkspace(workspaces)) : undefined;
303
+ const competingSet = boostSet
304
+ ? new Set(STOREFRONT_FRAMEWORK_CATEGORIES.filter((c) => !boostSet.has(c)))
305
+ : undefined;
306
+ const ms = getMiniSearch();
307
+ const raw = ms.search(query, {
308
+ filter: filterCategories ? (r) => filterCategories.includes(r.category) : undefined,
309
+ boostDocument: (_id, _term, storedFields) => {
310
+ const category = storedFields?.category;
311
+ if (!category)
312
+ return 1;
313
+ if (boostSet?.has(category))
314
+ return WORKSPACE_BOOST;
315
+ if (competingSet?.has(category))
316
+ return COMPETING_STOREFRONT_PENALTY;
317
+ return 1;
318
+ },
319
+ });
320
+ const results = [];
321
+ for (const r of raw) {
322
+ const entry = entryById.get(r.id);
323
+ if (!entry)
324
+ continue;
325
+ results.push({ entry: publicEntry(entry), score: r.score });
326
+ if (results.length >= limit)
327
+ break;
328
+ }
329
+ const logger = getLogger();
330
+ logger.debug({ query, filterCategories, workspaces, limit, matched: raw.length, returned: results.length }, 'docs searchDocs completed');
331
+ logger.trace({ query, top: results.slice(0, 5).map((r) => ({ id: r.entry.id, score: r.score })) }, 'docs search top hits');
332
+ return results;
96
333
  }
97
334
  /**
98
- * Reads the content of a documentation file by its ID.
99
- *
100
- * @param id - The documentation ID (filename without .md extension)
101
- * @returns The raw markdown content of the document
102
- * @throws Error if the document is not found
335
+ * Lists documentation entries, optionally filtered by category.
103
336
  *
104
- * @example
105
- * ```typescript
106
- * const content = readDoc('dw.catalog.ProductMgr');
107
- * console.log(content);
108
- * ```
337
+ * @param category - Optional corpus/category (or list) to restrict to
338
+ * @param enabledCategories - Optional launch-time allowlist that bounds the
339
+ * entire corpus (see {@link SearchDocsOptions.enabledCategories}). When set,
340
+ * only entries in these categories are eligible; `category` narrows within it.
341
+ * @returns Array of matching documentation entries
109
342
  */
110
- export function readDoc(id) {
343
+ export function listDocs(category, enabledCategories) {
111
344
  const index = loadSearchIndex();
112
- const entry = index.entries.find((e) => e.id === id);
345
+ const explicit = category ? (Array.isArray(category) ? category : [category]) : undefined;
346
+ const categories = intersectCategories(enabledCategories, explicit);
347
+ const entries = categories
348
+ ? index.entries.filter((e) => e.category && categories.includes(e.category))
349
+ : index.entries;
350
+ return entries.map(publicEntry);
351
+ }
352
+ /**
353
+ * Reads the full content of a documentation entry by its exact id.
354
+ *
355
+ * Bundled entries are read from disk. Entries whose content is published online
356
+ * (Developer Center guides) are fetched from their canonical URL; on network
357
+ * failure a readable fallback assembled from the indexed metadata is returned.
358
+ *
359
+ * @param id - The documentation id
360
+ * @returns The document content (markdown)
361
+ * @throws Error if the id is unknown
362
+ */
363
+ export async function readDoc(id) {
364
+ loadSearchIndex();
365
+ const entry = entryById.get(id);
113
366
  if (!entry) {
114
367
  throw new Error(`Documentation not found: ${id}`);
115
368
  }
116
- const dataDir = entryDataDir.get(entry.id) ?? SCRIPT_API_DATA_DIR;
117
- const filePath = path.join(dataDir, entry.filePath);
118
- return fs.readFileSync(filePath, 'utf-8');
369
+ return readEntryContent(entry);
370
+ }
371
+ /**
372
+ * Reads the content of a resolved {@link DocEntry}, choosing bundled-file vs.
373
+ * online fetch based on whether the entry ships its content on disk.
374
+ */
375
+ export async function readEntryContent(entry) {
376
+ const logger = getLogger();
377
+ const dataDir = entryDataDir.get(entry.id);
378
+ if (dataDir && entry.filePath) {
379
+ logger.debug({ id: entry.id, source: 'bundled', filePath: entry.filePath }, 'Reading bundled documentation entry');
380
+ return fs.readFileSync(path.join(dataDir, entry.filePath), 'utf-8');
381
+ }
382
+ // Online-only entries (guides): fetch the raw markdown. Prefer `sourceUrl`
383
+ // (the `.md`); fall back to `url` for any entry that only carries one.
384
+ const fetchUrl = entry.sourceUrl ?? entry.url;
385
+ if (fetchUrl) {
386
+ logger.debug({ id: entry.id, source: 'online', fetchUrl }, 'Reading online documentation entry');
387
+ return fetchOnlineContent(entry, fetchUrl);
388
+ }
389
+ throw new Error(`No content source for documentation entry: ${entry.id}`);
390
+ }
391
+ /**
392
+ * Fetches a guide's markdown from `fetchUrl`, falling back to a summary
393
+ * assembled from indexed metadata if the request fails (offline, 404, etc.).
394
+ */
395
+ async function fetchOnlineContent(entry, fetchUrl) {
396
+ const logger = getLogger();
397
+ try {
398
+ logger.trace({ fetchUrl }, 'Fetching online documentation content');
399
+ const res = await fetch(fetchUrl, {
400
+ headers: { accept: 'text/markdown, text/plain, */*' },
401
+ signal: AbortSignal.timeout(ONLINE_FETCH_TIMEOUT_MS),
402
+ });
403
+ if (!res.ok) {
404
+ logger.debug({ fetchUrl, status: res.status }, 'Online doc fetch returned non-OK status');
405
+ return offlineFallback(entry, `HTTP ${res.status}`);
406
+ }
407
+ const text = await res.text();
408
+ logger.trace({ fetchUrl, bytes: text.length }, 'Fetched online documentation content');
409
+ return text;
410
+ }
411
+ catch (err) {
412
+ logger.debug({ fetchUrl, err }, 'Online doc fetch failed');
413
+ return offlineFallback(entry, err instanceof Error ? err.message : String(err));
414
+ }
415
+ }
416
+ /** Assembles a minimal readable document from indexed metadata when fetch fails. */
417
+ function offlineFallback(entry, reason) {
418
+ const lines = [`# ${entry.title}`, ''];
419
+ if (entry.summary)
420
+ lines.push(entry.summary, '');
421
+ if (entry.headings)
422
+ lines.push('## Sections', '', entry.headings
423
+ .split(' • ')
424
+ .map((h) => `- ${h}`)
425
+ .join('\n'), '');
426
+ if (entry.url)
427
+ lines.push(`Full documentation: ${entry.url}`, '');
428
+ lines.push(`> Note: live content could not be fetched (${reason}); showing indexed summary only.`);
429
+ return lines.join('\n');
119
430
  }
120
431
  /**
121
432
  * Reads documentation by fuzzy-matching the query and returning the best match.
122
433
  *
123
434
  * @param query - The search query string
435
+ * @param options - Optional search constraints (e.g. category)
124
436
  * @returns The best matching entry and its content, or null if no match
125
437
  *
126
438
  * @example
127
439
  * ```typescript
128
- * const doc = readDocByQuery('ProductMgr');
129
- * if (doc) {
130
- * console.log(`Found: ${doc.entry.title}`);
131
- * console.log(doc.content);
132
- * }
440
+ * const doc = await readDocByQuery('ProductMgr');
441
+ * if (doc) console.log(doc.content);
133
442
  * ```
134
443
  */
135
- export function readDocByQuery(query) {
136
- const results = searchDocs(query, 1);
444
+ export async function readDocByQuery(query, options) {
445
+ // Prefer an exact id match so precise lookups are deterministic. Honor both
446
+ // the per-query category constraint and the launch-time allowlist so an exact
447
+ // id in a non-requested (or disabled) corpus does not win.
448
+ loadSearchIndex();
449
+ const exact = entryById.get(query);
450
+ if (exact) {
451
+ const perQuery = options?.category
452
+ ? Array.isArray(options.category)
453
+ ? options.category
454
+ : [options.category]
455
+ : undefined;
456
+ const categories = intersectCategories(options?.enabledCategories, perQuery);
457
+ if (!categories || (exact.category && categories.includes(exact.category))) {
458
+ // Resolve content from the stored entry (keeps headings for offline
459
+ // fallback), but return the public entry (headings stripped).
460
+ return { entry: publicEntry(exact), content: await readEntryContent(exact) };
461
+ }
462
+ }
463
+ const results = searchDocs(query, { ...options, limit: 1 });
137
464
  if (results.length === 0) {
138
465
  return null;
139
466
  }
140
- const entry = results[0].entry;
141
- const content = readDoc(entry.id);
142
- return { entry, content };
467
+ const stored = entryById.get(results[0].entry.id) ?? results[0].entry;
468
+ return { entry: publicEntry(stored), content: await readEntryContent(stored) };
143
469
  }
144
470
  /**
145
- * Lists all available documentation entries.
146
- *
147
- * @returns Array of all documentation entries in the index
148
- *
149
- * @example
150
- * ```typescript
151
- * const docs = listDocs();
152
- * console.log(`${docs.length} documentation files available`);
153
- * ```
471
+ * Resets the in-memory index/search caches. Intended for tests that swap the
472
+ * bundled data on disk between assertions.
154
473
  */
155
- export function listDocs() {
156
- const index = loadSearchIndex();
157
- return index.entries;
474
+ export function resetDocsCache() {
475
+ cachedIndex = null;
476
+ cachedMiniSearch = null;
477
+ entryDataDir.clear();
478
+ entryById.clear();
158
479
  }
159
480
  //# sourceMappingURL=search.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"search.js","sourceRoot":"","sources":["../../../src/docs/search.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../../src/docs/search.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,UAAU,MAAM,YAAY,CAAC;AAEpC,OAAO,EAAC,SAAS,EAAC,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,GAKjB,MAAM,YAAY,CAAC;AAEpB;;;;GAIG;AACH,MAAM,WAAW,GAAsB,CAAC,mBAAmB,EAAE,kBAAkB,EAAE,eAAe,EAAE,gBAAgB,CAAC,CAAC;AAEpH,wEAAwE;AACxE,MAAM,eAAe,GAAG,GAAG,CAAC;AAE5B;;;;GAIG;AACH,MAAM,uBAAuB,GAAG,MAAM,CAAC;AAEvC;;;;;;;;;GASG;AACH,MAAM,4BAA4B,GAAG,GAAG,CAAC;AAEzC;;;;;;GAMG;AACH,MAAM,+BAA+B,GAA2B,CAAC,MAAM,EAAE,yBAAyB,EAAE,QAAQ,CAAC,CAAC;AAE9G;;;;;;;;;GASG;AACH,MAAM,iBAAiB,GAAoD;IACzE,YAAY,EAAE,EAAE;IAChB,UAAU,EAAE,EAAE;IACd,cAAc,EAAE,EAAE;IAClB,yBAAyB,EAAE,EAAE;IAC7B,MAAM,EAAE,EAAE;IACV,IAAI,EAAE,EAAE;IACR,cAAc,EAAE,EAAC,cAAc,EAAE,IAAI,EAAC;IACtC,OAAO,EAAE,EAAC,cAAc,EAAE,IAAI,EAAC;CAChC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAA2B,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAkB,CAAC;AAEtG,+FAA+F;AAC/F,MAAM,eAAe,GAA2B,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;AAElH;;;;;;;;;;;;;GAaG;AACH,MAAM,oBAAoB,GAAgD;IACxE,UAAU,EAAE,CAAC,YAAY,EAAE,UAAU,CAAC;IACtC,IAAI,EAAE,CAAC,MAAM,CAAC;IACd,YAAY,EAAE,CAAC,yBAAyB,EAAE,cAAc,CAAC;IACzD,iBAAiB,EAAE,CAAC,QAAQ,EAAE,cAAc,CAAC;CAC9C,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,wBAAwB,CACtC,KAA6C,EAC7C,SAAuC;IAEvC,IAAI,KAAK,IAAI,SAAS;QAAE,OAAO,SAAS,CAAC;IACzC,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACpE,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACjF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAEzC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAS,cAAc,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAkB,EAAE,CAAC;IAChC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,IAAmB,CAAC,CAAC;;YAChD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,SAAS,EAAE,CAAC,OAAO,CAAC,CAAC;IAC7C,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC5D,CAAC;AAED,yEAAyE;AACzE,SAAS,eAAe,CAAC,SAAuC;IAC9D,IAAI,CAAC,SAAS;QAAE,OAAO,SAAS,CAAC;IACjC,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAChE,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AACxC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAAsC;IAC3E,MAAM,IAAI,GAAG,eAAe,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;IAC9C,MAAM,GAAG,GAAG,IAAI,GAAG,CAAc,eAAe,CAAC,CAAC;IAClD,KAAK,MAAM,MAAM,IAAI,IAAI,EAAE,CAAC;QAC1B,KAAK,MAAM,GAAG,IAAI,oBAAoB,CAAC,MAAM,CAAC,IAAI,EAAE;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC;AAClB,CAAC;AAED,uEAAuE;AACvE,IAAI,WAAW,GAAuB,IAAI,CAAC;AAC3C,IAAI,gBAAgB,GAAkC,IAAI,CAAC;AAE3D,iFAAiF;AACjF,8EAA8E;AAC9E,iFAAiF;AACjF,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;AAE/C,oEAAoE;AACpE,MAAM,SAAS,GAAG,IAAI,GAAG,EAAoB,CAAC;AAY9C;;;;GAIG;AACH,SAAS,WAAW,CAAC,KAAe;IAClC,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,EAAC,GAAG,KAAK,CAAC;IAC7C,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,SAAS,UAAU,CAAC,OAAe;IACjC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IACnD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAgB,CAAC;IAC9E,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnC,IAAI,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAAE,SAAS,CAAC,oCAAoC;QAC3E,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QAC/B,uEAAuE;QACvE,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACnB,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,OAAO,CAAC;AACxB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe;IAC7B,IAAI,WAAW;QAAE,OAAO,WAAW,CAAC;IAEpC,YAAY,CAAC,KAAK,EAAE,CAAC;IACrB,SAAS,CAAC,KAAK,EAAE,CAAC;IAElB,MAAM,OAAO,GAAe,EAAE,CAAC;IAC/B,MAAM,SAAS,GAA2B,EAAE,CAAC;IAC7C,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;QAC/B,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;QAC9C,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;IAC1B,CAAC;IAED,SAAS,EAAE,CAAC,KAAK,CAAC,EAAC,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,EAAC,EAAE,4CAA4C,CAAC,CAAC;IAEpG,WAAW,GAAG;QACZ,OAAO,EAAE,OAAO;QAChB,WAAW,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;QACtC,OAAO;KACR,CAAC;IACF,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;;;;;GAMG;AACH,SAAS,aAAa;IACpB,IAAI,gBAAgB;QAAE,OAAO,gBAAgB,CAAC;IAE9C,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAEhC,MAAM,EAAE,GAAG,IAAI,UAAU,CAAa;QACpC,OAAO,EAAE,IAAI;QACb,MAAM,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,CAAC;QAC1D,2EAA2E;QAC3E,WAAW,EAAE,CAAC,UAAU,CAAC;QACzB,aAAa,EAAE;YACb,KAAK,EAAE,EAAC,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,EAAC;YAClE,KAAK,EAAE,GAAG;YACV,MAAM,EAAE,IAAI;YACZ,2EAA2E;YAC3E,qEAAqE;YACrE,0EAA0E;YAC1E,iEAAiE;YACjE,wEAAwE;SACzE;KACF,CAAC,CAAC;IAEH,EAAE,CAAC,MAAM,CACP,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACxB,EAAE,EAAE,CAAC,CAAC,EAAE;QACR,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,EAAE;QACpB,QAAQ,EAAE,CAAC,CAAC,QAAQ,IAAI,EAAE;QAC1B,QAAQ,EAAE,CAAC,CAAC,QAAQ,IAAI,EAAE;QAC1B,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,EAAE;QACxB,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE;KAChE,CAAC,CAAC,CACJ,CAAC;IAEF,SAAS,EAAE,CAAC,KAAK,CAAC,EAAC,aAAa,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,EAAC,EAAE,iDAAiD,CAAC,CAAC;IAE5G,gBAAgB,GAAG,EAAE,CAAC;IACtB,OAAO,EAAE,CAAC;AACZ,CAAC;AA+BD,oGAAoG;AACpG,SAAS,mBAAmB,CAC1B,CAAqC,EACrC,CAAqC;IAErC,IAAI,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACtC,IAAI,CAAC,CAAC;QAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IACtB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;IACxB,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACtC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,UAAU,CAAC,KAAa,EAAE,cAA2C;IACnF,MAAM,IAAI,GAAsB,OAAO,cAAc,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAC,KAAK,EAAE,cAAc,EAAC,CAAC,CAAC,CAAC,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;IACtH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;IAE/B,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAEnD,gFAAgF;IAChF,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAE9G,4EAA4E;IAC5E,sEAAsE;IACtE,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC;IAE/E,6EAA6E;IAC7E,6EAA6E;IAC7E,8EAA8E;IAC9E,MAAM,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC,IAAI,GAAG,CAAc,sBAAsB,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACnG,MAAM,YAAY,GAAG,QAAQ;QAC3B,CAAC,CAAC,IAAI,GAAG,CAAc,+BAA+B,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACvF,CAAC,CAAC,SAAS,CAAC;IAEd,MAAM,EAAE,GAAG,aAAa,EAAE,CAAC;IAE3B,MAAM,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE;QAC3B,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAuB,CAAC,CAAC,CAAC,CAAC,SAAS;QAClG,aAAa,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE;YAC1C,MAAM,QAAQ,GAAG,YAAY,EAAE,QAAmC,CAAC;YACnE,IAAI,CAAC,QAAQ;gBAAE,OAAO,CAAC,CAAC;YACxB,IAAI,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC;gBAAE,OAAO,eAAe,CAAC;YACpD,IAAI,YAAY,EAAE,GAAG,CAAC,QAAQ,CAAC;gBAAE,OAAO,4BAA4B,CAAC;YACrE,OAAO,CAAC,CAAC;QACX,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;QACpB,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAY,CAAC,CAAC;QAC5C,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,OAAO,CAAC,IAAI,CAAC,EAAC,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAC,CAAC,CAAC;QAC1D,IAAI,OAAO,CAAC,MAAM,IAAI,KAAK;YAAE,MAAM;IACrC,CAAC;IAED,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,CAAC,KAAK,CACV,EAAC,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,MAAM,EAAC,EAC3F,2BAA2B,CAC5B,CAAC;IACF,MAAM,CAAC,KAAK,CACV,EAAC,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAC,CAAC,CAAC,EAAC,EAChF,sBAAsB,CACvB,CAAC;IAEF,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,QAAQ,CACtB,QAAsC,EACtC,iBAA0C;IAE1C,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1F,MAAM,UAAU,GAAG,mBAAmB,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC;IACpE,MAAM,OAAO,GAAG,UAAU;QACxB,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC5E,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC;IAClB,OAAO,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;AAClC,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,EAAU;IACtC,eAAe,EAAE,CAAC;IAClB,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,4BAA4B,EAAE,EAAE,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,gBAAgB,CAAC,KAAK,CAAC,CAAC;AACjC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,KAAe;IACpD,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC3C,IAAI,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC9B,MAAM,CAAC,KAAK,CAAC,EAAC,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAC,EAAE,qCAAqC,CAAC,CAAC;QACjH,OAAO,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;IACtE,CAAC;IACD,2EAA2E;IAC3E,uEAAuE;IACvE,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,GAAG,CAAC;IAC9C,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,CAAC,KAAK,CAAC,EAAC,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAC,EAAE,oCAAoC,CAAC,CAAC;QAC/F,OAAO,kBAAkB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC7C,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,8CAA8C,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;AAC5E,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,kBAAkB,CAAC,KAAe,EAAE,QAAgB;IACjE,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,IAAI,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,EAAC,QAAQ,EAAC,EAAE,uCAAuC,CAAC,CAAC;QAClE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE;YAChC,OAAO,EAAE,EAAC,MAAM,EAAE,gCAAgC,EAAC;YACnD,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,uBAAuB,CAAC;SACrD,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,CAAC,KAAK,CAAC,EAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAC,EAAE,yCAAyC,CAAC,CAAC;YACxF,OAAO,eAAe,CAAC,KAAK,EAAE,QAAQ,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACtD,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,CAAC,KAAK,CAAC,EAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,EAAC,EAAE,sCAAsC,CAAC,CAAC;QACrF,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,KAAK,CAAC,EAAC,QAAQ,EAAE,GAAG,EAAC,EAAE,yBAAyB,CAAC,CAAC;QACzD,OAAO,eAAe,CAAC,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAClF,CAAC;AACH,CAAC;AAED,oFAAoF;AACpF,SAAS,eAAe,CAAC,KAAe,EAAE,MAAc;IACtD,MAAM,KAAK,GAAG,CAAC,KAAK,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;IACvC,IAAI,KAAK,CAAC,OAAO;QAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACjD,IAAI,KAAK,CAAC,QAAQ;QAChB,KAAK,CAAC,IAAI,CACR,aAAa,EACb,EAAE,EACF,KAAK,CAAC,QAAQ;aACX,KAAK,CAAC,KAAK,CAAC;aACZ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;aACpB,IAAI,CAAC,IAAI,CAAC,EACb,EAAE,CACH,CAAC;IACJ,IAAI,KAAK,CAAC,GAAG;QAAE,KAAK,CAAC,IAAI,CAAC,uBAAuB,KAAK,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;IAClE,KAAK,CAAC,IAAI,CAAC,8CAA8C,MAAM,kCAAkC,CAAC,CAAC;IACnG,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,KAAa,EACb,OAA2B;IAE3B,4EAA4E;IAC5E,8EAA8E;IAC9E,2DAA2D;IAC3D,eAAe,EAAE,CAAC;IAClB,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ;YAChC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC;gBAC/B,CAAC,CAAC,OAAO,CAAC,QAAQ;gBAClB,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;YACtB,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,UAAU,GAAG,mBAAmB,CAAC,OAAO,EAAE,iBAAiB,EAAE,QAAQ,CAAC,CAAC;QAC7E,IAAI,CAAC,UAAU,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;YAC3E,oEAAoE;YACpE,8DAA8D;YAC9D,OAAO,EAAC,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC,KAAK,CAAC,EAAC,CAAC;QAC7E,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,EAAE,EAAC,GAAG,OAAO,EAAE,KAAK,EAAE,CAAC,EAAC,CAAC,CAAC;IAC1D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACtE,OAAO,EAAC,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC,MAAM,CAAC,EAAC,CAAC;AAC/E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc;IAC5B,WAAW,GAAG,IAAI,CAAC;IACnB,gBAAgB,GAAG,IAAI,CAAC;IACxB,YAAY,CAAC,KAAK,EAAE,CAAC;IACrB,SAAS,CAAC,KAAK,EAAE,CAAC;AACpB,CAAC"}