plumb-fhir 0.6.1 → 0.6.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.6.2 (2026-10-05)
4
+
5
+ `validate` and `push` from an installed Plumb, and on Medplum's `awslambda`
6
+ bot runtime, where the checker now has its first verified run.
7
+
8
+ - **The installed CLI finds its own package.** It stopped at
9
+ `dist/esm/package.json`, so `validate` and `push` failed reading
10
+ `dist/esm/dist/checker.cjs`, and `--version` printed `undefined` (#117,
11
+ #118). `./package.json` is exported.
12
+ - **On the `awslambda` runtime, a page waits while the checker's function is
13
+ not ready** (`Pending` after an install, an update in progress after a
14
+ redeploy), for up to a minute, instead of failing the first gate (#119).
15
+
3
16
  ## 0.6.1 (2026-10-05)
4
17
 
5
18
  Fixes from the first adoption of 0.6.0 in a Medplum monorepo. Regenerate to
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/commands.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,KAAK,OAAO,EAIb,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAiC,KAAK,IAAI,EAAE,MAAM,eAAe,CAAC;AAGzE,MAAM,WAAW,KAAK;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACxC,6DAA6D;IAC7D,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AAgDD,uEAAuE;AACvE,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAe1D;AAED,2EAA2E;AAC3E,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAuBpE;AAqID,KAAK,KAAK,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU,CAAC,CAAC;AAIjD,kGAAkG;AAClG,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,KAAK,GAAG,MAAM,EAAE,CAexD"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/commands.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,KAAK,OAAO,EAIb,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAiC,KAAK,IAAI,EAAE,MAAM,eAAe,CAAC;AAGzE,MAAM,WAAW,KAAK;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACxC,6DAA6D;IAC7D,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AAyDD,uEAAuE;AACvE,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAe1D;AAED,2EAA2E;AAC3E,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAuBpE;AAqID,KAAK,KAAK,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU,CAAC,CAAC;AAIjD,kGAAkG;AAClG,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,KAAK,GAAG,MAAM,EAAE,CAexD"}
@@ -1,5 +1,6 @@
1
1
  import { type MedplumClient } from '@medplum/core';
2
- import type { Reason } from './checker/handler.js';
2
+ import type { PageResult, Reason } from './checker/handler.js';
3
+ import { checkerInput } from './checker/input.js';
3
4
  import { type EnvOptions, type EnvResult } from './connect.js';
4
5
  import type { LoadProfilesResult } from './loader.js';
5
6
  type ValidateStepName = 'load' | 'connect' | 'checker' | 'profiles' | 'validate';
@@ -85,5 +86,7 @@ export declare function judge(result: Pick<Checked, 'types' | 'profiles'>, selec
85
86
  summary: string;
86
87
  failed: boolean;
87
88
  };
89
+ /** One page, as an async job: a page can outlast an HTTP request, not the bot's timeout. */
90
+ export declare function runPage(medplum: MedplumClient, botId: string, input: ReturnType<typeof checkerInput>, wait?: (ms: number) => Promise<void>): Promise<PageResult>;
88
91
  export {};
89
92
  //# sourceMappingURL=conformance.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"conformance.d.ts","sourceRoot":"","sources":["../../src/conformance.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"conformance.d.ts","sourceRoot":"","sources":["../../src/conformance.ts"],"names":[],"mappings":"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"}
package/dist/esm/cli.mjs CHANGED
@@ -1251,8 +1251,8 @@ function registerCore() {
1251
1251
  coreIndexed = true;
1252
1252
  }
1253
1253
  function dependenciesOf(dir) {
1254
- const manifest = JSON.parse(readFileSync(join2(dir, "package", "package.json"), "utf8"));
1255
- return Object.entries(manifest.dependencies ?? {}).map(([name2, version2]) => `${name2}@${version2}`);
1254
+ const manifest2 = JSON.parse(readFileSync(join2(dir, "package", "package.json"), "utf8"));
1255
+ return Object.entries(manifest2.dependencies ?? {}).map(([name2, version2]) => `${name2}@${version2}`);
1256
1256
  }
1257
1257
  var Closure = class {
1258
1258
  definitions = /* @__PURE__ */ new Map();
@@ -1498,8 +1498,8 @@ async function resolve3(igs, lock, check2, cacheDir, fetch) {
1498
1498
  const locked = lock?.packages[id]?.integrity;
1499
1499
  if (check2 && !locked) throw new Failure("lock-disagrees", `plumb.lock does not list ${id}.`);
1500
1500
  const { pkg, integrity } = await ensureCached(id, cacheDir, locked, fetch);
1501
- const manifest = readManifest(id, pkg.dir);
1502
- if (roots.has(id)) queue.push(...dependenciesOf2(id, manifest));
1501
+ const manifest2 = readManifest(id, pkg.dir);
1502
+ if (roots.has(id)) queue.push(...dependenciesOf2(id, manifest2));
1503
1503
  packages.push(pkg);
1504
1504
  integrities[id] = { integrity };
1505
1505
  } catch (err) {
@@ -1542,16 +1542,16 @@ async function ensureCached(id, cacheDir, locked, fetch) {
1542
1542
  return { pkg: { name: name2, version: version2, dir, fetched, integrity }, integrity };
1543
1543
  }
1544
1544
  function readManifest(id, dir) {
1545
- const manifest = JSON.parse(
1545
+ const manifest2 = JSON.parse(
1546
1546
  readFileSync2(join3(dir, "package", "package.json"), "utf8")
1547
1547
  );
1548
- if (manifest.fhirVersions && !manifest.fhirVersions.some((v) => v.startsWith("4.0"))) {
1549
- throw new Failure("not-r4", `${id} is for FHIR ${manifest.fhirVersions.join(", ")}, not R4.`);
1548
+ if (manifest2.fhirVersions && !manifest2.fhirVersions.some((v) => v.startsWith("4.0"))) {
1549
+ throw new Failure("not-r4", `${id} is for FHIR ${manifest2.fhirVersions.join(", ")}, not R4.`);
1550
1550
  }
1551
- return manifest;
1551
+ return manifest2;
1552
1552
  }
1553
- function dependenciesOf2(id, manifest) {
1554
- return Object.entries(manifest.dependencies ?? {}).filter(([name2]) => name2 !== BASE_R4).map(([name2, version2]) => {
1553
+ function dependenciesOf2(id, manifest2) {
1554
+ return Object.entries(manifest2.dependencies ?? {}).filter(([name2]) => name2 !== BASE_R4).map(([name2, version2]) => {
1555
1555
  if (!EXACT_VERSION.test(version2)) {
1556
1556
  throw new Failure(
1557
1557
  "inexact-dependency",
@@ -1570,8 +1570,8 @@ async function download(name2, version2, fetch) {
1570
1570
  if (!response.ok) throw new Failure("registry-error", `${url} returned ${response.status}.`);
1571
1571
  return response;
1572
1572
  };
1573
- const manifest = await (await get(`${REGISTRY}/${name2}`)).json();
1574
- const dist = manifest.versions?.[version2]?.dist;
1573
+ const manifest2 = await (await get(`${REGISTRY}/${name2}`)).json();
1574
+ const dist = manifest2.versions?.[version2]?.dist;
1575
1575
  if (!dist?.tarball || !dist.shasum) {
1576
1576
  throw new Failure("registry-error", `The registry has no ${id}.`);
1577
1577
  }
@@ -1862,20 +1862,31 @@ async function checkType(medplum, saved, options, botId, input, onCore) {
1862
1862
  await options.onPage?.(resourceType, saved.pages);
1863
1863
  } while (!type.done);
1864
1864
  }
1865
- async function runPage(medplum, botId, input) {
1866
- const job = await medplum.post(
1867
- medplum.fhirUrl("Bot", botId, "$execute"),
1868
- input,
1869
- ContentType.JSON,
1870
- { headers: { Prefer: "respond-async" }, pollStatusOnAccepted: true }
1871
- );
1872
- const output = job.output?.parameter ?? [];
1873
- const body = output.find((p) => p.name === "responseBody")?.valueString;
1874
- if (job.status !== "completed" || body === void 0) {
1875
- const outcome = output.find((p) => p.resource)?.resource;
1876
- throw new Error(`The checker's job ended ${job.status}: ${normalizeErrorString2(outcome)}`);
1865
+ var NOT_READY = /currently in the following state: Pending|An update is in progress for resource/;
1866
+ var READY_WAIT_MS = 2e3;
1867
+ var READY_TIMEOUT_MS = 6e4;
1868
+ async function runPage(medplum, botId, input, wait = (ms3) => new Promise((resolve4) => setTimeout(resolve4, ms3))) {
1869
+ for (let waited = 0; ; waited += READY_WAIT_MS) {
1870
+ const job = await medplum.post(
1871
+ medplum.fhirUrl("Bot", botId, "$execute"),
1872
+ input,
1873
+ ContentType.JSON,
1874
+ { headers: { Prefer: "respond-async" }, pollStatusOnAccepted: true }
1875
+ );
1876
+ const output = job.output?.parameter ?? [];
1877
+ const body = output.find((p) => p.name === "responseBody")?.valueString;
1878
+ if (job.status === "completed" && body !== void 0) return JSON.parse(body);
1879
+ const reason = normalizeErrorString2(output.find((p) => p.resource)?.resource);
1880
+ if (!NOT_READY.test(reason)) {
1881
+ throw new Error(`The checker's job ended ${job.status}: ${reason}`);
1882
+ }
1883
+ if (waited >= READY_TIMEOUT_MS) {
1884
+ throw new Error(
1885
+ `The checker bot is still not ready after ${READY_TIMEOUT_MS / 1e3}s: ${reason}`
1886
+ );
1887
+ }
1888
+ await wait(READY_WAIT_MS);
1877
1889
  }
1878
- return JSON.parse(body);
1879
1890
  }
1880
1891
  function merge(saved, type, page) {
1881
1892
  type.read += page.read;
@@ -3588,23 +3599,23 @@ function buildFsh(project, options = {}) {
3588
3599
  return { ok: errors.length === 0, counts, warnings: messages.warn, errors };
3589
3600
  }
3590
3601
  function findSushi(project) {
3591
- let manifest;
3602
+ let manifest2;
3592
3603
  try {
3593
- manifest = createRequire(join6(project, "package.json")).resolve("fsh-sushi/package.json");
3604
+ manifest2 = createRequire(join6(project, "package.json")).resolve("fsh-sushi/package.json");
3594
3605
  } catch {
3595
3606
  return {
3596
3607
  code: "sushi-not-installed",
3597
3608
  message: `"fsh" needs SUSHI, and none is installed for ${project}. Run npm install --save-dev fsh-sushi.`
3598
3609
  };
3599
3610
  }
3600
- const pkg = JSON.parse(readFileSync5(manifest, "utf8"));
3611
+ const pkg = JSON.parse(readFileSync5(manifest2, "utf8"));
3601
3612
  if (Number.parseInt(pkg.version, 10) < OLDEST) {
3602
3613
  return {
3603
3614
  code: "sushi-too-old",
3604
3615
  message: `"fsh" needs SUSHI ${OLDEST} or later; ${pkg.version} is installed. Run npm install --save-dev fsh-sushi@latest.`
3605
3616
  };
3606
3617
  }
3607
- return { bin: join6(dirname4(manifest), typeof pkg.bin === "string" ? pkg.bin : pkg.bin.sushi) };
3618
+ return { bin: join6(dirname4(manifest2), typeof pkg.bin === "string" ? pkg.bin : pkg.bin.sushi) };
3608
3619
  }
3609
3620
  function parseLog(text) {
3610
3621
  const messages = [];
@@ -4034,12 +4045,18 @@ var PROBLEMS = 1;
4034
4045
  var USAGE_ERROR = 2;
4035
4046
  function packageDir() {
4036
4047
  let dir = dirname5(fileURLToPath(import.meta.url));
4037
- while (!existsSync6(join8(dir, "package.json"))) dir = dirname5(dir);
4048
+ while (manifest(dir)?.name !== "plumb-fhir") {
4049
+ if (dir === dirname5(dir)) throw new Error("plumb: cannot find the plumb-fhir package.json.");
4050
+ dir = dirname5(dir);
4051
+ }
4038
4052
  return dir;
4039
4053
  }
4054
+ function manifest(dir) {
4055
+ const file = join8(dir, "package.json");
4056
+ return existsSync6(file) ? JSON.parse(readFileSync6(file, "utf8")) : void 0;
4057
+ }
4040
4058
  function version() {
4041
- const file = join8(packageDir(), "package.json");
4042
- return JSON.parse(readFileSync6(file, "utf8")).version;
4059
+ return manifest(packageDir())?.version ?? "";
4043
4060
  }
4044
4061
  var time = (ms3) => ms3 < 1e3 ? `${ms3}ms` : `${(ms3 / 1e3).toFixed(1)}s`;
4045
4062
  function formatStep(step, out) {