plumb-fhir 0.6.2 → 0.7.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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.7.0 (2026-10-05)
4
+
5
+ - **`stampProfiled(resource, options?)`** returns the copy `createProfiled`
6
+ would write, routed and stamped, without writing it: for conditional
7
+ creates, upserts and batch or transaction entries. It takes the same
8
+ options, is typed the same way, and throws the same `RoutingError` (#124).
9
+ - The README says `updateProfiled` stamps a record that was unstamped, so
10
+ edits of stored records that fail the profile start being refused; and to
11
+ commit `fsh-generated/resources/` but gitignore SUSHI's index files (#125).
12
+
3
13
  ## 0.6.2 (2026-10-05)
4
14
 
5
15
  `validate` and `push` from an installed Plumb, and on Medplum's `awslambda`
package/README.md CHANGED
@@ -185,8 +185,11 @@ export default defineConfig({
185
185
  ✔ sushi 1 StructureDefinitions, 0 ValueSets 6.8s
186
186
  ```
187
187
 
188
- - **Commit `fsh-generated/`** with the FSH. It is the JSON `push` loads into
189
- Medplum, and `validateProfiled` reads it without running SUSHI.
188
+ - **Commit `fsh-generated/resources/`** with the FSH. It is the JSON `push`
189
+ loads into Medplum, and `validateProfiled` reads it without running SUSHI.
190
+ SUSHI's own `fsh-index.txt` and `data/` are bookkeeping no command reads:
191
+ gitignore them. Marking the generated folders `linguist-generated` in
192
+ `.gitattributes` collapses them in review diffs.
190
193
  - **`generate --check` in CI** rebuilds the FSH into a temporary folder and
191
194
  fails when the committed `fsh-generated/` or the types differ from it.
192
195
  - **SUSHI's errors stop `generate`**, with their FSH file and line. Its
@@ -240,6 +243,22 @@ const saved = await createProfiled(medplum, bp); // stamped, then medplum.create
240
243
  - They take any client with `createResource` and `updateResource`, such as
241
244
  a `MedplumClient`, so the generated code needs nothing from Plumb at run
242
245
  time.
246
+ - **`stampProfiled(resource, options?)`** returns the copy `createProfiled`
247
+ would write, stamped and not written, for the writes it cannot make: a
248
+ conditional create, an upsert, a batch or transaction entry. It takes the
249
+ same options and throws the same `RoutingError`:
250
+
251
+ ```ts
252
+ await medplum.createResourceIfNoneExist(
253
+ stampProfiled(coverage, { profile: USCoreCoverageProfileUrl }),
254
+ `identifier=${system}|${value}`,
255
+ );
256
+ ```
257
+
258
+ - **Moving an edit path to `updateProfiled` stamps records that were
259
+ unstamped**, so the server starts holding them to the profile: an edit of a
260
+ stored record that does not meet it is refused from then on. Run
261
+ `plumb validate` and fix what fails before moving edit paths.
243
262
 
244
263
  **Keys come from each profile:** every fixed or pattern value on a required
245
264
  first-level element (a pinned `code`), and every required slice's
@@ -1 +1 @@
1
- {"version":3,"file":"print.d.ts","sourceRoot":"","sources":["../../../src/emit/print.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAS,OAAO,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAiB,YAAY,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE5E,uFAAuF;AACvF,eAAO,MAAM,MAAM,0BAA0B,CAAC;AAqG9C,wFAAwF;AACxF,wBAAgB,SAAS,CAAC,CAAC,EAAE,QAAQ,GAAG,MAAM,CAgD7C;AA8UD,KAAK,YAAY,GAAG,IAAI,CAAC,OAAO,EAAE,QAAQ,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC,CAAC;AAkR5F,kHAAkH;AAClH,wBAAgB,UAAU,CACxB,MAAM,EAAE,YAAY,EAAE,EACtB,MAAM,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,MAAM,EACvC,OAAO,GAAE,YAAiF,GACzF,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAyBrB"}
1
+ {"version":3,"file":"print.d.ts","sourceRoot":"","sources":["../../../src/emit/print.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAS,OAAO,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAiB,YAAY,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE5E,uFAAuF;AACvF,eAAO,MAAM,MAAM,0BAA0B,CAAC;AAqG9C,wFAAwF;AACxF,wBAAgB,SAAS,CAAC,CAAC,EAAE,QAAQ,GAAG,MAAM,CAgD7C;AA+VD,KAAK,YAAY,GAAG,IAAI,CAAC,OAAO,EAAE,QAAQ,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC,CAAC;AAkR5F,kHAAkH;AAClH,wBAAgB,UAAU,CACxB,MAAM,EAAE,YAAY,EAAE,EACtB,MAAM,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,MAAM,EACvC,OAAO,GAAE,YAAiF,GACzF,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAyBrB"}
package/dist/esm/cli.mjs CHANGED
@@ -2313,6 +2313,23 @@ export async function createProfiled(
2313
2313
  return medplum.createResource(stamped(resource, options.profile ?? route(resource)));
2314
2314
  }
2315
2315
 
2316
+ /**
2317
+ * The copy createProfiled would write, stamped and not written, for the writes
2318
+ * it cannot make: a conditional create, an upsert, a batch or transaction
2319
+ * entry. Options and errors as createProfiled; a RoutingError is thrown.
2320
+ */
2321
+ export function stampProfiled<U extends ProfileUrl>(
2322
+ resource: ProfileTypes[U],
2323
+ options: { profile: U },
2324
+ ): ProfileTypes[U];
2325
+ export function stampProfiled<T extends Resource>(resource: T, options?: { profile: false }): T;
2326
+ export function stampProfiled(
2327
+ resource: Resource,
2328
+ options: { profile?: ProfileUrl | false } = {},
2329
+ ): Resource {
2330
+ return stamped(resource, options.profile ?? route(resource));
2331
+ }
2332
+
2316
2333
  /**
2317
2334
  * Updates the resource held to the profile its new content selects: the
2318
2335
  * stamps Plumb manages are replaced, and any other URL in \`meta.profile\` is
@@ -2663,7 +2680,7 @@ function printFiles(models, hashOf2, routing = { routes: {}, profiles: [], stamp
2663
2680
  index.appendNoWrap(`${MARKER}. Do not edit.`);
2664
2681
  index.appendNoWrap("export type { Require } from './_plumb.js';");
2665
2682
  index.appendNoWrap(
2666
- "export { createProfiled, type ProfiledClient, type ProfileTypes, type ProfileUrl, RoutingError, route, updateProfiled } from './_routes.js';"
2683
+ "export { createProfiled, type ProfiledClient, type ProfileTypes, type ProfileUrl, RoutingError, route, stampProfiled, updateProfiled } from './_routes.js';"
2667
2684
  );
2668
2685
  index.appendNoWrap(
2669
2686
  "export { asProfiled, isProfiled, pickProfiled, type ProfiledQuery, type ProfiledReader, ProfileReadError, type ProfileReadFailure, readProfiled, searchProfiled } from './_reads.js';"