@atomic-ehr/fhir-canonical-manager 0.0.14 → 0.0.16

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 (81) hide show
  1. package/dist/cache.d.ts +4 -1
  2. package/dist/cache.d.ts.map +1 -1
  3. package/dist/cache.js +30 -4
  4. package/dist/cache.js.map +1 -1
  5. package/dist/index.d.ts +2 -2
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +1 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/local.d.ts +5 -0
  10. package/dist/local.d.ts.map +1 -0
  11. package/dist/local.js +148 -0
  12. package/dist/local.js.map +1 -0
  13. package/dist/manager/canonical.d.ts.map +1 -1
  14. package/dist/manager/canonical.js +231 -22
  15. package/dist/manager/canonical.js.map +1 -1
  16. package/dist/manager/package-spec.d.ts +5 -0
  17. package/dist/manager/package-spec.d.ts.map +1 -0
  18. package/dist/manager/package-spec.js +28 -0
  19. package/dist/manager/package-spec.js.map +1 -0
  20. package/dist/package.d.ts.map +1 -1
  21. package/dist/package.js +25 -5
  22. package/dist/package.js.map +1 -1
  23. package/dist/{reference/manager.d.ts → reference.d.ts} +8 -3
  24. package/dist/reference.d.ts.map +1 -0
  25. package/dist/{reference/manager.js → reference.js} +7 -2
  26. package/dist/reference.js.map +1 -0
  27. package/dist/{resolver/context.d.ts → resolver.d.ts} +3 -3
  28. package/dist/resolver.d.ts.map +1 -0
  29. package/dist/{resolver/context.js → resolver.js} +1 -1
  30. package/dist/resolver.js.map +1 -0
  31. package/dist/types/core.d.ts +14 -2
  32. package/dist/types/core.d.ts.map +1 -1
  33. package/dist/types/internal.d.ts +4 -2
  34. package/dist/types/internal.d.ts.map +1 -1
  35. package/package.json +2 -3
  36. package/dist/reference/index.d.ts +0 -4
  37. package/dist/reference/index.d.ts.map +0 -1
  38. package/dist/reference/index.js +0 -3
  39. package/dist/reference/index.js.map +0 -1
  40. package/dist/reference/manager.d.ts.map +0 -1
  41. package/dist/reference/manager.js.map +0 -1
  42. package/dist/reference/store.d.ts +0 -6
  43. package/dist/reference/store.d.ts.map +0 -1
  44. package/dist/reference/store.js +0 -6
  45. package/dist/reference/store.js.map +0 -1
  46. package/dist/resolver/context.d.ts.map +0 -1
  47. package/dist/resolver/context.js.map +0 -1
  48. package/dist/resolver/index.d.ts +0 -2
  49. package/dist/resolver/index.d.ts.map +0 -1
  50. package/dist/resolver/index.js +0 -2
  51. package/dist/resolver/index.js.map +0 -1
  52. package/src/cache.ts +0 -58
  53. package/src/cli/index.ts +0 -181
  54. package/src/cli/init.ts +0 -112
  55. package/src/cli/list.ts +0 -95
  56. package/src/cli/resolve.ts +0 -63
  57. package/src/cli/search.ts +0 -83
  58. package/src/cli/searchparam.ts +0 -163
  59. package/src/constants.ts +0 -6
  60. package/src/fs/index.ts +0 -5
  61. package/src/fs/utils.ts +0 -28
  62. package/src/index.ts +0 -18
  63. package/src/manager/canonical.ts +0 -327
  64. package/src/manager/index.ts +0 -6
  65. package/src/package.ts +0 -79
  66. package/src/reference/index.ts +0 -8
  67. package/src/reference/manager.ts +0 -55
  68. package/src/reference/store.ts +0 -14
  69. package/src/resolver/context.ts +0 -25
  70. package/src/resolver/index.ts +0 -5
  71. package/src/scanner/directory.ts +0 -36
  72. package/src/scanner/index.ts +0 -8
  73. package/src/scanner/package.ts +0 -35
  74. package/src/scanner/parser.ts +0 -40
  75. package/src/scanner/processor.ts +0 -65
  76. package/src/search/index.ts +0 -6
  77. package/src/search/smart.ts +0 -50
  78. package/src/search/terms.ts +0 -22
  79. package/src/types/core.ts +0 -131
  80. package/src/types/index.ts +0 -6
  81. package/src/types/internal.ts +0 -59
