@chengxianglibra/dsh-data-analysis 0.1.2 → 0.2.1

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 (222) hide show
  1. package/README.en.md +135 -0
  2. package/README.md +105 -98
  3. package/cordis.patch.yml +1 -1
  4. package/lib/bin/environment.js +8 -6
  5. package/lib/client/credentials/changes.js +74 -0
  6. package/lib/client/credentials/create-datasource.js +126 -22
  7. package/lib/client/credentials/credential-draft.js +42 -0
  8. package/lib/client/credentials/defaults.js +11 -0
  9. package/lib/client/credentials/descriptions.js +46 -0
  10. package/lib/client/credentials/install.js +209 -81
  11. package/lib/client/credentials/model.js +323 -51
  12. package/lib/client/credentials/report-publishing.js +96 -0
  13. package/lib/client/credentials/styles.js +13 -9
  14. package/lib/client/i18n/context.js +22 -0
  15. package/lib/client/i18n/copy.js +60 -0
  16. package/lib/client/i18n/credentials.js +475 -0
  17. package/lib/client/i18n/host.js +28 -0
  18. package/lib/client/i18n/navigation.js +41 -0
  19. package/lib/client/i18n/presentation.js +577 -0
  20. package/lib/client/i18n/python.js +36 -0
  21. package/lib/client/i18n/semantic.js +441 -0
  22. package/lib/client/i18n/settings.js +30 -0
  23. package/lib/client/input-context.js +21 -0
  24. package/lib/client/python-tool/card.js +35 -0
  25. package/lib/client/python-tool/execution-error.js +35 -0
  26. package/lib/client/python-tool/install.js +9 -0
  27. package/lib/client/python-tool/model.js +101 -0
  28. package/lib/client/right-tabs/install.js +535 -0
  29. package/lib/client/right-tabs/live-delivery.js +58 -0
  30. package/lib/client/right-tabs/navigation.js +47 -0
  31. package/lib/client/right-tabs/page.js +178 -0
  32. package/lib/client/right-tabs/styles.js +11 -0
  33. package/lib/client/rpc.js +5 -0
  34. package/lib/client/semantic-reference.js +10 -0
  35. package/lib/client/settings/card.js +90 -0
  36. package/lib/client/settings/install.js +10 -0
  37. package/lib/client/workspace-header-action.js +14 -1
  38. package/lib/client/workspace-shortcuts.js +26 -0
  39. package/lib/client.js +388 -242
  40. package/lib/compatibility.js +1 -1
  41. package/lib/datasource/authoring.js +43 -4
  42. package/lib/datasource/bridge-programs.js +23 -20
  43. package/lib/datasource/bridge.js +46 -3
  44. package/lib/datasource/changes-contract.js +41 -0
  45. package/lib/datasource/changes.js +49 -0
  46. package/lib/datasource/configure.js +39 -0
  47. package/lib/datasource/defaults.js +25 -0
  48. package/lib/datasource/index.js +2 -1
  49. package/lib/datasource/python-options.js +15 -0
  50. package/lib/datasource/python.js +119 -25
  51. package/lib/datasource/rpc.js +75 -13
  52. package/lib/datasource/service.js +286 -11
  53. package/lib/datasource/test.js +3 -2
  54. package/lib/disclosure/activation.js +19 -7
  55. package/lib/disclosure/execution-guidance.js +49 -0
  56. package/lib/disclosure/help.js +4 -1
  57. package/lib/environment/runtime.js +35 -34
  58. package/lib/environment/workspace.js +18 -1
  59. package/lib/lifecycle.js +33 -0
  60. package/lib/plugin-agents.js +154 -0
  61. package/lib/plugin.js +98 -172
  62. package/lib/presentation/asset.js +34 -0
  63. package/lib/presentation/assets/portable.js +14 -14
  64. package/lib/presentation/assets/static.js +344 -73
  65. package/lib/presentation/build/index.js +3 -2
  66. package/lib/presentation/commit.js +19 -12
  67. package/lib/presentation/contracts/asset-path.js +9 -0
  68. package/lib/presentation/contracts/catalog.js +62 -0
  69. package/lib/presentation/contracts/charts.js +0 -23
  70. package/lib/presentation/contracts/index.js +17 -5
  71. package/lib/presentation/contracts/types.js +1 -1
  72. package/lib/presentation/delivery.js +45 -30
  73. package/lib/presentation/export-html.js +214 -0
  74. package/lib/presentation/files.js +4 -5
  75. package/lib/presentation/projection/index.js +2 -1
  76. package/lib/presentation/projection/program.js +2 -9
  77. package/lib/presentation/projection/sql-code.js +13 -13
  78. package/lib/presentation/reports.js +114 -17
  79. package/lib/presentation/rpc.js +96 -58
  80. package/lib/presentation/tool.js +6 -10
  81. package/lib/report-publishing/adapters.js +111 -0
  82. package/lib/report-publishing/config.js +69 -0
  83. package/lib/report-publishing/service.js +180 -0
  84. package/lib/rpc.js +49 -0
  85. package/lib/semantic-browser/contracts.js +17 -0
  86. package/lib/semantic-browser/program.js +10 -0
  87. package/lib/semantic-browser/service.js +40 -6
  88. package/lib/semantic-reference/bridge.js +10 -1
  89. package/lib/semantic-reference/contracts.js +20 -6
  90. package/lib/semantic-reference/environment.js +56 -0
  91. package/lib/semantic-reference/labels.js +16 -0
  92. package/lib/semantic-reference/rpc.js +39 -18
  93. package/lib/semantic-reference/search.js +5 -4
  94. package/lib/semantic-reference/usage.js +12 -3
  95. package/lib/settings.js +21 -0
  96. package/lib/tool-lifecycle.js +22 -0
  97. package/lib/types/client/credentials/changes.d.ts +9 -0
  98. package/lib/types/client/credentials/create-datasource.d.ts +3 -1
  99. package/lib/types/client/credentials/credential-draft.d.ts +14 -0
  100. package/lib/types/client/credentials/defaults.d.ts +2 -0
  101. package/lib/types/client/credentials/descriptions.d.ts +1 -0
  102. package/lib/types/client/credentials/install.d.ts +19 -1
  103. package/lib/types/client/credentials/model.d.ts +31 -11
  104. package/lib/types/client/credentials/report-publishing.d.ts +5 -0
  105. package/lib/types/client/credentials/styles.d.ts +1 -1
  106. package/lib/types/client/i18n/context.d.ts +17 -0
  107. package/lib/types/client/i18n/copy.d.ts +821 -0
  108. package/lib/types/client/i18n/credentials.d.ts +475 -0
  109. package/lib/types/client/i18n/host.d.ts +17 -0
  110. package/lib/types/client/i18n/navigation.d.ts +41 -0
  111. package/lib/types/client/i18n/presentation.d.ts +577 -0
  112. package/lib/types/client/i18n/python.d.ts +19 -0
  113. package/lib/types/client/i18n/semantic.d.ts +441 -0
  114. package/lib/types/client/i18n/settings.d.ts +16 -0
  115. package/lib/types/client/input-context.d.ts +19 -0
  116. package/lib/types/client/presentation/ask-dsh.d.ts +4 -8
  117. package/lib/types/client/presentation/catalog-model.d.ts +24 -0
  118. package/lib/types/client/presentation/catalog.d.ts +20 -0
  119. package/lib/types/client/presentation/chart-tooltip.d.ts +2 -2
  120. package/lib/types/client/presentation/context-reference.d.ts +12 -0
  121. package/lib/types/client/presentation/copy-context.d.ts +2 -2
  122. package/lib/types/client/presentation/delivery-model.d.ts +27 -6
  123. package/lib/types/client/presentation/delivery.d.ts +8 -7
  124. package/lib/types/client/presentation/download.d.ts +2 -0
  125. package/lib/types/client/presentation/export-menu.d.ts +26 -0
  126. package/lib/types/client/presentation/export-view.d.ts +63 -0
  127. package/lib/types/client/presentation/host-entry.d.ts +8 -2
  128. package/lib/types/client/presentation/icons.d.ts +1 -1
  129. package/lib/types/client/presentation/model.d.ts +14 -15
  130. package/lib/types/client/presentation/reader.d.ts +15 -2
  131. package/lib/types/client/presentation/reference-source.d.ts +9 -0
  132. package/lib/types/client/presentation/source-code-model.d.ts +2 -1
  133. package/lib/types/client/presentation/source-code.d.ts +0 -5
  134. package/lib/types/client/presentation/source-dialog.d.ts +1 -2
  135. package/lib/types/client/presentation/sources.d.ts +5 -5
  136. package/lib/types/client/presentation/styles.d.ts +1 -1
  137. package/lib/types/client/presentation/table.d.ts +5 -1
  138. package/lib/types/client/python-tool/card.d.ts +2 -0
  139. package/lib/types/client/python-tool/execution-error.d.ts +3 -0
  140. package/lib/types/client/python-tool/install.d.ts +2 -0
  141. package/lib/types/client/python-tool/model.d.ts +20 -0
  142. package/lib/types/client/right-tabs/install.d.ts +18 -0
  143. package/lib/types/client/right-tabs/live-delivery.d.ts +8 -0
  144. package/lib/types/client/right-tabs/navigation.d.ts +17 -0
  145. package/lib/types/client/right-tabs/page.d.ts +36 -0
  146. package/lib/types/client/right-tabs/styles.d.ts +2 -0
  147. package/lib/types/client/rpc.d.ts +3 -0
  148. package/lib/types/client/semantic-reference.d.ts +4 -0
  149. package/lib/types/client/settings/card.d.ts +9 -0
  150. package/lib/types/client/settings/install.d.ts +2 -0
  151. package/lib/types/client/workspace-header-action.d.ts +1 -1
  152. package/lib/types/client/workspace-shortcuts.d.ts +15 -0
  153. package/lib/types/client.d.ts +5 -2
  154. package/lib/types/compatibility.d.ts +1 -1
  155. package/lib/types/datasource/authoring.d.ts +10 -0
  156. package/lib/types/datasource/bridge.d.ts +23 -2
  157. package/lib/types/datasource/changes-contract.d.ts +18 -0
  158. package/lib/types/datasource/changes.d.ts +15 -0
  159. package/lib/types/datasource/configure.d.ts +7 -0
  160. package/lib/types/datasource/defaults.d.ts +7 -0
  161. package/lib/types/datasource/index.d.ts +6 -1
  162. package/lib/types/datasource/python-options.d.ts +8 -0
  163. package/lib/types/datasource/python.d.ts +17 -2
  164. package/lib/types/datasource/rpc.d.ts +2 -1
  165. package/lib/types/datasource/service.d.ts +48 -5
  166. package/lib/types/datasource/test.d.ts +1 -1
  167. package/lib/types/disclosure/activation.d.ts +2 -1
  168. package/lib/types/disclosure/execution-guidance.d.ts +6 -0
  169. package/lib/types/disclosure/help.d.ts +1 -1
  170. package/lib/types/environment/types.d.ts +2 -1
  171. package/lib/types/environment/workspace.d.ts +1 -0
  172. package/lib/types/lifecycle.d.ts +8 -0
  173. package/lib/types/plugin-agents.d.ts +29 -0
  174. package/lib/types/plugin.d.ts +12 -28
  175. package/lib/types/presentation/asset.d.ts +6 -0
  176. package/lib/types/presentation/build/index.d.ts +7 -2
  177. package/lib/types/presentation/commit.d.ts +1 -1
  178. package/lib/types/presentation/contracts/asset-path.d.ts +2 -0
  179. package/lib/types/presentation/contracts/catalog.d.ts +27 -0
  180. package/lib/types/presentation/contracts/charts.d.ts +0 -2
  181. package/lib/types/presentation/contracts/types.d.ts +7 -4
  182. package/lib/types/presentation/delivery.d.ts +1 -1
  183. package/lib/types/presentation/export-html.d.ts +13 -0
  184. package/lib/types/presentation/reports.d.ts +6 -1
  185. package/lib/types/presentation/rpc.d.ts +3 -2
  186. package/lib/types/presentation/tool.d.ts +2 -2
  187. package/lib/types/report-publishing/adapters.d.ts +6 -0
  188. package/lib/types/report-publishing/config.d.ts +22 -0
  189. package/lib/types/report-publishing/service.d.ts +68 -0
  190. package/lib/types/rpc.d.ts +3 -0
  191. package/lib/types/semantic-browser/contracts.d.ts +7 -0
  192. package/lib/types/semantic-browser/service.d.ts +7 -1
  193. package/lib/types/semantic-reference/bridge.d.ts +1 -0
  194. package/lib/types/semantic-reference/contracts.d.ts +5 -2
  195. package/lib/types/semantic-reference/environment.d.ts +22 -0
  196. package/lib/types/semantic-reference/labels.d.ts +16 -0
  197. package/lib/types/semantic-reference/rpc.d.ts +1 -1
  198. package/lib/types/semantic-reference/search.d.ts +1 -1
  199. package/lib/types/settings.d.ts +14 -0
  200. package/lib/types/tool-lifecycle.d.ts +4 -0
  201. package/lib/types/workspace-identity.d.ts +6 -0
  202. package/lib/workspace-identity.js +9 -0
  203. package/package.json +93 -61
  204. package/python/presentation-kit/dist/dsh_data_analysis_presentation_kit-1.1.0-py3-none-any.whl +0 -0
  205. package/skills/dsh-data-analysis-files/SKILL.md +44 -0
  206. package/skills/dsh-data-analysis-files/references/delivery.md +15 -0
  207. package/skills/dsh-data-analysis-files/references/examples.md +93 -0
  208. package/skills/dsh-data-analysis-presentation/SKILL.md +15 -15
  209. package/skills/dsh-data-analysis-presentation/references/examples/artifact.draft.json +13 -4
  210. package/skills/dsh-data-analysis-presentation/references/examples/charts.draft.json +3 -2
  211. package/skills/dsh-data-analysis-presentation/references/examples/comparison.draft.json +3 -2
  212. package/skills/dsh-data-analysis-presentation/references/examples/computed-sources.draft.json +12 -5
  213. package/skills/dsh-data-analysis-presentation/references/examples/computed.draft.json +3 -2
  214. package/skills/dsh-data-analysis-presentation/references/examples/interaction.draft.json +3 -2
  215. package/skills/dsh-data-analysis-presentation/references/examples/source-only.draft.json +12 -4
  216. package/skills/dsh-data-analysis-presentation/references/examples.md +3 -1
  217. package/skills/dsh-data-analysis-presentation/references/export-html.md +7 -0
  218. package/skills/dsh-data-analysis-presentation/references/interaction.md +1 -1
  219. package/skills/dsh-data-analysis-presentation/references/narrative.md +1 -1
  220. package/skills/dsh-data-analysis-presentation/references/publishing.md +3 -0
  221. package/skills/dsh-data-analysis-presentation/references/schema.md +29 -2
  222. package/lib/types/client/presentation/install.d.ts +0 -15
