@unbrained/pm-web 2026.8.7 → 2026.8.14

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.
Files changed (173) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/app.d.ts +16 -0
  3. package/dist/app.js +16 -0
  4. package/dist/app.js.map +1 -1
  5. package/dist/auth.d.ts +5 -0
  6. package/dist/auth.js.map +1 -1
  7. package/dist/board.d.ts +53 -0
  8. package/dist/board.js +48 -0
  9. package/dist/board.js.map +1 -1
  10. package/dist/crypto.d.ts +23 -0
  11. package/dist/crypto.js +32 -0
  12. package/dist/crypto.js.map +1 -1
  13. package/dist/db.d.ts +19 -0
  14. package/dist/db.js +19 -0
  15. package/dist/db.js.map +1 -1
  16. package/dist/ical.d.ts +72 -0
  17. package/dist/ical.js +73 -0
  18. package/dist/ical.js.map +1 -1
  19. package/dist/index.d.ts +11 -0
  20. package/dist/index.js +52 -1
  21. package/dist/index.js.map +1 -1
  22. package/dist/middleware/auth.d.ts +8 -0
  23. package/dist/middleware/auth.js.map +1 -1
  24. package/dist/oidc.d.ts +87 -0
  25. package/dist/oidc.js +113 -0
  26. package/dist/oidc.js.map +1 -1
  27. package/dist/routes/admin.js +15 -0
  28. package/dist/routes/admin.js.map +1 -1
  29. package/dist/routes/github.js +13 -0
  30. package/dist/routes/github.js.map +1 -1
  31. package/dist/routes/oidc.d.ts +10 -0
  32. package/dist/routes/oidc.js +51 -0
  33. package/dist/routes/oidc.js.map +1 -1
  34. package/dist/routes/pm.js +132 -1
  35. package/dist/routes/pm.js.map +1 -1
  36. package/dist/routes/sharing.js +8 -0
  37. package/dist/routes/sharing.js.map +1 -1
  38. package/dist/services/mutation-event-watcher.js +13 -0
  39. package/dist/services/mutation-event-watcher.js.map +1 -1
  40. package/dist/services/pm-runner.d.ts +82 -0
  41. package/dist/services/pm-runner.js +121 -0
  42. package/dist/services/pm-runner.js.map +1 -1
  43. package/dist/services/project-watcher.d.ts +22 -0
  44. package/dist/services/project-watcher.js +51 -0
  45. package/dist/services/project-watcher.js.map +1 -1
  46. package/dist/services/realtime-bus.d.ts +46 -0
  47. package/dist/services/realtime-bus.js +59 -0
  48. package/dist/services/realtime-bus.js.map +1 -1
  49. package/dist/services/sse.d.ts +134 -0
  50. package/dist/services/sse.js +145 -0
  51. package/dist/services/sse.js.map +1 -1
  52. package/manifest.json +1 -1
  53. package/package.json +5 -3
  54. package/public/src/app.js +44 -1
  55. package/public/src/app.js.map +1 -1
  56. package/public/src/app.ts +44 -1
  57. package/public/src/components/modals.js +11 -0
  58. package/public/src/components/modals.js.map +1 -1
  59. package/public/src/components/modals.ts +11 -0
  60. package/public/src/components/toast.js +2 -0
  61. package/public/src/components/toast.js.map +1 -1
  62. package/public/src/components/toast.ts +2 -0
  63. package/public/src/constants.js +21 -4
  64. package/public/src/constants.js.map +1 -1
  65. package/public/src/constants.ts +21 -4
  66. package/public/src/filters.js +10 -7
  67. package/public/src/filters.js.map +1 -1
  68. package/public/src/filters.ts +10 -7
  69. package/public/src/i18n.js +11 -1
  70. package/public/src/i18n.js.map +1 -1
  71. package/public/src/i18n.ts +13 -1
  72. package/public/src/state.js +3 -0
  73. package/public/src/state.js.map +1 -1
  74. package/public/src/state.ts +3 -0
  75. package/public/src/sw.ts +71 -7
  76. package/public/src/theme.js +13 -1
  77. package/public/src/theme.js.map +1 -1
  78. package/public/src/theme.ts +15 -1
  79. package/public/src/types.ts +2 -0
  80. package/public/src/utils.js +26 -1
  81. package/public/src/utils.js.map +1 -1
  82. package/public/src/utils.ts +26 -1
  83. package/public/src/views/activity.js +1 -0
  84. package/public/src/views/activity.js.map +1 -1
  85. package/public/src/views/activity.ts +1 -0
  86. package/public/src/views/admin.js +134 -0
  87. package/public/src/views/admin.js.map +1 -1
  88. package/public/src/views/admin.ts +134 -0
  89. package/public/src/views/auth.js +31 -0
  90. package/public/src/views/auth.js.map +1 -1
  91. package/public/src/views/auth.ts +31 -0
  92. package/public/src/views/calendar.js +3 -0
  93. package/public/src/views/calendar.js.map +1 -1
  94. package/public/src/views/calendar.ts +3 -0
  95. package/public/src/views/comments-audit.js +1 -0
  96. package/public/src/views/comments-audit.js.map +1 -1
  97. package/public/src/views/comments-audit.ts +1 -0
  98. package/public/src/views/config.js +67 -0
  99. package/public/src/views/config.js.map +1 -1
  100. package/public/src/views/config.ts +67 -0
  101. package/public/src/views/context.js +2 -0
  102. package/public/src/views/context.js.map +1 -1
  103. package/public/src/views/context.ts +2 -0
  104. package/public/src/views/create.js +3 -0
  105. package/public/src/views/create.js.map +1 -1
  106. package/public/src/views/create.ts +3 -0
  107. package/public/src/views/dedupe.js +1 -0
  108. package/public/src/views/dedupe.js.map +1 -1
  109. package/public/src/views/dedupe.ts +1 -0
  110. package/public/src/views/export.js +6 -0
  111. package/public/src/views/export.js.map +1 -1
  112. package/public/src/views/export.ts +6 -0
  113. package/public/src/views/github.js +58 -0
  114. package/public/src/views/github.js.map +1 -1
  115. package/public/src/views/github.ts +58 -0
  116. package/public/src/views/graph-canvas.js +18 -0
  117. package/public/src/views/graph-canvas.js.map +1 -1
  118. package/public/src/views/graph-canvas.ts +20 -0
  119. package/public/src/views/graph.js +41 -0
  120. package/public/src/views/graph.js.map +1 -1
  121. package/public/src/views/graph.ts +42 -1
  122. package/public/src/views/groups.js +45 -0
  123. package/public/src/views/groups.js.map +1 -1
  124. package/public/src/views/groups.ts +45 -0
  125. package/public/src/views/guide.js +3 -0
  126. package/public/src/views/guide.js.map +1 -1
  127. package/public/src/views/guide.ts +3 -0
  128. package/public/src/views/health.js +3 -0
  129. package/public/src/views/health.js.map +1 -1
  130. package/public/src/views/health.ts +3 -0
  131. package/public/src/views/items.js +196 -6
  132. package/public/src/views/items.js.map +1 -1
  133. package/public/src/views/items.ts +196 -6
  134. package/public/src/views/normalize.js +2 -0
  135. package/public/src/views/normalize.js.map +1 -1
  136. package/public/src/views/normalize.ts +2 -0
  137. package/public/src/views/packages.js +41 -0
  138. package/public/src/views/packages.js.map +1 -1
  139. package/public/src/views/packages.ts +41 -0
  140. package/public/src/views/plan-execution.js +6 -0
  141. package/public/src/views/plan-execution.js.map +1 -1
  142. package/public/src/views/plan-execution.ts +8 -0
  143. package/public/src/views/plan.js +145 -0
  144. package/public/src/views/plan.js.map +1 -1
  145. package/public/src/views/plan.ts +146 -1
  146. package/public/src/views/projects.js +60 -0
  147. package/public/src/views/projects.js.map +1 -1
  148. package/public/src/views/projects.ts +60 -0
  149. package/public/src/views/router.js +43 -0
  150. package/public/src/views/router.js.map +1 -1
  151. package/public/src/views/router.ts +43 -0
  152. package/public/src/views/search.js +5 -0
  153. package/public/src/views/search.js.map +1 -1
  154. package/public/src/views/search.ts +5 -0
  155. package/public/src/views/settings.js +36 -0
  156. package/public/src/views/settings.js.map +1 -1
  157. package/public/src/views/settings.ts +36 -0
  158. package/public/src/views/shared.js +1 -0
  159. package/public/src/views/shared.js.map +1 -1
  160. package/public/src/views/shared.ts +1 -0
  161. package/public/src/views/sharing.js +32 -0
  162. package/public/src/views/sharing.js.map +1 -1
  163. package/public/src/views/sharing.ts +32 -0
  164. package/public/src/views/stats.js +1 -0
  165. package/public/src/views/stats.js.map +1 -1
  166. package/public/src/views/stats.ts +1 -0
  167. package/public/src/views/templates.js +4 -0
  168. package/public/src/views/templates.js.map +1 -1
  169. package/public/src/views/templates.ts +4 -0
  170. package/public/src/views/validate.js +1 -0
  171. package/public/src/views/validate.js.map +1 -1
  172. package/public/src/views/validate.ts +1 -0
  173. package/public/sw.js +60 -5
