unfairly 0.8.3 → 0.8.4
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/CHANGELOG.md +4 -0
- package/LICENSE +15 -0
- package/dist/auth/browser-flow.d.ts +0 -1
- package/dist/auth/browser-flow.js +5 -81
- package/dist/cmd/connect.d.ts +0 -1
- package/dist/cmd/connect.js +1 -164
- package/dist/cmd/init.d.ts +0 -1
- package/dist/cmd/init.js +2 -138
- package/dist/cmd/invite.d.ts +0 -1
- package/dist/cmd/invite.js +4 -73
- package/dist/cmd/join.d.ts +0 -1
- package/dist/cmd/join.js +1 -91
- package/dist/cmd/login.d.ts +0 -1
- package/dist/cmd/login.js +3 -41
- package/dist/cmd/mcp.d.ts +0 -1
- package/dist/cmd/mcp.js +2 -86
- package/dist/cmd/pace.d.ts +2 -2
- package/dist/cmd/pace.js +4 -426
- package/dist/cmd/parse-share-input.d.ts +0 -1
- package/dist/cmd/parse-share-input.js +1 -56
- package/dist/cmd/pull.d.ts +0 -1
- package/dist/cmd/pull.js +7 -143
- package/dist/cmd/push.d.ts +0 -1
- package/dist/cmd/push.js +1 -85
- package/dist/cmd/resolve.d.ts +0 -1
- package/dist/cmd/resolve.js +1 -35
- package/dist/cmd/setup.d.ts +0 -1
- package/dist/cmd/setup.js +2 -345
- package/dist/cmd/status-card.d.ts +0 -1
- package/dist/cmd/status-card.js +2 -156
- package/dist/cmd/status.d.ts +0 -1
- package/dist/cmd/status.js +3 -29
- package/dist/cmd/watch.d.ts +0 -1
- package/dist/cmd/watch.js +1 -26
- package/dist/hosts/claude-code.d.ts +0 -1
- package/dist/hosts/claude-code.js +3 -180
- package/dist/hosts/claude-desktop.d.ts +0 -1
- package/dist/hosts/claude-desktop.js +3 -222
- package/dist/hosts/codex.d.ts +0 -1
- package/dist/hosts/codex.js +20 -234
- package/dist/hosts/shell-env.d.ts +0 -1
- package/dist/hosts/shell-env.js +9 -81
- package/dist/index.d.ts +0 -1
- package/dist/index.js +14 -206
- package/dist/lib/client.d.ts +0 -1
- package/dist/lib/client.js +1 -58
- package/dist/lib/events/emit.d.ts +0 -1
- package/dist/lib/events/emit.js +1 -28
- package/dist/lib/index.d.ts +0 -1
- package/dist/lib/index.js +1 -11
- package/dist/lib/transport.d.ts +0 -1
- package/dist/lib/transport.js +1 -85
- package/dist/lib/types/index.d.ts +0 -1
- package/dist/lib/types/index.js +1 -50
- package/dist/lib/vault/checkpoint.d.ts +0 -1
- package/dist/lib/vault/checkpoint.js +1 -18
- package/dist/lib/vault/read.d.ts +0 -1
- package/dist/lib/vault/read.js +1 -9
- package/dist/lib/vault/search.d.ts +0 -1
- package/dist/lib/vault/search.js +1 -10
- package/dist/pace/device.d.ts +0 -1
- package/dist/pace/device.js +2 -149
- package/dist/pace/enroll.d.ts +0 -1
- package/dist/pace/enroll.js +2 -138
- package/dist/pace/identity.d.ts +0 -1
- package/dist/pace/identity.js +1 -17
- package/dist/pace/install.d.ts +0 -1
- package/dist/pace/install.js +4 -127
- package/dist/pace/local-evidence.d.ts +0 -1
- package/dist/pace/local-evidence.js +2 -228
- package/dist/pace/local-sessions.d.ts +0 -1
- package/dist/pace/local-sessions.js +1 -254
- package/dist/pace/managed-config.d.ts +0 -1
- package/dist/pace/managed-config.js +8 -102
- package/dist/pace/normalize.d.ts +0 -1
- package/dist/pace/normalize.js +1 -293
- package/dist/pace/repository.d.ts +0 -1
- package/dist/pace/repository.js +2 -120
- package/dist/pace/schema.d.ts +0 -1
- package/dist/pace/schema.js +1 -134
- package/dist/pace/session-summary.d.ts +0 -1
- package/dist/pace/session-summary.js +2 -140
- package/dist/pace/spool.d.ts +0 -1
- package/dist/pace/spool.js +8 -87
- package/dist/pace-runtime.d.ts +0 -1
- package/dist/pace-runtime.js +2 -67
- package/dist/sync/api.d.ts +0 -1
- package/dist/sync/api.js +1 -55
- package/dist/sync/autoloader.d.ts +0 -1
- package/dist/sync/autoloader.js +5 -127
- package/dist/sync/conflict.d.ts +0 -1
- package/dist/sync/conflict.js +5 -15
- package/dist/sync/credentials.d.ts +0 -1
- package/dist/sync/credentials.js +1 -51
- package/dist/sync/files.d.ts +0 -1
- package/dist/sync/files.js +1 -71
- package/dist/sync/manifest.d.ts +0 -1
- package/dist/sync/manifest.js +1 -37
- package/dist/sync/repo-root.d.ts +0 -1
- package/dist/sync/repo-root.js +1 -24
- package/dist/sync/stitch-claude-md.d.ts +0 -1
- package/dist/sync/stitch-claude-md.js +8 -48
- package/dist/ui/colors.d.ts +0 -1
- package/dist/ui/colors.js +1 -28
- package/dist/ui/screens.d.ts +0 -1
- package/dist/ui/screens.js +5 -135
- package/package.json +5 -12
- package/plugin/.cursor-plugin/plugin.json +0 -2
- package/plugin/.mcp.json +1 -1
- package/plugin/LICENSE +15 -0
- package/plugin/gemini/gemini-extension.json +1 -1
- package/plugin/mcp.json +1 -1
- package/plugin/plugin.json +0 -2
- package/plugin/runtime/unfairly-intelligence.mjs +14 -5512
- package/dist/auth/browser-flow.d.ts.map +0 -1
- package/dist/auth/browser-flow.js.map +0 -1
- package/dist/cmd/connect.d.ts.map +0 -1
- package/dist/cmd/connect.js.map +0 -1
- package/dist/cmd/init.d.ts.map +0 -1
- package/dist/cmd/init.js.map +0 -1
- package/dist/cmd/invite.d.ts.map +0 -1
- package/dist/cmd/invite.js.map +0 -1
- package/dist/cmd/join.d.ts.map +0 -1
- package/dist/cmd/join.js.map +0 -1
- package/dist/cmd/login.d.ts.map +0 -1
- package/dist/cmd/login.js.map +0 -1
- package/dist/cmd/mcp.d.ts.map +0 -1
- package/dist/cmd/mcp.js.map +0 -1
- package/dist/cmd/pace.d.ts.map +0 -1
- package/dist/cmd/pace.js.map +0 -1
- package/dist/cmd/parse-share-input.d.ts.map +0 -1
- package/dist/cmd/parse-share-input.js.map +0 -1
- package/dist/cmd/pull.d.ts.map +0 -1
- package/dist/cmd/pull.js.map +0 -1
- package/dist/cmd/push.d.ts.map +0 -1
- package/dist/cmd/push.js.map +0 -1
- package/dist/cmd/resolve.d.ts.map +0 -1
- package/dist/cmd/resolve.js.map +0 -1
- package/dist/cmd/setup.d.ts.map +0 -1
- package/dist/cmd/setup.js.map +0 -1
- package/dist/cmd/status-card.d.ts.map +0 -1
- package/dist/cmd/status-card.js.map +0 -1
- package/dist/cmd/status.d.ts.map +0 -1
- package/dist/cmd/status.js.map +0 -1
- package/dist/cmd/watch.d.ts.map +0 -1
- package/dist/cmd/watch.js.map +0 -1
- package/dist/hosts/claude-code.d.ts.map +0 -1
- package/dist/hosts/claude-code.js.map +0 -1
- package/dist/hosts/claude-desktop.d.ts.map +0 -1
- package/dist/hosts/claude-desktop.js.map +0 -1
- package/dist/hosts/codex.d.ts.map +0 -1
- package/dist/hosts/codex.js.map +0 -1
- package/dist/hosts/shell-env.d.ts.map +0 -1
- package/dist/hosts/shell-env.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lib/client.d.ts.map +0 -1
- package/dist/lib/client.js.map +0 -1
- package/dist/lib/events/emit.d.ts.map +0 -1
- package/dist/lib/events/emit.js.map +0 -1
- package/dist/lib/index.d.ts.map +0 -1
- package/dist/lib/index.js.map +0 -1
- package/dist/lib/transport.d.ts.map +0 -1
- package/dist/lib/transport.js.map +0 -1
- package/dist/lib/types/index.d.ts.map +0 -1
- package/dist/lib/types/index.js.map +0 -1
- package/dist/lib/vault/checkpoint.d.ts.map +0 -1
- package/dist/lib/vault/checkpoint.js.map +0 -1
- package/dist/lib/vault/read.d.ts.map +0 -1
- package/dist/lib/vault/read.js.map +0 -1
- package/dist/lib/vault/search.d.ts.map +0 -1
- package/dist/lib/vault/search.js.map +0 -1
- package/dist/pace/device.d.ts.map +0 -1
- package/dist/pace/device.js.map +0 -1
- package/dist/pace/enroll.d.ts.map +0 -1
- package/dist/pace/enroll.js.map +0 -1
- package/dist/pace/identity.d.ts.map +0 -1
- package/dist/pace/identity.js.map +0 -1
- package/dist/pace/install.d.ts.map +0 -1
- package/dist/pace/install.js.map +0 -1
- package/dist/pace/local-evidence.d.ts.map +0 -1
- package/dist/pace/local-evidence.js.map +0 -1
- package/dist/pace/local-sessions.d.ts.map +0 -1
- package/dist/pace/local-sessions.js.map +0 -1
- package/dist/pace/managed-config.d.ts.map +0 -1
- package/dist/pace/managed-config.js.map +0 -1
- package/dist/pace/normalize.d.ts.map +0 -1
- package/dist/pace/normalize.js.map +0 -1
- package/dist/pace/repository.d.ts.map +0 -1
- package/dist/pace/repository.js.map +0 -1
- package/dist/pace/schema.d.ts.map +0 -1
- package/dist/pace/schema.js.map +0 -1
- package/dist/pace/session-summary.d.ts.map +0 -1
- package/dist/pace/session-summary.js.map +0 -1
- package/dist/pace/spool.d.ts.map +0 -1
- package/dist/pace/spool.js.map +0 -1
- package/dist/pace-runtime.d.ts.map +0 -1
- package/dist/pace-runtime.js.map +0 -1
- package/dist/sync/api.d.ts.map +0 -1
- package/dist/sync/api.js.map +0 -1
- package/dist/sync/autoloader.d.ts.map +0 -1
- package/dist/sync/autoloader.js.map +0 -1
- package/dist/sync/conflict.d.ts.map +0 -1
- package/dist/sync/conflict.js.map +0 -1
- package/dist/sync/credentials.d.ts.map +0 -1
- package/dist/sync/credentials.js.map +0 -1
- package/dist/sync/files.d.ts.map +0 -1
- package/dist/sync/files.js.map +0 -1
- package/dist/sync/manifest.d.ts.map +0 -1
- package/dist/sync/manifest.js.map +0 -1
- package/dist/sync/repo-root.d.ts.map +0 -1
- package/dist/sync/repo-root.js.map +0 -1
- package/dist/sync/stitch-claude-md.d.ts.map +0 -1
- package/dist/sync/stitch-claude-md.js.map +0 -1
- package/dist/ui/colors.d.ts.map +0 -1
- package/dist/ui/colors.js.map +0 -1
- package/dist/ui/screens.d.ts.map +0 -1
- package/dist/ui/screens.js.map +0 -1
|
@@ -1,56 +1 @@
|
|
|
1
|
-
|
|
2
|
-
//
|
|
3
|
-
// Parse the positional arg to `unfairly connect`. Accepts:
|
|
4
|
-
// - Full URL: https://app.unfairly.ai/s/<uuid>
|
|
5
|
-
// - Short form: s/<uuid>
|
|
6
|
-
// - Bare UUID: <uuid>
|
|
7
|
-
//
|
|
8
|
-
// Returns the share_link UUID + the origin (when present in the input)
|
|
9
|
-
// so `connect` can POST to the same host the link came from. A bare UUID
|
|
10
|
-
// or short form yields `origin: null` — callers should fall back to the
|
|
11
|
-
// production app origin.
|
|
12
|
-
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
13
|
-
export function parseShareInput(input) {
|
|
14
|
-
if (typeof input !== "string") {
|
|
15
|
-
throw new Error("share link is required");
|
|
16
|
-
}
|
|
17
|
-
const trimmed = input.trim();
|
|
18
|
-
if (trimmed.length === 0) {
|
|
19
|
-
throw new Error("share link is required");
|
|
20
|
-
}
|
|
21
|
-
// Full URL form: https://host/s/<uuid> (with optional trailing slash / query).
|
|
22
|
-
if (/^https?:\/\//i.test(trimmed)) {
|
|
23
|
-
let url;
|
|
24
|
-
try {
|
|
25
|
-
url = new URL(trimmed);
|
|
26
|
-
}
|
|
27
|
-
catch {
|
|
28
|
-
throw new Error(`not a valid URL: ${trimmed}`);
|
|
29
|
-
}
|
|
30
|
-
const segments = url.pathname.split("/").filter(Boolean);
|
|
31
|
-
// Expect [..., "s", "<uuid>"] — find the "s/" marker.
|
|
32
|
-
const sIdx = segments.indexOf("s");
|
|
33
|
-
if (sIdx === -1 || sIdx === segments.length - 1) {
|
|
34
|
-
throw new Error(`share link URL must include /s/<id>: ${trimmed}`);
|
|
35
|
-
}
|
|
36
|
-
const candidate = segments[sIdx + 1] ?? "";
|
|
37
|
-
if (!UUID_RE.test(candidate)) {
|
|
38
|
-
throw new Error(`share id must be a UUID, got "${candidate}"`);
|
|
39
|
-
}
|
|
40
|
-
return { shareId: candidate.toLowerCase(), origin: url.origin };
|
|
41
|
-
}
|
|
42
|
-
// Short form: s/<uuid>
|
|
43
|
-
if (/^s\//i.test(trimmed)) {
|
|
44
|
-
const candidate = trimmed.slice(2);
|
|
45
|
-
if (!UUID_RE.test(candidate)) {
|
|
46
|
-
throw new Error(`share id must be a UUID, got "${candidate}"`);
|
|
47
|
-
}
|
|
48
|
-
return { shareId: candidate.toLowerCase(), origin: null };
|
|
49
|
-
}
|
|
50
|
-
// Bare UUID
|
|
51
|
-
if (UUID_RE.test(trimmed)) {
|
|
52
|
-
return { shareId: trimmed.toLowerCase(), origin: null };
|
|
53
|
-
}
|
|
54
|
-
throw new Error(`not a recognized share link: "${input}" — expected a URL like https://app.unfairly.ai/s/<uuid>, "s/<uuid>", or a bare UUID`);
|
|
55
|
-
}
|
|
56
|
-
//# sourceMappingURL=parse-share-input.js.map
|
|
1
|
+
const o=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function a(t){if(typeof t!="string")throw new Error("share link is required");const r=t.trim();if(r.length===0)throw new Error("share link is required");if(/^https?:\/\//i.test(r)){let e;try{e=new URL(r)}catch{throw new Error(`not a valid URL: ${r}`)}const i=e.pathname.split("/").filter(Boolean),n=i.indexOf("s");if(n===-1||n===i.length-1)throw new Error(`share link URL must include /s/<id>: ${r}`);const s=i[n+1]??"";if(!o.test(s))throw new Error(`share id must be a UUID, got "${s}"`);return{shareId:s.toLowerCase(),origin:e.origin}}if(/^s\//i.test(r)){const e=r.slice(2);if(!o.test(e))throw new Error(`share id must be a UUID, got "${e}"`);return{shareId:e.toLowerCase(),origin:null}}if(o.test(r))return{shareId:r.toLowerCase(),origin:null};throw new Error(`not a recognized share link: "${t}" \u2014 expected a URL like https://app.unfairly.ai/s/<uuid>, "s/<uuid>", or a bare UUID`)}export{a as parseShareInput};
|
package/dist/cmd/pull.d.ts
CHANGED
package/dist/cmd/pull.js
CHANGED
|
@@ -1,143 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import { getToken } from "../sync/credentials.js";
|
|
9
|
-
import { writeAutoloader } from "../sync/autoloader.js";
|
|
10
|
-
const execFileAsync = promisify(execFile);
|
|
11
|
-
async function gitMv(from, to) {
|
|
12
|
-
try {
|
|
13
|
-
await execFileAsync("git", ["mv", from, to], { cwd: process.cwd() });
|
|
14
|
-
return true;
|
|
15
|
-
}
|
|
16
|
-
catch {
|
|
17
|
-
return false;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
async function tryUnlink(p) {
|
|
21
|
-
try {
|
|
22
|
-
await fs.unlink(p);
|
|
23
|
-
}
|
|
24
|
-
catch { }
|
|
25
|
-
}
|
|
26
|
-
export async function runPull(vaultArg) {
|
|
27
|
-
const cwd = process.cwd();
|
|
28
|
-
const manifest = await readManifest(cwd);
|
|
29
|
-
if (!manifest) {
|
|
30
|
-
console.error("No .unfairly/ found. Run `unfairly init` first.");
|
|
31
|
-
process.exit(1);
|
|
32
|
-
}
|
|
33
|
-
const token = await getToken();
|
|
34
|
-
if (!token) {
|
|
35
|
-
console.error("No token. Run `unfairly init` to authenticate.");
|
|
36
|
-
process.exit(1);
|
|
37
|
-
}
|
|
38
|
-
const client = new SyncClient(manifest.api_url, token);
|
|
39
|
-
const targets = vaultArg ? [vaultArg] : Object.keys(manifest.vaults);
|
|
40
|
-
const failures = [];
|
|
41
|
-
for (const slug of targets) {
|
|
42
|
-
const v = manifest.vaults[slug];
|
|
43
|
-
if (!v) {
|
|
44
|
-
console.error(`No vault \`${slug}\` in manifest.`);
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
47
|
-
process.stdout.write(`pulling ${slug}... `);
|
|
48
|
-
let result;
|
|
49
|
-
try {
|
|
50
|
-
result = await client.pullAll(slug, v.last_pulled_at);
|
|
51
|
-
}
|
|
52
|
-
catch (err) {
|
|
53
|
-
// One vault failing shouldn't kill the rest of the pull. For a single-
|
|
54
|
-
// vault target (`unfairly pull <vault>`) we still want to surface and
|
|
55
|
-
// exit non-zero — fall through to throw at the end.
|
|
56
|
-
const message = err.message.split("\n")[0];
|
|
57
|
-
console.log(`FAILED — ${message}`);
|
|
58
|
-
failures.push({ slug, message });
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
// Vault root: track_in_git → .unfairly/{slug}/, else .unfairly/cache/{slug}/
|
|
62
|
-
const vaultRoot = v.track_in_git ? slug : path.join("cache", slug);
|
|
63
|
-
const absVaultRoot = path.join(cwd, ".unfairly", vaultRoot);
|
|
64
|
-
await fs.mkdir(absVaultRoot, { recursive: true });
|
|
65
|
-
let upserts = 0;
|
|
66
|
-
let deletes = 0;
|
|
67
|
-
let renames = 0;
|
|
68
|
-
let skipped = 0;
|
|
69
|
-
for (const doc of result.docs) {
|
|
70
|
-
let file;
|
|
71
|
-
try {
|
|
72
|
-
file = buildFileFromServer(doc, vaultRoot);
|
|
73
|
-
}
|
|
74
|
-
catch (err) {
|
|
75
|
-
// One bad doc shouldn't kill the whole pull. Most commonly this is
|
|
76
|
-
// gray-matter/js-yaml choking on body content that the YAML
|
|
77
|
-
// serializer mis-parses (e.g. `*Foo` interpreted as an alias). The
|
|
78
|
-
// doc stays on the server; the user can re-pull after the upstream
|
|
79
|
-
// doc is sanitized.
|
|
80
|
-
process.stderr.write(` · skipped ${doc.slug} — ${err.message.split("\n")[0]}\n`);
|
|
81
|
-
skipped++;
|
|
82
|
-
continue;
|
|
83
|
-
}
|
|
84
|
-
const relPath = file.path;
|
|
85
|
-
const absPath = path.join(cwd, ".unfairly", relPath);
|
|
86
|
-
// Detect rename: same id, different stored path
|
|
87
|
-
const prev = v.docs[doc.id];
|
|
88
|
-
if (prev && prev.path !== relPath) {
|
|
89
|
-
const prevAbs = path.join(cwd, ".unfairly", prev.path);
|
|
90
|
-
// Tracked vault → use git mv to preserve history
|
|
91
|
-
if (v.track_in_git) {
|
|
92
|
-
await fs.mkdir(path.dirname(absPath), { recursive: true });
|
|
93
|
-
const ok = await gitMv(prevAbs, absPath);
|
|
94
|
-
if (!ok) {
|
|
95
|
-
await tryUnlink(prevAbs);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
else {
|
|
99
|
-
await tryUnlink(prevAbs);
|
|
100
|
-
}
|
|
101
|
-
renames++;
|
|
102
|
-
}
|
|
103
|
-
await writeDocFile(absPath, file.content);
|
|
104
|
-
v.docs[doc.id] = {
|
|
105
|
-
slug: doc.slug,
|
|
106
|
-
path: relPath,
|
|
107
|
-
sha: file.sha,
|
|
108
|
-
updated_at: doc.updated_at,
|
|
109
|
-
source_type: doc.source_type ?? "markdown",
|
|
110
|
-
};
|
|
111
|
-
upserts++;
|
|
112
|
-
}
|
|
113
|
-
for (const tomb of result.deleted) {
|
|
114
|
-
const prev = v.docs[tomb.id];
|
|
115
|
-
if (!prev)
|
|
116
|
-
continue;
|
|
117
|
-
const absPath = path.join(cwd, ".unfairly", prev.path);
|
|
118
|
-
await tryUnlink(absPath);
|
|
119
|
-
delete v.docs[tomb.id];
|
|
120
|
-
deletes++;
|
|
121
|
-
}
|
|
122
|
-
v.last_pulled_at = new Date().toISOString();
|
|
123
|
-
console.log(`+${upserts} -${deletes}${renames ? ` ~${renames}` : ""}${skipped ? ` (skipped ${skipped})` : ""}`);
|
|
124
|
-
}
|
|
125
|
-
await writeManifest(cwd, manifest);
|
|
126
|
-
// Regenerate .unfairly/CLAUDE.md autoloader + .gitignore from the latest mirror.
|
|
127
|
-
// (init prints the @-import paste instruction; pull stays quiet.)
|
|
128
|
-
const refreshed = await readManifest(cwd);
|
|
129
|
-
if (refreshed) {
|
|
130
|
-
const target = path.join(cwd, ".unfairly");
|
|
131
|
-
await writeAutoloader(target, refreshed);
|
|
132
|
-
}
|
|
133
|
-
if (failures.length > 0) {
|
|
134
|
-
process.stderr.write(`\n${failures.length} vault${failures.length === 1 ? "" : "s"} failed:\n`);
|
|
135
|
-
for (const f of failures) {
|
|
136
|
-
process.stderr.write(` · ${f.slug} — ${f.message}\n`);
|
|
137
|
-
}
|
|
138
|
-
// Single-vault target → propagate so callers/CI see the failure.
|
|
139
|
-
// Multi-vault → keep what we got but signal partial failure via exit code.
|
|
140
|
-
process.exitCode = 1;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
//# sourceMappingURL=pull.js.map
|
|
1
|
+
import{promises as g}from"node:fs";import r from"node:path";import{execFile as A}from"node:child_process";import{promisify as P}from"node:util";import{SyncClient as R}from"../sync/api.js";import{readManifest as b,writeManifest as S}from"../sync/manifest.js";import{buildFileFromServer as D,writeDocFile as M}from"../sync/files.js";import{getToken as N}from"../sync/credentials.js";import{writeAutoloader as C}from"../sync/autoloader.js";const I=P(A);async function O(n,o){try{return await I("git",["mv",n,o],{cwd:process.cwd()}),!0}catch{return!1}}async function h(n){try{await g.unlink(n)}catch{}}async function J(n){const o=process.cwd(),a=await b(o);a||(console.error("No .unfairly/ found. Run `unfairly init` first."),process.exit(1));const y=await N();y||(console.error("No token. Run `unfairly init` to authenticate."),process.exit(1));const j=new R(a.api_url,y),x=n?[n]:Object.keys(a.vaults),c=[];for(const t of x){const i=a.vaults[t];if(!i){console.error(`No vault \`${t}\` in manifest.`);continue}process.stdout.write(`pulling ${t}... `);let f;try{f=await j.pullAll(t,i.last_pulled_at)}catch(e){const s=e.message.split(`
|
|
2
|
+
`)[0];console.log(`FAILED \u2014 ${s}`),c.push({slug:t,message:s});continue}const $=i.track_in_git?t:r.join("cache",t),F=r.join(o,".unfairly",$);await g.mkdir(F,{recursive:!0});let v=0,_=0,p=0,d=0;for(const e of f.docs){let s;try{s=D(e,$)}catch(u){process.stderr.write(` \xB7 skipped ${e.slug} \u2014 ${u.message.split(`
|
|
3
|
+
`)[0]}
|
|
4
|
+
`),d++;continue}const l=s.path,m=r.join(o,".unfairly",l),w=i.docs[e.id];if(w&&w.path!==l){const u=r.join(o,".unfairly",w.path);i.track_in_git?(await g.mkdir(r.dirname(m),{recursive:!0}),await O(u,m)||await h(u)):await h(u),p++}await M(m,s.content),i.docs[e.id]={slug:e.slug,path:l,sha:s.sha,updated_at:e.updated_at,source_type:e.source_type??"markdown"},v++}for(const e of f.deleted){const s=i.docs[e.id];if(!s)continue;const l=r.join(o,".unfairly",s.path);await h(l),delete i.docs[e.id],_++}i.last_pulled_at=new Date().toISOString(),console.log(`+${v} -${_}${p?` ~${p}`:""}${d?` (skipped ${d})`:""}`)}await S(o,a);const k=await b(o);if(k){const t=r.join(o,".unfairly");await C(t,k)}if(c.length>0){process.stderr.write(`
|
|
5
|
+
${c.length} vault${c.length===1?"":"s"} failed:
|
|
6
|
+
`);for(const t of c)process.stderr.write(` \xB7 ${t.slug} \u2014 ${t.message}
|
|
7
|
+
`);process.exitCode=1}}export{J as runPull};
|
package/dist/cmd/push.d.ts
CHANGED
package/dist/cmd/push.js
CHANGED
|
@@ -1,85 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { SyncClient } from "../sync/api.js";
|
|
4
|
-
import { readManifest, writeManifest } from "../sync/manifest.js";
|
|
5
|
-
import { computeSha, readDocFile, readDocRaw } from "../sync/files.js";
|
|
6
|
-
import { buildConflictFile } from "../sync/conflict.js";
|
|
7
|
-
import { getToken } from "../sync/credentials.js";
|
|
8
|
-
export async function runPush(vaultArg) {
|
|
9
|
-
const cwd = process.cwd();
|
|
10
|
-
const manifest = await readManifest(cwd);
|
|
11
|
-
if (!manifest) {
|
|
12
|
-
console.error("No .unfairly/ found. Run `unfairly init` first.");
|
|
13
|
-
process.exit(1);
|
|
14
|
-
}
|
|
15
|
-
const token = await getToken();
|
|
16
|
-
if (!token) {
|
|
17
|
-
console.error("No token. Run `unfairly init` to authenticate.");
|
|
18
|
-
process.exit(1);
|
|
19
|
-
}
|
|
20
|
-
const client = new SyncClient(manifest.api_url, token);
|
|
21
|
-
const targets = vaultArg ? [vaultArg] : Object.keys(manifest.vaults);
|
|
22
|
-
let conflicts = 0;
|
|
23
|
-
let pushed = 0;
|
|
24
|
-
for (const slug of targets) {
|
|
25
|
-
const v = manifest.vaults[slug];
|
|
26
|
-
if (!v) {
|
|
27
|
-
console.error(`No vault \`${slug}\` in manifest.`);
|
|
28
|
-
continue;
|
|
29
|
-
}
|
|
30
|
-
for (const [docId, entry] of Object.entries(v.docs)) {
|
|
31
|
-
const absPath = path.join(cwd, ".unfairly", entry.path);
|
|
32
|
-
let raw;
|
|
33
|
-
let local;
|
|
34
|
-
try {
|
|
35
|
-
raw = await readDocRaw(absPath);
|
|
36
|
-
local = await readDocFile(absPath);
|
|
37
|
-
}
|
|
38
|
-
catch {
|
|
39
|
-
// File missing locally — Phase 1 punt: skip (delete-locally not handled)
|
|
40
|
-
continue;
|
|
41
|
-
}
|
|
42
|
-
const currentSha = computeSha(raw);
|
|
43
|
-
if (currentSha === entry.sha)
|
|
44
|
-
continue; // not dirty
|
|
45
|
-
const result = await client.push({
|
|
46
|
-
vault: slug,
|
|
47
|
-
doc_id: docId,
|
|
48
|
-
expected_updated_at: entry.updated_at,
|
|
49
|
-
body: local.body,
|
|
50
|
-
client_frontmatter: local.frontmatter,
|
|
51
|
-
});
|
|
52
|
-
if (result.status === 200 && "ok" in result.data) {
|
|
53
|
-
const { updated_at, rejected_frontmatter } = result.data;
|
|
54
|
-
entry.sha = currentSha;
|
|
55
|
-
entry.updated_at = updated_at;
|
|
56
|
-
pushed++;
|
|
57
|
-
if (rejected_frontmatter.length > 0) {
|
|
58
|
-
console.warn(`! ${entry.path}: server kept ${rejected_frontmatter.map((r) => r.key).join(", ")} (your changes ignored)`);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
else if (result.status === 409 && "server_body" in result.data) {
|
|
62
|
-
const d = result.data;
|
|
63
|
-
const conflictContent = buildConflictFile({
|
|
64
|
-
serverFrontmatter: d.server_frontmatter,
|
|
65
|
-
localBody: local.body,
|
|
66
|
-
serverBody: d.server_body,
|
|
67
|
-
serverUpdatedAt: d.server_updated_at,
|
|
68
|
-
});
|
|
69
|
-
await fs.writeFile(absPath, conflictContent, "utf8");
|
|
70
|
-
// Update entry's known updated_at to the server's so a resolve+push works
|
|
71
|
-
entry.updated_at = d.server_updated_at;
|
|
72
|
-
console.warn(`! conflict: ${entry.path} (server updated ${d.server_updated_at}). Edit to remove merge markers, then \`unfairly resolve <path>\` and \`unfairly push\`.`);
|
|
73
|
-
conflicts++;
|
|
74
|
-
}
|
|
75
|
-
else {
|
|
76
|
-
const err = "error" in result.data ? result.data.error : "unknown";
|
|
77
|
-
console.error(`push failed for ${entry.path}: ${err}`);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
v.last_pushed_at = new Date().toISOString();
|
|
81
|
-
}
|
|
82
|
-
await writeManifest(cwd, manifest);
|
|
83
|
-
console.log(`pushed ${pushed}, conflicts ${conflicts}`);
|
|
84
|
-
}
|
|
85
|
-
//# sourceMappingURL=push.js.map
|
|
1
|
+
import{promises as b}from"node:fs";import k from"node:path";import{SyncClient as $}from"../sync/api.js";import{readManifest as g,writeManifest as j}from"../sync/manifest.js";import{computeSha as S,readDocFile as x,readDocRaw as F}from"../sync/files.js";import{buildConflictFile as C}from"../sync/conflict.js";import{getToken as D}from"../sync/credentials.js";async function E(l){const s=process.cwd(),r=await g(s);r||(console.error("No .unfairly/ found. Run `unfairly init` first."),process.exit(1));const u=await D();u||(console.error("No token. Run `unfairly init` to authenticate."),process.exit(1));const _=new $(r.api_url,u),y=l?[l]:Object.keys(r.vaults);let f=0,p=0;for(const i of y){const c=r.vaults[i];if(!c){console.error(`No vault \`${i}\` in manifest.`);continue}for(const[w,t]of Object.entries(c.docs)){const d=k.join(s,".unfairly",t.path);let m,a;try{m=await F(d),a=await x(d)}catch{continue}const h=S(m);if(h===t.sha)continue;const o=await _.push({vault:i,doc_id:w,expected_updated_at:t.updated_at,body:a.body,client_frontmatter:a.frontmatter});if(o.status===200&&"ok"in o.data){const{updated_at:e,rejected_frontmatter:n}=o.data;t.sha=h,t.updated_at=e,p++,n.length>0&&console.warn(`! ${t.path}: server kept ${n.map(v=>v.key).join(", ")} (your changes ignored)`)}else if(o.status===409&&"server_body"in o.data){const e=o.data,n=C({serverFrontmatter:e.server_frontmatter,localBody:a.body,serverBody:e.server_body,serverUpdatedAt:e.server_updated_at});await b.writeFile(d,n,"utf8"),t.updated_at=e.server_updated_at,console.warn(`! conflict: ${t.path} (server updated ${e.server_updated_at}). Edit to remove merge markers, then \`unfairly resolve <path>\` and \`unfairly push\`.`),f++}else{const e="error"in o.data?o.data.error:"unknown";console.error(`push failed for ${t.path}: ${e}`)}}c.last_pushed_at=new Date().toISOString()}await j(s,r),console.log(`pushed ${p}, conflicts ${f}`)}export{E as runPush};
|
package/dist/cmd/resolve.d.ts
CHANGED
package/dist/cmd/resolve.js
CHANGED
|
@@ -1,35 +1 @@
|
|
|
1
|
-
import path from
|
|
2
|
-
import { promises as fs } from "node:fs";
|
|
3
|
-
import { readManifest } from "../sync/manifest.js";
|
|
4
|
-
export async function runResolve(relOrAbsPath) {
|
|
5
|
-
const cwd = process.cwd();
|
|
6
|
-
const manifest = await readManifest(cwd);
|
|
7
|
-
if (!manifest) {
|
|
8
|
-
console.error("No .unfairly/ found.");
|
|
9
|
-
process.exit(1);
|
|
10
|
-
}
|
|
11
|
-
const abs = path.isAbsolute(relOrAbsPath)
|
|
12
|
-
? relOrAbsPath
|
|
13
|
-
: path.join(cwd, relOrAbsPath);
|
|
14
|
-
const raw = await fs.readFile(abs, "utf8");
|
|
15
|
-
if (raw.includes("<<<<<<< local") || raw.includes(">>>>>>> cloud")) {
|
|
16
|
-
console.error("Merge markers still present. Edit the file to remove them, then re-run resolve.");
|
|
17
|
-
process.exit(1);
|
|
18
|
-
}
|
|
19
|
-
// Verify the file is in the manifest. We do NOT mutate entry.sha — leaving
|
|
20
|
-
// the pre-conflict sha lets `push` detect the resolved content as dirty
|
|
21
|
-
// and ship it. entry.updated_at was already advanced to server's during
|
|
22
|
-
// the conflict, so the next push's expected_updated_at will match.
|
|
23
|
-
const relPath = path.relative(path.join(cwd, ".unfairly"), abs);
|
|
24
|
-
for (const v of Object.values(manifest.vaults)) {
|
|
25
|
-
for (const [, entry] of Object.entries(v.docs)) {
|
|
26
|
-
if (entry.path === relPath) {
|
|
27
|
-
console.log(`markers cleared. Run \`unfairly push\` to broadcast.`);
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
console.error("path not found in manifest");
|
|
33
|
-
process.exit(1);
|
|
34
|
-
}
|
|
35
|
-
//# sourceMappingURL=resolve.js.map
|
|
1
|
+
import e from"node:path";import{promises as l}from"node:fs";import{readManifest as f}from"../sync/manifest.js";async function m(o){const r=process.cwd(),s=await f(r);s||(console.error("No .unfairly/ found."),process.exit(1));const t=e.isAbsolute(o)?o:e.join(r,o),n=await l.readFile(t,"utf8");(n.includes("<<<<<<< local")||n.includes(">>>>>>> cloud"))&&(console.error("Merge markers still present. Edit the file to remove them, then re-run resolve."),process.exit(1));const i=e.relative(e.join(r,".unfairly"),t);for(const c of Object.values(s.vaults))for(const[,a]of Object.entries(c.docs))if(a.path===i){console.log("markers cleared. Run `unfairly push` to broadcast.");return}console.error("path not found in manifest"),process.exit(1)}export{m as runResolve};
|
package/dist/cmd/setup.d.ts
CHANGED