@@ -1,67 +1,171 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  // @ts-nocheck -- JSX is bundled by the plugin client build.
3
- import { useEffect, useState } from 'react';
4
- export function CreateDatasource({ model, workspaceId, close }) {
3
+ import { useEffect, useId, useRef, useState } from 'react';
4
+ import { useCopy } from "./../i18n/context.js";
5
+ import { errorMessage, message } from "./../i18n/copy.js";
6
+ import { credentialReference, prepareCredentials } from "./credential-draft.js";
7
+ import { creationFieldValues } from "./defaults.js";
8
+ import { datasourceDescription } from "./descriptions.js";
9
+ function credentialLabel(field) {
10
+ return ({
11
+ user_env: 'marivo.credentials.username',
12
+ password_env: 'marivo.credentials.password',
13
+ http_bearer_token_env: 'marivo.credentials.access-token',
14
+ http_headers_env: 'marivo.credentials.header-credential-value',
15
+ }[field] ?? field.replace(/_env$/, ''));
16
+ }
17
+ function credentialRows(schema, backend, values = {}) {
18
+ return (schema.backends.find((item) => item.name === backend)?.fields ?? [])
19
+ .filter((field) => field.name.endsWith('_env'))
20
+ .flatMap((field) => field.type === 'json'
21
+ ? Object.entries(values[field.name] ?? {}).map(([key, existing]) => ({
22
+ id: crypto.randomUUID(),
23
+ field: field.name,
24
+ key,
25
+ existing,
26
+ value: '',
27
+ }))
28
+ : [{ id: crypto.randomUUID(), field: field.name, existing: values[field.name], value: '' }]);
29
+ }
30
+ export function CreateDatasource({ model, workspaceId, close, name, requestId }) {
31
+ const t = useCopy();
32
+ const formId = useId();
33
+ const active = useRef(false);
5
34
  const [schema, setSchema] = useState(null);
35
+ const [original, setOriginal] = useState(null);
6
36
  const [backend, setBackend] = useState('');
7
37
  const [values, setValues] = useState({});
38
+ const [credentials, setCredentials] = useState([]);
8
39
  const [busy, setBusy] = useState(false);
9
40
  const [error, setError] = useState('');
10
41
  useEffect(() => {
11
42
  const controller = new AbortController();
12
- model
13
- .authoring(workspaceId, controller.signal)
14
- .then((value) => {
43
+ active.current = true;
44
+ Promise.all([
45
+ model.authoring(workspaceId, controller.signal, name ? 'edit' : 'create'),
46
+ name ? model.configuration(workspaceId, name, controller.signal) : Promise.resolve(null),
47
+ ])
48
+ .then(([value, configuration]) => {
15
49
  if (controller.signal.aborted)
16
50
  return;
17
51
  setSchema(value);
18
- setBackend(value.backends[0]?.name ?? '');
52
+ setOriginal(configuration);
53
+ setBackend(configuration?.backend ?? value.backends[0]?.name ?? '');
54
+ setCredentials(credentialRows(value, configuration?.backend ?? value.backends[0]?.name, configuration?.fields));
55
+ if (!configuration)
56
+ setValues(creationFieldValues(value, value.backends[0]?.name ?? ''));
57
+ if (configuration) {
58
+ const fields = value.backends.find((item) => item.name === configuration.backend)?.fields;
59
+ if (!fields)
60
+ throw new Error('marivo.credentials.this-runtime-cannot-fully-edit-this-datasource');
61
+ setValues(Object.fromEntries(fields
62
+ .filter((field) => !field.name.endsWith('_env') && configuration.fields[field.name] !== undefined)
63
+ .map((field) => [
64
+ field.name,
65
+ field.type === 'string'
66
+ ? configuration.fields[field.name]
67
+ : JSON.stringify(configuration.fields[field.name]),
68
+ ])));
69
+ }
19
70
  })
20
71
  .catch((error) => {
21
72
  if (!controller.signal.aborted)
22
- setError(error.message);
73
+ setError(errorMessage(error));
23
74
  });
24
- return () => controller.abort();
25
- }, [model, workspaceId]);
75
+ return () => {
76
+ active.current = false;
77
+ controller.abort();
78
+ };
79
+ }, [model, workspaceId, name]);
26
80
  const fields = schema?.backends.find((item) => item.name === backend)?.fields ?? [];
81
+ const credentialFields = fields.filter((field) => field.name.endsWith('_env'));
82
+ const updateCredential = (id, change) => setCredentials((rows) => rows.map((row) => (row.id === id ? { ...row, ...change } : row)));
27
83
  async function submit(event) {
28
84
  event.preventDefault();
29
85
  if (busy)
30
86
  return;
31
87
  setError('');
32
88
  const input = {};
89
+ let changes = {};
33
90
  try {
34
- for (const field of fields) {
91
+ for (const field of fields.filter((field) => !field.name.endsWith('_env'))) {
35
92
  const value = values[field.name];
36
- if (value === undefined || value === '')
93
+ if (value === undefined)
94
+ continue;
95
+ if (value === '' &&
96
+ (field.type !== 'string' ||
97
+ (name
98
+ ? original?.fields[field.name] !== ''
99
+ : schema.creationDefaults?.[backend]?.[field.name] !== '')))
37
100
  continue;
38
101
  input[field.name] = field.type === 'string' ? value : JSON.parse(value);
39
102
  }
103
+ const prepared = prepareCredentials(input.name ?? '', credentials);
104
+ Object.assign(input, prepared.fields);
105
+ changes = prepared.changes;
40
106
  }
41
- catch {
42
- setError('请检查数字、布尔值或 JSON 字段的格式。');
107
+ catch (error) {
108
+ setError(error instanceof SyntaxError
109
+ ? 'marivo.credentials.check-the-format-of-number-boolean-and-json-fields'
110
+ : errorMessage(error));
43
111
  return;
44
112
  }
45
113
  setBusy(true);
114
+ // Remove secrets from mounted inputs as soon as the explicit submission begins.
115
+ setCredentials((rows) => rows.map((row) => ({ ...row, value: '' })));
46
116
  try {
47
- await model.createDatasource(workspaceId, schema, { backend, fields: input });
48
- close();
117
+ await model.saveConfiguration(workspaceId, schema, { backend, fields: input }, original, requestId, changes);
118
+ if (active.current)
119
+ close();
49
120
  }
50
121
  catch (error) {
51
- setError(error.message);
122
+ if (active.current)
123
+ setError(message('marivo.credentials.value-credential-inputs-have-been-cleared-enter-them-again', {
124
+ p0: errorMessage(error),
125
+ }));
52
126
  }
53
127
  finally {
54
- setBusy(false);
128
+ for (const ref of Object.keys(changes))
129
+ delete changes[ref];
130
+ if (active.current)
131
+ setBusy(false);
55
132
  }
56
133
  }
57
- return (_jsxs("form", { className: "mc-form", "aria-label": "\u65B0\u589E\u6570\u636E\u6E90", onSubmit: submit, children: [_jsxs("div", { className: "mc-form-body", children: [_jsx("div", { className: "mc-detail-heading", children: _jsx("h3", { children: "\u65B0\u589E\u6570\u636E\u6E90" }) }), error && (_jsx("p", { role: "alert", className: "mc-result", "data-tone": "error", children: error })), !schema && !error && _jsx("p", { role: "status", children: "\u6B63\u5728\u8BFB\u53D6\u6570\u636E\u6E90\u914D\u7F6E\u5B57\u6BB5\u2026" }), schema && (_jsxs("fieldset", { className: "mc-field", disabled: busy, children: [_jsxs("label", { className: "mc-secret-input", children: ["\u5F15\u64CE", _jsx("select", { "aria-label": "\u5F15\u64CE", value: backend, onChange: (event) => {
134
+ return (_jsxs("form", { className: "mc-form", "aria-label": name ? t('marivo.credentials.edit-datasource') : t('marivo.credentials.add-datasource'), onSubmit: submit, children: [_jsxs("div", { className: "mc-form-body", children: [_jsx("div", { className: "mc-detail-heading", children: _jsx("h3", { children: name
135
+ ? t('marivo.credentials.edit-datasource')
136
+ : t('marivo.credentials.add-datasource') }) }), error && (_jsx("p", { role: "alert", className: "mc-result", "data-tone": "error", children: t(error) })), !schema && !error && (_jsx("p", { role: "status", children: t('marivo.credentials.loading-datasource-configuration-fields') })), schema && (_jsxs("fieldset", { className: "mc-field", disabled: busy, children: [_jsxs("label", { className: "mc-secret-input", children: [t('marivo.credentials.engine'), _jsx("select", { "aria-label": t('marivo.credentials.engine'), disabled: !!name, value: backend, onChange: (event) => {
58
137
  setBackend(event.target.value);
59
- setValues({});
138
+ setValues(creationFieldValues(schema, event.target.value));
139
+ setCredentials(credentialRows(schema, event.target.value));
60
140
  setError('');
61
- }, children: schema.backends.map((item) => (_jsx("option", { value: item.name, children: item.name }, item.name))) })] }), fields.map((field) => (_jsxs("label", { className: "mc-secret-input", htmlFor: `mc-create-${field.name}`, children: [_jsxs("span", { className: "mc-input-heading", children: [_jsxs("span", { className: "mc-input-name", children: [field.name, field.name.endsWith('_env') ? '(凭证引用名)' : '', field.required ? ' *' : ''] }), (field.description || field.name.endsWith('_env')) && (_jsxs("span", { className: "mc-input-description", children: [field.description, field.name.endsWith('_env') &&
62
- ' 填写引用名,如 MY_DB_PASSWORD;仅使用字母、数字和下划线,不能以数字开头。实际用户名或密码请在创建后的“新增凭证”中填写。'] }))] }), field.type === 'boolean' ? (_jsxs("select", { id: `mc-create-${field.name}`, "aria-label": field.name, value: values[field.name] ?? '', onChange: (event) => setValues({ ...values, [field.name]: event.target.value }), children: [_jsxs("option", { value: "", children: ["\u9ED8\u8BA4", field.default == null ? '' : ` (${field.default})`] }), _jsx("option", { value: "true", children: "true" }), _jsx("option", { value: "false", children: "false" })] })) : (_jsx("input", { id: `mc-create-${field.name}`, "aria-label": field.name, required: field.required, autoComplete: "off", type: field.type === 'number' ? 'number' : 'text', placeholder: field.default == null
141
+ }, children: schema.backends.map((item) => (_jsx("option", { value: item.name, children: item.name }, item.name))) })] }), fields
142
+ .filter((field) => !field.name.endsWith('_env'))
143
+ .map((field) => (_jsxs("label", { className: "mc-secret-input", htmlFor: `${formId}-${field.name}`, children: [_jsxs("span", { className: "mc-input-heading", children: [_jsxs("span", { className: "mc-input-name", children: [field.name, field.required ? ' *' : ''] }), field.description && (_jsx("span", { className: "mc-input-description", children: t(datasourceDescription(field.description)) }))] }), field.type === 'boolean' ? (_jsxs("select", { id: `${formId}-${field.name}`, "aria-label": field.name, value: values[field.name] ?? '', onChange: (event) => setValues({ ...values, [field.name]: event.target.value }), children: [_jsxs("option", { value: "", children: [t('marivo.credentials.default'), field.default == null ? '' : ` (${field.default})`] }), _jsx("option", { value: "true", children: "true" }), _jsx("option", { value: "false", children: "false" })] })) : (_jsx("input", { id: `${formId}-${field.name}`, "aria-label": field.name, required: field.required, disabled: !!name && field.name === 'name', autoComplete: "off", type: field.type === 'number' ? 'number' : 'text', placeholder: field.default == null
63
144
  ? field.type === 'json'
64
145
  ? 'JSON'
65
146
  : ''
66
- : String(field.default), value: values[field.name] ?? '', onChange: (event) => setValues({ ...values, [field.name]: event.target.value }) }))] }, field.name)))] }))] }), _jsxs("div", { className: "mc-form-footer", children: [_jsx("button", { className: "mc-primary", type: "submit", disabled: !backend || busy, children: busy ? '正在新增…' : '确认新增数据源' }), _jsx("button", { type: "button", onClick: close, disabled: busy, children: "\u53D6\u6D88" })] })] }));
147
+ : String(field.default), value: values[field.name] ?? '', onChange: (event) => setValues({ ...values, [field.name]: event.target.value }) }))] }, field.name))), credentialFields.length > 0 && (_jsxs("section", { className: "mc-inline-credentials", "aria-label": t('marivo.credentials.connection-credentials'), children: [_jsx("h4", { children: t('marivo.credentials.connection-credentials') }), _jsxs("p", { className: "mc-note", children: [t('marivo.credentials.enter-credential-values-directly-for-harness-to-save-references'), name ? t('marivo.credentials.leave-blank-to-keep-the-current-value-a-new') : ''] }), credentialFields.map((field) => (_jsxs("div", { className: "mc-credential-group", children: [credentials
148
+ .filter((row) => row.field === field.name)
149
+ .map((row) => {
150
+ const label = credentialLabel(field.name);
151
+ const reference = credentialReference(values.name ?? '', row);
152
+ return (_jsxs("div", { className: "mc-credential-entry", children: [row.key !== undefined && (_jsxs("label", { className: "mc-secret-input", children: [t('marivo.credentials.header-name'), _jsx("input", { "aria-label": t('marivo.credentials.header-name'), value: row.key, onChange: (event) => updateCredential(row.id, { key: event.target.value }) })] })), _jsxs("label", { className: "mc-secret-input", children: [_jsxs("span", { className: "mc-input-heading", children: [_jsxs("span", { className: "mc-input-name", children: [t(label), field.required ? ' *' : ''] }), _jsx("span", { className: "mc-input-description", children: row.existing
153
+ ? t('marivo.credentials.a-reference-is-configured-leave-blank-to-keep-it')
154
+ : t('marivo.credentials.enter-the-value-directly-no-need-to-create-a') })] }), _jsx("input", { "aria-label": t(label), type: "password", autoComplete: "new-password", maxLength: 65536, required: field.required && !reference, value: row.value, placeholder: row.existing
155
+ ? t('marivo.credentials.leave-blank-to-keep-enter-a-new-value-to')
156
+ : t('marivo.credentials.enter-credential-value'), onChange: (event) => updateCredential(row.id, { value: event.target.value }) })] }), _jsxs("details", { className: "mc-reference-options", children: [_jsx("summary", { children: t('marivo.credentials.credential-reference-review-or-change') }), _jsxs("label", { className: "mc-secret-input", children: [field.name, _jsx("input", { "aria-label": field.name, autoComplete: "off", value: reference, placeholder: t('marivo.credentials.generated-after-entering-a-credential-value'), onChange: (event) => updateCredential(row.id, { reference: event.target.value }) })] }), _jsx("p", { className: "mc-note", children: t('marivo.credentials.to-reuse-a-saved-credential-enter-its-reference-and') }), row.reference !== undefined && (_jsx("button", { type: "button", onClick: () => updateCredential(row.id, { reference: undefined }), children: t('marivo.credentials.restore-automatic-reference') }))] }), row.key !== undefined && (_jsx("button", { type: "button", className: "mc-quiet", onClick: () => setCredentials((rows) => rows.filter((item) => item.id !== row.id)), children: t('marivo.credentials.remove-header') }))] }, row.id));
157
+ }), field.type === 'json' && (_jsx("button", { type: "button", onClick: () => setCredentials((rows) => [
158
+ ...rows,
159
+ { id: crypto.randomUUID(), field: field.name, key: '', value: '' },
160
+ ]), children: t('marivo.credentials.add-header-credential') }))] }, field.name)))] }))] }))] }), _jsx("p", { className: "mc-note", children: requestId
161
+ ? t('marivo.credentials.save-configuration-and-credentials-then-test-the-connection-the')
162
+ : name
163
+ ? t('marivo.credentials.test-the-connection-again-after-saving-name-and-engine')
164
+ : '' }), _jsxs("div", { className: "mc-form-footer", children: [_jsx("button", { className: "mc-primary", type: "submit", disabled: !backend || busy, children: busy
165
+ ? t('marivo.credentials.saving-or-validating')
166
+ : requestId
167
+ ? t('marivo.credentials.save-and-test-then-continue')
168
+ : name
169
+ ? t('marivo.credentials.save-configuration')
170
+ : t('marivo.credentials.confirm-new-datasource') }), _jsx("button", { type: "button", onClick: close, disabled: busy, children: t('marivo.credentials.cancel') })] })] }));
67
171
  }
@@ -0,0 +1,42 @@
1
+ export function credentialReference(name, draft) {
2
+ if (draft.reference !== undefined)
3
+ return draft.reference.trim();
4
+ if (!draft.value)
5
+ return draft.existing ?? '';
6
+ const part = (value) => value
7
+ .toUpperCase()
8
+ .replace(/[^A-Z0-9_]/g, '_')
9
+ .slice(0, 40);
10
+ return `DS_${part(name) || 'CONNECTION'}_${part(draft.key ?? draft.field.replace(/_env$/, ''))}_${draft.id.replace(/-/g, '').toUpperCase()}`;
11
+ }
12
+ /** Values are kept separate from the public configuration, then handed to the credential operation. */
13
+ export function prepareCredentials(name, drafts) {
14
+ const fields = {};
15
+ const changes = Object.create(null);
16
+ for (const draft of drafts) {
17
+ const ref = credentialReference(name, draft);
18
+ if (!ref && !draft.value)
19
+ continue;
20
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(ref) ||
21
+ ref.length > 256 ||
22
+ /^(MARIVO_|DSH_DATA_ANALYSIS_|DSH_HOME$|DSH_SESSION_ID$|DSH_SESSION_JSONL$|DSH_SHELL$)/i.test(ref))
23
+ throw new Error('marivo.credentials.credential-references-may-contain-only-letters-numbers-and-underscores');
24
+ if (draft.key !== undefined) {
25
+ if (!draft.key.trim())
26
+ throw new Error('marivo.credentials.enter-the-header-name-for-this-credential');
27
+ fields[draft.field] ??= Object.create(null);
28
+ const mapping = fields[draft.field];
29
+ if (Object.hasOwn(mapping, draft.key))
30
+ throw new Error('marivo.credentials.header-names-must-be-unique');
31
+ mapping[draft.key] = ref;
32
+ }
33
+ else
34
+ fields[draft.field] = ref;
35
+ if (draft.value) {
36
+ if (changes[ref] !== undefined && changes[ref] !== draft.value)
37
+ throw new Error('marivo.credentials.the-same-credential-reference-cannot-have-different-values');
38
+ changes[ref] = draft.value;
39
+ }
40
+ }
41
+ return { fields, changes };
42
+ }
@@ -0,0 +1,11 @@
1
+ export function creationFieldValues(schema, backend) {
2
+ const defaults = schema.creationDefaults?.[backend] ?? {};
3
+ return Object.fromEntries((schema.backends.find((item) => item.name === backend)?.fields ?? [])
4
+ .filter((field) => !field.name.endsWith('_env') && Object.hasOwn(defaults, field.name))
5
+ .map((field) => [
6
+ field.name,
7
+ field.type === 'string'
8
+ ? defaults[field.name]
9
+ : JSON.stringify(defaults[field.name]),
10
+ ]));
11
+ }
@@ -0,0 +1,46 @@
1
+ // Presentation-only translations of public Runtime descriptions, not a field schema.
2
+ // Match the complete source text so changed or newly added descriptions retain their meaning.
3
+ const descriptions = {
4
+ 'Global datasource name; letters, digits, underscores, and hyphens only.': 'marivo.credentials.global-datasource-name-use-only-letters-numbers-underscores-and',
5
+ 'Rare JSON-safe ibis keyword arguments not modeled by the typed class.': 'marivo.credentials.additional-connection-parameters-for-ibis-options-not-listed-in',
6
+ 'DuckDB database path; defaults to in-memory.': 'marivo.credentials.duckdb-database-file-path-defaults-to-an-in-memory',
7
+ 'SQLite database path; defaults to in-memory.': 'marivo.credentials.sqlite-database-file-path-defaults-to-an-in-memory',
8
+ 'Open the DuckDB database in read-only mode.': 'marivo.credentials.open-the-duckdb-database-in-read-only-mode',
9
+ 'Open the SQLite database in query-only mode.': 'marivo.credentials.open-the-sqlite-database-in-query-only-mode',
10
+ 'Optional mapping from declared SQLite type names to Ibis type strings.': 'marivo.credentials.optional-mapping-from-sqlite-declared-type-names-to-ibis',
11
+ 'Optional HTTP(S) URL prefix for scoped remote JSON auth.': 'marivo.credentials.optional-http-s-url-prefix-where-remote-json-requests',
12
+ 'Environment variable for a scoped HTTP bearer token.': 'marivo.credentials.credential-reference-for-the-http-bearer-token-within-the',
13
+ 'Optional custom HTTP header names mapped to secret environment variables.': 'marivo.credentials.optional-mapping-from-custom-http-header-names-to-credential',
14
+ 'Trino coordinator host.': 'marivo.credentials.trino-coordinator-host-address',
15
+ 'Trino catalog; mapped to ibis database at connect time.': 'marivo.credentials.trino-catalog-name-mapped-to-the-ibis-database-parameter',
16
+ 'Required environment variable for the Trino user.': 'marivo.credentials.required-credential-reference-for-the-trino-username',
17
+ 'Trino port; ibis default is 8080.': 'marivo.credentials.trino-port-ibis-defaults-to-8080',
18
+ 'Optional default schema.': 'marivo.credentials.optional-default-schema-name',
19
+ 'Optional client application/source tag.': 'marivo.credentials.optional-client-application-or-request-source-identifier',
20
+ 'Optional engine session timezone.': 'marivo.credentials.optional-database-session-timezone',
21
+ "Set to 'https' for TLS.": 'marivo.credentials.enter-https-to-enable-tls-encryption',
22
+ 'Optional Trino client tags.': 'marivo.credentials.optional-trino-client-tags-as-a-json-array',
23
+ 'Optional Trino session properties.': 'marivo.credentials.optional-trino-session-properties-as-a-json-object',
24
+ 'Environment variable for Trino auth token or password.': 'marivo.credentials.credential-reference-for-the-trino-token-or-password',
25
+ 'MySQL host.': 'marivo.credentials.mysql-server-host-address',
26
+ 'MySQL database name.': 'marivo.credentials.mysql-database-name',
27
+ 'MySQL port; ibis default is 3306.': 'marivo.credentials.mysql-port-ibis-defaults-to-3306',
28
+ 'Optional autocommit override.': 'marivo.credentials.optional-setting-for-automatic-transaction-commits',
29
+ 'Environment variable for MySQL user.': 'marivo.credentials.credential-reference-for-the-mysql-username',
30
+ 'Environment variable for MySQL password.': 'marivo.credentials.credential-reference-for-the-mysql-password',
31
+ 'Postgres host.': 'marivo.credentials.postgresql-server-host-address',
32
+ 'Postgres database name.': 'marivo.credentials.postgresql-database-name',
33
+ 'Postgres port; ibis default is 5432.': 'marivo.credentials.postgresql-port-ibis-defaults-to-5432',
34
+ 'Environment variable for Postgres user.': 'marivo.credentials.credential-reference-for-the-postgresql-username',
35
+ 'Environment variable for Postgres password.': 'marivo.credentials.credential-reference-for-the-postgresql-password',
36
+ 'ClickHouse host.': 'marivo.credentials.clickhouse-server-host-address',
37
+ 'ClickHouse port; native default is 9000, secure default is 9440.': 'marivo.credentials.clickhouse-port-native-connections-default-to-9000-secure-connections',
38
+ "ClickHouse database; ibis default is 'default'.": 'marivo.credentials.clickhouse-database-name-ibis-defaults-to-default',
39
+ 'Enable TLS for ClickHouse.': 'marivo.credentials.enable-tls-encryption-for-clickhouse',
40
+ 'Optional ClickHouse settings map.': 'marivo.credentials.optional-clickhouse-settings-as-a-json-object',
41
+ 'Environment variable for ClickHouse user.': 'marivo.credentials.credential-reference-for-the-clickhouse-username',
42
+ 'Environment variable for ClickHouse password.': 'marivo.credentials.credential-reference-for-the-clickhouse-password',
43
+ };
44
+ export function datasourceDescription(description) {
45
+ return descriptions[description] ?? description;
46
+ }