@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/store.d.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { NatsConnection } from "@nats-io/nats-core/internal";
|
|
2
|
+
import { AsyncResult } from "@oatscenter/result";
|
|
3
|
+
import { StoreError } from "./errors/index.ts";
|
|
4
|
+
import { TypedStoreEntry } from "./store_entry.ts";
|
|
5
|
+
export { TypedStoreEntry } from "./store_entry.ts";
|
|
6
|
+
export type StoreBody = Uint8Array | ReadableStream<Uint8Array> | AsyncIterable<Uint8Array>;
|
|
7
|
+
export type StoreWaitOptions = {
|
|
8
|
+
timeoutMs?: number;
|
|
9
|
+
pollIntervalMs?: number;
|
|
10
|
+
signal?: AbortSignal;
|
|
11
|
+
};
|
|
12
|
+
export type StoreOpenOptions = {
|
|
13
|
+
ttlMs?: number;
|
|
14
|
+
maxObjectBytes?: number;
|
|
15
|
+
maxTotalBytes?: number;
|
|
16
|
+
bindOnly?: boolean;
|
|
17
|
+
isCurrent?: () => boolean;
|
|
18
|
+
};
|
|
19
|
+
export type StorePutOptions = {
|
|
20
|
+
contentType?: string;
|
|
21
|
+
metadata?: Record<string, string>;
|
|
22
|
+
};
|
|
23
|
+
/** Explicit bounded query for listing object metadata in a typed store. */
|
|
24
|
+
export type StoreListOptions = {
|
|
25
|
+
prefix?: string;
|
|
26
|
+
cursor?: string;
|
|
27
|
+
limit?: number;
|
|
28
|
+
};
|
|
29
|
+
/** One key-sorted page of object metadata and its opaque continuation. */
|
|
30
|
+
export type StoreListPage = {
|
|
31
|
+
entries: StoreInfo[];
|
|
32
|
+
nextCursor?: string;
|
|
33
|
+
};
|
|
34
|
+
export type StoreInfo = {
|
|
35
|
+
key: string;
|
|
36
|
+
size: number;
|
|
37
|
+
updatedAt: string;
|
|
38
|
+
digest?: string;
|
|
39
|
+
contentType?: string;
|
|
40
|
+
metadata: Record<string, string>;
|
|
41
|
+
};
|
|
42
|
+
export type StoreStatus = {
|
|
43
|
+
size: number;
|
|
44
|
+
sealed: boolean;
|
|
45
|
+
ttlMs: number;
|
|
46
|
+
maxObjectBytes?: number;
|
|
47
|
+
maxTotalBytes?: number;
|
|
48
|
+
};
|
|
49
|
+
type ExistingStoreStatus = {
|
|
50
|
+
ttl: number;
|
|
51
|
+
};
|
|
52
|
+
/** Verifies that an existing physical store matches its effective binding. */
|
|
53
|
+
export declare function ensureExistingStoreOptions(store: {
|
|
54
|
+
status(): Promise<ExistingStoreStatus>;
|
|
55
|
+
}, name: string, options: StoreOpenOptions): Promise<void>;
|
|
56
|
+
export declare class TypedStore {
|
|
57
|
+
#private;
|
|
58
|
+
private constructor();
|
|
59
|
+
static open(nats: NatsConnection, name: string, options?: StoreOpenOptions): AsyncResult<TypedStore, StoreError>;
|
|
60
|
+
create(key: string, body: StoreBody, options?: StorePutOptions): AsyncResult<void, StoreError>;
|
|
61
|
+
put(key: string, body: StoreBody, options?: StorePutOptions): AsyncResult<void, StoreError>;
|
|
62
|
+
get(key: string): AsyncResult<TypedStoreEntry, StoreError>;
|
|
63
|
+
/**
|
|
64
|
+
* Waits for an object key to appear in the store and returns the resulting entry.
|
|
65
|
+
*/
|
|
66
|
+
waitFor(key: string, options?: StoreWaitOptions): AsyncResult<TypedStoreEntry, StoreError>;
|
|
67
|
+
delete(key: string): AsyncResult<void, StoreError>;
|
|
68
|
+
list(opts?: StoreListOptions): AsyncResult<StoreListPage, StoreError>;
|
|
69
|
+
status(): AsyncResult<StoreStatus, StoreError>;
|
|
70
|
+
}
|
|
71
|
+
export declare function bytesFromStoreStream(stream: ReadableStream<Uint8Array>): Promise<Uint8Array>;
|
package/store.js
ADDED
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
import { Objm, } from "@nats-io/obj";
|
|
2
|
+
import { AsyncResult, Result, } from "@oatscenter/result";
|
|
3
|
+
import { StoreError } from "./errors/index.js";
|
|
4
|
+
import { decodePaginationCursor, encodePaginationCursor, paginationQueryDigest, } from "./auth/protocol_wasm.js";
|
|
5
|
+
import { TypedStoreEntry } from "./store_entry.js";
|
|
6
|
+
export { TypedStoreEntry } from "./store_entry.js";
|
|
7
|
+
const INTERNAL_CONTENT_TYPE_METADATA_KEY = "__trellis_content_type";
|
|
8
|
+
const DEFAULT_STORE_WAIT_POLL_INTERVAL_MS = 250;
|
|
9
|
+
const MAX_STORE_LIST_LIMIT = 500;
|
|
10
|
+
const DEFAULT_STORE_LIST_LIMIT = 100;
|
|
11
|
+
const STORE_LIST_CURSOR_ENDPOINT = "trellis.store.list";
|
|
12
|
+
function metadataWithContentType(options) {
|
|
13
|
+
if (!options?.metadata && !options?.contentType) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
...(options?.metadata ?? {}),
|
|
18
|
+
...(options?.contentType
|
|
19
|
+
? { [INTERNAL_CONTENT_TYPE_METADATA_KEY]: options.contentType }
|
|
20
|
+
: {}),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function storeInfoFromObjectInfo(info) {
|
|
24
|
+
const { [INTERNAL_CONTENT_TYPE_METADATA_KEY]: contentType, ...metadata } = info.metadata ?? {};
|
|
25
|
+
return {
|
|
26
|
+
key: info.name,
|
|
27
|
+
size: info.size,
|
|
28
|
+
updatedAt: info.mtime,
|
|
29
|
+
...(info.digest ? { digest: info.digest } : {}),
|
|
30
|
+
...(contentType ? { contentType } : {}),
|
|
31
|
+
metadata,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function compareStoreKeys(left, right) {
|
|
35
|
+
const leftBytes = new TextEncoder().encode(left);
|
|
36
|
+
const rightBytes = new TextEncoder().encode(right);
|
|
37
|
+
for (let index = 0; index < Math.min(leftBytes.length, rightBytes.length); index++) {
|
|
38
|
+
if (leftBytes[index] !== rightBytes[index]) {
|
|
39
|
+
return leftBytes[index] - rightBytes[index];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return leftBytes.length - rightBytes.length;
|
|
43
|
+
}
|
|
44
|
+
function streamFromAsyncIterable(iterable) {
|
|
45
|
+
const iterator = iterable[Symbol.asyncIterator]();
|
|
46
|
+
return new ReadableStream({
|
|
47
|
+
async pull(controller) {
|
|
48
|
+
const next = await iterator.next();
|
|
49
|
+
if (next.done) {
|
|
50
|
+
controller.close();
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
controller.enqueue(next.value);
|
|
54
|
+
},
|
|
55
|
+
async cancel(reason) {
|
|
56
|
+
await iterator.return?.(reason);
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
function validateStoreListOptions(opts = {}) {
|
|
61
|
+
const limit = opts.limit ?? DEFAULT_STORE_LIST_LIMIT;
|
|
62
|
+
if (!Number.isInteger(limit) || limit <= 0) {
|
|
63
|
+
return Result.err(new StoreError({
|
|
64
|
+
operation: "list",
|
|
65
|
+
context: { reason: "invalid_limit", limit },
|
|
66
|
+
}));
|
|
67
|
+
}
|
|
68
|
+
if (limit > MAX_STORE_LIST_LIMIT) {
|
|
69
|
+
return Result.err(new StoreError({
|
|
70
|
+
operation: "list",
|
|
71
|
+
context: {
|
|
72
|
+
reason: "limit_exceeded",
|
|
73
|
+
limit,
|
|
74
|
+
maxLimit: MAX_STORE_LIST_LIMIT,
|
|
75
|
+
},
|
|
76
|
+
}));
|
|
77
|
+
}
|
|
78
|
+
const cursor = opts.cursor ?? "";
|
|
79
|
+
if (opts.cursor !== undefined && cursor.length === 0) {
|
|
80
|
+
return Result.err(new StoreError({
|
|
81
|
+
operation: "list",
|
|
82
|
+
context: { reason: "invalid_cursor" },
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
return Result.ok({ prefix: opts.prefix ?? "", cursor, limit });
|
|
86
|
+
}
|
|
87
|
+
function enforceMaxObjectBytes(stream, maxObjectBytes) {
|
|
88
|
+
if (maxObjectBytes === undefined) {
|
|
89
|
+
return stream;
|
|
90
|
+
}
|
|
91
|
+
const reader = stream.getReader();
|
|
92
|
+
let totalBytes = 0;
|
|
93
|
+
return new ReadableStream({
|
|
94
|
+
async pull(controller) {
|
|
95
|
+
const next = await reader.read();
|
|
96
|
+
if (next.done) {
|
|
97
|
+
controller.close();
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
totalBytes += next.value.length;
|
|
101
|
+
if (totalBytes > maxObjectBytes) {
|
|
102
|
+
controller.error(new StoreError({
|
|
103
|
+
operation: "put",
|
|
104
|
+
context: {
|
|
105
|
+
reason: "max_object_bytes_exceeded",
|
|
106
|
+
maxObjectBytes,
|
|
107
|
+
attemptedBytes: totalBytes,
|
|
108
|
+
},
|
|
109
|
+
}));
|
|
110
|
+
await reader.cancel();
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
controller.enqueue(next.value);
|
|
114
|
+
},
|
|
115
|
+
async cancel(reason) {
|
|
116
|
+
await reader.cancel(reason);
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
async function bytesFromStream(stream) {
|
|
121
|
+
const reader = stream.getReader();
|
|
122
|
+
const chunks = [];
|
|
123
|
+
let totalLength = 0;
|
|
124
|
+
while (true) {
|
|
125
|
+
const next = await reader.read();
|
|
126
|
+
if (next.done) {
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
chunks.push(next.value);
|
|
130
|
+
totalLength += next.value.length;
|
|
131
|
+
}
|
|
132
|
+
const merged = new Uint8Array(totalLength);
|
|
133
|
+
let offset = 0;
|
|
134
|
+
for (const chunk of chunks) {
|
|
135
|
+
merged.set(chunk, offset);
|
|
136
|
+
offset += chunk.length;
|
|
137
|
+
}
|
|
138
|
+
return merged;
|
|
139
|
+
}
|
|
140
|
+
function isNotFoundStoreError(error) {
|
|
141
|
+
return error.getContext().reason === "not_found";
|
|
142
|
+
}
|
|
143
|
+
function abortedStoreError(key, cause) {
|
|
144
|
+
return new StoreError({
|
|
145
|
+
operation: "waitFor",
|
|
146
|
+
cause,
|
|
147
|
+
context: { key, reason: "aborted" },
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
async function sleepWithSignal(ms, signal) {
|
|
151
|
+
if (signal?.aborted) {
|
|
152
|
+
throw signal.reason ??
|
|
153
|
+
new DOMException("The operation was aborted", "AbortError");
|
|
154
|
+
}
|
|
155
|
+
await new Promise((resolve, reject) => {
|
|
156
|
+
const timeoutId = setTimeout(() => {
|
|
157
|
+
cleanup();
|
|
158
|
+
resolve();
|
|
159
|
+
}, ms);
|
|
160
|
+
const onAbort = () => {
|
|
161
|
+
cleanup();
|
|
162
|
+
reject(signal?.reason ??
|
|
163
|
+
new DOMException("The operation was aborted", "AbortError"));
|
|
164
|
+
};
|
|
165
|
+
const cleanup = () => {
|
|
166
|
+
clearTimeout(timeoutId);
|
|
167
|
+
signal?.removeEventListener("abort", onAbort);
|
|
168
|
+
};
|
|
169
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
function streamFromBody(body) {
|
|
173
|
+
return body instanceof ReadableStream ? body : streamFromAsyncIterable(body);
|
|
174
|
+
}
|
|
175
|
+
async function unwrapObjectInfo(store, key) {
|
|
176
|
+
try {
|
|
177
|
+
const info = await store.info(key);
|
|
178
|
+
if (info === null || info.deleted) {
|
|
179
|
+
return Result.err(new StoreError({
|
|
180
|
+
operation: "get",
|
|
181
|
+
context: { key, reason: "not_found" },
|
|
182
|
+
}));
|
|
183
|
+
}
|
|
184
|
+
return Result.ok(info);
|
|
185
|
+
}
|
|
186
|
+
catch (cause) {
|
|
187
|
+
return Result.err(new StoreError({ operation: "get", cause, context: { key } }));
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/** Verifies that an existing physical store matches its effective binding. */
|
|
191
|
+
export async function ensureExistingStoreOptions(store, name, options) {
|
|
192
|
+
const status = await store.status();
|
|
193
|
+
const actualTtlMs = status.ttl > 0 ? Math.floor(status.ttl / 1_000_000) : 0;
|
|
194
|
+
if (actualTtlMs !== (options.ttlMs ?? 0)) {
|
|
195
|
+
throw new Error(`Store '${name}' TTL does not match its binding`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
export class TypedStore {
|
|
199
|
+
#store;
|
|
200
|
+
#options;
|
|
201
|
+
constructor(store, options) {
|
|
202
|
+
this.#store = store;
|
|
203
|
+
this.#options = {
|
|
204
|
+
ttlMs: options.ttlMs ?? 0,
|
|
205
|
+
...(options.maxObjectBytes !== undefined
|
|
206
|
+
? { maxObjectBytes: options.maxObjectBytes }
|
|
207
|
+
: {}),
|
|
208
|
+
...(options.maxTotalBytes !== undefined
|
|
209
|
+
? { maxTotalBytes: options.maxTotalBytes }
|
|
210
|
+
: {}),
|
|
211
|
+
...(options.bindOnly !== undefined ? { bindOnly: options.bindOnly } : {}),
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
static open(nats, name, options = {}) {
|
|
215
|
+
return AsyncResult.from((async () => {
|
|
216
|
+
try {
|
|
217
|
+
const objm = new Objm(nats);
|
|
218
|
+
const store = options.bindOnly
|
|
219
|
+
? await objm.open(name)
|
|
220
|
+
: await objm.create(name, {
|
|
221
|
+
...(options.ttlMs && options.ttlMs > 0
|
|
222
|
+
? { ttl: options.ttlMs * 1_000_000 }
|
|
223
|
+
: {}),
|
|
224
|
+
...(options.maxTotalBytes !== undefined
|
|
225
|
+
? { max_bytes: options.maxTotalBytes }
|
|
226
|
+
: {}),
|
|
227
|
+
});
|
|
228
|
+
await ensureExistingStoreOptions(store, name, options);
|
|
229
|
+
return Result.ok(new TypedStore(store, options));
|
|
230
|
+
}
|
|
231
|
+
catch (cause) {
|
|
232
|
+
return Result.err(new StoreError({ operation: "open", cause, context: { name } }));
|
|
233
|
+
}
|
|
234
|
+
})());
|
|
235
|
+
}
|
|
236
|
+
create(key, body, options) {
|
|
237
|
+
return AsyncResult.from(this.#putInternal("create", key, body, options, 0));
|
|
238
|
+
}
|
|
239
|
+
put(key, body, options) {
|
|
240
|
+
return AsyncResult.from(this.#putInternal("put", key, body, options));
|
|
241
|
+
}
|
|
242
|
+
get(key) {
|
|
243
|
+
return AsyncResult.from((async () => {
|
|
244
|
+
if (!this.#isCurrent())
|
|
245
|
+
return this.#stale("get", key);
|
|
246
|
+
const info = await unwrapObjectInfo(this.#store, key);
|
|
247
|
+
return info.map((objectInfo) => new TypedStoreEntry(this.#store, storeInfoFromObjectInfo(objectInfo)));
|
|
248
|
+
})());
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Waits for an object key to appear in the store and returns the resulting entry.
|
|
252
|
+
*/
|
|
253
|
+
waitFor(key, options = {}) {
|
|
254
|
+
return AsyncResult.from((async () => {
|
|
255
|
+
const startedAt = Date.now();
|
|
256
|
+
const pollIntervalMs = options.pollIntervalMs ??
|
|
257
|
+
DEFAULT_STORE_WAIT_POLL_INTERVAL_MS;
|
|
258
|
+
while (true) {
|
|
259
|
+
if (options.signal?.aborted) {
|
|
260
|
+
return Result.err(abortedStoreError(key, options.signal.reason));
|
|
261
|
+
}
|
|
262
|
+
const entry = await this.get(key);
|
|
263
|
+
if (entry.isOk()) {
|
|
264
|
+
return entry;
|
|
265
|
+
}
|
|
266
|
+
if (!isNotFoundStoreError(entry.error)) {
|
|
267
|
+
return entry;
|
|
268
|
+
}
|
|
269
|
+
const remainingTimeoutMs = options.timeoutMs === undefined
|
|
270
|
+
? undefined
|
|
271
|
+
: options.timeoutMs - (Date.now() - startedAt);
|
|
272
|
+
if (remainingTimeoutMs !== undefined && remainingTimeoutMs <= 0) {
|
|
273
|
+
return Result.err(new StoreError({
|
|
274
|
+
operation: "waitFor",
|
|
275
|
+
context: { key, reason: "timeout", timeoutMs: options.timeoutMs },
|
|
276
|
+
}));
|
|
277
|
+
}
|
|
278
|
+
try {
|
|
279
|
+
await sleepWithSignal(remainingTimeoutMs === undefined
|
|
280
|
+
? pollIntervalMs
|
|
281
|
+
: Math.min(pollIntervalMs, remainingTimeoutMs), options.signal);
|
|
282
|
+
}
|
|
283
|
+
catch (cause) {
|
|
284
|
+
return Result.err(abortedStoreError(key, cause));
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
})());
|
|
288
|
+
}
|
|
289
|
+
delete(key) {
|
|
290
|
+
return AsyncResult.from((async () => {
|
|
291
|
+
if (!this.#isCurrent())
|
|
292
|
+
return this.#stale("delete", key);
|
|
293
|
+
try {
|
|
294
|
+
await this.#store.delete(key);
|
|
295
|
+
return Result.ok(undefined);
|
|
296
|
+
}
|
|
297
|
+
catch (cause) {
|
|
298
|
+
return Result.err(new StoreError({ operation: "delete", cause, context: { key } }));
|
|
299
|
+
}
|
|
300
|
+
})());
|
|
301
|
+
}
|
|
302
|
+
list(opts = {}) {
|
|
303
|
+
return AsyncResult.from((async () => {
|
|
304
|
+
if (!this.#isCurrent())
|
|
305
|
+
return this.#stale("list");
|
|
306
|
+
const query = validateStoreListOptions(opts);
|
|
307
|
+
if (query.isErr())
|
|
308
|
+
return Result.err(query.error);
|
|
309
|
+
const { prefix, cursor, limit } = query.unwrapOrElse(() => {
|
|
310
|
+
throw new Error("unreachable");
|
|
311
|
+
});
|
|
312
|
+
try {
|
|
313
|
+
const queryDigest = await paginationQueryDigest(STORE_LIST_CURSOR_ENDPOINT, { prefix });
|
|
314
|
+
let after = "";
|
|
315
|
+
if (cursor) {
|
|
316
|
+
const decoded = await decodePaginationCursor(cursor, queryDigest);
|
|
317
|
+
if (typeof decoded !== "string") {
|
|
318
|
+
throw new Error("invalid pagination cursor");
|
|
319
|
+
}
|
|
320
|
+
after = decoded;
|
|
321
|
+
}
|
|
322
|
+
const objects = await this.#store.list();
|
|
323
|
+
const filtered = objects
|
|
324
|
+
.filter((info) => !info.deleted && info.name.startsWith(prefix))
|
|
325
|
+
.map(storeInfoFromObjectInfo)
|
|
326
|
+
.sort((left, right) => compareStoreKeys(left.key, right.key))
|
|
327
|
+
.filter((info) => compareStoreKeys(info.key, after) > 0);
|
|
328
|
+
const entries = filtered.slice(0, limit);
|
|
329
|
+
return Result.ok({
|
|
330
|
+
entries,
|
|
331
|
+
...(filtered.length > limit
|
|
332
|
+
? {
|
|
333
|
+
nextCursor: await encodePaginationCursor(queryDigest, entries.at(-1)?.key),
|
|
334
|
+
}
|
|
335
|
+
: {}),
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
catch (cause) {
|
|
339
|
+
return Result.err(new StoreError({ operation: "list", cause, context: { prefix } }));
|
|
340
|
+
}
|
|
341
|
+
})());
|
|
342
|
+
}
|
|
343
|
+
status() {
|
|
344
|
+
return AsyncResult.from((async () => {
|
|
345
|
+
if (!this.#isCurrent())
|
|
346
|
+
return this.#stale("status");
|
|
347
|
+
try {
|
|
348
|
+
const status = await this.#store.status();
|
|
349
|
+
return Result.ok(storeStatusFromObjectStoreStatus(status, this.#options));
|
|
350
|
+
}
|
|
351
|
+
catch (cause) {
|
|
352
|
+
return Result.err(new StoreError({ operation: "status", cause }));
|
|
353
|
+
}
|
|
354
|
+
})());
|
|
355
|
+
}
|
|
356
|
+
async #putInternal(operation, key, body, options, previousRevision) {
|
|
357
|
+
try {
|
|
358
|
+
if (!this.#isCurrent())
|
|
359
|
+
return this.#stale(operation, key);
|
|
360
|
+
const metadata = metadataWithContentType(options);
|
|
361
|
+
if (body instanceof Uint8Array) {
|
|
362
|
+
if (this.#options.maxObjectBytes !== undefined &&
|
|
363
|
+
body.length > this.#options.maxObjectBytes) {
|
|
364
|
+
return Result.err(new StoreError({
|
|
365
|
+
operation,
|
|
366
|
+
context: {
|
|
367
|
+
key,
|
|
368
|
+
reason: "max_object_bytes_exceeded",
|
|
369
|
+
maxObjectBytes: this.#options.maxObjectBytes,
|
|
370
|
+
attemptedBytes: body.length,
|
|
371
|
+
},
|
|
372
|
+
}));
|
|
373
|
+
}
|
|
374
|
+
await this.#store.putBlob({ name: key, ...(metadata ? { metadata } : {}) }, body, previousRevision === undefined ? undefined : { previousRevision });
|
|
375
|
+
return Result.ok(undefined);
|
|
376
|
+
}
|
|
377
|
+
const limitedStream = enforceMaxObjectBytes(streamFromBody(body), this.#options.maxObjectBytes);
|
|
378
|
+
await this.#store.put({ name: key, ...(metadata ? { metadata } : {}) }, limitedStream, previousRevision === undefined ? undefined : { previousRevision });
|
|
379
|
+
return Result.ok(undefined);
|
|
380
|
+
}
|
|
381
|
+
catch (cause) {
|
|
382
|
+
return Result.err(cause instanceof StoreError
|
|
383
|
+
? cause
|
|
384
|
+
: new StoreError({ operation, cause, context: { key } }));
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
#isCurrent() {
|
|
388
|
+
return this.#options.isCurrent?.() ?? true;
|
|
389
|
+
}
|
|
390
|
+
#stale(operation, key) {
|
|
391
|
+
return Result.err(new StoreError({
|
|
392
|
+
operation,
|
|
393
|
+
context: { ...(key ? { key } : {}), reason: "stale_binding" },
|
|
394
|
+
}));
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
function storeStatusFromObjectStoreStatus(status, options) {
|
|
398
|
+
return {
|
|
399
|
+
size: status.size,
|
|
400
|
+
sealed: status.sealed,
|
|
401
|
+
ttlMs: status.ttl > 0 ? Math.floor(status.ttl / 1_000_000) : 0,
|
|
402
|
+
...(options.maxObjectBytes !== undefined
|
|
403
|
+
? { maxObjectBytes: options.maxObjectBytes }
|
|
404
|
+
: {}),
|
|
405
|
+
...(status.streamInfo.config.max_bytes > 0
|
|
406
|
+
? { maxTotalBytes: status.streamInfo.config.max_bytes }
|
|
407
|
+
: {}),
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
export function bytesFromStoreStream(stream) {
|
|
411
|
+
return bytesFromStream(stream);
|
|
412
|
+
}
|
package/store_entry.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { AsyncResult } from "@oatscenter/result";
|
|
2
|
+
import { StoreError } from "./errors/index.ts";
|
|
3
|
+
import type { StoreInfo } from "./store.ts";
|
|
4
|
+
type ObjectResultLike = {
|
|
5
|
+
data: ReadableStream<Uint8Array>;
|
|
6
|
+
error: Promise<unknown>;
|
|
7
|
+
};
|
|
8
|
+
type ObjectStoreLike = {
|
|
9
|
+
get(key: string): Promise<ObjectResultLike | null>;
|
|
10
|
+
getBlob(key: string): Promise<Uint8Array | null>;
|
|
11
|
+
};
|
|
12
|
+
export declare class TypedStoreEntry {
|
|
13
|
+
#private;
|
|
14
|
+
readonly key: string;
|
|
15
|
+
readonly info: StoreInfo;
|
|
16
|
+
constructor(store: ObjectStoreLike, info: StoreInfo);
|
|
17
|
+
stream(): AsyncResult<ReadableStream<Uint8Array>, StoreError>;
|
|
18
|
+
bytes(): AsyncResult<Uint8Array, StoreError>;
|
|
19
|
+
}
|
|
20
|
+
export {};
|
package/store_entry.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { AsyncResult, Result } from "@oatscenter/result";
|
|
2
|
+
import { StoreError } from "./errors/index.js";
|
|
3
|
+
export class TypedStoreEntry {
|
|
4
|
+
key;
|
|
5
|
+
info;
|
|
6
|
+
#store;
|
|
7
|
+
constructor(store, info) {
|
|
8
|
+
this.#store = store;
|
|
9
|
+
this.key = info.key;
|
|
10
|
+
this.info = info;
|
|
11
|
+
}
|
|
12
|
+
stream() {
|
|
13
|
+
return AsyncResult.from((async () => {
|
|
14
|
+
try {
|
|
15
|
+
const result = await this.#store.get(this.key);
|
|
16
|
+
if (result === null) {
|
|
17
|
+
return Result.err(new StoreError({
|
|
18
|
+
operation: "stream",
|
|
19
|
+
context: { key: this.key, reason: "not_found" },
|
|
20
|
+
}));
|
|
21
|
+
}
|
|
22
|
+
return Result.ok(streamWithErrorCheck(result));
|
|
23
|
+
}
|
|
24
|
+
catch (cause) {
|
|
25
|
+
return Result.err(new StoreError({
|
|
26
|
+
operation: "stream",
|
|
27
|
+
cause,
|
|
28
|
+
context: { key: this.key },
|
|
29
|
+
}));
|
|
30
|
+
}
|
|
31
|
+
})());
|
|
32
|
+
}
|
|
33
|
+
bytes() {
|
|
34
|
+
return AsyncResult.from((async () => {
|
|
35
|
+
try {
|
|
36
|
+
const bytes = await this.#store.getBlob(this.key);
|
|
37
|
+
if (bytes === null) {
|
|
38
|
+
return Result.err(new StoreError({
|
|
39
|
+
operation: "bytes",
|
|
40
|
+
context: { key: this.key, reason: "not_found" },
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
return Result.ok(bytes);
|
|
44
|
+
}
|
|
45
|
+
catch (cause) {
|
|
46
|
+
return Result.err(new StoreError({
|
|
47
|
+
operation: "bytes",
|
|
48
|
+
cause,
|
|
49
|
+
context: { key: this.key },
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
})());
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function streamWithErrorCheck(result) {
|
|
56
|
+
const reader = result.data.getReader();
|
|
57
|
+
return new ReadableStream({
|
|
58
|
+
async pull(controller) {
|
|
59
|
+
const next = await reader.read();
|
|
60
|
+
if (next.done) {
|
|
61
|
+
const error = await result.error;
|
|
62
|
+
if (error) {
|
|
63
|
+
controller.error(error);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
controller.close();
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
controller.enqueue(next.value);
|
|
70
|
+
},
|
|
71
|
+
async cancel(reason) {
|
|
72
|
+
await reader.cancel(reason);
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
}
|
package/tasks.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { AsyncResult, type BaseError } from "@oatscenter/result";
|
|
2
|
+
import { type LoggerLike } from "./globals.ts";
|
|
3
|
+
export declare class TrellisTasks {
|
|
4
|
+
#private;
|
|
5
|
+
constructor(opts: {
|
|
6
|
+
log?: LoggerLike;
|
|
7
|
+
});
|
|
8
|
+
add<E extends BaseError>(name: string, task: AsyncResult<void, E>): void;
|
|
9
|
+
wait(): AsyncResult<void, BaseError>;
|
|
10
|
+
}
|
package/tasks.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { AsyncResult, Result } from "@oatscenter/result";
|
|
2
|
+
import { logger } from "./globals.js";
|
|
3
|
+
export class TrellisTasks {
|
|
4
|
+
#tasks = {};
|
|
5
|
+
#log;
|
|
6
|
+
constructor(opts) {
|
|
7
|
+
this.#log = opts.log ?? logger;
|
|
8
|
+
}
|
|
9
|
+
/*
|
|
10
|
+
* Add a task to the task queue
|
|
11
|
+
*/
|
|
12
|
+
add(name, task) {
|
|
13
|
+
if (name in this.#tasks) {
|
|
14
|
+
this.#log.error({ name }, "Task already running?");
|
|
15
|
+
throw new Error(`Task ${name} already running`);
|
|
16
|
+
}
|
|
17
|
+
this.#log.debug({ name }, "Added task");
|
|
18
|
+
this.#tasks[name] = task.then((r) => {
|
|
19
|
+
if (Result.isErr(r)) {
|
|
20
|
+
this.#log.error(r, "Task encountered a runtime error");
|
|
21
|
+
}
|
|
22
|
+
return r;
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
wait() {
|
|
26
|
+
return AsyncResult.any(Object.values(this.#tasks));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type Context, type Span } from "@opentelemetry/api";
|
|
2
|
+
export interface HeaderCarrier {
|
|
3
|
+
get(key: string): string | undefined;
|
|
4
|
+
set(key: string, value: string): void;
|
|
5
|
+
}
|
|
6
|
+
export declare function injectTraceContext(carrier: HeaderCarrier, span?: Span): void;
|
|
7
|
+
export declare function extractTraceContext(carrier: HeaderCarrier): Context;
|
|
8
|
+
export declare function createMapCarrier(): HeaderCarrier;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { context, propagation, trace, } from "@opentelemetry/api";
|
|
2
|
+
export function injectTraceContext(carrier, span) {
|
|
3
|
+
const ctx = span ? trace.setSpan(context.active(), span) : context.active();
|
|
4
|
+
propagation.inject(ctx, carrier, {
|
|
5
|
+
set: (c, k, v) => c.set(k, v),
|
|
6
|
+
});
|
|
7
|
+
}
|
|
8
|
+
export function extractTraceContext(carrier) {
|
|
9
|
+
return propagation.extract(context.active(), carrier, {
|
|
10
|
+
get: (c, k) => c.get(k),
|
|
11
|
+
keys: () => [],
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
export function createMapCarrier() {
|
|
15
|
+
const map = new Map();
|
|
16
|
+
return {
|
|
17
|
+
get: (key) => map.get(key),
|
|
18
|
+
set: (key, value) => map.set(key, value),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type Context, context, type Span, SpanKind, SpanStatusCode, trace, type Tracer } from "@opentelemetry/api";
|
|
2
|
+
export declare function getTracer(scope?: string): Tracer;
|
|
3
|
+
export declare function getActiveSpan(): Span | undefined;
|
|
4
|
+
export declare function withSpan<T>(span: Span, fn: () => T): T;
|
|
5
|
+
export declare function withSpanAsync<T>(span: Span, fn: () => Promise<T>): Promise<T>;
|
|
6
|
+
export { context, SpanKind, SpanStatusCode, trace };
|
|
7
|
+
export type { Context, Span };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { context, SpanKind, SpanStatusCode, trace, } from "@opentelemetry/api";
|
|
2
|
+
export function getTracer(scope = "@oatscenter/trellis/telemetry") {
|
|
3
|
+
return trace.getTracer(scope);
|
|
4
|
+
}
|
|
5
|
+
export function getActiveSpan() {
|
|
6
|
+
return trace.getActiveSpan();
|
|
7
|
+
}
|
|
8
|
+
export function withSpan(span, fn) {
|
|
9
|
+
return context.with(trace.setSpan(context.active(), span), fn);
|
|
10
|
+
}
|
|
11
|
+
export async function withSpanAsync(span, fn) {
|
|
12
|
+
return context.with(trace.setSpan(context.active(), span), fn);
|
|
13
|
+
}
|
|
14
|
+
export { context, SpanKind, SpanStatusCode, trace };
|
package/telemetry/env.js
ADDED