@crossworks/client-types 0.232.244 → 0.232.246
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 +1 -1
- package/src/app-nav.ts +122 -0
- package/src/dto/rows.ts +17 -0
- package/src/dto/views.ts +4 -0
- package/src/index.ts +13 -0
- package/src/types/sanity.ts +1 -1
package/package.json
CHANGED
package/src/app-nav.ts
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* App navigation: how the owner organises their mini apps in the sidebar.
|
|
3
|
+
*
|
|
4
|
+
* Two halves with different owners:
|
|
5
|
+
*
|
|
6
|
+
* - The LAYOUT (`AppNav`: folders, nesting, order) is BRAIN-level. It is one
|
|
7
|
+
* shared record on the anchor row (see BRAIN_PREFERENCE_KEYS), so every admin
|
|
8
|
+
* and every client (web, desktop, phone) renders the same tree.
|
|
9
|
+
* - PINS and OPEN COUNTS are per-login: what one person keeps at hand and what
|
|
10
|
+
* they actually use.
|
|
11
|
+
*
|
|
12
|
+
* App icon and colour live on the app itself (`AppRow.icon` / `AppRow.color`),
|
|
13
|
+
* not here, so every surface that lists an app shows the same face.
|
|
14
|
+
*
|
|
15
|
+
* Pure (no React, no runtime deps) so the server, the web client and any other
|
|
16
|
+
* client can share the types and the limits.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Named tints for app and folder tiles. We store the KEY, never a colour: each
|
|
21
|
+
* theme defines its own `--app-tint-<key>` / `--app-tint-<key>-ink` pair, so a
|
|
22
|
+
* tile stays legible on every generated theme and in both modes.
|
|
23
|
+
*/
|
|
24
|
+
export const APP_TINTS = [
|
|
25
|
+
'slate',
|
|
26
|
+
'red',
|
|
27
|
+
'orange',
|
|
28
|
+
'amber',
|
|
29
|
+
'lime',
|
|
30
|
+
'green',
|
|
31
|
+
'teal',
|
|
32
|
+
'sky',
|
|
33
|
+
'blue',
|
|
34
|
+
'indigo',
|
|
35
|
+
'violet',
|
|
36
|
+
'pink',
|
|
37
|
+
] as const;
|
|
38
|
+
export type AppTint = (typeof APP_TINTS)[number];
|
|
39
|
+
|
|
40
|
+
export function isAppTint(v: unknown): v is AppTint {
|
|
41
|
+
return typeof v === 'string' && (APP_TINTS as readonly string[]).includes(v);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* An app or folder icon is either an emoji (the historical form, up to 16
|
|
46
|
+
* UTF-16 units so flags and ZWJ sequences fit) or `lucide:<name>` naming an
|
|
47
|
+
* icon from the client's curated set. The server checks the SHAPE only; a
|
|
48
|
+
* client that doesn't know a lucide name falls back to its default tile.
|
|
49
|
+
*/
|
|
50
|
+
export const LUCIDE_ICON_PREFIX = 'lucide:';
|
|
51
|
+
export const APP_ICON_EMOJI_MAX = 16;
|
|
52
|
+
export const APP_ICON_MAX = 48;
|
|
53
|
+
|
|
54
|
+
/** Folders nest at most this deep: folder › subfolder › sub-subfolder. */
|
|
55
|
+
export const APP_NAV_MAX_DEPTH = 3;
|
|
56
|
+
/** Across the whole tree. Generous; it bounds the stored jsonb, not taste. */
|
|
57
|
+
export const APP_NAV_MAX_FOLDERS = 200;
|
|
58
|
+
export const APP_NAV_FOLDER_NAME_MAX = 60;
|
|
59
|
+
/** Personal pins shown above the tree. */
|
|
60
|
+
export const APP_PINS_MAX = 12;
|
|
61
|
+
/** Personal sidebar favourites (nav hrefs). */
|
|
62
|
+
export const NAV_FAVORITES_MAX = 40;
|
|
63
|
+
export const NAV_FAVORITE_HREF_MAX = 200;
|
|
64
|
+
/** Per-login open counters kept; the least recently opened fall off. */
|
|
65
|
+
export const APP_OPENS_MAX = 300;
|
|
66
|
+
|
|
67
|
+
export type AppNavApp = { kind: 'app'; id: string };
|
|
68
|
+
|
|
69
|
+
export type AppNavFolder = {
|
|
70
|
+
kind: 'folder';
|
|
71
|
+
/** Client-generated UUID, stable across renames and moves. */
|
|
72
|
+
id: string;
|
|
73
|
+
name: string;
|
|
74
|
+
icon?: string;
|
|
75
|
+
color?: AppTint;
|
|
76
|
+
children: AppNavEntry[];
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export type AppNavEntry = AppNavApp | AppNavFolder;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* The shared layout. `entries` is the root level in display order; each folder
|
|
83
|
+
* carries its own ordered children, so order and nesting are one structure and
|
|
84
|
+
* a dangling parent or a cycle can't be expressed.
|
|
85
|
+
*
|
|
86
|
+
* An app that appears nowhere in the tree is UNSORTED: clients list those after
|
|
87
|
+
* the tree (newest first), which is where a freshly created app lands.
|
|
88
|
+
*
|
|
89
|
+
* `rev` increments on every save. A save names the rev it was based on and is
|
|
90
|
+
* refused (409) when another client saved first, so two devices can't silently
|
|
91
|
+
* overwrite each other's reorganisation.
|
|
92
|
+
*/
|
|
93
|
+
export type AppNav = { rev: number; entries: AppNavEntry[] };
|
|
94
|
+
|
|
95
|
+
export const EMPTY_APP_NAV: AppNav = { rev: 0, entries: [] };
|
|
96
|
+
|
|
97
|
+
/** One login's use of one app: open count and last-opened ISO instant. */
|
|
98
|
+
export type AppOpenStat = { n: number; at: string };
|
|
99
|
+
|
|
100
|
+
/** Slim app row for navigation surfaces: everything the tree needs to render
|
|
101
|
+
* and search, nothing it doesn't. */
|
|
102
|
+
export type AppNavItem = {
|
|
103
|
+
id: string;
|
|
104
|
+
title: string;
|
|
105
|
+
icon: string | null;
|
|
106
|
+
color: AppTint | null;
|
|
107
|
+
tags: string[];
|
|
108
|
+
description: string | null;
|
|
109
|
+
/** Previewable: a green published or draft build (the frame-ticket test).
|
|
110
|
+
* Differs from AppRow.hasBuild, which is published-only. */
|
|
111
|
+
hasBuild: boolean;
|
|
112
|
+
updatedAt: string;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/** GET /api/app-nav — the whole sidebar in one round-trip. `nav` is already
|
|
116
|
+
* pruned to apps that still exist, and `pins` likewise. */
|
|
117
|
+
export type AppNavResponse = {
|
|
118
|
+
nav: AppNav;
|
|
119
|
+
pins: string[];
|
|
120
|
+
opens: Record<string, AppOpenStat>;
|
|
121
|
+
apps: AppNavItem[];
|
|
122
|
+
};
|
package/src/dto/rows.ts
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
* public surface is byte-identical — only the file a symbol lives in moved.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
import type { AppNav, AppOpenStat, AppTint } from '../app-nav';
|
|
14
|
+
|
|
13
15
|
// ── Row/DTO shapes moved from the server packages (jackdaw split P0) ─────────
|
|
14
16
|
// Sources: @mantle/content, @mantle/email, @mantle/microsoft, @mantle/runtime/agent
|
|
15
17
|
// re-export these names, so server code keeps its original import paths.
|
|
@@ -148,7 +150,10 @@ export type PageListRow = PageRow & {
|
|
|
148
150
|
export type AppRow = {
|
|
149
151
|
id: string;
|
|
150
152
|
title: string;
|
|
153
|
+
/** Emoji, or `lucide:<name>` from the client's curated set (app-nav.ts). */
|
|
151
154
|
icon: string | null;
|
|
155
|
+
/** Tile tint key (APP_TINTS); null = the client's neutral default. */
|
|
156
|
+
color: AppTint | null;
|
|
152
157
|
tags: string[];
|
|
153
158
|
summary: string | null;
|
|
154
159
|
description: string | null;
|
|
@@ -450,6 +455,18 @@ export type ProfilePreferences = {
|
|
|
450
455
|
* this pref only chooses which tag groupings get pinned. Unset/empty ⇒ no
|
|
451
456
|
* curated sections. Read via projectTeamHubTags, never raw. */
|
|
452
457
|
teamHubTags?: string[];
|
|
458
|
+
/** BRAIN-level sidebar layout for mini apps: folders (nested up to
|
|
459
|
+
* APP_NAV_MAX_DEPTH), their order, and where each app sits. Written ONLY
|
|
460
|
+
* through saveAppNav (rev-checked), read via projectAppNav, never raw. */
|
|
461
|
+
appNav?: AppNav;
|
|
462
|
+
/** Per-login: app ids pinned above the tree, in order. */
|
|
463
|
+
appPins?: string[];
|
|
464
|
+
/** Per-login: sidebar favourite hrefs, in order. Moved server-side from the
|
|
465
|
+
* web client's localStorage so they follow the person across devices. */
|
|
466
|
+
navFavorites?: string[];
|
|
467
|
+
/** Per-login: open count + last-opened instant per app id, feeding the
|
|
468
|
+
* "Most used" and "Recent" filters. Written by recordAppOpen. */
|
|
469
|
+
appOpens?: Record<string, AppOpenStat>;
|
|
453
470
|
};
|
|
454
471
|
|
|
455
472
|
export type BackupConfig = {
|
package/src/dto/views.ts
CHANGED
|
@@ -595,6 +595,10 @@ export type SystemHealth = {
|
|
|
595
595
|
topTables: { name: string; bytes: number }[];
|
|
596
596
|
};
|
|
597
597
|
storage: {
|
|
598
|
+
/** The object store answered (any S3 backend). */
|
|
599
|
+
objectStoreUp: boolean | null;
|
|
600
|
+
/** @deprecated Same value as `objectStoreUp`; kept for clients built
|
|
601
|
+
* before the object store went backend-neutral. */
|
|
598
602
|
minioUp: boolean | null;
|
|
599
603
|
attachmentBytes: number | null;
|
|
600
604
|
filesDisk: DiskInfo | null;
|
package/src/index.ts
CHANGED
|
@@ -32,3 +32,16 @@ export * from './dto/turns';
|
|
|
32
32
|
export * from './dto/rows';
|
|
33
33
|
export * from './dto/views';
|
|
34
34
|
export * from './dto/recall';
|
|
35
|
+
|
|
36
|
+
// Types only at the root; the runtime constants (APP_TINTS, limits) are the
|
|
37
|
+
// `@mantle/client-types/app-nav` subpath.
|
|
38
|
+
export type {
|
|
39
|
+
AppNav,
|
|
40
|
+
AppNavApp,
|
|
41
|
+
AppNavEntry,
|
|
42
|
+
AppNavFolder,
|
|
43
|
+
AppNavItem,
|
|
44
|
+
AppNavResponse,
|
|
45
|
+
AppOpenStat,
|
|
46
|
+
AppTint,
|
|
47
|
+
} from './app-nav';
|
package/src/types/sanity.ts
CHANGED
|
@@ -30,7 +30,7 @@ export type SanityStatus =
|
|
|
30
30
|
export type SanityCategory = 'Storage' | 'Updater' | 'Environment' | 'Embedding' | 'Database';
|
|
31
31
|
|
|
32
32
|
/** How to fix a non-passing check. `command` is a copy-pasteable one-liner when
|
|
33
|
-
* one exists (e.g. the
|
|
33
|
+
* one exists (e.g. the command that creates the bucket). */
|
|
34
34
|
export type SanityFix = { summary: string; command?: string };
|
|
35
35
|
|
|
36
36
|
export type SanityCheck = {
|