@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.
- package/dist/adapters/entity-rest/build-entity-rest-adapter-delete/build-entity-rest-adapter-delete.d.ts +1 -1
- package/dist/adapters/entity-rest/build-entity-rest-adapter-delete/build-entity-rest-adapter-delete.d.ts.map +1 -1
- package/dist/adapters/entity-rest/build-entity-rest-adapter-facets/build-entity-rest-adapter-facets.d.ts +1 -1
- package/dist/adapters/entity-rest/build-entity-rest-adapter-facets/build-entity-rest-adapter-facets.d.ts.map +1 -1
- package/dist/adapters/entity-rest/build-entity-rest-adapter-get/build-entity-rest-adapter-get.d.ts +1 -1
- package/dist/adapters/entity-rest/build-entity-rest-adapter-get/build-entity-rest-adapter-get.d.ts.map +1 -1
- package/dist/adapters/entity-rest/build-entity-rest-adapter-load/build-entity-rest-adapter-load.d.ts +1 -1
- package/dist/adapters/entity-rest/build-entity-rest-adapter-load/build-entity-rest-adapter-load.d.ts.map +1 -1
- package/dist/adapters/entity-rest/build-entity-rest-adapter-mixins/build-entity-base-url.d.ts +1 -1
- package/dist/adapters/entity-rest/build-entity-rest-adapter-mixins/build-entity-base-url.d.ts.map +1 -1
- package/dist/adapters/entity-rest/build-entity-rest-adapter-mixins/index.d.ts +1 -1
- package/dist/adapters/entity-rest/build-entity-rest-adapter-save/build-entity-rest-adapter-save.d.ts +4 -8
- package/dist/adapters/entity-rest/build-entity-rest-adapter-save/build-entity-rest-adapter-save.d.ts.map +1 -1
- package/dist/adapters/entity-rest/build-entity-rest-adapter-save/build-entity-rest-adapter-save.js +15 -94
- package/dist/adapters/entity-rest/build-entity-rest-adapter-save/build-entity-rest-adapter-save.js.map +1 -1
- package/dist/adapters/entity-rest/build-entity-rest-adapter-write/build-entity-rest-adapter-write.d.ts +10 -0
- package/dist/adapters/entity-rest/build-entity-rest-adapter-write/build-entity-rest-adapter-write.d.ts.map +1 -0
- package/dist/adapters/entity-rest/build-entity-rest-adapter-write/build-entity-rest-adapter-write.js +49 -0
- package/dist/adapters/entity-rest/build-entity-rest-adapter-write/build-entity-rest-adapter-write.js.map +1 -0
- package/dist/adapters/entity-rest/build-entity-rest-adapter-write/index.d.ts +2 -0
- package/dist/adapters/entity-rest/build-entity-rest-adapter-write/index.d.ts.map +1 -0
- package/dist/adapters/entity-rest/build-entity-rest-adapter-write/index.js +3 -0
- package/dist/adapters/entity-rest/build-entity-rest-adapter-write/index.js.map +1 -0
- package/dist/adapters/entity-rest/pending-save-keys.d.ts +13 -0
- package/dist/adapters/entity-rest/pending-save-keys.d.ts.map +1 -0
- package/dist/adapters/entity-rest/pending-save-keys.js +13 -0
- package/dist/adapters/entity-rest/pending-save-keys.js.map +1 -0
- package/dist/adapters/entity-rest/read-write-response.d.ts +13 -0
- package/dist/adapters/entity-rest/read-write-response.d.ts.map +1 -0
- package/dist/adapters/entity-rest/read-write-response.js +17 -0
- package/dist/adapters/entity-rest/read-write-response.js.map +1 -0
- package/dist/adapters/entity-rest/types.d.ts +5 -15
- package/dist/adapters/entity-rest/types.d.ts.map +1 -1
- package/dist/adapters/entity-rest/types.js.map +1 -1
- package/dist/adapters/entity-use-case/make-entity-rest-use-case-runner.d.ts +3 -1
- package/dist/adapters/entity-use-case/make-entity-rest-use-case-runner.d.ts.map +1 -1
- package/dist/adapters/entity-use-case/make-entity-rest-use-case-runner.js +9 -2
- package/dist/adapters/entity-use-case/make-entity-rest-use-case-runner.js.map +1 -1
- package/dist/adapters/flow-status/build-flow-status-reader/build-flow-status-reader.d.ts +19 -0
- package/dist/adapters/flow-status/build-flow-status-reader/build-flow-status-reader.d.ts.map +1 -0
- package/dist/adapters/flow-status/build-flow-status-reader/build-flow-status-reader.js +27 -0
- package/dist/adapters/flow-status/build-flow-status-reader/build-flow-status-reader.js.map +1 -0
- package/dist/adapters/flow-status/build-flow-status-reader/index.d.ts +2 -0
- package/dist/adapters/flow-status/build-flow-status-reader/index.d.ts.map +1 -0
- package/dist/adapters/flow-status/build-flow-status-reader/index.js +3 -0
- package/dist/adapters/flow-status/build-flow-status-reader/index.js.map +1 -0
- package/dist/adapters/is-not-found.d.ts +7 -0
- package/dist/adapters/is-not-found.d.ts.map +1 -0
- package/dist/adapters/is-not-found.js +8 -0
- package/dist/adapters/is-not-found.js.map +1 -0
- package/dist/clients/types.d.ts +1 -1
- package/dist/clients/types.d.ts.map +1 -1
- package/dist/clients/types.js.map +1 -1
- package/dist/configuration-client/configuration-client-rest-client.d.ts.map +1 -1
- package/dist/configuration-client/configuration-client-rest-client.js +5 -3
- package/dist/configuration-client/configuration-client-rest-client.js.map +1 -1
- package/dist/endpoint/participant-client.d.ts +3 -2
- package/dist/endpoint/participant-client.d.ts.map +1 -1
- package/dist/endpoint/participant-client.js +10 -16
- package/dist/endpoint/participant-client.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
- package/dist/adapters/transaction-status/build-transaction-status-reader/build-transaction-status-reader.d.ts +0 -4
- package/dist/adapters/transaction-status/build-transaction-status-reader/build-transaction-status-reader.d.ts.map +0 -1
- package/dist/adapters/transaction-status/build-transaction-status-reader/build-transaction-status-reader.js +0 -47
- package/dist/adapters/transaction-status/build-transaction-status-reader/build-transaction-status-reader.js.map +0 -1
- package/dist/adapters/transaction-status/build-transaction-status-reader/index.d.ts +0 -2
- package/dist/adapters/transaction-status/build-transaction-status-reader/index.d.ts.map +0 -1
- package/dist/adapters/transaction-status/build-transaction-status-reader/index.js +0 -3
- 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").
|
|
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,
|
|
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").
|
|
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,
|
|
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"}
|
package/dist/adapters/entity-rest/build-entity-rest-adapter-get/build-entity-rest-adapter-get.d.ts
CHANGED
|
@@ -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").
|
|
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,
|
|
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"}
|
package/dist/adapters/entity-rest/build-entity-rest-adapter-load/build-entity-rest-adapter-load.d.ts
CHANGED
|
@@ -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").
|
|
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,
|
|
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"}
|
package/dist/adapters/entity-rest/build-entity-rest-adapter-mixins/build-entity-base-url.d.ts
CHANGED
|
@@ -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").
|
|
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
|
package/dist/adapters/entity-rest/build-entity-rest-adapter-mixins/build-entity-base-url.d.ts.map
CHANGED
|
@@ -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,
|
|
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").
|
|
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
|
package/dist/adapters/entity-rest/build-entity-rest-adapter-save/build-entity-rest-adapter-save.d.ts
CHANGED
|
@@ -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
|
|
16
|
-
*
|
|
17
|
-
*
|
|
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>,
|
|
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,
|
|
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"}
|
package/dist/adapters/entity-rest/build-entity-rest-adapter-save/build-entity-rest-adapter-save.js
CHANGED
|
@@ -1,20 +1,6 @@
|
|
|
1
|
-
import { extractMetaEntity,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
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
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
|
|
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
|
|
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
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (
|
|
48
|
-
|
|
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
|
-
|
|
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
|
|
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"}
|
package/dist/adapters/entity-rest/build-entity-rest-adapter-write/build-entity-rest-adapter-write.js
ADDED
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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
|
-
/**
|
|
22
|
-
|
|
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
|
|
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\
|
|
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;
|
|
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;
|