@entifix/rest 0.13.0 → 0.15.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.
Files changed (73) hide show
  1. package/dist/adapters/entity-rest/build-entity-rest-adapter-delete/build-entity-rest-adapter-delete.d.ts +1 -1
  2. package/dist/adapters/entity-rest/build-entity-rest-adapter-delete/build-entity-rest-adapter-delete.d.ts.map +1 -1
  3. package/dist/adapters/entity-rest/build-entity-rest-adapter-facets/build-entity-rest-adapter-facets.d.ts +1 -1
  4. package/dist/adapters/entity-rest/build-entity-rest-adapter-facets/build-entity-rest-adapter-facets.d.ts.map +1 -1
  5. package/dist/adapters/entity-rest/build-entity-rest-adapter-get/build-entity-rest-adapter-get.d.ts +1 -1
  6. package/dist/adapters/entity-rest/build-entity-rest-adapter-get/build-entity-rest-adapter-get.d.ts.map +1 -1
  7. package/dist/adapters/entity-rest/build-entity-rest-adapter-load/build-entity-rest-adapter-load.d.ts +1 -1
  8. package/dist/adapters/entity-rest/build-entity-rest-adapter-load/build-entity-rest-adapter-load.d.ts.map +1 -1
  9. package/dist/adapters/entity-rest/build-entity-rest-adapter-mixins/build-entity-base-url.d.ts +1 -1
  10. package/dist/adapters/entity-rest/build-entity-rest-adapter-mixins/build-entity-base-url.d.ts.map +1 -1
  11. package/dist/adapters/entity-rest/build-entity-rest-adapter-mixins/index.d.ts +1 -1
  12. package/dist/adapters/entity-rest/build-entity-rest-adapter-save/build-entity-rest-adapter-save.d.ts +4 -8
  13. package/dist/adapters/entity-rest/build-entity-rest-adapter-save/build-entity-rest-adapter-save.d.ts.map +1 -1
  14. package/dist/adapters/entity-rest/build-entity-rest-adapter-save/build-entity-rest-adapter-save.js +15 -94
  15. package/dist/adapters/entity-rest/build-entity-rest-adapter-save/build-entity-rest-adapter-save.js.map +1 -1
  16. package/dist/adapters/entity-rest/build-entity-rest-adapter-write/build-entity-rest-adapter-write.d.ts +10 -0
  17. package/dist/adapters/entity-rest/build-entity-rest-adapter-write/build-entity-rest-adapter-write.d.ts.map +1 -0
  18. package/dist/adapters/entity-rest/build-entity-rest-adapter-write/build-entity-rest-adapter-write.js +49 -0
  19. package/dist/adapters/entity-rest/build-entity-rest-adapter-write/build-entity-rest-adapter-write.js.map +1 -0
  20. package/dist/adapters/entity-rest/build-entity-rest-adapter-write/index.d.ts +2 -0
  21. package/dist/adapters/entity-rest/build-entity-rest-adapter-write/index.d.ts.map +1 -0
  22. package/dist/adapters/entity-rest/build-entity-rest-adapter-write/index.js +3 -0
  23. package/dist/adapters/entity-rest/build-entity-rest-adapter-write/index.js.map +1 -0
  24. package/dist/adapters/entity-rest/pending-save-keys.d.ts +13 -0
  25. package/dist/adapters/entity-rest/pending-save-keys.d.ts.map +1 -0
  26. package/dist/adapters/entity-rest/pending-save-keys.js +13 -0
  27. package/dist/adapters/entity-rest/pending-save-keys.js.map +1 -0
  28. package/dist/adapters/entity-rest/read-write-response.d.ts +13 -0
  29. package/dist/adapters/entity-rest/read-write-response.d.ts.map +1 -0
  30. package/dist/adapters/entity-rest/read-write-response.js +17 -0
  31. package/dist/adapters/entity-rest/read-write-response.js.map +1 -0
  32. package/dist/adapters/entity-rest/types.d.ts +5 -15
  33. package/dist/adapters/entity-rest/types.d.ts.map +1 -1
  34. package/dist/adapters/entity-rest/types.js.map +1 -1
  35. package/dist/adapters/entity-use-case/make-entity-rest-use-case-runner.d.ts +3 -1
  36. package/dist/adapters/entity-use-case/make-entity-rest-use-case-runner.d.ts.map +1 -1
  37. package/dist/adapters/entity-use-case/make-entity-rest-use-case-runner.js +9 -2
  38. package/dist/adapters/entity-use-case/make-entity-rest-use-case-runner.js.map +1 -1
  39. package/dist/adapters/flow-status/build-flow-status-reader/build-flow-status-reader.d.ts +19 -0
  40. package/dist/adapters/flow-status/build-flow-status-reader/build-flow-status-reader.d.ts.map +1 -0
  41. package/dist/adapters/flow-status/build-flow-status-reader/build-flow-status-reader.js +27 -0
  42. package/dist/adapters/flow-status/build-flow-status-reader/build-flow-status-reader.js.map +1 -0
  43. package/dist/adapters/flow-status/build-flow-status-reader/index.d.ts +2 -0
  44. package/dist/adapters/flow-status/build-flow-status-reader/index.d.ts.map +1 -0
  45. package/dist/adapters/flow-status/build-flow-status-reader/index.js +3 -0
  46. package/dist/adapters/flow-status/build-flow-status-reader/index.js.map +1 -0
  47. package/dist/adapters/is-not-found.d.ts +7 -0
  48. package/dist/adapters/is-not-found.d.ts.map +1 -0
  49. package/dist/adapters/is-not-found.js +8 -0
  50. package/dist/adapters/is-not-found.js.map +1 -0
  51. package/dist/clients/types.d.ts +1 -1
  52. package/dist/clients/types.d.ts.map +1 -1
  53. package/dist/clients/types.js.map +1 -1
  54. package/dist/configuration-client/configuration-client-rest-client.d.ts.map +1 -1
  55. package/dist/configuration-client/configuration-client-rest-client.js +5 -3
  56. package/dist/configuration-client/configuration-client-rest-client.js.map +1 -1
  57. package/dist/endpoint/participant-client.d.ts +3 -2
  58. package/dist/endpoint/participant-client.d.ts.map +1 -1
  59. package/dist/endpoint/participant-client.js +10 -16
  60. package/dist/endpoint/participant-client.js.map +1 -1
  61. package/dist/index.d.ts +2 -1
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +2 -1
  64. package/dist/index.js.map +1 -1
  65. package/package.json +6 -6
  66. package/dist/adapters/transaction-status/build-transaction-status-reader/build-transaction-status-reader.d.ts +0 -4
  67. package/dist/adapters/transaction-status/build-transaction-status-reader/build-transaction-status-reader.d.ts.map +0 -1
  68. package/dist/adapters/transaction-status/build-transaction-status-reader/build-transaction-status-reader.js +0 -47
  69. package/dist/adapters/transaction-status/build-transaction-status-reader/build-transaction-status-reader.js.map +0 -1
  70. package/dist/adapters/transaction-status/build-transaction-status-reader/index.d.ts +0 -2
  71. package/dist/adapters/transaction-status/build-transaction-status-reader/index.d.ts.map +0 -1
  72. package/dist/adapters/transaction-status/build-transaction-status-reader/index.js +0 -3
  73. package/dist/adapters/transaction-status/build-transaction-status-reader/index.js.map +0 -1
@@ -8,5 +8,5 @@ import { BuildEntityRestOptions } from '../types.js';
8
8
  * envelope rather than a bare `204`: the shared fetch client always parses the
9
9
  * response as JSON, and an empty body would fail that parse.
10
10
  */
11
- export declare const buildEntityRestAdapterDelete: <TEntity extends Entity>(entityConstructor: EntityConstructor<TEntity>, { uriConfig, configuration }: BuildEntityRestOptions) => <TEntity_1 extends Entity>(entityOrId: EntityId | TEntity_1) => Effect.Effect<undefined, import("@entifix/core").EntifixBuildError | import("@entifix/core").EntifixFailure<string, string, import("@entifix/core").FailureCategory>, never>;
11
+ export declare const buildEntityRestAdapterDelete: <TEntity extends Entity>(entityConstructor: EntityConstructor<TEntity>, { uriConfig, configuration }: BuildEntityRestOptions) => <TEntity_1 extends Entity>(entityOrId: EntityId | TEntity_1) => Effect.Effect<undefined, import("@entifix/core").EntifixFailure<string, string, import("@entifix/core").FailureCategory>, never>;
12
12
  //# sourceMappingURL=build-entity-rest-adapter-delete.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"build-entity-rest-adapter-delete.d.ts","sourceRoot":"","sources":["../../../../src/adapters/entity-rest/build-entity-rest-adapter-delete/build-entity-rest-adapter-delete.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,iBAAiB,EACjB,QAAQ,EAGT,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AASrD;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,GACtC,OAAO,SAAS,MAAM,EACrB,mBAAmB,iBAAiB,CAAC,OAAO,CAAC,EAC7C,8BAA8B,sBAAsB,MAErD,SAAO,SAAS,MAAM,EAAE,YAAY,QAAQ,GAAG,SAAO,iLAmBnD,CAAC"}
