@ystemsrx/cfshare 0.1.5 → 0.1.6
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/src/cli.js +131 -1
- package/dist/src/manager.d.ts +15 -1
- package/dist/src/manager.d.ts.map +1 -1
- package/dist/src/manager.js +479 -110
- package/dist/src/tools.js +1 -1
- package/package.json +1 -1
- package/src/cli.ts +148 -1
- package/src/manager.ts +569 -115
- package/src/tools.ts +1 -1
package/dist/src/cli.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
3
|
+
import { writeFileSync } from "node:fs";
|
|
2
4
|
import fs from "node:fs/promises";
|
|
3
5
|
import os from "node:os";
|
|
4
6
|
import path from "node:path";
|
|
5
7
|
import process from "node:process";
|
|
6
8
|
import { CfshareManager } from "./manager.js";
|
|
9
|
+
const DETACHED_HANDOFF_TIMEOUT_MS = 45_000;
|
|
7
10
|
const TOOL_NAMES = new Set([
|
|
8
11
|
"env_check",
|
|
9
12
|
"expose_port",
|
|
@@ -120,6 +123,15 @@ function parseArgs(argv) {
|
|
|
120
123
|
i += 1;
|
|
121
124
|
continue;
|
|
122
125
|
}
|
|
126
|
+
if (token === "--detached-worker") {
|
|
127
|
+
opts.detachedWorker = true;
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
if (token === "--handoff-file") {
|
|
131
|
+
opts.handoffFile = assertValue(argv, i + 1, token);
|
|
132
|
+
i += 1;
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
123
135
|
if (token === "--keep-alive") {
|
|
124
136
|
opts.keepAlive = true;
|
|
125
137
|
continue;
|
|
@@ -218,6 +230,109 @@ function shouldKeepAlive(keepAliveFlag) {
|
|
|
218
230
|
}
|
|
219
231
|
return false;
|
|
220
232
|
}
|
|
233
|
+
function isExposeCommand(command) {
|
|
234
|
+
return command === "expose_port" || command === "expose_files";
|
|
235
|
+
}
|
|
236
|
+
function extractHandoffFileFromArgv(argv) {
|
|
237
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
238
|
+
if (argv[i] !== "--handoff-file") {
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
const value = argv[i + 1];
|
|
242
|
+
if (value && !value.startsWith("-")) {
|
|
243
|
+
return value;
|
|
244
|
+
}
|
|
245
|
+
return undefined;
|
|
246
|
+
}
|
|
247
|
+
return undefined;
|
|
248
|
+
}
|
|
249
|
+
function stripDetachedControlArgs(argv) {
|
|
250
|
+
const out = [];
|
|
251
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
252
|
+
const token = argv[i];
|
|
253
|
+
if (token === "--keep-alive" || token === "--no-keep-alive" || token === "--detached-worker") {
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
if (token === "--handoff-file") {
|
|
257
|
+
i += 1;
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
out.push(token);
|
|
261
|
+
}
|
|
262
|
+
return out;
|
|
263
|
+
}
|
|
264
|
+
function makeHandoffPath() {
|
|
265
|
+
return path.join(os.tmpdir(), `cfshare-handoff-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}.json`);
|
|
266
|
+
}
|
|
267
|
+
async function writeHandoffFile(filePath, payload) {
|
|
268
|
+
if (!filePath) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
272
|
+
const tempPath = `${filePath}.${process.pid}.tmp`;
|
|
273
|
+
await fs.writeFile(tempPath, JSON.stringify(payload), "utf8");
|
|
274
|
+
await fs.rename(tempPath, filePath);
|
|
275
|
+
}
|
|
276
|
+
async function waitForDetachedHandoff(filePath, workerPid) {
|
|
277
|
+
const startedAt = Date.now();
|
|
278
|
+
while (Date.now() - startedAt < DETACHED_HANDOFF_TIMEOUT_MS) {
|
|
279
|
+
try {
|
|
280
|
+
const raw = await fs.readFile(filePath, "utf8");
|
|
281
|
+
await fs.rm(filePath, { force: true });
|
|
282
|
+
const parsed = JSON.parse(raw);
|
|
283
|
+
if (parsed.ok === true) {
|
|
284
|
+
return parsed.result;
|
|
285
|
+
}
|
|
286
|
+
if (typeof parsed.error === "string" && parsed.error.trim()) {
|
|
287
|
+
throw new Error(parsed.error);
|
|
288
|
+
}
|
|
289
|
+
throw new Error("failed to start detached exposure");
|
|
290
|
+
}
|
|
291
|
+
catch (error) {
|
|
292
|
+
const errno = error;
|
|
293
|
+
if (errno?.code !== "ENOENT" && !(error instanceof SyntaxError)) {
|
|
294
|
+
throw error;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
298
|
+
}
|
|
299
|
+
if (workerPid) {
|
|
300
|
+
try {
|
|
301
|
+
process.kill(workerPid, "SIGTERM");
|
|
302
|
+
}
|
|
303
|
+
catch {
|
|
304
|
+
// ignore best-effort cleanup
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
throw new Error("timed out waiting for detached exposure startup");
|
|
308
|
+
}
|
|
309
|
+
async function runDetachedExposureWorker() {
|
|
310
|
+
const scriptArg = process.argv[1];
|
|
311
|
+
if (!scriptArg) {
|
|
312
|
+
throw new Error("unable to resolve cli entry");
|
|
313
|
+
}
|
|
314
|
+
const scriptPath = path.resolve(scriptArg);
|
|
315
|
+
const handoffFile = makeHandoffPath();
|
|
316
|
+
const childArgs = [
|
|
317
|
+
scriptPath,
|
|
318
|
+
...stripDetachedControlArgs(process.argv.slice(2)),
|
|
319
|
+
"--keep-alive",
|
|
320
|
+
"--detached-worker",
|
|
321
|
+
"--handoff-file",
|
|
322
|
+
handoffFile,
|
|
323
|
+
"--compact",
|
|
324
|
+
];
|
|
325
|
+
const child = spawn(process.execPath, childArgs, {
|
|
326
|
+
detached: true,
|
|
327
|
+
stdio: "ignore",
|
|
328
|
+
env: {
|
|
329
|
+
...process.env,
|
|
330
|
+
CFSHARE_DETACHED_WORKER: "1",
|
|
331
|
+
},
|
|
332
|
+
});
|
|
333
|
+
child.unref();
|
|
334
|
+
return await waitForDetachedHandoff(handoffFile, child.pid ?? undefined);
|
|
335
|
+
}
|
|
221
336
|
async function waitUntilExposureStops(manager, id) {
|
|
222
337
|
await new Promise((resolve, reject) => {
|
|
223
338
|
let stopping = false;
|
|
@@ -287,7 +402,7 @@ async function runTool(manager, command, params, opts) {
|
|
|
287
402
|
return await manager.exposeFiles(params, ctx);
|
|
288
403
|
}
|
|
289
404
|
if (command === "exposure_list") {
|
|
290
|
-
return manager.exposureList();
|
|
405
|
+
return await manager.exposureList();
|
|
291
406
|
}
|
|
292
407
|
if (command === "exposure_get") {
|
|
293
408
|
return await manager.exposureGet(params);
|
|
@@ -354,8 +469,14 @@ async function main() {
|
|
|
354
469
|
: {};
|
|
355
470
|
const params = asObject(paramsInput, "params");
|
|
356
471
|
const config = asObject(configInput, "config");
|
|
472
|
+
if (isExposeCommand(command) && !shouldKeepAlive(options.keepAlive) && !options.detachedWorker) {
|
|
473
|
+
const detachedResult = await runDetachedExposureWorker();
|
|
474
|
+
process.stdout.write(`${JSON.stringify(detachedResult, null, options.compact ? undefined : 2)}\n`);
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
357
477
|
const manager = new CfshareManager(createRuntimeApi(config));
|
|
358
478
|
const result = await runTool(manager, command, params, options);
|
|
479
|
+
await writeHandoffFile(options.handoffFile, { ok: true, result });
|
|
359
480
|
process.stdout.write(`${JSON.stringify(result, null, options.compact ? undefined : 2)}\n`);
|
|
360
481
|
if (shouldKeepAlive(options.keepAlive)) {
|
|
361
482
|
const exposureId = typeof result === "object" && result ? result.id : undefined;
|
|
@@ -368,6 +489,15 @@ async function main() {
|
|
|
368
489
|
}
|
|
369
490
|
void main().catch((error) => {
|
|
370
491
|
const message = error instanceof Error ? error.message : String(error);
|
|
492
|
+
const handoffFile = extractHandoffFileFromArgv(process.argv.slice(2));
|
|
493
|
+
if (handoffFile) {
|
|
494
|
+
try {
|
|
495
|
+
writeFileSync(handoffFile, JSON.stringify({ ok: false, error: message }), "utf8");
|
|
496
|
+
}
|
|
497
|
+
catch {
|
|
498
|
+
// ignore handoff write failure
|
|
499
|
+
}
|
|
500
|
+
}
|
|
371
501
|
process.stderr.write(`cfshare error: ${message}\n`);
|
|
372
502
|
process.exit(1);
|
|
373
503
|
});
|
package/dist/src/manager.d.ts
CHANGED
|
@@ -43,6 +43,7 @@ export declare class CfshareManager {
|
|
|
43
43
|
private readonly workspaceRoot;
|
|
44
44
|
private readonly auditFile;
|
|
45
45
|
private readonly sessionsFile;
|
|
46
|
+
private readonly sessionsDir;
|
|
46
47
|
private readonly exportsDir;
|
|
47
48
|
private initialized;
|
|
48
49
|
private initializing?;
|
|
@@ -58,8 +59,16 @@ export declare class CfshareManager {
|
|
|
58
59
|
private reloadPolicy;
|
|
59
60
|
private appendLog;
|
|
60
61
|
private writeAudit;
|
|
62
|
+
private sessionRecordPath;
|
|
63
|
+
private toPersistedSessionRecord;
|
|
64
|
+
private parsePersistedSessionRecord;
|
|
65
|
+
private readPersistedSessions;
|
|
66
|
+
private writePersistedSessionRecord;
|
|
67
|
+
private deletePersistedSessionRecord;
|
|
68
|
+
private isProcessAlive;
|
|
61
69
|
private persistSessionsSnapshot;
|
|
62
70
|
private makeAccessState;
|
|
71
|
+
private makeResponsePublicUrlFromValues;
|
|
63
72
|
private makeResponsePublicUrl;
|
|
64
73
|
private buildRateLimiter;
|
|
65
74
|
private isAuthorized;
|
|
@@ -99,13 +108,18 @@ export declare class CfshareManager {
|
|
|
99
108
|
max_downloads?: number;
|
|
100
109
|
};
|
|
101
110
|
}, ctx?: ToolContext): Promise<Record<string, unknown>>;
|
|
102
|
-
exposureList(): ExposureRecord[]
|
|
111
|
+
exposureList(): Promise<ExposureRecord[]>;
|
|
103
112
|
private normalizeRequestedIds;
|
|
113
|
+
private matchesExposureFilterByValues;
|
|
104
114
|
private matchesExposureFilter;
|
|
115
|
+
private loadSessionLookupMap;
|
|
105
116
|
private resolveExposureSelection;
|
|
106
117
|
private buildExposureDetail;
|
|
118
|
+
private probePublicEndpoint;
|
|
119
|
+
private buildPersistedExposureDetail;
|
|
107
120
|
private projectExposureDetail;
|
|
108
121
|
private makeExposureGetNotFound;
|
|
122
|
+
private stopPersistedSession;
|
|
109
123
|
exposureGet(params: ExposureGetParams): Promise<Record<string, unknown>>;
|
|
110
124
|
stopExposure(idOrIds: string | string[], opts?: {
|
|
111
125
|
reason?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/manager.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAK7D,OAAO,KAAK,EACV,UAAU,EAEV,UAAU,EAGV,cAAc,
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/manager.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAK7D,OAAO,KAAK,EACV,UAAU,EAEV,UAAU,EAGV,cAAc,EAGd,cAAc,EACd,YAAY,EACZ,oBAAoB,EAGrB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,EAAE,QAAQ,GAAG,aAAa,GAAG,cAAc,CAAC,CAAC;AA+CnG,KAAK,cAAc,GAAG;IACpB,WAAW,EAAE;QACX,EAAE,EAAE,OAAO,CAAC;QACZ,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,KAAK,cAAc,GAAG;IACpB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB,CAAC;AAEF,KAAK,gBAAgB,GACjB,IAAI,GACJ,MAAM,GACN,QAAQ,GACR,MAAM,GACN,YAAY,GACZ,YAAY,GACZ,WAAW,GACX,OAAO,GACP,cAAc,GACd,YAAY,GACZ,UAAU,GACV,YAAY,CAAC;AAEjB,KAAK,iBAAiB,GAAG;IACvB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,MAAM,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC5B,IAAI,CAAC,EAAE;QACL,YAAY,CAAC,EAAE,OAAO,CAAC;KACxB,CAAC;CACH,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,KAAK,CAAC;CACzC,CAAC;AAonBF,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA8B;IACrD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA4B;IACxD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAsB;IACnD,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;IAC9C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IAEpC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,YAAY,CAAC,CAAgB;IACrC,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,aAAa,CAAY;IACjC,OAAO,CAAC,uBAAuB,CAAC,CAAS;IACzC,OAAO,CAAC,UAAU,CAAC,CAAiB;IACpC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsC;gBAEnD,GAAG,EAAE,iBAAiB;YAoBpB,iBAAiB;YAUjB,UAAU;YAUV,YAAY;IAW1B,OAAO,CAAC,SAAS;YAQH,UAAU;IAQxB,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,wBAAwB;IAyBhC,OAAO,CAAC,2BAA2B;YAwDrB,qBAAqB;YAoErB,2BAA2B;YAO3B,4BAA4B;IAI1C,OAAO,CAAC,cAAc;YAYR,uBAAuB;IAiCrC,OAAO,CAAC,eAAe;IA8BvB,OAAO,CAAC,+BAA+B;IAiBvC,OAAO,CAAC,qBAAqB;IAI7B,OAAO,CAAC,gBAAgB;IAoBxB,OAAO,CAAC,YAAY;YAeN,iBAAiB;YAsFjB,gBAAgB;YAqHhB,gBAAgB;YA2BhB,sBAAsB;YA4CtB,eAAe;YA6Nf,2BAA2B;YAsB3B,qBAAqB;IAyDnC,OAAO,CAAC,kBAAkB;YAWZ,qBAAqB;IA0BnC,OAAO,CAAC,gCAAgC;IAuCxC,OAAO,CAAC,oBAAoB;IAmB5B,OAAO,CAAC,UAAU;YAUJ,WAAW;YAUX,WAAW;YA0FX,oBAAoB;YA6CpB,gBAAgB;IA+BxB,QAAQ,IAAI,OAAO,CAAC,cAAc,CAAC;IAmDnC,UAAU,CACd,MAAM,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE;YACL,WAAW,CAAC,EAAE,MAAM,CAAC;YACrB,MAAM,CAAC,EAAE,UAAU,CAAC;YACpB,cAAc,CAAC,EAAE,OAAO,CAAC;YACzB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;SAC5B,CAAC;KACH,GACA,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAmH7B,WAAW,CACf,MAAM,EAAE;QACN,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,IAAI,CAAC,EAAE;YACL,IAAI,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;YACxB,YAAY,CAAC,EAAE,oBAAoB,CAAC;YACpC,WAAW,CAAC,EAAE,MAAM,CAAC;YACrB,MAAM,CAAC,EAAE,UAAU,CAAC;YACpB,aAAa,CAAC,EAAE,MAAM,CAAC;SACxB,CAAC;KACH,EACD,GAAG,CAAC,EAAE,WAAW,GAChB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAiJ7B,YAAY,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAuB/C,OAAO,CAAC,qBAAqB;IAiB7B,OAAO,CAAC,6BAA6B;IAiBrC,OAAO,CAAC,qBAAqB;YAIf,oBAAoB;IAmBlC,OAAO,CAAC,wBAAwB;YAqFlB,mBAAmB;YA4DnB,mBAAmB;YAkCnB,4BAA4B;IA0D1C,OAAO,CAAC,qBAAqB;IAwB7B,OAAO,CAAC,uBAAuB;YAQjB,oBAAoB;IAsC5B,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAkFxE,YAAY,CAChB,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,EAC1B,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,GACjE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAkGnC,OAAO,CAAC,eAAe;IA2BvB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IA0CpF,WAAW,CACf,MAAM,EAAE,aAAa,GAAG,QAAQ,GAAG,YAAY,EAC/C,IAAI,CAAC,EAAE;QACL,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;KAC5B,GACA,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAuDnC,OAAO,CAAC,SAAS;YAsBH,cAAc;YAad,KAAK;IA2Db,UAAU,CAAC,OAAO,CAAC,EAAE;QACzB,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QACxB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IA8BnB,WAAW,CAAC,KAAK,CAAC,EAAE;QACxB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QACxB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAmCrC"}
|