@get-technology-inc/jamf-docs-mcp-server 1.0.0 → 1.1.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.
- package/README.md +61 -139
- package/dist/constants.d.ts +4 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +10 -5
- package/dist/constants.js.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/resources/index.d.ts +13 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +45 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/schemas/index.d.ts +24 -61
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/index.js +18 -1
- package/dist/schemas/index.js.map +1 -1
- package/dist/services/cache.d.ts +4 -13
- package/dist/services/cache.d.ts.map +1 -1
- package/dist/services/cache.js +8 -32
- package/dist/services/cache.js.map +1 -1
- package/dist/services/metadata.d.ts +78 -0
- package/dist/services/metadata.d.ts.map +1 -0
- package/dist/services/metadata.js +349 -0
- package/dist/services/metadata.js.map +1 -0
- package/dist/services/scraper.d.ts +2 -2
- package/dist/services/scraper.d.ts.map +1 -1
- package/dist/services/scraper.js +118 -142
- package/dist/services/scraper.js.map +1 -1
- package/dist/services/search-suggestions.d.ts +27 -0
- package/dist/services/search-suggestions.d.ts.map +1 -0
- package/dist/services/search-suggestions.js +193 -0
- package/dist/services/search-suggestions.js.map +1 -0
- package/dist/services/tokenizer.d.ts +17 -1
- package/dist/services/tokenizer.d.ts.map +1 -1
- package/dist/services/tokenizer.js +122 -66
- package/dist/services/tokenizer.js.map +1 -1
- package/dist/tools/get-article.d.ts +1 -1
- package/dist/tools/get-article.d.ts.map +1 -1
- package/dist/tools/get-article.js +114 -65
- package/dist/tools/get-article.js.map +1 -1
- package/dist/tools/get-toc.d.ts +1 -1
- package/dist/tools/get-toc.d.ts.map +1 -1
- package/dist/tools/get-toc.js +71 -41
- package/dist/tools/get-toc.js.map +1 -1
- package/dist/tools/list-products.d.ts +1 -1
- package/dist/tools/list-products.d.ts.map +1 -1
- package/dist/tools/list-products.js +21 -3
- package/dist/tools/list-products.js.map +1 -1
- package/dist/tools/search.d.ts +1 -1
- package/dist/tools/search.d.ts.map +1 -1
- package/dist/tools/search.js +97 -57
- package/dist/tools/search.js.map +1 -1
- package/dist/types.d.ts +8 -17
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/schemas/index.js
CHANGED
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
* Zod schemas for input validation
|
|
3
3
|
*/
|
|
4
4
|
import { z } from 'zod';
|
|
5
|
-
import { ResponseFormat, JAMF_PRODUCTS, CONTENT_LIMITS, TOKEN_CONFIG, PAGINATION_CONFIG, JAMF_TOPICS } from '../constants.js';
|
|
5
|
+
import { ResponseFormat, OutputMode, JAMF_PRODUCTS, CONTENT_LIMITS, TOKEN_CONFIG, PAGINATION_CONFIG, JAMF_TOPICS } from '../constants.js';
|
|
6
6
|
// Valid product IDs
|
|
7
7
|
const productIds = Object.keys(JAMF_PRODUCTS);
|
|
8
8
|
// Valid topic IDs
|
|
9
9
|
const topicIds = Object.keys(JAMF_TOPICS);
|
|
10
10
|
// Response format enum
|
|
11
11
|
const ResponseFormatSchema = z.nativeEnum(ResponseFormat);
|
|
12
|
+
// Output mode enum
|
|
13
|
+
const OutputModeSchema = z.nativeEnum(OutputMode);
|
|
12
14
|
// Common maxTokens parameter schema
|
|
13
15
|
const MaxTokensSchema = z.number()
|
|
14
16
|
.int()
|
|
@@ -30,6 +32,9 @@ export const ListProductsInputSchema = z.object({
|
|
|
30
32
|
maxTokens: MaxTokensSchema
|
|
31
33
|
.optional()
|
|
32
34
|
.describe(`Maximum tokens in response (${TOKEN_CONFIG.MIN_TOKENS}-${TOKEN_CONFIG.MAX_TOKENS_LIMIT}, default: ${TOKEN_CONFIG.DEFAULT_MAX_TOKENS})`),
|
|
35
|
+
outputMode: OutputModeSchema
|
|
36
|
+
.default(OutputMode.FULL)
|
|
37
|
+
.describe('Output detail level: "full" for detailed output or "compact" for brief output'),
|
|
33
38
|
responseFormat: ResponseFormatSchema
|
|
34
39
|
.default(ResponseFormat.MARKDOWN)
|
|
35
40
|
.describe('Output format: "markdown" for human-readable or "json" for machine-readable')
|
|
@@ -63,6 +68,9 @@ export const SearchInputSchema = z.object({
|
|
|
63
68
|
maxTokens: MaxTokensSchema
|
|
64
69
|
.optional()
|
|
65
70
|
.describe(`Maximum tokens in response (${TOKEN_CONFIG.MIN_TOKENS}-${TOKEN_CONFIG.MAX_TOKENS_LIMIT}, default: ${TOKEN_CONFIG.DEFAULT_MAX_TOKENS})`),
|
|
71
|
+
outputMode: OutputModeSchema
|
|
72
|
+
.default(OutputMode.FULL)
|
|
73
|
+
.describe('Output detail level: "full" for detailed output or "compact" for brief output'),
|
|
66
74
|
responseFormat: ResponseFormatSchema
|
|
67
75
|
.default(ResponseFormat.MARKDOWN)
|
|
68
76
|
.describe('Output format: "markdown" for human-readable or "json" for machine-readable')
|
|
@@ -78,12 +86,18 @@ export const GetArticleInputSchema = z.object({
|
|
|
78
86
|
section: z.string()
|
|
79
87
|
.optional()
|
|
80
88
|
.describe('Extract only a specific section by title or ID (e.g., "Prerequisites", "Configuration")'),
|
|
89
|
+
summaryOnly: z.boolean()
|
|
90
|
+
.default(false)
|
|
91
|
+
.describe('Return only article summary and outline instead of full content (token-efficient)'),
|
|
81
92
|
includeRelated: z.boolean()
|
|
82
93
|
.default(false)
|
|
83
94
|
.describe('Include related article links in the response'),
|
|
84
95
|
maxTokens: MaxTokensSchema
|
|
85
96
|
.optional()
|
|
86
97
|
.describe(`Maximum tokens in response (${TOKEN_CONFIG.MIN_TOKENS}-${TOKEN_CONFIG.MAX_TOKENS_LIMIT}, default: ${TOKEN_CONFIG.DEFAULT_MAX_TOKENS})`),
|
|
98
|
+
outputMode: OutputModeSchema
|
|
99
|
+
.default(OutputMode.FULL)
|
|
100
|
+
.describe('Output detail level: "full" for detailed output or "compact" for brief output'),
|
|
87
101
|
responseFormat: ResponseFormatSchema
|
|
88
102
|
.default(ResponseFormat.MARKDOWN)
|
|
89
103
|
.describe('Output format: "markdown" for human-readable or "json" for machine-readable')
|
|
@@ -103,6 +117,9 @@ export const GetTocInputSchema = z.object({
|
|
|
103
117
|
maxTokens: MaxTokensSchema
|
|
104
118
|
.optional()
|
|
105
119
|
.describe(`Maximum tokens in response (${TOKEN_CONFIG.MIN_TOKENS}-${TOKEN_CONFIG.MAX_TOKENS_LIMIT}, default: ${TOKEN_CONFIG.DEFAULT_MAX_TOKENS})`),
|
|
120
|
+
outputMode: OutputModeSchema
|
|
121
|
+
.default(OutputMode.FULL)
|
|
122
|
+
.describe('Output detail level: "full" for detailed output or "compact" for brief output'),
|
|
106
123
|
responseFormat: ResponseFormatSchema
|
|
107
124
|
.default(ResponseFormat.MARKDOWN)
|
|
108
125
|
.describe('Output format: "markdown" for human-readable or "json" for machine-readable')
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/schemas/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/schemas/index.ts"],"names":[],"mappings":"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"}
|
package/dist/services/cache.d.ts
CHANGED
|
@@ -7,20 +7,11 @@
|
|
|
7
7
|
* File-based cache implementation
|
|
8
8
|
*/
|
|
9
9
|
declare class FileCache {
|
|
10
|
-
private cacheDir;
|
|
11
|
-
private memoryCache;
|
|
10
|
+
private readonly cacheDir;
|
|
11
|
+
private readonly memoryCache;
|
|
12
12
|
constructor(cacheDir?: string);
|
|
13
|
-
|
|
14
|
-
* Generate a cache key hash
|
|
15
|
-
*/
|
|
16
|
-
private getCacheKey;
|
|
17
|
-
/**
|
|
18
|
-
* Get the file path for a cache key
|
|
19
|
-
*/
|
|
13
|
+
private static getCacheKey;
|
|
20
14
|
private getCachePath;
|
|
21
|
-
/**
|
|
22
|
-
* Ensure cache directory exists
|
|
23
|
-
*/
|
|
24
15
|
private ensureCacheDir;
|
|
25
16
|
/**
|
|
26
17
|
* Get a value from cache
|
|
@@ -29,7 +20,7 @@ declare class FileCache {
|
|
|
29
20
|
/**
|
|
30
21
|
* Set a value in cache
|
|
31
22
|
*/
|
|
32
|
-
set
|
|
23
|
+
set(key: string, data: unknown, ttl?: number): Promise<void>;
|
|
33
24
|
/**
|
|
34
25
|
* Delete a cache entry
|
|
35
26
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/services/cache.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH;;GAEG;AACH,cAAM,SAAS;IACb,OAAO,CAAC,QAAQ,CAAS;
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/services/cache.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH;;GAEG;AACH,cAAM,SAAS;IACb,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA0C;gBAE1D,QAAQ,GAAE,MAAkB;IAIxC,OAAO,CAAC,MAAM,CAAC,WAAW;IAI1B,OAAO,CAAC,YAAY;YAIN,cAAc;IAI5B;;OAEG;IACG,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAiC5C;;OAEG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,GAAE,MAAkC,GAAG,OAAO,CAAC,IAAI,CAAC;IAsB7F;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKxC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAa5B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAwBzF;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;CAmC/B;AAGD,eAAO,MAAM,KAAK,WAAkB,CAAC"}
|
package/dist/services/cache.js
CHANGED
|
@@ -16,28 +16,14 @@ class FileCache {
|
|
|
16
16
|
constructor(cacheDir = CACHE_DIR) {
|
|
17
17
|
this.cacheDir = cacheDir;
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
* Generate a cache key hash
|
|
21
|
-
*/
|
|
22
|
-
getCacheKey(key) {
|
|
19
|
+
static getCacheKey(key) {
|
|
23
20
|
return crypto.createHash('md5').update(key).digest('hex');
|
|
24
21
|
}
|
|
25
|
-
/**
|
|
26
|
-
* Get the file path for a cache key
|
|
27
|
-
*/
|
|
28
22
|
getCachePath(key) {
|
|
29
|
-
return path.join(this.cacheDir, `${
|
|
23
|
+
return path.join(this.cacheDir, `${FileCache.getCacheKey(key)}.json`);
|
|
30
24
|
}
|
|
31
|
-
/**
|
|
32
|
-
* Ensure cache directory exists
|
|
33
|
-
*/
|
|
34
25
|
async ensureCacheDir() {
|
|
35
|
-
|
|
36
|
-
await fs.mkdir(this.cacheDir, { recursive: true });
|
|
37
|
-
}
|
|
38
|
-
catch {
|
|
39
|
-
// Directory may already exist
|
|
40
|
-
}
|
|
26
|
+
await fs.mkdir(this.cacheDir, { recursive: true }).catch(() => { });
|
|
41
27
|
}
|
|
42
28
|
/**
|
|
43
29
|
* Get a value from cache
|
|
@@ -45,7 +31,7 @@ class FileCache {
|
|
|
45
31
|
async get(key) {
|
|
46
32
|
// Check memory cache first
|
|
47
33
|
const memCached = this.memoryCache.get(key);
|
|
48
|
-
if (memCached) {
|
|
34
|
+
if (memCached !== undefined) {
|
|
49
35
|
if (Date.now() - memCached.timestamp < memCached.ttl) {
|
|
50
36
|
return memCached.data;
|
|
51
37
|
}
|
|
@@ -90,35 +76,25 @@ class FileCache {
|
|
|
90
76
|
}
|
|
91
77
|
catch (error) {
|
|
92
78
|
// Log but don't fail
|
|
93
|
-
console.error(`[CACHE] Failed to write cache: ${error}`);
|
|
79
|
+
console.error(`[CACHE] Failed to write cache: ${String(error)}`);
|
|
94
80
|
}
|
|
95
81
|
}
|
|
96
82
|
/**
|
|
97
83
|
* Delete a cache entry
|
|
98
84
|
*/
|
|
99
85
|
async delete(key) {
|
|
100
|
-
// Remove from memory
|
|
101
86
|
this.memoryCache.delete(key);
|
|
102
|
-
|
|
103
|
-
try {
|
|
104
|
-
await fs.unlink(this.getCachePath(key));
|
|
105
|
-
}
|
|
106
|
-
catch {
|
|
107
|
-
// File may not exist
|
|
108
|
-
}
|
|
87
|
+
await fs.unlink(this.getCachePath(key)).catch(() => { });
|
|
109
88
|
}
|
|
110
89
|
/**
|
|
111
90
|
* Clear all cache entries
|
|
112
91
|
*/
|
|
113
92
|
async clear() {
|
|
114
|
-
// Clear memory
|
|
115
93
|
this.memoryCache.clear();
|
|
116
|
-
// Clear files
|
|
117
94
|
try {
|
|
118
95
|
const files = await fs.readdir(this.cacheDir);
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
.map(f => fs.unlink(path.join(this.cacheDir, f))));
|
|
96
|
+
const jsonFiles = files.filter(f => f.endsWith('.json'));
|
|
97
|
+
await Promise.all(jsonFiles.map(async (f) => { await fs.unlink(path.join(this.cacheDir, f)); }));
|
|
122
98
|
}
|
|
123
99
|
catch {
|
|
124
100
|
// Directory may not exist
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/services/cache.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAEjC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGvD;;GAEG;AACH,MAAM,SAAS;
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/services/cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metadata service for Jamf documentation
|
|
3
|
+
*
|
|
4
|
+
* Dynamically fetches product versions and topic categories from the API
|
|
5
|
+
* with fallback to static constants.
|
|
6
|
+
*/
|
|
7
|
+
import { type ProductId } from '../constants.js';
|
|
8
|
+
export interface ProductMetadata {
|
|
9
|
+
id: string;
|
|
10
|
+
name: string;
|
|
11
|
+
description: string;
|
|
12
|
+
bundleId: string;
|
|
13
|
+
latestVersion: string;
|
|
14
|
+
availableVersions: string[];
|
|
15
|
+
labelKey: string;
|
|
16
|
+
}
|
|
17
|
+
export interface TopicMetadata {
|
|
18
|
+
id: string;
|
|
19
|
+
name: string;
|
|
20
|
+
source: 'toc' | 'manual';
|
|
21
|
+
articleCount?: number;
|
|
22
|
+
}
|
|
23
|
+
export interface TocCategory {
|
|
24
|
+
navId: string;
|
|
25
|
+
title: string;
|
|
26
|
+
articleCount: number;
|
|
27
|
+
children: string[];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Get all products with their latest metadata
|
|
31
|
+
* Uses cache with fallback to static constants
|
|
32
|
+
*/
|
|
33
|
+
export declare function getProductsMetadata(): Promise<ProductMetadata[]>;
|
|
34
|
+
/**
|
|
35
|
+
* Get the bundle ID for a specific product and version
|
|
36
|
+
* Returns the latest bundle ID if version is undefined or 'current'
|
|
37
|
+
*/
|
|
38
|
+
export declare function getBundleIdForVersion(productId: ProductId, version?: string): Promise<string | null>;
|
|
39
|
+
/**
|
|
40
|
+
* Get available versions for a product
|
|
41
|
+
*/
|
|
42
|
+
export declare function getAvailableVersions(productId: ProductId): Promise<string[]>;
|
|
43
|
+
/**
|
|
44
|
+
* Get all topics, combining TOC-derived from all products and manual topics
|
|
45
|
+
*/
|
|
46
|
+
export declare function getTopicsMetadata(): Promise<TopicMetadata[]>;
|
|
47
|
+
/**
|
|
48
|
+
* Get products data formatted for resource response
|
|
49
|
+
*/
|
|
50
|
+
export declare function getProductsResourceData(): Promise<{
|
|
51
|
+
description: string;
|
|
52
|
+
products: {
|
|
53
|
+
id: string;
|
|
54
|
+
name: string;
|
|
55
|
+
description: string;
|
|
56
|
+
latestVersion: string;
|
|
57
|
+
availableVersions: string[];
|
|
58
|
+
bundleId: string;
|
|
59
|
+
}[];
|
|
60
|
+
lastUpdated: string;
|
|
61
|
+
usage: string;
|
|
62
|
+
}>;
|
|
63
|
+
/**
|
|
64
|
+
* Get topics data formatted for resource response
|
|
65
|
+
*/
|
|
66
|
+
export declare function getTopicsResourceData(): Promise<{
|
|
67
|
+
description: string;
|
|
68
|
+
totalTopics: number;
|
|
69
|
+
topics: {
|
|
70
|
+
id: string;
|
|
71
|
+
name: string;
|
|
72
|
+
source: string;
|
|
73
|
+
articleCount?: number;
|
|
74
|
+
}[];
|
|
75
|
+
lastUpdated: string;
|
|
76
|
+
usage: string;
|
|
77
|
+
}>;
|
|
78
|
+
//# sourceMappingURL=metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/services/metadata.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAML,KAAK,SAAS,EACf,MAAM,iBAAiB,CAAC;AAOzB,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,KAAK,GAAG,QAAQ,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAmID;;;GAGG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CAoCtE;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,SAAS,EACpB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAsBxB;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAIlF;AAmHD;;GAEG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAyClE;AAMD;;GAEG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE;QACR,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,aAAa,EAAE,MAAM,CAAC;QACtB,iBAAiB,EAAE,MAAM,EAAE,CAAC;QAC5B,QAAQ,EAAE,MAAM,CAAC;KAClB,EAAE,CAAC;IACJ,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAgBD;AAED;;GAEG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC;IACrD,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE;QACN,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,EAAE,CAAC;IACJ,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAeD"}
|
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metadata service for Jamf documentation
|
|
3
|
+
*
|
|
4
|
+
* Dynamically fetches product versions and topic categories from the API
|
|
5
|
+
* with fallback to static constants.
|
|
6
|
+
*/
|
|
7
|
+
import axios from 'axios';
|
|
8
|
+
import * as cheerio from 'cheerio';
|
|
9
|
+
import { DOCS_API_URL, JAMF_PRODUCTS, JAMF_TOPICS, REQUEST_CONFIG, CACHE_TTL } from '../constants.js';
|
|
10
|
+
import { cache } from './cache.js';
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// API Helpers
|
|
13
|
+
// ============================================================================
|
|
14
|
+
async function fetchJson(url) {
|
|
15
|
+
const response = await axios.get(url, {
|
|
16
|
+
timeout: REQUEST_CONFIG.TIMEOUT,
|
|
17
|
+
headers: {
|
|
18
|
+
'User-Agent': REQUEST_CONFIG.USER_AGENT,
|
|
19
|
+
'Accept': 'application/json'
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
return response.data;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Discover all available versions for a product
|
|
26
|
+
*/
|
|
27
|
+
async function discoverProductVersions(productId) {
|
|
28
|
+
const product = JAMF_PRODUCTS[productId];
|
|
29
|
+
const versions = new Set();
|
|
30
|
+
try {
|
|
31
|
+
// Search with a broad query to find all bundle versions
|
|
32
|
+
const apiUrl = `${DOCS_API_URL}/api/search?q=${encodeURIComponent(product.name)}&rpp=100`;
|
|
33
|
+
const response = await fetchJson(apiUrl);
|
|
34
|
+
const versionRegex = /-(\d+\.\d+\.\d+)$/;
|
|
35
|
+
const bundlePrefix = `${product.bundleId}-`;
|
|
36
|
+
for (const wrapper of response.Results) {
|
|
37
|
+
const bundleId = wrapper.leading_result?.bundle_id;
|
|
38
|
+
// Skip if no bundle_id (null or undefined)
|
|
39
|
+
if (bundleId === null || bundleId === undefined) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
// Check if this is a versioned documentation bundle for our product
|
|
43
|
+
if (bundleId.startsWith(bundlePrefix) || bundleId === product.bundleId) {
|
|
44
|
+
const match = versionRegex.exec(bundleId);
|
|
45
|
+
if (match?.[1] !== undefined) {
|
|
46
|
+
versions.add(match[1]);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
console.error(`[METADATA] Error discovering versions for ${productId}:`, error);
|
|
53
|
+
}
|
|
54
|
+
// Sort versions in descending order (newest first)
|
|
55
|
+
return Array.from(versions).sort((a, b) => {
|
|
56
|
+
const partsA = a.split('.').map(Number);
|
|
57
|
+
const partsB = b.split('.').map(Number);
|
|
58
|
+
for (let i = 0; i < 3; i++) {
|
|
59
|
+
const diff = (partsB[i] ?? 0) - (partsA[i] ?? 0);
|
|
60
|
+
if (diff !== 0) {
|
|
61
|
+
return diff;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return 0;
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Fetch latest version and metadata for a product from the API
|
|
69
|
+
*/
|
|
70
|
+
async function fetchProductMetadata(productId) {
|
|
71
|
+
const product = JAMF_PRODUCTS[productId];
|
|
72
|
+
try {
|
|
73
|
+
// Discover all available versions
|
|
74
|
+
const availableVersions = await discoverProductVersions(productId);
|
|
75
|
+
// Search for a doc from this product to get the bundle ID and labels
|
|
76
|
+
const apiUrl = `${DOCS_API_URL}/api/search?q=${encodeURIComponent(product.name)}&rpp=5`;
|
|
77
|
+
const response = await fetchJson(apiUrl);
|
|
78
|
+
for (const wrapper of response.Results) {
|
|
79
|
+
const result = wrapper.leading_result;
|
|
80
|
+
const bundleId = result?.bundle_id;
|
|
81
|
+
// Skip if no bundle_id or doesn't match our product
|
|
82
|
+
if (bundleId?.startsWith(product.bundleId) !== true) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
// Extract version from bundle_id (e.g., "jamf-pro-documentation-11.24.0" → "11.24.0")
|
|
86
|
+
const versionRegex = /-(\d+\.\d+\.\d+)$/;
|
|
87
|
+
const versionMatch = versionRegex.exec(bundleId);
|
|
88
|
+
const latestVersion = versionMatch?.[1] ?? 'current';
|
|
89
|
+
// Find product label key
|
|
90
|
+
const productLabel = result?.labels?.find(l => l.key.startsWith('product-') && !l.key.includes('-'));
|
|
91
|
+
const labelKey = productLabel?.key ?? product.searchLabel;
|
|
92
|
+
return {
|
|
93
|
+
id: productId,
|
|
94
|
+
name: product.name,
|
|
95
|
+
description: product.description,
|
|
96
|
+
bundleId,
|
|
97
|
+
latestVersion,
|
|
98
|
+
availableVersions: availableVersions.length > 0 ? availableVersions : [latestVersion],
|
|
99
|
+
labelKey
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
console.error(`[METADATA] Error fetching metadata for ${productId}:`, error);
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Get all products with their latest metadata
|
|
110
|
+
* Uses cache with fallback to static constants
|
|
111
|
+
*/
|
|
112
|
+
export async function getProductsMetadata() {
|
|
113
|
+
const cacheKey = 'metadata:products';
|
|
114
|
+
// Check cache
|
|
115
|
+
const cached = await cache.get(cacheKey);
|
|
116
|
+
if (cached !== null) {
|
|
117
|
+
return cached;
|
|
118
|
+
}
|
|
119
|
+
const products = [];
|
|
120
|
+
// Fetch metadata for each product
|
|
121
|
+
for (const productId of Object.keys(JAMF_PRODUCTS)) {
|
|
122
|
+
const metadata = await fetchProductMetadata(productId);
|
|
123
|
+
if (metadata !== null) {
|
|
124
|
+
products.push(metadata);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
// Fallback to static data
|
|
128
|
+
const product = JAMF_PRODUCTS[productId];
|
|
129
|
+
products.push({
|
|
130
|
+
id: productId,
|
|
131
|
+
name: product.name,
|
|
132
|
+
description: product.description,
|
|
133
|
+
bundleId: product.bundleId,
|
|
134
|
+
latestVersion: product.latestVersion,
|
|
135
|
+
availableVersions: [product.latestVersion],
|
|
136
|
+
labelKey: product.searchLabel
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// Cache for 24 hours
|
|
141
|
+
await cache.set(cacheKey, products, CACHE_TTL.ARTICLE_CONTENT);
|
|
142
|
+
return products;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Get the bundle ID for a specific product and version
|
|
146
|
+
* Returns the latest bundle ID if version is undefined or 'current'
|
|
147
|
+
*/
|
|
148
|
+
export async function getBundleIdForVersion(productId, version) {
|
|
149
|
+
const products = await getProductsMetadata();
|
|
150
|
+
const product = products.find(p => p.id === productId);
|
|
151
|
+
if (product === undefined) {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
// If no version specified or 'current', return latest
|
|
155
|
+
if (version === undefined || version === 'current' || version === 'latest') {
|
|
156
|
+
return product.bundleId;
|
|
157
|
+
}
|
|
158
|
+
// Check if requested version is available
|
|
159
|
+
if (!product.availableVersions.includes(version)) {
|
|
160
|
+
console.error(`[METADATA] Version ${version} not available for ${productId}. Available: ${product.availableVersions.join(', ')}`);
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
// Construct versioned bundle ID
|
|
164
|
+
const baseBundle = JAMF_PRODUCTS[productId].bundleId;
|
|
165
|
+
return `${baseBundle}-${version}`;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Get available versions for a product
|
|
169
|
+
*/
|
|
170
|
+
export async function getAvailableVersions(productId) {
|
|
171
|
+
const products = await getProductsMetadata();
|
|
172
|
+
const product = products.find(p => p.id === productId);
|
|
173
|
+
return product?.availableVersions ?? [];
|
|
174
|
+
}
|
|
175
|
+
// ============================================================================
|
|
176
|
+
// Topic Categories from TOC
|
|
177
|
+
// ============================================================================
|
|
178
|
+
/**
|
|
179
|
+
* Parse TOC HTML to extract categories
|
|
180
|
+
*/
|
|
181
|
+
function parseTocCategories(tocData) {
|
|
182
|
+
const categories = [];
|
|
183
|
+
// Sort by nav ID number
|
|
184
|
+
const sortedEntries = Object.entries(tocData)
|
|
185
|
+
.filter(([key]) => key.startsWith('nav-'))
|
|
186
|
+
.sort((a, b) => {
|
|
187
|
+
const numA = parseInt(a[0].replace('nav-', ''), 10);
|
|
188
|
+
const numB = parseInt(b[0].replace('nav-', ''), 10);
|
|
189
|
+
return numA - numB;
|
|
190
|
+
});
|
|
191
|
+
for (const [navId, html] of sortedEntries) {
|
|
192
|
+
if (typeof html !== 'string' || !html.includes('<ul')) {
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
const $ = cheerio.load(html);
|
|
196
|
+
const children = [];
|
|
197
|
+
// Get all article titles in this section
|
|
198
|
+
$('a').each((_, el) => {
|
|
199
|
+
const title = $(el).text().trim();
|
|
200
|
+
if (title !== '') {
|
|
201
|
+
children.push(title);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
if (children.length > 0) {
|
|
205
|
+
// First child is usually the section title
|
|
206
|
+
const title = children[0] ?? 'Untitled';
|
|
207
|
+
categories.push({
|
|
208
|
+
navId,
|
|
209
|
+
title,
|
|
210
|
+
articleCount: children.length,
|
|
211
|
+
children: children.slice(1) // Exclude the title itself
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return categories;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Convert TOC category to topic ID (slug)
|
|
219
|
+
*/
|
|
220
|
+
function categoryToTopicId(title) {
|
|
221
|
+
return title
|
|
222
|
+
.toLowerCase()
|
|
223
|
+
.replace(/[^a-z0-9\s-]/g, '')
|
|
224
|
+
.replace(/\s+/g, '-')
|
|
225
|
+
.replace(/-+/g, '-')
|
|
226
|
+
.replace(/^-|-$/g, '')
|
|
227
|
+
.slice(0, 30); // Limit length
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Fetch topic categories from TOC for a product
|
|
231
|
+
*/
|
|
232
|
+
async function fetchTopicCategories(productId) {
|
|
233
|
+
try {
|
|
234
|
+
// First get the latest bundle ID
|
|
235
|
+
const products = await getProductsMetadata();
|
|
236
|
+
const product = products.find(p => p.id === productId);
|
|
237
|
+
if (product === undefined) {
|
|
238
|
+
return [];
|
|
239
|
+
}
|
|
240
|
+
const tocUrl = `${DOCS_API_URL}/bundle/${product.bundleId}/toc`;
|
|
241
|
+
const tocData = await fetchJson(tocUrl);
|
|
242
|
+
return parseTocCategories(tocData);
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
console.error(`[METADATA] Error fetching TOC categories for ${productId}:`, error);
|
|
246
|
+
return [];
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Add or update a topic in the map
|
|
251
|
+
*/
|
|
252
|
+
function upsertTopic(topicsMap, category) {
|
|
253
|
+
const topicId = categoryToTopicId(category.title);
|
|
254
|
+
if (!topicsMap.has(topicId)) {
|
|
255
|
+
// Add new topic from TOC
|
|
256
|
+
topicsMap.set(topicId, {
|
|
257
|
+
id: topicId,
|
|
258
|
+
name: category.title,
|
|
259
|
+
source: 'toc',
|
|
260
|
+
articleCount: category.articleCount
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
// Update existing topic with article count (accumulate across products)
|
|
265
|
+
const existing = topicsMap.get(topicId);
|
|
266
|
+
if (existing !== undefined) {
|
|
267
|
+
existing.articleCount = (existing.articleCount ?? 0) + category.articleCount;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Get all topics, combining TOC-derived from all products and manual topics
|
|
273
|
+
*/
|
|
274
|
+
export async function getTopicsMetadata() {
|
|
275
|
+
const cacheKey = 'metadata:topics';
|
|
276
|
+
// Check cache
|
|
277
|
+
const cached = await cache.get(cacheKey);
|
|
278
|
+
if (cached !== null) {
|
|
279
|
+
return cached;
|
|
280
|
+
}
|
|
281
|
+
const topicsMap = new Map();
|
|
282
|
+
// Start with manual topics as fallback
|
|
283
|
+
for (const [id, topic] of Object.entries(JAMF_TOPICS)) {
|
|
284
|
+
topicsMap.set(id, {
|
|
285
|
+
id,
|
|
286
|
+
name: topic.name,
|
|
287
|
+
source: 'manual'
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
// Fetch TOC categories from ALL products
|
|
291
|
+
const productIds = Object.keys(JAMF_PRODUCTS);
|
|
292
|
+
for (const productId of productIds) {
|
|
293
|
+
try {
|
|
294
|
+
const categories = await fetchTopicCategories(productId);
|
|
295
|
+
for (const category of categories) {
|
|
296
|
+
upsertTopic(topicsMap, category);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
catch (error) {
|
|
300
|
+
console.error(`[METADATA] Error fetching TOC for ${productId}:`, error);
|
|
301
|
+
// Continue with other products
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
const topics = Array.from(topicsMap.values());
|
|
305
|
+
// Cache for 24 hours
|
|
306
|
+
await cache.set(cacheKey, topics, CACHE_TTL.ARTICLE_CONTENT);
|
|
307
|
+
return topics;
|
|
308
|
+
}
|
|
309
|
+
// ============================================================================
|
|
310
|
+
// Convenience functions for Resources
|
|
311
|
+
// ============================================================================
|
|
312
|
+
/**
|
|
313
|
+
* Get products data formatted for resource response
|
|
314
|
+
*/
|
|
315
|
+
export async function getProductsResourceData() {
|
|
316
|
+
const products = await getProductsMetadata();
|
|
317
|
+
return {
|
|
318
|
+
description: 'Available Jamf products for documentation search',
|
|
319
|
+
products: products.map(p => ({
|
|
320
|
+
id: p.id,
|
|
321
|
+
name: p.name,
|
|
322
|
+
description: p.description,
|
|
323
|
+
latestVersion: p.latestVersion,
|
|
324
|
+
availableVersions: p.availableVersions,
|
|
325
|
+
bundleId: p.bundleId
|
|
326
|
+
})),
|
|
327
|
+
lastUpdated: new Date().toISOString(),
|
|
328
|
+
usage: 'Use product ID (e.g., "jamf-pro") with jamf_docs_search or jamf_docs_get_toc tools. Use version parameter to query specific versions.'
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Get topics data formatted for resource response
|
|
333
|
+
*/
|
|
334
|
+
export async function getTopicsResourceData() {
|
|
335
|
+
const topics = await getTopicsMetadata();
|
|
336
|
+
return {
|
|
337
|
+
description: 'Topic categories for filtering Jamf documentation searches',
|
|
338
|
+
totalTopics: topics.length,
|
|
339
|
+
topics: topics.map(t => ({
|
|
340
|
+
id: t.id,
|
|
341
|
+
name: t.name,
|
|
342
|
+
source: t.source,
|
|
343
|
+
...(t.articleCount !== undefined ? { articleCount: t.articleCount } : {})
|
|
344
|
+
})),
|
|
345
|
+
lastUpdated: new Date().toISOString(),
|
|
346
|
+
usage: 'Use topic ID (e.g., "enrollment") with jamf_docs_search tool to filter results'
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
//# sourceMappingURL=metadata.js.map
|