@hasna/recordings 0.3.13 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +279 -43
- package/bun.lock +37 -38
- package/contracts/v1/fixtures.json +1206 -0
- package/dist/cli/index.js +1909 -619
- package/dist/cli/macos-shortcut.d.ts +2 -2
- package/dist/contracts/hosted-v1.d.ts +105 -0
- package/dist/contracts/hosted-v1.d.ts.map +1 -0
- package/dist/contracts/hosted-v1.js +41 -0
- package/dist/contracts/stream-v1.d.ts +117 -0
- package/dist/contracts/stream-v1.d.ts.map +1 -0
- package/dist/contracts/stream-v1.js +35 -0
- package/dist/db/database.d.ts.map +1 -1
- package/dist/db/pg-migrations.d.ts.map +1 -1
- package/dist/db/recordings.d.ts +6 -0
- package/dist/db/recordings.d.ts.map +1 -1
- package/dist/hosted/index.d.ts +58 -0
- package/dist/hosted/index.d.ts.map +1 -0
- package/dist/hosted/index.js +266 -0
- package/dist/hosted/transport.d.ts +36 -0
- package/dist/hosted/transport.d.ts.map +1 -0
- package/dist/hosted-v1-aavn7ktb.js +4114 -0
- package/dist/hosted-v1-gdr9extc.js +84 -0
- package/dist/http/client.d.ts +183 -22
- package/dist/http/client.d.ts.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2879 -2288
- package/dist/lib/audio-artifact-storage.d.ts +98 -0
- package/dist/lib/audio-artifact-storage.d.ts.map +1 -0
- package/dist/lib/capture-probe.d.ts +3 -3
- package/dist/lib/capture-probe.d.ts.map +1 -1
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/local-opt-in.d.ts +132 -0
- package/dist/lib/local-opt-in.d.ts.map +1 -0
- package/dist/lib/macos-bundle.d.ts +1 -1
- package/dist/lib/persistence-probe.d.ts +56 -17
- package/dist/lib/persistence-probe.d.ts.map +1 -1
- package/dist/lib/transcriber.d.ts.map +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +1713 -459
- package/dist/sdk/index.d.ts +13 -5
- package/dist/sdk/index.d.ts.map +1 -1
- package/dist/sdk/index.js +904 -1
- package/dist/sdk/resolve.d.ts +53 -0
- package/dist/sdk/resolve.d.ts.map +1 -0
- package/dist/sdk/v1.generated.d.ts +6 -0
- package/dist/sdk/v1.generated.d.ts.map +1 -1
- package/dist/server/client-ip.d.ts +39 -0
- package/dist/server/client-ip.d.ts.map +1 -0
- package/dist/server/cloud-config.d.ts +12 -0
- package/dist/server/cloud-config.d.ts.map +1 -1
- package/dist/server/cloud-readiness.d.ts.map +1 -1
- package/dist/server/cloud.d.ts +20 -2
- package/dist/server/cloud.d.ts.map +1 -1
- package/dist/server/index.js +590 -287
- package/dist/server/migrate-command.d.ts +1 -1
- package/dist/server/migrate-command.d.ts.map +1 -1
- package/dist/server/openapi.d.ts +21 -0
- package/dist/server/openapi.d.ts.map +1 -1
- package/dist/server/repo.d.ts.map +1 -1
- package/dist/server/serve.d.ts.map +1 -1
- package/dist/storage.d.ts +2 -2
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +1358 -874
- package/dist/store.d.ts +12 -3
- package/dist/store.d.ts.map +1 -1
- package/dist/types/index.d.ts +15 -0
- package/dist/types/index.d.ts.map +1 -1
- package/docs/hosted-sdk.md +71 -0
- package/docs/wire-contracts.md +24 -0
- package/package.json +33 -11
- package/packaging/macos/build_release_pkg.sh +3 -3
- package/packaging/macos/managed_bootstrap.sh +4 -4
- package/packaging/macos/scripts/postinstall +2 -2
- package/packaging/macos/scripts/preinstall +2 -2
- package/scripts/build_companion_cli.sh +7 -1
- package/scripts/ci-linux-suite.ts +23 -13
- package/scripts/install_macos_app.sh +27 -24
- package/scripts/macos_artifact.ts +60 -49
- package/scripts/migrate.ts +4 -20
- package/scripts/native/prebuilds/darwin-universal/recordings_fs_guard.node +0 -0
- package/scripts/native/recordings_fs_guard.c +36 -4
- package/scripts/native-core-receipt.py +171 -0
- package/scripts/native_fs_guard.ts +2 -0
- package/scripts/release-suite-gate.ts +227 -150
- package/scripts/resolve_tailscale_cli.sh +24 -3
- package/scripts/smoke_macos_app.sh +21 -21
- package/src/native/Recordings/App/ContentView.swift +53 -68
- package/src/native/Recordings/App/MenuBarStatusView.swift +171 -61
- package/src/native/Recordings/App/RecordWorkspaceView.swift +47 -449
- package/src/native/Recordings/App/RecorderSettingsView.swift +75 -0
- package/src/native/Recordings/App/RecordingDetailView.swift +3 -4
- package/src/native/Recordings/App/RecordingsApp.swift +185 -9
- package/src/native/Recordings/App/RecordingsListView.swift +60 -112
- package/src/native/Recordings/App/RecordingsStore.swift +124 -109
- package/src/native/Recordings/App/Theme.swift +73 -61
- package/src/native/Recordings/Package.swift +1 -0
- package/src/native/Recordings/RecordingsLib/BlockingOperation.swift +29 -0
- package/src/native/Recordings/RecordingsLib/CaptureMonitor.swift +65 -0
- package/src/native/Recordings/RecordingsLib/Info.plist +3 -3
- package/src/native/Recordings/RecordingsLib/OpenAIAPIKeyStore.swift +75 -21
- package/src/native/Recordings/RecordingsLib/ProjectStore.swift +4 -4
- package/src/native/Recordings/RecordingsLib/Recording.swift +14 -2
- package/src/native/Recordings/RecordingsLib/RecordingEngine.swift +539 -89
- package/src/native/Recordings/RecordingsLib/RecordingGlassBackground.swift +34 -0
- package/src/native/Recordings/RecordingsLib/RecordingPasteTarget.swift +114 -0
- package/src/native/Recordings/RecordingsLib/RecordingProvider.swift +112 -0
- package/src/native/Recordings/RecordingsLib/RecordingsCLI.swift +17 -10
- package/src/native/Recordings/RecordingsLib/ServiceAPIConfiguration.swift +107 -0
- package/src/native/Recordings/RecordingsLib/ServiceConnectionView.swift +76 -0
- package/src/native/Recordings/RecordingsLib/SettingsView.swift +45 -149
- package/src/native/Recordings/RecordingsLib/SettingsWindowController.swift +48 -0
- package/src/native/Recordings/RecordingsTests/BlockingOperationTests.swift +85 -0
- package/src/native/Recordings/RecordingsTests/CLIRunnerTests.swift +454 -76
- package/src/native/Recordings/RecordingsTests/OpenAIAPIKeyStoreTests.swift +43 -38
- package/src/native/Recordings/RecordingsTests/PipeClosureFixture.swift +215 -0
- package/src/native/Recordings/RecordingsTests/ProjectStoreTests.swift +10 -10
- package/src/native/Recordings/RecordingsTests/RecorderSurfaceTests.swift +60 -0
- package/src/native/Recordings/RecordingsTests/RecordingDateTests.swift +26 -0
- package/src/native/Recordings/RecordingsTests/RecordingEngineDeliveryTests.swift +1 -1
- package/src/native/Recordings/RecordingsTests/RecordingFrozenPasteTargetTests.swift +50 -0
- package/src/native/Recordings/RecordingsTests/RecordingPasteTargetTrackerTests.swift +48 -0
- package/src/native/Recordings/RecordingsTests/RecordingProviderTests.swift +308 -0
- package/src/native/Recordings/RecordingsTests/RecordingStartGateTests.swift +1 -1
- package/src/native/Recordings/RecordingsTests/RecordingStartTimingTests.swift +123 -21
- package/src/native/Recordings/RecordingsTests/ServiceAPIConfigurationTests.swift +75 -0
- package/src/native/Recordings/RecordingsTests/SettingsWindowControllerTests.swift +28 -0
- package/src/native/Recordings/RecordingsTests/TestHomeDirectory.swift +5 -1
- package/src/native/Recordings/Updater/BootstrapPreflight/BootstrapPreflightMain.swift +1 -1
- package/src/native/Recordings/Updater/Broker/ApplicationNamespace.swift +2 -2
- package/src/native/Recordings/Updater/Broker/BrokerMain.swift +1 -1
- package/src/native/Recordings/Updater/Broker/CanonicalTreeCopy.swift +1 -1
- package/src/native/Recordings/Updater/Broker/InstallJournal.swift +1 -1
- package/src/native/Recordings/Updater/BrokerTests/ActivationRecoveryPolicyTests.swift +2 -2
- package/src/native/Recordings/Updater/Protocol/UpdateProtocol.swift +1 -1
- package/src/native/Recordings/Updater/VerifierLauncher/RecordingsVerifierLauncher.c +2 -2
- package/src/native/Recordings/build.sh +8 -7
- package/dist/__tests__/helpers/installer-guard-execution.d.ts +0 -22
- package/dist/__tests__/helpers/installer-guard-execution.d.ts.map +0 -1
- package/dist/__tests__/helpers/installer-preflight.d.ts +0 -22
- package/dist/__tests__/helpers/installer-preflight.d.ts.map +0 -1
- package/dist/__tests__/helpers/native-fs-guard.d.ts +0 -2
- package/dist/__tests__/helpers/native-fs-guard.d.ts.map +0 -1
- package/dist/__tests__/helpers/source-assertions.d.ts +0 -171
- package/dist/__tests__/helpers/source-assertions.d.ts.map +0 -1
- package/dist/__tests__/preload.d.ts +0 -2
- package/dist/__tests__/preload.d.ts.map +0 -1
- package/src/native/Recordings/App/SidebarView.swift +0 -212
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
accountResponseParser,
|
|
4
|
+
healthResponseParser,
|
|
5
|
+
pageOptionsParser,
|
|
6
|
+
pasteInputParser,
|
|
7
|
+
pasteListParser,
|
|
8
|
+
pasteResponseParser,
|
|
9
|
+
pendingDeletionParser,
|
|
10
|
+
readyResponseParser,
|
|
11
|
+
recordingInputParser,
|
|
12
|
+
recordingListParser,
|
|
13
|
+
recordingResponseParser,
|
|
14
|
+
renameInputParser,
|
|
15
|
+
versionResponseParser
|
|
16
|
+
} from "../hosted-v1-gdr9extc.js";
|
|
17
|
+
import {
|
|
18
|
+
recordingIDParser
|
|
19
|
+
} from "../hosted-v1-aavn7ktb.js";
|
|
20
|
+
|
|
21
|
+
// src/hosted/transport.ts
|
|
22
|
+
import { appendQuery, toV1BaseUrl } from "@hasna/contracts/client";
|
|
23
|
+
var messages = {
|
|
24
|
+
invalid_configuration: "Choose a complete HTTPS v1 API base, or an explicit HTTP loopback v1 base, and valid bounds.",
|
|
25
|
+
invalid_input: "The operation input does not match the hosted Recordings contract.",
|
|
26
|
+
credential_unavailable: "A valid access credential is required for this hosted operation.",
|
|
27
|
+
aborted: "The hosted request was cancelled.",
|
|
28
|
+
timeout: "The hosted request exceeded its deadline.",
|
|
29
|
+
network_error: "The hosted API could not be reached.",
|
|
30
|
+
redirect_refused: "The hosted API returned a refused redirect.",
|
|
31
|
+
response_too_large: "The hosted response exceeded its byte limit. Request a smaller page.",
|
|
32
|
+
invalid_response: "The hosted API returned an unexpected response.",
|
|
33
|
+
unauthorized: "Sign in again to use this hosted session.",
|
|
34
|
+
forbidden: "This hosted account is not permitted to perform the operation.",
|
|
35
|
+
not_found: "The hosted resource was not found.",
|
|
36
|
+
recording_deleted: "The recording was permanently deleted.",
|
|
37
|
+
conflict: "The operation conflicts with existing hosted state.",
|
|
38
|
+
rate_limited: "The hosted usage or request limit was reached.",
|
|
39
|
+
http_error: "The hosted API refused the request."
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
class RecordingsSDKError extends Error {
|
|
43
|
+
code;
|
|
44
|
+
status;
|
|
45
|
+
requestId;
|
|
46
|
+
constructor(code, status, requestId) {
|
|
47
|
+
super(messages[code]);
|
|
48
|
+
this.code = code;
|
|
49
|
+
this.status = status;
|
|
50
|
+
this.requestId = requestId;
|
|
51
|
+
this.name = "RecordingsSDKError";
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function input(schema, value) {
|
|
55
|
+
const parsed = schema.safeParse(value);
|
|
56
|
+
if (!parsed.success)
|
|
57
|
+
throw new RecordingsSDKError("invalid_input");
|
|
58
|
+
return parsed.data;
|
|
59
|
+
}
|
|
60
|
+
function abortable(value, signal) {
|
|
61
|
+
if (signal.aborted) {
|
|
62
|
+
value.catch(() => {});
|
|
63
|
+
return Promise.reject(new RecordingsSDKError("aborted"));
|
|
64
|
+
}
|
|
65
|
+
return new Promise((resolve, reject) => {
|
|
66
|
+
const onAbort = () => reject(new RecordingsSDKError("aborted"));
|
|
67
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
68
|
+
value.then(resolve, reject).finally(() => signal.removeEventListener("abort", onAbort));
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
class Transport {
|
|
73
|
+
base;
|
|
74
|
+
#fetch;
|
|
75
|
+
#credential;
|
|
76
|
+
#timeout;
|
|
77
|
+
#limit;
|
|
78
|
+
constructor(options) {
|
|
79
|
+
try {
|
|
80
|
+
const base = toV1BaseUrl(options.apiBase);
|
|
81
|
+
const original = new URL(options.apiBase.trim()), url = new URL(base);
|
|
82
|
+
if (!/\/v1\/?$/.test(original.pathname) || original.search || original.hash || url.protocol !== "https:" && !(url.protocol === "http:" && ["localhost", "127.0.0.1", "[::1]"].includes(url.hostname)))
|
|
83
|
+
throw Error();
|
|
84
|
+
this.base = base;
|
|
85
|
+
this.#timeout = options.timeoutMs ?? 20000;
|
|
86
|
+
this.#limit = options.maxResponseBytes ?? 4194304;
|
|
87
|
+
if (!Number.isInteger(this.#timeout) || this.#timeout < 10 || this.#timeout > 300000 || !Number.isInteger(this.#limit) || this.#limit < 1024 || this.#limit > 33554432)
|
|
88
|
+
throw Error();
|
|
89
|
+
} catch {
|
|
90
|
+
throw new RecordingsSDKError("invalid_configuration");
|
|
91
|
+
}
|
|
92
|
+
this.#fetch = options.fetch ?? globalThis.fetch.bind(globalThis);
|
|
93
|
+
this.#credential = options.credentialProvider;
|
|
94
|
+
}
|
|
95
|
+
async request(method, path, authenticated, statuses, body, options = {}, query) {
|
|
96
|
+
const controller = new AbortController;
|
|
97
|
+
let timedOut = false;
|
|
98
|
+
const onAbort = () => controller.abort();
|
|
99
|
+
if (options.signal?.aborted)
|
|
100
|
+
controller.abort();
|
|
101
|
+
else
|
|
102
|
+
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
103
|
+
const timer = setTimeout(() => {
|
|
104
|
+
timedOut = true;
|
|
105
|
+
controller.abort();
|
|
106
|
+
}, this.#timeout);
|
|
107
|
+
let response;
|
|
108
|
+
try {
|
|
109
|
+
controller.signal.throwIfAborted();
|
|
110
|
+
const headers = new Headers({ accept: "application/json" });
|
|
111
|
+
const encoded = body === undefined ? undefined : JSON.stringify(body);
|
|
112
|
+
if (encoded !== undefined) {
|
|
113
|
+
if (new TextEncoder().encode(encoded).byteLength > 1048576)
|
|
114
|
+
throw new RecordingsSDKError("invalid_input");
|
|
115
|
+
headers.set("content-type", "application/json");
|
|
116
|
+
}
|
|
117
|
+
if (authenticated) {
|
|
118
|
+
let token;
|
|
119
|
+
try {
|
|
120
|
+
if (!this.#credential)
|
|
121
|
+
throw Error();
|
|
122
|
+
token = await abortable(Promise.resolve(this.#credential(Object.freeze({ apiBase: this.base, signal: controller.signal }))), controller.signal);
|
|
123
|
+
if (typeof token !== "string" || !/^[A-Za-z0-9._~+\/-]{1,16000}={0,2}$/.test(token))
|
|
124
|
+
throw Error();
|
|
125
|
+
} catch {
|
|
126
|
+
throw new RecordingsSDKError("credential_unavailable");
|
|
127
|
+
}
|
|
128
|
+
controller.signal.throwIfAborted();
|
|
129
|
+
headers.set("authorization", "Bearer " + token);
|
|
130
|
+
}
|
|
131
|
+
const url = this.base + appendQuery(path, query);
|
|
132
|
+
response = await abortable(this.#fetch(url, { method, headers, body: encoded, redirect: "manual", credentials: "omit", cache: "no-store", signal: controller.signal }), controller.signal);
|
|
133
|
+
if (response.status >= 300 && response.status < 400 || response.redirected || response.url && response.url !== url)
|
|
134
|
+
throw new RecordingsSDKError("redirect_refused");
|
|
135
|
+
if (!statuses.includes(response.status)) {
|
|
136
|
+
const codes = { 401: "unauthorized", 403: "forbidden", 404: "not_found", 410: "recording_deleted", 409: "conflict", 429: "rate_limited" };
|
|
137
|
+
const requestID = response.headers.get("x-request-id");
|
|
138
|
+
throw new RecordingsSDKError(codes[response.status] ?? "http_error", response.status, recordingIDParser.safeParse(requestID).success ? requestID : undefined);
|
|
139
|
+
}
|
|
140
|
+
if (response.status === 204)
|
|
141
|
+
return { status: 204 };
|
|
142
|
+
if (!/^application\/json(?:\s*;.*)?$/i.test(response.headers.get("content-type") ?? ""))
|
|
143
|
+
throw new RecordingsSDKError("invalid_response");
|
|
144
|
+
const encoding = response.headers.get("content-encoding");
|
|
145
|
+
const declared = !encoding || encoding === "identity" ? response.headers.get("content-length") : null;
|
|
146
|
+
if (declared !== null && (!/^\d+$/.test(declared) || Number(declared) > this.#limit))
|
|
147
|
+
throw new RecordingsSDKError("response_too_large");
|
|
148
|
+
const reader = response.body?.getReader();
|
|
149
|
+
if (!reader)
|
|
150
|
+
throw new RecordingsSDKError("invalid_response");
|
|
151
|
+
let bytes = new Uint8Array(Math.min(16384, this.#limit)), length = 0;
|
|
152
|
+
try {
|
|
153
|
+
while (true) {
|
|
154
|
+
const { done, value } = await abortable(reader.read(), controller.signal);
|
|
155
|
+
if (done)
|
|
156
|
+
break;
|
|
157
|
+
if (value.byteLength > this.#limit - length)
|
|
158
|
+
throw new RecordingsSDKError("response_too_large");
|
|
159
|
+
const required = length + value.byteLength;
|
|
160
|
+
if (required > bytes.byteLength) {
|
|
161
|
+
const grown = new Uint8Array(Math.min(this.#limit, Math.max(required, bytes.byteLength * 2)));
|
|
162
|
+
grown.set(bytes.subarray(0, length));
|
|
163
|
+
bytes = grown;
|
|
164
|
+
}
|
|
165
|
+
bytes.set(value, length);
|
|
166
|
+
length = required;
|
|
167
|
+
}
|
|
168
|
+
} finally {
|
|
169
|
+
reader.cancel().catch(() => {});
|
|
170
|
+
reader.releaseLock();
|
|
171
|
+
}
|
|
172
|
+
if (declared !== null && Number(declared) !== length)
|
|
173
|
+
throw new RecordingsSDKError("invalid_response");
|
|
174
|
+
try {
|
|
175
|
+
return { status: response.status, data: JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, length))) };
|
|
176
|
+
} catch {
|
|
177
|
+
throw new RecordingsSDKError("invalid_response");
|
|
178
|
+
}
|
|
179
|
+
} catch (error) {
|
|
180
|
+
if (controller.signal.aborted)
|
|
181
|
+
throw new RecordingsSDKError(timedOut ? "timeout" : "aborted");
|
|
182
|
+
if (error instanceof RecordingsSDKError)
|
|
183
|
+
throw error;
|
|
184
|
+
throw new RecordingsSDKError("network_error");
|
|
185
|
+
} finally {
|
|
186
|
+
clearTimeout(timer);
|
|
187
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
188
|
+
response?.body?.cancel().catch(() => {});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
function output(schema, data) {
|
|
193
|
+
const parsed = schema.safeParse(data);
|
|
194
|
+
if (!parsed.success)
|
|
195
|
+
throw new RecordingsSDKError("invalid_response");
|
|
196
|
+
return parsed.data;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// src/hosted/index.ts
|
|
200
|
+
var recordingCursor = (last) => ({ before: last.createdAt, beforeId: last.id });
|
|
201
|
+
var pasteCursor = (last) => ({ before: last.occurredAt, beforeId: last.id });
|
|
202
|
+
|
|
203
|
+
class HostedRecordingsClient {
|
|
204
|
+
#transport;
|
|
205
|
+
constructor(options) {
|
|
206
|
+
this.#transport = new Transport(options);
|
|
207
|
+
}
|
|
208
|
+
get apiBase() {
|
|
209
|
+
return this.#transport.base;
|
|
210
|
+
}
|
|
211
|
+
async health(options) {
|
|
212
|
+
return output(healthResponseParser, (await this.#transport.request("GET", "/health", false, [200], undefined, options)).data);
|
|
213
|
+
}
|
|
214
|
+
async version(options) {
|
|
215
|
+
return output(versionResponseParser, (await this.#transport.request("GET", "/version", false, [200], undefined, options)).data);
|
|
216
|
+
}
|
|
217
|
+
async ready(options) {
|
|
218
|
+
return output(readyResponseParser, (await this.#transport.request("GET", "/ready", true, [200], undefined, options)).data);
|
|
219
|
+
}
|
|
220
|
+
async account(options) {
|
|
221
|
+
return output(accountResponseParser, (await this.#transport.request("GET", "/account", true, [200], undefined, options)).data);
|
|
222
|
+
}
|
|
223
|
+
async bootstrap(options) {
|
|
224
|
+
return output(accountResponseParser, (await this.#transport.request("POST", "/account/bootstrap", true, [200], {}, options)).data);
|
|
225
|
+
}
|
|
226
|
+
async logout(options) {
|
|
227
|
+
await this.#transport.request("POST", "/auth/logout", true, [204], undefined, options);
|
|
228
|
+
}
|
|
229
|
+
async listRecordings(page = {}, options) {
|
|
230
|
+
return output(recordingListParser, (await this.#transport.request("GET", "/recordings", true, [200], undefined, options, { ...input(pageOptionsParser, page) })).data);
|
|
231
|
+
}
|
|
232
|
+
async getRecording(id, options) {
|
|
233
|
+
return output(recordingResponseParser, (await this.#transport.request("GET", "/recordings/" + input(recordingIDParser, id), true, [200], undefined, options)).data);
|
|
234
|
+
}
|
|
235
|
+
async saveRecording(value, options) {
|
|
236
|
+
return output(recordingResponseParser, (await this.#transport.request("POST", "/recordings", true, [201], input(recordingInputParser, value), options)).data);
|
|
237
|
+
}
|
|
238
|
+
async renameRecording(id, title, options) {
|
|
239
|
+
return output(recordingResponseParser, (await this.#transport.request("PATCH", "/recordings/" + input(recordingIDParser, id), true, [200], input(renameInputParser, { title }), options)).data);
|
|
240
|
+
}
|
|
241
|
+
async deleteRecording(id, options) {
|
|
242
|
+
const response = await this.#transport.request("DELETE", "/recordings/" + input(recordingIDParser, id), true, [202, 204], undefined, options);
|
|
243
|
+
if (response.status === 204)
|
|
244
|
+
return { state: "removed" };
|
|
245
|
+
output(pendingDeletionParser, response.data);
|
|
246
|
+
return { state: "pending" };
|
|
247
|
+
}
|
|
248
|
+
async listPasteReceipts(page = {}, options) {
|
|
249
|
+
return output(pasteListParser, (await this.#transport.request("GET", "/paste-history", true, [200], undefined, options, { ...input(pageOptionsParser, page) })).data);
|
|
250
|
+
}
|
|
251
|
+
async savePasteReceipt(value, options) {
|
|
252
|
+
return output(pasteResponseParser, (await this.#transport.request("POST", "/paste-history", true, [201], input(pasteInputParser, value), options)).data);
|
|
253
|
+
}
|
|
254
|
+
async deletePasteReceipt(id, options) {
|
|
255
|
+
await this.#transport.request("DELETE", "/paste-history/" + input(recordingIDParser, id), true, [204], undefined, options);
|
|
256
|
+
}
|
|
257
|
+
async clearPasteHistory(options) {
|
|
258
|
+
await this.#transport.request("DELETE", "/paste-history", true, [204], undefined, options);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
export {
|
|
262
|
+
recordingCursor,
|
|
263
|
+
pasteCursor,
|
|
264
|
+
RecordingsSDKError,
|
|
265
|
+
HostedRecordingsClient
|
|
266
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type ContractParser } from "../contracts/stream-v1.js";
|
|
2
|
+
export type CredentialProvider = (context: Readonly<{
|
|
3
|
+
apiBase: string;
|
|
4
|
+
signal: AbortSignal;
|
|
5
|
+
}>) => string | Promise<string>;
|
|
6
|
+
export type SDKErrorCode = "invalid_configuration" | "invalid_input" | "credential_unavailable" | "aborted" | "timeout" | "network_error" | "redirect_refused" | "response_too_large" | "invalid_response" | "unauthorized" | "forbidden" | "not_found" | "recording_deleted" | "conflict" | "rate_limited" | "http_error";
|
|
7
|
+
/** Never retains a token, request/response body, URL, native Error cause or server message. */
|
|
8
|
+
export declare class RecordingsSDKError extends Error {
|
|
9
|
+
readonly code: SDKErrorCode;
|
|
10
|
+
readonly status?: number | undefined;
|
|
11
|
+
readonly requestId?: string | undefined;
|
|
12
|
+
constructor(code: SDKErrorCode, status?: number | undefined, requestId?: string | undefined);
|
|
13
|
+
}
|
|
14
|
+
export interface ClientOptions {
|
|
15
|
+
apiBase: string;
|
|
16
|
+
credentialProvider?: CredentialProvider;
|
|
17
|
+
/** Trusted injection for tests/custom runtimes; must honor manual redirects and AbortSignal. */
|
|
18
|
+
fetch?: typeof globalThis.fetch;
|
|
19
|
+
timeoutMs?: number;
|
|
20
|
+
maxResponseBytes?: number;
|
|
21
|
+
}
|
|
22
|
+
export interface RequestOptions {
|
|
23
|
+
signal?: AbortSignal;
|
|
24
|
+
}
|
|
25
|
+
export declare function input<T>(schema: ContractParser<T>, value: unknown): T;
|
|
26
|
+
export declare class Transport {
|
|
27
|
+
#private;
|
|
28
|
+
readonly base: string;
|
|
29
|
+
constructor(options: ClientOptions);
|
|
30
|
+
request(method: string, path: string, authenticated: boolean, statuses: readonly number[], body?: unknown, options?: RequestOptions, query?: Record<string, string | number | undefined>): Promise<{
|
|
31
|
+
status: number;
|
|
32
|
+
data?: unknown;
|
|
33
|
+
}>;
|
|
34
|
+
}
|
|
35
|
+
export declare function output<T>(schema: ContractParser<T>, data: unknown): T;
|
|
36
|
+
//# sourceMappingURL=transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/hosted/transport.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAEnF,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,CAAC,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAC3H,MAAM,MAAM,YAAY,GAAG,uBAAuB,GAAG,eAAe,GAAG,wBAAwB,GAAG,SAAS,GAAG,SAAS,GACrH,eAAe,GAAG,kBAAkB,GAAG,oBAAoB,GAAG,kBAAkB,GAAG,cAAc,GAAG,WAAW,GAC/G,WAAW,GAAG,mBAAmB,GAAG,UAAU,GAAG,cAAc,GAAG,YAAY,CAAC;AAajF,+FAA+F;AAC/F,qBAAa,kBAAmB,SAAQ,KAAK;IAC/B,QAAQ,CAAC,IAAI,EAAE,YAAY;IAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM;IAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM;gBAAzE,IAAI,EAAE,YAAY,EAAW,MAAM,CAAC,EAAE,MAAM,YAAA,EAAW,SAAS,CAAC,EAAE,MAAM,YAAA;CAG/F;AACD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,gGAAgG;IAChG,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AACD,MAAM,WAAW,cAAc;IAAG,MAAM,CAAC,EAAE,WAAW,CAAA;CAAE;AACxD,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,GAAG,CAAC,CAIrE;AAcD,qBAAa,SAAS;;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAKV,OAAO,EAAE,aAAa;IAe5B,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,EACjF,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,GAAE,cAAmB,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAqE9J;AACD,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,GAAG,CAAC,CAIrE"}
|