@oatscenter/trellis 0.100.0-rc.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.
- package/README.md +59 -0
- package/auth/authorization/client_context.d.ts +61 -0
- package/auth/authorization/client_context.js +266 -0
- package/auth/authorization/nats_registry.d.ts +41 -0
- package/auth/authorization/nats_registry.js +283 -0
- package/auth/authorization/provider_cache.d.ts +90 -0
- package/auth/authorization/provider_cache.js +783 -0
- package/auth/authorization/refresh.d.ts +46 -0
- package/auth/authorization/refresh.js +246 -0
- package/auth/authorization/types.d.ts +207 -0
- package/auth/authorization/types.js +60 -0
- package/auth/authorization_context.d.ts +11 -0
- package/auth/authorization_context.js +10 -0
- package/auth/browser/flow_types.d.ts +84 -0
- package/auth/browser/flow_types.js +70 -0
- package/auth/browser/portal.d.ts +21 -0
- package/auth/browser/portal.js +307 -0
- package/auth/browser/storage.d.ts +26 -0
- package/auth/browser/storage.js +224 -0
- package/auth/browser.d.ts +11 -0
- package/auth/browser.js +10 -0
- package/auth/browser_recovery.d.ts +13 -0
- package/auth/browser_recovery.js +38 -0
- package/auth/device_activation.d.ts +134 -0
- package/auth/device_activation.js +376 -0
- package/auth/http_error.d.ts +12 -0
- package/auth/http_error.js +32 -0
- package/auth/keys.d.ts +5 -0
- package/auth/keys.js +63 -0
- package/auth/mod.d.ts +16 -0
- package/auth/mod.js +16 -0
- package/auth/proof.d.ts +31 -0
- package/auth/proof.js +95 -0
- package/auth/protocol_wasm/trellis_protocol_wasm.d.ts +138 -0
- package/auth/protocol_wasm/trellis_protocol_wasm.js +605 -0
- package/auth/protocol_wasm/trellis_protocol_wasm_bg.wasm +0 -0
- package/auth/protocol_wasm/trellis_protocol_wasm_bytes.d.ts +1 -0
- package/auth/protocol_wasm/trellis_protocol_wasm_bytes.js +2 -0
- package/auth/protocol_wasm.d.ts +179 -0
- package/auth/protocol_wasm.js +133 -0
- package/auth/session_auth.d.ts +30 -0
- package/auth/session_auth.js +77 -0
- package/auth/session_proof.d.ts +53 -0
- package/auth/session_proof.js +43 -0
- package/auth/time.d.ts +6 -0
- package/auth/time.js +7 -0
- package/auth/trellis_id.d.ts +1 -0
- package/auth/trellis_id.js +5 -0
- package/auth/utils.d.ts +10 -0
- package/auth/utils.js +69 -0
- package/auth.d.ts +1 -0
- package/auth.js +1 -0
- package/caller.d.ts +111 -0
- package/caller.js +85 -0
- package/client.d.ts +14 -0
- package/client.js +1 -0
- package/client_connect.d.ts +143 -0
- package/client_connect.js +1097 -0
- package/codec.d.ts +13 -0
- package/codec.js +192 -0
- package/connection.d.ts +107 -0
- package/connection.js +396 -0
- package/device/activation.d.ts +42 -0
- package/device/activation.js +319 -0
- package/device.d.ts +80 -0
- package/device.js +687 -0
- package/env.d.ts +2 -0
- package/env.js +10 -0
- package/errors/AuthError.d.ts +30 -0
- package/errors/AuthError.js +34 -0
- package/errors/KVError.d.ts +30 -0
- package/errors/KVError.js +36 -0
- package/errors/OperationLifecycleError.d.ts +110 -0
- package/errors/OperationLifecycleError.js +142 -0
- package/errors/RemoteError.d.ts +61 -0
- package/errors/RemoteError.js +72 -0
- package/errors/SchemaValidationError.d.ts +48 -0
- package/errors/SchemaValidationError.js +49 -0
- package/errors/StoreError.d.ts +21 -0
- package/errors/StoreError.js +31 -0
- package/errors/TransferError.d.ts +21 -0
- package/errors/TransferError.js +31 -0
- package/errors/TransportError.d.ts +29 -0
- package/errors/TransportError.js +33 -0
- package/errors/TrellisError.d.ts +15 -0
- package/errors/TrellisError.js +15 -0
- package/errors/ValidationError.d.ts +50 -0
- package/errors/ValidationError.js +59 -0
- package/errors/index.d.ts +254 -0
- package/errors/index.js +238 -0
- package/generated.d.ts +4 -0
- package/generated.js +3 -0
- package/generated_support.d.ts +120 -0
- package/generated_support.js +359 -0
- package/globals.d.ts +9 -0
- package/globals.js +16 -0
- package/health_transport.d.ts +18 -0
- package/health_transport.js +32 -0
- package/helpers.d.ts +11 -0
- package/helpers.js +53 -0
- package/index.d.ts +2 -0
- package/index.js +2 -0
- package/internal_sdk/generated/apis/auth/mod.d.ts +805 -0
- package/internal_sdk/generated/apis/auth/mod.js +958 -0
- package/internal_sdk/generated/apis/core/mod.d.ts +79 -0
- package/internal_sdk/generated/apis/core/mod.js +93 -0
- package/internal_sdk/generated/apis/events/mod.d.ts +224 -0
- package/internal_sdk/generated/apis/events/mod.js +313 -0
- package/internal_sdk/generated/apis/health/mod.d.ts +106 -0
- package/internal_sdk/generated/apis/health/mod.js +132 -0
- package/internal_sdk/generated/apis/index.d.ts +7 -0
- package/internal_sdk/generated/apis/index.js +8 -0
- package/internal_sdk/generated/apis/jobs/mod.d.ts +176 -0
- package/internal_sdk/generated/apis/jobs/mod.js +209 -0
- package/internal_sdk/generated/apis/state/mod.d.ts +104 -0
- package/internal_sdk/generated/apis/state/mod.js +139 -0
- package/internal_sdk/generated/index.d.ts +4 -0
- package/internal_sdk/generated/index.js +5 -0
- package/internal_sdk/generated/package.json +18 -0
- package/internal_sdk/generated/participants/cli/mod.d.ts +402 -0
- package/internal_sdk/generated/participants/cli/mod.js +460 -0
- package/internal_sdk/generated/participants/cli/types.d.ts +2 -0
- package/internal_sdk/generated/participants/cli/types.js +3 -0
- package/internal_sdk/generated/participants/console/mod.d.ts +489 -0
- package/internal_sdk/generated/participants/console/mod.js +579 -0
- package/internal_sdk/generated/participants/console/types.d.ts +2 -0
- package/internal_sdk/generated/participants/console/types.js +3 -0
- package/internal_sdk/generated/participants/eventsRuntime/mod.d.ts +64 -0
- package/internal_sdk/generated/participants/eventsRuntime/mod.js +42 -0
- package/internal_sdk/generated/participants/eventsRuntime/types.d.ts +2 -0
- package/internal_sdk/generated/participants/eventsRuntime/types.js +3 -0
- package/internal_sdk/generated/participants/healthRuntime/mod.d.ts +58 -0
- package/internal_sdk/generated/participants/healthRuntime/mod.js +36 -0
- package/internal_sdk/generated/participants/healthRuntime/types.d.ts +2 -0
- package/internal_sdk/generated/participants/healthRuntime/types.js +3 -0
- package/internal_sdk/generated/participants/index.d.ts +8 -0
- package/internal_sdk/generated/participants/index.js +9 -0
- package/internal_sdk/generated/participants/jobsRuntime/mod.d.ts +64 -0
- package/internal_sdk/generated/participants/jobsRuntime/mod.js +42 -0
- package/internal_sdk/generated/participants/jobsRuntime/types.d.ts +2 -0
- package/internal_sdk/generated/participants/jobsRuntime/types.js +3 -0
- package/internal_sdk/generated/participants/platform/mod.d.ts +164 -0
- package/internal_sdk/generated/participants/platform/mod.js +149 -0
- package/internal_sdk/generated/participants/platform/types.d.ts +7 -0
- package/internal_sdk/generated/participants/platform/types.js +5 -0
- package/internal_sdk/generated/participants/portal/mod.d.ts +131 -0
- package/internal_sdk/generated/participants/portal/mod.js +109 -0
- package/internal_sdk/generated/participants/portal/types.d.ts +2 -0
- package/internal_sdk/generated/participants/portal/types.js +3 -0
- package/internal_sdk/generated/types/_internal/p0.d.ts +13511 -0
- package/internal_sdk/generated/types/_internal/p0.js +6105 -0
- package/internal_sdk/generated/types/index.d.ts +2951 -0
- package/internal_sdk/generated/types/index.js +1477 -0
- package/jobs.d.ts +309 -0
- package/jobs.js +389 -0
- package/kv.d.ts +85 -0
- package/kv.js +330 -0
- package/operations.d.ts +189 -0
- package/operations.js +847 -0
- package/package.json +73 -0
- package/pagination.d.ts +25 -0
- package/pagination.js +117 -0
- package/participant.d.ts +6 -0
- package/participant.js +6 -0
- package/participant_runtime/api.d.ts +131 -0
- package/participant_runtime/api.js +42 -0
- package/participant_runtime/json.d.ts +16 -0
- package/participant_runtime/json.js +193 -0
- package/participant_runtime/metadata.d.ts +34 -0
- package/participant_runtime/metadata.js +4 -0
- package/participant_runtime/participant.d.ts +200 -0
- package/participant_runtime/participant.js +330 -0
- package/participant_runtime/schemas.d.ts +347 -0
- package/participant_runtime/schemas.js +211 -0
- package/participant_runtime/surface_names.d.ts +16 -0
- package/participant_runtime/surface_names.js +34 -0
- package/portable.d.ts +30 -0
- package/portable.js +14 -0
- package/provider.d.ts +69 -0
- package/provider.js +68 -0
- package/runtime_transport.d.ts +25 -0
- package/runtime_transport.js +48 -0
- package/service/mod.d.ts +14 -0
- package/service/mod.js +13 -0
- package/service/outbox_inbox.d.ts +259 -0
- package/service/outbox_inbox.js +908 -0
- package/service/runtime/bootstrap.d.ts +56 -0
- package/service/runtime/bootstrap.js +226 -0
- package/service/runtime/core.d.ts +46 -0
- package/service/runtime/core.js +1747 -0
- package/service/runtime/health.d.ts +97 -0
- package/service/runtime/health.js +153 -0
- package/service/runtime/health_schemas.d.ts +23 -0
- package/service/runtime/health_schemas.js +20 -0
- package/service/runtime/internal_jobs/active-job.d.ts +40 -0
- package/service/runtime/internal_jobs/active-job.js +91 -0
- package/service/runtime/internal_jobs/bindings.d.ts +40 -0
- package/service/runtime/internal_jobs/bindings.js +1 -0
- package/service/runtime/internal_jobs/cancellation-registry.d.ts +13 -0
- package/service/runtime/internal_jobs/cancellation-registry.js +55 -0
- package/service/runtime/internal_jobs/heartbeat.d.ts +33 -0
- package/service/runtime/internal_jobs/heartbeat.js +65 -0
- package/service/runtime/internal_jobs/job-manager.d.ts +126 -0
- package/service/runtime/internal_jobs/job-manager.js +821 -0
- package/service/runtime/internal_jobs/key-coordinator.d.ts +280 -0
- package/service/runtime/internal_jobs/key-coordinator.js +747 -0
- package/service/runtime/internal_jobs/projection.d.ts +3 -0
- package/service/runtime/internal_jobs/projection.js +42 -0
- package/service/runtime/internal_jobs/runtime-worker.d.ts +126 -0
- package/service/runtime/internal_jobs/runtime-worker.js +454 -0
- package/service/runtime/internal_jobs/types.d.ts +246 -0
- package/service/runtime/internal_jobs/types.js +163 -0
- package/service/runtime/logger.d.ts +2 -0
- package/service/runtime/logger.js +7 -0
- package/service/runtime/runtime.d.ts +16 -0
- package/service/runtime/runtime.js +1 -0
- package/service/runtime/service.d.ts +372 -0
- package/service/runtime/service.js +1896 -0
- package/service/runtime/transfer/download.d.ts +27 -0
- package/service/runtime/transfer/download.js +1 -0
- package/service/runtime/transfer/protocol.d.ts +15 -0
- package/service/runtime/transfer/protocol.js +46 -0
- package/service/runtime/transfer/queue.d.ts +18 -0
- package/service/runtime/transfer/queue.js +136 -0
- package/service/runtime/transfer/upload.d.ts +40 -0
- package/service/runtime/transfer/upload.js +27 -0
- package/service/runtime/transfer.d.ts +62 -0
- package/service/runtime/transfer.js +763 -0
- package/session.d.ts +862 -0
- package/session.js +3407 -0
- package/store.d.ts +71 -0
- package/store.js +412 -0
- package/store_entry.d.ts +20 -0
- package/store_entry.js +75 -0
- package/tasks.d.ts +10 -0
- package/tasks.js +28 -0
- package/telemetry/carrier.d.ts +8 -0
- package/telemetry/carrier.js +20 -0
- package/telemetry/core.d.ts +7 -0
- package/telemetry/core.js +14 -0
- package/telemetry/env.d.ts +2 -0
- package/telemetry/env.js +10 -0
- package/telemetry/init.d.ts +2 -0
- package/telemetry/init.js +7 -0
- package/telemetry/metrics.d.ts +81 -0
- package/telemetry/metrics.js +267 -0
- package/telemetry/mod.d.ts +13 -0
- package/telemetry/mod.js +8 -0
- package/telemetry/nats.d.ts +6 -0
- package/telemetry/nats.js +6 -0
- package/telemetry/result.d.ts +1 -0
- package/telemetry/result.js +18 -0
- package/telemetry/runtime.d.ts +1 -0
- package/telemetry/runtime.js +141 -0
- package/telemetry/trace.d.ts +4 -0
- package/telemetry/trace.js +26 -0
- package/telemetry/trellis.d.ts +1 -0
- package/telemetry/trellis.js +1 -0
- package/telemetry.d.ts +1 -0
- package/telemetry.js +1 -0
- package/transfer.d.ts +112 -0
- package/transfer.js +525 -0
- package/transfer_protocol.d.ts +1 -0
- package/transfer_protocol.js +13 -0
package/connection.js
ADDED
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
import { logger as noopLogger } from "./globals.js";
|
|
2
|
+
const EMPTY_AVAILABILITY = Object.freeze({
|
|
3
|
+
capabilities: Object.freeze({}),
|
|
4
|
+
resources: Object.freeze({}),
|
|
5
|
+
});
|
|
6
|
+
const installAvailability = Symbol("installAvailability");
|
|
7
|
+
function immutableAvailability(availability) {
|
|
8
|
+
return Object.freeze({
|
|
9
|
+
capabilities: Object.freeze({ ...availability.capabilities }),
|
|
10
|
+
resources: Object.freeze({ ...availability.resources }),
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Framework-neutral Trellis connection lifecycle handle.
|
|
15
|
+
*
|
|
16
|
+
* The class stores the latest transport-neutral status, delivers it immediately
|
|
17
|
+
* to subscribers, and owns lifecycle cleanup without exposing raw transport
|
|
18
|
+
* handles to framework adapters.
|
|
19
|
+
*/
|
|
20
|
+
export class TrellisConnection {
|
|
21
|
+
#status;
|
|
22
|
+
#listeners = new Set();
|
|
23
|
+
#availability;
|
|
24
|
+
#availabilityListeners = new Set();
|
|
25
|
+
#closeTransport;
|
|
26
|
+
#stopObserving;
|
|
27
|
+
#observationStopped = Promise.resolve();
|
|
28
|
+
#observationFailure;
|
|
29
|
+
#log;
|
|
30
|
+
#stopped = false;
|
|
31
|
+
/** Creates a Trellis connection lifecycle handle. */
|
|
32
|
+
constructor(options) {
|
|
33
|
+
this.#status = options.initialStatus ??
|
|
34
|
+
createStatus(options.kind, "connected");
|
|
35
|
+
this.#closeTransport = options.close ?? (async () => { });
|
|
36
|
+
this.#stopObserving = options.stopObserving ?? (async () => { });
|
|
37
|
+
this.#log = options.log === false ? noopLogger : options.log ?? noopLogger;
|
|
38
|
+
this.#availability = options.availability
|
|
39
|
+
? immutableAvailability(options.availability)
|
|
40
|
+
: EMPTY_AVAILABILITY;
|
|
41
|
+
}
|
|
42
|
+
/** Returns the latest observed connection status. */
|
|
43
|
+
get status() {
|
|
44
|
+
return this.#status;
|
|
45
|
+
}
|
|
46
|
+
/** Returns the current immutable installed availability snapshot. */
|
|
47
|
+
availability() {
|
|
48
|
+
return this.#availability;
|
|
49
|
+
}
|
|
50
|
+
/** Yields the current availability and each subsequent installed replacement. */
|
|
51
|
+
watchAvailability() {
|
|
52
|
+
const availabilityListeners = this.#availabilityListeners;
|
|
53
|
+
const initialAvailability = this.#availability;
|
|
54
|
+
return {
|
|
55
|
+
async *[Symbol.asyncIterator]() {
|
|
56
|
+
const pending = [initialAvailability];
|
|
57
|
+
let wake;
|
|
58
|
+
const listener = (availability) => {
|
|
59
|
+
pending.push(availability);
|
|
60
|
+
wake?.();
|
|
61
|
+
wake = undefined;
|
|
62
|
+
};
|
|
63
|
+
availabilityListeners.add(listener);
|
|
64
|
+
try {
|
|
65
|
+
while (true) {
|
|
66
|
+
if (pending.length === 0) {
|
|
67
|
+
await new Promise((resolve) => {
|
|
68
|
+
wake = resolve;
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
const next = pending.shift();
|
|
72
|
+
if (next)
|
|
73
|
+
yield next;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
availabilityListeners.delete(listener);
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
[installAvailability](availability) {
|
|
83
|
+
if (availability === this.#availability)
|
|
84
|
+
return;
|
|
85
|
+
this.#availability = immutableAvailability(availability);
|
|
86
|
+
for (const listener of this.#availabilityListeners) {
|
|
87
|
+
listener(this.#availability);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Subscribes to status changes and immediately delivers the current status.
|
|
92
|
+
*
|
|
93
|
+
* The returned function removes the listener. Calling it more than once is
|
|
94
|
+
* safe.
|
|
95
|
+
*/
|
|
96
|
+
subscribe(listener) {
|
|
97
|
+
this.#listeners.add(listener);
|
|
98
|
+
listener(this.#status);
|
|
99
|
+
return () => {
|
|
100
|
+
this.#listeners.delete(listener);
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/** Stops status observation without closing the underlying transport. */
|
|
104
|
+
stopObserving() {
|
|
105
|
+
if (this.#stopped) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
this.#stopped = true;
|
|
109
|
+
this.#observationStopped = Promise.resolve().then(() => this.#stopObserving()).catch((error) => {
|
|
110
|
+
this.#observationFailure = error;
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
/** Closes the underlying transport and publishes a terminal closed status. */
|
|
114
|
+
async close() {
|
|
115
|
+
this.stopObserving();
|
|
116
|
+
try {
|
|
117
|
+
await this.#closeTransport();
|
|
118
|
+
await this.#observationStopped;
|
|
119
|
+
if (this.#observationFailure !== undefined) {
|
|
120
|
+
throw this.#observationFailure;
|
|
121
|
+
}
|
|
122
|
+
this.setStatus(createStatus(this.#status.kind, "closed"));
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
this.setStatus(createStatus(this.#status.kind, "error", { error }));
|
|
126
|
+
throw error;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/** Publishes a new status to all active listeners. */
|
|
130
|
+
setStatus(status) {
|
|
131
|
+
if (this.#stopped && status.phase !== "closed" && status.phase !== "error") {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
this.#status = status;
|
|
135
|
+
this.#log.debug({
|
|
136
|
+
kind: status.kind,
|
|
137
|
+
phase: status.phase,
|
|
138
|
+
transport: status.transport,
|
|
139
|
+
}, "Trellis connection status changed");
|
|
140
|
+
for (const listener of this.#listeners) {
|
|
141
|
+
listener(status);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/** @internal Installs one immutable availability snapshot after bootstrap verification. */
|
|
146
|
+
export function installConnectionAvailability(connection, availability) {
|
|
147
|
+
connection[installAvailability](availability);
|
|
148
|
+
}
|
|
149
|
+
/** Observes a narrow transport status stream as a Trellis connection lifecycle. */
|
|
150
|
+
export function observeTrellisConnection(options) {
|
|
151
|
+
let stopped = false;
|
|
152
|
+
const statusStream = options.transport.status;
|
|
153
|
+
const statusIterator = typeof statusStream === "function"
|
|
154
|
+
? statusStream.call(options.transport)[Symbol.asyncIterator]()
|
|
155
|
+
: undefined;
|
|
156
|
+
let statusTask;
|
|
157
|
+
let closedFailure;
|
|
158
|
+
let closedTask = Promise.resolve();
|
|
159
|
+
const connection = new TrellisConnection({
|
|
160
|
+
kind: options.kind,
|
|
161
|
+
availability: options.availability,
|
|
162
|
+
close: async () => {
|
|
163
|
+
const alreadyClosed = options.transport.isClosed?.() ?? false;
|
|
164
|
+
await options.transport.close();
|
|
165
|
+
await statusIterator?.return?.();
|
|
166
|
+
await statusTask;
|
|
167
|
+
await closedTask;
|
|
168
|
+
if (!alreadyClosed && closedFailure !== undefined)
|
|
169
|
+
throw closedFailure;
|
|
170
|
+
},
|
|
171
|
+
stopObserving: () => {
|
|
172
|
+
stopped = true;
|
|
173
|
+
},
|
|
174
|
+
log: options.log,
|
|
175
|
+
});
|
|
176
|
+
const baseTransport = createTransportMetadata(options.transport, options.transportName);
|
|
177
|
+
if (statusIterator) {
|
|
178
|
+
statusTask = (async () => {
|
|
179
|
+
try {
|
|
180
|
+
while (true) {
|
|
181
|
+
const next = await statusIterator.next();
|
|
182
|
+
if (next.done)
|
|
183
|
+
return;
|
|
184
|
+
const event = next.value;
|
|
185
|
+
options.onTransportEvent?.(event);
|
|
186
|
+
if (stopped) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const status = statusFromTransportEvent(options.kind, event, baseTransport);
|
|
190
|
+
if (status) {
|
|
191
|
+
logTransportLifecycleEvent(options, event);
|
|
192
|
+
connection.setStatus(status);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
if (!stopped) {
|
|
198
|
+
logTransportStatusWatcherFailure(options, error);
|
|
199
|
+
connection.setStatus(createStatus(options.kind, "error", {
|
|
200
|
+
...baseTransport,
|
|
201
|
+
error,
|
|
202
|
+
}));
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
})();
|
|
206
|
+
}
|
|
207
|
+
closedTask = options.transport.closed().then((closedError) => {
|
|
208
|
+
if (closedError instanceof Error)
|
|
209
|
+
closedFailure = closedError;
|
|
210
|
+
if (stopped)
|
|
211
|
+
return;
|
|
212
|
+
if (closedError instanceof Error) {
|
|
213
|
+
logTransportClosed(options, closedError);
|
|
214
|
+
connection.setStatus(createStatus(options.kind, "error", {
|
|
215
|
+
...baseTransport,
|
|
216
|
+
error: closedError,
|
|
217
|
+
}));
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
logTransportClosed(options);
|
|
221
|
+
connection.setStatus(createStatus(options.kind, "closed", baseTransport));
|
|
222
|
+
}, (error) => {
|
|
223
|
+
closedFailure = error;
|
|
224
|
+
if (stopped)
|
|
225
|
+
return;
|
|
226
|
+
logTransportClosed(options, error);
|
|
227
|
+
connection.setStatus(createStatus(options.kind, "error", {
|
|
228
|
+
...baseTransport,
|
|
229
|
+
error,
|
|
230
|
+
}));
|
|
231
|
+
});
|
|
232
|
+
return connection;
|
|
233
|
+
}
|
|
234
|
+
/** Observes a NATS connection without exposing the raw NATS handle publicly. */
|
|
235
|
+
export function observeNatsTrellisConnection(options) {
|
|
236
|
+
return observeTrellisConnection({
|
|
237
|
+
kind: options.kind,
|
|
238
|
+
transport: options.nc,
|
|
239
|
+
transportName: "nats",
|
|
240
|
+
log: options.log,
|
|
241
|
+
lifecycleLog: options.lifecycleLog,
|
|
242
|
+
availability: options.availability,
|
|
243
|
+
onTransportEvent: options.onTransportEvent,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
function lifecycleLabel(kind) {
|
|
247
|
+
switch (kind) {
|
|
248
|
+
case "client":
|
|
249
|
+
return "Client";
|
|
250
|
+
case "device":
|
|
251
|
+
return "Device";
|
|
252
|
+
case "service":
|
|
253
|
+
return "Service";
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function normalizeTransportError(error) {
|
|
257
|
+
const record = error;
|
|
258
|
+
return {
|
|
259
|
+
name: error.name,
|
|
260
|
+
message: error.message,
|
|
261
|
+
...(typeof record.operation === "string"
|
|
262
|
+
? { operation: record.operation }
|
|
263
|
+
: {}),
|
|
264
|
+
...(typeof record.subject === "string" ? { subject: record.subject } : {}),
|
|
265
|
+
...(typeof record.queue === "string" ? { queue: record.queue } : {}),
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
function normalizeTransportStatus(status) {
|
|
269
|
+
if (!status || typeof status !== "object") {
|
|
270
|
+
return { status };
|
|
271
|
+
}
|
|
272
|
+
const record = status;
|
|
273
|
+
return {
|
|
274
|
+
...(typeof record.type === "string" ? { type: record.type } : {}),
|
|
275
|
+
...(record.error instanceof Error
|
|
276
|
+
? { error: normalizeTransportError(record.error) }
|
|
277
|
+
: {}),
|
|
278
|
+
...(typeof record.data === "string" ? { data: record.data } : {}),
|
|
279
|
+
...(record.data && typeof record.data === "object"
|
|
280
|
+
? { data: record.data }
|
|
281
|
+
: {}),
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
function getNatsLifecycleLog(kind, event) {
|
|
285
|
+
if (!event || typeof event !== "object") {
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
const label = lifecycleLabel(kind);
|
|
289
|
+
switch (event.type) {
|
|
290
|
+
case "disconnect":
|
|
291
|
+
return { level: "warn", message: `${label} disconnected from NATS` };
|
|
292
|
+
case "reconnecting":
|
|
293
|
+
return { level: "warn", message: `${label} attempting NATS reconnect` };
|
|
294
|
+
case "forceReconnect":
|
|
295
|
+
return { level: "warn", message: `${label} forcing NATS reconnect` };
|
|
296
|
+
case "reconnect":
|
|
297
|
+
return { level: "info", message: `${label} reconnected to NATS` };
|
|
298
|
+
case "staleConnection":
|
|
299
|
+
return {
|
|
300
|
+
level: "warn",
|
|
301
|
+
message: `${label} NATS connection became stale`,
|
|
302
|
+
};
|
|
303
|
+
case "error":
|
|
304
|
+
return { level: "error", message: `${label} NATS error` };
|
|
305
|
+
default:
|
|
306
|
+
return null;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
function logTransportLifecycleEvent(options, event) {
|
|
310
|
+
if (!options.lifecycleLog) {
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
const lifecycleLog = getNatsLifecycleLog(options.kind, event);
|
|
314
|
+
if (!lifecycleLog) {
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
options.lifecycleLog.log[lifecycleLog.level]({
|
|
318
|
+
...options.lifecycleLog.context,
|
|
319
|
+
connection: normalizeTransportStatus(event),
|
|
320
|
+
}, lifecycleLog.message);
|
|
321
|
+
}
|
|
322
|
+
function logTransportStatusWatcherFailure(options, error) {
|
|
323
|
+
if (!options.lifecycleLog) {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
options.lifecycleLog.log.warn({ ...options.lifecycleLog.context, error }, `${lifecycleLabel(options.kind)} NATS status watcher failed`);
|
|
327
|
+
}
|
|
328
|
+
function logTransportClosed(options, error) {
|
|
329
|
+
if (!options.lifecycleLog) {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
const label = lifecycleLabel(options.kind);
|
|
333
|
+
if (error) {
|
|
334
|
+
options.lifecycleLog.log.error({ ...options.lifecycleLog.context, error }, `${label} NATS connection closed with error`);
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
options.lifecycleLog.log.warn(options.lifecycleLog.context, `${label} NATS connection closed`);
|
|
338
|
+
}
|
|
339
|
+
function createStatus(kind, phase, transport) {
|
|
340
|
+
return {
|
|
341
|
+
kind,
|
|
342
|
+
phase,
|
|
343
|
+
observedAt: new Date(),
|
|
344
|
+
...(transport ? { transport } : {}),
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
function createTransportMetadata(transport, name) {
|
|
348
|
+
return {
|
|
349
|
+
...(name ? { name } : {}),
|
|
350
|
+
...(typeof transport.getServer === "function"
|
|
351
|
+
? { server: transport.getServer() }
|
|
352
|
+
: {}),
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
function statusFromTransportEvent(kind, event, baseTransport) {
|
|
356
|
+
const transportEvent = normalizeTransportEvent(event);
|
|
357
|
+
if (!transportEvent.type) {
|
|
358
|
+
return null;
|
|
359
|
+
}
|
|
360
|
+
const transport = {
|
|
361
|
+
...baseTransport,
|
|
362
|
+
event: transportEvent.type,
|
|
363
|
+
...(transportEvent.data === undefined ? {} : { data: transportEvent.data }),
|
|
364
|
+
...(transportEvent.error === undefined
|
|
365
|
+
? {}
|
|
366
|
+
: { error: transportEvent.error }),
|
|
367
|
+
};
|
|
368
|
+
switch (transportEvent.type) {
|
|
369
|
+
case "disconnect":
|
|
370
|
+
case "disconnected":
|
|
371
|
+
return createStatus(kind, "disconnected", transport);
|
|
372
|
+
case "reconnecting":
|
|
373
|
+
case "forceReconnect":
|
|
374
|
+
case "staleConnection":
|
|
375
|
+
return createStatus(kind, "reconnecting", transport);
|
|
376
|
+
case "reconnect":
|
|
377
|
+
return createStatus(kind, "connected", transport);
|
|
378
|
+
case "error":
|
|
379
|
+
return createStatus(kind, "error", transport);
|
|
380
|
+
case "closed":
|
|
381
|
+
return createStatus(kind, "closed", transport);
|
|
382
|
+
default:
|
|
383
|
+
return null;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
function normalizeTransportEvent(event) {
|
|
387
|
+
if (!event || typeof event !== "object") {
|
|
388
|
+
return {};
|
|
389
|
+
}
|
|
390
|
+
const record = event;
|
|
391
|
+
return {
|
|
392
|
+
...(typeof record.type === "string" ? { type: record.type } : {}),
|
|
393
|
+
...("data" in record ? { data: record.data } : {}),
|
|
394
|
+
...("error" in record ? { error: record.error } : {}),
|
|
395
|
+
};
|
|
396
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { TrellisDeviceActivationArgs } from "../device.ts";
|
|
2
|
+
/**
|
|
3
|
+
* Options for the native device activation status helper.
|
|
4
|
+
*/
|
|
5
|
+
export type CheckDeviceActivationArgs<TContract extends TrellisDeviceActivationArgs["participant"] = TrellisDeviceActivationArgs["participant"]> = TrellisDeviceActivationArgs<TContract> & {
|
|
6
|
+
stateDir?: string;
|
|
7
|
+
statePath?: string;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Activation status for a device that is already ready to connect.
|
|
11
|
+
*/
|
|
12
|
+
export type TrellisDeviceActivatedStatus = {
|
|
13
|
+
status: "activated";
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Activation status for a device that cannot proceed yet.
|
|
17
|
+
*/
|
|
18
|
+
export type TrellisDeviceNotReadyStatus = {
|
|
19
|
+
status: "not_ready";
|
|
20
|
+
reason: string;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Activation status for a device that still needs activation.
|
|
24
|
+
*/
|
|
25
|
+
export type TrellisDeviceActivationRequiredStatus = {
|
|
26
|
+
status: "activation_required";
|
|
27
|
+
activationUrl: string;
|
|
28
|
+
/** Device-local code the activating user must confirm in the portal. */
|
|
29
|
+
confirmationCode: string;
|
|
30
|
+
waitForOnlineApproval(opts?: {
|
|
31
|
+
signal?: AbortSignal;
|
|
32
|
+
}): Promise<TrellisDeviceActivatedStatus>;
|
|
33
|
+
acceptConfirmationCode(code: string): Promise<TrellisDeviceActivatedStatus>;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Caller-facing activation status union for native device runtimes.
|
|
37
|
+
*/
|
|
38
|
+
export type TrellisDeviceActivationStatus = TrellisDeviceActivatedStatus | TrellisDeviceNotReadyStatus | TrellisDeviceActivationRequiredStatus;
|
|
39
|
+
/**
|
|
40
|
+
* Reports native device activation status and hides local activation persistence details.
|
|
41
|
+
*/
|
|
42
|
+
export declare function checkDeviceActivation<TContract extends TrellisDeviceActivationArgs["participant"]>(args: CheckDeviceActivationArgs<TContract>): Promise<TrellisDeviceActivationStatus>;
|