1
+ {"version":3,"file":"build-entity-rest-adapter-delete.d.ts","sourceRoot":"","sources":["../../../../src/adapters/entity-rest/build-entity-rest-adapter-delete/build-entity-rest-adapter-delete.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,iBAAiB,EACjB,QAAQ,EAGT,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AASrD;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,GACtC,OAAO,SAAS,MAAM,EACrB,mBAAmB,iBAAiB,CAAC,OAAO,CAAC,EAC7C,8BAA8B,sBAAsB,MAErD,SAAO,SAAS,MAAM,EAAE,YAAY,QAAQ,GAAG,SAAO,qIAmBnD,CAAC"}
@@ -7,5 +7,5 @@ import { BuildEntityRestOptions } from '../types.js';
7
7
  * the same query protocol, so what this composes is what the service parses
8
8
  * back. The caller binds it to the port, as it binds `load` to the repository.
9
9
  */
10
- export declare const buildEntityRestAdapterFacets: <TEntity extends Entity>(entityConstructor: EntityConstructor<TEntity>, { uriConfig, configuration }: BuildEntityRestOptions) => <T extends Entity>(queries: readonly EntityFacetQuery<T>[]) => Effect.Effect<Readonly<Record<string, readonly import("@entifix/core").EntityFacetValue[]>>, import("@entifix/core").EntifixBuildError | import("@entifix/core").EntifixFailure<string, string, import("@entifix/core").FailureCategory>, never>;
10
+ export declare const buildEntityRestAdapterFacets: <TEntity extends Entity>(entityConstructor: EntityConstructor<TEntity>, { uriConfig, configuration }: BuildEntityRestOptions) => <T extends Entity>(queries: readonly EntityFacetQuery<T>[]) => Effect.Effect<Readonly<Record<string, readonly import("@entifix/core").EntityFacetValue[]>>, import("@entifix/core").EntifixFailure<string, string, import("@entifix/core").FailureCategory>, never>;
11
11
  //# sourceMappingURL=build-entity-rest-adapter-facets.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"build-entity-rest-adapter-facets.d.ts","sourceRoot":"","sources":["../../../../src/adapters/entity-rest/build-entity-rest-adapter-facets/build-entity-rest-adapter-facets.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,MAAM,EACX,KAAK,iBAAiB,EAEtB,KAAK,gBAAgB,EAItB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAErD;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,GACtC,OAAO,SAAS,MAAM,EACrB,mBAAmB,iBAAiB,CAAC,OAAO,CAAC,EAC7C,8BAA8B,sBAAsB,MAErD,CAAC,SAAS,MAAM,EAAE,SAAS,SAAS,gBAAgB,CAAC,CAAC,CAAC,EAAE,qPAoBtD,CAAC"}
1
+ {"version":3,"file":"build-entity-rest-adapter-facets.d.ts","sourceRoot":"","sources":["../../../../src/adapters/entity-rest/build-entity-rest-adapter-facets/build-entity-rest-adapter-facets.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,MAAM,EACX,KAAK,iBAAiB,EAEtB,KAAK,gBAAgB,EAItB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAErD;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,GACtC,OAAO,SAAS,MAAM,EACrB,mBAAmB,iBAAiB,CAAC,OAAO,CAAC,EAC7C,8BAA8B,sBAAsB,MAErD,CAAC,SAAS,MAAM,EAAE,SAAS,SAAS,gBAAgB,CAAC,CAAC,CAAC,EAAE,yMAoBtD,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { Entity, EntityConstructor } from '@entifix/core';
2
2
  import { Effect } from 'effect';
3
3
  import { BuildEntityRestOptions } from '../types.js';
4
- export declare const buildEntityRestAdapterGet: <TEntity extends Entity>(entityConstructor: EntityConstructor<TEntity>, { uriConfig, configuration }: BuildEntityRestOptions) => <TEntity_1 extends Entity>(entityId: string) => Effect.Effect<TEntity_1, import("@entifix/core").EntifixBuildError | import("@entifix/core").EntifixFailure<string, string, import("@entifix/core").FailureCategory>, never>;
4
+ export declare const buildEntityRestAdapterGet: <TEntity extends Entity>(entityConstructor: EntityConstructor<TEntity>, { uriConfig, configuration }: BuildEntityRestOptions) => <TEntity_1 extends Entity>(entityId: string) => Effect.Effect<TEntity_1, import("@entifix/core").EntifixFailure<string, string, import("@entifix/core").FailureCategory>, never>;
5
5
  //# sourceMappingURL=build-entity-rest-adapter-get.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"build-entity-rest-adapter-get.d.ts","sourceRoot":"","sources":["../../../../src/adapters/entity-rest/build-entity-rest-adapter-get/build-entity-rest-adapter-get.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,iBAAiB,EAGlB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAErD,eAAO,MAAM,yBAAyB,GACnC,OAAO,SAAS,MAAM,EACrB,mBAAmB,iBAAiB,CAAC,OAAO,CAAC,EAC7C,8BAA8B,sBAAsB,MAErD,SAAO,SAAS,MAAM,EAAE,UAAU,MAAM,iLAoBrC,CAAC"}
1
+ {"version":3,"file":"build-entity-rest-adapter-get.d.ts","sourceRoot":"","sources":["../../../../src/adapters/entity-rest/build-entity-rest-adapter-get/build-entity-rest-adapter-get.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,iBAAiB,EAGlB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAErD,eAAO,MAAM,yBAAyB,GACnC,OAAO,SAAS,MAAM,EACrB,mBAAmB,iBAAiB,CAAC,OAAO,CAAC,EAC7C,8BAA8B,sBAAsB,MAErD,SAAO,SAAS,MAAM,EAAE,UAAU,MAAM,qIAoBrC,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { Entity, EntityConstructor, EntityLoadRequest, EntityPage } from '@entifix/core';
2
2
  import { Effect } from 'effect';
3
3
  import { BuildEntityRestOptions } from '../types.js';
4
- export declare const buildEntityRestAdapterLoad: <TEntity extends Entity>(entityConstructor: EntityConstructor<TEntity>, { uriConfig, configuration }: BuildEntityRestOptions) => <TEntity_1 extends Entity>(request: EntityLoadRequest<TEntity_1>) => Effect.Effect<EntityPage<TEntity_1>, import("@entifix/core").EntifixBuildError | import("@entifix/core").EntifixFailure<string, string, import("@entifix/core").FailureCategory>, never>;
4
+ export declare const buildEntityRestAdapterLoad: <TEntity extends Entity>(entityConstructor: EntityConstructor<TEntity>, { uriConfig, configuration }: BuildEntityRestOptions) => <TEntity_1 extends Entity>(request: EntityLoadRequest<TEntity_1>) => Effect.Effect<EntityPage<TEntity_1>, import("@entifix/core").EntifixFailure<string, string, import("@entifix/core").FailureCategory>, never>;
5
5
  //# sourceMappingURL=build-entity-rest-adapter-load.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"build-entity-rest-adapter-load.d.ts","sourceRoot":"","sources":["../../../../src/adapters/entity-rest/build-entity-rest-adapter-load/build-entity-rest-adapter-load.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,iBAAiB,EACjB,iBAAiB,EACjB,UAAU,EAIX,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAErD,eAAO,MAAM,0BAA0B,GACpC,OAAO,SAAS,MAAM,EACrB,mBAAmB,iBAAiB,CAAC,OAAO,CAAC,EAC7C,8BAA8B,sBAAsB,MAErD,SAAO,SAAS,MAAM,EAAE,SAAS,iBAAiB,CAAC,SAAO,CAAC,6LA8BxD,CAAC"}
1
+ {"version":3,"file":"build-entity-rest-adapter-load.d.ts","sourceRoot":"","sources":["../../../../src/adapters/entity-rest/build-entity-rest-adapter-load/build-entity-rest-adapter-load.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,iBAAiB,EACjB,iBAAiB,EACjB,UAAU,EAIX,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAErD,eAAO,MAAM,0BAA0B,GACpC,OAAO,SAAS,MAAM,EACrB,mBAAmB,iBAAiB,CAAC,OAAO,CAAC,EAC7C,8BAA8B,sBAAsB,MAErD,SAAO,SAAS,MAAM,EAAE,SAAS,iBAAiB,CAAC,SAAO,CAAC,iJA8BxD,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { ConfigurationClient } from '@entifix/core';
2
2
  import { Effect } from 'effect';
3
3
  import { BuildEntityRestOptions } from '../types.js';
4
- export declare const buildEntityBaseUrl: (configurationStore: ConfigurationClient, options: Pick<BuildEntityRestOptions, "uriConfig">, entityName: string, entityId?: string) => Effect.Effect<string, import("@entifix/core").EntifixBuildError, never>;
4
+ export declare const buildEntityBaseUrl: (configurationStore: ConfigurationClient, options: Pick<BuildEntityRestOptions, "uriConfig">, entityName: string, entityId?: string) => Effect.Effect<string, import("@entifix/core").Unavailable, never>;
5
5
  //# sourceMappingURL=build-entity-base-url.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"build-entity-base-url.d.ts","sourceRoot":"","sources":["../../../../src/adapters/entity-rest/build-entity-rest-adapter-mixins/build-entity-base-url.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAIrD,eAAO,MAAM,kBAAkB,GAC7B,oBAAoB,mBAAmB,EACvC,SAAS,IAAI,CAAC,sBAAsB,EAAE,WAAW,CAAC,EAClD,YAAY,MAAM,EAClB,WAAW,MAAM,4EAYf,CAAC"}
1
+ {"version":3,"file":"build-entity-base-url.d.ts","sourceRoot":"","sources":["../../../../src/adapters/entity-rest/build-entity-rest-adapter-mixins/build-entity-base-url.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAIrD,eAAO,MAAM,kBAAkB,GAC7B,oBAAoB,mBAAmB,EACvC,SAAS,IAAI,CAAC,sBAAsB,EAAE,WAAW,CAAC,EAClD,YAAY,MAAM,EAClB,WAAW,MAAM,sEAYf,CAAC"}
@@ -1,5 +1,5 @@
1
1
  export declare const buildEntityRestAdapterMixins: {
2
- buildEntityBaseUrl: (configurationStore: import("@entifix/core").ConfigurationClient, options: Pick<import("../types.js").BuildEntityRestOptions, "uriConfig">, entityName: string, entityId?: string) => import("effect/Effect").Effect<string, import("@entifix/core").EntifixBuildError, never>;
2
+ buildEntityBaseUrl: (configurationStore: import("@entifix/core").ConfigurationClient, options: Pick<import("../types.js").BuildEntityRestOptions, "uriConfig">, entityName: string, entityId?: string) => import("effect/Effect").Effect<string, import("@entifix/core").Unavailable, never>;
3
3
  buildEntityRequest: ({ method, url, envelope, idempotencyKey, }: import("./build-entity-request.js").BuildEntityRequestOptions) => import("../../../index.js").HttpRequest<import("@entifix/core").EntifixEnvelope<unknown>>;
4
4
  };
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -12,13 +12,9 @@ import { BuildEntityRestOptions } from '../types.js';
12
12
  * deserialized and returned, because the service is the authority on the stored
13
13
  * entity (it assigns ids and may normalize fields).
14
14
  *
15
- * A **transactional** create inverts that, and deliberately. The service answers
16
- * `202` describing a transaction rather than an entity, so there is no stored
17
- * entity to read back yet: the client mints the transaction id, which *is* the
18
- * id the entity will be stored under, and returns the entity it already holds.
19
- * That is the point of the client owning the id — before it, this
20
- * adapter parsed the `202` as an entity envelope, failed, and reported an error
21
- * for a create that was in fact about to succeed.
15
+ * A write the service hands to a flow answers `202`; a repository save has no
16
+ * stored entity to return for it, so such an entity is written through
17
+ * `buildEntityRestAdapterWrite`, which answers the flow to follow.
22
18
  */
23
- export declare const buildEntityRestAdapterSave: <TEntity extends Entity>(entityConstructor: EntityConstructor<TEntity>, { uriConfig, create, configuration }: BuildEntityRestOptions) => <TInput extends Entity>(entity: TInput) => Effect.Effect<TInput, import("@entifix/core").EntifixBuildError | import("@entifix/core").EntifixFailure<string, string, import("@entifix/core").FailureCategory>, never>;
19
+ export declare const buildEntityRestAdapterSave: <TEntity extends Entity>(entityConstructor: EntityConstructor<TEntity>, options: BuildEntityRestOptions) => <TInput extends Entity>(entity: TInput) => Effect.Effect<TInput, import("@entifix/core").EntifixFailure<string, string, import("@entifix/core").FailureCategory>, never>;
24
20
  //# sourceMappingURL=build-entity-rest-adapter-save.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"build-entity-rest-adapter-save.d.ts","sourceRoot":"","sources":["../../../../src/adapters/entity-rest/build-entity-rest-adapter-save/build-entity-rest-adapter-save.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,iBAAiB,EAKlB,MAAM,eAAe,CAAC;AAOvB,OAAO,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAC;AAIxC,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAkBrD;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,0BAA0B,GACpC,OAAO,SAAS,MAAM,EACrB,mBAAmB,iBAAiB,CAAC,OAAO,CAAC,EAC7C,sCAAiD,sBAAsB,MAKxE,MAAM,SAAS,MAAM,EAAE,QAAQ,MAAM,8KA4FlC,CAAC"}
1
+ {"version":3,"file":"build-entity-rest-adapter-save.d.ts","sourceRoot":"","sources":["../../../../src/adapters/entity-rest/build-entity-rest-adapter-save/build-entity-rest-adapter-save.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,iBAAiB,EAGlB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGhC,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAErD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,0BAA0B,GACpC,OAAO,SAAS,MAAM,EACrB,mBAAmB,iBAAiB,CAAC,OAAO,CAAC,EAC7C,SAAS,sBAAsB,MAKhC,MAAM,SAAS,MAAM,EAAE,QAAQ,MAAM,kIAgBlC,CAAC"}
@@ -1,20 +1,6 @@
1
- import { extractMetaEntity, makeEntityEnvelope, readEntityEnvelope, serializeEntity } from '@entifix/core';
2
- import { makeCommandEnvelope, readTransactionAcceptedEnvelope, TransactionSinkTag } from '@entifix/transactions';
3
- import { Effect, Option } from 'effect';
4
- import { performHttpRequestThroughFetch } from '../../../clients/fetch/index.js';
5
- import { buildEntityRestAdapterMixins as adapterMixins } from '../build-entity-rest-adapter-mixins/index.js';
6
- /**
7
- * The `Idempotency-Key` each entity's pending save was sent under, kept until
8
- * that save succeeds.
9
- *
10
- * Keyed by the entity instance, so a save called again on the same object
11
- * after a network error — the case the key exists for — sends the same key and
12
- * the service replays its first answer instead of writing twice. A save that
13
- * succeeded forgets its key, so the next edit of that object is a new request.
14
- * The browser itself never retries (ADR 0014); this is what makes a person's
15
- * retry safe.
16
- */ const pendingKeys = new WeakMap();
17
- /** A transactional create whose `202` never arrived: same command, same id. */ const pendingCreates = new WeakSet();
1
+ import { extractMetaEntity, ProtocolFailure } from '@entifix/core';
2
+ import { Effect } from 'effect';
3
+ import { buildEntityRestAdapterWrite } from '../build-entity-rest-adapter-write/index.js';
18
4
  /**
19
5
  * Persists an entity over HTTP.
20
6
  *
@@ -26,89 +12,24 @@ import { buildEntityRestAdapterMixins as adapterMixins } from '../build-entity-r
26
12
  * deserialized and returned, because the service is the authority on the stored
27
13
  * entity (it assigns ids and may normalize fields).
28
14
  *
29
- * A **transactional** create inverts that, and deliberately. The service answers
30
- * `202` describing a transaction rather than an entity, so there is no stored
31
- * entity to read back yet: the client mints the transaction id, which *is* the
32
- * id the entity will be stored under, and returns the entity it already holds.
33
- * That is the point of the client owning the id — before it, this
34
- * adapter parsed the `202` as an entity envelope, failed, and reported an error
35
- * for a create that was in fact about to succeed.
36
- */ export const buildEntityRestAdapterSave = (entityConstructor, { uriConfig, create = 'entity', configuration })=>// Deliberately not shadowing `TEntity` here (as the read builders do): the
15
+ * A write the service hands to a flow answers `202`; a repository save has no
16
+ * stored entity to return for it, so such an entity is written through
17
+ * `buildEntityRestAdapterWrite`, which answers the flow to follow.
18
+ */ export const buildEntityRestAdapterSave = (entityConstructor, options)=>// Deliberately not shadowing `TEntity` here (as the read builders do): the
37
19
  // envelope has to be built against the *constructor's* entity type, which a
38
20
  // shadowed parameter would make unreachable.
39
21
  (entity)=>Effect.gen(function*() {
40
- var _metaEntity_key, _pendingKeys_get;
22
+ var _metaEntity_key;
41
23
  const metaEntity = extractMetaEntity(entityConstructor);
42
24
  const key = (_metaEntity_key = metaEntity.key) != null ? _metaEntity_key : metaEntity.name;
43
- const isCreate = entity.id == null || pendingCreates.has(entity);
44
- const url = yield* adapterMixins.buildEntityBaseUrl(configuration, {
45
- uriConfig
46
- }, key, isCreate ? undefined : String(entity.id));
47
- if (isCreate && create === 'command') {
48
- var _pendingKeys_get1;
49
- // `crypto.randomUUID` is available in every browser this ships to and in
50
- // Node — and the id must be a UUID, because the service constrains the
51
- // key space a caller may address.
52
- // A retried create reuses the id it was first sent with: that id *is*
53
- // the idempotency key, so a new one would write a second record.
54
- const transactionId = (_pendingKeys_get1 = pendingKeys.get(entity)) != null ? _pendingKeys_get1 : crypto.randomUUID();
55
- pendingKeys.set(entity, transactionId);
56
- pendingCreates.add(entity);
57
- entity.id = transactionId;
58
- const command = {
59
- transactionId,
60
- type: 'create',
61
- entity: key,
62
- payload: serializeEntity(entityConstructor, entity)
63
- };
64
- const accepted = yield* performHttpRequestThroughFetch(adapterMixins.buildEntityRequest({
65
- method: 'POST',
66
- url,
67
- envelope: makeCommandEnvelope(command),
68
- idempotencyKey: transactionId
69
- }));
70
- // Read for its shape, not its contents: this asserts the service really
71
- // accepted a transaction rather than answering something else with a
72
- // 2xx, which is the failure the old code path could not distinguish.
73
- yield* readTransactionAcceptedEnvelope(accepted.body);
74
- pendingKeys.delete(entity);
75
- pendingCreates.delete(entity);
76
- // Tell whoever is watching that a write is in flight. This is the only
77
- // point in the system that knows it — the entity returned below is
78
- // indistinguishable from a plain REST create, so without this the
79
- // browser navigates away at the `202` and a later failure leaves no row,
80
- // no message and nothing to retry from.
81
- //
82
- // `serviceOption`, deliberately: reading the tag this way keeps it out
83
- // of this function's `R`, so the storefront, the plain REST adapters and
84
- // every existing spec compile and run with no layer to provide. The cost
85
- // is that nothing *forces* a composition root to provide it, which is
86
- // why `mergeContext` has a spec pinning that it does.
87
- const sink = yield* Effect.serviceOption(TransactionSinkTag);
88
- if (Option.isSome(sink)) {
89
- // After the assertion above, never before: a `2xx` that is not a
90
- // transaction envelope must not register a pending id, because nothing
91
- // would ever settle it and the entry becomes a permanent phantom.
92
- sink.value.began({
93
- transactionId,
94
- entity: key,
95
- at: new Date().toISOString()
96
- });
97
- }
98
- return entity;
99
- }
100
- const idempotencyKey = (_pendingKeys_get = pendingKeys.get(entity)) != null ? _pendingKeys_get : crypto.randomUUID();
101
- pendingKeys.set(entity, idempotencyKey);
102
- const httpRequest = adapterMixins.buildEntityRequest({
103
- method: isCreate ? 'POST' : 'PUT',
104
- url,
105
- envelope: makeEntityEnvelope(entityConstructor, entity),
106
- idempotencyKey
25
+ const result = yield* buildEntityRestAdapterWrite(entityConstructor, options).save(entity);
26
+ // A repository save answers the stored entity, so it has nothing to
27
+ // return for a write the service handed to a flow; a screen writes such
28
+ // an entity through `buildEntityRestAdapterWrite` instead.
29
+ if (result._tag === 'pending') return yield* new ProtocolFailure({
30
+ reason: `'${key}' answered a save with 202 flowAccepted; write it through buildEntityRestAdapterWrite`
107
31
  });
108
- const response = yield* performHttpRequestThroughFetch(httpRequest);
109
- const saved = yield* readEntityEnvelope(entityConstructor, response.body);
110
- pendingKeys.delete(entity);
111
- return saved;
32
+ return result.value;
112
33
  });
113
34
 
114
35
  //# sourceMappingURL=build-entity-rest-adapter-save.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/adapters/entity-rest/build-entity-rest-adapter-save/build-entity-rest-adapter-save.ts"],"sourcesContent":["import {\n Entity,\n EntityConstructor,\n extractMetaEntity,\n makeEntityEnvelope,\n readEntityEnvelope,\n serializeEntity,\n} from '@entifix/core';\nimport {\n makeCommandEnvelope,\n readTransactionAcceptedEnvelope,\n type TransactionCommand,\n TransactionSinkTag,\n} from '@entifix/transactions';\nimport { Effect, Option } from 'effect';\n\nimport { performHttpRequestThroughFetch } from '../../../clients/fetch/index.js';\nimport { buildEntityRestAdapterMixins as adapterMixins } from '../build-entity-rest-adapter-mixins/index.js';\nimport { BuildEntityRestOptions } from '../types.js';\n\n/**\n * The `Idempotency-Key` each entity's pending save was sent under, kept until\n * that save succeeds.\n *\n * Keyed by the entity instance, so a save called again on the same object\n * after a network error — the case the key exists for — sends the same key and\n * the service replays its first answer instead of writing twice. A save that\n * succeeded forgets its key, so the next edit of that object is a new request.\n * The browser itself never retries (ADR 0014); this is what makes a person's\n * retry safe.\n */\nconst pendingKeys = new WeakMap<object, string>();\n\n/** A transactional create whose `202` never arrived: same command, same id. */\nconst pendingCreates = new WeakSet<object>();\n\n/**\n * Persists an entity over HTTP.\n *\n * An entity without an id has never been stored, so it is created with `POST`\n * against the collection; one with an id is replaced with `PUT` against its own\n * URL.\n *\n * For a plain create the response envelope — not the request — is what gets\n * deserialized and returned, because the service is the authority on the stored\n * entity (it assigns ids and may normalize fields).\n *\n * A **transactional** create inverts that, and deliberately. The service answers\n * `202` describing a transaction rather than an entity, so there is no stored\n * entity to read back yet: the client mints the transaction id, which *is* the\n * id the entity will be stored under, and returns the entity it already holds.\n * That is the point of the client owning the id — before it, this\n * adapter parsed the `202` as an entity envelope, failed, and reported an error\n * for a create that was in fact about to succeed.\n */\nexport const buildEntityRestAdapterSave =\n <TEntity extends Entity>(\n entityConstructor: EntityConstructor<TEntity>,\n { uriConfig, create = 'entity', configuration }: BuildEntityRestOptions,\n ) =>\n // Deliberately not shadowing `TEntity` here (as the read builders do): the\n // envelope has to be built against the *constructor's* entity type, which a\n // shadowed parameter would make unreachable.\n <TInput extends Entity>(entity: TInput) =>\n Effect.gen(function* () {\n const metaEntity = extractMetaEntity(entityConstructor);\n const key = metaEntity.key ?? metaEntity.name;\n const isCreate = entity.id == null || pendingCreates.has(entity);\n\n const url = yield* adapterMixins.buildEntityBaseUrl(\n configuration,\n { uriConfig },\n key,\n isCreate ? undefined : String(entity.id),\n );\n\n if (isCreate && create === 'command') {\n // `crypto.randomUUID` is available in every browser this ships to and in\n // Node — and the id must be a UUID, because the service constrains the\n // key space a caller may address.\n // A retried create reuses the id it was first sent with: that id *is*\n // the idempotency key, so a new one would write a second record.\n const transactionId = pendingKeys.get(entity) ?? crypto.randomUUID();\n pendingKeys.set(entity, transactionId);\n pendingCreates.add(entity);\n entity.id = transactionId;\n\n const command: TransactionCommand = {\n transactionId,\n type: 'create',\n entity: key,\n payload: serializeEntity(\n entityConstructor,\n entity as unknown as TEntity,\n ),\n };\n\n const accepted = yield* performHttpRequestThroughFetch(\n adapterMixins.buildEntityRequest({\n method: 'POST',\n url,\n envelope: makeCommandEnvelope(command),\n idempotencyKey: transactionId,\n }),\n );\n // Read for its shape, not its contents: this asserts the service really\n // accepted a transaction rather than answering something else with a\n // 2xx, which is the failure the old code path could not distinguish.\n yield* readTransactionAcceptedEnvelope(accepted.body);\n pendingKeys.delete(entity);\n pendingCreates.delete(entity);\n\n // Tell whoever is watching that a write is in flight. This is the only\n // point in the system that knows it — the entity returned below is\n // indistinguishable from a plain REST create, so without this the\n // browser navigates away at the `202` and a later failure leaves no row,\n // no message and nothing to retry from.\n //\n // `serviceOption`, deliberately: reading the tag this way keeps it out\n // of this function's `R`, so the storefront, the plain REST adapters and\n // every existing spec compile and run with no layer to provide. The cost\n // is that nothing *forces* a composition root to provide it, which is\n // why `mergeContext` has a spec pinning that it does.\n const sink = yield* Effect.serviceOption(TransactionSinkTag);\n if (Option.isSome(sink)) {\n // After the assertion above, never before: a `2xx` that is not a\n // transaction envelope must not register a pending id, because nothing\n // would ever settle it and the entry becomes a permanent phantom.\n sink.value.began({\n transactionId,\n entity: key,\n at: new Date().toISOString(),\n });\n }\n\n return entity;\n }\n\n const idempotencyKey = pendingKeys.get(entity) ?? crypto.randomUUID();\n pendingKeys.set(entity, idempotencyKey);\n const httpRequest = adapterMixins.buildEntityRequest({\n method: isCreate ? 'POST' : 'PUT',\n url,\n envelope: makeEntityEnvelope(\n entityConstructor,\n entity as unknown as TEntity,\n ),\n idempotencyKey,\n });\n\n const response = yield* performHttpRequestThroughFetch(httpRequest);\n const saved = yield* readEntityEnvelope(entityConstructor, response.body);\n pendingKeys.delete(entity);\n\n return saved as unknown as TInput;\n });\n"],"names":["extractMetaEntity","makeEntityEnvelope","readEntityEnvelope","serializeEntity","makeCommandEnvelope","readTransactionAcceptedEnvelope","TransactionSinkTag","Effect","Option","performHttpRequestThroughFetch","buildEntityRestAdapterMixins","adapterMixins","pendingKeys","WeakMap","pendingCreates","WeakSet","buildEntityRestAdapterSave","entityConstructor","uriConfig","create","configuration","entity","gen","metaEntity","key","name","isCreate","id","has","url","buildEntityBaseUrl","undefined","String","transactionId","get","crypto","randomUUID","set","add","command","type","payload","accepted","buildEntityRequest","method","envelope","idempotencyKey","body","delete","sink","serviceOption","isSome","value","began","at","Date","toISOString","httpRequest","response","saved"],"mappings":"AAAA,SAGEA,iBAAiB,EACjBC,kBAAkB,EAClBC,kBAAkB,EAClBC,eAAe,QACV,gBAAgB;AACvB,SACEC,mBAAmB,EACnBC,+BAA+B,EAE/BC,kBAAkB,QACb,wBAAwB;AAC/B,SAASC,MAAM,EAAEC,MAAM,QAAQ,SAAS;AAExC,SAASC,8BAA8B,QAAQ,kCAAkC;AACjF,SAASC,gCAAgCC,aAAa,QAAQ,+CAA+C;AAG7G;;;;;;;;;;CAUC,GACD,MAAMC,cAAc,IAAIC;AAExB,6EAA6E,GAC7E,MAAMC,iBAAiB,IAAIC;AAE3B;;;;;;;;;;;;;;;;;;CAkBC,GACD,OAAO,MAAMC,6BACX,CACEC,mBACA,EAAEC,SAAS,EAAEC,SAAS,QAAQ,EAAEC,aAAa,EAA0B,GAEzE,2EAA2E;IAC3E,4EAA4E;IAC5E,6CAA6C;IAC7C,CAAwBC,SACtBd,OAAOe,GAAG,CAAC;gBAEGC,iBAwEWX;YAzEvB,MAAMW,aAAavB,kBAAkBiB;YACrC,MAAMO,OAAMD,kBAAAA,WAAWC,GAAG,YAAdD,kBAAkBA,WAAWE,IAAI;YAC7C,MAAMC,WAAWL,OAAOM,EAAE,IAAI,QAAQb,eAAec,GAAG,CAACP;YAEzD,MAAMQ,MAAM,OAAOlB,cAAcmB,kBAAkB,CACjDV,eACA;gBAAEF;YAAU,GACZM,KACAE,WAAWK,YAAYC,OAAOX,OAAOM,EAAE;YAGzC,IAAID,YAAYP,WAAW,WAAW;oBAMdP;gBALtB,yEAAyE;gBACzE,uEAAuE;gBACvE,kCAAkC;gBAClC,sEAAsE;gBACtE,iEAAiE;gBACjE,MAAMqB,iBAAgBrB,oBAAAA,YAAYsB,GAAG,CAACb,mBAAhBT,oBAA2BuB,OAAOC,UAAU;gBAClExB,YAAYyB,GAAG,CAAChB,QAAQY;gBACxBnB,eAAewB,GAAG,CAACjB;gBACnBA,OAAOM,EAAE,GAAGM;gBAEZ,MAAMM,UAA8B;oBAClCN;oBACAO,MAAM;oBACNnB,QAAQG;oBACRiB,SAAStC,gBACPc,mBACAI;gBAEJ;gBAEA,MAAMqB,WAAW,OAAOjC,+BACtBE,cAAcgC,kBAAkB,CAAC;oBAC/BC,QAAQ;oBACRf;oBACAgB,UAAUzC,oBAAoBmC;oBAC9BO,gBAAgBb;gBAClB;gBAEF,wEAAwE;gBACxE,qEAAqE;gBACrE,qEAAqE;gBACrE,OAAO5B,gCAAgCqC,SAASK,IAAI;gBACpDnC,YAAYoC,MAAM,CAAC3B;gBACnBP,eAAekC,MAAM,CAAC3B;gBAEtB,uEAAuE;gBACvE,mEAAmE;gBACnE,kEAAkE;gBAClE,yEAAyE;gBACzE,wCAAwC;gBACxC,EAAE;gBACF,uEAAuE;gBACvE,yEAAyE;gBACzE,yEAAyE;gBACzE,sEAAsE;gBACtE,sDAAsD;gBACtD,MAAM4B,OAAO,OAAO1C,OAAO2C,aAAa,CAAC5C;gBACzC,IAAIE,OAAO2C,MAAM,CAACF,OAAO;oBACvB,iEAAiE;oBACjE,uEAAuE;oBACvE,kEAAkE;oBAClEA,KAAKG,KAAK,CAACC,KAAK,CAAC;wBACfpB;wBACAZ,QAAQG;wBACR8B,IAAI,IAAIC,OAAOC,WAAW;oBAC5B;gBACF;gBAEA,OAAOnC;YACT;YAEA,MAAMyB,kBAAiBlC,mBAAAA,YAAYsB,GAAG,CAACb,mBAAhBT,mBAA2BuB,OAAOC,UAAU;YACnExB,YAAYyB,GAAG,CAAChB,QAAQyB;YACxB,MAAMW,cAAc9C,cAAcgC,kBAAkB,CAAC;gBACnDC,QAAQlB,WAAW,SAAS;gBAC5BG;gBACAgB,UAAU5C,mBACRgB,mBACAI;gBAEFyB;YACF;YAEA,MAAMY,WAAW,OAAOjD,+BAA+BgD;YACvD,MAAME,QAAQ,OAAOzD,mBAAmBe,mBAAmByC,SAASX,IAAI;YACxEnC,YAAYoC,MAAM,CAAC3B;YAEnB,OAAOsC;QACT,GAAG"}
1
+ {"version":3,"sources":["../../../../src/adapters/entity-rest/build-entity-rest-adapter-save/build-entity-rest-adapter-save.ts"],"sourcesContent":["import {\n Entity,\n EntityConstructor,\n extractMetaEntity,\n ProtocolFailure,\n} from '@entifix/core';\nimport { Effect } from 'effect';\n\nimport { buildEntityRestAdapterWrite } from '../build-entity-rest-adapter-write/index.js';\nimport { BuildEntityRestOptions } from '../types.js';\n\n/**\n * Persists an entity over HTTP.\n *\n * An entity without an id has never been stored, so it is created with `POST`\n * against the collection; one with an id is replaced with `PUT` against its own\n * URL.\n *\n * For a plain create the response envelope — not the request — is what gets\n * deserialized and returned, because the service is the authority on the stored\n * entity (it assigns ids and may normalize fields).\n *\n * A write the service hands to a flow answers `202`; a repository save has no\n * stored entity to return for it, so such an entity is written through\n * `buildEntityRestAdapterWrite`, which answers the flow to follow.\n */\nexport const buildEntityRestAdapterSave =\n <TEntity extends Entity>(\n entityConstructor: EntityConstructor<TEntity>,\n options: BuildEntityRestOptions,\n ) =>\n // Deliberately not shadowing `TEntity` here (as the read builders do): the\n // envelope has to be built against the *constructor's* entity type, which a\n // shadowed parameter would make unreachable.\n <TInput extends Entity>(entity: TInput) =>\n Effect.gen(function* () {\n const metaEntity = extractMetaEntity(entityConstructor);\n const key = metaEntity.key ?? metaEntity.name;\n const result = yield* buildEntityRestAdapterWrite(\n entityConstructor,\n options,\n ).save(entity);\n // A repository save answers the stored entity, so it has nothing to\n // return for a write the service handed to a flow; a screen writes such\n // an entity through `buildEntityRestAdapterWrite` instead.\n if (result._tag === 'pending')\n return yield* new ProtocolFailure({\n reason: `'${key}' answered a save with 202 flowAccepted; write it through buildEntityRestAdapterWrite`,\n });\n return result.value;\n });\n"],"names":["extractMetaEntity","ProtocolFailure","Effect","buildEntityRestAdapterWrite","buildEntityRestAdapterSave","entityConstructor","options","entity","gen","metaEntity","key","name","result","save","_tag","reason","value"],"mappings":"AAAA,SAGEA,iBAAiB,EACjBC,eAAe,QACV,gBAAgB;AACvB,SAASC,MAAM,QAAQ,SAAS;AAEhC,SAASC,2BAA2B,QAAQ,8CAA8C;AAG1F;;;;;;;;;;;;;;CAcC,GACD,OAAO,MAAMC,6BACX,CACEC,mBACAC,UAEF,2EAA2E;IAC3E,4EAA4E;IAC5E,6CAA6C;IAC7C,CAAwBC,SACtBL,OAAOM,GAAG,CAAC;gBAEGC;YADZ,MAAMA,aAAaT,kBAAkBK;YACrC,MAAMK,OAAMD,kBAAAA,WAAWC,GAAG,YAAdD,kBAAkBA,WAAWE,IAAI;YAC7C,MAAMC,SAAS,OAAOT,4BACpBE,mBACAC,SACAO,IAAI,CAACN;YACP,oEAAoE;YACpE,wEAAwE;YACxE,2DAA2D;YAC3D,IAAIK,OAAOE,IAAI,KAAK,WAClB,OAAO,OAAO,IAAIb,gBAAgB;gBAChCc,QAAQ,CAAC,CAAC,EAAEL,IAAI,qFAAqF,CAAC;YACxG;YACF,OAAOE,OAAOI,KAAK;QACrB,GAAG"}
@@ -0,0 +1,10 @@
1
+ import { type Entity, type EntityConstructor, type EntityWriter } from '@entifix/core';
2
+ import type { BuildEntityRestOptions } from '../types.js';
3
+ /**
4
+ * The write half of an entity's REST adapters, answering both settle modes.
5
+ *
6
+ * The `command` create protocol is the tracker's and is not served here; it
7
+ * stays on `buildEntityRestAdapterSave`.
8
+ */
9
+ export declare const buildEntityRestAdapterWrite: <TEntity extends Entity>(entityConstructor: EntityConstructor<TEntity>, { uriConfig, update, configuration }: BuildEntityRestOptions) => EntityWriter;
10
+ //# sourceMappingURL=build-entity-rest-adapter-write.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-entity-rest-adapter-write.d.ts","sourceRoot":"","sources":["../../../../src/adapters/entity-rest/build-entity-rest-adapter-write/build-entity-rest-adapter-write.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,MAAM,EACX,KAAK,iBAAiB,EAEtB,KAAK,YAAY,EAKlB,MAAM,eAAe,CAAC;AAOvB,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAO1D;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,GAAI,OAAO,SAAS,MAAM,EAChE,mBAAmB,iBAAiB,CAAC,OAAO,CAAC,EAC7C,sCAA8C,sBAAsB,KACnE,YAqDF,CAAC"}
@@ -0,0 +1,49 @@
1
+ import { extractMetaEntity, Internal, makeEntityEnvelope, readEntityEnvelope } from '@entifix/core';
2
+ import { Effect } from 'effect';
3
+ import { performHttpRequestThroughFetch } from '../../../clients/fetch/index.js';
4
+ import { buildEntityRestAdapterMixins as adapterMixins } from '../build-entity-rest-adapter-mixins/index.js';
5
+ import { pendingSaveKeys } from '../pending-save-keys.js';
6
+ import { readWriteResponse } from '../read-write-response.js';
7
+ const idOf = (entityOrId)=>entityOrId != null && typeof entityOrId === 'object' ? entityOrId.id : entityOrId;
8
+ /**
9
+ * The write half of an entity's REST adapters, answering both settle modes.
10
+ *
11
+ * The `command` create protocol is the tracker's and is not served here; it
12
+ * stays on `buildEntityRestAdapterSave`.
13
+ */ export const buildEntityRestAdapterWrite = (entityConstructor, { uriConfig, update = 'PUT', configuration })=>{
14
+ var _metaEntity_key;
15
+ const metaEntity = extractMetaEntity(entityConstructor);
16
+ const key = (_metaEntity_key = metaEntity.key) != null ? _metaEntity_key : metaEntity.name;
17
+ const urlOf = (id)=>adapterMixins.buildEntityBaseUrl(configuration, {
18
+ uriConfig
19
+ }, key, id == null ? undefined : String(id));
20
+ return {
21
+ save: (entity)=>Effect.gen(function*() {
22
+ var _pendingSaveKeys_get;
23
+ const isCreate = entity.id == null;
24
+ const url = yield* urlOf(entity.id);
25
+ const idempotencyKey = (_pendingSaveKeys_get = pendingSaveKeys.get(entity)) != null ? _pendingSaveKeys_get : crypto.randomUUID();
26
+ pendingSaveKeys.set(entity, idempotencyKey);
27
+ const response = yield* performHttpRequestThroughFetch(adapterMixins.buildEntityRequest({
28
+ method: isCreate ? 'POST' : update,
29
+ url,
30
+ envelope: makeEntityEnvelope(entityConstructor, entity),
31
+ idempotencyKey
32
+ }));
33
+ const result = yield* readWriteResponse(response, (body)=>Effect.map(readEntityEnvelope(entityConstructor, body), (saved)=>saved));
34
+ pendingSaveKeys.delete(entity);
35
+ return result;
36
+ }),
37
+ delete: (entityOrId)=>Effect.gen(function*() {
38
+ const id = idOf(entityOrId);
39
+ if (id == null) return yield* Effect.fail(new Internal());
40
+ const response = yield* performHttpRequestThroughFetch(adapterMixins.buildEntityRequest({
41
+ method: 'DELETE',
42
+ url: yield* urlOf(id)
43
+ }));
44
+ return yield* readWriteResponse(response, ()=>Effect.void);
45
+ })
46
+ };
47
+ };
48
+
49
+ //# sourceMappingURL=build-entity-rest-adapter-write.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/adapters/entity-rest/build-entity-rest-adapter-write/build-entity-rest-adapter-write.ts"],"sourcesContent":["import {\n type Entity,\n type EntityConstructor,\n type EntityId,\n type EntityWriter,\n extractMetaEntity,\n Internal,\n makeEntityEnvelope,\n readEntityEnvelope,\n} from '@entifix/core';\nimport { Effect } from 'effect';\n\nimport { performHttpRequestThroughFetch } from '../../../clients/fetch/index.js';\nimport { buildEntityRestAdapterMixins as adapterMixins } from '../build-entity-rest-adapter-mixins/index.js';\nimport { pendingSaveKeys } from '../pending-save-keys.js';\nimport { readWriteResponse } from '../read-write-response.js';\nimport type { BuildEntityRestOptions } from '../types.js';\n\nconst idOf = (entityOrId: EntityId | Entity): EntityId =>\n entityOrId != null && typeof entityOrId === 'object'\n ? entityOrId.id\n : entityOrId;\n\n/**\n * The write half of an entity's REST adapters, answering both settle modes.\n *\n * The `command` create protocol is the tracker's and is not served here; it\n * stays on `buildEntityRestAdapterSave`.\n */\nexport const buildEntityRestAdapterWrite = <TEntity extends Entity>(\n entityConstructor: EntityConstructor<TEntity>,\n { uriConfig, update = 'PUT', configuration }: BuildEntityRestOptions,\n): EntityWriter => {\n const metaEntity = extractMetaEntity(entityConstructor);\n const key = metaEntity.key ?? metaEntity.name;\n const urlOf = (id?: EntityId) =>\n adapterMixins.buildEntityBaseUrl(\n configuration,\n { uriConfig },\n key,\n id == null ? undefined : String(id),\n );\n\n return {\n save: <TInput extends Entity>(entity: TInput) =>\n Effect.gen(function* () {\n const isCreate = entity.id == null;\n const url = yield* urlOf(entity.id);\n const idempotencyKey =\n pendingSaveKeys.get(entity) ?? crypto.randomUUID();\n pendingSaveKeys.set(entity, idempotencyKey);\n\n const response = yield* performHttpRequestThroughFetch(\n adapterMixins.buildEntityRequest({\n method: isCreate ? 'POST' : update,\n url,\n envelope: makeEntityEnvelope(\n entityConstructor,\n entity as unknown as TEntity,\n ),\n idempotencyKey,\n }),\n );\n const result = yield* readWriteResponse(response, body =>\n Effect.map(\n readEntityEnvelope(entityConstructor, body),\n saved => saved as unknown as TInput,\n ),\n );\n pendingSaveKeys.delete(entity);\n return result;\n }),\n delete: entityOrId =>\n Effect.gen(function* () {\n const id = idOf(entityOrId);\n if (id == null) return yield* Effect.fail(new Internal());\n const response = yield* performHttpRequestThroughFetch(\n adapterMixins.buildEntityRequest({\n method: 'DELETE',\n url: yield* urlOf(id),\n }),\n );\n return yield* readWriteResponse(response, () => Effect.void);\n }),\n };\n};\n"],"names":["extractMetaEntity","Internal","makeEntityEnvelope","readEntityEnvelope","Effect","performHttpRequestThroughFetch","buildEntityRestAdapterMixins","adapterMixins","pendingSaveKeys","readWriteResponse","idOf","entityOrId","id","buildEntityRestAdapterWrite","entityConstructor","uriConfig","update","configuration","metaEntity","key","name","urlOf","buildEntityBaseUrl","undefined","String","save","entity","gen","isCreate","url","idempotencyKey","get","crypto","randomUUID","set","response","buildEntityRequest","method","envelope","result","body","map","saved","delete","fail","void"],"mappings":"AAAA,SAKEA,iBAAiB,EACjBC,QAAQ,EACRC,kBAAkB,EAClBC,kBAAkB,QACb,gBAAgB;AACvB,SAASC,MAAM,QAAQ,SAAS;AAEhC,SAASC,8BAA8B,QAAQ,kCAAkC;AACjF,SAASC,gCAAgCC,aAAa,QAAQ,+CAA+C;AAC7G,SAASC,eAAe,QAAQ,0BAA0B;AAC1D,SAASC,iBAAiB,QAAQ,4BAA4B;AAG9D,MAAMC,OAAO,CAACC,aACZA,cAAc,QAAQ,OAAOA,eAAe,WACxCA,WAAWC,EAAE,GACbD;AAEN;;;;;CAKC,GACD,OAAO,MAAME,8BAA8B,CACzCC,mBACA,EAAEC,SAAS,EAAEC,SAAS,KAAK,EAAEC,aAAa,EAA0B;QAGxDC;IADZ,MAAMA,aAAalB,kBAAkBc;IACrC,MAAMK,OAAMD,kBAAAA,WAAWC,GAAG,YAAdD,kBAAkBA,WAAWE,IAAI;IAC7C,MAAMC,QAAQ,CAACT,KACbL,cAAce,kBAAkB,CAC9BL,eACA;YAAEF;QAAU,GACZI,KACAP,MAAM,OAAOW,YAAYC,OAAOZ;IAGpC,OAAO;QACLa,MAAM,CAAwBC,SAC5BtB,OAAOuB,GAAG,CAAC;oBAIPnB;gBAHF,MAAMoB,WAAWF,OAAOd,EAAE,IAAI;gBAC9B,MAAMiB,MAAM,OAAOR,MAAMK,OAAOd,EAAE;gBAClC,MAAMkB,kBACJtB,uBAAAA,gBAAgBuB,GAAG,CAACL,mBAApBlB,uBAA+BwB,OAAOC,UAAU;gBAClDzB,gBAAgB0B,GAAG,CAACR,QAAQI;gBAE5B,MAAMK,WAAW,OAAO9B,+BACtBE,cAAc6B,kBAAkB,CAAC;oBAC/BC,QAAQT,WAAW,SAASZ;oBAC5Ba;oBACAS,UAAUpC,mBACRY,mBACAY;oBAEFI;gBACF;gBAEF,MAAMS,SAAS,OAAO9B,kBAAkB0B,UAAUK,CAAAA,OAChDpC,OAAOqC,GAAG,CACRtC,mBAAmBW,mBAAmB0B,OACtCE,CAAAA,QAASA;gBAGblC,gBAAgBmC,MAAM,CAACjB;gBACvB,OAAOa;YACT;QACFI,QAAQhC,CAAAA,aACNP,OAAOuB,GAAG,CAAC;gBACT,MAAMf,KAAKF,KAAKC;gBAChB,IAAIC,MAAM,MAAM,OAAO,OAAOR,OAAOwC,IAAI,CAAC,IAAI3C;gBAC9C,MAAMkC,WAAW,OAAO9B,+BACtBE,cAAc6B,kBAAkB,CAAC;oBAC/BC,QAAQ;oBACRR,KAAK,OAAOR,MAAMT;gBACpB;gBAEF,OAAO,OAAOH,kBAAkB0B,UAAU,IAAM/B,OAAOyC,IAAI;YAC7D;IACJ;AACF,EAAE"}
@@ -0,0 +1,2 @@
1
+ export * from './build-entity-rest-adapter-write.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/adapters/entity-rest/build-entity-rest-adapter-write/index.ts"],"names":[],"mappings":"AAAA,cAAc,sCAAsC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './build-entity-rest-adapter-write.js';
2
+
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/adapters/entity-rest/build-entity-rest-adapter-write/index.ts"],"sourcesContent":["export * from './build-entity-rest-adapter-write.js';\n"],"names":[],"mappings":"AAAA,cAAc,uCAAuC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The `Idempotency-Key` each entity's pending save was sent under, kept until
3
+ * that save is answered.
4
+ *
5
+ * Keyed by the entity instance, so a save called again on the same object
6
+ * after a network error — the case the key exists for — sends the same key and
7
+ * the service replays its first answer instead of writing twice. An answered
8
+ * save forgets its key, so the next edit of that object is a new request. The
9
+ * browser itself never retries (ADR 0014); this is what makes a person's retry
10
+ * safe.
11
+ */
12
+ export declare const pendingSaveKeys: WeakMap<object, string>;
13
+ //# sourceMappingURL=pending-save-keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pending-save-keys.d.ts","sourceRoot":"","sources":["../../../src/adapters/entity-rest/pending-save-keys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,yBAAgC,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The `Idempotency-Key` each entity's pending save was sent under, kept until
3
+ * that save is answered.
4
+ *
5
+ * Keyed by the entity instance, so a save called again on the same object
6
+ * after a network error — the case the key exists for — sends the same key and
7
+ * the service replays its first answer instead of writing twice. An answered
8
+ * save forgets its key, so the next edit of that object is a new request. The
9
+ * browser itself never retries (ADR 0014); this is what makes a person's retry
10
+ * safe.
11
+ */ export const pendingSaveKeys = new WeakMap();
12
+
13
+ //# sourceMappingURL=pending-save-keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/adapters/entity-rest/pending-save-keys.ts"],"sourcesContent":["/**\n * The `Idempotency-Key` each entity's pending save was sent under, kept until\n * that save is answered.\n *\n * Keyed by the entity instance, so a save called again on the same object\n * after a network error — the case the key exists for — sends the same key and\n * the service replays its first answer instead of writing twice. An answered\n * save forgets its key, so the next edit of that object is a new request. The\n * browser itself never retries (ADR 0014); this is what makes a person's retry\n * safe.\n */\nexport const pendingSaveKeys = new WeakMap<object, string>();\n"],"names":["pendingSaveKeys","WeakMap"],"mappings":"AAAA;;;;;;;;;;CAUC,GACD,OAAO,MAAMA,kBAAkB,IAAIC,UAA0B"}
@@ -0,0 +1,13 @@
1
+ import '@entifix/transactions';
2
+ import { type ProtocolFailure, type WriteResult } from '@entifix/core';
3
+ import { Effect } from 'effect';
4
+ import type { HttpResponse } from '../../clients/types.js';
5
+ /**
6
+ * Reads a write's answer as one of its two modes
7
+ * ([ADR 0022](../../../../../../docs/adr/0022-two-settle-modes-and-the-pending-flow-store.md)):
8
+ * a `202` is a flow, and its body must decode as `flowAccepted`; any other
9
+ * success is the write itself, read by `readSettled`. A failure status never
10
+ * gets here — the fetch client already decoded it as the failure it is.
11
+ */
12
+ export declare const readWriteResponse: <T, E>(response: HttpResponse<unknown>, readSettled: (body: unknown) => Effect.Effect<T, E>) => Effect.Effect<WriteResult<T>, E | ProtocolFailure>;
13
+ //# sourceMappingURL=read-write-response.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-write-response.d.ts","sourceRoot":"","sources":["../../../src/adapters/entity-rest/read-write-response.ts"],"names":[],"mappings":"AACA,OAAO,uBAAuB,CAAC;AAE/B,OAAO,EAGL,KAAK,eAAe,EAEpB,KAAK,WAAW,EACjB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAAI,CAAC,EAAE,CAAC,EACpC,UAAU,YAAY,CAAC,OAAO,CAAC,EAC/B,aAAa,CAAC,IAAI,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,KAClD,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,eAAe,CAOiB,CAAC"}
@@ -0,0 +1,17 @@
1
+ // Loaded for its registration of `flowAccepted`, which the decode below reads.
2
+ import '@entifix/transactions';
3
+ import { decodeEnvelope, pending, settled } from '@entifix/core';
4
+ import { Effect } from 'effect';
5
+ /**
6
+ * Reads a write's answer as one of its two modes
7
+ * ([ADR 0022](../../../../../../docs/adr/0022-two-settle-modes-and-the-pending-flow-store.md)):
8
+ * a `202` is a flow, and its body must decode as `flowAccepted`; any other
9
+ * success is the write itself, read by `readSettled`. A failure status never
10
+ * gets here — the fetch client already decoded it as the failure it is.
11
+ */ export const readWriteResponse = (response, readSettled)=>response.status === 202 ? Effect.map(decodeEnvelope(response.body, 'flowAccepted'), (envelope)=>{
12
+ // Decoded against the registered `flowAccepted` schema just above.
13
+ const accepted = envelope.data;
14
+ return pending(accepted.flowId, accepted.links);
15
+ }) : Effect.map(readSettled(response.body), (value)=>settled(value));
16
+
17
+ //# sourceMappingURL=read-write-response.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/adapters/entity-rest/read-write-response.ts"],"sourcesContent":["// Loaded for its registration of `flowAccepted`, which the decode below reads.\nimport '@entifix/transactions';\n\nimport {\n decodeEnvelope,\n pending,\n type ProtocolFailure,\n settled,\n type WriteResult,\n} from '@entifix/core';\nimport type { FlowAccepted } from '@entifix/transactions';\nimport { Effect } from 'effect';\n\nimport type { HttpResponse } from '../../clients/types.js';\n\n/**\n * Reads a write's answer as one of its two modes\n * ([ADR 0022](../../../../../../docs/adr/0022-two-settle-modes-and-the-pending-flow-store.md)):\n * a `202` is a flow, and its body must decode as `flowAccepted`; any other\n * success is the write itself, read by `readSettled`. A failure status never\n * gets here — the fetch client already decoded it as the failure it is.\n */\nexport const readWriteResponse = <T, E>(\n response: HttpResponse<unknown>,\n readSettled: (body: unknown) => Effect.Effect<T, E>,\n): Effect.Effect<WriteResult<T>, E | ProtocolFailure> =>\n response.status === 202\n ? Effect.map(decodeEnvelope(response.body, 'flowAccepted'), envelope => {\n // Decoded against the registered `flowAccepted` schema just above.\n const accepted = envelope.data as FlowAccepted;\n return pending(accepted.flowId, accepted.links);\n })\n : Effect.map(readSettled(response.body), value => settled(value));\n"],"names":["decodeEnvelope","pending","settled","Effect","readWriteResponse","response","readSettled","status","map","body","envelope","accepted","data","flowId","links","value"],"mappings":"AAAA,+EAA+E;AAC/E,OAAO,wBAAwB;AAE/B,SACEA,cAAc,EACdC,OAAO,EAEPC,OAAO,QAEF,gBAAgB;AAEvB,SAASC,MAAM,QAAQ,SAAS;AAIhC;;;;;;CAMC,GACD,OAAO,MAAMC,oBAAoB,CAC/BC,UACAC,cAEAD,SAASE,MAAM,KAAK,MAChBJ,OAAOK,GAAG,CAACR,eAAeK,SAASI,IAAI,EAAE,iBAAiBC,CAAAA;QACxD,mEAAmE;QACnE,MAAMC,WAAWD,SAASE,IAAI;QAC9B,OAAOX,QAAQU,SAASE,MAAM,EAAEF,SAASG,KAAK;IAChD,KACAX,OAAOK,GAAG,CAACF,YAAYD,SAASI,IAAI,GAAGM,CAAAA,QAASb,QAAQa,QAAQ"}
@@ -1,25 +1,15 @@
1
1
  import type { ConfigurationClient, ConfigurationExtractMode } from '@entifix/core';
2
- /**
3
- * How a create is sent to this entity's service.
4
- *
5
- * `entity` is the plain REST write: `POST` an entity envelope, get the stored
6
- * entity back. `command` is the CQRS write path — the client mints the
7
- * transaction id, `POST`s a `command` envelope and gets a `202` naming the
8
- * transaction, because the write completes asynchronously behind a saga.
9
- *
10
- * It is per entity rather than global because the two live side by side today:
11
- * `ProductSpecification` is transactional, while `ProductBrand` and
12
- * `ProductCategory` are plain writes on another service.
13
- */
14
- export type EntityCreateProtocol = 'entity' | 'command';
15
2
  export interface BuildEntityRestOptions {
16
3
  uriConfig: {
17
4
  key: string;
18
5
  group?: string;
19
6
  extractionMode?: ConfigurationExtractMode;
20
7
  };
21
- /** Defaults to `'entity'` — the plain REST write. */
22
- create?: EntityCreateProtocol;
8
+ /**
9
+ * The method an update is sent with: `PUT` replaces the stored entity,
10
+ * `PATCH` merges into it. Defaults to `'PUT'`.
11
+ */
12
+ update?: 'PUT' | 'PATCH';
23
13
  /**
24
14
  * Where `uriConfig` is looked up, bound when the adapter is built.
25
15
  *
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/adapters/entity-rest/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,wBAAwB,EACzB,MAAM,eAAe,CAAC;AAEvB;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,SAAS,CAAC;AAExD,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE;QACT,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,cAAc,CAAC,EAAE,wBAAwB,CAAC;KAC3C,CAAC;IACF,qDAAqD;IACrD,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B;;;;;;;OAOG;IACH,aAAa,EAAE,mBAAmB,CAAC;CACpC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/adapters/entity-rest/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,wBAAwB,EACzB,MAAM,eAAe,CAAC;AAEvB,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE;QACT,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,cAAc,CAAC,EAAE,wBAAwB,CAAC;KAC3C,CAAC;IACF;;;OAGG;IACH,MAAM,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC;IACzB;;;;;;;OAOG;IACH,aAAa,EAAE,mBAAmB,CAAC;CACpC"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/adapters/entity-rest/types.ts"],"sourcesContent":["import type {\n ConfigurationClient,\n ConfigurationExtractMode,\n} from '@entifix/core';\n\n/**\n * How a create is sent to this entity's service.\n *\n * `entity` is the plain REST write: `POST` an entity envelope, get the stored\n * entity back. `command` is the CQRS write path — the client mints the\n * transaction id, `POST`s a `command` envelope and gets a `202` naming the\n * transaction, because the write completes asynchronously behind a saga.\n *\n * It is per entity rather than global because the two live side by side today:\n * `ProductSpecification` is transactional, while `ProductBrand` and\n * `ProductCategory` are plain writes on another service.\n */\nexport type EntityCreateProtocol = 'entity' | 'command';\n\nexport interface BuildEntityRestOptions {\n uriConfig: {\n key: string;\n group?: string;\n extractionMode?: ConfigurationExtractMode;\n };\n /** Defaults to `'entity'` — the plain REST write. */\n create?: EntityCreateProtocol;\n /**\n * Where `uriConfig` is looked up, bound when the adapter is built.\n *\n * A value rather than a requirement on each call: the URL lookup is this\n * adapter's mechanism, and putting it in the repository port's environment\n * made every use case — and every static or database-backed caller — provide\n * a configuration it never read.\n */\n configuration: ConfigurationClient;\n}\n"],"names":[],"mappings":"AAmBA,WAiBC"}
1
+ {"version":3,"sources":["../../../src/adapters/entity-rest/types.ts"],"sourcesContent":["import type {\n ConfigurationClient,\n ConfigurationExtractMode,\n} from '@entifix/core';\n\nexport interface BuildEntityRestOptions {\n uriConfig: {\n key: string;\n group?: string;\n extractionMode?: ConfigurationExtractMode;\n };\n /**\n * The method an update is sent with: `PUT` replaces the stored entity,\n * `PATCH` merges into it. Defaults to `'PUT'`.\n */\n update?: 'PUT' | 'PATCH';\n /**\n * Where `uriConfig` is looked up, bound when the adapter is built.\n *\n * A value rather than a requirement on each call: the URL lookup is this\n * adapter's mechanism, and putting it in the repository port's environment\n * made every use case — and every static or database-backed caller — provide\n * a configuration it never read.\n */\n configuration: ConfigurationClient;\n}\n"],"names":[],"mappings":"AAKA,WAoBC"}
@@ -7,7 +7,9 @@ import type { BuildEntityRestOptions } from '../entity-rest/types.js';
7
7
  * ([ADR 0020](../../../../../../docs/adr/0020-endpoints-are-descriptors-and-the-shell-builds-an-httpapi.md)).
8
8
  *
9
9
  * A refusal arrives as the failure the service sent, decoded from its problem
10
- * body, so a screen shows the coded message rather than a generic error.
10
+ * body, so a screen shows the coded message rather than a generic error. A
11
+ * verb that starts a flow answers `202 flowAccepted` and runs as pending; any
12
+ * other success is settled with the `data` of what the service answered.
11
13
  */
12
14
  export declare const makeEntityRestUseCaseRunner: <TEntity extends Entity>(entityConstructor: EntityConstructor<TEntity>, { uriConfig, configuration }: BuildEntityRestOptions) => EntityUseCaseRunner;
13
15
  //# sourceMappingURL=make-entity-rest-use-case-runner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"make-entity-rest-use-case-runner.d.ts","sourceRoot":"","sources":["../../../src/adapters/entity-use-case/make-entity-rest-use-case-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,MAAM,EACX,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EAIzB,MAAM,eAAe,CAAC;AAKvB,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEtE;;;;;;;;GAQG;AACH,eAAO,MAAM,2BAA2B,GAAI,OAAO,SAAS,MAAM,EAChE,mBAAmB,iBAAiB,CAAC,OAAO,CAAC,EAC7C,8BAA8B,sBAAsB,KACnD,mBA0CF,CAAC"}
1
+ {"version":3,"file":"make-entity-rest-use-case-runner.d.ts","sourceRoot":"","sources":["../../../src/adapters/entity-use-case/make-entity-rest-use-case-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,MAAM,EACX,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EAIzB,MAAM,eAAe,CAAC;AAMvB,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEtE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,2BAA2B,GAAI,OAAO,SAAS,MAAM,EAChE,mBAAmB,iBAAiB,CAAC,OAAO,CAAC,EAC7C,8BAA8B,sBAAsB,KACnD,mBA+CF,CAAC"}
@@ -2,6 +2,7 @@ import { extractMetaEntity, ProtocolFailure, toWireSelection } from '@entifix/co
2
2
  import { Effect } from 'effect';
3
3
  import { performHttpRequestThroughFetch } from '../../clients/fetch/index.js';
4
4
  import { buildEntityRestAdapterMixins as adapterMixins } from '../entity-rest/build-entity-rest-adapter-mixins/index.js';
5
+ import { readWriteResponse } from '../entity-rest/read-write-response.js';
5
6
  /**
6
7
  * Runs an entity's verbs against the service that serves them, at the path the
7
8
  * shell derives from each verb's key and binding — under the same base URL the
@@ -9,7 +10,9 @@ import { buildEntityRestAdapterMixins as adapterMixins } from '../entity-rest/bu
9
10
  * ([ADR 0020](../../../../../../docs/adr/0020-endpoints-are-descriptors-and-the-shell-builds-an-httpapi.md)).
10
11
  *
11
12
  * A refusal arrives as the failure the service sent, decoded from its problem
12
- * body, so a screen shows the coded message rather than a generic error.
13
+ * body, so a screen shows the coded message rather than a generic error. A
14
+ * verb that starts a flow answers `202 flowAccepted` and runs as pending; any
15
+ * other success is settled with the `data` of what the service answered.
13
16
  */ export const makeEntityRestUseCaseRunner = (entityConstructor, { uriConfig, configuration })=>{
14
17
  var _metaEntity_key;
15
18
  const metaEntity = extractMetaEntity(entityConstructor);
@@ -20,10 +23,14 @@ import { buildEntityRestAdapterMixins as adapterMixins } from '../entity-rest/bu
20
23
  return {
21
24
  run: (useCase, id)=>Effect.gen(function*() {
22
25
  const url = yield* baseUrl(useCase.binding === 'entity' && id != null ? String(id) : undefined);
23
- yield* performHttpRequestThroughFetch({
26
+ const response = yield* performHttpRequestThroughFetch({
24
27
  method: 'POST',
25
28
  url: `${url}/${useCase.key}`
26
29
  });
30
+ return yield* readWriteResponse(response, ()=>{
31
+ var _response_body;
32
+ return Effect.succeed((_response_body = response.body) == null ? void 0 : _response_body.data);
33
+ });
27
34
  }),
28
35
  bulk: (useCase, selection)=>Effect.gen(function*() {
29
36
  var _response_body;