@entifix/core 0.9.0 → 0.10.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 (54) hide show
  1. package/dist/deadline/deadline.d.ts +33 -0
  2. package/dist/deadline/deadline.d.ts.map +1 -0
  3. package/dist/deadline/deadline.js +33 -0
  4. package/dist/deadline/deadline.js.map +1 -0
  5. package/dist/entity-definition/links/entity-collection-link/entity-collection-link.d.ts +3 -3
  6. package/dist/entity-definition/links/entity-collection-link/entity-collection-link.d.ts.map +1 -1
  7. package/dist/entity-definition/links/entity-collection-link/entity-collection-link.js.map +1 -1
  8. package/dist/entity-definition/links/entity-link/entity-link.d.ts +4 -4
  9. package/dist/entity-definition/links/entity-link/entity-link.d.ts.map +1 -1
  10. package/dist/entity-definition/links/entity-link/entity-link.js.map +1 -1
  11. package/dist/entity-definition/links/entity-link-source/entity-link-source.d.ts +3 -3
  12. package/dist/entity-definition/links/entity-link-source/entity-link-source.d.ts.map +1 -1
  13. package/dist/entity-definition/links/entity-link-source/entity-link-source.js.map +1 -1
  14. package/dist/entity-definition/validate/validate-records.d.ts +23 -6
  15. package/dist/entity-definition/validate/validate-records.d.ts.map +1 -1
  16. package/dist/entity-definition/validate/validate-records.js +25 -10
  17. package/dist/entity-definition/validate/validate-records.js.map +1 -1
  18. package/dist/envelope/read-envelope.d.ts +8 -8
  19. package/dist/envelope/read-envelope.d.ts.map +1 -1
  20. package/dist/envelope/read-envelope.js +18 -27
  21. package/dist/envelope/read-envelope.js.map +1 -1
  22. package/dist/failure/define.d.ts +39 -0
  23. package/dist/failure/define.d.ts.map +1 -0
  24. package/dist/failure/define.js +70 -0
  25. package/dist/failure/define.js.map +1 -0
  26. package/dist/failure/failure.d.ts +79 -0
  27. package/dist/failure/failure.d.ts.map +1 -0
  28. package/dist/failure/failure.js +39 -0
  29. package/dist/failure/failure.js.map +1 -0
  30. package/dist/failure/generic.d.ts +141 -0
  31. package/dist/failure/generic.d.ts.map +1 -0
  32. package/dist/failure/generic.js +101 -0
  33. package/dist/failure/generic.js.map +1 -0
  34. package/dist/failure/index.d.ts +50 -0
  35. package/dist/failure/index.d.ts.map +1 -0
  36. package/dist/failure/index.js +47 -0
  37. package/dist/failure/index.js.map +1 -0
  38. package/dist/failure/predicates.d.ts +56 -0
  39. package/dist/failure/predicates.d.ts.map +1 -0
  40. package/dist/failure/predicates.js +22 -0
  41. package/dist/failure/predicates.js.map +1 -0
  42. package/dist/failure/problem.d.ts +49 -0
  43. package/dist/failure/problem.d.ts.map +1 -0
  44. package/dist/failure/problem.js +87 -0
  45. package/dist/failure/problem.js.map +1 -0
  46. package/dist/failure/registry.d.ts +28 -0
  47. package/dist/failure/registry.d.ts.map +1 -0
  48. package/dist/failure/registry.js +36 -0
  49. package/dist/failure/registry.js.map +1 -0
  50. package/dist/index.d.ts +2 -0
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +2 -0
  53. package/dist/index.js.map +1 -1
  54. package/package.json +3 -3
@@ -1,7 +1,7 @@
1
1
  import { _ as _extends } from "@swc/helpers/_/_extends";
2
2
  import { Effect } from 'effect';
3
- import { EntifixBuildError } from '../base-entities/entifix-error/index.js';
4
3
  import { deserializeEntityCollection, deserializeSingleEntity } from '../entity-definition/serializer/index.js';
4
+ import { InvalidEnvelope } from '../failure/generic.js';
5
5
  import { envelopeEntityName } from './make-envelope.js';
