@relayfile/sdk 0.8.10 → 0.8.11
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/dist/index.d.ts +1 -1
- package/dist/mount-launcher.js +33 -4
- package/dist/setup-types.d.ts +8 -0
- package/dist/setup.js +32 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export { RelayFileClient, DEFAULT_RELAYFILE_BASE_URL, type AccessTokenProvider,
|
|
|
2
2
|
export { RelayfileSetup, RELAYFILE_SDK_VERSION, WorkspaceHandle } from "./setup.js";
|
|
3
3
|
export { type RelayfileCloudLoginOptions, type RelayfileCloudTokenSet, type RelayfileCloudTokenSetupOptions } from "./cloud-login.js";
|
|
4
4
|
export { CloudAbortError, CloudApiError, CloudTimeoutError, InvalidLocalDirError, InvalidMountModeError, InvalidRemotePathError, IntegrationConnectionTimeoutError, MalformedCloudResponseError, MissingConnectionIdError, MountModeUnavailableError, MountReadyTimeoutError, MountSessionInputError, ProviderNotConnectedError, ProviderNotReadyError, RelayfileSetupError, UnknownProviderError } from "./setup-errors.js";
|
|
5
|
-
export { type EnsureMountedWorkspaceInput, WORKSPACE_INTEGRATION_PROVIDERS, type AgentWorkspaceInvite, type AgentWorkspaceInviteOptions, type AgentWorkspaceScopedInviteOptions, type ConnectIntegrationOptions, type ConnectIntegrationResult, type CreateWorkspaceOptions, type JoinWorkspaceOptions, type MountLauncher, type MountLauncherEvent, type MountLauncherInstance, type MountLauncherStart, type MountMode, type MountSessionRequest, type MountSessionResponse, type MountSessionResult, type MountedWorkspaceHandle, type MountedWorkspaceStatus, type MountWorkspaceInput, type ReadMountedWorkspaceStatusInput, type RelayfileSetupOptions, type RelayfileSetupRetryOptions, type WaitForConnectionOptions, type WorkspaceInfo, type WorkspaceIntegrationProvider, type WorkspaceMountEnv, type WorkspaceMountEnvOptions, type WorkspacePermissions } from "./setup-types.js";
|
|
5
|
+
export { type EnsureMountedWorkspaceInput, WORKSPACE_INTEGRATION_PROVIDERS, type AgentWorkspaceInvite, type AgentWorkspaceInviteOptions, type AgentWorkspaceScopedInviteOptions, type ConnectIntegrationOptions, type ConnectIntegrationResult, type CreateWorkspaceOptions, type JoinWorkspaceOptions, type MountLauncher, type MountLauncherEvent, type MountLauncherInstance, type MountLauncherStart, type MountLocalLayout, type MountMode, type MountSessionRequest, type MountSessionResponse, type MountSessionResult, type MountSyncMode, type MountedWorkspaceHandle, type MountedWorkspaceStatus, type MountWorkspaceInput, type ReadMountedWorkspaceStatusInput, type RelayfileSetupOptions, type RelayfileSetupRetryOptions, type WaitForConnectionOptions, type WorkspaceInfo, type WorkspaceIntegrationProvider, type WorkspaceMountEnv, type WorkspaceMountEnvOptions, type WorkspacePermissions } from "./setup-types.js";
|
|
6
6
|
export { RelayFileSync, type RelayFileSyncOptions, type RelayFileSyncPong, type RelayFileSyncReconnectOptions, type RelayFileSyncSocket, type RelayFileSyncStart, type RelayFileSyncState, type RelayFileSyncTokenProvider } from "./sync.js";
|
|
7
7
|
export { onWrite, pathMatches, type OnWriteClient, type OnWriteHandler, type OnWriteHandlerError, type OnWriteOptions } from "./onWrite.js";
|
|
8
8
|
export { InvalidStateError, PayloadTooLargeError, QueueFullError, RelayFileApiError, RevisionConflictError } from "./errors.js";
|
package/dist/mount-launcher.js
CHANGED
|
@@ -20,7 +20,7 @@ export function createDefaultMountLauncher(options = {}) {
|
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
22
|
export async function readMountedWorkspaceStatus(input) {
|
|
23
|
-
const state = await readMountStateFile(input.localDir);
|
|
23
|
+
const state = await readMountStateFile(resolveMountLocalDir(input.localDir, input.remotePath, input.localLayout));
|
|
24
24
|
if (state && !isMountStateStale(state)) {
|
|
25
25
|
return {
|
|
26
26
|
ready: isMountStateReady(state),
|
|
@@ -46,7 +46,8 @@ export async function readMountedWorkspaceStatus(input) {
|
|
|
46
46
|
}
|
|
47
47
|
async function startRelayfileMount(input, options) {
|
|
48
48
|
const localDir = path.resolve(input.env.RELAYFILE_LOCAL_DIR ?? process.cwd());
|
|
49
|
-
const
|
|
49
|
+
const mountLocalDir = resolveMountLocalDir(localDir, input.env.RELAYFILE_REMOTE_PATH, input.env.RELAYFILE_MOUNT_LOCAL_LAYOUT);
|
|
50
|
+
const relayDir = path.join(mountLocalDir, ".relay");
|
|
50
51
|
const logPath = path.join(relayDir, "mount.log");
|
|
51
52
|
const pidPath = path.join(relayDir, "mount.pid");
|
|
52
53
|
await mkdir(relayDir, { recursive: true });
|
|
@@ -54,7 +55,7 @@ async function startRelayfileMount(input, options) {
|
|
|
54
55
|
const command = await resolveRelayfileMountCommand();
|
|
55
56
|
const args = input.background === false ? ["--once"] : [];
|
|
56
57
|
const child = (options.spawnImpl ?? spawn)(command, args, {
|
|
57
|
-
cwd: input.cwd ??
|
|
58
|
+
cwd: input.cwd ?? mountLocalDir,
|
|
58
59
|
env: {
|
|
59
60
|
...process.env,
|
|
60
61
|
...input.env
|
|
@@ -73,7 +74,7 @@ async function startRelayfileMount(input, options) {
|
|
|
73
74
|
pidPath,
|
|
74
75
|
outputBuffer,
|
|
75
76
|
input,
|
|
76
|
-
localDir,
|
|
77
|
+
localDir: mountLocalDir,
|
|
77
78
|
now: options.now ?? Date.now,
|
|
78
79
|
readyPollIntervalMs: options.readyPollIntervalMs ?? DEFAULT_READY_POLL_INTERVAL_MS
|
|
79
80
|
});
|
|
@@ -113,6 +114,8 @@ class RelayfileMountProcessInstance {
|
|
|
113
114
|
workspaceId: this.input.env.RELAYFILE_WORKSPACE ?? "",
|
|
114
115
|
remotePath: this.input.env.RELAYFILE_REMOTE_PATH ?? "/",
|
|
115
116
|
mode: normalizeMountMode(this.input.env.RELAYFILE_MOUNT_MODE) ?? "poll",
|
|
117
|
+
localLayout: normalizeMountLocalLayout(this.input.env.RELAYFILE_MOUNT_LOCAL_LAYOUT),
|
|
118
|
+
syncMode: normalizeMountSyncMode(this.input.env.RELAYFILE_MOUNT_SYNC_MODE),
|
|
116
119
|
relayfileBaseUrl: this.input.env.RELAYFILE_BASE_URL ?? "",
|
|
117
120
|
relayfileToken: this.input.env.RELAYFILE_TOKEN ?? "",
|
|
118
121
|
expiresAt: null,
|
|
@@ -251,6 +254,32 @@ function isMountStateStale(state) {
|
|
|
251
254
|
function normalizeMountMode(mode) {
|
|
252
255
|
return mode === "fuse" ? "fuse" : mode === "poll" ? "poll" : undefined;
|
|
253
256
|
}
|
|
257
|
+
function normalizeMountLocalLayout(layout) {
|
|
258
|
+
return layout === "scoped" ? "scoped" : "exact";
|
|
259
|
+
}
|
|
260
|
+
function normalizeMountSyncMode(mode) {
|
|
261
|
+
return mode === "write-only" ? "write-only" : "mirror";
|
|
262
|
+
}
|
|
263
|
+
function resolveMountLocalDir(localDir, remotePath, localLayout) {
|
|
264
|
+
const root = path.resolve(localDir);
|
|
265
|
+
if (normalizeMountLocalLayout(localLayout) !== "scoped") {
|
|
266
|
+
return root;
|
|
267
|
+
}
|
|
268
|
+
const normalizedRemote = normalizeRemotePath(remotePath);
|
|
269
|
+
if (normalizedRemote === "/") {
|
|
270
|
+
return root;
|
|
271
|
+
}
|
|
272
|
+
return path.join(root, ...normalizedRemote.split("/").filter(Boolean));
|
|
273
|
+
}
|
|
274
|
+
function normalizeRemotePath(remotePath) {
|
|
275
|
+
const trimmed = typeof remotePath === "string" ? remotePath.trim() : "";
|
|
276
|
+
if (!trimmed || trimmed === "/") {
|
|
277
|
+
return "/";
|
|
278
|
+
}
|
|
279
|
+
const slashNormalized = trimmed.replace(/\\/g, "/");
|
|
280
|
+
const normalized = path.posix.normalize(slashNormalized.startsWith("/") ? slashNormalized : `/${slashNormalized}`);
|
|
281
|
+
return normalized === "/" ? "/" : normalized.replace(/\/+$/, "");
|
|
282
|
+
}
|
|
254
283
|
function normalizeIsoString(value) {
|
|
255
284
|
if (typeof value !== "string" || value.trim() === "") {
|
|
256
285
|
return undefined;
|
package/dist/setup-types.d.ts
CHANGED
|
@@ -67,6 +67,8 @@ export interface WorkspaceMountEnvOptions {
|
|
|
67
67
|
}
|
|
68
68
|
export type WorkspaceMountEnv = Record<string, string>;
|
|
69
69
|
export type MountMode = "poll" | "fuse";
|
|
70
|
+
export type MountLocalLayout = "exact" | "scoped";
|
|
71
|
+
export type MountSyncMode = "mirror" | "write-only";
|
|
70
72
|
export interface MountSessionRequest {
|
|
71
73
|
localDir: string;
|
|
72
74
|
remotePath?: string;
|
|
@@ -98,6 +100,8 @@ export interface MountSessionResult {
|
|
|
98
100
|
remotePath: string;
|
|
99
101
|
localDir: string;
|
|
100
102
|
mode: MountMode;
|
|
103
|
+
localLayout: MountLocalLayout;
|
|
104
|
+
syncMode: MountSyncMode;
|
|
101
105
|
scopes: string[];
|
|
102
106
|
tokenIssuedAt: string | null;
|
|
103
107
|
expiresAt: string | null;
|
|
@@ -122,6 +126,8 @@ export interface ReadMountedWorkspaceStatusInput {
|
|
|
122
126
|
workspaceId: string;
|
|
123
127
|
remotePath: string;
|
|
124
128
|
mode: MountMode;
|
|
129
|
+
localLayout?: MountLocalLayout;
|
|
130
|
+
syncMode?: MountSyncMode;
|
|
125
131
|
relayfileBaseUrl: string;
|
|
126
132
|
relayfileToken: string;
|
|
127
133
|
expiresAt: string | null;
|
|
@@ -167,6 +173,8 @@ export interface MountWorkspaceInput {
|
|
|
167
173
|
localDir: string;
|
|
168
174
|
remotePath?: string;
|
|
169
175
|
mode?: MountMode;
|
|
176
|
+
localLayout?: MountLocalLayout;
|
|
177
|
+
syncMode?: MountSyncMode;
|
|
170
178
|
background?: boolean;
|
|
171
179
|
agentName?: string;
|
|
172
180
|
scopes?: string[];
|
package/dist/setup.js
CHANGED
|
@@ -16,6 +16,8 @@ const DEFAULT_WAIT_INTERVAL_MS = 2_000;
|
|
|
16
16
|
const DEFAULT_WAIT_TIMEOUT_MS = 300_000;
|
|
17
17
|
const DEFAULT_MOUNT_READY_TIMEOUT_MS = 60_000;
|
|
18
18
|
const DEFAULT_MOUNT_AGENT_NAME = "relayfile-mount";
|
|
19
|
+
const DEFAULT_MOUNT_LOCAL_LAYOUT = "exact";
|
|
20
|
+
const DEFAULT_MOUNT_SYNC_MODE = "mirror";
|
|
19
21
|
const TOKEN_REFRESH_AGE_MS = 55 * 60 * 1000;
|
|
20
22
|
const nodeOnlyMountLauncher = {
|
|
21
23
|
async start() {
|
|
@@ -142,6 +144,8 @@ export class RelayfileSetup {
|
|
|
142
144
|
localDir: normalized.localDir,
|
|
143
145
|
remotePath: normalized.remotePath,
|
|
144
146
|
mode: normalized.mode,
|
|
147
|
+
localLayout: normalized.localLayout,
|
|
148
|
+
syncMode: normalized.syncMode,
|
|
145
149
|
background: normalized.background,
|
|
146
150
|
agentName: normalized.agentName,
|
|
147
151
|
scopes: normalized.scopes,
|
|
@@ -246,13 +250,18 @@ export class RelayfileSetup {
|
|
|
246
250
|
: undefined
|
|
247
251
|
});
|
|
248
252
|
try {
|
|
249
|
-
|
|
253
|
+
const session = validateMountSessionResponse(await workspace.requestJson({
|
|
250
254
|
operation: "mountWorkspace",
|
|
251
255
|
method: "POST",
|
|
252
256
|
path: `api/v1/workspaces/${encodeURIComponent(workspace.workspaceId)}/relayfile/mount-session`,
|
|
253
257
|
body: request,
|
|
254
258
|
signal: input.signal
|
|
255
259
|
}), input.localDir);
|
|
260
|
+
return {
|
|
261
|
+
...session,
|
|
262
|
+
localLayout: input.localLayout,
|
|
263
|
+
syncMode: input.syncMode
|
|
264
|
+
};
|
|
256
265
|
}
|
|
257
266
|
catch (error) {
|
|
258
267
|
throw mapMountSessionError(error, request);
|
|
@@ -731,6 +740,8 @@ class MountedWorkspaceHandleImpl {
|
|
|
731
740
|
workspaceId: this.workspaceId,
|
|
732
741
|
remotePath: this.remotePath,
|
|
733
742
|
mode: this.mode,
|
|
743
|
+
localLayout: this.mountSession.localLayout,
|
|
744
|
+
syncMode: this.mountSession.syncMode,
|
|
734
745
|
relayfileBaseUrl: this.mountSession.relayfileBaseUrl,
|
|
735
746
|
relayfileToken: this.mountSession.relayfileToken,
|
|
736
747
|
expiresAt: this.expiresAt,
|
|
@@ -837,6 +848,8 @@ function validateMountSessionResponse(payload, localDir) {
|
|
|
837
848
|
remotePath: requireStringField(payload, "remotePath"),
|
|
838
849
|
localDir,
|
|
839
850
|
mode: requireMountModeField(payload, "mode"),
|
|
851
|
+
localLayout: DEFAULT_MOUNT_LOCAL_LAYOUT,
|
|
852
|
+
syncMode: DEFAULT_MOUNT_SYNC_MODE,
|
|
840
853
|
scopes: requireStringArrayField(payload, "scopes"),
|
|
841
854
|
tokenIssuedAt: readNullableStringField(payload, "tokenIssuedAt"),
|
|
842
855
|
expiresAt: readNullableStringField(payload, "expiresAt"),
|
|
@@ -930,6 +943,8 @@ function normalizeMountWorkspaceInput(input) {
|
|
|
930
943
|
localDir: resolveLocalDir(localDir),
|
|
931
944
|
remotePath: normalizeMountRemotePath(input.remotePath),
|
|
932
945
|
mode: normalizeMountModeInput(input.mode),
|
|
946
|
+
localLayout: normalizeMountLocalLayoutInput(input.localLayout),
|
|
947
|
+
syncMode: normalizeMountSyncModeInput(input.syncMode),
|
|
933
948
|
background: input.background !== false,
|
|
934
949
|
agentName: normalizeNonEmptyString(input.agentName),
|
|
935
950
|
scopes: input.scopes && input.scopes.length > 0 ? [...input.scopes] : undefined,
|
|
@@ -954,6 +969,20 @@ function normalizeMountModeInput(mode) {
|
|
|
954
969
|
}
|
|
955
970
|
return normalized;
|
|
956
971
|
}
|
|
972
|
+
function normalizeMountLocalLayoutInput(layout) {
|
|
973
|
+
const normalized = normalizeNonEmptyString(layout) ?? DEFAULT_MOUNT_LOCAL_LAYOUT;
|
|
974
|
+
if (normalized !== "exact" && normalized !== "scoped") {
|
|
975
|
+
throw new MountSessionInputError(`Invalid localLayout "${normalized}" for mount session.`);
|
|
976
|
+
}
|
|
977
|
+
return normalized;
|
|
978
|
+
}
|
|
979
|
+
function normalizeMountSyncModeInput(mode) {
|
|
980
|
+
const normalized = normalizeNonEmptyString(mode) ?? DEFAULT_MOUNT_SYNC_MODE;
|
|
981
|
+
if (normalized !== "mirror" && normalized !== "write-only") {
|
|
982
|
+
throw new MountSessionInputError(`Invalid syncMode "${normalized}" for mount session.`);
|
|
983
|
+
}
|
|
984
|
+
return normalized;
|
|
985
|
+
}
|
|
957
986
|
function normalizeMountRemotePath(remotePath) {
|
|
958
987
|
const normalized = normalizeNonEmptyString(remotePath) ?? "/";
|
|
959
988
|
if (normalized.includes("\u0000")) {
|
|
@@ -1052,6 +1081,8 @@ function buildMountedWorkspaceEnv(mountSession) {
|
|
|
1052
1081
|
RELAYFILE_REMOTE_PATH: mountSession.remotePath,
|
|
1053
1082
|
RELAYFILE_LOCAL_DIR: mountSession.localDir,
|
|
1054
1083
|
RELAYFILE_MOUNT_MODE: mountSession.mode,
|
|
1084
|
+
RELAYFILE_MOUNT_LOCAL_LAYOUT: mountSession.localLayout,
|
|
1085
|
+
RELAYFILE_MOUNT_SYNC_MODE: mountSession.syncMode,
|
|
1055
1086
|
RELAYCAST_API_KEY: mountSession.relaycastApiKey,
|
|
1056
1087
|
RELAY_API_KEY: mountSession.relaycastApiKey,
|
|
1057
1088
|
RELAYCAST_BASE_URL: relaycastBaseUrl,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@relayfile/sdk",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.11",
|
|
4
4
|
"description": "TypeScript SDK for relayfile — real-time filesystem for humans and agents",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"prepublishOnly": "npm run build"
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"@relayfile/core": "0.8.
|
|
58
|
+
"@relayfile/core": "0.8.11",
|
|
59
59
|
"ignore": "^7.0.5",
|
|
60
60
|
"tar": "^7.5.10"
|
|
61
61
|
},
|