@@ -6,6 +6,14 @@ import { api } from '../api.js';
6
6
  import { escHtml } from '../utils.js';
7
7
  import { showModal, hideModal, createModal, confirmDialog } from '../components/modals.js';
8
8
  import { toast } from '../components/toast.js';
9
+ /**
10
+ * Derives a display record (name, detail line, two-letter avatar, and group
11
+ * flag) for a single share row, preferring group fields when the row
12
+ * references a group and falling back through user fields otherwise.
13
+ *
14
+ * @param share - the share row to summarize.
15
+ * @returns display fields for rendering a member row.
16
+ */
9
17
  function shareDisplay(share) {
10
18
  const isGroup = Boolean(share.group_id || share.groupId);
11
19
  const name = isGroup
@@ -16,6 +24,10 @@ function shareDisplay(share) {
16
24
  : (share.user_email || share.email || '');
17
25
  return { name, detail, avatar: name.slice(0, 2).toUpperCase(), isGroup };
18
26
  }
27
+ /**
28
+ * Renders the project sharing page header and a placeholder, then loads the
29
+ * current list of shares. Shows an empty state when no project is selected.
30
+ */
19
31
  export async function renderSharingView() {
20
32
  const el = document.getElementById('content-sharing');
21
33
  if (!el)
@@ -38,6 +50,11 @@ export async function renderSharingView() {
38
50
  <div id="shares-list"><div class="loading-state"><div class="loading-spinner"></div></div></div>`;
39
51
  await loadShares();
40
52
  }
53
+ /**
54
+ * Fetches the shares for the current project and renders each one as a
55
+ * member row with its permission and a remove control, or an empty state
56
+ * when nobody has been invited yet.
57
+ */
41
58
  async function loadShares() {
42
59
  const el = document.getElementById('shares-list');
43
60
  if (!el)
@@ -84,6 +101,10 @@ async function loadShares() {
84
101
  el.innerHTML = `<div class="empty-state"><div class="empty-state-text">Error: ${escHtml(err instanceof Error ? err.message : String(err))}</div></div>`;
85
102
  }
86
103
  }
104
+ /**
105
+ * Builds and displays the invite dialog for sharing the current project,
106
+ * collecting an email or group id and a permission level.
107
+ */
87
108
  export function openShareModal() {
88
109
  createModal('share-modal', 'Invite to Project', `
89
110
  <div class="form-group">
@@ -105,6 +126,11 @@ export function openShareModal() {
105
126
  <button class="btn btn-primary" onclick="window.__app.submitShare()"><span>Send Invite</span></button>`);
106
127
  showModal('share-modal');
107
128
  }
129
+ /**
130
+ * Reads the invite form fields and posts a new share for the current project
131
+ * using the entered email or group id and selected permission. Surfaces
132
+ * validation and server errors inline and refreshes the list on success.
133
+ */
108
134
  export async function submitShare() {
109
135
  const email = document.getElementById('share-email')?.value?.trim() || '';
110
136
  const groupId = document.getElementById('share-group-id')?.value?.trim() || '';
@@ -137,6 +163,12 @@ export async function submitShare() {
137
163
  }
138
164
  }
139
165
  }
166
+ /**
167
+ * Asks for confirmation then deletes the given share from the current
168
+ * project, refreshing the list and showing errors as toasts.
169
+ *
170
+ * @param shareId - identifier of the share to revoke.
171
+ */
140
172
  export function removeShare(shareId) {
141
173
  confirmDialog('Remove Access?', 'The user will lose access to this project.', async () => {
142
174
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"sharing.js","sourceRoot":"","sources":["sharing.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sharing.js","sourceRoot":"","sources":["sharing.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,14 @@ import { showModal, hideModal, createModal, confirmDialog } from '../components/
8
8
  import { toast } from '../components/toast.js';
9
9
  import type { ShareRow, SharesResponse } from '../api-types.js';
10
10
 
11
+ /**
12
+ * Derives a display record (name, detail line, two-letter avatar, and group
13
+ * flag) for a single share row, preferring group fields when the row
14
+ * references a group and falling back through user fields otherwise.
15
+ *
16
+ * @param share - the share row to summarize.
17
+ * @returns display fields for rendering a member row.
18
+ */
11
19
  function shareDisplay(share: ShareRow): { name: string; detail: string; avatar: string; isGroup: boolean } {
12
20
  const isGroup = Boolean(share.group_id || share.groupId);
13
21
  const name = isGroup
@@ -19,6 +27,10 @@ function shareDisplay(share: ShareRow): { name: string; detail: string; avatar:
19
27
  return { name, detail, avatar: name.slice(0, 2).toUpperCase(), isGroup };
20
28
  }
21
29
 
30
+ /**
31
+ * Renders the project sharing page header and a placeholder, then loads the
32
+ * current list of shares. Shows an empty state when no project is selected.
33
+ */
22
34
  export async function renderSharingView(): Promise<void> {
23
35
  const el = document.getElementById('content-sharing');
24
36
  if (!el) return;
@@ -38,6 +50,11 @@ export async function renderSharingView(): Promise<void> {
38
50
  await loadShares();
39
51
  }
40
52
 
53
+ /**
54
+ * Fetches the shares for the current project and renders each one as a
55
+ * member row with its permission and a remove control, or an empty state
56
+ * when nobody has been invited yet.
57
+ */
41
58
  async function loadShares(): Promise<void> {
42
59
  const el = document.getElementById('shares-list');
43
60
  if (!el) return;
@@ -82,6 +99,10 @@ async function loadShares(): Promise<void> {
82
99
  }
83
100
  }
84
101
 
102
+ /**
103
+ * Builds and displays the invite dialog for sharing the current project,
104
+ * collecting an email or group id and a permission level.
105
+ */
85
106
  export function openShareModal(): void {
86
107
  createModal('share-modal','Invite to Project',`
87
108
  <div class="form-group">
@@ -106,6 +127,11 @@ export function openShareModal(): void {
106
127
  showModal('share-modal');
107
128
  }
108
129
 
130
+ /**
131
+ * Reads the invite form fields and posts a new share for the current project
132
+ * using the entered email or group id and selected permission. Surfaces
133
+ * validation and server errors inline and refreshes the list on success.
134
+ */
109
135
  export async function submitShare(): Promise<void> {
110
136
  const email = (document.getElementById('share-email') as HTMLInputElement | null)?.value?.trim() || '';
111
137
  const groupId = (document.getElementById('share-group-id') as HTMLInputElement | null)?.value?.trim() || '';
@@ -129,6 +155,12 @@ export async function submitShare(): Promise<void> {
129
155
  }
130
156
  }
131
157
 
158
+ /**
159
+ * Asks for confirmation then deletes the given share from the current
160
+ * project, refreshing the list and showing errors as toasts.
161
+ *
162
+ * @param shareId - identifier of the share to revoke.
163
+ */
132
164
  export function removeShare(shareId: string): void {
133
165
  confirmDialog('Remove Access?', 'The user will lose access to this project.', async () => {
134
166
  try {
@@ -4,6 +4,7 @@
4
4
  import { state } from '../state.js';
5
5
  import { api } from '../api.js';
6
6
  import { escHtml, statusBadge, typeIcon } from '../utils.js';
7
+ /** Renders project statistics — total, open, closed, blocked, and completion cards, plus by-status and by-type breakdown bars and any project health issues — fetched in parallel from the stats, aggregate, and health endpoints. */
7
8
  export async function renderStatsView() {
8
9
  const el = document.getElementById('content-stats');
9
10
  if (!el)
@@ -1 +1 @@
1
- {"version":3,"file":"stats.js","sourceRoot":"","sources":["stats.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stats.js","sourceRoot":"","sources":["stats.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,7 @@ import { api } from '../api.js';
6
6
  import { escHtml, statusBadge, typeIcon } from '../utils.js';
7
7
  import type { HealthResponse, StatsResponse } from '../api-types.js';
8
8
 
9
+ /** Renders project statistics — total, open, closed, blocked, and completion cards, plus by-status and by-type breakdown bars and any project health issues — fetched in parallel from the stats, aggregate, and health endpoints. */
9
10
  export async function renderStatsView(): Promise<void> {
10
11
  const el = document.getElementById('content-stats');
11
12
  if (!el) return;
@@ -6,6 +6,7 @@ import { api } from '../api.js';
6
6
  import { escHtml, typeIcon } from '../utils.js';
7
7
  import { toast } from '../components/toast.js';
8
8
  import { showView } from './router.js';
9
+ /** Renders the templates view header for the current project, then fetches and renders the available item templates. */
9
10
  export async function renderTemplatesView() {
10
11
  const el = document.getElementById('content-templates');
11
12
  if (!el)
@@ -27,6 +28,7 @@ export async function renderTemplatesView() {
27
28
  <div id="templates-content"><div class="loading-state"><div class="loading-spinner"></div></div></div>`;
28
29
  await fetchAndRenderTemplates();
29
30
  }
31
+ /** Loads item templates for the current project from the templates endpoint and renders either an empty-state hint or a responsive grid of template cards. */
30
32
  async function fetchAndRenderTemplates() {
31
33
  const pid = state.currentProject?.id;
32
34
  if (!pid)
@@ -62,6 +64,7 @@ async function fetchAndRenderTemplates() {
62
64
  el.innerHTML = `<div class="empty-state"><div class="empty-state-text">Failed to load templates: ${escHtml(err instanceof Error ? err.message : String(err))}</div></div>`;
63
65
  }
64
66
  }
67
+ /** Renders a single template card showing its name, type icon, priority badge, tags, and description, with a button to create a new item from it. */
65
68
  function renderTemplateCard(t) {
66
69
  const name = t.name || t.id || 'Unnamed';
67
70
  const type = t.type || t.defaults?.type || '';
@@ -87,6 +90,7 @@ function renderTemplateCard(t) {
87
90
  </div>
88
91
  </div>`;
89
92
  }
93
+ /** Navigates to the create-item view and pre-fills its fields (type, priority, tags, description, sprint, release, assignee, acceptance criteria) from the selected template. */
90
94
  export function createFromTemplate(name, template) {
91
95
  // Navigate to create view and pre-fill from template
92
96
  showView('create');
@@ -1 +1 @@
1
- {"version":3,"file":"templates.js","sourceRoot":"","sources":["templates.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["templates.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,7 @@ import { toast } from '../components/toast.js';
8
8
  import { showView } from './router.js';
9
9
  import type { TemplateEntry, TemplatesResponse } from '../api-types.js';
10
10
 
11
+ /** Renders the templates view header for the current project, then fetches and renders the available item templates. */
11
12
  export async function renderTemplatesView(): Promise<void> {
12
13
  const el = document.getElementById('content-templates');
13
14
  if (!el) return;
@@ -29,6 +30,7 @@ export async function renderTemplatesView(): Promise<void> {
29
30
  await fetchAndRenderTemplates();
30
31
  }
31
32
 
33
+ /** Loads item templates for the current project from the templates endpoint and renders either an empty-state hint or a responsive grid of template cards. */
32
34
  async function fetchAndRenderTemplates(): Promise<void> {
33
35
  const pid = state.currentProject?.id;
34
36
  if (!pid) return;
@@ -61,6 +63,7 @@ async function fetchAndRenderTemplates(): Promise<void> {
61
63
  }
62
64
  }
63
65
 
66
+ /** Renders a single template card showing its name, type icon, priority badge, tags, and description, with a button to create a new item from it. */
64
67
  function renderTemplateCard(t: TemplateEntry): string {
65
68
  const name = t.name || t.id || 'Unnamed';
66
69
  const type = t.type || t.defaults?.type || '';
@@ -87,6 +90,7 @@ function renderTemplateCard(t: TemplateEntry): string {
87
90
  </div>`;
88
91
  }
89
92
 
93
+ /** Navigates to the create-item view and pre-fills its fields (type, priority, tags, description, sprint, release, assignee, acceptance criteria) from the selected template. */
90
94
  export function createFromTemplate(name: string, template: TemplateEntry): void {
91
95
  // Navigate to create view and pre-fill from template
92
96
  showView('create');
@@ -4,6 +4,7 @@
4
4
  import { state } from '../state.js';
5
5
  import { api } from '../api.js';
6
6
  import { escHtml } from '../utils.js';
7
+ /** Renders metadata and lifecycle validation results for the current project: a combined list of error and warning issues with item links, an optional summary, and an overall pass/fail status. */
7
8
  export async function renderValidateView() {
8
9
  const el = document.getElementById('content-validate');
9
10
  if (!el)
@@ -1 +1 @@
1
- {"version":3,"file":"validate.js","sourceRoot":"","sources":["validate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["validate.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,7 @@ import { api } from '../api.js';
6
6
  import { escHtml } from '../utils.js';
7
7
  import type { ValidateIssue, ValidateResponse } from '../api-types.js';
8
8
 
9
+ /** Renders metadata and lifecycle validation results for the current project: a combined list of error and warning issues with item links, an optional summary, and an overall pass/fail status. */
9
10
  export async function renderValidateView(): Promise<void> {
10
11
  const el = document.getElementById('content-validate');
11
12
  if (!el) return;
package/public/sw.js CHANGED
@@ -100,6 +100,9 @@ const OFFLINE_HTML = `<!DOCTYPE html>
100
100
  </div>
101
101
  </body>
102
102
  </html>`;
103
+ /** Open (creating on first run) the IndexedDB database backing the offline
104
+ * mutation queue, ensuring the `mutations` object store and its timestamp
105
+ * index exist. Resolves with the ready database handle. */
103
106
  function openMutationDB() {
104
107
  return new Promise((resolve, reject) => {
105
108
  const request = indexedDB.open(MUTATION_DB, 1);
@@ -156,19 +159,25 @@ async function queueMutation(method, path, body) {
156
159
  return false;
157
160
  }
158
161
  }
162
+ /** Read every queued mutation out of IndexedDB in insertion order. Returns
163
+ * `{ ok: true, mutations }` on success (including an empty array when the
164
+ * queue is genuinely empty) or `{ ok: false, error }` on storage failure so
165
+ * callers can distinguish an empty queue from an unreadable one instead of
166
+ * treating both as drained. */
159
167
  async function getQueuedMutations() {
160
168
  try {
161
169
  const db = await openMutationDB();
162
170
  const tx = db.transaction(MUTATION_STORE, 'readonly');
163
171
  const store = tx.objectStore(MUTATION_STORE);
164
- return await new Promise((resolve, reject) => {
172
+ const mutations = await new Promise((resolve, reject) => {
165
173
  const request = store.getAll();
166
174
  request.onsuccess = () => resolve(request.result);
167
175
  request.onerror = () => reject(request.error);
168
176
  });
177
+ return { ok: true, mutations };
169
178
  }
170
- catch {
171
- return [];
179
+ catch (error) {
180
+ return { ok: false, error };
172
181
  }
173
182
  }
174
183
  /**
@@ -189,10 +198,22 @@ async function clearMutation(id) {
189
198
  return false;
190
199
  }
191
200
  }
201
+ /** Replay queued mutations to the API in order, removing each on success and
202
+ * stopping at the first failure so it can retry later, then post-message the
203
+ * connected clients with how many were replayed or remain. A storage read
204
+ * failure is never treated as a drained queue: the initial read failure
205
+ * aborts the flush, and a final read failure reports a partial result rather
206
+ * than claiming all mutations were replayed. */
192
207
  async function flushMutationQueue() {
193
- const mutations = await getQueuedMutations();
208
+ const read = await getQueuedMutations();
209
+ if (!read.ok) {
210
+ console.warn('Failed to read mutation queue:', read.error);
211
+ return;
212
+ }
213
+ const mutations = read.mutations;
194
214
  if (mutations.length === 0)
195
215
  return;
216
+ let replayed = 0;
196
217
  for (const mut of mutations) {
197
218
  try {
198
219
  const opts = {
@@ -210,6 +231,7 @@ async function flushMutationQueue() {
210
231
  // avoid duplicate replays on the next flush; it will retry later.
211
232
  break;
212
233
  }
234
+ replayed++;
213
235
  }
214
236
  else {
215
237
  console.warn('Offline mutation failed:', mut.method, mut.path, res.status);
@@ -223,8 +245,25 @@ async function flushMutationQueue() {
223
245
  }
224
246
  }
225
247
  // Notify clients about replayed mutations
226
- const remaining = await getQueuedMutations();
248
+ const remainingRead = await getQueuedMutations();
227
249
  const clients = await sw.clients.matchAll();
250
+ if (!remainingRead.ok) {
251
+ // Could not re-read the queue — do NOT claim all mutations were replayed.
252
+ // Report a partial result with the known replayed count so unreplayed
253
+ // mutations are not treated as drained.
254
+ console.warn('Failed to re-read mutation queue after replay:', remainingRead.error);
255
+ if (mutations.length > 0) {
256
+ clients.forEach((client) => {
257
+ client.postMessage({
258
+ type: 'MUTATIONS_PARTIAL',
259
+ replayed,
260
+ remaining: mutations.length - replayed,
261
+ });
262
+ });
263
+ }
264
+ return;
265
+ }
266
+ const remaining = remainingRead.mutations;
228
267
  if (remaining.length === 0 && mutations.length > 0) {
229
268
  clients.forEach((client) => {
230
269
  client.postMessage({ type: 'MUTATIONS_REPLAYED', count: mutations.length });
@@ -385,3 +424,19 @@ sw.addEventListener('sync', (event) => {
385
424
  sw.addEventListener('online', () => {
386
425
  void flushMutationQueue();
387
426
  });
427
+ // ── Test-only: expose queue internals ──
428
+ // app.ts registers this file as a CLASSIC worker (`register('/sw.js', ...)`
429
+ // with no `type: 'module'`), so it cannot use `export` — a module-mode script
430
+ // fails to load under a classic registration, which would take offline support
431
+ // down. That leaves a global as the only seam a test can reach.
432
+ //
433
+ // It is inert in the browser because a classic service worker is the only
434
+ // script that ever runs in its own global scope: no page script, extension or
435
+ // import shares it, so nothing exists that could set the flag before this line
436
+ // executes. That invariant is the registration mode, not the flag name — if
437
+ // app.ts ever registers with `type: 'module'`, replace this with real exports
438
+ // rather than keeping both.
439
+ const __testGlobals = globalThis;
440
+ if (__testGlobals.__swTestHarness) {
441
+ __testGlobals.__swInternals = { getQueuedMutations, flushMutationQueue, queueMutation, clearMutation };
442
+ }