6
6
  /**
7
7
  * Structural check only — `meta.type` is validated separately so a mismatch
@@ -15,22 +15,18 @@ import { envelopeEntityName } from './make-envelope.js';
15
15
  }
16
16
  /**
17
17
  * Narrows an arbitrary body to an envelope of the expected `meta.type`, failing
18
- * with an {@link EntifixBuildError} otherwise. A wrong shape must never
18
+ * with an {@link InvalidEnvelope} otherwise. A wrong shape must never
19
19
  * silently deserialize into a half-populated entity.
20
20
  */ function assertEnvelope(entityConstructor, body, expected) {
21
21
  const entity = envelopeEntityName(entityConstructor);
22
22
  if (!isEntifixEnvelope(body)) {
23
- return Effect.fail(new EntifixBuildError(`Expected an EntifixEnvelope for "${entity}" but the payload carried no meta.type`, undefined, {
24
- entity,
25
- expected,
26
- body
23
+ return Effect.fail(new InvalidEnvelope({
24
+ reason: `Expected an EntifixEnvelope for "${entity}" but the payload carried no meta.type`
27
25
  }));
28
26
  }
29
27
  if (body.meta.type !== expected) {
30
- return Effect.fail(new EntifixBuildError(`Expected an EntifixEnvelope of type "${expected}" for "${entity}" but got "${body.meta.type}"`, undefined, {
31
- entity,
32
- expected,
33
- actual: body.meta.type
28
+ return Effect.fail(new InvalidEnvelope({
29
+ reason: `Expected an EntifixEnvelope of type "${expected}" for "${entity}" but got "${body.meta.type}"`
34
30
  }));
35
31
  }
36
32
  return Effect.succeed(body);
@@ -41,17 +37,13 @@ import { envelopeEntityName } from './make-envelope.js';
41
37
  * whose `data` is not a serialized entity. `label` only sharpens error text.
42
38
  */ export function readEnvelope(body, expected, label = 'message') {
43
39
  if (!isEntifixEnvelope(body)) {
44
- return Effect.fail(new EntifixBuildError(`Expected an EntifixEnvelope for "${label}" but the payload carried no meta.type`, undefined, {
45
- label,
46
- expected,
47
- body
40
+ return Effect.fail(new InvalidEnvelope({
41
+ reason: `Expected an EntifixEnvelope for "${label}" but the payload carried no meta.type`
48
42
  }));
49
43
  }
50
44
  if (body.meta.type !== expected) {
51
- return Effect.fail(new EntifixBuildError(`Expected an EntifixEnvelope of type "${expected}" for "${label}" but got "${body.meta.type}"`, undefined, {
52
- label,
53
- expected,
54
- actual: body.meta.type
45
+ return Effect.fail(new InvalidEnvelope({
46
+ reason: `Expected an EntifixEnvelope of type "${expected}" for "${label}" but got "${body.meta.type}"`
55
47
  }));
56
48
  }
57
49
  return Effect.succeed(body);
@@ -60,8 +52,8 @@ export const readEntityEnvelope = (entityConstructor, body)=>Effect.gen(function
60
52
  const envelope = yield* assertEnvelope(entityConstructor, body, 'entity');
61
53
  const entity = yield* deserializeSingleEntity(entityConstructor, envelope.data);
62
54
  if (entity === undefined) {
63
- return yield* Effect.fail(new EntifixBuildError(`EntifixEnvelope for "${envelopeEntityName(entityConstructor)}" carried no data`, undefined, {
64
- entity: envelopeEntityName(entityConstructor)
55
+ return yield* Effect.fail(new InvalidEnvelope({
56
+ reason: `EntifixEnvelope for "${envelopeEntityName(entityConstructor)}" carried no data`
65
57
  }));
66
58
  }
67
59
  return entity;
@@ -93,8 +85,8 @@ export const readEntityPageEnvelope = (entityConstructor, body)=>Effect.gen(func
93
85
  const envelope = yield* assertEnvelope(entityConstructor, body, 'entityMetadata');
94
86
  const document = envelope.data;
95
87
  if (!Array.isArray(document == null ? void 0 : document.actions) || !Array.isArray(document == null ? void 0 : document.useCases)) {
96
- return yield* Effect.fail(new EntifixBuildError(`EntifixEnvelope for "${envelopeEntityName(entityConstructor)}" carried no metadata document`, undefined, {
97
- entity: envelopeEntityName(entityConstructor)
88
+ return yield* Effect.fail(new InvalidEnvelope({
89
+ reason: `EntifixEnvelope for "${envelopeEntityName(entityConstructor)}" carried no metadata document`
98
90
  }));
99
91
  }
100
92
  return document;
@@ -113,8 +105,8 @@ const isFacetValueRow = (row)=>row != null && typeof row === 'object' && [
113
105
  const counts = envelope.data;
114
106
  const wellFormed = counts != null && typeof counts === 'object' && Object.values(counts).every((rows)=>Array.isArray(rows) && rows.every(isFacetValueRow));
115
107
  if (!wellFormed) {
116
- return yield* Effect.fail(new EntifixBuildError(`EntifixEnvelope for "${envelopeEntityName(entityConstructor)}" carried no facet counts`, undefined, {
117
- entity: envelopeEntityName(entityConstructor)
108
+ return yield* Effect.fail(new InvalidEnvelope({
109
+ reason: `EntifixEnvelope for "${envelopeEntityName(entityConstructor)}" carried no facet counts`
118
110
  }));
119
111
  }
120
112
  return counts;
@@ -144,9 +136,8 @@ const isFacetValueRow = (row)=>row != null && typeof row === 'object' && [
144
136
  const event = envelope.meta.event;
145
137
  const missing = REQUIRED_EVENT_META.filter((member)=>typeof (event == null ? void 0 : event[member]) !== 'string' || event[member] === '');
146
138
  if (missing.length > 0) {
147
- return yield* Effect.fail(new EntifixBuildError(`event envelope carried incomplete meta.event (missing ${missing.join(', ')})`, undefined, {
148
- missing,
149
- body
139
+ return yield* Effect.fail(new InvalidEnvelope({
140
+ reason: `event envelope carried incomplete meta.event (missing ${missing.join(', ')})`
150
141
  }));
151
142
  }
152
143
  return _extends({}, event, {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/envelope/read-envelope.ts"],"sourcesContent":["import { Effect } from 'effect';\n\nimport { EntifixBuildError } from '../base-entities/entifix-error/index.js';\nimport type { EntityMetadataDocument } from '../entity-definition/metadata/index.js';\nimport {\n deserializeEntityCollection,\n deserializeSingleEntity,\n} from '../entity-definition/serializer/index.js';\nimport type { Entity, EntityConstructor } from '../types/Entity.js';\nimport type {\n EntityFacetCounts,\n EntityFacetValue,\n} from '../types/EntityFacets.js';\nimport type { EntityPage } from '../types/EntityPage.js';\nimport { envelopeEntityName } from './make-envelope.js';\nimport type {\n DomainEvent,\n EntifixEnvelope,\n EntifixEnvelopeType,\n EntifixEventMeta,\n SerializedEntityPage,\n} from './types.js';\n\n/**\n * Structural check only — `meta.type` is validated separately so a mismatch\n * reports the expected/actual types rather than a generic \"not an envelope\".\n */\nexport function isEntifixEnvelope(body: unknown): body is EntifixEnvelope {\n if (body == null || typeof body !== 'object') {\n return false;\n }\n const meta = (body as EntifixEnvelope).meta;\n return (\n meta != null && typeof meta === 'object' && typeof meta.type === 'string'\n );\n}\n\n/**\n * Narrows an arbitrary body to an envelope of the expected `meta.type`, failing\n * with an {@link EntifixBuildError} otherwise. A wrong shape must never\n * silently deserialize into a half-populated entity.\n */\nfunction assertEnvelope<TEntity extends Entity, TData>(\n entityConstructor: EntityConstructor<TEntity>,\n body: unknown,\n expected: EntifixEnvelopeType,\n): Effect.Effect<EntifixEnvelope<TData>, EntifixBuildError> {\n const entity = envelopeEntityName(entityConstructor);\n\n if (!isEntifixEnvelope(body)) {\n return Effect.fail(\n new EntifixBuildError(\n `Expected an EntifixEnvelope for \"${entity}\" but the payload carried no meta.type`,\n undefined,\n { entity, expected, body },\n ),\n );\n }\n if (body.meta.type !== expected) {\n return Effect.fail(\n new EntifixBuildError(\n `Expected an EntifixEnvelope of type \"${expected}\" for \"${entity}\" but got \"${body.meta.type}\"`,\n undefined,\n { entity, expected, actual: body.meta.type },\n ),\n );\n }\n return Effect.succeed(body as EntifixEnvelope<TData>);\n}\n\n/**\n * Narrows an arbitrary body to an envelope of the expected `meta.type` without\n * requiring an entity constructor — for `command`/`transactionRecord` messages\n * whose `data` is not a serialized entity. `label` only sharpens error text.\n */\nexport function readEnvelope<TData>(\n body: unknown,\n expected: EntifixEnvelopeType,\n label = 'message',\n): Effect.Effect<EntifixEnvelope<TData>, EntifixBuildError> {\n if (!isEntifixEnvelope(body)) {\n return Effect.fail(\n new EntifixBuildError(\n `Expected an EntifixEnvelope for \"${label}\" but the payload carried no meta.type`,\n undefined,\n { label, expected, body },\n ),\n );\n }\n if (body.meta.type !== expected) {\n return Effect.fail(\n new EntifixBuildError(\n `Expected an EntifixEnvelope of type \"${expected}\" for \"${label}\" but got \"${body.meta.type}\"`,\n undefined,\n { label, expected, actual: body.meta.type },\n ),\n );\n }\n return Effect.succeed(body as EntifixEnvelope<TData>);\n}\n\nexport const readEntityEnvelope = <TEntity extends Entity>(\n entityConstructor: EntityConstructor<TEntity>,\n body: unknown,\n) =>\n Effect.gen(function* () {\n const envelope = yield* assertEnvelope<TEntity, unknown>(\n entityConstructor,\n body,\n 'entity',\n );\n const entity = yield* deserializeSingleEntity(\n entityConstructor,\n envelope.data,\n );\n if (entity === undefined) {\n return yield* Effect.fail(\n new EntifixBuildError(\n `EntifixEnvelope for \"${envelopeEntityName(\n entityConstructor,\n )}\" carried no data`,\n undefined,\n { entity: envelopeEntityName(entityConstructor) },\n ),\n );\n }\n return entity;\n });\n\nexport const readEntityCollectionEnvelope = <TEntity extends Entity>(\n entityConstructor: EntityConstructor<TEntity>,\n body: unknown,\n) =>\n Effect.gen(function* () {\n const envelope = yield* assertEnvelope<TEntity, unknown>(\n entityConstructor,\n body,\n 'entityCollection',\n );\n const items = yield* deserializeEntityCollection(\n entityConstructor,\n envelope.data,\n );\n return items as TEntity[];\n });\n\nexport const readEntityPageEnvelope = <TEntity extends Entity>(\n entityConstructor: EntityConstructor<TEntity>,\n body: unknown,\n) =>\n Effect.gen(function* () {\n const envelope = yield* assertEnvelope<\n TEntity,\n SerializedEntityPage<TEntity>\n >(entityConstructor, body, 'entityPage');\n const items = yield* deserializeEntityCollection(\n entityConstructor,\n envelope.data?.items,\n );\n return {\n items: items as TEntity[],\n total: envelope.data?.total ?? 0,\n request: envelope.data?.request ?? {},\n } satisfies EntityPage<TEntity>;\n });\n\n/**\n * Reads a `$metadata` response back into its document.\n *\n * No deserialization step, and no defaulting of the members either: an envelope\n * whose `data` is missing a list would leave a form guessing whether \"no\n * actions\" meant \"denied\" or \"malformed\", so a broken payload fails loudly here\n * the way a half-populated entity does.\n */\nexport const readEntityMetadataEnvelope = <TEntity extends Entity>(\n entityConstructor: EntityConstructor<TEntity>,\n body: unknown,\n) =>\n Effect.gen(function* () {\n const envelope = yield* assertEnvelope<TEntity, EntityMetadataDocument>(\n entityConstructor,\n body,\n 'entityMetadata',\n );\n const document = envelope.data;\n if (\n !Array.isArray(document?.actions) ||\n !Array.isArray(document?.useCases)\n ) {\n return yield* Effect.fail(\n new EntifixBuildError(\n `EntifixEnvelope for \"${envelopeEntityName(\n entityConstructor,\n )}\" carried no metadata document`,\n undefined,\n { entity: envelopeEntityName(entityConstructor) },\n ),\n );\n }\n return document;\n });\n\nconst isFacetValueRow = (row: unknown): row is EntityFacetValue =>\n row != null &&\n typeof row === 'object' &&\n ['string', 'number', 'boolean'].includes(\n typeof (row as EntityFacetValue).value,\n ) &&\n typeof (row as EntityFacetValue).count === 'number';\n\n/**\n * Reads a `$facets` response back into its counts, refusing a body whose lists\n * are not `{ value, count }` rows — a panel that rendered a malformed count\n * would show a number nobody computed.\n */\nexport const readEntityFacetsEnvelope = <TEntity extends Entity>(\n entityConstructor: EntityConstructor<TEntity>,\n body: unknown,\n) =>\n Effect.gen(function* () {\n const envelope = yield* assertEnvelope<TEntity, EntityFacetCounts>(\n entityConstructor,\n body,\n 'entityFacets',\n );\n const counts = envelope.data;\n const wellFormed =\n counts != null &&\n typeof counts === 'object' &&\n Object.values(counts).every(\n rows => Array.isArray(rows) && rows.every(isFacetValueRow),\n );\n if (!wellFormed) {\n return yield* Effect.fail(\n new EntifixBuildError(\n `EntifixEnvelope for \"${envelopeEntityName(\n entityConstructor,\n )}\" carried no facet counts`,\n undefined,\n { entity: envelopeEntityName(entityConstructor) },\n ),\n );\n }\n return counts;\n });\n\n/** Every member `meta.event` must carry for a message to be routable at all. */\nconst REQUIRED_EVENT_META = ['name', 'id', 'source', 'at'] as const;\n\n/**\n * Reads a bus message back into a {@link DomainEvent}.\n *\n * The metadata is validated rather than defaulted, and that is the point: a\n * message missing `id` cannot be deduplicated and a message missing `name`\n * cannot be routed, so both are failures a consumer must see rather than\n * absences it silently works around. It is the same call\n * {@link readEntityMetadataEnvelope} makes — a broken payload fails loudly\n * instead of arriving half-populated.\n *\n * Note this does not validate `data`. The transport has no idea what a\n * `catalog.published` payload should look like, and inventing an opinion here\n * is how the bus would start knowing about domains.\n */\nexport function readEventEnvelope<TData = unknown>(\n body: unknown,\n): Effect.Effect<DomainEvent<TData>, EntifixBuildError> {\n return Effect.gen(function* () {\n const envelope = yield* readEnvelope<TData>(body, 'event', 'event');\n const event = envelope.meta.event;\n const missing = REQUIRED_EVENT_META.filter(\n member => typeof event?.[member] !== 'string' || event[member] === '',\n );\n if (missing.length > 0) {\n return yield* Effect.fail(\n new EntifixBuildError(\n `event envelope carried incomplete meta.event (missing ${missing.join(\n ', ',\n )})`,\n undefined,\n { missing, body },\n ),\n );\n }\n return { ...(event as EntifixEventMeta), data: envelope.data };\n });\n}\n"],"names":["Effect","EntifixBuildError","deserializeEntityCollection","deserializeSingleEntity","envelopeEntityName","isEntifixEnvelope","body","meta","type","assertEnvelope","entityConstructor","expected","entity","fail","undefined","actual","succeed","readEnvelope","label","readEntityEnvelope","gen","envelope","data","readEntityCollectionEnvelope","items","readEntityPageEnvelope","total","request","readEntityMetadataEnvelope","document","Array","isArray","actions","useCases","isFacetValueRow","row","includes","value","count","readEntityFacetsEnvelope","counts","wellFormed","Object","values","every","rows","REQUIRED_EVENT_META","readEventEnvelope","event","missing","filter","member","length","join"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/envelope/read-envelope.ts"],"sourcesContent":["import { Effect } from 'effect';\n\nimport type { EntityMetadataDocument } from '../entity-definition/metadata/index.js';\nimport {\n deserializeEntityCollection,\n deserializeSingleEntity,\n} from '../entity-definition/serializer/index.js';\nimport { InvalidEnvelope } from '../failure/generic.js';\nimport type { Entity, EntityConstructor } from '../types/Entity.js';\nimport type {\n EntityFacetCounts,\n EntityFacetValue,\n} from '../types/EntityFacets.js';\nimport type { EntityPage } from '../types/EntityPage.js';\nimport { envelopeEntityName } from './make-envelope.js';\nimport type {\n DomainEvent,\n EntifixEnvelope,\n EntifixEnvelopeType,\n EntifixEventMeta,\n SerializedEntityPage,\n} from './types.js';\n\n/**\n * Structural check only — `meta.type` is validated separately so a mismatch\n * reports the expected/actual types rather than a generic \"not an envelope\".\n */\nexport function isEntifixEnvelope(body: unknown): body is EntifixEnvelope {\n if (body == null || typeof body !== 'object') {\n return false;\n }\n const meta = (body as EntifixEnvelope).meta;\n return (\n meta != null && typeof meta === 'object' && typeof meta.type === 'string'\n );\n}\n\n/**\n * Narrows an arbitrary body to an envelope of the expected `meta.type`, failing\n * with an {@link InvalidEnvelope} otherwise. A wrong shape must never\n * silently deserialize into a half-populated entity.\n */\nfunction assertEnvelope<TEntity extends Entity, TData>(\n entityConstructor: EntityConstructor<TEntity>,\n body: unknown,\n expected: EntifixEnvelopeType,\n): Effect.Effect<EntifixEnvelope<TData>, InvalidEnvelope> {\n const entity = envelopeEntityName(entityConstructor);\n\n if (!isEntifixEnvelope(body)) {\n return Effect.fail(\n new InvalidEnvelope({\n reason: `Expected an EntifixEnvelope for \"${entity}\" but the payload carried no meta.type`,\n }),\n );\n }\n if (body.meta.type !== expected) {\n return Effect.fail(\n new InvalidEnvelope({\n reason: `Expected an EntifixEnvelope of type \"${expected}\" for \"${entity}\" but got \"${body.meta.type}\"`,\n }),\n );\n }\n return Effect.succeed(body as EntifixEnvelope<TData>);\n}\n\n/**\n * Narrows an arbitrary body to an envelope of the expected `meta.type` without\n * requiring an entity constructor — for `command`/`transactionRecord` messages\n * whose `data` is not a serialized entity. `label` only sharpens error text.\n */\nexport function readEnvelope<TData>(\n body: unknown,\n expected: EntifixEnvelopeType,\n label = 'message',\n): Effect.Effect<EntifixEnvelope<TData>, InvalidEnvelope> {\n if (!isEntifixEnvelope(body)) {\n return Effect.fail(\n new InvalidEnvelope({\n reason: `Expected an EntifixEnvelope for \"${label}\" but the payload carried no meta.type`,\n }),\n );\n }\n if (body.meta.type !== expected) {\n return Effect.fail(\n new InvalidEnvelope({\n reason: `Expected an EntifixEnvelope of type \"${expected}\" for \"${label}\" but got \"${body.meta.type}\"`,\n }),\n );\n }\n return Effect.succeed(body as EntifixEnvelope<TData>);\n}\n\nexport const readEntityEnvelope = <TEntity extends Entity>(\n entityConstructor: EntityConstructor<TEntity>,\n body: unknown,\n) =>\n Effect.gen(function* () {\n const envelope = yield* assertEnvelope<TEntity, unknown>(\n entityConstructor,\n body,\n 'entity',\n );\n const entity = yield* deserializeSingleEntity(\n entityConstructor,\n envelope.data,\n );\n if (entity === undefined) {\n return yield* Effect.fail(\n new InvalidEnvelope({\n reason: `EntifixEnvelope for \"${envelopeEntityName(\n entityConstructor,\n )}\" carried no data`,\n }),\n );\n }\n return entity;\n });\n\nexport const readEntityCollectionEnvelope = <TEntity extends Entity>(\n entityConstructor: EntityConstructor<TEntity>,\n body: unknown,\n) =>\n Effect.gen(function* () {\n const envelope = yield* assertEnvelope<TEntity, unknown>(\n entityConstructor,\n body,\n 'entityCollection',\n );\n const items = yield* deserializeEntityCollection(\n entityConstructor,\n envelope.data,\n );\n return items as TEntity[];\n });\n\nexport const readEntityPageEnvelope = <TEntity extends Entity>(\n entityConstructor: EntityConstructor<TEntity>,\n body: unknown,\n) =>\n Effect.gen(function* () {\n const envelope = yield* assertEnvelope<\n TEntity,\n SerializedEntityPage<TEntity>\n >(entityConstructor, body, 'entityPage');\n const items = yield* deserializeEntityCollection(\n entityConstructor,\n envelope.data?.items,\n );\n return {\n items: items as TEntity[],\n total: envelope.data?.total ?? 0,\n request: envelope.data?.request ?? {},\n } satisfies EntityPage<TEntity>;\n });\n\n/**\n * Reads a `$metadata` response back into its document.\n *\n * No deserialization step, and no defaulting of the members either: an envelope\n * whose `data` is missing a list would leave a form guessing whether \"no\n * actions\" meant \"denied\" or \"malformed\", so a broken payload fails loudly here\n * the way a half-populated entity does.\n */\nexport const readEntityMetadataEnvelope = <TEntity extends Entity>(\n entityConstructor: EntityConstructor<TEntity>,\n body: unknown,\n) =>\n Effect.gen(function* () {\n const envelope = yield* assertEnvelope<TEntity, EntityMetadataDocument>(\n entityConstructor,\n body,\n 'entityMetadata',\n );\n const document = envelope.data;\n if (\n !Array.isArray(document?.actions) ||\n !Array.isArray(document?.useCases)\n ) {\n return yield* Effect.fail(\n new InvalidEnvelope({\n reason: `EntifixEnvelope for \"${envelopeEntityName(\n entityConstructor,\n )}\" carried no metadata document`,\n }),\n );\n }\n return document;\n });\n\nconst isFacetValueRow = (row: unknown): row is EntityFacetValue =>\n row != null &&\n typeof row === 'object' &&\n ['string', 'number', 'boolean'].includes(\n typeof (row as EntityFacetValue).value,\n ) &&\n typeof (row as EntityFacetValue).count === 'number';\n\n/**\n * Reads a `$facets` response back into its counts, refusing a body whose lists\n * are not `{ value, count }` rows — a panel that rendered a malformed count\n * would show a number nobody computed.\n */\nexport const readEntityFacetsEnvelope = <TEntity extends Entity>(\n entityConstructor: EntityConstructor<TEntity>,\n body: unknown,\n) =>\n Effect.gen(function* () {\n const envelope = yield* assertEnvelope<TEntity, EntityFacetCounts>(\n entityConstructor,\n body,\n 'entityFacets',\n );\n const counts = envelope.data;\n const wellFormed =\n counts != null &&\n typeof counts === 'object' &&\n Object.values(counts).every(\n rows => Array.isArray(rows) && rows.every(isFacetValueRow),\n );\n if (!wellFormed) {\n return yield* Effect.fail(\n new InvalidEnvelope({\n reason: `EntifixEnvelope for \"${envelopeEntityName(\n entityConstructor,\n )}\" carried no facet counts`,\n }),\n );\n }\n return counts;\n });\n\n/** Every member `meta.event` must carry for a message to be routable at all. */\nconst REQUIRED_EVENT_META = ['name', 'id', 'source', 'at'] as const;\n\n/**\n * Reads a bus message back into a {@link DomainEvent}.\n *\n * The metadata is validated rather than defaulted, and that is the point: a\n * message missing `id` cannot be deduplicated and a message missing `name`\n * cannot be routed, so both are failures a consumer must see rather than\n * absences it silently works around. It is the same call\n * {@link readEntityMetadataEnvelope} makes — a broken payload fails loudly\n * instead of arriving half-populated.\n *\n * Note this does not validate `data`. The transport has no idea what a\n * `catalog.published` payload should look like, and inventing an opinion here\n * is how the bus would start knowing about domains.\n */\nexport function readEventEnvelope<TData = unknown>(\n body: unknown,\n): Effect.Effect<DomainEvent<TData>, InvalidEnvelope> {\n return Effect.gen(function* () {\n const envelope = yield* readEnvelope<TData>(body, 'event', 'event');\n const event = envelope.meta.event;\n const missing = REQUIRED_EVENT_META.filter(\n member => typeof event?.[member] !== 'string' || event[member] === '',\n );\n if (missing.length > 0) {\n return yield* Effect.fail(\n new InvalidEnvelope({\n reason: `event envelope carried incomplete meta.event (missing ${missing.join(\n ', ',\n )})`,\n }),\n );\n }\n return { ...(event as EntifixEventMeta), data: envelope.data };\n });\n}\n"],"names":["Effect","deserializeEntityCollection","deserializeSingleEntity","InvalidEnvelope","envelopeEntityName","isEntifixEnvelope","body","meta","type","assertEnvelope","entityConstructor","expected","entity","fail","reason","succeed","readEnvelope","label","readEntityEnvelope","gen","envelope","data","undefined","readEntityCollectionEnvelope","items","readEntityPageEnvelope","total","request","readEntityMetadataEnvelope","document","Array","isArray","actions","useCases","isFacetValueRow","row","includes","value","count","readEntityFacetsEnvelope","counts","wellFormed","Object","values","every","rows","REQUIRED_EVENT_META","readEventEnvelope","event","missing","filter","member","length","join"],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import { Schema } from 'effect';
2
+ import { type FailureCategory, type FailureFacts } from './failure.js';
3
+ export interface FailureOptions<Fields> {
4
+ /**
5
+ * The failure's `message`, from its fields — what a terminal shows when it is
6
+ * thrown and what a problem body carries as `detail`. Written for a reader:
7
+ * never a stack, never `String(error)`.
8
+ */
9
+ readonly message?: (fields: Fields) => string;
10
+ }
11
+ /**
12
+ * The definer for one category.
13
+ *
14
+ * ```ts
15
+ * class DuplicateSlug extends Failure.conflict<DuplicateSlug>()(
16
+ * 'DuplicateSlug',
17
+ * 'duplicateSlug',
18
+ * { slug: Schema.String },
19
+ * ) {}
20
+ * ```
21
+ *
22
+ * The curried `<Self>()` is `Schema.TaggedError`'s own shape, kept because the
23
+ * class has to name itself for its instances to type as itself. `code`,
24
+ * `category` and `family` ride on the prototype — they are facts about the
25
+ * class, not fields an instance is constructed with — and enter the instance
26
+ * type through `TaggedError`'s brand parameter, as literals, so a predicate on
27
+ * them narrows a union.
28
+ *
29
+ * The code is registered here, at definition. A second tag claiming it throws
30
+ * before anything runs.
31
+ *
32
+ * ⚠️ The registry holds the class this returns, not the subclass that extends
33
+ * it, so a failure decoded from a wire is an instance of the base. That is why
34
+ * a failure class carries fields and no behaviour — a `message` written as a
35
+ * getter on the subclass would vanish on decode, so it is passed here and put
36
+ * on the base — and why nothing matches a failure with `instanceof`.
37
+ */
38
+ export declare const defineFailure: <C extends FailureCategory>(category: C) => <Self = never>() => <const Tag extends string, const Code extends string, const Fields extends Schema.Struct.Fields = Record<never, never>>(tag: Tag, code: Code, fields?: Fields, options?: FailureOptions<Schema.Struct.Type<Fields>>) => [Self] extends [never] ? "Missing `Self` generic - use `class Self extends Schema.TaggedError<Self>(...)`" : Schema.Class<Self, Schema.TaggedStruct<Tag, Fields>, import("effect/Cause").YieldableError & FailureFacts<Code, C>>;
39
+ //# sourceMappingURL=define.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../../src/failure/define.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,EACL,KAAK,eAAe,EAEpB,KAAK,YAAY,EAGlB,MAAM,cAAc,CAAC;AAGtB,MAAM,WAAW,cAAc,CAAC,MAAM;IACpC;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;CAC/C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,aAAa,GACvB,CAAC,SAAS,eAAe,EAAE,UAAU,CAAC,MACtC,IAAI,GAAG,KAAK,QAEX,KAAK,CAAC,GAAG,SAAS,MAAM,EACxB,KAAK,CAAC,IAAI,SAAS,MAAM,EACzB,KAAK,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAEhE,KAAK,GAAG,EACR,MAAM,IAAI,EACV,SAAS,MAAM,EACf,UAAS,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAM,qOA0CzD,CAAC"}
@@ -0,0 +1,70 @@
1
+ import { _ as _extends } from "@swc/helpers/_/_extends";
2
+ import { Schema } from 'effect';
3
+ import { familyOf, RESERVED_FIELDS } from './failure.js';
4
+ import { failureTypeUri, registerFailure } from './registry.js';
5
+ /**
6
+ * The definer for one category.
7
+ *
8
+ * ```ts
9
+ * class DuplicateSlug extends Failure.conflict<DuplicateSlug>()(
10
+ * 'DuplicateSlug',
11
+ * 'duplicateSlug',
12
+ * { slug: Schema.String },
13
+ * ) {}
14
+ * ```
15
+ *
16
+ * The curried `<Self>()` is `Schema.TaggedError`'s own shape, kept because the
17
+ * class has to name itself for its instances to type as itself. `code`,
18
+ * `category` and `family` ride on the prototype — they are facts about the
19
+ * class, not fields an instance is constructed with — and enter the instance
20
+ * type through `TaggedError`'s brand parameter, as literals, so a predicate on
21
+ * them narrows a union.
22
+ *
23
+ * The code is registered here, at definition. A second tag claiming it throws
24
+ * before anything runs.
25
+ *
26
+ * ⚠️ The registry holds the class this returns, not the subclass that extends
27
+ * it, so a failure decoded from a wire is an instance of the base. That is why
28
+ * a failure class carries fields and no behaviour — a `message` written as a
29
+ * getter on the subclass would vanish on decode, so it is passed here and put
30
+ * on the base — and why nothing matches a failure with `instanceof`.
31
+ */ export const defineFailure = (category)=>()=>(tag, code, fields, options = {})=>{
32
+ const own = fields != null ? fields : {};
33
+ const shadowed = Object.keys(own).filter((key)=>RESERVED_FIELDS.has(key));
34
+ if (shadowed.length > 0) throw new Error(`failure '${tag}' declares ${shadowed.map((key)=>`'${key}'`).join(', ')}, ` + 'which the problem body reserves for itself. Rename the field.');
35
+ const Base = Schema.TaggedError()(tag, own);
36
+ // `Base` is still `TaggedError`'s conditional type here — `Self` resolves
37
+ // only at the `extends` site — so the prototype is reached through a cast.
38
+ Object.defineProperties(Base.prototype, _extends({
39
+ code: {
40
+ value: code,
41
+ enumerable: false
42
+ },
43
+ category: {
44
+ value: category,
45
+ enumerable: false
46
+ },
47
+ family: {
48
+ value: familyOf(category),
49
+ enumerable: false
50
+ }
51
+ }, options.message === undefined ? {} : {
52
+ message: {
53
+ get () {
54
+ return options.message == null ? void 0 : options.message.call(options, this);
55
+ },
56
+ enumerable: false
57
+ }
58
+ }));
59
+ registerFailure({
60
+ code,
61
+ tag,
62
+ category,
63
+ family: familyOf(category),
64
+ type: failureTypeUri(code),
65
+ failureClass: Base
66
+ });
67
+ return Base;
68
+ };
69
+
70
+ //# sourceMappingURL=define.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/failure/define.ts"],"sourcesContent":["import { Schema } from 'effect';\n\nimport {\n type FailureCategory,\n type FailureClass,\n type FailureFacts,\n familyOf,\n RESERVED_FIELDS,\n} from './failure.js';\nimport { failureTypeUri, registerFailure } from './registry.js';\n\nexport interface FailureOptions<Fields> {\n /**\n * The failure's `message`, from its fields — what a terminal shows when it is\n * thrown and what a problem body carries as `detail`. Written for a reader:\n * never a stack, never `String(error)`.\n */\n readonly message?: (fields: Fields) => string;\n}\n\n/**\n * The definer for one category.\n *\n * ```ts\n * class DuplicateSlug extends Failure.conflict<DuplicateSlug>()(\n * 'DuplicateSlug',\n * 'duplicateSlug',\n * { slug: Schema.String },\n * ) {}\n * ```\n *\n * The curried `<Self>()` is `Schema.TaggedError`'s own shape, kept because the\n * class has to name itself for its instances to type as itself. `code`,\n * `category` and `family` ride on the prototype — they are facts about the\n * class, not fields an instance is constructed with — and enter the instance\n * type through `TaggedError`'s brand parameter, as literals, so a predicate on\n * them narrows a union.\n *\n * The code is registered here, at definition. A second tag claiming it throws\n * before anything runs.\n *\n * ⚠️ The registry holds the class this returns, not the subclass that extends\n * it, so a failure decoded from a wire is an instance of the base. That is why\n * a failure class carries fields and no behaviour — a `message` written as a\n * getter on the subclass would vanish on decode, so it is passed here and put\n * on the base — and why nothing matches a failure with `instanceof`.\n */\nexport const defineFailure =\n <C extends FailureCategory>(category: C) =>\n <Self = never>() =>\n <\n const Tag extends string,\n const Code extends string,\n const Fields extends Schema.Struct.Fields = Record<never, never>,\n >(\n tag: Tag,\n code: Code,\n fields?: Fields,\n options: FailureOptions<Schema.Struct.Type<Fields>> = {},\n ) => {\n const own = fields ?? ({} as Fields);\n const shadowed = Object.keys(own).filter(key => RESERVED_FIELDS.has(key));\n if (shadowed.length > 0)\n throw new Error(\n `failure '${tag}' declares ${shadowed.map(key => `'${key}'`).join(', ')}, ` +\n 'which the problem body reserves for itself. Rename the field.',\n );\n\n const Base = Schema.TaggedError<Self, FailureFacts<Code, C>>()(tag, own);\n // `Base` is still `TaggedError`'s conditional type here — `Self` resolves\n // only at the `extends` site — so the prototype is reached through a cast.\n Object.defineProperties(\n (Base as unknown as { prototype: object }).prototype,\n {\n code: { value: code, enumerable: false },\n category: { value: category, enumerable: false },\n family: { value: familyOf(category), enumerable: false },\n ...(options.message === undefined\n ? {}\n : {\n message: {\n get(this: Schema.Struct.Type<Fields>) {\n return options.message?.(this);\n },\n enumerable: false,\n },\n }),\n },\n );\n\n registerFailure({\n code,\n tag,\n category,\n family: familyOf(category),\n type: failureTypeUri(code),\n failureClass: Base as unknown as FailureClass,\n });\n\n return Base;\n };\n"],"names":["Schema","familyOf","RESERVED_FIELDS","failureTypeUri","registerFailure","defineFailure","category","tag","code","fields","options","own","shadowed","Object","keys","filter","key","has","length","Error","map","join","Base","TaggedError","defineProperties","prototype","value","enumerable","family","message","undefined","get","type","failureClass"],"mappings":";AAAA,SAASA,MAAM,QAAQ,SAAS;AAEhC,SAIEC,QAAQ,EACRC,eAAe,QACV,eAAe;AACtB,SAASC,cAAc,EAAEC,eAAe,QAAQ,gBAAgB;AAWhE;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BC,GACD,OAAO,MAAMC,gBACX,CAA4BC,WAC5B,IACA,CAKEC,KACAC,MACAC,QACAC,UAAsD,CAAC,CAAC;YAExD,MAAMC,MAAMF,iBAAAA,SAAW,CAAC;YACxB,MAAMG,WAAWC,OAAOC,IAAI,CAACH,KAAKI,MAAM,CAACC,CAAAA,MAAOd,gBAAgBe,GAAG,CAACD;YACpE,IAAIJ,SAASM,MAAM,GAAG,GACpB,MAAM,IAAIC,MACR,CAAC,SAAS,EAAEZ,IAAI,WAAW,EAAEK,SAASQ,GAAG,CAACJ,CAAAA,MAAO,CAAC,CAAC,EAAEA,IAAI,CAAC,CAAC,EAAEK,IAAI,CAAC,MAAM,EAAE,CAAC,GACzE;YAGN,MAAMC,OAAOtB,OAAOuB,WAAW,GAAgChB,KAAKI;YACpE,0EAA0E;YAC1E,2EAA2E;YAC3EE,OAAOW,gBAAgB,CACrB,AAACF,KAA0CG,SAAS,EACpD;gBACEjB,MAAM;oBAAEkB,OAAOlB;oBAAMmB,YAAY;gBAAM;gBACvCrB,UAAU;oBAAEoB,OAAOpB;oBAAUqB,YAAY;gBAAM;gBAC/CC,QAAQ;oBAAEF,OAAOzB,SAASK;oBAAWqB,YAAY;gBAAM;eACnDjB,QAAQmB,OAAO,KAAKC,YACpB,CAAC,IACD;gBACED,SAAS;oBACPE;wBACE,OAAOrB,QAAQmB,OAAO,oBAAfnB,QAAQmB,OAAO,MAAfnB,SAAkB,IAAI;oBAC/B;oBACAiB,YAAY;gBACd;YACF;YAIRvB,gBAAgB;gBACdI;gBACAD;gBACAD;gBACAsB,QAAQ3B,SAASK;gBACjB0B,MAAM7B,eAAeK;gBACrByB,cAAcX;YAChB;YAEA,OAAOA;QACT,EAAE"}
@@ -0,0 +1,79 @@
1
+ import type { Schema } from 'effect';
2
+ import type { EntifixError } from '../base-entities/entifix-error/entifix-error.js';
3
+ /**
4
+ * The two families every failure belongs to
5
+ * ([ADR 0013](../../../../../docs/adr/0013-failures-are-typed-values-decided-at-the-shell.md)).
6
+ *
7
+ * - `business` — an answer. The request was understood and the answer is no.
8
+ * Never retried, never trips a breaker.
9
+ * - `technical` — a non-answer. Something stopped the request being answered,
10
+ * and the layer directly above may retry it.
11
+ */
12
+ export type FailureFamily = 'business' | 'technical';
13
+ /** The business categories, each with the status it answers by default. */
14
+ export declare const BUSINESS_CATEGORIES: {
15
+ readonly invalid: 400;
16
+ readonly unauthenticated: 401;
17
+ readonly forbidden: 403;
18
+ readonly notFound: 404;
19
+ readonly conflict: 409;
20
+ readonly declined: 422;
21
+ };
22
+ /** The technical categories, each with the status it answers by default. */
23
+ export declare const TECHNICAL_CATEGORIES: {
24
+ readonly contention: 409;
25
+ readonly exhausted: 429;
26
+ readonly unavailable: 503;
27
+ readonly timeout: 504;
28
+ readonly protocol: 502;
29
+ readonly internal: 500;
30
+ };
31
+ export type BusinessCategory = keyof typeof BUSINESS_CATEGORIES;
32
+ export type TechnicalCategory = keyof typeof TECHNICAL_CATEGORIES;
33
+ /**
34
+ * The closed set. Every layer branches on it — the shell's status and log
35
+ * tables, the bus's poison rule, the client's inline-versus-toast choice — so
36
+ * it stays small enough for each of them to be exhaustive over. Tags stay open.
37
+ */
38
+ export type FailureCategory = BusinessCategory | TechnicalCategory;
39
+ export type FamilyOf<C extends FailureCategory> = C extends BusinessCategory ? 'business' : 'technical';
40
+ export declare const FAILURE_CATEGORIES: readonly FailureCategory[];
41
+ export declare const familyOf: <C extends FailureCategory>(category: C) => FamilyOf<C>;
42
+ /** The status a category answers with unless a host overrides its tag. */
43
+ export declare const defaultStatus: (category: FailureCategory) => number;
44
+ /**
45
+ * What every failure carries beyond its own fields. `code` is the permanent,
46
+ * wire-visible key a client translates; `category` and `family` are what every
47
+ * layer above decides by.
48
+ */
49
+ export interface FailureFacts<Code extends string = string, C extends FailureCategory = FailureCategory> {
50
+ readonly code: Code;
51
+ readonly category: C;
52
+ readonly family: FamilyOf<C>;
53
+ }
54
+ /**
55
+ * Any failure the framework or a host raises: a `Schema.TaggedError` carrying
56
+ * its code, category and family.
57
+ */
58
+ export interface EntifixFailure<Tag extends string = string, Code extends string = string, C extends FailureCategory = FailureCategory> extends FailureFacts<Code, C> {
59
+ readonly _tag: Tag;
60
+ readonly message: string;
61
+ }
62
+ /** A failure class, as the registry and the problem codec hold it. */
63
+ export interface FailureClass {
64
+ new (...args: never[]): EntifixFailure;
65
+ readonly identifier: string;
66
+ readonly fields: Schema.Struct.Fields;
67
+ }
68
+ /**
69
+ * Members of the problem body that a failure's own fields must not shadow,
70
+ * because the decoder reads them back as the envelope rather than as fields.
71
+ */
72
+ export declare const RESERVED_FIELDS: ReadonlySet<string>;
73
+ /**
74
+ * What a port or a hook fails with while the framework moves from the
75
+ * `EntifixError` class tree to typed failures: either one. Deleted with the
76
+ * class tree, in the release that removes it.
77
+ */
78
+ export type TransitionalFailure = EntifixError | EntifixFailure;
79
+ //# sourceMappingURL=failure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"failure.d.ts","sourceRoot":"","sources":["../../src/failure/failure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAErC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iDAAiD,CAAC;AAEpF;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,WAAW,CAAC;AAErD,2EAA2E;AAC3E,eAAO,MAAM,mBAAmB;;;;;;;CAOtB,CAAC;AAEX,4EAA4E;AAC5E,eAAO,MAAM,oBAAoB;;;;;;;CAOvB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,MAAM,OAAO,mBAAmB,CAAC;AAChE,MAAM,MAAM,iBAAiB,GAAG,MAAM,OAAO,oBAAoB,CAAC;AAElE;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,gBAAgB,GAAG,iBAAiB,CAAC;AAEnE,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,eAAe,IAAI,CAAC,SAAS,gBAAgB,GACxE,UAAU,GACV,WAAW,CAAC;AAEhB,eAAO,MAAM,kBAAkB,EAAE,SAAS,eAAe,EAGxD,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,CAAC,SAAS,eAAe,EAAE,UAAU,CAAC,KAAG,QAAQ,CAAC,CAAC,CACC,CAAC;AAE9E,0EAA0E;AAC1E,eAAO,MAAM,aAAa,GAAI,UAAU,eAAe,KAAG,MAGD,CAAC;AAE1D;;;;GAIG;AACH,MAAM,WAAW,YAAY,CAC3B,IAAI,SAAS,MAAM,GAAG,MAAM,EAC5B,CAAC,SAAS,eAAe,GAAG,eAAe;IAE3C,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc,CAC7B,GAAG,SAAS,MAAM,GAAG,MAAM,EAC3B,IAAI,SAAS,MAAM,GAAG,MAAM,EAC5B,CAAC,SAAS,eAAe,GAAG,eAAe,CAC3C,SAAQ,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC;IACnB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,sEAAsE;AACtE,MAAM,WAAW,YAAY;IAC3B,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,GAAG,cAAc,CAAC;IACvC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;CACvC;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,MAAM,CAW9C,CAAC;AAEH;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,YAAY,GAAG,cAAc,CAAC"}
@@ -0,0 +1,39 @@
1
+ /** The business categories, each with the status it answers by default. */ export const BUSINESS_CATEGORIES = {
2
+ invalid: 400,
3
+ unauthenticated: 401,
4
+ forbidden: 403,
5
+ notFound: 404,
6
+ conflict: 409,
7
+ declined: 422
8
+ };
9
+ /** The technical categories, each with the status it answers by default. */ export const TECHNICAL_CATEGORIES = {
10
+ contention: 409,
11
+ exhausted: 429,
12
+ unavailable: 503,
13
+ timeout: 504,
14
+ protocol: 502,
15
+ internal: 500
16
+ };
17
+ export const FAILURE_CATEGORIES = [
18
+ ...Object.keys(BUSINESS_CATEGORIES),
19
+ ...Object.keys(TECHNICAL_CATEGORIES)
20
+ ];
21
+ export const familyOf = (category)=>category in BUSINESS_CATEGORIES ? 'business' : 'technical';
22
+ /** The status a category answers with unless a host overrides its tag. */ export const defaultStatus = (category)=>category in BUSINESS_CATEGORIES ? BUSINESS_CATEGORIES[category] : TECHNICAL_CATEGORIES[category];
23
+ /**
24
+ * Members of the problem body that a failure's own fields must not shadow,
25
+ * because the decoder reads them back as the envelope rather than as fields.
26
+ */ export const RESERVED_FIELDS = new Set([
27
+ 'type',
28
+ 'title',
29
+ 'status',
30
+ 'detail',
31
+ 'instance',
32
+ 'code',
33
+ 'category',
34
+ 'family',
35
+ 'traceId',
36
+ 'retryAfter'
37
+ ]);
38
+
39
+ //# sourceMappingURL=failure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/failure/failure.ts"],"sourcesContent":["import type { Schema } from 'effect';\n\nimport type { EntifixError } from '../base-entities/entifix-error/entifix-error.js';\n\n/**\n * The two families every failure belongs to\n * ([ADR 0013](../../../../../docs/adr/0013-failures-are-typed-values-decided-at-the-shell.md)).\n *\n * - `business` — an answer. The request was understood and the answer is no.\n * Never retried, never trips a breaker.\n * - `technical` — a non-answer. Something stopped the request being answered,\n * and the layer directly above may retry it.\n */\nexport type FailureFamily = 'business' | 'technical';\n\n/** The business categories, each with the status it answers by default. */\nexport const BUSINESS_CATEGORIES = {\n invalid: 400,\n unauthenticated: 401,\n forbidden: 403,\n notFound: 404,\n conflict: 409,\n declined: 422,\n} as const;\n\n/** The technical categories, each with the status it answers by default. */\nexport const TECHNICAL_CATEGORIES = {\n contention: 409,\n exhausted: 429,\n unavailable: 503,\n timeout: 504,\n protocol: 502,\n internal: 500,\n} as const;\n\nexport type BusinessCategory = keyof typeof BUSINESS_CATEGORIES;\nexport type TechnicalCategory = keyof typeof TECHNICAL_CATEGORIES;\n\n/**\n * The closed set. Every layer branches on it — the shell's status and log\n * tables, the bus's poison rule, the client's inline-versus-toast choice — so\n * it stays small enough for each of them to be exhaustive over. Tags stay open.\n */\nexport type FailureCategory = BusinessCategory | TechnicalCategory;\n\nexport type FamilyOf<C extends FailureCategory> = C extends BusinessCategory\n ? 'business'\n : 'technical';\n\nexport const FAILURE_CATEGORIES: readonly FailureCategory[] = [\n ...(Object.keys(BUSINESS_CATEGORIES) as BusinessCategory[]),\n ...(Object.keys(TECHNICAL_CATEGORIES) as TechnicalCategory[]),\n];\n\nexport const familyOf = <C extends FailureCategory>(category: C): FamilyOf<C> =>\n (category in BUSINESS_CATEGORIES ? 'business' : 'technical') as FamilyOf<C>;\n\n/** The status a category answers with unless a host overrides its tag. */\nexport const defaultStatus = (category: FailureCategory): number =>\n category in BUSINESS_CATEGORIES\n ? BUSINESS_CATEGORIES[category as BusinessCategory]\n : TECHNICAL_CATEGORIES[category as TechnicalCategory];\n\n/**\n * What every failure carries beyond its own fields. `code` is the permanent,\n * wire-visible key a client translates; `category` and `family` are what every\n * layer above decides by.\n */\nexport interface FailureFacts<\n Code extends string = string,\n C extends FailureCategory = FailureCategory,\n> {\n readonly code: Code;\n readonly category: C;\n readonly family: FamilyOf<C>;\n}\n\n/**\n * Any failure the framework or a host raises: a `Schema.TaggedError` carrying\n * its code, category and family.\n */\nexport interface EntifixFailure<\n Tag extends string = string,\n Code extends string = string,\n C extends FailureCategory = FailureCategory,\n> extends FailureFacts<Code, C> {\n readonly _tag: Tag;\n readonly message: string;\n}\n\n/** A failure class, as the registry and the problem codec hold it. */\nexport interface FailureClass {\n new (...args: never[]): EntifixFailure;\n readonly identifier: string;\n readonly fields: Schema.Struct.Fields;\n}\n\n/**\n * Members of the problem body that a failure's own fields must not shadow,\n * because the decoder reads them back as the envelope rather than as fields.\n */\nexport const RESERVED_FIELDS: ReadonlySet<string> = new Set([\n 'type',\n 'title',\n 'status',\n 'detail',\n 'instance',\n 'code',\n 'category',\n 'family',\n 'traceId',\n 'retryAfter',\n]);\n\n/**\n * What a port or a hook fails with while the framework moves from the\n * `EntifixError` class tree to typed failures: either one. Deleted with the\n * class tree, in the release that removes it.\n */\nexport type TransitionalFailure = EntifixError | EntifixFailure;\n"],"names":["BUSINESS_CATEGORIES","invalid","unauthenticated","forbidden","notFound","conflict","declined","TECHNICAL_CATEGORIES","contention","exhausted","unavailable","timeout","protocol","internal","FAILURE_CATEGORIES","Object","keys","familyOf","category","defaultStatus","RESERVED_FIELDS","Set"],"mappings":"AAeA,yEAAyE,GACzE,OAAO,MAAMA,sBAAsB;IACjCC,SAAS;IACTC,iBAAiB;IACjBC,WAAW;IACXC,UAAU;IACVC,UAAU;IACVC,UAAU;AACZ,EAAW;AAEX,0EAA0E,GAC1E,OAAO,MAAMC,uBAAuB;IAClCC,YAAY;IACZC,WAAW;IACXC,aAAa;IACbC,SAAS;IACTC,UAAU;IACVC,UAAU;AACZ,EAAW;AAgBX,OAAO,MAAMC,qBAAiD;OACxDC,OAAOC,IAAI,CAAChB;OACZe,OAAOC,IAAI,CAACT;CACjB,CAAC;AAEF,OAAO,MAAMU,WAAW,CAA4BC,WACjDA,YAAYlB,sBAAsB,aAAa,YAA4B;AAE9E,wEAAwE,GACxE,OAAO,MAAMmB,gBAAgB,CAACD,WAC5BA,YAAYlB,sBACRA,mBAAmB,CAACkB,SAA6B,GACjDX,oBAAoB,CAACW,SAA8B,CAAC;AAoC1D;;;CAGC,GACD,OAAO,MAAME,kBAAuC,IAAIC,IAAI;IAC1D;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD,EAAE"}
@@ -0,0 +1,141 @@
1
+ import { Schema } from 'effect';
2
+ /**
3
+ * The failures every host shares — the ones a framework route, an adapter or a
4
+ * transport raises without knowing the domain it serves. A domain names its
5
+ * own refusals beside these, through the same definers.
6
+ *
7
+ * Each code is permanent: a host's message catalog keys on it.
8
+ */
9
+ /** One field a request got wrong. `pointer` locates it, `code` names the rule. */
10
+ export declare const FieldProblem: Schema.Struct<{
11
+ readonly pointer: Schema.String;
12
+ readonly detail: Schema.String;
13
+ readonly code: Schema.String;
14
+ }>;
15
+ export type FieldProblem = typeof FieldProblem.Type;
16
+ declare const Invalid_base: Schema.Class<Invalid, Schema.TaggedStruct<"Invalid", {
17
+ readonly errors: Schema.$Array<Schema.Struct<{
18
+ readonly pointer: Schema.String;
19
+ readonly detail: Schema.String;
20
+ readonly code: Schema.String;
21
+ }>>;
22
+ }>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<"invalid", "invalid">>;
23
+ /** The request breaks rules on its own; every broken one is listed. */
24
+ export declare class Invalid extends Invalid_base {
25
+ }
26
+ declare const InvalidQuery_base: Schema.Class<InvalidQuery, Schema.TaggedStruct<"InvalidQuery", {
27
+ readonly reason: Schema.String;
28
+ }>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<"invalidQuery", "invalid">>;
29
+ /** A list, filter or sort the query language cannot accept. */
30
+ export declare class InvalidQuery extends InvalidQuery_base {
31
+ }
32
+ declare const InvalidEnvelope_base: Schema.Class<InvalidEnvelope, Schema.TaggedStruct<"InvalidEnvelope", {
33
+ readonly reason: Schema.String;
34
+ }>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<"invalidEnvelope", "invalid">>;
35
+ /**
36
+ * A payload that is not the envelope its reader expected. The sender's fault —
37
+ * a `400` at an HTTP edge and poison on a bus, where redelivering the same
38
+ * bytes produces the same refusal.
39
+ */
40
+ export declare class InvalidEnvelope extends InvalidEnvelope_base {
41
+ }
42
+ declare const Unauthenticated_base: Schema.Class<Unauthenticated, Schema.TaggedStruct<"Unauthenticated", Record<never, never>>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<"unauthenticated", "unauthenticated">>;
43
+ /** No credential, or one that does not verify. */
44
+ export declare class Unauthenticated extends Unauthenticated_base {
45
+ }
46
+ declare const Forbidden_base: Schema.Class<Forbidden, Schema.TaggedStruct<"Forbidden", {
47
+ readonly permission: Schema.optionalKey<Schema.String>;
48
+ }>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<"forbidden", "forbidden">>;
49
+ /** A verified caller without the grant. */
50
+ export declare class Forbidden extends Forbidden_base {
51
+ }
52
+ declare const NotFound_base: Schema.Class<NotFound, Schema.TaggedStruct<"NotFound", {
53
+ readonly entity: Schema.optionalKey<Schema.String>;
54
+ }>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<"notFound", "notFound">>;
55
+ /** The addressed record does not exist. */
56
+ export declare class NotFound extends NotFound_base {
57
+ }
58
+ declare const DuplicateKey_base: Schema.Class<DuplicateKey, Schema.TaggedStruct<"DuplicateKey", {
59
+ readonly key: Schema.optionalKey<Schema.String>;
60
+ }>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<"duplicateKey", "conflict">>;
61
+ /** A write that would duplicate a value the store declares unique. */
62
+ export declare class DuplicateKey extends DuplicateKey_base {
63
+ }
64
+ declare const Declined_base: Schema.Class<Declined, Schema.TaggedStruct<"Declined", {
65
+ readonly reason: Schema.optionalKey<Schema.String>;
66
+ }>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<"declined", "declined">>;
67
+ /** A third party, or a rule over other records, said no. */
68
+ export declare class Declined extends Declined_base {
69
+ }
70
+ declare const Contention_base: Schema.Class<Contention, Schema.TaggedStruct<"Contention", Record<never, never>>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<"contention", "contention">>;
71
+ /** Lost a race that a retry can win — a claim taken, a transaction aborted. */
72
+ export declare class Contention extends Contention_base {
73
+ }
74
+ declare const Overloaded_base: Schema.Class<Overloaded, Schema.TaggedStruct<"Overloaded", {
75
+ readonly retryAfterSeconds: Schema.optionalKey<Schema.Number>;
76
+ }>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<"overloaded", "exhausted">>;
77
+ /** The dependency asked for less load. Stops retries wherever it appears. */
78
+ export declare class Overloaded extends Overloaded_base {
79
+ }
80
+ declare const Unavailable_base: Schema.Class<Unavailable, Schema.TaggedStruct<"Unavailable", {
81
+ readonly dependency: Schema.optionalKey<Schema.String>;
82
+ }>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<"unavailable", "unavailable">>;
83
+ /** A dependency could not be reached. */
84
+ export declare class Unavailable extends Unavailable_base {
85
+ }
86
+ declare const UpstreamUnavailable_base: Schema.Class<UpstreamUnavailable, Schema.TaggedStruct<"UpstreamUnavailable", {
87
+ readonly upstream: Schema.optionalKey<Schema.String>;
88
+ }>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<"upstreamUnavailable", "unavailable">>;
89
+ /** The service a proxy forwards to could not be reached. */
90
+ export declare class UpstreamUnavailable extends UpstreamUnavailable_base {
91
+ }
92
+ declare const Timeout_base: Schema.Class<Timeout, Schema.TaggedStruct<"Timeout", {
93
+ readonly dependency: Schema.optionalKey<Schema.String>;
94
+ }>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<"timeout", "timeout">>;
95
+ /** A dependency did not answer in time. */
96
+ export declare class Timeout extends Timeout_base {
97
+ }
98
+ declare const ProtocolFailure_base: Schema.Class<ProtocolFailure, Schema.TaggedStruct<"ProtocolFailure", {
99
+ readonly reason: Schema.String;
100
+ readonly upstreamStatus: Schema.optionalKey<Schema.Number>;
101
+ }>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<"protocol", "protocol">>;
102
+ /**
103
+ * A peer answered something that does not decode — a body that is not a
104
+ * problem, a code nothing registered, a document that does not match its
105
+ * schema.
106
+ */
107
+ export declare class ProtocolFailure extends ProtocolFailure_base {
108
+ }
109
+ declare const Internal_base: Schema.Class<Internal, Schema.TaggedStruct<"Internal", Record<never, never>>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<"internal", "internal">>;
110
+ /** A bug, surfaced as a value. Never carries the bug's text onto a wire. */
111
+ export declare class Internal extends Internal_base {
112
+ }
113
+ declare const IdempotencyKeyMissing_base: Schema.Class<IdempotencyKeyMissing, Schema.TaggedStruct<"IdempotencyKeyMissing", Record<never, never>>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<"idempotencyKeyMissing", "invalid">>;
114
+ /** An idempotent route was called without its `Idempotency-Key`. */
115
+ export declare class IdempotencyKeyMissing extends IdempotencyKeyMissing_base {
116
+ }
117
+ declare const IdempotencyKeyReused_base: Schema.Class<IdempotencyKeyReused, Schema.TaggedStruct<"IdempotencyKeyReused", Record<never, never>>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<"idempotencyKeyReused", "declined">>;
118
+ /** One `Idempotency-Key` arrived with two different payloads. */
119
+ export declare class IdempotencyKeyReused extends IdempotencyKeyReused_base {
120
+ }
121
+ declare const IdempotencyKeyInFlight_base: Schema.Class<IdempotencyKeyInFlight, Schema.TaggedStruct<"IdempotencyKeyInFlight", Record<never, never>>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<"idempotencyKeyInFlight", "contention">>;
122
+ /** The first request under this `Idempotency-Key` has not finished. */
123
+ export declare class IdempotencyKeyInFlight extends IdempotencyKeyInFlight_base {
124
+ }
125
+ /**
126
+ * What a store adapter fails with — a datastore, a cache, a bus: the value it
127
+ * guarded already exists, someone else got there first, it could not be
128
+ * reached, it did not answer in time, or it answered something unreadable.
129
+ * A port that talks to storage names this as its failure.
130
+ */
131
+ export type StoreFailure = DuplicateKey | Contention | Unavailable | Timeout | ProtocolFailure;
132
+ /**
133
+ * The technical part of {@link StoreFailure}: the store failing to answer, as
134
+ * opposed to answering no. A unit of work rolls back and surfaces these; a
135
+ * business failure — a `DuplicateKey` included — is its abort.
136
+ */
137
+ export type StoreFault = Exclude<StoreFailure, DuplicateKey>;
138
+ /** Whether `value` is a {@link StoreFault}, read by tag. */
139
+ export declare const isStoreFault: (value: unknown) => value is StoreFault;
140
+ export {};
141
+ //# sourceMappingURL=generic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generic.d.ts","sourceRoot":"","sources":["../../src/failure/generic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC;;;;;;GAMG;AAEH,kFAAkF;AAClF,eAAO,MAAM,YAAY;;;;EAIvB,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,OAAO,YAAY,CAAC,IAAI,CAAC;;;;;;;;AAEpD,uEAAuE;AACvE,qBAAa,OAAQ,SAAQ,YAI5B;CAAG;;;;AAEJ,+DAA+D;AAC/D,qBAAa,YAAa,SAAQ,iBAKjC;CAAG;;;;AAEJ;;;;GAIG;AACH,qBAAa,eAAgB,SAAQ,oBAOpC;CAAG;;AAEJ,kDAAkD;AAClD,qBAAa,eAAgB,SAAQ,oBAEqB;CAAG;;;;AAE7D,2CAA2C;AAC3C,qBAAa,SAAU,SAAQ,cAM9B;CAAG;;;;AAEJ,2CAA2C;AAC3C,qBAAa,QAAS,SAAQ,aAI7B;CAAG;;;;AAEJ,sEAAsE;AACtE,qBAAa,YAAa,SAAQ,iBAIjC;CAAG;;;;AAEJ,4DAA4D;AAC5D,qBAAa,QAAS,SAAQ,aAK7B;CAAG;;AAEJ,+EAA+E;AAC/E,qBAAa,UAAW,SAAQ,eAG/B;CAAG;;;;AAEJ,6EAA6E;AAC7E,qBAAa,UAAW,SAAQ,eAI/B;CAAG;;;;AAEJ,yCAAyC;AACzC,qBAAa,WAAY,SAAQ,gBAIhC;CAAG;;;;AAEJ,4DAA4D;AAC5D,qBAAa,mBAAoB,SAAQ,wBAIvC;CAAG;;;;AAEL,2CAA2C;AAC3C,qBAAa,OAAQ,SAAQ,YAI5B;CAAG;;;;;AAEJ;;;;GAIG;AACH,qBAAa,eAAgB,SAAQ,oBAUpC;CAAG;;AAEJ,4EAA4E;AAC5E,qBAAa,QAAS,SAAQ,aAG7B;CAAG;;AAEJ,oEAAoE;AACpE,qBAAa,qBAAsB,SAAQ,0BAEiC;CAAG;;AAE/E,iEAAiE;AACjE,qBAAa,oBAAqB,SAAQ,yBAE+B;CAAG;;AAE5E,uEAAuE;AACvE,qBAAa,sBAAuB,SAAQ,2BAK3C;CAAG;AAEJ;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GACtB,YAAY,GAAG,UAAU,GAAG,WAAW,GAAG,OAAO,GAAG,eAAe,CAAC;AAEtE;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;AAS7D,4DAA4D;AAC5D,eAAO,MAAM,YAAY,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,UAGsB,CAAC"}