@entifix/core 0.9.0 → 0.10.1

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
@@ -0,0 +1,101 @@
1
+ import { Schema } from 'effect';
2
+ import { defineFailure } from './define.js';
3
+ /**
4
+ * The failures every host shares — the ones a framework route, an adapter or a
5
+ * transport raises without knowing the domain it serves. A domain names its
6
+ * own refusals beside these, through the same definers.
7
+ *
8
+ * Each code is permanent: a host's message catalog keys on it.
9
+ */ /** One field a request got wrong. `pointer` locates it, `code` names the rule. */ export const FieldProblem = Schema.Struct({
10
+ pointer: Schema.String,
11
+ detail: Schema.String,
12
+ code: Schema.String
13
+ });
14
+ /** The request breaks rules on its own; every broken one is listed. */ export class Invalid extends defineFailure('invalid')()('Invalid', 'invalid', {
15
+ errors: Schema.Array(FieldProblem)
16
+ }) {
17
+ }
18
+ /** A list, filter or sort the query language cannot accept. */ export class InvalidQuery extends defineFailure('invalid')()('InvalidQuery', 'invalidQuery', {
19
+ reason: Schema.String
20
+ }, {
21
+ message: ({ reason })=>reason
22
+ }) {
23
+ }
24
+ /**
25
+ * A payload that is not the envelope its reader expected. The sender's fault —
26
+ * a `400` at an HTTP edge and poison on a bus, where redelivering the same
27
+ * bytes produces the same refusal.
28
+ */ export class InvalidEnvelope extends defineFailure('invalid')()('InvalidEnvelope', 'invalidEnvelope', {
29
+ reason: Schema.String
30
+ }, {
31
+ message: ({ reason })=>reason
32
+ }) {
33
+ }
34
+ /** No credential, or one that does not verify. */ export class Unauthenticated extends defineFailure('unauthenticated')()('Unauthenticated', 'unauthenticated') {
35
+ }
36
+ /** A verified caller without the grant. */ export class Forbidden extends defineFailure('forbidden')()('Forbidden', 'forbidden', // Which grant was missing: diagnostic, not a leak — the caller already
37
+ // knows what it asked to do.
38
+ {
39
+ permission: Schema.optionalKey(Schema.String)
40
+ }) {
41
+ }
42
+ /** The addressed record does not exist. */ export class NotFound extends defineFailure('notFound')()('NotFound', 'notFound', {
43
+ entity: Schema.optionalKey(Schema.String)
44
+ }) {
45
+ }
46
+ /** A write that would duplicate a value the store declares unique. */ export class DuplicateKey extends defineFailure('conflict')()('DuplicateKey', 'duplicateKey', {
47
+ key: Schema.optionalKey(Schema.String)
48
+ }) {
49
+ }
50
+ /** A third party, or a rule over other records, said no. */ export class Declined extends defineFailure('declined')()('Declined', 'declined', {
51
+ reason: Schema.optionalKey(Schema.String)
52
+ }, {
53
+ message: ({ reason })=>reason != null ? reason : ''
54
+ }) {
55
+ }
56
+ /** Lost a race that a retry can win — a claim taken, a transaction aborted. */ export class Contention extends defineFailure('contention')()('Contention', 'contention') {
57
+ }
58
+ /** The dependency asked for less load. Stops retries wherever it appears. */ export class Overloaded extends defineFailure('exhausted')()('Overloaded', 'overloaded', {
59
+ retryAfterSeconds: Schema.optionalKey(Schema.Number)
60
+ }) {
61
+ }
62
+ /** A dependency could not be reached. */ export class Unavailable extends defineFailure('unavailable')()('Unavailable', 'unavailable', {
63
+ dependency: Schema.optionalKey(Schema.String)
64
+ }) {
65
+ }
66
+ /** The service a proxy forwards to could not be reached. */ export class UpstreamUnavailable extends defineFailure('unavailable')()('UpstreamUnavailable', 'upstreamUnavailable', {
67
+ upstream: Schema.optionalKey(Schema.String)
68
+ }) {
69
+ }
70
+ /** A dependency did not answer in time. */ export class Timeout extends defineFailure('timeout')()('Timeout', 'timeout', {
71
+ dependency: Schema.optionalKey(Schema.String)
72
+ }) {
73
+ }
74
+ /**
75
+ * A peer answered something that does not decode — a body that is not a
76
+ * problem, a code nothing registered, a document that does not match its
77
+ * schema.
78
+ */ export class ProtocolFailure extends defineFailure('protocol')()('ProtocolFailure', 'protocol', {
79
+ reason: Schema.String,
80
+ upstreamStatus: Schema.optionalKey(Schema.Number)
81
+ }, {
82
+ message: ({ reason })=>reason
83
+ }) {
84
+ }
85
+ /** A bug, surfaced as a value. Never carries the bug's text onto a wire. */ export class Internal extends defineFailure('internal')()('Internal', 'internal') {
86
+ }
87
+ /** An idempotent route was called without its `Idempotency-Key`. */ export class IdempotencyKeyMissing extends defineFailure('invalid')()('IdempotencyKeyMissing', 'idempotencyKeyMissing') {
88
+ }
89
+ /** One `Idempotency-Key` arrived with two different payloads. */ export class IdempotencyKeyReused extends defineFailure('declined')()('IdempotencyKeyReused', 'idempotencyKeyReused') {
90
+ }
91
+ /** The first request under this `Idempotency-Key` has not finished. */ export class IdempotencyKeyInFlight extends defineFailure('contention')()('IdempotencyKeyInFlight', 'idempotencyKeyInFlight') {
92
+ }
93
+ const STORE_FAULT_TAGS = new Set([
94
+ 'Contention',
95
+ 'Unavailable',
96
+ 'Timeout',
97
+ 'ProtocolFailure'
98
+ ]);
99
+ /** Whether `value` is a {@link StoreFault}, read by tag. */ export const isStoreFault = (value)=>typeof value === 'object' && value !== null && STORE_FAULT_TAGS.has(value._tag);
100
+
101
+ //# sourceMappingURL=generic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/failure/generic.ts"],"sourcesContent":["import { Schema } from 'effect';\n\nimport { defineFailure } from './define.js';\n\n/**\n * The failures every host shares — the ones a framework route, an adapter or a\n * transport raises without knowing the domain it serves. A domain names its\n * own refusals beside these, through the same definers.\n *\n * Each code is permanent: a host's message catalog keys on it.\n */\n\n/** One field a request got wrong. `pointer` locates it, `code` names the rule. */\nexport const FieldProblem = Schema.Struct({\n pointer: Schema.String,\n detail: Schema.String,\n code: Schema.String,\n});\nexport type FieldProblem = typeof FieldProblem.Type;\n\n/** The request breaks rules on its own; every broken one is listed. */\nexport class Invalid extends defineFailure('invalid')<Invalid>()(\n 'Invalid',\n 'invalid',\n { errors: Schema.Array(FieldProblem) },\n) {}\n\n/** A list, filter or sort the query language cannot accept. */\nexport class InvalidQuery extends defineFailure('invalid')<InvalidQuery>()(\n 'InvalidQuery',\n 'invalidQuery',\n { reason: Schema.String },\n { message: ({ reason }) => reason },\n) {}\n\n/**\n * A payload that is not the envelope its reader expected. The sender's fault —\n * a `400` at an HTTP edge and poison on a bus, where redelivering the same\n * bytes produces the same refusal.\n */\nexport class InvalidEnvelope extends defineFailure(\n 'invalid',\n)<InvalidEnvelope>()(\n 'InvalidEnvelope',\n 'invalidEnvelope',\n { reason: Schema.String },\n { message: ({ reason }) => reason },\n) {}\n\n/** No credential, or one that does not verify. */\nexport class Unauthenticated extends defineFailure(\n 'unauthenticated',\n)<Unauthenticated>()('Unauthenticated', 'unauthenticated') {}\n\n/** A verified caller without the grant. */\nexport class Forbidden extends defineFailure('forbidden')<Forbidden>()(\n 'Forbidden',\n 'forbidden',\n // Which grant was missing: diagnostic, not a leak — the caller already\n // knows what it asked to do.\n { permission: Schema.optionalKey(Schema.String) },\n) {}\n\n/** The addressed record does not exist. */\nexport class NotFound extends defineFailure('notFound')<NotFound>()(\n 'NotFound',\n 'notFound',\n { entity: Schema.optionalKey(Schema.String) },\n) {}\n\n/** A write that would duplicate a value the store declares unique. */\nexport class DuplicateKey extends defineFailure('conflict')<DuplicateKey>()(\n 'DuplicateKey',\n 'duplicateKey',\n { key: Schema.optionalKey(Schema.String) },\n) {}\n\n/** A third party, or a rule over other records, said no. */\nexport class Declined extends defineFailure('declined')<Declined>()(\n 'Declined',\n 'declined',\n { reason: Schema.optionalKey(Schema.String) },\n { message: ({ reason }) => reason ?? '' },\n) {}\n\n/** Lost a race that a retry can win — a claim taken, a transaction aborted. */\nexport class Contention extends defineFailure('contention')<Contention>()(\n 'Contention',\n 'contention',\n) {}\n\n/** The dependency asked for less load. Stops retries wherever it appears. */\nexport class Overloaded extends defineFailure('exhausted')<Overloaded>()(\n 'Overloaded',\n 'overloaded',\n { retryAfterSeconds: Schema.optionalKey(Schema.Number) },\n) {}\n\n/** A dependency could not be reached. */\nexport class Unavailable extends defineFailure('unavailable')<Unavailable>()(\n 'Unavailable',\n 'unavailable',\n { dependency: Schema.optionalKey(Schema.String) },\n) {}\n\n/** The service a proxy forwards to could not be reached. */\nexport class UpstreamUnavailable extends defineFailure(\n 'unavailable',\n)<UpstreamUnavailable>()('UpstreamUnavailable', 'upstreamUnavailable', {\n upstream: Schema.optionalKey(Schema.String),\n}) {}\n\n/** A dependency did not answer in time. */\nexport class Timeout extends defineFailure('timeout')<Timeout>()(\n 'Timeout',\n 'timeout',\n { dependency: Schema.optionalKey(Schema.String) },\n) {}\n\n/**\n * A peer answered something that does not decode — a body that is not a\n * problem, a code nothing registered, a document that does not match its\n * schema.\n */\nexport class ProtocolFailure extends defineFailure(\n 'protocol',\n)<ProtocolFailure>()(\n 'ProtocolFailure',\n 'protocol',\n {\n reason: Schema.String,\n upstreamStatus: Schema.optionalKey(Schema.Number),\n },\n { message: ({ reason }) => reason },\n) {}\n\n/** A bug, surfaced as a value. Never carries the bug's text onto a wire. */\nexport class Internal extends defineFailure('internal')<Internal>()(\n 'Internal',\n 'internal',\n) {}\n\n/** An idempotent route was called without its `Idempotency-Key`. */\nexport class IdempotencyKeyMissing extends defineFailure(\n 'invalid',\n)<IdempotencyKeyMissing>()('IdempotencyKeyMissing', 'idempotencyKeyMissing') {}\n\n/** One `Idempotency-Key` arrived with two different payloads. */\nexport class IdempotencyKeyReused extends defineFailure(\n 'declined',\n)<IdempotencyKeyReused>()('IdempotencyKeyReused', 'idempotencyKeyReused') {}\n\n/** The first request under this `Idempotency-Key` has not finished. */\nexport class IdempotencyKeyInFlight extends defineFailure(\n 'contention',\n)<IdempotencyKeyInFlight>()(\n 'IdempotencyKeyInFlight',\n 'idempotencyKeyInFlight',\n) {}\n\n/**\n * What a store adapter fails with — a datastore, a cache, a bus: the value it\n * guarded already exists, someone else got there first, it could not be\n * reached, it did not answer in time, or it answered something unreadable.\n * A port that talks to storage names this as its failure.\n */\nexport type StoreFailure =\n DuplicateKey | Contention | Unavailable | Timeout | ProtocolFailure;\n\n/**\n * The technical part of {@link StoreFailure}: the store failing to answer, as\n * opposed to answering no. A unit of work rolls back and surfaces these; a\n * business failure — a `DuplicateKey` included — is its abort.\n */\nexport type StoreFault = Exclude<StoreFailure, DuplicateKey>;\n\nconst STORE_FAULT_TAGS: ReadonlySet<string> = new Set([\n 'Contention',\n 'Unavailable',\n 'Timeout',\n 'ProtocolFailure',\n]);\n\n/** Whether `value` is a {@link StoreFault}, read by tag. */\nexport const isStoreFault = (value: unknown): value is StoreFault =>\n typeof value === 'object' &&\n value !== null &&\n STORE_FAULT_TAGS.has((value as { readonly _tag?: unknown })._tag as string);\n"],"names":["Schema","defineFailure","FieldProblem","Struct","pointer","String","detail","code","Invalid","errors","Array","InvalidQuery","reason","message","InvalidEnvelope","Unauthenticated","Forbidden","permission","optionalKey","NotFound","entity","DuplicateKey","key","Declined","Contention","Overloaded","retryAfterSeconds","Number","Unavailable","dependency","UpstreamUnavailable","upstream","Timeout","ProtocolFailure","upstreamStatus","Internal","IdempotencyKeyMissing","IdempotencyKeyReused","IdempotencyKeyInFlight","STORE_FAULT_TAGS","Set","isStoreFault","value","has","_tag"],"mappings":"AAAA,SAASA,MAAM,QAAQ,SAAS;AAEhC,SAASC,aAAa,QAAQ,cAAc;AAE5C;;;;;;CAMC,GAED,gFAAgF,GAChF,OAAO,MAAMC,eAAeF,OAAOG,MAAM,CAAC;IACxCC,SAASJ,OAAOK,MAAM;IACtBC,QAAQN,OAAOK,MAAM;IACrBE,MAAMP,OAAOK,MAAM;AACrB,GAAG;AAGH,qEAAqE,GACrE,OAAO,MAAMG,gBAAgBP,cAAc,aACzC,WACA,WACA;IAAEQ,QAAQT,OAAOU,KAAK,CAACR;AAAc;AACpC;AAEH,6DAA6D,GAC7D,OAAO,MAAMS,qBAAqBV,cAAc,aAC9C,gBACA,gBACA;IAAEW,QAAQZ,OAAOK,MAAM;AAAC,GACxB;IAAEQ,SAAS,CAAC,EAAED,MAAM,EAAE,GAAKA;AAAO;AACjC;AAEH;;;;CAIC,GACD,OAAO,MAAME,wBAAwBb,cACnC,aAEA,mBACA,mBACA;IAAEW,QAAQZ,OAAOK,MAAM;AAAC,GACxB;IAAEQ,SAAS,CAAC,EAAED,MAAM,EAAE,GAAKA;AAAO;AACjC;AAEH,gDAAgD,GAChD,OAAO,MAAMG,wBAAwBd,cACnC,qBACmB,mBAAmB;AAAoB;AAE5D,yCAAyC,GACzC,OAAO,MAAMe,kBAAkBf,cAAc,eAC3C,aACA,aACA,uEAAuE;AACvE,6BAA6B;AAC7B;IAAEgB,YAAYjB,OAAOkB,WAAW,CAAClB,OAAOK,MAAM;AAAE;AAC/C;AAEH,yCAAyC,GACzC,OAAO,MAAMc,iBAAiBlB,cAAc,cAC1C,YACA,YACA;IAAEmB,QAAQpB,OAAOkB,WAAW,CAAClB,OAAOK,MAAM;AAAE;AAC3C;AAEH,oEAAoE,GACpE,OAAO,MAAMgB,qBAAqBpB,cAAc,cAC9C,gBACA,gBACA;IAAEqB,KAAKtB,OAAOkB,WAAW,CAAClB,OAAOK,MAAM;AAAE;AACxC;AAEH,0DAA0D,GAC1D,OAAO,MAAMkB,iBAAiBtB,cAAc,cAC1C,YACA,YACA;IAAEW,QAAQZ,OAAOkB,WAAW,CAAClB,OAAOK,MAAM;AAAE,GAC5C;IAAEQ,SAAS,CAAC,EAAED,MAAM,EAAE,GAAKA,iBAAAA,SAAU;AAAG;AACvC;AAEH,6EAA6E,GAC7E,OAAO,MAAMY,mBAAmBvB,cAAc,gBAC5C,cACA;AACC;AAEH,2EAA2E,GAC3E,OAAO,MAAMwB,mBAAmBxB,cAAc,eAC5C,cACA,cACA;IAAEyB,mBAAmB1B,OAAOkB,WAAW,CAAClB,OAAO2B,MAAM;AAAE;AACtD;AAEH,uCAAuC,GACvC,OAAO,MAAMC,oBAAoB3B,cAAc,iBAC7C,eACA,eACA;IAAE4B,YAAY7B,OAAOkB,WAAW,CAAClB,OAAOK,MAAM;AAAE;AAC/C;AAEH,0DAA0D,GAC1D,OAAO,MAAMyB,4BAA4B7B,cACvC,iBACuB,uBAAuB,uBAAuB;IACrE8B,UAAU/B,OAAOkB,WAAW,CAAClB,OAAOK,MAAM;AAC5C;AAAI;AAEJ,yCAAyC,GACzC,OAAO,MAAM2B,gBAAgB/B,cAAc,aACzC,WACA,WACA;IAAE4B,YAAY7B,OAAOkB,WAAW,CAAClB,OAAOK,MAAM;AAAE;AAC/C;AAEH;;;;CAIC,GACD,OAAO,MAAM4B,wBAAwBhC,cACnC,cAEA,mBACA,YACA;IACEW,QAAQZ,OAAOK,MAAM;IACrB6B,gBAAgBlC,OAAOkB,WAAW,CAAClB,OAAO2B,MAAM;AAClD,GACA;IAAEd,SAAS,CAAC,EAAED,MAAM,EAAE,GAAKA;AAAO;AACjC;AAEH,0EAA0E,GAC1E,OAAO,MAAMuB,iBAAiBlC,cAAc,cAC1C,YACA;AACC;AAEH,kEAAkE,GAClE,OAAO,MAAMmC,8BAA8BnC,cACzC,aACyB,yBAAyB;AAA0B;AAE9E,+DAA+D,GAC/D,OAAO,MAAMoC,6BAA6BpC,cACxC,cACwB,wBAAwB;AAAyB;AAE3E,qEAAqE,GACrE,OAAO,MAAMqC,+BAA+BrC,cAC1C,gBAEA,0BACA;AACC;AAkBH,MAAMsC,mBAAwC,IAAIC,IAAI;IACpD;IACA;IACA;IACA;CACD;AAED,0DAA0D,GAC1D,OAAO,MAAMC,eAAe,CAACC,QAC3B,OAAOA,UAAU,YACjBA,UAAU,QACVH,iBAAiBI,GAAG,CAAC,AAACD,MAAsCE,IAAI,EAAY"}
@@ -0,0 +1,50 @@
1
+ export * from './failure.js';
2
+ export * from './generic.js';
3
+ export * from './predicates.js';
4
+ export * from './problem.js';
5
+ export * from './registry.js';
6
+ /**
7
+ * Everything a host needs to define and match failures, under one name
8
+ * ([ADR 0013](../../../../../docs/adr/0013-failures-are-typed-values-decided-at-the-shell.md)).
9
+ *
10
+ * ```ts
11
+ * class DuplicateSlug extends Failure.conflict<DuplicateSlug>()(
12
+ * 'DuplicateSlug',
13
+ * 'duplicateSlug',
14
+ * { slug: Schema.String },
15
+ * ) {}
16
+ *
17
+ * effect.pipe(Effect.catchIf(Failure.isCategory('conflict'), …))
18
+ * ```
19
+ */
20
+ export declare const Failure: {
21
+ readonly invalid: <Self = never>() => <const Tag extends string, const Code extends string, const Fields extends import("effect/Schema").Struct.Fields = Record<never, never>>(tag: Tag, code: Code, fields?: Fields, options?: import("./define.js").FailureOptions<import("effect/Schema").Struct.Type<Fields>>) => [Self] extends [never] ? "Missing `Self` generic - use `class Self extends Schema.TaggedError<Self>(...)`" : import("effect/Schema").Class<Self, import("effect/Schema").TaggedStruct<Tag, Fields>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<Code, "invalid">>;
22
+ readonly unauthenticated: <Self = never>() => <const Tag extends string, const Code extends string, const Fields extends import("effect/Schema").Struct.Fields = Record<never, never>>(tag: Tag, code: Code, fields?: Fields, options?: import("./define.js").FailureOptions<import("effect/Schema").Struct.Type<Fields>>) => [Self] extends [never] ? "Missing `Self` generic - use `class Self extends Schema.TaggedError<Self>(...)`" : import("effect/Schema").Class<Self, import("effect/Schema").TaggedStruct<Tag, Fields>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<Code, "unauthenticated">>;
23
+ readonly forbidden: <Self = never>() => <const Tag extends string, const Code extends string, const Fields extends import("effect/Schema").Struct.Fields = Record<never, never>>(tag: Tag, code: Code, fields?: Fields, options?: import("./define.js").FailureOptions<import("effect/Schema").Struct.Type<Fields>>) => [Self] extends [never] ? "Missing `Self` generic - use `class Self extends Schema.TaggedError<Self>(...)`" : import("effect/Schema").Class<Self, import("effect/Schema").TaggedStruct<Tag, Fields>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<Code, "forbidden">>;
24
+ readonly notFound: <Self = never>() => <const Tag extends string, const Code extends string, const Fields extends import("effect/Schema").Struct.Fields = Record<never, never>>(tag: Tag, code: Code, fields?: Fields, options?: import("./define.js").FailureOptions<import("effect/Schema").Struct.Type<Fields>>) => [Self] extends [never] ? "Missing `Self` generic - use `class Self extends Schema.TaggedError<Self>(...)`" : import("effect/Schema").Class<Self, import("effect/Schema").TaggedStruct<Tag, Fields>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<Code, "notFound">>;
25
+ readonly conflict: <Self = never>() => <const Tag extends string, const Code extends string, const Fields extends import("effect/Schema").Struct.Fields = Record<never, never>>(tag: Tag, code: Code, fields?: Fields, options?: import("./define.js").FailureOptions<import("effect/Schema").Struct.Type<Fields>>) => [Self] extends [never] ? "Missing `Self` generic - use `class Self extends Schema.TaggedError<Self>(...)`" : import("effect/Schema").Class<Self, import("effect/Schema").TaggedStruct<Tag, Fields>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<Code, "conflict">>;
26
+ readonly declined: <Self = never>() => <const Tag extends string, const Code extends string, const Fields extends import("effect/Schema").Struct.Fields = Record<never, never>>(tag: Tag, code: Code, fields?: Fields, options?: import("./define.js").FailureOptions<import("effect/Schema").Struct.Type<Fields>>) => [Self] extends [never] ? "Missing `Self` generic - use `class Self extends Schema.TaggedError<Self>(...)`" : import("effect/Schema").Class<Self, import("effect/Schema").TaggedStruct<Tag, Fields>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<Code, "declined">>;
27
+ readonly contention: <Self = never>() => <const Tag extends string, const Code extends string, const Fields extends import("effect/Schema").Struct.Fields = Record<never, never>>(tag: Tag, code: Code, fields?: Fields, options?: import("./define.js").FailureOptions<import("effect/Schema").Struct.Type<Fields>>) => [Self] extends [never] ? "Missing `Self` generic - use `class Self extends Schema.TaggedError<Self>(...)`" : import("effect/Schema").Class<Self, import("effect/Schema").TaggedStruct<Tag, Fields>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<Code, "contention">>;
28
+ readonly exhausted: <Self = never>() => <const Tag extends string, const Code extends string, const Fields extends import("effect/Schema").Struct.Fields = Record<never, never>>(tag: Tag, code: Code, fields?: Fields, options?: import("./define.js").FailureOptions<import("effect/Schema").Struct.Type<Fields>>) => [Self] extends [never] ? "Missing `Self` generic - use `class Self extends Schema.TaggedError<Self>(...)`" : import("effect/Schema").Class<Self, import("effect/Schema").TaggedStruct<Tag, Fields>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<Code, "exhausted">>;
29
+ readonly unavailable: <Self = never>() => <const Tag extends string, const Code extends string, const Fields extends import("effect/Schema").Struct.Fields = Record<never, never>>(tag: Tag, code: Code, fields?: Fields, options?: import("./define.js").FailureOptions<import("effect/Schema").Struct.Type<Fields>>) => [Self] extends [never] ? "Missing `Self` generic - use `class Self extends Schema.TaggedError<Self>(...)`" : import("effect/Schema").Class<Self, import("effect/Schema").TaggedStruct<Tag, Fields>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<Code, "unavailable">>;
30
+ readonly timeout: <Self = never>() => <const Tag extends string, const Code extends string, const Fields extends import("effect/Schema").Struct.Fields = Record<never, never>>(tag: Tag, code: Code, fields?: Fields, options?: import("./define.js").FailureOptions<import("effect/Schema").Struct.Type<Fields>>) => [Self] extends [never] ? "Missing `Self` generic - use `class Self extends Schema.TaggedError<Self>(...)`" : import("effect/Schema").Class<Self, import("effect/Schema").TaggedStruct<Tag, Fields>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<Code, "timeout">>;
31
+ readonly protocol: <Self = never>() => <const Tag extends string, const Code extends string, const Fields extends import("effect/Schema").Struct.Fields = Record<never, never>>(tag: Tag, code: Code, fields?: Fields, options?: import("./define.js").FailureOptions<import("effect/Schema").Struct.Type<Fields>>) => [Self] extends [never] ? "Missing `Self` generic - use `class Self extends Schema.TaggedError<Self>(...)`" : import("effect/Schema").Class<Self, import("effect/Schema").TaggedStruct<Tag, Fields>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<Code, "protocol">>;
32
+ readonly internal: <Self = never>() => <const Tag extends string, const Code extends string, const Fields extends import("effect/Schema").Struct.Fields = Record<never, never>>(tag: Tag, code: Code, fields?: Fields, options?: import("./define.js").FailureOptions<import("effect/Schema").Struct.Type<Fields>>) => [Self] extends [never] ? "Missing `Self` generic - use `class Self extends Schema.TaggedError<Self>(...)`" : import("effect/Schema").Class<Self, import("effect/Schema").TaggedStruct<Tag, Fields>, import("effect/Cause").YieldableError & import("./failure.js").FailureFacts<Code, "internal">>;
33
+ readonly is: import("./predicates.js").FailureGuard<import("./failure.js").EntifixFailure<string, string, import("./failure.js").FailureCategory>>;
34
+ readonly isTag: <const Tag extends string>(tag: Tag) => import("./predicates.js").FailureGuard<{
35
+ readonly _tag: Tag;
36
+ }>;
37
+ readonly isCategory: <const C extends import("./failure.js").FailureCategory>(category: C) => import("./predicates.js").FailureGuard<{
38
+ readonly category: C;
39
+ }>;
40
+ readonly isFamily: <const F extends import("./failure.js").FailureFamily>(family: F) => import("./predicates.js").FailureGuard<{
41
+ readonly family: F;
42
+ }>;
43
+ readonly and: <A, B>(left: import("./predicates.js").FailureGuard<A>, right: import("./predicates.js").FailureGuard<B>) => import("./predicates.js").FailureGuard<A & B>;
44
+ readonly or: <A, B>(left: import("./predicates.js").FailureGuard<A>, right: import("./predicates.js").FailureGuard<B>) => import("./predicates.js").FailureGuard<A | B>;
45
+ readonly not: <S>(guard: import("./predicates.js").FailureGuard<S>) => <E>(value: E) => value is Exclude<E, S>;
46
+ readonly when: <Shape, R = never>(guard: import("./predicates.js").FailureGuard<Shape>, condition: (failure: Shape) => import("effect/Effect").Effect<boolean, never, R>) => import("./predicates.js").EffectfulFailurePredicate<Shape, R>;
47
+ readonly lookup: (code: string) => import("./registry.js").RegisteredFailure | undefined;
48
+ readonly registered: () => readonly import("./registry.js").RegisteredFailure[];
49
+ };
50
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/failure/index.ts"],"names":[],"mappings":"AAaA,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAE9B;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,OAAO;2CAwBqR,wBAA6B,EAAC,yBAA8B,EAAC,iFAAqE,EAAM,QAAa,EAAC,UAAe,EAAC,eAAoB,EAAC,2FAA6D;mDAAxP,wBAA6B,EAAC,yBAA8B,EAAC,iFAAqE,EAAM,QAAa,EAAC,UAAe,EAAC,eAAoB,EAAC,2FAA6D;6CAAxP,wBAA6B,EAAC,yBAA8B,EAAC,iFAAqE,EAAM,QAAa,EAAC,UAAe,EAAC,eAAoB,EAAC,2FAA6D;4CAAxP,wBAA6B,EAAC,yBAA8B,EAAC,iFAAqE,EAAM,QAAa,EAAC,UAAe,EAAC,eAAoB,EAAC,2FAA6D;4CAAxP,wBAA6B,EAAC,yBAA8B,EAAC,iFAAqE,EAAM,QAAa,EAAC,UAAe,EAAC,eAAoB,EAAC,2FAA6D;4CAAxP,wBAA6B,EAAC,yBAA8B,EAAC,iFAAqE,EAAM,QAAa,EAAC,UAAe,EAAC,eAAoB,EAAC,2FAA6D;8CAAxP,wBAA6B,EAAC,yBAA8B,EAAC,iFAAqE,EAAM,QAAa,EAAC,UAAe,EAAC,eAAoB,EAAC,2FAA6D;6CAAxP,wBAA6B,EAAC,yBAA8B,EAAC,iFAAqE,EAAM,QAAa,EAAC,UAAe,EAAC,eAAoB,EAAC,2FAA6D;+CAAxP,wBAA6B,EAAC,yBAA8B,EAAC,iFAAqE,EAAM,QAAa,EAAC,UAAe,EAAC,eAAoB,EAAC,2FAA6D;2CAAxP,wBAA6B,EAAC,yBAA8B,EAAC,iFAAqE,EAAM,QAAa,EAAC,UAAe,EAAC,eAAoB,EAAC,2FAA6D;4CAAxP,wBAA6B,EAAC,yBAA8B,EAAC,iFAAqE,EAAM,QAAa,EAAC,UAAe,EAAC,eAAoB,EAAC,2FAA6D;4CAAxP,wBAA6B,EAAC,yBAA8B,EAAC,iFAAqE,EAAM,QAAa,EAAC,UAAe,EAAC,eAAoB,EAAC,2FAA6D;;;;;;;;;;;;;4EAA89B,CAAC,EAAE,QAAQ;;;;CADhgD,CAAC"}
@@ -0,0 +1,47 @@
1
+ import { defineFailure } from './define.js';
2
+ import { and, isCategory, isFailure, isFamily, isTag, not, or, when } from './predicates.js';
3
+ import { lookupFailure, registeredFailures } from './registry.js';
4
+ export * from './failure.js';
5
+ export * from './generic.js';
6
+ export * from './predicates.js';
7
+ export * from './problem.js';
8
+ export * from './registry.js';
9
+ /**
10
+ * Everything a host needs to define and match failures, under one name
11
+ * ([ADR 0013](../../../../../docs/adr/0013-failures-are-typed-values-decided-at-the-shell.md)).
12
+ *
13
+ * ```ts
14
+ * class DuplicateSlug extends Failure.conflict<DuplicateSlug>()(
15
+ * 'DuplicateSlug',
16
+ * 'duplicateSlug',
17
+ * { slug: Schema.String },
18
+ * ) {}
19
+ *
20
+ * effect.pipe(Effect.catchIf(Failure.isCategory('conflict'), …))
21
+ * ```
22
+ */ export const Failure = {
23
+ invalid: defineFailure('invalid'),
24
+ unauthenticated: defineFailure('unauthenticated'),
25
+ forbidden: defineFailure('forbidden'),
26
+ notFound: defineFailure('notFound'),
27
+ conflict: defineFailure('conflict'),
28
+ declined: defineFailure('declined'),
29
+ contention: defineFailure('contention'),
30
+ exhausted: defineFailure('exhausted'),
31
+ unavailable: defineFailure('unavailable'),
32
+ timeout: defineFailure('timeout'),
33
+ protocol: defineFailure('protocol'),
34
+ internal: defineFailure('internal'),
35
+ is: isFailure,
36
+ isTag,
37
+ isCategory,
38
+ isFamily,
39
+ and,
40
+ or,
41
+ not,
42
+ when,
43
+ lookup: lookupFailure,
44
+ registered: registeredFailures
45
+ };
46
+
47
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/failure/index.ts"],"sourcesContent":["import { defineFailure } from './define.js';\nimport {\n and,\n isCategory,\n isFailure,\n isFamily,\n isTag,\n not,\n or,\n when,\n} from './predicates.js';\nimport { lookupFailure, registeredFailures } from './registry.js';\n\nexport * from './failure.js';\nexport * from './generic.js';\nexport * from './predicates.js';\nexport * from './problem.js';\nexport * from './registry.js';\n\n/**\n * Everything a host needs to define and match failures, under one name\n * ([ADR 0013](../../../../../docs/adr/0013-failures-are-typed-values-decided-at-the-shell.md)).\n *\n * ```ts\n * class DuplicateSlug extends Failure.conflict<DuplicateSlug>()(\n * 'DuplicateSlug',\n * 'duplicateSlug',\n * { slug: Schema.String },\n * ) {}\n *\n * effect.pipe(Effect.catchIf(Failure.isCategory('conflict'), …))\n * ```\n */\nexport const Failure = {\n invalid: defineFailure('invalid'),\n unauthenticated: defineFailure('unauthenticated'),\n forbidden: defineFailure('forbidden'),\n notFound: defineFailure('notFound'),\n conflict: defineFailure('conflict'),\n declined: defineFailure('declined'),\n contention: defineFailure('contention'),\n exhausted: defineFailure('exhausted'),\n unavailable: defineFailure('unavailable'),\n timeout: defineFailure('timeout'),\n protocol: defineFailure('protocol'),\n internal: defineFailure('internal'),\n is: isFailure,\n isTag,\n isCategory,\n isFamily,\n and,\n or,\n not,\n when,\n lookup: lookupFailure,\n registered: registeredFailures,\n} as const;\n"],"names":["defineFailure","and","isCategory","isFailure","isFamily","isTag","not","or","when","lookupFailure","registeredFailures","Failure","invalid","unauthenticated","forbidden","notFound","conflict","declined","contention","exhausted","unavailable","timeout","protocol","internal","is","lookup","registered"],"mappings":"AAAA,SAASA,aAAa,QAAQ,cAAc;AAC5C,SACEC,GAAG,EACHC,UAAU,EACVC,SAAS,EACTC,QAAQ,EACRC,KAAK,EACLC,GAAG,EACHC,EAAE,EACFC,IAAI,QACC,kBAAkB;AACzB,SAASC,aAAa,EAAEC,kBAAkB,QAAQ,gBAAgB;AAElE,cAAc,eAAe;AAC7B,cAAc,eAAe;AAC7B,cAAc,kBAAkB;AAChC,cAAc,eAAe;AAC7B,cAAc,gBAAgB;AAE9B;;;;;;;;;;;;;CAaC,GACD,OAAO,MAAMC,UAAU;IACrBC,SAASZ,cAAc;IACvBa,iBAAiBb,cAAc;IAC/Bc,WAAWd,cAAc;IACzBe,UAAUf,cAAc;IACxBgB,UAAUhB,cAAc;IACxBiB,UAAUjB,cAAc;IACxBkB,YAAYlB,cAAc;IAC1BmB,WAAWnB,cAAc;IACzBoB,aAAapB,cAAc;IAC3BqB,SAASrB,cAAc;IACvBsB,UAAUtB,cAAc;IACxBuB,UAAUvB,cAAc;IACxBwB,IAAIrB;IACJE;IACAH;IACAE;IACAH;IACAM;IACAD;IACAE;IACAiB,QAAQhB;IACRiB,YAAYhB;AACd,EAAW"}
@@ -0,0 +1,56 @@
1
+ import type { Effect } from 'effect';
2
+ import type { EntifixFailure, FailureCategory, FailureFamily } from './failure.js';
3
+ /**
4
+ * A guard over anything, naming the shape it admits.
5
+ *
6
+ * It is written over `unknown` rather than over a failure union on purpose:
7
+ * TypeScript narrows a union by a guard on a supertype by **filtering** its
8
+ * members, so `if (isCategory('conflict')(e))` leaves exactly the members of
9
+ * `E` whose `category` is `'conflict'` — the same as `Extract<E, Shape>` — and
10
+ * one predicate serves every union it is applied to.
11
+ *
12
+ * The check reads `_tag`, `category` and `family` and never the prototype, so a
13
+ * failure decoded off a wire or defined in a second copy of this module
14
+ * matches exactly as one constructed in place.
15
+ */
16
+ export type FailureGuard<Shape> = (value: unknown) => value is Shape;
17
+ /** Admits the failure whose `_tag` is `tag`. */
18
+ export declare const isTag: <const Tag extends string>(tag: Tag) => FailureGuard<{
19
+ readonly _tag: Tag;
20
+ }>;
21
+ /** Admits every failure in `category`. */
22
+ export declare const isCategory: <const C extends FailureCategory>(category: C) => FailureGuard<{
23
+ readonly category: C;
24
+ }>;
25
+ /** Admits every failure in `family`. */
26
+ export declare const isFamily: <const F extends FailureFamily>(family: F) => FailureGuard<{
27
+ readonly family: F;
28
+ }>;
29
+ /** Admits any `EntifixFailure`, of any category. */
30
+ export declare const isFailure: FailureGuard<EntifixFailure>;
31
+ /** Both guards admit it. */
32
+ export declare const and: <A, B>(left: FailureGuard<A>, right: FailureGuard<B>) => FailureGuard<A & B>;
33
+ /** Either guard admits it. */
34
+ export declare const or: <A, B>(left: FailureGuard<A>, right: FailureGuard<B>) => FailureGuard<A | B>;
35
+ /**
36
+ * The guard does not admit it.
37
+ *
38
+ * ⚠️ Generic over the union it is applied to, because "not this shape" has no
39
+ * shape of its own: `not(isFamily('business'))(e)` narrows `E` to
40
+ * `Exclude<E, { family: 'business' }>`. Applied with no union in view — as an
41
+ * argument to {@link and} or {@link or} — it admits correctly and narrows
42
+ * nothing, so keep it the outermost combinator.
43
+ */
44
+ export declare const not: <S>(guard: FailureGuard<S>) => <E>(value: E) => value is Exclude<E, S>;
45
+ /**
46
+ * A guard plus a condition that needs the request — a dial read from
47
+ * configuration, the caller's organization. The guard narrows; the condition
48
+ * decides, and it is an Effect because the context it reads is.
49
+ */
50
+ export interface EffectfulFailurePredicate<Shape, R = never> {
51
+ readonly guard: FailureGuard<Shape>;
52
+ readonly condition: (failure: Shape) => Effect.Effect<boolean, never, R>;
53
+ }
54
+ /** Pairs a guard with a condition read from the request's context. */
55
+ export declare const when: <Shape, R = never>(guard: FailureGuard<Shape>, condition: (failure: Shape) => Effect.Effect<boolean, never, R>) => EffectfulFailurePredicate<Shape, R>;
56
+ //# sourceMappingURL=predicates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"predicates.d.ts","sourceRoot":"","sources":["../../src/failure/predicates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAErC,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EACf,aAAa,EACd,MAAM,cAAc,CAAC;AAEtB;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,YAAY,CAAC,KAAK,IAAI,CAAC,KAAK,EAAE,OAAO,KAAK,KAAK,IAAI,KAAK,CAAC;AAOrE,gDAAgD;AAChD,eAAO,MAAM,KAAK,GACf,KAAK,CAAC,GAAG,SAAS,MAAM,EAAE,KAAK,GAAG,KAAG,YAAY,CAAC;IAAE,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAA;CAAE,CAE5C,CAAC;AAEhC,0CAA0C;AAC1C,eAAO,MAAM,UAAU,GACpB,KAAK,CAAC,CAAC,SAAS,eAAe,EAC9B,UAAU,CAAC,KACV,YAAY,CAAC;IAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAA;CAAE,CAEF,CAAC;AAEzC,wCAAwC;AACxC,eAAO,MAAM,QAAQ,GAClB,KAAK,CAAC,CAAC,SAAS,aAAa,EAC5B,QAAQ,CAAC,KACR,YAAY,CAAC;IAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;CAAE,CAEJ,CAAC;AAErC,oDAAoD;AACpD,eAAO,MAAM,SAAS,EAAE,YAAY,CAAC,cAAc,CAOiB,CAAC;AAErE,4BAA4B;AAC5B,eAAO,MAAM,GAAG,GACb,CAAC,EAAE,CAAC,EAAE,MAAM,YAAY,CAAC,CAAC,CAAC,EAAE,OAAO,YAAY,CAAC,CAAC,CAAC,KAAG,YAAY,CAAC,CAAC,GAAG,CAAC,CAE5C,CAAC;AAEhC,8BAA8B;AAC9B,eAAO,MAAM,EAAE,GACZ,CAAC,EAAE,CAAC,EAAE,MAAM,YAAY,CAAC,CAAC,CAAC,EAAE,OAAO,YAAY,CAAC,CAAC,CAAC,KAAG,YAAY,CAAC,CAAC,GAAG,CAAC,CAE5C,CAAC;AAEhC;;;;;;;;GAQG;AACH,eAAO,MAAM,GAAG,GACb,CAAC,EAAE,OAAO,YAAY,CAAC,CAAC,CAAC,MACzB,CAAC,EAAE,OAAO,CAAC,KAAG,KAAK,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC,CACrB,CAAC;AAElB;;;;GAIG;AACH,MAAM,WAAW,yBAAyB,CAAC,KAAK,EAAE,CAAC,GAAG,KAAK;IACzD,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC;IACpC,QAAQ,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;CAC1E;AAED,sEAAsE;AACtE,eAAO,MAAM,IAAI,GAAI,KAAK,EAAE,CAAC,GAAG,KAAK,EACnC,OAAO,YAAY,CAAC,KAAK,CAAC,EAC1B,WAAW,CAAC,OAAO,EAAE,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,KAC9D,yBAAyB,CAAC,KAAK,EAAE,CAAC,CAA2B,CAAC"}
@@ -0,0 +1,22 @@
1
+ const readsAs = (value, key, expected)=>typeof value === 'object' && value !== null && value[key] === expected;
2
+ /** Admits the failure whose `_tag` is `tag`. */ export const isTag = (tag)=>(value)=>readsAs(value, '_tag', tag);
3
+ /** Admits every failure in `category`. */ export const isCategory = (category)=>(value)=>readsAs(value, 'category', category);
4
+ /** Admits every failure in `family`. */ export const isFamily = (family)=>(value)=>readsAs(value, 'family', family);
5
+ /** Admits any `EntifixFailure`, of any category. */ export const isFailure = (value)=>typeof value === 'object' && value !== null && typeof value['_tag'] === 'string' && typeof value['code'] === 'string' && typeof value['category'] === 'string';
6
+ /** Both guards admit it. */ export const and = (left, right)=>(value)=>left(value) && right(value);
7
+ /** Either guard admits it. */ export const or = (left, right)=>(value)=>left(value) || right(value);
8
+ /**
9
+ * The guard does not admit it.
10
+ *
11
+ * ⚠️ Generic over the union it is applied to, because "not this shape" has no
12
+ * shape of its own: `not(isFamily('business'))(e)` narrows `E` to
13
+ * `Exclude<E, { family: 'business' }>`. Applied with no union in view — as an
14
+ * argument to {@link and} or {@link or} — it admits correctly and narrows
15
+ * nothing, so keep it the outermost combinator.
16
+ */ export const not = (guard)=>(value)=>!guard(value);
17
+ /** Pairs a guard with a condition read from the request's context. */ export const when = (guard, condition)=>({
18
+ guard,
19
+ condition
20
+ });
21
+
22
+ //# sourceMappingURL=predicates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/failure/predicates.ts"],"sourcesContent":["import type { Effect } from 'effect';\n\nimport type {\n EntifixFailure,\n FailureCategory,\n FailureFamily,\n} from './failure.js';\n\n/**\n * A guard over anything, naming the shape it admits.\n *\n * It is written over `unknown` rather than over a failure union on purpose:\n * TypeScript narrows a union by a guard on a supertype by **filtering** its\n * members, so `if (isCategory('conflict')(e))` leaves exactly the members of\n * `E` whose `category` is `'conflict'` — the same as `Extract<E, Shape>` — and\n * one predicate serves every union it is applied to.\n *\n * The check reads `_tag`, `category` and `family` and never the prototype, so a\n * failure decoded off a wire or defined in a second copy of this module\n * matches exactly as one constructed in place.\n */\nexport type FailureGuard<Shape> = (value: unknown) => value is Shape;\n\nconst readsAs = (value: unknown, key: string, expected: string): boolean =>\n typeof value === 'object' &&\n value !== null &&\n (value as Record<string, unknown>)[key] === expected;\n\n/** Admits the failure whose `_tag` is `tag`. */\nexport const isTag =\n <const Tag extends string>(tag: Tag): FailureGuard<{ readonly _tag: Tag }> =>\n (value): value is { readonly _tag: Tag } =>\n readsAs(value, '_tag', tag);\n\n/** Admits every failure in `category`. */\nexport const isCategory =\n <const C extends FailureCategory>(\n category: C,\n ): FailureGuard<{ readonly category: C }> =>\n (value): value is { readonly category: C } =>\n readsAs(value, 'category', category);\n\n/** Admits every failure in `family`. */\nexport const isFamily =\n <const F extends FailureFamily>(\n family: F,\n ): FailureGuard<{ readonly family: F }> =>\n (value): value is { readonly family: F } =>\n readsAs(value, 'family', family);\n\n/** Admits any `EntifixFailure`, of any category. */\nexport const isFailure: FailureGuard<EntifixFailure> = (\n value,\n): value is EntifixFailure =>\n typeof value === 'object' &&\n value !== null &&\n typeof (value as Record<string, unknown>)['_tag'] === 'string' &&\n typeof (value as Record<string, unknown>)['code'] === 'string' &&\n typeof (value as Record<string, unknown>)['category'] === 'string';\n\n/** Both guards admit it. */\nexport const and =\n <A, B>(left: FailureGuard<A>, right: FailureGuard<B>): FailureGuard<A & B> =>\n (value): value is A & B =>\n left(value) && right(value);\n\n/** Either guard admits it. */\nexport const or =\n <A, B>(left: FailureGuard<A>, right: FailureGuard<B>): FailureGuard<A | B> =>\n (value): value is A | B =>\n left(value) || right(value);\n\n/**\n * The guard does not admit it.\n *\n * ⚠️ Generic over the union it is applied to, because \"not this shape\" has no\n * shape of its own: `not(isFamily('business'))(e)` narrows `E` to\n * `Exclude<E, { family: 'business' }>`. Applied with no union in view — as an\n * argument to {@link and} or {@link or} — it admits correctly and narrows\n * nothing, so keep it the outermost combinator.\n */\nexport const not =\n <S>(guard: FailureGuard<S>) =>\n <E>(value: E): value is Exclude<E, S> =>\n !guard(value);\n\n/**\n * A guard plus a condition that needs the request — a dial read from\n * configuration, the caller's organization. The guard narrows; the condition\n * decides, and it is an Effect because the context it reads is.\n */\nexport interface EffectfulFailurePredicate<Shape, R = never> {\n readonly guard: FailureGuard<Shape>;\n readonly condition: (failure: Shape) => Effect.Effect<boolean, never, R>;\n}\n\n/** Pairs a guard with a condition read from the request's context. */\nexport const when = <Shape, R = never>(\n guard: FailureGuard<Shape>,\n condition: (failure: Shape) => Effect.Effect<boolean, never, R>,\n): EffectfulFailurePredicate<Shape, R> => ({ guard, condition });\n"],"names":["readsAs","value","key","expected","isTag","tag","isCategory","category","isFamily","family","isFailure","and","left","right","or","not","guard","when","condition"],"mappings":"AAuBA,MAAMA,UAAU,CAACC,OAAgBC,KAAaC,WAC5C,OAAOF,UAAU,YACjBA,UAAU,QACV,AAACA,KAAiC,CAACC,IAAI,KAAKC;AAE9C,8CAA8C,GAC9C,OAAO,MAAMC,QACX,CAA2BC,MAC3B,CAACJ,QACCD,QAAQC,OAAO,QAAQI,KAAK;AAEhC,wCAAwC,GACxC,OAAO,MAAMC,aACX,CACEC,WAEF,CAACN,QACCD,QAAQC,OAAO,YAAYM,UAAU;AAEzC,sCAAsC,GACtC,OAAO,MAAMC,WACX,CACEC,SAEF,CAACR,QACCD,QAAQC,OAAO,UAAUQ,QAAQ;AAErC,kDAAkD,GAClD,OAAO,MAAMC,YAA0C,CACrDT,QAEA,OAAOA,UAAU,YACjBA,UAAU,QACV,OAAO,AAACA,KAAiC,CAAC,OAAO,KAAK,YACtD,OAAO,AAACA,KAAiC,CAAC,OAAO,KAAK,YACtD,OAAO,AAACA,KAAiC,CAAC,WAAW,KAAK,SAAS;AAErE,0BAA0B,GAC1B,OAAO,MAAMU,MACX,CAAOC,MAAuBC,QAC9B,CAACZ,QACCW,KAAKX,UAAUY,MAAMZ,OAAO;AAEhC,4BAA4B,GAC5B,OAAO,MAAMa,KACX,CAAOF,MAAuBC,QAC9B,CAACZ,QACCW,KAAKX,UAAUY,MAAMZ,OAAO;AAEhC;;;;;;;;CAQC,GACD,OAAO,MAAMc,MACX,CAAIC,QACJ,CAAIf,QACF,CAACe,MAAMf,OAAO;AAYlB,oEAAoE,GACpE,OAAO,MAAMgB,OAAO,CAClBD,OACAE,YACyC,CAAA;QAAEF;QAAOE;IAAU,CAAA,EAAG"}
@@ -0,0 +1,49 @@
1
+ import { Schema } from 'effect';
2
+ import { type EntifixFailure } from './failure.js';
3
+ /** The content type every error answer carries (RFC 9457). */
4
+ export declare const PROBLEM_CONTENT_TYPE = "application/problem+json";
5
+ /**
6
+ * The envelope of an RFC 9457 problem, with entifix's members beside the
7
+ * standard ones. `code` is top-level because it is what a client translates;
8
+ * the failure's own fields ride as extension members.
9
+ */
10
+ export declare const Problem: Schema.Struct<{
11
+ readonly type: Schema.String;
12
+ readonly title: Schema.String;
13
+ readonly status: Schema.Number;
14
+ readonly code: Schema.String;
15
+ readonly category: Schema.Literals<readonly import("./failure.js").FailureCategory[]>;
16
+ readonly detail: Schema.optionalKey<Schema.String>;
17
+ readonly instance: Schema.optionalKey<Schema.String>;
18
+ readonly traceId: Schema.optionalKey<Schema.String>;
19
+ }>;
20
+ /** A problem body: the envelope plus the failure's own fields. */
21
+ export type Problem = typeof Problem.Type & Readonly<Record<string, unknown>>;
22
+ export interface ProblemOptions {
23
+ /** The status to answer with; the category's default when absent. */
24
+ readonly status?: number;
25
+ readonly traceId?: string;
26
+ /** The request path the failure answers. */
27
+ readonly instance?: string;
28
+ }
29
+ /**
30
+ * The problem body a failure answers with.
31
+ *
32
+ * `detail` is the failure's `message` when it has one, and is never
33
+ * `String(error)`: a failure's message is written by its author for a reader,
34
+ * a defect's text is not, and a defect never reaches this function.
35
+ */
36
+ export declare const problemOf: (failure: EntifixFailure, options?: ProblemOptions) => Problem;
37
+ /**
38
+ * The failure a problem body names, with its typed fields — or a
39
+ * {@link ProtocolFailure} when the body is not a problem, names a code nothing
40
+ * registered, or carries fields that do not decode.
41
+ *
42
+ * Never throws and never fails: whatever a peer sends, the caller gets a
43
+ * failure it can branch on.
44
+ *
45
+ * @param status the HTTP status the body arrived with, kept on a
46
+ * `ProtocolFailure` so the caller still knows what the peer meant.
47
+ */
48
+ export declare const decodeProblem: (body: unknown, status?: number) => EntifixFailure;
49
+ //# sourceMappingURL=problem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"problem.d.ts","sourceRoot":"","sources":["../../src/failure/problem.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,cAAc,CAAC;AAItB,8DAA8D;AAC9D,eAAO,MAAM,oBAAoB,6BAA6B,CAAC;AAE/D;;;;GAIG;AACH,eAAO,MAAM,OAAO;;;;;;;;;EASlB,CAAC;AAEH,kEAAkE;AAClE,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAE9E,MAAM,WAAW,cAAc;IAC7B,qEAAqE;IACrE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,4CAA4C;IAC5C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AA0BD;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,GACpB,SAAS,cAAc,EACvB,UAAS,cAAmB,KAC3B,OAUD,CAAC;AAKH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,aAAa,GACxB,MAAM,OAAO,EACb,SAAS,MAAM,KACd,cAqBF,CAAC"}
@@ -0,0 +1,87 @@
1
+ import { _ as _extends } from "@swc/helpers/_/_extends";
2
+ import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
3
+ import { Exit, Schema } from 'effect';
4
+ import { defaultStatus, FAILURE_CATEGORIES } from './failure.js';
5
+ import { ProtocolFailure } from './generic.js';
6
+ import { failureTypeUri, lookupFailure } from './registry.js';
7
+ /** The content type every error answer carries (RFC 9457). */ export const PROBLEM_CONTENT_TYPE = 'application/problem+json';
8
+ /**
9
+ * The envelope of an RFC 9457 problem, with entifix's members beside the
10
+ * standard ones. `code` is top-level because it is what a client translates;
11
+ * the failure's own fields ride as extension members.
12
+ */ export const Problem = Schema.Struct({
13
+ type: Schema.String,
14
+ title: Schema.String,
15
+ status: Schema.Number,
16
+ code: Schema.String,
17
+ category: Schema.Literals(FAILURE_CATEGORIES),
18
+ detail: Schema.optionalKey(Schema.String),
19
+ instance: Schema.optionalKey(Schema.String),
20
+ traceId: Schema.optionalKey(Schema.String)
21
+ });
22
+ /**
23
+ * The failure's own fields, encoded by the class that registered its code.
24
+ *
25
+ * ⚠️ Encoded through the **registered** class, not the instance's
26
+ * constructor, so a failure decoded elsewhere encodes the same way. A failure
27
+ * whose code nothing registered — impossible through the definers — encodes
28
+ * with no fields rather than leaking whatever it carries.
29
+ */ const encodedFields = (failure)=>{
30
+ const registered = lookupFailure(failure.code);
31
+ if (registered === undefined) return {};
32
+ const encoded = Schema.encodeUnknownExit(registered.failureClass)(failure);
33
+ if (Exit.isFailure(encoded)) return {};
34
+ const _encoded_value = encoded.value, { _tag: _ignored } = _encoded_value, fields = _object_without_properties_loose(_encoded_value, [
35
+ "_tag"
36
+ ]);
37
+ return fields;
38
+ };
39
+ /**
40
+ * The problem body a failure answers with.
41
+ *
42
+ * `detail` is the failure's `message` when it has one, and is never
43
+ * `String(error)`: a failure's message is written by its author for a reader,
44
+ * a defect's text is not, and a defect never reaches this function.
45
+ */ export const problemOf = (failure, options = {})=>{
46
+ var _options_status;
47
+ return _extends({}, encodedFields(failure), {
48
+ type: failureTypeUri(failure.code),
49
+ title: failure._tag,
50
+ status: (_options_status = options.status) != null ? _options_status : defaultStatus(failure.category),
51
+ code: failure.code,
52
+ category: failure.category
53
+ }, failure.message === '' ? {} : {
54
+ detail: failure.message
55
+ }, options.instance === undefined ? {} : {
56
+ instance: options.instance
57
+ }, options.traceId === undefined ? {} : {
58
+ traceId: options.traceId
59
+ });
60
+ };
61
+ const isRecord = (value)=>typeof value === 'object' && value !== null && !Array.isArray(value);
62
+ /**
63
+ * The failure a problem body names, with its typed fields — or a
64
+ * {@link ProtocolFailure} when the body is not a problem, names a code nothing
65
+ * registered, or carries fields that do not decode.
66
+ *
67
+ * Never throws and never fails: whatever a peer sends, the caller gets a
68
+ * failure it can branch on.
69
+ *
70
+ * @param status the HTTP status the body arrived with, kept on a
71
+ * `ProtocolFailure` so the caller still knows what the peer meant.
72
+ */ export const decodeProblem = (body, status)=>{
73
+ const protocol = (reason)=>new ProtocolFailure(_extends({
74
+ reason
75
+ }, status === undefined ? {} : {
76
+ upstreamStatus: status
77
+ }));
78
+ if (!isRecord(body) || typeof body['code'] !== 'string') return protocol('the error body is not a problem');
79
+ const registered = lookupFailure(body['code']);
80
+ if (registered === undefined) return protocol(`the problem names an unknown code '${body['code']}'`);
81
+ const decoded = Schema.decodeUnknownExit(registered.failureClass)(_extends({}, body, {
82
+ _tag: registered.tag
83
+ }));
84
+ return Exit.isSuccess(decoded) ? decoded.value : protocol(`the fields of '${body['code']}' do not decode`);
85
+ };
86
+
87
+ //# sourceMappingURL=problem.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/failure/problem.ts"],"sourcesContent":["import { Exit, Schema } from 'effect';\n\nimport {\n defaultStatus,\n type EntifixFailure,\n FAILURE_CATEGORIES,\n} from './failure.js';\nimport { ProtocolFailure } from './generic.js';\nimport { failureTypeUri, lookupFailure } from './registry.js';\n\n/** The content type every error answer carries (RFC 9457). */\nexport const PROBLEM_CONTENT_TYPE = 'application/problem+json';\n\n/**\n * The envelope of an RFC 9457 problem, with entifix's members beside the\n * standard ones. `code` is top-level because it is what a client translates;\n * the failure's own fields ride as extension members.\n */\nexport const Problem = Schema.Struct({\n type: Schema.String,\n title: Schema.String,\n status: Schema.Number,\n code: Schema.String,\n category: Schema.Literals(FAILURE_CATEGORIES),\n detail: Schema.optionalKey(Schema.String),\n instance: Schema.optionalKey(Schema.String),\n traceId: Schema.optionalKey(Schema.String),\n});\n\n/** A problem body: the envelope plus the failure's own fields. */\nexport type Problem = typeof Problem.Type & Readonly<Record<string, unknown>>;\n\nexport interface ProblemOptions {\n /** The status to answer with; the category's default when absent. */\n readonly status?: number;\n readonly traceId?: string;\n /** The request path the failure answers. */\n readonly instance?: string;\n}\n\n/**\n * The failure's own fields, encoded by the class that registered its code.\n *\n * ⚠️ Encoded through the **registered** class, not the instance's\n * constructor, so a failure decoded elsewhere encodes the same way. A failure\n * whose code nothing registered — impossible through the definers — encodes\n * with no fields rather than leaking whatever it carries.\n */\nconst encodedFields = (\n failure: EntifixFailure,\n): Readonly<Record<string, unknown>> => {\n const registered = lookupFailure(failure.code);\n if (registered === undefined) return {};\n const encoded = Schema.encodeUnknownExit(\n registered.failureClass as unknown as Schema.Codec<unknown, unknown>,\n )(failure);\n if (Exit.isFailure(encoded)) return {};\n const { _tag: _ignored, ...fields } = encoded.value as Record<\n string,\n unknown\n >;\n return fields;\n};\n\n/**\n * The problem body a failure answers with.\n *\n * `detail` is the failure's `message` when it has one, and is never\n * `String(error)`: a failure's message is written by its author for a reader,\n * a defect's text is not, and a defect never reaches this function.\n */\nexport const problemOf = (\n failure: EntifixFailure,\n options: ProblemOptions = {},\n): Problem => ({\n ...encodedFields(failure),\n type: failureTypeUri(failure.code),\n title: failure._tag,\n status: options.status ?? defaultStatus(failure.category),\n code: failure.code,\n category: failure.category,\n ...(failure.message === '' ? {} : { detail: failure.message }),\n ...(options.instance === undefined ? {} : { instance: options.instance }),\n ...(options.traceId === undefined ? {} : { traceId: options.traceId }),\n});\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\n/**\n * The failure a problem body names, with its typed fields — or a\n * {@link ProtocolFailure} when the body is not a problem, names a code nothing\n * registered, or carries fields that do not decode.\n *\n * Never throws and never fails: whatever a peer sends, the caller gets a\n * failure it can branch on.\n *\n * @param status the HTTP status the body arrived with, kept on a\n * `ProtocolFailure` so the caller still knows what the peer meant.\n */\nexport const decodeProblem = (\n body: unknown,\n status?: number,\n): EntifixFailure => {\n const protocol = (reason: string) =>\n new ProtocolFailure({\n reason,\n ...(status === undefined ? {} : { upstreamStatus: status }),\n });\n\n if (!isRecord(body) || typeof body['code'] !== 'string')\n return protocol('the error body is not a problem');\n\n const registered = lookupFailure(body['code']);\n if (registered === undefined)\n return protocol(`the problem names an unknown code '${body['code']}'`);\n\n const decoded = Schema.decodeUnknownExit(\n registered.failureClass as unknown as Schema.Codec<unknown, unknown>,\n )({ ...body, _tag: registered.tag });\n\n return Exit.isSuccess(decoded)\n ? (decoded.value as EntifixFailure)\n : protocol(`the fields of '${body['code']}' do not decode`);\n};\n"],"names":["Exit","Schema","defaultStatus","FAILURE_CATEGORIES","ProtocolFailure","failureTypeUri","lookupFailure","PROBLEM_CONTENT_TYPE","Problem","Struct","type","String","title","status","Number","code","category","Literals","detail","optionalKey","instance","traceId","encodedFields","failure","registered","undefined","encoded","encodeUnknownExit","failureClass","isFailure","value","_tag","_ignored","fields","problemOf","options","message","isRecord","Array","isArray","decodeProblem","body","protocol","reason","upstreamStatus","decoded","decodeUnknownExit","tag","isSuccess"],"mappings":";;AAAA,SAASA,IAAI,EAAEC,MAAM,QAAQ,SAAS;AAEtC,SACEC,aAAa,EAEbC,kBAAkB,QACb,eAAe;AACtB,SAASC,eAAe,QAAQ,eAAe;AAC/C,SAASC,cAAc,EAAEC,aAAa,QAAQ,gBAAgB;AAE9D,4DAA4D,GAC5D,OAAO,MAAMC,uBAAuB,2BAA2B;AAE/D;;;;CAIC,GACD,OAAO,MAAMC,UAAUP,OAAOQ,MAAM,CAAC;IACnCC,MAAMT,OAAOU,MAAM;IACnBC,OAAOX,OAAOU,MAAM;IACpBE,QAAQZ,OAAOa,MAAM;IACrBC,MAAMd,OAAOU,MAAM;IACnBK,UAAUf,OAAOgB,QAAQ,CAACd;IAC1Be,QAAQjB,OAAOkB,WAAW,CAAClB,OAAOU,MAAM;IACxCS,UAAUnB,OAAOkB,WAAW,CAAClB,OAAOU,MAAM;IAC1CU,SAASpB,OAAOkB,WAAW,CAAClB,OAAOU,MAAM;AAC3C,GAAG;AAaH;;;;;;;CAOC,GACD,MAAMW,gBAAgB,CACpBC;IAEA,MAAMC,aAAalB,cAAciB,QAAQR,IAAI;IAC7C,IAAIS,eAAeC,WAAW,OAAO,CAAC;IACtC,MAAMC,UAAUzB,OAAO0B,iBAAiB,CACtCH,WAAWI,YAAY,EACvBL;IACF,IAAIvB,KAAK6B,SAAS,CAACH,UAAU,OAAO,CAAC;IACrC,MAAsCA,iBAAAA,QAAQI,KAAK,EAA7C,EAAEC,MAAMC,QAAQ,EAAa,GAAGN,gBAAXO,0CAAWP;;;IAItC,OAAOO;AACT;AAEA;;;;;;CAMC,GACD,OAAO,MAAMC,YAAY,CACvBX,SACAY,UAA0B,CAAC,CAAC;QAKpBA;WAJK,aACVb,cAAcC;QACjBb,MAAML,eAAekB,QAAQR,IAAI;QACjCH,OAAOW,QAAQQ,IAAI;QACnBlB,MAAM,GAAEsB,kBAAAA,QAAQtB,MAAM,YAAdsB,kBAAkBjC,cAAcqB,QAAQP,QAAQ;QACxDD,MAAMQ,QAAQR,IAAI;QAClBC,UAAUO,QAAQP,QAAQ;OACtBO,QAAQa,OAAO,KAAK,KAAK,CAAC,IAAI;QAAElB,QAAQK,QAAQa,OAAO;IAAC,GACxDD,QAAQf,QAAQ,KAAKK,YAAY,CAAC,IAAI;QAAEL,UAAUe,QAAQf,QAAQ;IAAC,GACnEe,QAAQd,OAAO,KAAKI,YAAY,CAAC,IAAI;QAAEJ,SAASc,QAAQd,OAAO;IAAC;EACnE;AAEH,MAAMgB,WAAW,CAACP,QAChB,OAAOA,UAAU,YAAYA,UAAU,QAAQ,CAACQ,MAAMC,OAAO,CAACT;AAEhE;;;;;;;;;;CAUC,GACD,OAAO,MAAMU,gBAAgB,CAC3BC,MACA5B;IAEA,MAAM6B,WAAW,CAACC,SAChB,IAAIvC,gBAAgB;YAClBuC;WACI9B,WAAWY,YAAY,CAAC,IAAI;YAAEmB,gBAAgB/B;QAAO;IAG7D,IAAI,CAACwB,SAASI,SAAS,OAAOA,IAAI,CAAC,OAAO,KAAK,UAC7C,OAAOC,SAAS;IAElB,MAAMlB,aAAalB,cAAcmC,IAAI,CAAC,OAAO;IAC7C,IAAIjB,eAAeC,WACjB,OAAOiB,SAAS,CAAC,mCAAmC,EAAED,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAEvE,MAAMI,UAAU5C,OAAO6C,iBAAiB,CACtCtB,WAAWI,YAAY,EACvB,aAAKa;QAAMV,MAAMP,WAAWuB,GAAG;;IAEjC,OAAO/C,KAAKgD,SAAS,CAACH,WACjBA,QAAQf,KAAK,GACdY,SAAS,CAAC,eAAe,EAAED,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC;AAC9D,EAAE"}
@@ -0,0 +1,28 @@
1
+ import type { FailureCategory, FailureClass, FailureFamily } from './failure.js';
2
+ /** One registered failure: what a wire `code` decodes back into. */
3
+ export interface RegisteredFailure {
4
+ readonly code: string;
5
+ readonly tag: string;
6
+ readonly category: FailureCategory;
7
+ readonly family: FailureFamily;
8
+ /** The RFC 9457 `type` URI. */
9
+ readonly type: string;
10
+ readonly failureClass: FailureClass;
11
+ }
12
+ /** The RFC 9457 `type` a code answers with. */
13
+ export declare const failureTypeUri: (code: string) => string;
14
+ /**
15
+ * Record a failure's code. A code is permanent (AIP-193): it never changes
16
+ * meaning and is never reused, so a second **tag** claiming one throws here,
17
+ * at module load, rather than putting two meanings on one wire.
18
+ *
19
+ * The same tag registering the same code again replaces the entry. That is a
20
+ * module evaluated twice — a dev server's hot reload, a test re-importing —
21
+ * and refusing it would turn every reload into a boot failure.
22
+ */
23
+ export declare const registerFailure: (entry: RegisteredFailure) => void;
24
+ /** The failure a code names, if anything registered it. */
25
+ export declare const lookupFailure: (code: string) => RegisteredFailure | undefined;
26
+ /** Every registered failure, ordered by code. */
27
+ export declare const registeredFailures: () => readonly RegisteredFailure[];
28
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/failure/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EACZ,aAAa,EACd,MAAM,cAAc,CAAC;AAEtB,oEAAoE;AACpE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,+BAA+B;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;CACrC;AAsBD,+CAA+C;AAC/C,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,KAAG,MACf,CAAC;AAEhC;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,GAAI,OAAO,iBAAiB,KAAG,IAS1D,CAAC;AAEF,2DAA2D;AAC3D,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,KAAG,iBAAiB,GAAG,SAC3C,CAAC;AAEvB,iDAAiD;AACjD,eAAO,MAAM,kBAAkB,QAAO,SAAS,iBAAiB,EACO,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * The registry is shared through `globalThis` under a registered symbol, not
3
+ * held in a module-level `Map`.
4
+ *
5
+ * ⚠️ Two copies of `@entifix/core` in one process — a bundler that duplicated
6
+ * it, a consumer's own pin beside a dependency's — would otherwise hold two
7
+ * registries, and a failure defined against one would not decode through the
8
+ * other. One table per process is the property the bus relies on when it
9
+ * decodes a failure a second module instance defined.
10
+ */ const REGISTRY_KEY = Symbol.for('@entifix/core/failure-registry');
11
+ const registry = ()=>{
12
+ var _holder, _REGISTRY_KEY, _;
13
+ const holder = globalThis;
14
+ (_ = (_holder = holder)[_REGISTRY_KEY = REGISTRY_KEY]) != null ? _ : _holder[_REGISTRY_KEY] = new Map();
15
+ return holder[REGISTRY_KEY];
16
+ };
17
+ /** The RFC 9457 `type` a code answers with. */ export const failureTypeUri = (code)=>`urn:entifix:failure:${code}`;
18
+ /**
19
+ * Record a failure's code. A code is permanent (AIP-193): it never changes
20
+ * meaning and is never reused, so a second **tag** claiming one throws here,
21
+ * at module load, rather than putting two meanings on one wire.
22
+ *
23
+ * The same tag registering the same code again replaces the entry. That is a
24
+ * module evaluated twice — a dev server's hot reload, a test re-importing —
25
+ * and refusing it would turn every reload into a boot failure.
26
+ */ export const registerFailure = (entry)=>{
27
+ const existing = registry().get(entry.code);
28
+ if (existing !== undefined && existing.tag !== entry.tag) throw new Error(`failure code '${entry.code}' is already registered by '${existing.tag}', ` + `and '${entry.tag}' cannot claim it. A code is permanent and names ` + 'one failure: give this one its own.');
29
+ registry().set(entry.code, entry);
30
+ };
31
+ /** The failure a code names, if anything registered it. */ export const lookupFailure = (code)=>registry().get(code);
32
+ /** Every registered failure, ordered by code. */ export const registeredFailures = ()=>[
33
+ ...registry().values()
34
+ ].sort((a, b)=>a.code.localeCompare(b.code));
35
+
36
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/failure/registry.ts"],"sourcesContent":["import type {\n FailureCategory,\n FailureClass,\n FailureFamily,\n} from './failure.js';\n\n/** One registered failure: what a wire `code` decodes back into. */\nexport interface RegisteredFailure {\n readonly code: string;\n readonly tag: string;\n readonly category: FailureCategory;\n readonly family: FailureFamily;\n /** The RFC 9457 `type` URI. */\n readonly type: string;\n readonly failureClass: FailureClass;\n}\n\n/**\n * The registry is shared through `globalThis` under a registered symbol, not\n * held in a module-level `Map`.\n *\n * ⚠️ Two copies of `@entifix/core` in one process — a bundler that duplicated\n * it, a consumer's own pin beside a dependency's — would otherwise hold two\n * registries, and a failure defined against one would not decode through the\n * other. One table per process is the property the bus relies on when it\n * decodes a failure a second module instance defined.\n */\nconst REGISTRY_KEY = Symbol.for('@entifix/core/failure-registry');\n\ntype Registry = Map<string, RegisteredFailure>;\n\nconst registry = (): Registry => {\n const holder = globalThis as { [REGISTRY_KEY]?: Registry };\n holder[REGISTRY_KEY] ??= new Map();\n return holder[REGISTRY_KEY];\n};\n\n/** The RFC 9457 `type` a code answers with. */\nexport const failureTypeUri = (code: string): string =>\n `urn:entifix:failure:${code}`;\n\n/**\n * Record a failure's code. A code is permanent (AIP-193): it never changes\n * meaning and is never reused, so a second **tag** claiming one throws here,\n * at module load, rather than putting two meanings on one wire.\n *\n * The same tag registering the same code again replaces the entry. That is a\n * module evaluated twice — a dev server's hot reload, a test re-importing —\n * and refusing it would turn every reload into a boot failure.\n */\nexport const registerFailure = (entry: RegisteredFailure): void => {\n const existing = registry().get(entry.code);\n if (existing !== undefined && existing.tag !== entry.tag)\n throw new Error(\n `failure code '${entry.code}' is already registered by '${existing.tag}', ` +\n `and '${entry.tag}' cannot claim it. A code is permanent and names ` +\n 'one failure: give this one its own.',\n );\n registry().set(entry.code, entry);\n};\n\n/** The failure a code names, if anything registered it. */\nexport const lookupFailure = (code: string): RegisteredFailure | undefined =>\n registry().get(code);\n\n/** Every registered failure, ordered by code. */\nexport const registeredFailures = (): readonly RegisteredFailure[] =>\n [...registry().values()].sort((a, b) => a.code.localeCompare(b.code));\n"],"names":["REGISTRY_KEY","Symbol","for","registry","holder","globalThis","Map","failureTypeUri","code","registerFailure","entry","existing","get","undefined","tag","Error","set","lookupFailure","registeredFailures","values","sort","a","b","localeCompare"],"mappings":"AAiBA;;;;;;;;;CASC,GACD,MAAMA,eAAeC,OAAOC,GAAG,CAAC;AAIhC,MAAMC,WAAW;QAEfC,SAAOJ,eAAPI;IADA,MAAMA,SAASC;KACfD,IAAAA,CAAAA,UAAAA,OAAM,CAACJ,gBAAAA,aAAa,YAApBI,IAAAA,OAAM,CAACJ,cAAa,GAAK,IAAIM;IAC7B,OAAOF,MAAM,CAACJ,aAAa;AAC7B;AAEA,6CAA6C,GAC7C,OAAO,MAAMO,iBAAiB,CAACC,OAC7B,CAAC,oBAAoB,EAAEA,MAAM,CAAC;AAEhC;;;;;;;;CAQC,GACD,OAAO,MAAMC,kBAAkB,CAACC;IAC9B,MAAMC,WAAWR,WAAWS,GAAG,CAACF,MAAMF,IAAI;IAC1C,IAAIG,aAAaE,aAAaF,SAASG,GAAG,KAAKJ,MAAMI,GAAG,EACtD,MAAM,IAAIC,MACR,CAAC,cAAc,EAAEL,MAAMF,IAAI,CAAC,4BAA4B,EAAEG,SAASG,GAAG,CAAC,GAAG,CAAC,GACzE,CAAC,KAAK,EAAEJ,MAAMI,GAAG,CAAC,iDAAiD,CAAC,GACpE;IAENX,WAAWa,GAAG,CAACN,MAAMF,IAAI,EAAEE;AAC7B,EAAE;AAEF,yDAAyD,GACzD,OAAO,MAAMO,gBAAgB,CAACT,OAC5BL,WAAWS,GAAG,CAACJ,MAAM;AAEvB,+CAA+C,GAC/C,OAAO,MAAMU,qBAAqB,IAChC;WAAIf,WAAWgB,MAAM;KAAG,CAACC,IAAI,CAAC,CAACC,GAAGC,IAAMD,EAAEb,IAAI,CAACe,aAAa,CAACD,EAAEd,IAAI,GAAG"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from './base-entities/configuration-client/index.js';
2
2
  export * from './base-entities/entifix-error/index.js';
3
3
  export * from './command-palette/index.js';
4
+ export * from './deadline/deadline.js';
4
5
  export * from './entity-definition/decorators/accessor/index.js';
5
6
  export * from './entity-definition/decorators/entity/index.js';
6
7
  export * from './entity-definition/decorators/method/index.js';
@@ -22,6 +23,7 @@ export * from './entity-definition/reconstruct/index.js';
22
23
  export * from './entity-definition/serializer/index.js';
23
24
  export * from './entity-definition/validate/index.js';
24
25
  export * from './envelope/index.js';
26
+ export * from './failure/index.js';
25
27
  export * from './hierarchy/index.js';
26
28
  export * from './http/session-cookies.js';
27
29
  export * from './i18n/format.js';