@sparkelf/dsh-dataops-managed 0.3.22 → 0.3.24
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/lib/client.js +287 -263
- package/lib/client.js.map +1 -1
- package/lib/index.js +52 -21
- package/lib/types/client/SkillPlazaSection.d.ts +33 -0
- package/lib/types/client/locales.d.ts +4 -1
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -1930,40 +1930,67 @@ const CONNECTORS_PATH = "/api/dsh-skill-center/connectors";
|
|
|
1930
1930
|
const DATAOPS_CONNECTOR_ID = "dataops-managed";
|
|
1931
1931
|
/** Resolve the persisted state file without depending on a global DSH path. */
|
|
1932
1932
|
const CONNECTOR_STATE_PATH = join(process.env.DSH_HOME?.trim() || "/workspace/.dataops/dsh", "dataops-managed", "connector-state.json");
|
|
1933
|
-
/**
|
|
1933
|
+
/**
|
|
1934
|
+
* Capability definitions before permission filtering.
|
|
1935
|
+
*
|
|
1936
|
+
* The set and its order follow `dataops/docs/dataops-connector-development-spec.md` §2.3,
|
|
1937
|
+
* whose credential `requiredFor` list is `approval.push`, `data.query`, and `admin.manage`.
|
|
1938
|
+
* Skill plaza and review queue are governed by `skill:*` permissions and stay out of the
|
|
1939
|
+
* connector's capability switches.
|
|
1940
|
+
*/
|
|
1934
1941
|
const CAPABILITIES = [
|
|
1935
|
-
{
|
|
1936
|
-
id: "skill.plaza",
|
|
1937
|
-
name: "技能广场",
|
|
1938
|
-
description: "读取、安装和管理当前账号可见的技能",
|
|
1939
|
-
allowed: (scope) => hasPermission(scope, "skill:read")
|
|
1940
|
-
},
|
|
1941
|
-
{
|
|
1942
|
-
id: "review.queue",
|
|
1943
|
-
name: "审核队列",
|
|
1944
|
-
description: "查看待审技能、扫描风险并给出审核结论",
|
|
1945
|
-
allowed: (scope) => canReview(scope)
|
|
1946
|
-
},
|
|
1947
1942
|
{
|
|
1948
1943
|
id: "data.query",
|
|
1949
1944
|
name: "数据查询",
|
|
1950
1945
|
description: "通过 DataOps 数据查询能力回答业务问题",
|
|
1946
|
+
defaultEnabled: true,
|
|
1951
1947
|
allowed: () => true
|
|
1952
1948
|
},
|
|
1953
1949
|
{
|
|
1954
|
-
id: "
|
|
1955
|
-
name: "
|
|
1956
|
-
description: "
|
|
1957
|
-
|
|
1950
|
+
id: "approval.push",
|
|
1951
|
+
name: "审批资源",
|
|
1952
|
+
description: "读取/办理万相中台的审批任务,并把状态回写",
|
|
1953
|
+
defaultEnabled: true,
|
|
1954
|
+
allowed: (scope) => canReview(scope)
|
|
1955
|
+
},
|
|
1956
|
+
{
|
|
1957
|
+
id: "admin.manage",
|
|
1958
|
+
name: "万相中台管理",
|
|
1959
|
+
description: "登录万相中台后台执行管理动作",
|
|
1960
|
+
defaultEnabled: true,
|
|
1961
|
+
allowed: (scope) => isAdmin(scope)
|
|
1958
1962
|
}
|
|
1959
1963
|
];
|
|
1964
|
+
/** The ids the catalogue accepts; any other persisted key is a legacy value. */
|
|
1965
|
+
const CAPABILITY_IDS = CAPABILITIES.map((capability) => capability.id);
|
|
1966
|
+
/**
|
|
1967
|
+
* Keep only boolean values for known capability ids.
|
|
1968
|
+
*
|
|
1969
|
+
* A state file written before the catalogue changed may still hold retired ids. Those keys are
|
|
1970
|
+
* ignored rather than treated as a corrupt file; a missing new key takes the capability's
|
|
1971
|
+
* `defaultEnabled`.
|
|
1972
|
+
* @param value - the `capabilities` member of a parsed state file.
|
|
1973
|
+
* @returns the readable toggles, keyed by current capability id.
|
|
1974
|
+
*/
|
|
1975
|
+
function migrateCapabilities(value) {
|
|
1976
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return {};
|
|
1977
|
+
const stored = value;
|
|
1978
|
+
const capabilities = {};
|
|
1979
|
+
for (const id of CAPABILITY_IDS) if (typeof stored[id] === "boolean") capabilities[id] = stored[id];
|
|
1980
|
+
return capabilities;
|
|
1981
|
+
}
|
|
1960
1982
|
/** Read state; a missing or corrupt file is a safe disabled state. */
|
|
1961
1983
|
async function readConnectorState(path = CONNECTOR_STATE_PATH) {
|
|
1962
1984
|
try {
|
|
1963
1985
|
const payload = JSON.parse(await readFile(path, "utf8"));
|
|
1986
|
+
if (typeof payload !== "object" || payload === null || Array.isArray(payload)) return {
|
|
1987
|
+
enabled: false,
|
|
1988
|
+
capabilities: {}
|
|
1989
|
+
};
|
|
1990
|
+
const record = payload;
|
|
1964
1991
|
return {
|
|
1965
|
-
enabled:
|
|
1966
|
-
capabilities:
|
|
1992
|
+
enabled: record.enabled === true,
|
|
1993
|
+
capabilities: migrateCapabilities(record.capabilities)
|
|
1967
1994
|
};
|
|
1968
1995
|
} catch {
|
|
1969
1996
|
return {
|
|
@@ -1976,7 +2003,11 @@ async function readConnectorState(path = CONNECTOR_STATE_PATH) {
|
|
|
1976
2003
|
async function writeConnectorState(state, path = CONNECTOR_STATE_PATH) {
|
|
1977
2004
|
await mkdir(dirname(path), { recursive: true });
|
|
1978
2005
|
const temporary = path + ".tmp-" + process.pid.toString();
|
|
1979
|
-
|
|
2006
|
+
const payload = {
|
|
2007
|
+
enabled: state.enabled,
|
|
2008
|
+
capabilities: migrateCapabilities(state.capabilities)
|
|
2009
|
+
};
|
|
2010
|
+
await writeFile(temporary, JSON.stringify(payload, null, 2), "utf8");
|
|
1980
2011
|
await rename(temporary, path);
|
|
1981
2012
|
}
|
|
1982
2013
|
/** Build the connector row for one current scope. */
|
|
@@ -1985,7 +2016,7 @@ function buildConnectorView(scope, state) {
|
|
|
1985
2016
|
id: capability.id,
|
|
1986
2017
|
name: capability.name,
|
|
1987
2018
|
description: capability.description,
|
|
1988
|
-
enabled: state.capabilities[capability.id]
|
|
2019
|
+
enabled: state.capabilities[capability.id] ?? capability.defaultEnabled,
|
|
1989
2020
|
permitted: true
|
|
1990
2021
|
}));
|
|
1991
2022
|
return {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
2
|
import type { InjectFace } from '@deepseek-ai/dsh-client-ui-slots';
|
|
3
3
|
import type { en } from './locales.ts';
|
|
4
|
+
import { type PlazaSkill } from './skill-plaza-client.ts';
|
|
4
5
|
/** Values the skill center passes to a contributed section. */
|
|
5
6
|
export interface SkillPlazaSectionInjected {
|
|
6
7
|
/** Translate one DataOps plaza message key. */
|
|
@@ -16,6 +17,38 @@ export interface SkillPlazaSectionInjected {
|
|
|
16
17
|
}
|
|
17
18
|
/** Props accepted by the plaza section. */
|
|
18
19
|
export type SkillPlazaSectionProps = Partial<InjectFace<SkillPlazaSectionInjected>>;
|
|
20
|
+
/** One department option derived from the rows the plaza can show. */
|
|
21
|
+
export interface PlazaDepartmentOption {
|
|
22
|
+
/** Value the select submits: the department code when the row carries one. */
|
|
23
|
+
code: string;
|
|
24
|
+
/** Label shown in the select; never empty. */
|
|
25
|
+
name: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The department a plaza row belongs to.
|
|
29
|
+
*
|
|
30
|
+
* The backend normally sends `departmentCode`; a legacy row may carry only a name or path, so the
|
|
31
|
+
* fallbacks keep those rows selectable instead of dropping them into an empty key.
|
|
32
|
+
* @param skill - one plaza row.
|
|
33
|
+
* @returns the code, the name, or the deepest path name; empty when the row says nothing.
|
|
34
|
+
*/
|
|
35
|
+
export declare function departmentKeyOf(skill: PlazaSkill): string;
|
|
36
|
+
/**
|
|
37
|
+
* The department choices present in the visible rows.
|
|
38
|
+
*
|
|
39
|
+
* The label falls back from the row's own name to the deepest path name and finally to the code,
|
|
40
|
+
* so a department the backend can no longer name still renders as a readable option.
|
|
41
|
+
* @param skills - every row the current query returned.
|
|
42
|
+
* @returns distinct departments, sorted by label.
|
|
43
|
+
*/
|
|
44
|
+
export declare function departmentOptionsOf(skills: readonly PlazaSkill[]): PlazaDepartmentOption[];
|
|
45
|
+
/**
|
|
46
|
+
* The rows the department tab shows.
|
|
47
|
+
* @param skills - every row the current query returned.
|
|
48
|
+
* @param code - selected department key, or an empty string for all of them.
|
|
49
|
+
* @returns the department-shared rows, narrowed to `code` when it is set.
|
|
50
|
+
*/
|
|
51
|
+
export declare function filterByDepartment(skills: readonly PlazaSkill[], code: string): PlazaSkill[];
|
|
19
52
|
/**
|
|
20
53
|
* Browse, share, and install skills other users published.
|
|
21
54
|
*
|
|
@@ -23,7 +23,6 @@ export declare const en: {
|
|
|
23
23
|
readonly defaultsNeverPublished: "Not published yet";
|
|
24
24
|
readonly defaultsNotAdmin: "Administrators only";
|
|
25
25
|
readonly plazaTitle: "Skill plaza";
|
|
26
|
-
readonly plazaAllTags: "All tags";
|
|
27
26
|
readonly plazaMine: "Shared by me";
|
|
28
27
|
readonly plazaShowDetail: "Details";
|
|
29
28
|
readonly plazaClose: "Close";
|
|
@@ -42,6 +41,10 @@ export declare const en: {
|
|
|
42
41
|
readonly plazaTabApproved: "Approved";
|
|
43
42
|
readonly plazaTabPending: "Pending";
|
|
44
43
|
readonly plazaTabAll: "All";
|
|
44
|
+
readonly plazaTabDepartment: "Department";
|
|
45
|
+
readonly plazaDepartment: "Department";
|
|
46
|
+
readonly plazaDepartmentAll: "All departments";
|
|
47
|
+
readonly plazaDepartmentEmpty: "No department-shared skills yet.";
|
|
45
48
|
readonly plazaSharedTag: "Shared";
|
|
46
49
|
readonly plazaReview: "Review";
|
|
47
50
|
readonly plazaPendingEmpty: "No skills are waiting for review.";
|
package/package.json
CHANGED