ework-web 0.10.102 → 0.10.103

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ework-web",
3
- "version": "0.10.102",
3
+ "version": "0.10.103",
4
4
  "type": "module",
5
5
  "description": "ework-web — standalone multi-project issue tracker. Local SQLite-backed, no external API dependency. Bun + TypeScript + SSR HTML.",
6
6
  "license": "MIT",
package/src/store.ts CHANGED
@@ -627,6 +627,20 @@ export async function getIssueByUpstreamNumber(projectId: number, upstreamNumber
627
627
  );
628
628
  }
629
629
 
630
+ export async function linkIssueToUpstream(issueId: number, upstreamNumber: number): Promise<boolean> {
631
+ try {
632
+ const res = await getDB().run(
633
+ "UPDATE {{issues}} SET upstream_issue_number = ?, updated_at = ? WHERE id = ? AND upstream_issue_number IS NULL",
634
+ [upstreamNumber, now(), issueId]
635
+ );
636
+ return res.changes > 0;
637
+ } catch {
638
+ // Unique index (project_id, upstream_issue_number): another row already
639
+ // holds this mapping — leave it alone, the existing winner stays linked.
640
+ return false;
641
+ }
642
+ }
643
+
630
644
  export async function getCommentByUpstreamId(upstreamCommentId: number): Promise<CommentRow | null> {
631
645
  return await getDB().get<CommentRow>(
632
646
  "SELECT * FROM {{comments}} WHERE upstream_comment_id = ?",
@@ -3,7 +3,9 @@ import {
3
3
  type ProjectRow,
4
4
  type IssueRow,
5
5
  getProjectById,
6
+ getIssue,
6
7
  getIssueByUpstreamNumber,
8
+ linkIssueToUpstream,
7
9
  getCommentByUpstreamId,
8
10
  createIssue,
9
11
  ensureUser,
@@ -110,6 +112,22 @@ export class UpstreamSync {
110
112
  }
111
113
 
112
114
  private async importIssue(gi: GiteaIssue, emit: boolean): Promise<void> {
115
+ const body = gi.body ?? "";
116
+ // Issues ework-mirror created upstream reference their origin issue by
117
+ // number in the footer. Linking instead of importing prevents the echo
118
+ // loop (local → mirror → GitHub → poll → twin) while keeping comment and
119
+ // state sync flowing to the original.
120
+ const mirrored = body.includes("<!-- ework-mirror -->")
121
+ ? body.match(/Mirrored from ework issue #(\d+)/)
122
+ : null;
123
+ if (mirrored?.[1]) {
124
+ const origin = await getIssue(this.project.id, Number(mirrored[1]));
125
+ if (origin) {
126
+ await linkIssueToUpstream(origin.id, gi.number);
127
+ return;
128
+ }
129
+ }
130
+ if (body.includes("<!-- ework-mirror -->")) return;
113
131
  await ensureUser(gi.user?.login ?? "upstream", fromGithubBot(gi.user?.login) ? "bot" : "human");
114
132
  await createIssue(
115
133
  this.project.id,
@@ -82,7 +82,7 @@ function syncCardHtml(project: ProjectRow, sync: UpstreamSyncRow | null): string
82
82
  ${statusHtml}
83
83
  <div class="form-grid">
84
84
  <div><label for="s-base">上游地址(Gitea 根地址,如 http://host:3000)</label>
85
- <input id="s-base" name="base_url" type="url" placeholder="http://192.168.10.96:3300" value="${escapeAttr(baseUrl)}" required></div>
85
+ <input id="s-base" name="base_url" type="url" placeholder="http://192.168.1.100:3300" value="${escapeAttr(baseUrl)}" required></div>
86
86
  <div><label for="s-owner">上游 owner</label>
87
87
  <input id="s-owner" name="upstream_owner" value="${escapeAttr(sync?.upstream_owner ?? project.owner)}" required></div>
88
88
  <div><label for="s-repo">上游 repo</label>