@atomic-ehr/fhir-canonical-manager 0.0.13 → 0.0.15
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/dist/cache.d.ts +17 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +50 -0
- package/dist/cache.js.map +1 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +15 -15
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +7 -10
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/list.d.ts.map +1 -1
- package/dist/cli/list.js +14 -10
- package/dist/cli/list.js.map +1 -1
- package/dist/cli/resolve.js +7 -7
- package/dist/cli/resolve.js.map +1 -1
- package/dist/cli/search.js +9 -9
- package/dist/cli/search.js.map +1 -1
- package/dist/cli/searchparam.d.ts.map +1 -1
- package/dist/cli/searchparam.js +27 -24
- package/dist/cli/searchparam.js.map +1 -1
- package/dist/fs/index.d.ts +1 -1
- package/dist/fs/index.d.ts.map +1 -1
- package/dist/fs/index.js +1 -1
- package/dist/fs/index.js.map +1 -1
- package/dist/fs/utils.js +2 -2
- package/dist/fs/utils.js.map +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/manager/canonical.d.ts +1 -1
- package/dist/manager/canonical.d.ts.map +1 -1
- package/dist/manager/canonical.js +77 -45
- package/dist/manager/canonical.js.map +1 -1
- package/dist/manager/index.d.ts +1 -2
- package/dist/manager/index.d.ts.map +1 -1
- package/dist/manager/index.js +1 -2
- package/dist/manager/index.js.map +1 -1
- package/dist/package.d.ts +4 -0
- package/dist/package.d.ts.map +1 -0
- package/dist/package.js +69 -0
- package/dist/package.js.map +1 -0
- package/dist/{reference/manager.d.ts → reference.d.ts} +8 -3
- package/dist/reference.d.ts.map +1 -0
- package/dist/{reference/manager.js → reference.js} +13 -4
- package/dist/reference.js.map +1 -0
- package/dist/resolver.d.ts +4 -0
- package/dist/resolver.d.ts.map +1 -0
- package/dist/{resolver/context.js → resolver.js} +2 -2
- package/dist/resolver.js.map +1 -0
- package/dist/scanner/directory.d.ts +2 -2
- package/dist/scanner/directory.d.ts.map +1 -1
- package/dist/scanner/directory.js +24 -27
- package/dist/scanner/directory.js.map +1 -1
- package/dist/scanner/index.d.ts +4 -4
- package/dist/scanner/index.d.ts.map +1 -1
- package/dist/scanner/index.js +4 -4
- package/dist/scanner/index.js.map +1 -1
- package/dist/scanner/package.d.ts +1 -1
- package/dist/scanner/package.d.ts.map +1 -1
- package/dist/scanner/package.js +4 -4
- package/dist/scanner/package.js.map +1 -1
- package/dist/scanner/parser.d.ts +2 -2
- package/dist/scanner/parser.d.ts.map +1 -1
- package/dist/scanner/parser.js +1 -1
- package/dist/scanner/parser.js.map +1 -1
- package/dist/scanner/processor.d.ts +2 -2
- package/dist/scanner/processor.d.ts.map +1 -1
- package/dist/scanner/processor.js +3 -3
- package/dist/scanner/processor.js.map +1 -1
- package/dist/search/index.d.ts +2 -2
- package/dist/search/index.d.ts.map +1 -1
- package/dist/search/index.js +2 -2
- package/dist/search/index.js.map +1 -1
- package/dist/search/smart.d.ts +1 -1
- package/dist/search/smart.d.ts.map +1 -1
- package/dist/search/smart.js +3 -7
- package/dist/search/smart.js.map +1 -1
- package/dist/search/terms.js.map +1 -1
- package/dist/types/core.d.ts +5 -4
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.js +2 -2
- package/dist/types/internal.d.ts +7 -4
- package/dist/types/internal.d.ts.map +1 -1
- package/package.json +12 -2
- package/src/cache.ts +59 -0
- package/src/cli/index.ts +112 -114
- package/src/cli/init.ts +104 -108
- package/src/cli/list.ts +84 -77
- package/src/cli/resolve.ts +57 -57
- package/src/cli/search.ts +72 -72
- package/src/cli/searchparam.ts +118 -117
- package/src/constants.ts +1 -1
- package/src/fs/index.ts +1 -1
- package/src/fs/utils.ts +16 -16
- package/src/index.ts +9 -12
- package/src/manager/canonical.ts +349 -360
- package/src/manager/index.ts +1 -3
- package/src/package.ts +79 -0
- package/src/reference.ts +77 -0
- package/src/resolver.ts +38 -0
- package/src/scanner/directory.ts +25 -31
- package/src/scanner/index.ts +4 -4
- package/src/scanner/package.ts +26 -29
- package/src/scanner/parser.ts +25 -27
- package/src/scanner/processor.ts +51 -55
- package/src/search/index.ts +2 -2
- package/src/search/smart.ts +41 -48
- package/src/search/terms.ts +17 -17
- package/src/types/core.ts +102 -89
- package/src/types/index.ts +2 -2
- package/src/types/internal.ts +36 -34
- package/dist/cache/core.d.ts +0 -7
- package/dist/cache/core.d.ts.map +0 -1
- package/dist/cache/core.js +0 -11
- package/dist/cache/core.js.map +0 -1
- package/dist/cache/index.d.ts +0 -4
- package/dist/cache/index.d.ts.map +0 -1
- package/dist/cache/index.js +0 -4
- package/dist/cache/index.js.map +0 -1
- package/dist/cache/persistence.d.ts +0 -5
- package/dist/cache/persistence.d.ts.map +0 -1
- package/dist/cache/persistence.js +0 -25
- package/dist/cache/persistence.js.map +0 -1
- package/dist/cache/validation.d.ts +0 -2
- package/dist/cache/validation.d.ts.map +0 -1
- package/dist/cache/validation.js +0 -21
- package/dist/cache/validation.js.map +0 -1
- package/dist/package/detector.d.ts +0 -2
- package/dist/package/detector.d.ts.map +0 -1
- package/dist/package/detector.js +0 -19
- package/dist/package/detector.js.map +0 -1
- package/dist/package/index.d.ts +0 -3
- package/dist/package/index.d.ts.map +0 -1
- package/dist/package/index.js +0 -3
- package/dist/package/index.js.map +0 -1
- package/dist/package/installer.d.ts +0 -2
- package/dist/package/installer.d.ts.map +0 -1
- package/dist/package/installer.js +0 -55
- package/dist/package/installer.js.map +0 -1
- package/dist/reference/index.d.ts +0 -5
- package/dist/reference/index.d.ts.map +0 -1
- package/dist/reference/index.js +0 -4
- package/dist/reference/index.js.map +0 -1
- package/dist/reference/manager.d.ts.map +0 -1
- package/dist/reference/manager.js.map +0 -1
- package/dist/reference/store.d.ts +0 -6
- package/dist/reference/store.d.ts.map +0 -1
- package/dist/reference/store.js +0 -6
- package/dist/reference/store.js.map +0 -1
- package/dist/resolver/context.d.ts +0 -4
- package/dist/resolver/context.d.ts.map +0 -1
- package/dist/resolver/context.js.map +0 -1
- package/dist/resolver/index.d.ts +0 -2
- package/dist/resolver/index.d.ts.map +0 -1
- package/dist/resolver/index.js +0 -2
- package/dist/resolver/index.js.map +0 -1
- package/src/cache/core.ts +0 -20
- package/src/cache/index.ts +0 -7
- package/src/cache/persistence.ts +0 -39
- package/src/cache/validation.ts +0 -27
- package/src/package/detector.ts +0 -24
- package/src/package/index.ts +0 -6
- package/src/package/installer.ts +0 -77
- package/src/reference/index.ts +0 -10
- package/src/reference/manager.ts +0 -51
- package/src/reference/store.ts +0 -15
- package/src/resolver/context.ts +0 -25
- package/src/resolver/index.ts +0 -5
package/src/manager/index.ts
CHANGED
|
@@ -2,7 +2,5 @@
|
|
|
2
2
|
* Manager module exports
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
export { createCanonicalManager } from './canonical.js';
|
|
6
|
-
|
|
7
5
|
// For backward compatibility
|
|
8
|
-
export { createCanonicalManager as CanonicalManager } from
|
|
6
|
+
export { createCanonicalManager, createCanonicalManager as CanonicalManager } from "./canonical.js";
|
package/src/package.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Package management functionality
|
|
3
|
+
* Merged from package/detector.ts, package/installer.ts, and package/index.ts
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { exec } from "node:child_process";
|
|
7
|
+
import * as afs from "node:fs/promises";
|
|
8
|
+
import * as Path from "node:path";
|
|
9
|
+
import { promisify } from "node:util";
|
|
10
|
+
import { ensureDir, fileExists } from "./fs/index.js";
|
|
11
|
+
|
|
12
|
+
const execAsync = promisify(exec);
|
|
13
|
+
|
|
14
|
+
export type PackageManager = "bun" | "npm";
|
|
15
|
+
|
|
16
|
+
export const detectPackageManager = async (): Promise<PackageManager | undefined> => {
|
|
17
|
+
try {
|
|
18
|
+
await execAsync("bun --version");
|
|
19
|
+
return "bun";
|
|
20
|
+
} catch {
|
|
21
|
+
try {
|
|
22
|
+
await execAsync("npm --version");
|
|
23
|
+
return "npm";
|
|
24
|
+
} catch {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const ensurePackageJson = async (pwd: string) => {
|
|
31
|
+
const packageJsonPath = Path.join(pwd, "package.json");
|
|
32
|
+
if (!(await fileExists(packageJsonPath))) {
|
|
33
|
+
const minimalPackageJson = {
|
|
34
|
+
name: "fhir-canonical-manager-workspace",
|
|
35
|
+
version: "1.0.0",
|
|
36
|
+
private: true,
|
|
37
|
+
dependencies: {},
|
|
38
|
+
};
|
|
39
|
+
await afs.writeFile(packageJsonPath, JSON.stringify(minimalPackageJson, null, 2));
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const installPackages = async (packages: string[], pwd: string, registry?: string): Promise<void> => {
|
|
44
|
+
await ensureDir(pwd);
|
|
45
|
+
ensurePackageJson(pwd);
|
|
46
|
+
|
|
47
|
+
const packageManager = await detectPackageManager();
|
|
48
|
+
if (!packageManager) throw new Error("No package manager found. Please install bun or npm.");
|
|
49
|
+
|
|
50
|
+
for (const pkg of packages) {
|
|
51
|
+
try {
|
|
52
|
+
if (packageManager === "bun") {
|
|
53
|
+
// Use bun with auth bypass trick for FHIR registry
|
|
54
|
+
const env = {
|
|
55
|
+
...process.env,
|
|
56
|
+
HOME: pwd, // Prevent reading user's .npmrc
|
|
57
|
+
NPM_CONFIG_USERCONFIG: "/dev/null", // Extra safety
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const cmd = registry
|
|
61
|
+
? `bun add ${pkg} --cwd='${pwd}' --registry='${registry}'`
|
|
62
|
+
: `bun add --cwd='${pwd}' ${pkg}`;
|
|
63
|
+
await execAsync(cmd, {
|
|
64
|
+
env,
|
|
65
|
+
maxBuffer: 10 * 1024 * 1024, // 10MB buffer
|
|
66
|
+
});
|
|
67
|
+
} else {
|
|
68
|
+
// Use npm (handles auth correctly)
|
|
69
|
+
const cmd = registry ? `cd ${pwd} && npm add ${pkg} --registry=${registry}` : `npm add ${pkg}`;
|
|
70
|
+
await execAsync(cmd, {
|
|
71
|
+
maxBuffer: 10 * 1024 * 1024, // 10MB buffer
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
} catch (err) {
|
|
75
|
+
console.error(`Failed to install package ${pkg}:`, err);
|
|
76
|
+
throw err;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
package/src/reference.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reference management module
|
|
3
|
+
* Merged from reference/index.ts, reference/manager.ts, and reference/store.ts
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { createHash } from "node:crypto";
|
|
7
|
+
import type { Reference, ReferenceMetadata, ReferenceStore } from "./types/index.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Generate a unique reference ID from metadata
|
|
11
|
+
*/
|
|
12
|
+
export const generateReferenceId = (metadata: {
|
|
13
|
+
packageName: string;
|
|
14
|
+
packageVersion: string;
|
|
15
|
+
filePath: string;
|
|
16
|
+
}): string => {
|
|
17
|
+
const input = `${metadata.packageName}@${metadata.packageVersion}:${metadata.filePath}`;
|
|
18
|
+
return createHash("sha256").update(input).digest("base64url");
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Reference manager interface
|
|
23
|
+
*/
|
|
24
|
+
export interface ReferenceManager extends ReferenceStore {
|
|
25
|
+
generateId: typeof generateReferenceId;
|
|
26
|
+
getIdsByUrl: (url: string) => string[];
|
|
27
|
+
createReference: (id: string, metadata: ReferenceMetadata) => Reference;
|
|
28
|
+
getAllReferences: () => Record<string, ReferenceMetadata>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Create a reference manager instance
|
|
33
|
+
*/
|
|
34
|
+
export const createReferenceManager = (): ReferenceManager => {
|
|
35
|
+
const references: Record<string, ReferenceMetadata> = {};
|
|
36
|
+
const urlToIds: Record<string, string[]> = {};
|
|
37
|
+
|
|
38
|
+
const set = (id: string, metadata: ReferenceMetadata): void => {
|
|
39
|
+
references[id] = metadata;
|
|
40
|
+
if (metadata.url) {
|
|
41
|
+
if (!urlToIds[metadata.url]) {
|
|
42
|
+
urlToIds[metadata.url] = [];
|
|
43
|
+
}
|
|
44
|
+
const ids = urlToIds[metadata.url];
|
|
45
|
+
if (ids && !ids.includes(id)) {
|
|
46
|
+
ids.push(id);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const clear = (): void => {
|
|
52
|
+
Object.keys(references).forEach((key) => {
|
|
53
|
+
delete references[key];
|
|
54
|
+
});
|
|
55
|
+
Object.keys(urlToIds).forEach((key) => {
|
|
56
|
+
delete urlToIds[key];
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
generateId: generateReferenceId,
|
|
62
|
+
get: (id: string) => references[id],
|
|
63
|
+
set,
|
|
64
|
+
has: (id: string) => id in references,
|
|
65
|
+
clear,
|
|
66
|
+
size: () => Object.keys(references).length,
|
|
67
|
+
getIdsByUrl: (url: string) => urlToIds[url] || [],
|
|
68
|
+
createReference: (id: string, metadata: ReferenceMetadata): Reference => ({
|
|
69
|
+
id,
|
|
70
|
+
resourceType: metadata.resourceType,
|
|
71
|
+
}),
|
|
72
|
+
getAllReferences: () => references,
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// For backward compatibility - function alias (will be deprecated)
|
|
77
|
+
export { createReferenceManager as ReferenceManagerFactory };
|
package/src/resolver.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolver module - Context-aware resolution functionality
|
|
3
|
+
* Merged from resolver/index.ts and resolver/context.ts
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { ExtendedCache } from "./cache.js";
|
|
7
|
+
import type { IndexEntry, SourceContext } from "./types/index.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Resolve a canonical URL with context awareness
|
|
11
|
+
*
|
|
12
|
+
* Attempts to resolve a URL within a specific package context first,
|
|
13
|
+
* then falls back to global resolution if the context-specific resolution fails.
|
|
14
|
+
*
|
|
15
|
+
* @param url - The canonical URL to resolve
|
|
16
|
+
* @param context - The source context containing package information
|
|
17
|
+
* @param _cache - The extended cache instance (currently unused but kept for future use)
|
|
18
|
+
* @param resolveEntry - Function to resolve an entry by URL with optional package/version
|
|
19
|
+
* @returns The resolved index entry or null if resolution fails
|
|
20
|
+
*/
|
|
21
|
+
export const resolveWithContext = async (
|
|
22
|
+
url: string,
|
|
23
|
+
context: SourceContext,
|
|
24
|
+
_cache: ExtendedCache,
|
|
25
|
+
resolveEntry: (url: string, options?: any) => Promise<IndexEntry>,
|
|
26
|
+
): Promise<IndexEntry | null> => {
|
|
27
|
+
if (context.package) {
|
|
28
|
+
try {
|
|
29
|
+
return await resolveEntry(url, {
|
|
30
|
+
package: context.package.name,
|
|
31
|
+
version: context.package.version,
|
|
32
|
+
});
|
|
33
|
+
} catch {
|
|
34
|
+
// Fall through to global resolution
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
};
|
package/src/scanner/directory.ts
CHANGED
|
@@ -2,41 +2,35 @@
|
|
|
2
2
|
* Directory scanning functionality
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import * as fs from
|
|
6
|
-
import * as path from
|
|
7
|
-
import type { ExtendedCache } from
|
|
8
|
-
import { isFhirPackage } from
|
|
9
|
-
import { scanPackage } from
|
|
10
|
-
|
|
11
|
-
export const scanDirectory = async (
|
|
12
|
-
dirPath: string,
|
|
13
|
-
cache: ExtendedCache,
|
|
14
|
-
): Promise<void> => {
|
|
15
|
-
try {
|
|
16
|
-
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
5
|
+
import * as fs from "node:fs/promises";
|
|
6
|
+
import * as path from "node:path";
|
|
7
|
+
import type { ExtendedCache } from "../cache.js";
|
|
8
|
+
import { isFhirPackage } from "../fs/index.js";
|
|
9
|
+
import { scanPackage } from "./package.js";
|
|
17
10
|
|
|
11
|
+
export const scanDirectory = async (cache: ExtendedCache, pwd: string): Promise<void> => {
|
|
12
|
+
const nodeModulesPath = path.join(pwd, "node_modules");
|
|
13
|
+
const entries = await fs.readdir(nodeModulesPath, { withFileTypes: true });
|
|
18
14
|
for (const entry of entries) {
|
|
19
|
-
|
|
15
|
+
if (!entry.isDirectory()) continue;
|
|
16
|
+
|
|
17
|
+
const fullPath = path.join(entry.parentPath, entry.name);
|
|
20
18
|
|
|
21
|
-
|
|
19
|
+
if (entry.name.startsWith("@")) {
|
|
20
|
+
const scopedEntries = await fs.readdir(fullPath, {
|
|
21
|
+
withFileTypes: true,
|
|
22
|
+
});
|
|
23
|
+
for (const scopedEntry of scopedEntries) {
|
|
24
|
+
if (!scopedEntry.isDirectory()) continue;
|
|
22
25
|
|
|
23
|
-
|
|
24
|
-
const scopedEntries = await fs.readdir(fullPath, {
|
|
25
|
-
withFileTypes: true,
|
|
26
|
-
});
|
|
27
|
-
for (const scopedEntry of scopedEntries) {
|
|
28
|
-
if (!scopedEntry.isDirectory()) continue;
|
|
26
|
+
const scopedPath = path.join(fullPath, scopedEntry.name);
|
|
29
27
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
if (await isFhirPackage(scopedPath)) {
|
|
29
|
+
await scanPackage(scopedPath, cache);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
} else if (await isFhirPackage(fullPath)) {
|
|
33
|
+
await scanPackage(fullPath, cache);
|
|
34
34
|
}
|
|
35
|
-
} else if (await isFhirPackage(fullPath)) {
|
|
36
|
-
await scanPackage(fullPath, cache);
|
|
37
|
-
}
|
|
38
35
|
}
|
|
39
|
-
|
|
40
|
-
// Silently ignore scan errors
|
|
41
|
-
}
|
|
42
|
-
};
|
|
36
|
+
};
|
package/src/scanner/index.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Scanner module exports
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
export {
|
|
6
|
-
export {
|
|
7
|
-
export {
|
|
8
|
-
export {
|
|
5
|
+
export { scanDirectory } from "./directory.js";
|
|
6
|
+
export { scanPackage } from "./package.js";
|
|
7
|
+
export { isValidFileEntry, isValidIndexFile, parseIndex } from "./parser.js";
|
|
8
|
+
export { processIndex } from "./processor.js";
|
package/src/scanner/package.ts
CHANGED
|
@@ -2,37 +2,34 @@
|
|
|
2
2
|
* Package scanning functionality
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import * as fs from
|
|
6
|
-
import * as path from
|
|
7
|
-
import type {
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
import { processIndex } from
|
|
5
|
+
import * as fs from "node:fs/promises";
|
|
6
|
+
import * as path from "node:path";
|
|
7
|
+
import type { ExtendedCache } from "../cache.js";
|
|
8
|
+
import { fileExists } from "../fs/index.js";
|
|
9
|
+
import type { PackageInfo, PackageJson } from "../types/index.js";
|
|
10
|
+
import { processIndex } from "./processor.js";
|
|
11
11
|
|
|
12
|
-
export const scanPackage = async (
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const packageJsonPath = path.join(packagePath, "package.json");
|
|
18
|
-
const packageJsonContent = await fs.readFile(packageJsonPath, "utf-8");
|
|
19
|
-
const packageJson: PackageJson = JSON.parse(packageJsonContent);
|
|
12
|
+
export const scanPackage = async (packagePath: string, cache: ExtendedCache): Promise<void> => {
|
|
13
|
+
try {
|
|
14
|
+
const packageJsonPath = path.join(packagePath, "package.json");
|
|
15
|
+
const packageJsonContent = await fs.readFile(packageJsonPath, "utf-8");
|
|
16
|
+
const packageJson: PackageJson = JSON.parse(packageJsonContent);
|
|
20
17
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
18
|
+
const packageInfo: PackageInfo = {
|
|
19
|
+
id: { name: packageJson.name, version: packageJson.version },
|
|
20
|
+
path: packagePath,
|
|
21
|
+
canonical: packageJson.canonical,
|
|
22
|
+
fhirVersions: packageJson.fhirVersions,
|
|
23
|
+
};
|
|
24
|
+
cache.packages[packageJson.name] = packageInfo;
|
|
28
25
|
|
|
29
|
-
|
|
26
|
+
await processIndex(packagePath, packageJson, cache);
|
|
30
27
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
const examplesPath = path.join(packagePath, "examples");
|
|
29
|
+
if (await fileExists(path.join(examplesPath, ".index.json"))) {
|
|
30
|
+
await processIndex(examplesPath, packageJson, cache);
|
|
31
|
+
}
|
|
32
|
+
} catch {
|
|
33
|
+
// Silently ignore package scan errors
|
|
34
34
|
}
|
|
35
|
-
|
|
36
|
-
// Silently ignore package scan errors
|
|
37
|
-
}
|
|
38
|
-
};
|
|
35
|
+
};
|
package/src/scanner/parser.ts
CHANGED
|
@@ -2,41 +2,39 @@
|
|
|
2
2
|
* Index file parsing and validation
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type { IndexFile
|
|
5
|
+
import type { IndexFile } from "../types/index.js";
|
|
6
6
|
|
|
7
7
|
export const isValidFileEntry = (entry: any): boolean => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return false;
|
|
12
|
-
if (!entry.id || typeof entry.id !== "string") return false;
|
|
8
|
+
if (!entry || typeof entry !== "object") return false;
|
|
9
|
+
if (!entry.filename || typeof entry.filename !== "string") return false;
|
|
10
|
+
if (!entry.resourceType || typeof entry.resourceType !== "string") return false;
|
|
11
|
+
if (!entry.id || typeof entry.id !== "string") return false;
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
const optionalStringFields = ["url", "version", "kind", "type"];
|
|
14
|
+
for (const field of optionalStringFields) {
|
|
15
|
+
if (entry[field] !== undefined && typeof entry[field] !== "string") {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
18
|
}
|
|
19
|
-
}
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
return true;
|
|
22
21
|
};
|
|
23
22
|
|
|
24
23
|
export const isValidIndexFile = (data: any): boolean => {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return false;
|
|
28
|
-
|
|
29
|
-
return data.files.every((file: any) => isValidFileEntry(file));
|
|
24
|
+
if (!data || typeof data !== "object") return false;
|
|
25
|
+
if (!data["index-version"] || typeof data["index-version"] !== "number") return false;
|
|
26
|
+
if (!Array.isArray(data.files)) return false;
|
|
27
|
+
return data.files.every((file: any) => isValidFileEntry(file));
|
|
30
28
|
};
|
|
31
29
|
|
|
32
|
-
export const parseIndex = (content: string,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
30
|
+
export const parseIndex = (content: string, _filePath: string): IndexFile | null => {
|
|
31
|
+
try {
|
|
32
|
+
const data = JSON.parse(content);
|
|
33
|
+
if (!isValidIndexFile(data)) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
return data as IndexFile;
|
|
37
|
+
} catch {
|
|
38
|
+
return null;
|
|
37
39
|
}
|
|
38
|
-
|
|
39
|
-
} catch {
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
};
|
|
40
|
+
};
|
package/src/scanner/processor.ts
CHANGED
|
@@ -2,68 +2,64 @@
|
|
|
2
2
|
* Index processing functionality
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import * as fs from
|
|
6
|
-
import * as path from
|
|
7
|
-
import type {
|
|
8
|
-
import type {
|
|
9
|
-
import { parseIndex } from
|
|
5
|
+
import * as fs from "node:fs/promises";
|
|
6
|
+
import * as path from "node:path";
|
|
7
|
+
import type { ExtendedCache } from "../cache.js";
|
|
8
|
+
import type { IndexEntry, PackageJson } from "../types/index.js";
|
|
9
|
+
import { parseIndex } from "./parser.js";
|
|
10
10
|
|
|
11
|
-
export const processIndex = async (
|
|
12
|
-
|
|
13
|
-
packageJson: PackageJson,
|
|
14
|
-
cache: ExtendedCache,
|
|
15
|
-
): Promise<void> => {
|
|
16
|
-
const indexPath = path.join(basePath, ".index.json");
|
|
11
|
+
export const processIndex = async (basePath: string, packageJson: PackageJson, cache: ExtendedCache): Promise<void> => {
|
|
12
|
+
const indexPath = path.join(basePath, ".index.json");
|
|
17
13
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
try {
|
|
15
|
+
const indexContent = await fs.readFile(indexPath, "utf-8");
|
|
16
|
+
const index = parseIndex(indexContent, indexPath);
|
|
21
17
|
|
|
22
|
-
|
|
18
|
+
if (!index) return;
|
|
23
19
|
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
for (const file of index.files) {
|
|
21
|
+
if (!file.url) continue;
|
|
26
22
|
|
|
27
|
-
|
|
23
|
+
const filePath = path.join(basePath, file.filename);
|
|
28
24
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
const id = cache.referenceManager.generateId({
|
|
26
|
+
packageName: packageJson.name,
|
|
27
|
+
packageVersion: packageJson.version,
|
|
28
|
+
filePath,
|
|
29
|
+
});
|
|
34
30
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
31
|
+
cache.referenceManager.set(id, {
|
|
32
|
+
packageName: packageJson.name,
|
|
33
|
+
packageVersion: packageJson.version,
|
|
34
|
+
filePath,
|
|
35
|
+
resourceType: file.resourceType,
|
|
36
|
+
url: file.url,
|
|
37
|
+
version: file.version,
|
|
38
|
+
});
|
|
43
39
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
40
|
+
const entry: IndexEntry = {
|
|
41
|
+
id,
|
|
42
|
+
resourceType: file.resourceType,
|
|
43
|
+
indexVersion: index["index-version"],
|
|
44
|
+
url: file.url,
|
|
45
|
+
version: file.version,
|
|
46
|
+
kind: file.kind,
|
|
47
|
+
type: file.type,
|
|
48
|
+
package: {
|
|
49
|
+
name: packageJson.name,
|
|
50
|
+
version: packageJson.version,
|
|
51
|
+
},
|
|
52
|
+
};
|
|
57
53
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
54
|
+
if (!cache.entries[file.url]) {
|
|
55
|
+
cache.entries[file.url] = [];
|
|
56
|
+
}
|
|
57
|
+
const entries = cache.entries[file.url];
|
|
58
|
+
if (entries) {
|
|
59
|
+
entries.push(entry);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
} catch {
|
|
63
|
+
// Silently ignore index processing errors
|
|
65
64
|
}
|
|
66
|
-
|
|
67
|
-
// Silently ignore index processing errors
|
|
68
|
-
}
|
|
69
|
-
};
|
|
65
|
+
};
|
package/src/search/index.ts
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
* Search module exports
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
export {
|
|
6
|
-
export {
|
|
5
|
+
export { filterBySmartSearch, type SmartSearchFilters } from "./smart.js";
|
|
6
|
+
export { expandedTerms } from "./terms.js";
|
package/src/search/smart.ts
CHANGED
|
@@ -2,56 +2,49 @@
|
|
|
2
2
|
* Smart search functionality with abbreviation support
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type { IndexEntry, PackageId } from
|
|
6
|
-
import { expandedTerms } from
|
|
5
|
+
import type { IndexEntry, PackageId } from "../types/index.js";
|
|
6
|
+
import { expandedTerms } from "./terms.js";
|
|
7
7
|
|
|
8
8
|
export interface SmartSearchFilters {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
resourceType?: string;
|
|
10
|
+
type?: string;
|
|
11
|
+
kind?: string;
|
|
12
|
+
package?: PackageId;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
export const filterBySmartSearch = (
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return true;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// If still no match, check if the term appears anywhere (substring match)
|
|
54
|
-
return fullText.includes(term);
|
|
15
|
+
export const filterBySmartSearch = (results: IndexEntry[], searchTerms: string[]): IndexEntry[] => {
|
|
16
|
+
if (searchTerms.length === 0) {
|
|
17
|
+
return results;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const terms = searchTerms.map((t) => t.toLowerCase());
|
|
21
|
+
|
|
22
|
+
return results.filter((entry) => {
|
|
23
|
+
if (!entry.url) return false;
|
|
24
|
+
const urlLower = entry.url.toLowerCase();
|
|
25
|
+
|
|
26
|
+
// Also check type and resourceType for matching
|
|
27
|
+
const fullText = [urlLower, entry.type?.toLowerCase() || "", entry.resourceType?.toLowerCase() || ""].join(" ");
|
|
28
|
+
|
|
29
|
+
// Check if all search terms match
|
|
30
|
+
return terms.every((term) => {
|
|
31
|
+
// Split the text into parts (by /, -, _, ., spaces)
|
|
32
|
+
const allParts = fullText.split(/[/\-_.\s]+/);
|
|
33
|
+
|
|
34
|
+
// Check if any part starts with the search term
|
|
35
|
+
const directMatch = allParts.some((part) => part.startsWith(term));
|
|
36
|
+
if (directMatch) return true;
|
|
37
|
+
|
|
38
|
+
// Check if the term is an abbreviation
|
|
39
|
+
const expansions = expandedTerms[term] || [];
|
|
40
|
+
for (const expansion of expansions) {
|
|
41
|
+
if (allParts.some((part) => part.startsWith(expansion))) {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// If still no match, check if the term appears anywhere (substring match)
|
|
47
|
+
return fullText.includes(term);
|
|
48
|
+
});
|
|
55
49
|
});
|
|
56
|
-
|
|
57
|
-
};
|
|
50
|
+
};
|