@sparkelf/dsh-knowledge-base 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/SKILL.md +147 -0
- package/cordis.patch.yml +5 -0
- package/i18n/zh.json +10 -0
- package/lib/client.js +15976 -0
- package/lib/client.js.map +1 -0
- package/lib/index.js +5724 -0
- package/lib/types/api.d.ts +574 -0
- package/lib/types/client/KnowledgeAudit.d.ts +39 -0
- package/lib/types/client/KnowledgeContextMenu.d.ts +96 -0
- package/lib/types/client/KnowledgeCreateDialog.d.ts +134 -0
- package/lib/types/client/KnowledgeFileTree.d.ts +88 -0
- package/lib/types/client/KnowledgeHome.d.ts +79 -0
- package/lib/types/client/KnowledgeIndexing.d.ts +60 -0
- package/lib/types/client/KnowledgeListing.d.ts +160 -0
- package/lib/types/client/KnowledgeLoading.d.ts +41 -0
- package/lib/types/client/KnowledgeMenuIcon.d.ts +27 -0
- package/lib/types/client/KnowledgePanel.d.ts +58 -0
- package/lib/types/client/KnowledgePermissionOverview.d.ts +99 -0
- package/lib/types/client/KnowledgePermissions.d.ts +47 -0
- package/lib/types/client/KnowledgeReferencePicker.d.ts +65 -0
- package/lib/types/client/KnowledgeSearch.d.ts +83 -0
- package/lib/types/client/KnowledgeSectionHeader.d.ts +71 -0
- package/lib/types/client/KnowledgeSelectionBar.d.ts +45 -0
- package/lib/types/client/KnowledgeSettings.d.ts +96 -0
- package/lib/types/client/KnowledgeSettingsSection.d.ts +21 -0
- package/lib/types/client/KnowledgeShareDialog.d.ts +70 -0
- package/lib/types/client/KnowledgeTemplates.d.ts +43 -0
- package/lib/types/client/KnowledgeTrash.d.ts +62 -0
- package/lib/types/client/MenuGlyphs.d.ts +37 -0
- package/lib/types/client/departmentFolders.d.ts +57 -0
- package/lib/types/client/deployTarget.d.ts +34 -0
- package/lib/types/client/index.d.ts +27 -0
- package/lib/types/client/knowledgeMenuCopy.d.ts +23 -0
- package/lib/types/client/locales.d.ts +438 -0
- package/lib/types/client/openInSidebar.d.ts +62 -0
- package/lib/types/client/ownerLabel.d.ts +39 -0
- package/lib/types/client/permissionRows.d.ts +94 -0
- package/lib/types/client/roleSummary.d.ts +47 -0
- package/lib/types/client/saveAudit.d.ts +87 -0
- package/lib/types/client/useFavorites.d.ts +49 -0
- package/lib/types/client/usePinnedPaths.d.ts +39 -0
- package/lib/types/client/useTreeState.d.ts +46 -0
- package/lib/types/client/useViewMode.d.ts +39 -0
- package/lib/types/deploy.d.ts +209 -0
- package/lib/types/extract.d.ts +144 -0
- package/lib/types/index.d.ts +846 -0
- package/lib/types/permissions.d.ts +237 -0
- package/lib/types/protocol.d.ts +229 -0
- package/lib/types/remote.d.ts +105 -0
- package/lib/types/trash.d.ts +142 -0
- package/lib/types/viewMetadata.d.ts +20 -0
- package/lib/types/views.d.ts +923 -0
- package/package.json +109 -4
- package/skills/kb-organize/SKILL.md +365 -0
- package/skills/kb-organize/i18n/zh.json +10 -0
- package/README.md +0 -3
|
@@ -0,0 +1,574 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The same-origin API surface shared by this package's two halves.
|
|
3
|
+
*
|
|
4
|
+
* The Host registers one prefix and dispatches on the trailing method name; the
|
|
5
|
+
* browser calls the same strings. Keeping them in one module is what stops the
|
|
6
|
+
* two halves drifting apart, which is exactly the failure this file was written
|
|
7
|
+
* to fix: the panel once called `/knowledge-base/config` while the Host served
|
|
8
|
+
* `/knowledge-base/api/config`.
|
|
9
|
+
*
|
|
10
|
+
* This module must stay dependency-free so both bundles can import it: the
|
|
11
|
+
* Client bundle rejects Node builtins and non-platform packages.
|
|
12
|
+
*
|
|
13
|
+
* @module @sparkelf/dsh-knowledge-base/api
|
|
14
|
+
*/
|
|
15
|
+
/** Prefix the Host registers and the browser calls. */
|
|
16
|
+
export declare const KB_API_PREFIX = "/knowledge-base/api";
|
|
17
|
+
/** Method names the Host dispatches on. */
|
|
18
|
+
export declare const KB_API: {
|
|
19
|
+
/** Resolved layout plus whether the DataOps backend is wired. */
|
|
20
|
+
readonly config: "config";
|
|
21
|
+
/**
|
|
22
|
+
* Persist the operator's storage choices.
|
|
23
|
+
*
|
|
24
|
+
* Separate from {@link KB_API.config} because it is the only route here that writes
|
|
25
|
+
* deployment configuration: a read must never be able to change what a write controls.
|
|
26
|
+
*/
|
|
27
|
+
readonly configSet: "config.set";
|
|
28
|
+
/** Aggregated view and index status. */
|
|
29
|
+
readonly status: "status";
|
|
30
|
+
/** Authorized paths for the calling user. */
|
|
31
|
+
readonly grants: "grants";
|
|
32
|
+
/** Grant one principal access to one path. */
|
|
33
|
+
readonly grant: "grant";
|
|
34
|
+
/** Revoke one previously granted path. */
|
|
35
|
+
readonly revoke: "revoke";
|
|
36
|
+
/** List the principals that can be granted, so the surface can offer a picker. */
|
|
37
|
+
readonly principals: "principals";
|
|
38
|
+
readonly roles: "roles";
|
|
39
|
+
readonly trash: "trash";
|
|
40
|
+
readonly trashRemove: "trash.remove";
|
|
41
|
+
readonly trashRestore: "trash.restore";
|
|
42
|
+
/** Search the mounted tree by file name and text. */
|
|
43
|
+
readonly search: "search";
|
|
44
|
+
/** List one directory level, with each entry's modification time. */
|
|
45
|
+
readonly list: "list";
|
|
46
|
+
/** Read one file for the preview, without needing a conversation session. */
|
|
47
|
+
readonly read: "read";
|
|
48
|
+
/** Rebuild the caller's visible tree from what DataOps resolves for them. */
|
|
49
|
+
readonly viewsSync: "views.sync";
|
|
50
|
+
/** Rescan the mounted tree and report its shape. */
|
|
51
|
+
readonly index: "index";
|
|
52
|
+
/**
|
|
53
|
+
* Report the mounted tree's per-directory shape.
|
|
54
|
+
*
|
|
55
|
+
* Separate from {@link KB_API.index}, which recounts and answers with a single
|
|
56
|
+
* total: this one answers with the rows the indexing table renders, so opening
|
|
57
|
+
* the page does not have to trigger a scan to have something to show.
|
|
58
|
+
*/
|
|
59
|
+
readonly indexDirs: "index.dirs";
|
|
60
|
+
/**
|
|
61
|
+
* Start a document or folder in the authoritative tree.
|
|
62
|
+
*
|
|
63
|
+
* Not a per-user private space: the destination has no caller component, so a
|
|
64
|
+
* document created here is shared with everyone DataOps resolves as a reader of
|
|
65
|
+
* that path. That is the knowledge base's own semantic, and it is why the write
|
|
66
|
+
* needs write access rather than merely read.
|
|
67
|
+
*/
|
|
68
|
+
readonly create: "create";
|
|
69
|
+
/**
|
|
70
|
+
* Replace one existing document's bytes.
|
|
71
|
+
*
|
|
72
|
+
* Kept separate from `create` because the two differ in what they must not do:
|
|
73
|
+
* a create refuses to overwrite, while an edit must write IN PLACE. Writing in
|
|
74
|
+
* place is the requirement, not an implementation detail -- the caller's view
|
|
75
|
+
* links this document to the authoritative copy by hardlink, and a
|
|
76
|
+
* write-temp-then-rename save (which is how the host's own editor saves) replaces
|
|
77
|
+
* the inode and silently leaves the view showing the old bytes.
|
|
78
|
+
*/
|
|
79
|
+
readonly edit: "edit";
|
|
80
|
+
/**
|
|
81
|
+
* Record an edit that happened outside this plugin's write path.
|
|
82
|
+
*
|
|
83
|
+
* The host's file editor saves through its own route, so the knowledge base
|
|
84
|
+
* cannot intercept it without owning that editor. This route is the side channel:
|
|
85
|
+
* the page reports the save it observed, and the audit trail stays complete
|
|
86
|
+
* without the host's write path knowing the knowledge base exists.
|
|
87
|
+
*/
|
|
88
|
+
readonly auditAppend: "audit.append";
|
|
89
|
+
/** Put one file's bytes into the authoritative tree under the same rules. */
|
|
90
|
+
readonly upload: "upload";
|
|
91
|
+
/**
|
|
92
|
+
* List the templates a reader can start from.
|
|
93
|
+
*
|
|
94
|
+
* A template is a DataOps wiki page whose category is `report_template`, so the
|
|
95
|
+
* Host relays `GET /api/resources/wiki/pages/templates` rather than keeping a
|
|
96
|
+
* second copy to keep in step.
|
|
97
|
+
*/
|
|
98
|
+
readonly templates: "templates";
|
|
99
|
+
/**
|
|
100
|
+
* Add or replace one template: a document file plus its metadata.
|
|
101
|
+
*
|
|
102
|
+
* A template is exactly a document plus a small record describing it, so this
|
|
103
|
+
* route takes the file's text and the metadata in one body rather than modelling
|
|
104
|
+
* a second kind of object. The document is written through the same create/upload
|
|
105
|
+
* path a reader's own file uses, under a template directory the knowledge base
|
|
106
|
+
* owns, and the metadata goes beside it.
|
|
107
|
+
*/
|
|
108
|
+
readonly templateSave: "template.save";
|
|
109
|
+
/** Remove one template: its document and its metadata record. */
|
|
110
|
+
readonly templateRemove: "template.remove";
|
|
111
|
+
/** Read the caller's pinned paths. */
|
|
112
|
+
readonly favoritesGet: "favorites.get";
|
|
113
|
+
readonly favoritesSet: "favorites.set";
|
|
114
|
+
readonly pinsGet: "pins.get";
|
|
115
|
+
/** Replace the caller's pinned paths. */
|
|
116
|
+
readonly pinsSet: "pins.set";
|
|
117
|
+
/**
|
|
118
|
+
* Read this knowledge base's review settings.
|
|
119
|
+
*
|
|
120
|
+
* Stored beside the pins and the view mode, in the caller's view directory. The answer
|
|
121
|
+
* defaults to review OFF, which is what a deployment that never opened the settings
|
|
122
|
+
* page must do.
|
|
123
|
+
*/
|
|
124
|
+
readonly settingsGet: "settings.get";
|
|
125
|
+
/**
|
|
126
|
+
* Replace this knowledge base's review settings.
|
|
127
|
+
*
|
|
128
|
+
* Gated on write access rather than mere read: turning review on or off decides whether
|
|
129
|
+
* other people's contributions take effect immediately, which is an operator decision.
|
|
130
|
+
*/
|
|
131
|
+
readonly settingsSet: "settings.set";
|
|
132
|
+
/**
|
|
133
|
+
* Read the audit trail for this knowledge base, newest first.
|
|
134
|
+
*
|
|
135
|
+
* Append-only on the Host side; this route only reads.
|
|
136
|
+
*/
|
|
137
|
+
readonly auditList: "audit.list";
|
|
138
|
+
/**
|
|
139
|
+
* Rename one entry in place, keeping it in its own directory.
|
|
140
|
+
*
|
|
141
|
+
* Separate from `move` on purpose: that route deliberately concatenates the entry's
|
|
142
|
+
* CURRENT name onto the destination, so it cannot rename. Renaming is its own decision
|
|
143
|
+
* and gets its own check at the resulting path.
|
|
144
|
+
*/
|
|
145
|
+
readonly rename: "rename";
|
|
146
|
+
/**
|
|
147
|
+
* Read one file as bytes for a save-to-disk, as opposed to `read` for on-screen text.
|
|
148
|
+
*
|
|
149
|
+
* Answers base64 so a binary file survives the JSON round trip; a markdown file uses
|
|
150
|
+
* the same route, because one download path is simpler than two.
|
|
151
|
+
*/
|
|
152
|
+
readonly download: "download";
|
|
153
|
+
/**
|
|
154
|
+
* List the submissions waiting for review.
|
|
155
|
+
*
|
|
156
|
+
* Only meaningful when review is on, but it always answers: an empty queue is a
|
|
157
|
+
* valid state and the page shows it rather than hiding the section.
|
|
158
|
+
*/
|
|
159
|
+
readonly pendingList: "pending.list";
|
|
160
|
+
/**
|
|
161
|
+
* Accept one submission, writing its bytes into the authoritative tree.
|
|
162
|
+
*
|
|
163
|
+
* Requires write access, like every other operation that changes shared content.
|
|
164
|
+
*/
|
|
165
|
+
readonly pendingApprove: "pending.approve";
|
|
166
|
+
/**
|
|
167
|
+
* Refuse one submission and discard its bytes.
|
|
168
|
+
*
|
|
169
|
+
* Requires write access for the same reason: refusing someone else's contribution
|
|
170
|
+
* is a decision about shared content.
|
|
171
|
+
*/
|
|
172
|
+
readonly pendingReject: "pending.reject";
|
|
173
|
+
/**
|
|
174
|
+
* Move or rename one entry inside the caller's tree.
|
|
175
|
+
*
|
|
176
|
+
* A rename rather than a copy, so the inode survives and every view's hardlink
|
|
177
|
+
* to it stays meaningful; the Host resynchronizes the caller's view afterwards,
|
|
178
|
+
* because a moved file's old path is a dead link until it does.
|
|
179
|
+
*/
|
|
180
|
+
readonly copy: "copy";
|
|
181
|
+
readonly move: "move";
|
|
182
|
+
/** Read the caller's list/grid preference. */
|
|
183
|
+
readonly viewModeGet: "viewMode.get";
|
|
184
|
+
/** Replace the caller's list/grid preference. */
|
|
185
|
+
readonly viewModeSet: "viewMode.set";
|
|
186
|
+
/**
|
|
187
|
+
* Read which folders the caller had open in the explorer.
|
|
188
|
+
*
|
|
189
|
+
* Beside the layout preference for the same reason: it describes how this reader
|
|
190
|
+
* looks at the tree rather than what is in it, so it belongs to the caller's view
|
|
191
|
+
* instead of one browser's storage.
|
|
192
|
+
*/
|
|
193
|
+
readonly treeStateGet: "treeState.get";
|
|
194
|
+
/** Replace the set of expanded folders. */
|
|
195
|
+
readonly treeStateSet: "treeState.set";
|
|
196
|
+
/** The ordered deployment steps and their recent runs. */
|
|
197
|
+
readonly deploySteps: "deploy.steps";
|
|
198
|
+
/** SSH hosts available as deployment targets. */
|
|
199
|
+
readonly deployHosts: "deploy.hosts";
|
|
200
|
+
/** Run one deployment step against one host. */
|
|
201
|
+
readonly deployRun: "deploy.run";
|
|
202
|
+
};
|
|
203
|
+
/** One method name. */
|
|
204
|
+
export type KbApiMethod = (typeof KB_API)[keyof typeof KB_API];
|
|
205
|
+
/** Absolute URL for one API method. */
|
|
206
|
+
export declare function kbApiPath(method: KbApiMethod): string;
|
|
207
|
+
/**
|
|
208
|
+
* Read a knowledge-base response as JSON without trusting it to BE JSON.
|
|
209
|
+
*
|
|
210
|
+
* Every route in this plugin answers JSON, but a response is not always this plugin's:
|
|
211
|
+
* a gateway, a proxy, an auth redirect, or a stopped DSH can all return HTML or plain
|
|
212
|
+
* text with a 2xx status. Calling `response.json()` on that throws a parser message like
|
|
213
|
+
* `Unexpected token 'D', "DataOps au"... is not valid JSON`, which then reached the page
|
|
214
|
+
* verbatim -- an internal parser complaint shown to a reader as if it were the document.
|
|
215
|
+
*
|
|
216
|
+
* This reads the body once as text and decides from the CONTENT whether it parsed, so a
|
|
217
|
+
* non-JSON answer becomes a sentence naming the status instead of a parser exception. The
|
|
218
|
+
* status is still surfaced, because "the server said no" and "the body was not JSON" are
|
|
219
|
+
* different problems an operator needs to tell apart.
|
|
220
|
+
* @param response - the fetch response.
|
|
221
|
+
* @returns The parsed body, or an object carrying a readable `error`.
|
|
222
|
+
*/
|
|
223
|
+
export declare function readKnowledgeJson<T extends Record<string, unknown>>(response: Response): Promise<T & {
|
|
224
|
+
error?: string;
|
|
225
|
+
}>;
|
|
226
|
+
/** Resolved layout as the panel renders it. */
|
|
227
|
+
export interface KnowledgeConfigView {
|
|
228
|
+
/** Human-facing identifier of the storage host, empty when unconfigured. */
|
|
229
|
+
host: string;
|
|
230
|
+
/** Absolute path of the authoritative tree on the storage host. */
|
|
231
|
+
actualRoot: string;
|
|
232
|
+
/** Absolute path of the caller's view tree on the storage host. */
|
|
233
|
+
viewRoot: string;
|
|
234
|
+
/** Path where the view tree is mounted inside the container. */
|
|
235
|
+
mountPoint: string;
|
|
236
|
+
/** NFS export host, when the deployment uses the NFS transport. */
|
|
237
|
+
nfsServer?: string;
|
|
238
|
+
/** Whether a DataOps knowledge API base URL is configured. */
|
|
239
|
+
backendConfigured: boolean;
|
|
240
|
+
/** Why the backend probe failed, when it did. */
|
|
241
|
+
backendError?: {
|
|
242
|
+
message: string;
|
|
243
|
+
code?: string;
|
|
244
|
+
};
|
|
245
|
+
/** How a remote deployment reaches its share; absent means `nfs`. */
|
|
246
|
+
storageProtocol?: 'nfs' | 'sshfs';
|
|
247
|
+
/** SSHFS transport, present so the panel can show and edit what it will mount. */
|
|
248
|
+
ssh?: KnowledgeSshView;
|
|
249
|
+
}
|
|
250
|
+
/** One transport field the panel may persist. */
|
|
251
|
+
export interface KnowledgeConfigWrite {
|
|
252
|
+
/** Storage shape to store. */
|
|
253
|
+
storageMode?: 'local' | 'remote';
|
|
254
|
+
/** Transport for a remote deployment. */
|
|
255
|
+
storageProtocol?: 'nfs' | 'sshfs';
|
|
256
|
+
/** NFS export host. */
|
|
257
|
+
nfsServer?: string;
|
|
258
|
+
/** SSHFS transport fields; the key is named by reference only. */
|
|
259
|
+
sshHost?: string;
|
|
260
|
+
sshUser?: string;
|
|
261
|
+
sshPort?: number;
|
|
262
|
+
sshRemotePath?: string;
|
|
263
|
+
sshMountOptions?: string;
|
|
264
|
+
sshKeyRef?: string;
|
|
265
|
+
}
|
|
266
|
+
/** What a config write actually stored, and what it could not. */
|
|
267
|
+
export interface KnowledgeConfigWriteResult {
|
|
268
|
+
/** Fields written to the settings file. */
|
|
269
|
+
saved: string[];
|
|
270
|
+
/**
|
|
271
|
+
* True when the running deployment differs from what was just saved, so a restart is
|
|
272
|
+
* required before the change takes effect. The file is the record; the process read its
|
|
273
|
+
* configuration at startup.
|
|
274
|
+
*/
|
|
275
|
+
restartRequired: boolean;
|
|
276
|
+
/** The config as it will read back after a restart. */
|
|
277
|
+
config: KnowledgeConfigView;
|
|
278
|
+
/** Fields refused, with the reason. */
|
|
279
|
+
refused?: {
|
|
280
|
+
field: string;
|
|
281
|
+
reason: string;
|
|
282
|
+
}[];
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* The SSHFS transport as the panel may see it.
|
|
286
|
+
*
|
|
287
|
+
* Every field here is safe to render: a host, a user, a port, a path, mount options, and
|
|
288
|
+
* a credential REFERENCE. The private key itself is never part of this shape -- there is
|
|
289
|
+
* no field it could travel in. `keyConfigured` is the resolved answer to "will the mount
|
|
290
|
+
* step find a key", which is the only thing the panel needs to know about it.
|
|
291
|
+
*/
|
|
292
|
+
export interface KnowledgeSshView {
|
|
293
|
+
/** Remote host, address or hostname. */
|
|
294
|
+
host: string;
|
|
295
|
+
/** Login user on that host. */
|
|
296
|
+
user: string;
|
|
297
|
+
/** TCP port the SSH daemon listens on. */
|
|
298
|
+
port: number;
|
|
299
|
+
/** Absolute path of the shared directory on the remote host. */
|
|
300
|
+
remotePath: string;
|
|
301
|
+
/** Extra `-o` options, as the operator typed them. */
|
|
302
|
+
mountOptions: string;
|
|
303
|
+
/** Name of the credential holding the private key. A reference, never the key. */
|
|
304
|
+
keyRef: string;
|
|
305
|
+
/** Whether that credential currently resolves to a usable key. */
|
|
306
|
+
keyConfigured: boolean;
|
|
307
|
+
}
|
|
308
|
+
/** Aggregated view and index status as the panel renders it. */
|
|
309
|
+
export interface KnowledgeStatusView {
|
|
310
|
+
/**
|
|
311
|
+
* Which storage shape this deployment runs.
|
|
312
|
+
*
|
|
313
|
+
* `local` stores documents in the workspace itself; `remote` keeps the synchronized
|
|
314
|
+
* NFS shape. The settings page keys its whole storage section off this, so a reader
|
|
315
|
+
* never sees mount controls for a workspace that has no mount.
|
|
316
|
+
*/
|
|
317
|
+
storageMode?: 'local' | 'remote';
|
|
318
|
+
/**
|
|
319
|
+
* How a remote deployment reaches its share.
|
|
320
|
+
*
|
|
321
|
+
* Reported for both modes so the panel can show the configured transport even while the
|
|
322
|
+
* deployment runs locally: a reader switching to remote needs to see what it will use
|
|
323
|
+
* before they commit to it.
|
|
324
|
+
*/
|
|
325
|
+
storageProtocol?: 'nfs' | 'sshfs';
|
|
326
|
+
/**
|
|
327
|
+
* Who this page is acting as, as DataOps resolved them.
|
|
328
|
+
*
|
|
329
|
+
* Absent when the backend is unconfigured or did not answer. The page uses it to
|
|
330
|
+
* name the actor on editor saves, so the audit trail records a person rather than
|
|
331
|
+
* an anonymous edit.
|
|
332
|
+
*
|
|
333
|
+
* The organization path is optional because the backend may not report it: an older
|
|
334
|
+
* DataOps answers only `code`/`name`, and the tree then labels the department bucket
|
|
335
|
+
* with that single name exactly as it did before hierarchy existed. Code that
|
|
336
|
+
* assumed the path was present would break against such a backend.
|
|
337
|
+
*/
|
|
338
|
+
caller?: {
|
|
339
|
+
userId: string;
|
|
340
|
+
label: string;
|
|
341
|
+
departmentCode?: string;
|
|
342
|
+
departmentName?: string;
|
|
343
|
+
departmentPathCodes?: string[];
|
|
344
|
+
departmentPathNames?: string[];
|
|
345
|
+
};
|
|
346
|
+
/** Visible file count, or null when the backend is not configured. */
|
|
347
|
+
visibleFiles: number | null;
|
|
348
|
+
/** ISO-8601 time of the last successful synchronization. */
|
|
349
|
+
lastSyncAt: string | null;
|
|
350
|
+
/** In-flight index state. */
|
|
351
|
+
indexing: {
|
|
352
|
+
running: boolean;
|
|
353
|
+
jobId?: string;
|
|
354
|
+
progress?: number;
|
|
355
|
+
};
|
|
356
|
+
/**
|
|
357
|
+
* Which of the two empty states applies when there is no file count.
|
|
358
|
+
*
|
|
359
|
+
* `null` for a count is compatible with a mount that is absent and with a pointer
|
|
360
|
+
* this plugin has not built yet, and those need different sentences: the first
|
|
361
|
+
* sends the reader to the deployment, the second resolves itself. The Host
|
|
362
|
+
* reports which one it is.
|
|
363
|
+
*
|
|
364
|
+
* Optional because a response from an older Host does not carry it; a reader that
|
|
365
|
+
* finds it absent falls back to the mount-not-present wording, which is the
|
|
366
|
+
* message that was correct before the two were told apart.
|
|
367
|
+
*/
|
|
368
|
+
mountState?: 'mounted' | 'pointer-missing' | 'absent';
|
|
369
|
+
/**
|
|
370
|
+
* Whether the Host verified that this caller may manage grants.
|
|
371
|
+
*
|
|
372
|
+
* Decided on the Host by asking DataOps, and deliberately not derived here: a
|
|
373
|
+
* client-side decision would duplicate the policy in a process the user controls,
|
|
374
|
+
* where it governs rendering rather than access. Absent or false both mean "do not
|
|
375
|
+
* offer the surface", so a response from an older Host hides it rather than
|
|
376
|
+
* showing a menu whose writes the backend would reject.
|
|
377
|
+
*/
|
|
378
|
+
canManageGrants?: boolean;
|
|
379
|
+
}
|
|
380
|
+
/** The principal kinds the DataOps backend accepts on a grant. */
|
|
381
|
+
export type KnowledgeGrantSubjectType = 'user' | 'role' | 'department' | 'group';
|
|
382
|
+
/**
|
|
383
|
+
* One grant as the permissions surface renders it.
|
|
384
|
+
*
|
|
385
|
+
* The shape mirrors what the backend stores, so the page can echo a row back when
|
|
386
|
+
* revoking it without keeping a second copy of the fields.
|
|
387
|
+
*/
|
|
388
|
+
export interface GrantView {
|
|
389
|
+
/** Stable row identifier. */
|
|
390
|
+
id: string;
|
|
391
|
+
/** Path the grant covers, relative to the knowledge mount point. */
|
|
392
|
+
relPath: string;
|
|
393
|
+
/** Whether the path is a file or a directory. */
|
|
394
|
+
kind: 'file' | 'directory';
|
|
395
|
+
/** Principal kind the grant names. */
|
|
396
|
+
principalType: KnowledgeGrantSubjectType;
|
|
397
|
+
/** Principal id within its kind. */
|
|
398
|
+
principalId: string;
|
|
399
|
+
/** Permission the grant confers. */
|
|
400
|
+
action: string;
|
|
401
|
+
/** Who created the grant. */
|
|
402
|
+
grantedBy: string;
|
|
403
|
+
/** ISO-8601 creation time. */
|
|
404
|
+
grantedAt: string;
|
|
405
|
+
}
|
|
406
|
+
/** One deployment step as the browser receives it. */
|
|
407
|
+
export interface DeployStepView {
|
|
408
|
+
id: string;
|
|
409
|
+
label: string;
|
|
410
|
+
timeoutMs: number;
|
|
411
|
+
commands: string[];
|
|
412
|
+
}
|
|
413
|
+
/** One recorded deployment run. */
|
|
414
|
+
export interface DeployRunView {
|
|
415
|
+
stepId: string;
|
|
416
|
+
hostId: string;
|
|
417
|
+
state: 'running' | 'succeeded' | 'failed';
|
|
418
|
+
startedAt: string;
|
|
419
|
+
finishedAt: string | null;
|
|
420
|
+
log: string[];
|
|
421
|
+
}
|
|
422
|
+
/** One SSH host offered as a deployment target. */
|
|
423
|
+
export interface DeployHostView {
|
|
424
|
+
id: string;
|
|
425
|
+
name: string;
|
|
426
|
+
hostname: string;
|
|
427
|
+
username: string;
|
|
428
|
+
port: number;
|
|
429
|
+
credentialConfigured: boolean;
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* The caller's pinned paths, as the browser renders them.
|
|
433
|
+
*
|
|
434
|
+
* Pins are a document-level preference rather than a per-device one, so they live
|
|
435
|
+
* in the caller's own view directory on the share rather than in browser storage:
|
|
436
|
+
* a reader who pins a folder on one machine expects it pinned on the next. The
|
|
437
|
+
* list is addressed by `relPath` only, because every path it may name has already
|
|
438
|
+
* been resolved as readable for this caller.
|
|
439
|
+
*/
|
|
440
|
+
export interface PinnedView {
|
|
441
|
+
/** Paths the caller pinned, relative to the mount point. */
|
|
442
|
+
relPaths: string[];
|
|
443
|
+
/**
|
|
444
|
+
* Paths that were dropped because the caller may no longer read them.
|
|
445
|
+
*
|
|
446
|
+
* Reported rather than silently discarded: a pin that disappears without a word
|
|
447
|
+
* reads as a bug, while a count explains a revoke.
|
|
448
|
+
*/
|
|
449
|
+
dropped: string[];
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* The caller's favourited paths, as the browser renders them.
|
|
453
|
+
*
|
|
454
|
+
* A star marks a row the reader wanted to find again, so the list is addressed by
|
|
455
|
+
* `relPath` only: every entry has already been resolved as readable for this caller.
|
|
456
|
+
* Kept apart from {@link PinnedView} deliberately -- see `favoritesPathFor`.
|
|
457
|
+
*/
|
|
458
|
+
export interface FavoritesView {
|
|
459
|
+
/** Paths the caller starred, relative to the mount point. */
|
|
460
|
+
relPaths: string[];
|
|
461
|
+
/**
|
|
462
|
+
* Paths dropped because the caller may no longer read them.
|
|
463
|
+
*
|
|
464
|
+
* Reported rather than silently discarded, so a star that disappears after a
|
|
465
|
+
* revoke can be explained instead of looking like a bug.
|
|
466
|
+
*/
|
|
467
|
+
dropped: string[];
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* One entry the caller may move, as the move route reports it.
|
|
471
|
+
*
|
|
472
|
+
* Returned instead of a bare boolean so the caller can tell a refusal apart from a
|
|
473
|
+
* move that did nothing: the route answers 403 for the first and 200 with both
|
|
474
|
+
* paths for the second.
|
|
475
|
+
*/
|
|
476
|
+
export interface MoveResultView {
|
|
477
|
+
/** The path the entry held before the move. */
|
|
478
|
+
from: string;
|
|
479
|
+
/** The path it holds now. */
|
|
480
|
+
to: string;
|
|
481
|
+
/**
|
|
482
|
+
* What the caller's view sync changed, so the surface can report a relink.
|
|
483
|
+
*
|
|
484
|
+
* A move changes two paths in the view -- the new one is linked and the old one
|
|
485
|
+
* is dropped -- and the reader is looking at the old one, so the count is the
|
|
486
|
+
* evidence that the tree they are about to re-read is current.
|
|
487
|
+
*/
|
|
488
|
+
delta: {
|
|
489
|
+
linked: number;
|
|
490
|
+
unlinked: number;
|
|
491
|
+
unchanged: number;
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* The caller's list/grid preference.
|
|
496
|
+
*
|
|
497
|
+
* A document-level preference rather than a per-device one, stored beside the pins
|
|
498
|
+
* for the same reason: a reader who switches to the grid on one machine expects it
|
|
499
|
+
* on the next.
|
|
500
|
+
*/
|
|
501
|
+
export interface ViewModeView {
|
|
502
|
+
/** The stored layout. */
|
|
503
|
+
mode: 'list' | 'grid' | 'explorer';
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* The folders the caller had open in the explorer, as absolute paths.
|
|
507
|
+
*
|
|
508
|
+
* Absolute rather than tree-relative because that is the vocabulary the explorer
|
|
509
|
+
* speaks: it reports `onToggle` with the absolute path of the row and takes
|
|
510
|
+
* `expanded` the same way. Storing them in that form means neither side has to
|
|
511
|
+
* re-derive the root, and a folder that a grant revoke removed simply never
|
|
512
|
+
* matches a row again rather than pointing at some other directory's new occupant.
|
|
513
|
+
*
|
|
514
|
+
* An empty list is the correct answer both for "the reader has collapsed
|
|
515
|
+
* everything" and for "nothing was ever stored", which is why the two share one
|
|
516
|
+
* representation: the tree's default state IS all-collapsed.
|
|
517
|
+
*/
|
|
518
|
+
export interface TreeStateView {
|
|
519
|
+
/** Absolute paths of the folders the reader had expanded. */
|
|
520
|
+
expanded: string[];
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* One template: a document plus the metadata that describes it.
|
|
524
|
+
*
|
|
525
|
+
* Deliberately a flat record rather than a model with its own identity rules: the
|
|
526
|
+
* `id` is derived from the file name inside the template directory, so a template
|
|
527
|
+
* cannot exist without its document and deleting one cannot leave the other behind.
|
|
528
|
+
*/
|
|
529
|
+
export interface KnowledgeTemplateView {
|
|
530
|
+
/** Stable id, derived from the stored file's name. */
|
|
531
|
+
id: string;
|
|
532
|
+
/** Display name. */
|
|
533
|
+
title: string;
|
|
534
|
+
/** One-line description shown on the card. */
|
|
535
|
+
description: string;
|
|
536
|
+
/** Grouping label, e.g. `report` or `meeting`. */
|
|
537
|
+
category: string;
|
|
538
|
+
/** Free-form tags, already split. */
|
|
539
|
+
tags: string[];
|
|
540
|
+
/** The document's file name including its extension. */
|
|
541
|
+
fileName: string;
|
|
542
|
+
/** Extension without the dot, lower-cased; drives the card's file badge. */
|
|
543
|
+
extension: string;
|
|
544
|
+
/** Document size in bytes. */
|
|
545
|
+
bytes: number;
|
|
546
|
+
/** Last-modified instant, ISO-8601. */
|
|
547
|
+
updatedAt: string;
|
|
548
|
+
/** Where the document lives, relative to the knowledge root. */
|
|
549
|
+
relPath: string;
|
|
550
|
+
}
|
|
551
|
+
/** The template library as the Host answers it. */
|
|
552
|
+
export interface KnowledgeTemplatesView {
|
|
553
|
+
/** Every stored template, newest first. */
|
|
554
|
+
templates: KnowledgeTemplateView[];
|
|
555
|
+
/** Set when the list was read but the store could not be (never both). */
|
|
556
|
+
error?: string;
|
|
557
|
+
}
|
|
558
|
+
/** The body of one template save. */
|
|
559
|
+
export interface KnowledgeTemplateSaveInput {
|
|
560
|
+
/** Display name; also used to derive the file name when the document is new. */
|
|
561
|
+
title: string;
|
|
562
|
+
/** One-line description. */
|
|
563
|
+
description: string;
|
|
564
|
+
/** Grouping label. */
|
|
565
|
+
category: string;
|
|
566
|
+
/** Free-form tags. */
|
|
567
|
+
tags: string[];
|
|
568
|
+
/** The document's text. Required when creating, omitted when only metadata changes. */
|
|
569
|
+
content?: string;
|
|
570
|
+
/** The file name to store, including its extension. */
|
|
571
|
+
fileName: string;
|
|
572
|
+
/** Set when editing an existing template, so its document is replaced in place. */
|
|
573
|
+
id?: string;
|
|
574
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The audit surface: what is waiting for a decision, and what has already happened.
|
|
3
|
+
*
|
|
4
|
+
* These two belong on one page and were previously two sections of Settings, which
|
|
5
|
+
* was the wrong shelf for either. A review queue is a WORKLIST -- something an
|
|
6
|
+
* operator opens to get through -- and a trail is a RECORD of what the worklist
|
|
7
|
+
* already settled. Setting them under the review switch made the viewer scroll past
|
|
8
|
+
* configuration to find today's arrivals, and put a record of the past next to a
|
|
9
|
+
* control that governs the future.
|
|
10
|
+
*
|
|
11
|
+
* They share a page because they are one loop seen from two ends: a submission
|
|
12
|
+
* entering, and a decision leaving. Deciding in the first tab appends to the second,
|
|
13
|
+
* so keeping both on screen (one click apart) is what makes the loop legible.
|
|
14
|
+
*
|
|
15
|
+
* Both readings are loaded together and the tabs only choose which table is drawn,
|
|
16
|
+
* so the two can never show different answers to "is the queue empty".
|
|
17
|
+
*
|
|
18
|
+
* @module @sparkelf/dsh-knowledge-base/client
|
|
19
|
+
*/
|
|
20
|
+
/** Props for the audit surface. */
|
|
21
|
+
export interface KnowledgeAuditProps {
|
|
22
|
+
/** Locale-bound copy resolver for this package's namespace. */
|
|
23
|
+
t: (key: string) => string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Format an audit instant for a table cell.
|
|
27
|
+
*
|
|
28
|
+
* DataOps' own surfaces print `YYYY/MM/DD HH:mm`, and a reader comparing this trail
|
|
29
|
+
* against one of those should see the same date rather than a second dialect.
|
|
30
|
+
* @param value - ISO timestamp.
|
|
31
|
+
* @returns The formatted instant, or a dash when unparseable.
|
|
32
|
+
*/
|
|
33
|
+
export declare function formatAuditWhen(value: string): string;
|
|
34
|
+
/**
|
|
35
|
+
* Render the audit page: one tab per end of the review loop.
|
|
36
|
+
* @param props - copy resolver.
|
|
37
|
+
* @returns The audit surface.
|
|
38
|
+
*/
|
|
39
|
+
export declare function KnowledgeAudit(props: KnowledgeAuditProps): import("react").JSX.Element;
|