jowork 0.2.4 → 0.3.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/dist/{chunk-ROIINI33.js → chunk-4PIT2GZ4.js} +13 -1
- package/dist/{chunk-XLYRHKG6.js → chunk-54SD5GBF.js} +1 -1
- package/dist/chunk-63AMINQC.js +156 -0
- package/dist/{chunk-XAEGXSEO.js → chunk-74AHY7X6.js} +4 -0
- package/dist/{chunk-7U3SXINY.js → chunk-ATAUWJYD.js} +320 -50
- package/dist/chunk-DQW74UCN.js +671 -0
- package/dist/chunk-EYP6WMFF.js +153 -0
- package/dist/{chunk-JSTXMDXI.js → chunk-FCFZCZHR.js} +1 -1
- package/dist/chunk-FX6Z3QHV.js +34 -0
- package/dist/chunk-HENAABEL.js +419 -0
- package/dist/chunk-OXWWOKC7.js +201 -0
- package/dist/chunk-QGHJ45PL.js +661 -0
- package/dist/chunk-RO3KK5RC.js +132 -0
- package/dist/{chunk-JE6TOU7W.js → chunk-TFMF3EXE.js} +2 -7
- package/dist/{chunk-TN327MDF.js → chunk-VX662YLA.js} +3 -3
- package/dist/cli.js +338 -149
- package/dist/{config-AI6UIJJN.js → config-FH2XLN7A.js} +2 -2
- package/dist/content-reader-VPGTR2SF.js +10 -0
- package/dist/context-ZNI3WOB7.js +10 -0
- package/dist/{credential-store-ZRZCSRPC.js → credential-store-OS5ZY4OW.js} +2 -2
- package/dist/{feishu-A6YVFKEN.js → feishu-XW5T6ER2.js} +8 -3
- package/dist/{git-manager-N35XSG4Y.js → git-manager-RVWV2GSV.js} +2 -1
- package/dist/github-PQKAYTLO.js +11 -0
- package/dist/{paths-JXOMBYIT.js → paths-FFRET6F7.js} +7 -3
- package/dist/{server-5GVWN2NB.js → server-WEADPUST.js} +59 -66
- package/dist/{setup-IDQDPCEJ.js → setup-S2S2CHB2.js} +91 -32
- package/dist/sync-SRLFR5NA.js +21 -0
- package/dist/transport.js +6 -4
- package/package.json +1 -1
- package/src/dashboard/public/app.js +34 -8
- package/src/dashboard/public/style.css +14 -0
- package/dist/chunk-AIXKXEYS.js +0 -547
- package/dist/chunk-L5ZR7TSK.js +0 -82
- package/dist/chunk-LS2AJM5A.js +0 -163
- package/dist/chunk-QMOFQX7X.js +0 -612
- package/dist/chunk-YJWTKFWX.js +0 -451
- package/dist/github-SHWUFNYB.js +0 -10
- package/dist/sync-7V54N62M.js +0 -18
package/dist/chunk-L5ZR7TSK.js
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
logInfo
|
|
3
|
-
} from "./chunk-MYDK7MWB.js";
|
|
4
|
-
|
|
5
|
-
// src/sync/git-manager.ts
|
|
6
|
-
import simpleGit from "simple-git";
|
|
7
|
-
import { existsSync, writeFileSync } from "fs";
|
|
8
|
-
import { join } from "path";
|
|
9
|
-
var GitManager = class {
|
|
10
|
-
git;
|
|
11
|
-
repoDir;
|
|
12
|
-
constructor(repoDir) {
|
|
13
|
-
this.repoDir = repoDir;
|
|
14
|
-
this.git = simpleGit(repoDir);
|
|
15
|
-
}
|
|
16
|
-
/** Initialize git repo if not already initialized */
|
|
17
|
-
async init() {
|
|
18
|
-
const gitDir = join(this.repoDir, ".git");
|
|
19
|
-
if (existsSync(gitDir)) return;
|
|
20
|
-
await this.git.init();
|
|
21
|
-
const gitignore = [
|
|
22
|
-
"# JoWork \u2014 auto-generated",
|
|
23
|
-
"*.db",
|
|
24
|
-
"*.db-wal",
|
|
25
|
-
"*.db-shm",
|
|
26
|
-
".DS_Store",
|
|
27
|
-
"Thumbs.db",
|
|
28
|
-
"*.key",
|
|
29
|
-
"*.pem",
|
|
30
|
-
"*.env",
|
|
31
|
-
"credentials/",
|
|
32
|
-
""
|
|
33
|
-
].join("\n");
|
|
34
|
-
writeFileSync(join(this.repoDir, ".gitignore"), gitignore);
|
|
35
|
-
await this.git.add("-A");
|
|
36
|
-
await this.git.commit("init: jowork data repo");
|
|
37
|
-
logInfo("git", "Initialized data repo");
|
|
38
|
-
}
|
|
39
|
-
/** Commit all changes after a sync cycle */
|
|
40
|
-
async commitSync(summary) {
|
|
41
|
-
await this.git.add("-A");
|
|
42
|
-
const status = await this.git.status();
|
|
43
|
-
if (status.staged.length === 0 && status.created.length === 0 && status.modified.length === 0 && status.deleted.length === 0) {
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
const lines = [`sync: ${summary.timestamp}`, ""];
|
|
47
|
-
for (const s of summary.sources) {
|
|
48
|
-
if (s.newObjects > 0) {
|
|
49
|
-
lines.push(`${s.source}: +${s.newObjects} ${s.label ?? "objects"}`);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
if (lines.length === 2) lines.push("(no new data)");
|
|
53
|
-
const result = await this.git.commit(lines.join("\n"));
|
|
54
|
-
const sha = result.commit;
|
|
55
|
-
logInfo("git", `Committed sync: ${sha}`, {
|
|
56
|
-
files: status.staged.length + status.created.length
|
|
57
|
-
});
|
|
58
|
-
return sha;
|
|
59
|
-
}
|
|
60
|
-
/** Get recent sync log entries */
|
|
61
|
-
async getLog(limit = 20) {
|
|
62
|
-
const log = await this.git.log({ maxCount: limit });
|
|
63
|
-
return log.all.map((entry) => ({
|
|
64
|
-
hash: entry.hash.slice(0, 7),
|
|
65
|
-
date: entry.date,
|
|
66
|
-
message: entry.message.split("\n")[0]
|
|
67
|
-
}));
|
|
68
|
-
}
|
|
69
|
-
/** Get current status (changed files) */
|
|
70
|
-
async getStatus() {
|
|
71
|
-
const status = await this.git.status();
|
|
72
|
-
return {
|
|
73
|
-
modified: status.modified,
|
|
74
|
-
created: status.created,
|
|
75
|
-
deleted: status.deleted
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
export {
|
|
81
|
-
GitManager
|
|
82
|
-
};
|
package/dist/chunk-LS2AJM5A.js
DELETED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
contentHash,
|
|
3
|
-
formatIssue,
|
|
4
|
-
formatPullRequest
|
|
5
|
-
} from "./chunk-QMOFQX7X.js";
|
|
6
|
-
import {
|
|
7
|
-
createId
|
|
8
|
-
} from "./chunk-JE6TOU7W.js";
|
|
9
|
-
import {
|
|
10
|
-
logError,
|
|
11
|
-
logInfo
|
|
12
|
-
} from "./chunk-MYDK7MWB.js";
|
|
13
|
-
|
|
14
|
-
// src/sync/github.ts
|
|
15
|
-
var defaultLogger = {
|
|
16
|
-
info: (msg, ctx) => logInfo("sync", msg, ctx),
|
|
17
|
-
warn: (msg, ctx) => logError("sync", msg, ctx),
|
|
18
|
-
error: (msg, ctx) => logError("sync", msg, ctx)
|
|
19
|
-
};
|
|
20
|
-
var GITHUB_API = "https://api.github.com";
|
|
21
|
-
var MAX_REPOS = 30;
|
|
22
|
-
var RATE_LIMIT_DELAY_MS = 200;
|
|
23
|
-
async function syncGitHub(sqlite, data, logger = defaultLogger, fileWriter) {
|
|
24
|
-
const token = data.token;
|
|
25
|
-
if (!token) throw new Error("Missing GitHub token");
|
|
26
|
-
const headers = {
|
|
27
|
-
Authorization: `Bearer ${token}`,
|
|
28
|
-
Accept: "application/vnd.github.v3+json",
|
|
29
|
-
"User-Agent": "jowork/0.1.0"
|
|
30
|
-
};
|
|
31
|
-
let repos = 0;
|
|
32
|
-
let issues = 0;
|
|
33
|
-
let prs = 0;
|
|
34
|
-
let newObjects = 0;
|
|
35
|
-
const reposRes = await fetch(
|
|
36
|
-
`${GITHUB_API}/user/repos?per_page=30&sort=pushed&affiliation=owner,collaborator`,
|
|
37
|
-
{ headers }
|
|
38
|
-
);
|
|
39
|
-
if (!reposRes.ok) {
|
|
40
|
-
if (reposRes.status === 401) throw new Error("GitHub token expired or invalid");
|
|
41
|
-
if (reposRes.status === 403) throw new Error("GitHub rate limit exceeded");
|
|
42
|
-
throw new Error(`GitHub API error: ${reposRes.status}`);
|
|
43
|
-
}
|
|
44
|
-
const repoList = await reposRes.json();
|
|
45
|
-
repos = repoList.length;
|
|
46
|
-
logger.info(`Found ${repos} repos`);
|
|
47
|
-
const checkExists = sqlite.prepare("SELECT id FROM objects WHERE uri = ?");
|
|
48
|
-
const insertObj = sqlite.prepare(`
|
|
49
|
-
INSERT INTO objects (id, source, source_type, uri, title, summary, tags, content_hash, last_synced_at, created_at)
|
|
50
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
51
|
-
`);
|
|
52
|
-
const insertBody = sqlite.prepare(`
|
|
53
|
-
INSERT OR REPLACE INTO object_bodies (object_id, content, content_type, fetched_at)
|
|
54
|
-
VALUES (?, ?, ?, ?)
|
|
55
|
-
`);
|
|
56
|
-
const insertFts = sqlite.prepare(`
|
|
57
|
-
INSERT INTO objects_fts(rowid, title, summary, tags, source, source_type, body_excerpt)
|
|
58
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
59
|
-
`);
|
|
60
|
-
const getRowid = sqlite.prepare("SELECT rowid FROM objects WHERE id = ?");
|
|
61
|
-
for (const repo of repoList.slice(0, MAX_REPOS)) {
|
|
62
|
-
try {
|
|
63
|
-
const issuesRes = await fetch(
|
|
64
|
-
`${GITHUB_API}/repos/${repo.full_name}/issues?state=all&per_page=30&sort=updated`,
|
|
65
|
-
{ headers }
|
|
66
|
-
);
|
|
67
|
-
if (!issuesRes.ok) {
|
|
68
|
-
logger.warn(`Failed to fetch issues for ${repo.full_name}: ${issuesRes.status}`);
|
|
69
|
-
continue;
|
|
70
|
-
}
|
|
71
|
-
const issueList = await issuesRes.json();
|
|
72
|
-
const batchInsert = sqlite.transaction((items) => {
|
|
73
|
-
for (const item of items) {
|
|
74
|
-
const isPR = !!item.pull_request;
|
|
75
|
-
const sourceType = isPR ? "pull_request" : "issue";
|
|
76
|
-
const uri = `github://${repo.full_name}/${sourceType}/${item.number}`;
|
|
77
|
-
if (checkExists.get(uri)) continue;
|
|
78
|
-
const now = Date.now();
|
|
79
|
-
const id = createId("obj");
|
|
80
|
-
const title = `${repo.full_name}#${item.number}: ${item.title}`;
|
|
81
|
-
const summary = item.body ? item.body.length > 200 ? item.body.slice(0, 200) + "..." : item.body : item.title;
|
|
82
|
-
const tags = JSON.stringify([
|
|
83
|
-
"github",
|
|
84
|
-
sourceType,
|
|
85
|
-
item.state,
|
|
86
|
-
...item.labels.map((l) => l.name)
|
|
87
|
-
]);
|
|
88
|
-
const body = formatIssueBody(item, repo.full_name);
|
|
89
|
-
const hash = contentHash(title + (item.body ?? ""));
|
|
90
|
-
insertObj.run(
|
|
91
|
-
id,
|
|
92
|
-
"github",
|
|
93
|
-
sourceType,
|
|
94
|
-
uri,
|
|
95
|
-
title,
|
|
96
|
-
summary,
|
|
97
|
-
tags,
|
|
98
|
-
hash,
|
|
99
|
-
now,
|
|
100
|
-
new Date(item.created_at).getTime()
|
|
101
|
-
);
|
|
102
|
-
insertBody.run(id, body, "text/plain", now);
|
|
103
|
-
try {
|
|
104
|
-
const rowid = getRowid.get(id);
|
|
105
|
-
if (rowid) {
|
|
106
|
-
const excerpt = body.length > 500 ? body.slice(0, 500) : body;
|
|
107
|
-
insertFts.run(rowid.rowid, title, summary ?? "", tags, "github", sourceType, excerpt);
|
|
108
|
-
}
|
|
109
|
-
} catch {
|
|
110
|
-
}
|
|
111
|
-
if (fileWriter) {
|
|
112
|
-
try {
|
|
113
|
-
const labelNames = item.labels.map((l) => l.name);
|
|
114
|
-
const formatter = isPR ? formatPullRequest : formatIssue;
|
|
115
|
-
const fileContent = formatter({
|
|
116
|
-
source: "github",
|
|
117
|
-
repo: repo.full_name,
|
|
118
|
-
number: item.number,
|
|
119
|
-
title: item.title,
|
|
120
|
-
state: item.state,
|
|
121
|
-
author: item.user?.login ?? "unknown",
|
|
122
|
-
labels: labelNames,
|
|
123
|
-
created: item.created_at,
|
|
124
|
-
uri,
|
|
125
|
-
body: item.body ?? ""
|
|
126
|
-
});
|
|
127
|
-
const filePath = fileWriter.writeObject("github", sourceType, {
|
|
128
|
-
id,
|
|
129
|
-
repo: repo.full_name,
|
|
130
|
-
number: item.number,
|
|
131
|
-
title: item.title
|
|
132
|
-
}, fileContent);
|
|
133
|
-
sqlite.prepare("UPDATE objects SET file_path = ? WHERE id = ?").run(filePath, id);
|
|
134
|
-
} catch {
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
newObjects++;
|
|
138
|
-
if (isPR) prs++;
|
|
139
|
-
else issues++;
|
|
140
|
-
}
|
|
141
|
-
});
|
|
142
|
-
batchInsert(issueList);
|
|
143
|
-
} catch (err) {
|
|
144
|
-
logger.warn(`Error syncing ${repo.full_name}: ${err}`);
|
|
145
|
-
}
|
|
146
|
-
await new Promise((r) => setTimeout(r, RATE_LIMIT_DELAY_MS));
|
|
147
|
-
}
|
|
148
|
-
logger.info("GitHub sync complete", { repos, issues, prs, newObjects });
|
|
149
|
-
return { repos, issues, prs, newObjects };
|
|
150
|
-
}
|
|
151
|
-
function formatIssueBody(item, repo) {
|
|
152
|
-
return [
|
|
153
|
-
`${repo}#${item.number}: ${item.title}`,
|
|
154
|
-
`State: ${item.state} | Author: ${item.user?.login ?? "unknown"} | Created: ${item.created_at}`,
|
|
155
|
-
`Labels: ${item.labels.map((l) => l.name).join(", ") || "none"}`,
|
|
156
|
-
"",
|
|
157
|
-
item.body ?? "(no description)"
|
|
158
|
-
].join("\n");
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
export {
|
|
162
|
-
syncGitHub
|
|
163
|
-
};
|