@hasna/events 0.1.14 → 0.1.15

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.
@@ -0,0 +1,108 @@
1
+ {
2
+ "event_id": "evt_fixture_todo_completed_01",
3
+ "event_type": "todos.task.completed",
4
+ "schema_version": "hasna.app_event.v1",
5
+ "source": {
6
+ "app": "open-todos",
7
+ "version": "0.0.0-fixture",
8
+ "machine": "fixture.local"
9
+ },
10
+ "occurred_at": "2026-07-29T12:00:00.000Z",
11
+ "severity": "notice",
12
+ "idempotency": {
13
+ "dedupe_key": "fixture:interop-project:todo-42:completed:v1",
14
+ "replay_safe": true
15
+ },
16
+ "correlation": {
17
+ "correlation_id": "corr_fixture_interop_project_01",
18
+ "causation_id": "evt_fixture_todo_created_01"
19
+ },
20
+ "subject": {
21
+ "kind": "task",
22
+ "id": "todo_fixture_42",
23
+ "uri": "hasna://todos/tasks/todo_fixture_42"
24
+ },
25
+ "actor": {
26
+ "kind": "service",
27
+ "id": "open-todos",
28
+ "name": "Todos fixture producer"
29
+ },
30
+ "project_mappings": {
31
+ "canonical_id": "project_fixture_interop",
32
+ "slug": "interop-fixture",
33
+ "repository": "https://example.invalid/hasna/interop-fixture",
34
+ "workspace": "workspace_fixture_interop",
35
+ "external_ids": {
36
+ "todos": "project_fixture_interop",
37
+ "conversations": "conversation_fixture_17",
38
+ "mementos": "memento_fixture_09",
39
+ "projects": "project_fixture_interop",
40
+ "codewith": "mailbox_fixture_interop"
41
+ }
42
+ },
43
+ "summary": "Interop fixture task completed successfully.",
44
+ "data": {
45
+ "task_status": "completed",
46
+ "task_title": "Verify app-event interoperability",
47
+ "conversation_id": "conversation_fixture_17",
48
+ "memento_id": "memento_fixture_09",
49
+ "mailbox_topic": "project.activity",
50
+ "render_hint": {
51
+ "component": "StatusBadge",
52
+ "tone": "success"
53
+ }
54
+ },
55
+ "resource_refs": [
56
+ {
57
+ "kind": "task",
58
+ "id": "todo_fixture_42",
59
+ "uri": "hasna://todos/tasks/todo_fixture_42",
60
+ "source_package": "@hasna/todos",
61
+ "external_id": "todo_fixture_42"
62
+ },
63
+ {
64
+ "kind": "conversation",
65
+ "id": "conversation_fixture_17",
66
+ "uri": "hasna://conversations/conversation_fixture_17"
67
+ },
68
+ {
69
+ "kind": "memento",
70
+ "id": "memento_fixture_09",
71
+ "uri": "hasna://mementos/memento_fixture_09"
72
+ },
73
+ {
74
+ "kind": "render",
75
+ "id": "project_fixture_interop_status",
76
+ "uri": "hasna://projects/project_fixture_interop/render/status"
77
+ }
78
+ ],
79
+ "evidence_refs": [
80
+ {
81
+ "kind": "test_result",
82
+ "id": "evidence_fixture_interop_01",
83
+ "uri": "artifact://interop-fixture/test-report.json",
84
+ "redaction": "none"
85
+ }
86
+ ],
87
+ "sensitivity": {
88
+ "classification": "internal",
89
+ "contains_personal_data": false
90
+ },
91
+ "redaction": {
92
+ "state": "none",
93
+ "fields": [],
94
+ "safe_for_logs": true
95
+ },
96
+ "delivery": {
97
+ "intent": "notification",
98
+ "mode": "at_least_once",
99
+ "targets": [
100
+ "todos",
101
+ "conversations",
102
+ "mementos",
103
+ "projects-json-render",
104
+ "codewith-mailbox"
105
+ ],
106
+ "agent_conversation_injection": false
107
+ }
108
+ }
@@ -0,0 +1,70 @@
1
+ {
2
+ "schema": "hasna.service_contract.v1",
3
+ "name": "events",
4
+ "class": "library",
5
+ "contractVersion": "v1",
6
+ "kitVersion": "0.8.5",
7
+ "description": "Shared event envelopes, local channels, replay, and delivery transports for Hasna open-source apps. Library class: SDK exports are the primary surface and the local `events` CLI is the operator seam. The default compatibility store remains user-owned JSON; opt-in durable delivery uses a Node-safe filesystem spool plus a Bun SQLite outbox under the same caller-selected data directory. The package provisions no remote infrastructure.",
8
+ "bins": [
9
+ "events"
10
+ ],
11
+ "hosting": [
12
+ "user-hosted"
13
+ ],
14
+ "serviceSurfaces": [
15
+ {
16
+ "name": "package-sdk",
17
+ "kind": "sdk",
18
+ "status": "supported",
19
+ "authMode": "none",
20
+ "exportSubpath": "."
21
+ },
22
+ {
23
+ "name": "durable-spool-sdk",
24
+ "kind": "sdk",
25
+ "status": "supported",
26
+ "authMode": "none",
27
+ "exportSubpath": "./durable-spool"
28
+ },
29
+ {
30
+ "name": "durable-delivery-sdk",
31
+ "kind": "sdk",
32
+ "status": "supported",
33
+ "authMode": "none",
34
+ "exportSubpath": "./durable"
35
+ },
36
+ {
37
+ "name": "durable-worker-sdk",
38
+ "kind": "sdk",
39
+ "status": "supported",
40
+ "authMode": "none",
41
+ "exportSubpath": "./durable-worker"
42
+ },
43
+ {
44
+ "name": "events-cli",
45
+ "kind": "cli",
46
+ "status": "supported",
47
+ "bin": "events",
48
+ "authMode": "local-only"
49
+ }
50
+ ],
51
+ "metadata": {
52
+ "release": {
53
+ "artifactScan": {
54
+ "script": "artifact-scan"
55
+ }
56
+ },
57
+ "conformance": {
58
+ "waivedSurfaces": [
59
+ {
60
+ "kind": "api",
61
+ "reason": "Embedded library plus a local CLI; it owns no HTTP service boundary and ships no serve bin."
62
+ },
63
+ {
64
+ "kind": "mcp",
65
+ "reason": "Embedded library; MCP execution belongs to the applications that consume these envelopes."
66
+ }
67
+ ]
68
+ }
69
+ }
70
+ }
package/package.json CHANGED
@@ -1,57 +1,85 @@
1
1
  {
2
2
  "name": "@hasna/events",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "description": "Shared event envelopes, local channels, replay, and delivery transports for Hasna open-source apps",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
- "types": "./dist/index.d.ts",
7
+ "types": "./types/index.d.ts",
8
8
  "bin": {
9
9
  "events": "dist/cli/index.js",
10
10
  "hasna-events": "dist/cli/index.js"
11
11
  },
12
12
  "exports": {
13
13
  ".": {
14
- "types": "./dist/index.d.ts",
14
+ "types": "./types/index.d.ts",
15
15
  "import": "./dist/index.js"
16
16
  },
17
17
  "./storage": {
18
- "types": "./dist/storage.d.ts",
18
+ "types": "./types/storage.d.ts",
19
19
  "import": "./dist/storage.js"
20
20
  },
21
+ "./durable": {
22
+ "types": "./types/durable.d.ts",
23
+ "import": "./dist/durable.js"
24
+ },
25
+ "./durable-spool": {
26
+ "types": "./types/durable-spool.d.ts",
27
+ "import": "./dist/durable-spool.js"
28
+ },
29
+ "./durable-worker": {
30
+ "types": "./types/durable-worker.d.ts",
31
+ "import": "./dist/durable-worker.js"
32
+ },
21
33
  "./signing": {
22
- "types": "./dist/signing.d.ts",
34
+ "types": "./types/signing.d.ts",
23
35
  "import": "./dist/signing.js"
24
36
  },
25
37
  "./filter": {
26
- "types": "./dist/filter.d.ts",
38
+ "types": "./types/filter.d.ts",
27
39
  "import": "./dist/filter.js"
28
40
  },
29
41
  "./transports": {
30
- "types": "./dist/transports.d.ts",
42
+ "types": "./types/transports.d.ts",
31
43
  "import": "./dist/transports.js"
32
44
  },
33
45
  "./catalog": {
34
- "types": "./dist/catalog.d.ts",
46
+ "types": "./types/catalog.d.ts",
35
47
  "import": "./dist/catalog.js"
36
48
  },
49
+ "./app-event": {
50
+ "types": "./types/app-event.d.ts",
51
+ "import": "./dist/app-event.js"
52
+ },
53
+ "./schemas/hasna.app_event.v1.json": "./schemas/hasna.app_event.v1.json",
54
+ "./fixtures/hasna.app_event.v1.json": "./fixtures/hasna.app_event.v1.json",
37
55
  "./commander": {
38
- "types": "./dist/commander.d.ts",
56
+ "types": "./types/commander.d.ts",
39
57
  "import": "./dist/commander.js"
40
58
  },
41
59
  "./cli": {
42
- "types": "./dist/cli/index.d.ts",
60
+ "types": "./types/cli/index.d.ts",
43
61
  "import": "./dist/cli/index.js"
44
62
  }
45
63
  },
46
64
  "files": [
47
65
  "dist",
66
+ "types",
67
+ "schemas",
68
+ "fixtures",
48
69
  "README.md",
49
- "LICENSE"
70
+ "LICENSE",
71
+ "hasna.contract.json"
50
72
  ],
51
73
  "scripts": {
52
- "build": "rm -rf dist && bun build src/cli/index.ts --outdir dist/cli --target bun && bun build src/index.ts src/storage.ts src/signing.ts src/filter.ts src/transports.ts src/types.ts src/commander.ts src/catalog.ts --outdir dist --target bun && tsc -p tsconfig.build.json --emitDeclarationOnly --outDir dist",
74
+ "build": "bun run build:runtime && bun run build:types",
75
+ "build:runtime": "rm -rf dist && bun build src/cli/index.ts --outdir dist/cli --target bun && bun build src/index.ts src/storage.ts src/signing.ts src/filter.ts src/transports.ts src/types.ts src/commander.ts src/catalog.ts src/app-event.ts src/durable.ts src/durable-worker.ts --root src --outdir dist --target bun && bun build src/durable-spool.ts --root src --outdir dist --target node",
76
+ "build:types": "rm -rf types && tsc -p tsconfig.build.json --emitDeclarationOnly --outDir types",
77
+ "generated-artifacts:check": "bun run build && test -z \"$(git status --porcelain --untracked-files=all -- dist types)\"",
78
+ "contract:check": "contracts repo-conformance .",
79
+ "artifact-scan": "bun scripts/artifact-scan.ts",
53
80
  "typecheck": "tsc --noEmit",
54
81
  "test": "bun test",
82
+ "prepack": "bun run build && bun run artifact-scan",
55
83
  "prepublishOnly": "bun run test && bun run build"
56
84
  },
57
85
  "keywords": [
@@ -75,7 +103,8 @@
75
103
  "url": "https://github.com/hasna/events/issues"
76
104
  },
77
105
  "engines": {
78
- "bun": ">=1.0.0"
106
+ "bun": ">=1.0.0",
107
+ "node": ">=20.0.0"
79
108
  },
80
109
  "author": "Hasna",
81
110
  "license": "Apache-2.0",
@@ -83,6 +112,7 @@
83
112
  "commander": "^13.1.0"
84
113
  },