package/src/constants.ts DELETED
@@ -1,6 +0,0 @@
1
- /**
2
- * Shared constants for FHIR Canonical Manager
3
- */
4
-
5
- // Default FHIR package registry
6
- export const DEFAULT_REGISTRY = "https://fs.get-ig.org/pkgs/";
package/src/fs/index.ts DELETED
@@ -1,5 +0,0 @@
1
- /**
2
- * File system utilities exports
3
- */
4
-
5
- export { ensureDir, fileExists, isFhirPackage } from "./utils.js";
package/src/fs/utils.ts DELETED
@@ -1,28 +0,0 @@
1
- /**
2
- * File system utility functions
3
- */
4
-
5
- import * as fs from "node:fs/promises";
6
- import * as path from "node:path";
7
-
8
- export const fileExists = async (filePath: string): Promise<boolean> => {
9
- try {
10
- await fs.access(filePath);
11
- return true;
12
- } catch {
13
- return false;
14
- }
15
- };
16
-
17
- export const ensureDir = async (dirPath: string): Promise<void> => {
18
- try {
19
- await fs.mkdir(dirPath, { recursive: true });
20
- } catch {
21
- // Ignore errors
22
- }
23
- };
24
-
25
- export const isFhirPackage = async (dirPath: string): Promise<boolean> => {
26
- const indexPath = path.join(dirPath, ".index.json");
27
- return fileExists(indexPath);
28
- };
package/src/index.ts DELETED
@@ -1,18 +0,0 @@
1
- /**
2
- * FHIR Canonical Manager - Modular Implementation
3
- * A package manager for FHIR resources with canonical URL resolution
4
- */
5
-
6
- // Re-export main CanonicalManager factory and class
7
- export { CanonicalManager, createCanonicalManager } from "./manager/index.js";
8
- export type { ReferenceManager as ReferenceManagerType } from "./reference/index.js";
9
- // Re-export reference management
10
- export { createReferenceManager, ReferenceManagerFactory as ReferenceManager } from "./reference/index.js";
11
- // Re-export CanonicalManager type interface with T prefix
12
- export type { CanonicalManager as TCanonicalManager } from "./types/core.js";
13
- // Re-export all public types
14
- export * from "./types/index.js";
15
-
16
- // Default export for backward compatibility
17
- import { createCanonicalManager } from "./manager/index.js";
18
- export default createCanonicalManager;
@@ -1,327 +0,0 @@
1
- /**
2
- * Main CanonicalManager implementation
3
- */
4
-
5
- import * as afs from "node:fs/promises";
6
- import * as Path from "node:path";
7
- import { cacheRecordPaths, createCacheRecord, loadCacheRecordFromDisk, saveCacheRecordToDisk } from "../cache.js";
8
- import { DEFAULT_REGISTRY } from "../constants.js";
9
- import { ensureDir } from "../fs/index.js";
10
- import { installPackages } from "../package.js";
11
- import { resolveWithContext } from "../resolver/index.js";
12
- import { scanDirectory } from "../scanner/index.js";
13
- import { filterBySmartSearch } from "../search/index.js";
14
- import type {
15
- CanonicalManager,
16
- Config,
17
- IndexEntry,
18
- PackageId,
19
- PackageInfo,
20
- Reference,
21
- Resource,
22
- SearchParameter,
23
- SourceContext,
24
- } from "../types/index.js";
25
-
26
- export const createCanonicalManager = (config: Config): CanonicalManager => {
27
- const { packages = [], workingDir } = config;
28
- // Ensure registry URL ends with /
29
- let registry = DEFAULT_REGISTRY;
30
- if (config.registry) {
31
- registry = config.registry.endsWith("/") ? config.registry : `${config.registry}/`;
32
- }
33
-
34
- const cache = createCacheRecord();
35
- let initialized = false;
36
- const searchParamsCache = new Map<string, SearchParameter[]>();
37
-
38
- const ensureInitialized = (): void => {
39
- if (!initialized) {
40
- throw new Error("CanonicalManager not initialized. Call init() first.");
41
- }
42
- };
43
-
44
- const init = async (): Promise<void> => {
45
- if (initialized) return;
46
-
47
- await ensureDir(workingDir);
48
- const { cacheKey, npmPackagePath } = cacheRecordPaths(workingDir, packages);
49
-
50
- const cachedData = await loadCacheRecordFromDisk(workingDir, cacheKey);
51
- const isCacheValid = cachedData && cachedData.packageLockHash === cacheKey;
52
- if (isCacheValid) {
53
- // Restore cache from disk
54
- cache.entries = cachedData.entries;
55
- cache.packages = cachedData.packages;
56
- Object.entries(cachedData.references).forEach(([id, metadata]) => {
57
- cache.referenceManager.set(id, metadata);
58
- });
59
- } else {
60
- await installPackages(packages, npmPackagePath, registry);
61
- await scanDirectory(cache, npmPackagePath);
62
- await saveCacheRecordToDisk(cache, workingDir, cacheKey);
63
- }
64
-
65
- initialized = true;
66
- };
67
-
68
- const destroy = async (): Promise<void> => {
69
- cache.entries = {};
70
- cache.packages = {};
71
- cache.referenceManager.clear();
72
- searchParamsCache.clear();
73
- initialized = false;
74
- };
75
-
76
- const getPackages = async (): Promise<PackageId[]> => {
77
- ensureInitialized();
78
- return Object.values(cache.packages).map((p: PackageInfo) => p.id);
79
- };
80
-
81
- const addPackages = async (...newPackages: string[]): Promise<void> => {
82
- if (newPackages.length === 0) return;
83
-
84
- // Check if packages already exists in packages
85
- const packagesToAdd = newPackages.filter((pkg) => !packages.includes(pkg));
86
- if (packagesToAdd.length !== 0) {
87
- packages.push(...packagesToAdd);
88
- }
89
-
90
- if (!initialized) {
91
- await init();
92
- return;
93
- }
94
-
95
- if (packagesToAdd.length > 0) {
96
- // TODO: very expensive, we can just copy/paste old cache to avoid reinstalling packages
97
- await destroy();
98
- await init();
99
- }
100
- return;
101
- };
102
-
103
- const resolveEntry = async (
104
- canonicalUrl: string,
105
- options?: {
106
- package?: string;
107
- version?: string;
108
- sourceContext?: SourceContext;
109
- },
110
- ): Promise<IndexEntry> => {
111
- ensureInitialized();
112
-
113
- if (options?.sourceContext) {
114
- const contextResolved = await resolveWithContext(canonicalUrl, options.sourceContext, cache, resolveEntry);
115
- if (contextResolved) {
116
- return contextResolved;
117
- }
118
- }
119
-
120
- const entries = cache.entries[canonicalUrl] || [];
121
-
122
- if (entries.length === 0) {
123
- throw new Error(`Cannot resolve canonical URL: ${canonicalUrl}`);
124
- }
125
-
126
- let filtered = [...entries];
127
-
128
- if (options?.package) {
129
- filtered = filtered.filter((e) => e.package?.name === options.package);
130
- }
131
-
132
- if (options?.version) {
133
- filtered = filtered.filter((e) => e.version === options.version);
134
- }
135
-
136
- if (filtered.length === 0) {
137
- throw new Error(`No matching resource found for ${canonicalUrl} with given options`);
138
- }
139
-
140
- const result = filtered[0];
141
- if (!result) {
142
- throw new Error(`No matching resource found for ${canonicalUrl}`);
143
- }
144
- return result;
145
- };
146
-
147
- const resolve = async (
148
- canonicalUrl: string,
149
- options?: {
150
- package?: string;
151
- version?: string;
152
- sourceContext?: SourceContext;
153
- },
154
- ): Promise<Resource> => {
155
- const entry = await resolveEntry(canonicalUrl, options);
156
- return read(entry);
157
- };
158
-
159
- const read = async (reference: Reference): Promise<Resource> => {
160
- ensureInitialized();
161
-
162
- const metadata = cache.referenceManager.get(reference.id);
163
- if (!metadata) {
164
- throw new Error(`Invalid reference ID: ${reference.id}`);
165
- }
166
-
167
- try {
168
- const content = await afs.readFile(metadata.filePath, "utf-8");
169
- const resource = JSON.parse(content);
170
-
171
- return {
172
- ...resource,
173
- id: reference.id,
174
- resourceType: reference.resourceType,
175
- };
176
- } catch (err) {
177
- throw new Error(`Failed to read resource: ${err}`);
178
- }
179
- };
180
-
181
- const searchEntries = async (params: {
182
- kind?: string;
183
- url?: string;
184
- type?: string;
185
- version?: string;
186
- package?: PackageId;
187
- }): Promise<IndexEntry[]> => {
188
- ensureInitialized();
189
-
190
- let results: IndexEntry[] = [];
191
-
192
- if (params.url) {
193
- results = cache.entries[params.url] || [];
194
- } else {
195
- for (const entries of Object.values(cache.entries)) {
196
- results.push(...entries);
197
- }
198
- }
199
-
200
- if (params.kind !== undefined) {
201
- results = results.filter((e) => e.kind === params.kind);
202
- }
203
-
204
- if (params.type !== undefined) {
205
- results = results.filter((e) => e.type === params.type);
206
- }
207
-
208
- if (params.version !== undefined) {
209
- results = results.filter((e) => e.version === params.version);
210
- }
211
-
212
- if (params.package) {
213
- const pkg = params.package;
214
- results = results.filter((e) => e.package?.name === pkg.name && e.package?.version === pkg.version);
215
- }
216
-
217
- return results;
218
- };
219
-
220
- const search = async (params: {
221
- kind?: string;
222
- url?: string;
223
- type?: string;
224
- version?: string;
225
- package?: PackageId;
226
- }): Promise<Resource[]> => {
227
- const entries = await searchEntries(params);
228
- const resources = await Promise.all(entries.map((entry) => read(entry)));
229
- return resources;
230
- };
231
-
232
- const smartSearch = async (
233
- searchTerms: string[],
234
- filters?: {
235
- resourceType?: string;
236
- type?: string;
237
- kind?: string;
238
- package?: PackageId;
239
- },
240
- ): Promise<IndexEntry[]> => {
241
- ensureInitialized();
242
-
243
- // Start with base search using filters
244
- let results = await searchEntries({
245
- kind: filters?.kind,
246
- package: filters?.package,
247
- });
248
-
249
- // Apply resourceType filter
250
- if (filters?.resourceType) {
251
- results = results.filter((entry) => entry.resourceType === filters.resourceType);
252
- }
253
-
254
- // Apply type filter
255
- if (filters?.type) {
256
- results = results.filter((entry) => entry.type === filters.type);
257
- }
258
-
259
- // Apply smart search filtering
260
- return filterBySmartSearch(results, searchTerms);
261
- };
262
-
263
- const getSearchParametersForResource = async (resourceType: string): Promise<SearchParameter[]> => {
264
- ensureInitialized();
265
-
266
- // Check cache first
267
- if (searchParamsCache.has(resourceType)) {
268
- const cached = searchParamsCache.get(resourceType);
269
- if (cached) {
270
- return cached;
271
- }
272
- }
273
-
274
- // Query all SearchParameter resources
275
- // Note: We search by resourceType, not type, because for SearchParameter resources,
276
- // 'type' refers to the search parameter type (token, string, etc.)
277
- const allEntries = await searchEntries({});
278
- const searchParamEntries = allEntries.filter((entry) => entry.resourceType === "SearchParameter");
279
-
280
- const results: SearchParameter[] = [];
281
-
282
- for (const entry of searchParamEntries) {
283
- const resource = await read(entry);
284
-
285
- // Check if this parameter applies to the requested resource
286
- const bases = resource.base || [];
287
- if (Array.isArray(bases) && bases.includes(resourceType)) {
288
- // Return the full original resource - it already contains all fields
289
- // Cast through unknown to satisfy TypeScript
290
- results.push(resource as unknown as SearchParameter);
291
- }
292
- }
293
-
294
- // Sort by code for consistent output
295
- results.sort((a, b) => {
296
- const codeA = a.code || "";
297
- const codeB = b.code || "";
298
- return codeA.localeCompare(codeB);
299
- });
300
-
301
- // Cache the results
302
- searchParamsCache.set(resourceType, results);
303
-
304
- return results;
305
- };
306
-
307
- return {
308
- init,
309
- destroy,
310
- packages: getPackages,
311
- addPackages,
312
- resolveEntry,
313
- resolve,
314
- read,
315
- searchEntries,
316
- search,
317
- smartSearch,
318
- getSearchParametersForResource,
319
- packageJson: async (packageName: string) => {
320
- ensureInitialized();
321
- const fn = cache.packages[packageName]?.path;
322
- if (!fn) throw new Error(`Package ${packageName} not found`);
323
- const packageJSON = JSON.parse(await afs.readFile(Path.join(fn, "package.json"), "utf8"));
324
- return packageJSON;
325
- },
326
- };
327
- };
@@ -1,6 +0,0 @@
1
- /**
2
- * Manager module exports
3
- */
4
-
5
- // For backward compatibility
6
- export { createCanonicalManager, createCanonicalManager as CanonicalManager } from "./canonical.js";
package/src/package.ts DELETED
@@ -1,79 +0,0 @@
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
- };
@@ -1,8 +0,0 @@
1
- /**
2
- * Reference management exports
3
- */
4
-
5
- export type { ReferenceManager } from "./manager.js";
6
- // For backward compatibility - function alias (will be deprecated)
7
- export { createReferenceManager, createReferenceManager as ReferenceManagerFactory } from "./manager.js";
8
- export { generateReferenceId } from "./store.js";
@@ -1,55 +0,0 @@
1
- /**
2
- * Reference manager factory
3
- */
4
-
5
- import type { Reference, ReferenceMetadata, ReferenceStore } from "../types/index.js";
6
- import { generateReferenceId } from "./store.js";
7
-
8
- export interface ReferenceManager extends ReferenceStore {
9
- generateId: typeof generateReferenceId;
10
- getIdsByUrl: (url: string) => string[];
11
- createReference: (id: string, metadata: ReferenceMetadata) => Reference;
12
- getAllReferences: () => Record<string, ReferenceMetadata>;
13
- }
14
-
15
- export const createReferenceManager = (): ReferenceManager => {
16
- const references: Record<string, ReferenceMetadata> = {};
17
- const urlToIds: Record<string, string[]> = {};
18
-
19
- const set = (id: string, metadata: ReferenceMetadata): void => {
20
- references[id] = metadata;
21
- if (metadata.url) {
22
- if (!urlToIds[metadata.url]) {
23
- urlToIds[metadata.url] = [];
24
- }
25
- const ids = urlToIds[metadata.url];
26
- if (ids && !ids.includes(id)) {
27
- ids.push(id);
28
- }
29
- }
30
- };
31
-
32
- const clear = (): void => {
33
- Object.keys(references).forEach((key) => {
34
- delete references[key];
35
- });
36
- Object.keys(urlToIds).forEach((key) => {
37
- delete urlToIds[key];
38
- });
39
- };
40
-
41
- return {
42
- generateId: generateReferenceId,
43
- get: (id: string) => references[id],
44
- set,
45
- has: (id: string) => id in references,
46
- clear,
47
- size: () => Object.keys(references).length,
48
- getIdsByUrl: (url: string) => urlToIds[url] || [],
49
- createReference: (id: string, metadata: ReferenceMetadata): Reference => ({
50
- id,
51
- resourceType: metadata.resourceType,
52
- }),
53
- getAllReferences: () => references,
54
- };
55
- };
@@ -1,14 +0,0 @@
1
- /**
2
- * Reference store implementation
3
- */
4
-
5
- import { createHash } from "node:crypto";
6
-
7
- export const generateReferenceId = (metadata: {
8
- packageName: string;
9
- packageVersion: string;
10
- filePath: string;
11
- }): string => {
12
- const input = `${metadata.packageName}@${metadata.packageVersion}:${metadata.filePath}`;
13
- return createHash("sha256").update(input).digest("base64url");
14
- };
@@ -1,25 +0,0 @@
1
- /**
2
- * Context-aware resolution functionality
3
- */
4
-
5
- import type { ExtendedCache } from "../cache.js";
6
- import type { IndexEntry, SourceContext } from "../types/index.js";
7
-
8
- export const resolveWithContext = async (
9
- url: string,
10
- context: SourceContext,
11
- _cache: ExtendedCache,
12
- resolveEntry: (url: string, options?: any) => Promise<IndexEntry>,
13
- ): Promise<IndexEntry | null> => {
14
- if (context.package) {
15
- try {
16
- return await resolveEntry(url, {
17
- package: context.package.name,
18
- version: context.package.version,
19
- });
20
- } catch {
21
- // Fall through to global resolution
22
- }
23
- }
24
- return null;
25
- };
@@ -1,5 +0,0 @@
1
- /**
2
- * Resolver module exports
3
- */
4
-
5
- export { resolveWithContext } from "./context.js";
@@ -1,36 +0,0 @@
1
- /**
2
- * Directory scanning functionality
3
- */
4
-
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";
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 });
14
- for (const entry of entries) {
15
- if (!entry.isDirectory()) continue;
16
-
17
- const fullPath = path.join(entry.parentPath, entry.name);
18
-
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;
25
-
26
- const scopedPath = path.join(fullPath, scopedEntry.name);
27
-
28
- if (await isFhirPackage(scopedPath)) {
29
- await scanPackage(scopedPath, cache);
30
- }
31
- }
32
- } else if (await isFhirPackage(fullPath)) {
33
- await scanPackage(fullPath, cache);
34
- }
35
- }
36
- };
@@ -1,8 +0,0 @@
1
- /**
2
- * Scanner module exports
3
- */
4
-
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";
@@ -1,35 +0,0 @@
1
- /**
2
- * Package scanning functionality
3
- */
4
-
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
-
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);
17
-
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;
25
-
26
- await processIndex(packagePath, packageJson, cache);
27
-
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
- }
35
- };