@fenglimg/fabric-shared 2.2.0-rc.1 → 2.2.0-rc.10

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.
@@ -1,109 +1,9 @@
1
- // src/node/atomic-write.ts
2
- import { appendFile, mkdir, open, rename, stat, unlink, writeFile } from "fs/promises";
3
- import { dirname } from "path";
4
- function makeTmpSuffix() {
5
- const rand = Math.floor(Math.random() * 65535).toString(16).padStart(4, "0");
6
- return `.${process.pid}.${Date.now()}.${rand}.tmp`;
7
- }
8
- async function atomicWriteText(path, content, opts) {
9
- const tmpPath = path + makeTmpSuffix();
10
- try {
11
- if (opts?.fsync) {
12
- const fd = await open(tmpPath, "w");
13
- try {
14
- await fd.writeFile(content, "utf8");
15
- await fd.datasync();
16
- } finally {
17
- await fd.close();
18
- }
19
- } else {
20
- await writeFile(tmpPath, content, "utf8");
21
- }
22
- await rename(tmpPath, path);
23
- } catch (err) {
24
- try {
25
- await unlink(tmpPath);
26
- } catch {
27
- }
28
- throw err;
29
- }
30
- }
31
- async function atomicWriteJson(path, value, opts) {
32
- const indent = opts?.indent ?? 2;
33
- const content = JSON.stringify(value, null, indent) + "\n";
34
- await atomicWriteText(path, content, { fsync: opts?.fsync });
35
- }
36
- function isErrnoException(err) {
37
- return err instanceof Error && typeof err.code === "string";
38
- }
39
- function sleep(ms) {
40
- return new Promise((resolve) => setTimeout(resolve, ms));
41
- }
42
- async function withFileLock(lockPath, fn, opts = {}) {
43
- const staleMs = opts.staleMs ?? 1e4;
44
- const retryDelayMs = opts.retryDelayMs ?? 20;
45
- const maxWaitMs = opts.maxWaitMs ?? 1e4;
46
- await mkdir(dirname(lockPath), { recursive: true });
47
- const start = Date.now();
48
- for (; ; ) {
49
- let handle;
50
- try {
51
- handle = await open(lockPath, "wx");
52
- } catch (err) {
53
- if (!isErrnoException(err) || err.code !== "EEXIST") throw err;
54
- try {
55
- const st = await stat(lockPath);
56
- if (Date.now() - st.mtimeMs > staleMs) {
57
- await unlink(lockPath).catch(() => void 0);
58
- continue;
59
- }
60
- } catch {
61
- continue;
62
- }
63
- if (Date.now() - start > maxWaitMs) {
64
- throw new Error(`withFileLock: timed out acquiring ${lockPath} after ${maxWaitMs}ms`);
65
- }
66
- await sleep(retryDelayMs);
67
- continue;
68
- }
69
- try {
70
- await handle.close();
71
- return await fn();
72
- } finally {
73
- await unlink(lockPath).catch(() => void 0);
74
- }
75
- }
76
- }
77
- function createLedgerWriteQueue() {
78
- const chains = /* @__PURE__ */ new Map();
79
- async function doAppend(path, line) {
80
- const normalized = line.endsWith("\n") ? line : line + "\n";
81
- await appendFile(path, normalized, "utf8");
82
- }
83
- function enqueue(path, work) {
84
- const prev = chains.get(path) ?? Promise.resolve();
85
- const result = prev.catch(() => void 0).then(() => work());
86
- const chainSlot = result.then(
87
- () => void 0,
88
- () => void 0
89
- );
90
- chains.set(path, chainSlot);
91
- chainSlot.finally(() => {
92
- if (chains.get(path) === chainSlot) {
93
- chains.delete(path);
94
- }
95
- });
96
- return result;
97
- }
98
- return {
99
- append(path, line) {
100
- return enqueue(path, () => doAppend(path, line));
101
- },
102
- runExclusive(path, fn) {
103
- return enqueue(path, fn);
104
- }
105
- };
106
- }
1
+ import {
2
+ atomicWriteJson,
3
+ atomicWriteText,
4
+ createLedgerWriteQueue,
5
+ withFileLock
6
+ } from "../chunk-C7WZPYZE.js";
107
7
  export {
108
8
  atomicWriteJson,
109
9
  atomicWriteText,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  MCPError
3
- } from "../chunk-3SZRB42B.js";
3
+ } from "../chunk-O6GIHZF3.js";
4
4
 
5
5
  // src/node/mcp-payload-guard.ts
6
6
  var McpPayloadTooLargeError = class extends MCPError {
package/dist/node.d.ts CHANGED
@@ -11,4 +11,13 @@ type FrameworkInfo = {
11
11
  type TechProfile = FrameworkInfo;
12
12
  declare function detectFramework(root: string): FrameworkInfo;
13
13
 
14
- export { type FrameworkInfo, type TechProfile, detectFramework };
14
+ interface ServeLockState {
15
+ pid: number;
16
+ acquiredAt: number;
17
+ host?: string;
18
+ }
19
+ declare function serveLockPath(projectRoot: string): string;
20
+ declare function isAlive(pid: number): boolean;
21
+ declare function readServeLockState(projectRoot: string): ServeLockState | null;
22
+
23
+ export { type FrameworkInfo, type ServeLockState, type TechProfile, detectFramework, isAlive, readServeLockState, serveLockPath };
package/dist/node.js CHANGED
@@ -170,6 +170,37 @@ function collectProjectFileEvidence(root, relativePaths) {
170
170
  function compactStrings(values) {
171
171
  return [...new Set(values.filter((value) => value !== null && value !== void 0 && value.length > 0))];
172
172
  }
173
+
174
+ // src/node/serve-lock.ts
175
+ import fs from "fs";
176
+ import path from "path";
177
+ var SERVE_LOCK_FILENAME = ".serve.lock";
178
+ function serveLockPath(projectRoot) {
179
+ return path.join(projectRoot, ".fabric", SERVE_LOCK_FILENAME);
180
+ }
181
+ function isAlive(pid) {
182
+ try {
183
+ process.kill(pid, 0);
184
+ return true;
185
+ } catch (e) {
186
+ const err = e;
187
+ if (err.code === "ESRCH") return false;
188
+ if (err.code === "EPERM") return true;
189
+ throw e;
190
+ }
191
+ }
192
+ function readServeLockState(projectRoot) {
193
+ const p = serveLockPath(projectRoot);
194
+ if (!fs.existsSync(p)) return null;
195
+ try {
196
+ return JSON.parse(fs.readFileSync(p, "utf8"));
197
+ } catch {
198
+ return null;
199
+ }
200
+ }
173
201
  export {
174
- detectFramework
202
+ detectFramework,
203
+ isAlive,
204
+ readServeLockState,
205
+ serveLockPath
175
206
  };