85
114
  "devDependencies": {
115
+ "@hasna/contracts": "0.8.5",
86
116
  "@types/bun": "latest",
87
117
  "typescript": "^5.7.3"
88
118
  }
@@ -0,0 +1,186 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.hasna.com/hasna.app_event.v1.json",
4
+ "title": "hasna.app_event.v1",
5
+ "description": "Versioned cross-app event profile carried by @hasna/events.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": [
9
+ "event_id",
10
+ "event_type",
11
+ "schema_version",
12
+ "source",
13
+ "occurred_at",
14
+ "severity",
15
+ "idempotency",
16
+ "correlation",
17
+ "subject",
18
+ "actor",
19
+ "project_mappings",
20
+ "summary",
21
+ "data",
22
+ "resource_refs",
23
+ "evidence_refs",
24
+ "sensitivity",
25
+ "redaction",
26
+ "delivery"
27
+ ],
28
+ "properties": {
29
+ "event_id": { "type": "string", "minLength": 1, "maxLength": 200 },
30
+ "event_type": { "type": "string", "minLength": 1, "maxLength": 200 },
31
+ "schema_version": { "const": "hasna.app_event.v1" },
32
+ "source": {
33
+ "type": "object",
34
+ "additionalProperties": false,
35
+ "required": ["app", "version", "machine"],
36
+ "properties": {
37
+ "app": { "type": "string", "minLength": 1, "maxLength": 200 },
38
+ "version": { "type": "string", "minLength": 1, "maxLength": 100 },
39
+ "machine": { "type": "string", "minLength": 1, "maxLength": 200 }
40
+ }
41
+ },
42
+ "occurred_at": { "type": "string", "format": "date-time" },
43
+ "severity": { "enum": ["debug", "info", "notice", "warning", "error", "critical"] },
44
+ "idempotency": {
45
+ "type": "object",
46
+ "additionalProperties": false,
47
+ "required": ["dedupe_key", "replay_safe"],
48
+ "properties": {
49
+ "dedupe_key": { "type": "string", "minLength": 1, "maxLength": 512 },
50
+ "replay_safe": { "type": "boolean" },
51
+ "replay_of_event_id": { "type": "string", "minLength": 1, "maxLength": 200 }
52
+ }
53
+ },
54
+ "correlation": {
55
+ "type": "object",
56
+ "additionalProperties": false,
57
+ "required": ["correlation_id"],
58
+ "properties": {
59
+ "correlation_id": { "type": "string", "minLength": 1, "maxLength": 200 },
60
+ "causation_id": { "type": "string", "minLength": 1, "maxLength": 200 },
61
+ "trace_id": { "type": "string", "minLength": 1, "maxLength": 200 }
62
+ }
63
+ },
64
+ "subject": {
65
+ "type": "object",
66
+ "additionalProperties": false,
67
+ "required": ["kind", "id"],
68
+ "properties": {
69
+ "kind": { "type": "string", "minLength": 1, "maxLength": 100 },
70
+ "id": { "type": "string", "minLength": 1, "maxLength": 200 },
71
+ "uri": { "type": "string", "minLength": 1, "maxLength": 2048, "format": "uri-reference" }
72
+ }
73
+ },
74
+ "actor": {
75
+ "type": "object",
76
+ "additionalProperties": false,
77
+ "required": ["kind", "id"],
78
+ "properties": {
79
+ "kind": { "enum": ["agent", "human", "service", "model", "workflow", "system"] },
80
+ "id": { "type": "string", "minLength": 1, "maxLength": 200 },
81
+ "name": { "type": "string", "minLength": 1, "maxLength": 200 }
82
+ }
83
+ },
84
+ "project_mappings": {
85
+ "type": "object",
86
+ "additionalProperties": false,
87
+ "required": ["canonical_id", "external_ids"],
88
+ "properties": {
89
+ "canonical_id": { "type": "string", "minLength": 1, "maxLength": 200 },
90
+ "slug": { "type": "string", "minLength": 1, "maxLength": 200 },
91
+ "repository": { "type": "string", "minLength": 1, "maxLength": 2048, "format": "uri-reference" },
92
+ "workspace": { "type": "string", "minLength": 1, "maxLength": 2048 },
93
+ "external_ids": {
94
+ "type": "object",
95
+ "maxProperties": 16,
96
+ "propertyNames": { "minLength": 1 },
97
+ "additionalProperties": { "type": "string", "minLength": 1 }
98
+ }
99
+ }
100
+ },
101
+ "summary": { "type": "string", "minLength": 1, "maxLength": 512 },
102
+ "data": {
103
+ "type": "object",
104
+ "description": "Bounded to 32768 serialized UTF-8 bytes by the runtime validator.",
105
+ "x-max-utf8-bytes": 32768
106
+ },
107
+ "resource_refs": {
108
+ "type": "array",
109
+ "maxItems": 32,
110
+ "items": { "$ref": "#/$defs/resource_ref" }
111
+ },
112
+ "evidence_refs": {
113
+ "type": "array",
114
+ "maxItems": 32,
115
+ "items": { "$ref": "#/$defs/evidence_ref" }
116
+ },
117
+ "sensitivity": {
118
+ "type": "object",
119
+ "additionalProperties": false,
120
+ "required": ["classification", "contains_personal_data"],
121
+ "properties": {
122
+ "classification": { "enum": ["public", "internal", "confidential", "restricted"] },
123
+ "contains_personal_data": { "type": "boolean" }
124
+ }
125
+ },
126
+ "redaction": {
127
+ "type": "object",
128
+ "additionalProperties": false,
129
+ "required": ["state", "fields", "safe_for_logs"],
130
+ "properties": {
131
+ "state": { "enum": ["none", "partial", "full"] },
132
+ "fields": {
133
+ "type": "array",
134
+ "maxItems": 32,
135
+ "items": { "type": "string", "minLength": 1 }
136
+ },
137
+ "safe_for_logs": { "type": "boolean" }
138
+ }
139
+ },
140
+ "delivery": {
141
+ "type": "object",
142
+ "additionalProperties": false,
143
+ "required": ["intent", "mode", "targets", "agent_conversation_injection"],
144
+ "properties": {
145
+ "intent": { "enum": ["notification", "state_sync", "audit", "command"] },
146
+ "mode": { "enum": ["at_most_once", "at_least_once"] },
147
+ "targets": {
148
+ "type": "array",
149
+ "minItems": 1,
150
+ "maxItems": 16,
151
+ "items": { "type": "string", "minLength": 1 }
152
+ },
153
+ "agent_conversation_injection": {
154
+ "const": false,
155
+ "description": "Event text is untrusted data and must not be injected into agent conversations."
156
+ }
157
+ }
158
+ }
159
+ },
160
+ "$defs": {
161
+ "resource_ref": {
162
+ "type": "object",
163
+ "additionalProperties": false,
164
+ "required": ["kind", "id"],
165
+ "properties": {
166
+ "kind": { "type": "string", "minLength": 1, "maxLength": 100 },
167
+ "id": { "type": "string", "minLength": 1, "maxLength": 200 },
168
+ "uri": { "type": "string", "minLength": 1, "maxLength": 2048, "format": "uri-reference" },
169
+ "source_package": { "type": "string", "minLength": 1, "maxLength": 200 },
170
+ "external_id": { "type": "string", "minLength": 1, "maxLength": 200 }
171
+ }
172
+ },
173
+ "evidence_ref": {
174
+ "type": "object",
175
+ "additionalProperties": false,
176
+ "required": ["kind", "id", "uri", "redaction"],
177
+ "properties": {
178
+ "kind": { "type": "string", "minLength": 1, "maxLength": 100 },
179
+ "id": { "type": "string", "minLength": 1, "maxLength": 200 },
180
+ "uri": { "type": "string", "minLength": 1, "maxLength": 2048, "format": "uri-reference" },
181
+ "sha256": { "type": "string", "pattern": "^[a-fA-F0-9]{64}$" },
182
+ "redaction": { "enum": ["none", "partial", "full"] }
183
+ }
184
+ }
185
+ }
186
+ }
@@ -0,0 +1,130 @@
1
+ import type { EventData, EventEnvelope, EventInput, EventSeverity } from "./types.js";
2
+ /** Stable wire-profile identifier for cross-app events. */
3
+ export declare const APP_EVENT_V1_SCHEMA_VERSION: "hasna.app_event.v1";
4
+ export declare const APP_EVENT_V1_METADATA_KEY: "app_event";
5
+ export declare const APP_EVENT_V1_MAX_SUMMARY_LENGTH = 512;
6
+ export declare const APP_EVENT_V1_MAX_DATA_BYTES: number;
7
+ export declare const APP_EVENT_V1_MAX_REFS = 32;
8
+ export declare const APP_EVENT_V1_MAX_TARGETS = 16;
9
+ export type AppEventActorKind = "agent" | "human" | "service" | "model" | "workflow" | "system";
10
+ export type AppEventSensitivity = "public" | "internal" | "confidential" | "restricted";
11
+ export type AppEventRedactionState = "none" | "partial" | "full";
12
+ export type AppEventDeliveryIntent = "notification" | "state_sync" | "audit" | "command";
13
+ export type AppEventDeliveryMode = "at_most_once" | "at_least_once";
14
+ export interface AppEventSource {
15
+ app: string;
16
+ version: string;
17
+ machine: string;
18
+ }
19
+ export interface AppEventIdempotency {
20
+ dedupe_key: string;
21
+ replay_safe: boolean;
22
+ replay_of_event_id?: string;
23
+ }
24
+ export interface AppEventCorrelation {
25
+ correlation_id: string;
26
+ causation_id?: string;
27
+ trace_id?: string;
28
+ }
29
+ export interface AppEventSubject {
30
+ kind: string;
31
+ id: string;
32
+ uri?: string;
33
+ }
34
+ export interface AppEventActor {
35
+ kind: AppEventActorKind;
36
+ id: string;
37
+ name?: string;
38
+ }
39
+ export interface AppEventProjectMappings {
40
+ canonical_id: string;
41
+ slug?: string;
42
+ repository?: string;
43
+ workspace?: string;
44
+ external_ids: Record<string, string>;
45
+ }
46
+ /** Dependency-free structural mirror of a hasna.resource_ref pointer. */
47
+ export interface AppEventResourceRef {
48
+ kind: string;
49
+ id: string;
50
+ uri?: string;
51
+ source_package?: string;
52
+ external_id?: string;
53
+ }
54
+ /** Dependency-free structural mirror of a hasna.evidence_ref pointer. */
55
+ export interface AppEventEvidenceRef {
56
+ kind: string;
57
+ id: string;
58
+ uri: string;
59
+ sha256?: string;
60
+ redaction: AppEventRedactionState;
61
+ }
62
+ export interface AppEventSensitivityPolicy {
63
+ classification: AppEventSensitivity;
64
+ contains_personal_data: boolean;
65
+ }
66
+ export interface AppEventRedaction {
67
+ state: AppEventRedactionState;
68
+ fields: string[];
69
+ safe_for_logs: boolean;
70
+ }
71
+ export interface AppEventDelivery {
72
+ intent: AppEventDeliveryIntent;
73
+ mode: AppEventDeliveryMode;
74
+ targets: string[];
75
+ /** Untrusted event text is data, never an instruction to an agent. */
76
+ agent_conversation_injection: false;
77
+ }
78
+ /**
79
+ * Cross-app wire profile carried by the existing @hasna/events envelope.
80
+ * Use {@link appEventV1ToEventInput}; this profile does not define another bus.
81
+ */
82
+ export interface AppEventV1<TData extends EventData = EventData> {
83
+ event_id: string;
84
+ event_type: string;
85
+ schema_version: typeof APP_EVENT_V1_SCHEMA_VERSION;
86
+ source: AppEventSource;
87
+ occurred_at: string;
88
+ severity: EventSeverity;
89
+ idempotency: AppEventIdempotency;
90
+ correlation: AppEventCorrelation;
91
+ subject: AppEventSubject;
92
+ actor: AppEventActor;
93
+ project_mappings: AppEventProjectMappings;
94
+ summary: string;
95
+ data: TData;
96
+ resource_refs: AppEventResourceRef[];
97
+ evidence_refs: AppEventEvidenceRef[];
98
+ sensitivity: AppEventSensitivityPolicy;
99
+ redaction: AppEventRedaction;
100
+ delivery: AppEventDelivery;
101
+ }
102
+ export interface AppEventValidationIssue {
103
+ path: string;
104
+ message: string;
105
+ }
106
+ export type AppEventValidationResult = {
107
+ ok: true;
108
+ } | {
109
+ ok: false;
110
+ issues: AppEventValidationIssue[];
111
+ };
112
+ export declare class AppEventValidationError extends Error {
113
+ readonly issues: AppEventValidationIssue[];
114
+ constructor(issues: AppEventValidationIssue[]);
115
+ }
116
+ export declare class AppEventReplaySafetyError extends Error {
117
+ readonly eventId: string;
118
+ constructor(eventId: string);
119
+ }
120
+ export declare function validateAppEventV1(value: unknown): AppEventValidationResult;
121
+ export declare function assertAppEventV1<TData extends EventData = EventData>(value: unknown): asserts value is AppEventV1<TData>;
122
+ export declare function assertAppEventV1ReplaySafe(event: AppEventV1): void;
123
+ export declare function appEventV1ReplayIdentity(event: AppEventV1): {
124
+ eventId: string;
125
+ dedupeKey: string;
126
+ };
127
+ /** Map the profile onto the existing @hasna/events envelope without another transport or store. */
128
+ export declare function appEventV1ToEventInput<TData extends EventData>(event: AppEventV1<TData>): EventInput<TData>;
129
+ /** Reconstruct a profile from an @hasna/events envelope produced by the adapter. */
130
+ export declare function appEventV1FromEventEnvelope<TData extends EventData = EventData>(envelope: EventEnvelope<TData>): AppEventV1<TData>;
@@ -0,0 +1,30 @@
1
+ import type { EventEnvelope, EventInput } from "./types.js";
2
+ export interface DurableEventSpoolOptions {
3
+ dataDir: string;
4
+ }
5
+ export interface DurableSpoolEnqueueResult<TData extends Record<string, unknown> = Record<string, unknown>> {
6
+ event: EventEnvelope<TData>;
7
+ stored: boolean;
8
+ deduped: boolean;
9
+ }
10
+ export interface DurableSpoolRecoveryOptions {
11
+ olderThanMs?: number;
12
+ }
13
+ export interface DurableSpoolRecoveryResult {
14
+ recovered: number;
15
+ deduped: number;
16
+ cleaned: number;
17
+ }
18
+ export declare class DurableEventSpool {
19
+ readonly dataDir: string;
20
+ readonly inboxDir: string;
21
+ constructor(options: DurableEventSpoolOptions);
22
+ enqueue<TData extends Record<string, unknown>>(input: EventInput<TData>): Promise<DurableSpoolEnqueueResult<TData>>;
23
+ recover(options?: DurableSpoolRecoveryOptions): Promise<DurableSpoolRecoveryResult>;
24
+ close(): Promise<void>;
25
+ private pathFor;
26
+ private assertSameIdentity;
27
+ private ensureInbox;
28
+ private syncInbox;
29
+ private syncDirectory;
30
+ }
@@ -0,0 +1,27 @@
1
+ import { DurableEventsBroker, type DurableDrainResult, type DurableSpoolImportResult } from "./durable.js";
2
+ export interface DurableWorkerOptions {
3
+ broker: DurableEventsBroker;
4
+ signal: AbortSignal;
5
+ workerId?: string;
6
+ limit?: number;
7
+ leaseMs?: number;
8
+ debounceMs?: number;
9
+ reconcileMs?: number;
10
+ watchRestartMs?: number;
11
+ onCycle?: (cycle: DurableWorkerCycle) => void | Promise<void>;
12
+ }
13
+ export interface DurableWorkerCycle {
14
+ imported: DurableSpoolImportResult;
15
+ drained: DurableDrainResult;
16
+ }
17
+ export interface DurableWorkerResult {
18
+ workerId: string;
19
+ cycles: number;
20
+ imported: number;
21
+ deduped: number;
22
+ delivered: number;
23
+ retried: number;
24
+ dead: number;
25
+ lost: number;
26
+ }
27
+ export declare function runDurableWorker(options: DurableWorkerOptions): Promise<DurableWorkerResult>;