@krapwoo/ds-viewer 0.3.0 → 0.4.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/README.md +69 -0
- package/config/index.ts +4 -2
- package/dist/cli/dev.js +312 -15
- package/dist/cli/doctor.js +10 -0
- package/dist/cli/endpoint.js +142 -0
- package/dist/cli/githubAction.js +8 -11
- package/dist/cli/init.js +3 -3
- package/dist/cli/kitDiff.js +132 -0
- package/dist/cli/kitRoot.js +20 -0
- package/dist/cli/main.js +77 -18
- package/dist/cli/migrate.js +30 -0
- package/dist/cli/migrateEntry.js +19 -0
- package/dist/cli/migrations/index.js +14 -0
- package/dist/cli/migrations/types.js +9 -0
- package/dist/cli/packageManager.js +29 -0
- package/dist/cli/packageVersion.js +24 -0
- package/dist/cli/semver.js +26 -0
- package/dist/cli/update.js +93 -0
- package/dist/cli/updateCheck.js +143 -0
- package/dist/cli/updatePlan.js +202 -0
- package/dist/cli/workspace.js +10 -5
- package/dist/native/catalog/catalogNavigation.js +129 -0
- package/dist/native/catalog/tokens.js +15 -0
- package/native/catalog/CatalogShell.tsx +105 -11
- package/native/catalog/CatalogSidebar.tsx +58 -2
- package/native/catalog/SectionBlock.tsx +5 -0
- package/native/catalog/UpdatePanel.tsx +556 -0
- package/native/catalog/catalogNavigation.ts +70 -1
- package/native/catalog/index.ts +3 -0
- package/native/catalog/tokens.ts +15 -0
- package/native/catalog/types.ts +11 -0
- package/native/catalog/updatePanelState.ts +74 -0
- package/package.json +1 -1
package/native/catalog/tokens.ts
CHANGED
|
@@ -63,6 +63,10 @@ export const CATALOG_LAYOUT = {
|
|
|
63
63
|
logoMark: 32,
|
|
64
64
|
logoWordmarkHeight: 28,
|
|
65
65
|
logoCaptionGap: 6,
|
|
66
|
+
/** Max width of the update page's content column (approved mockup: direction "C · Update
|
|
67
|
+
* page", content at most 512px) — independent of `CATALOG_MAX_CONTENT_WIDTH` (1200px), which
|
|
68
|
+
* is every other page's column width. */
|
|
69
|
+
updateContentMaxWidth: 512,
|
|
66
70
|
} as const;
|
|
67
71
|
|
|
68
72
|
/** Max width of the main content column. */
|
|
@@ -124,4 +128,15 @@ export const CATALOG_COLOR = {
|
|
|
124
128
|
/** 3px keyboard focus ring on every catalog control. */
|
|
125
129
|
focusRing: '#c9d7ff',
|
|
126
130
|
code: 'Menlo',
|
|
131
|
+
/** Major-update banner background/border/text (design §5 "Viewer notice"). */
|
|
132
|
+
warning: '#8a4b00',
|
|
133
|
+
warningSubtle: '#fff4e0',
|
|
134
|
+
warningBorder: '#f0cf97',
|
|
135
|
+
/** "Can't prepare"/failure note-boxes on the update page. */
|
|
136
|
+
danger: '#b3261e',
|
|
137
|
+
dangerSubtle: '#fdecea',
|
|
138
|
+
dangerBorder: '#f2b8b5',
|
|
139
|
+
/** The update page's post-update success note-box and "Updated" pill. */
|
|
140
|
+
success: '#1e6b3a',
|
|
141
|
+
successSubtle: '#e8f5ec',
|
|
127
142
|
} as const;
|
package/native/catalog/types.ts
CHANGED
|
@@ -195,3 +195,14 @@ export interface NavGroup<TId extends string = string> {
|
|
|
195
195
|
label: string;
|
|
196
196
|
ids: readonly TId[];
|
|
197
197
|
}
|
|
198
|
+
|
|
199
|
+
/** Design §5 "Update check"/"Viewer notice" — the generated entry file (Task 17) imports this
|
|
200
|
+
* shape directly from `.ds-viewer/update.json`; `null` when no update is known (disabled,
|
|
201
|
+
* offline, or genuinely up to date — the viewer treats all three identically). */
|
|
202
|
+
export interface UpdateNotice {
|
|
203
|
+
current: string;
|
|
204
|
+
latest: string;
|
|
205
|
+
breaking: boolean;
|
|
206
|
+
summary: string[];
|
|
207
|
+
releasedAt?: string;
|
|
208
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/** The same shape as `cli/updatePlan.ts`'s `UpdatePlan` — duplicated, not imported: `native/catalog/`
|
|
2
|
+
* is the published package root and never imports from `cli/` (the reverse is normal: `cli/`
|
|
3
|
+
* already imports `native/catalog/` throughout). The endpoint's `POST /plan` response is this
|
|
4
|
+
* exact shape (confirmed by `cli/endpoint.ts`, Task 12, which forwards `cli/updatePlan.ts`'s own
|
|
5
|
+
* `UpdatePlan` verbatim as JSON). */
|
|
6
|
+
export interface UpdatePlanView {
|
|
7
|
+
current: string;
|
|
8
|
+
latest: string;
|
|
9
|
+
breaking: boolean;
|
|
10
|
+
summary: string[];
|
|
11
|
+
releasedAt?: string;
|
|
12
|
+
files: { path: string; reason: string; dirty: boolean }[];
|
|
13
|
+
dirtyFiles: string[];
|
|
14
|
+
kitFilesDiffering: number;
|
|
15
|
+
outsideGitRepo: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** The same shape as `cli/endpoint.ts`'s `UpdateStatus`, same reason as above. `updating`'s each
|
|
19
|
+
* step carries a three-way `state`, not a boolean `done` (Important finding, Fable correction
|
|
20
|
+
* pass: the approved mockup's own `updating` state shows one step mid-flight — `ic now`, a
|
|
21
|
+
* distinct icon from both `done` and the not-yet-reached `todo` — which a boolean cannot
|
|
22
|
+
* represent). `success` also carries the changed files' paths and the version just installed
|
|
23
|
+
* (Errata 1b: `update.json` becomes `null` once latest equals current, so `success` must carry
|
|
24
|
+
* its own `latest` rather than relying on the now-gone `update` prop) — Task 16's `ready` phase
|
|
25
|
+
* has `plan.files`/`plan.latest` to show the same values, but `plan` is gone by the time
|
|
26
|
+
* `success` renders (the page has reloaded onto the new version), so the result itself must carry
|
|
27
|
+
* them. */
|
|
28
|
+
export type UpdateStatusView =
|
|
29
|
+
| { phase: 'idle' }
|
|
30
|
+
| { phase: 'updating'; steps: { label: string; state: 'done' | 'now' | 'todo' }[] }
|
|
31
|
+
| { phase: 'restarting' }
|
|
32
|
+
| { phase: 'success'; doctorSummary: string; files: string[]; latest: string }
|
|
33
|
+
| { phase: 'failure'; log: string; failedStep: string };
|
|
34
|
+
|
|
35
|
+
export type UpdatePhase = 'checking' | 'ready' | 'dirty' | 'offline' | 'updating' | 'restarting' | 'success' | 'failure';
|
|
36
|
+
|
|
37
|
+
/** Minor finding, Fable correction pass: every `{ error }` previously mapped to the same
|
|
38
|
+
* `'offline'` phase regardless of *which* error — including `buildUpdatePlan`'s own "Already on
|
|
39
|
+
* the latest version" message, which is not an offline/failure condition at all. `UpdatePanel`
|
|
40
|
+
* (Task 16) still only needs one phase to key its `switch` on; it reads `result.error` itself,
|
|
41
|
+
* directly, to pick between the two copies the mockup's `offline` state and a plain "you're
|
|
42
|
+
* already up to date" note both need. */
|
|
43
|
+
export function phaseFromPlanResult(result: UpdatePlanView | { error: string }): 'ready' | 'dirty' | 'offline' {
|
|
44
|
+
if ('error' in result) return 'offline';
|
|
45
|
+
return result.dirtyFiles.length > 0 ? 'dirty' : 'ready';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** `true` only for `buildUpdatePlan`'s own "Already on the latest version (…)." message — never a
|
|
49
|
+
* real failure, so `UpdatePanel`'s `offline` phase shows a plain up-to-date note instead of the
|
|
50
|
+
* "Couldn't prepare the update" error copy for this one case. */
|
|
51
|
+
export function isAlreadyUpToDateError(result: UpdatePlanView | { error: string }): boolean {
|
|
52
|
+
return 'error' in result && result.error.startsWith('Already on the latest version');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** The one function `UpdatePanel.tsx` calls to decide which of the mockup's 10 states to render.
|
|
56
|
+
* `status` (from the endpoint's own `/update/status`, authoritative once an update has started)
|
|
57
|
+
* always wins over `planResult` — a plan fetched before an update began is stale the moment one
|
|
58
|
+
* starts, and the mockup itself never shows plan content and progress content at once. While
|
|
59
|
+
* `status.phase` is `'idle'` and no plan has resolved yet (`planResult === undefined`), the panel
|
|
60
|
+
* is still in the mockup's own `'checking'` state. */
|
|
61
|
+
export function resolvePanelPhase(status: UpdateStatusView, planResult: UpdatePlanView | { error: string } | undefined): UpdatePhase {
|
|
62
|
+
if (status.phase !== 'idle') return status.phase;
|
|
63
|
+
if (planResult === undefined) return 'checking';
|
|
64
|
+
return phaseFromPlanResult(planResult);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** The panel's `"Released N days ago."` line — floors to whole days, never "23 hours ago" (the
|
|
68
|
+
* mockup's own example, "Released 2 days ago.", is always a whole number of days). */
|
|
69
|
+
export function daysAgoLabel(releasedAt: string, nowMs: number): string {
|
|
70
|
+
const days = Math.floor((nowMs - Date.parse(releasedAt)) / (24 * 60 * 60 * 1000));
|
|
71
|
+
if (days <= 0) return 'Released today.';
|
|
72
|
+
if (days === 1) return 'Released 1 day ago.';
|
|
73
|
+
return `Released ${days} days ago.`;
|
|
74
|
+
}
|