@chengxianglibra/dsh-data-analysis 0.1.1 → 0.1.2

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 (195) hide show
  1. package/README.md +83 -34
  2. package/lib/bin/environment.js +1 -1
  3. package/lib/bin/presentation-lint.js +21 -0
  4. package/lib/bridges.js +2 -2
  5. package/lib/client/credentials/create-datasource.js +67 -0
  6. package/lib/client/credentials/install.js +191 -0
  7. package/lib/client/credentials/model.js +494 -0
  8. package/lib/client/credentials/styles.js +17 -0
  9. package/lib/client/workspace-header-action.js +11 -0
  10. package/lib/client.js +1133 -736
  11. package/lib/compatibility.js +1 -1
  12. package/lib/datasource/authoring.js +70 -0
  13. package/lib/datasource/bridge-programs.js +30 -18
  14. package/lib/datasource/bridge.js +100 -8
  15. package/lib/datasource/index.js +3 -2
  16. package/lib/datasource/python.js +115 -0
  17. package/lib/datasource/resolver-program.js +112 -0
  18. package/lib/datasource/rpc.js +88 -0
  19. package/lib/datasource/service.js +687 -0
  20. package/lib/datasource/shell-env.js +2 -333
  21. package/lib/datasource/test.js +24 -51
  22. package/lib/environment/binding.js +54 -9
  23. package/lib/environment/runtime.js +89 -78
  24. package/lib/environment/subprocess.js +6 -1
  25. package/lib/environment/summary.js +3 -3
  26. package/lib/environment/workspace.js +5 -0
  27. package/lib/index.js +1 -1
  28. package/lib/plugin.js +168 -51
  29. package/lib/presentation/assets/portable.js +606 -0
  30. package/lib/presentation/assets/static.js +945 -0
  31. package/lib/presentation/build/index.js +71 -0
  32. package/lib/presentation/commit.js +156 -0
  33. package/lib/presentation/contracts/charts.js +476 -0
  34. package/lib/presentation/contracts/editing.js +58 -0
  35. package/lib/presentation/contracts/index.js +651 -0
  36. package/lib/presentation/contracts/interaction.js +62 -0
  37. package/lib/presentation/contracts/types.js +15 -0
  38. package/lib/presentation/contracts/values.js +28 -0
  39. package/lib/presentation/delivery.js +56 -0
  40. package/lib/presentation/files.js +83 -0
  41. package/lib/presentation/index.js +6 -0
  42. package/lib/presentation/lint.js +46 -0
  43. package/lib/presentation/projection/files.js +85 -0
  44. package/lib/presentation/projection/index.js +195 -0
  45. package/lib/presentation/projection/program.js +144 -0
  46. package/lib/presentation/projection/sql-code.js +79 -0
  47. package/lib/presentation/receipt.js +34 -0
  48. package/lib/presentation/reports.js +122 -0
  49. package/lib/presentation/rpc.js +148 -0
  50. package/lib/presentation/tool.js +122 -0
  51. package/lib/python-execution-contracts.js +1 -0
  52. package/lib/python-execution.js +232 -0
  53. package/lib/semantic-browser/contracts.js +80 -0
  54. package/lib/semantic-browser/definition.js +64 -0
  55. package/lib/semantic-browser/program.js +119 -0
  56. package/lib/semantic-browser/service.js +72 -0
  57. package/lib/semantic-reference/bridge.js +118 -0
  58. package/lib/semantic-reference/contracts.js +113 -0
  59. package/lib/semantic-reference/index.js +3 -0
  60. package/lib/semantic-reference/rpc.js +122 -0
  61. package/lib/semantic-reference/search.js +94 -0
  62. package/lib/semantic-reference/usage.js +143 -0
  63. package/lib/types/bridges.d.ts +2 -2
  64. package/lib/types/client/credentials/create-datasource.d.ts +5 -0
  65. package/lib/types/client/credentials/install.d.ts +1 -0
  66. package/lib/types/client/credentials/model.d.ts +59 -0
  67. package/lib/types/client/credentials/styles.d.ts +1 -0
  68. package/lib/types/client/presentation/ask-dsh.d.ts +9 -0
  69. package/lib/types/client/presentation/chart-explorer.d.ts +12 -0
  70. package/lib/types/client/presentation/chart-geometry.d.ts +30 -0
  71. package/lib/types/client/presentation/chart-renderer.d.ts +10 -0
  72. package/lib/types/client/presentation/chart-specials.d.ts +10 -0
  73. package/lib/types/client/presentation/chart-styles.d.ts +1 -0
  74. package/lib/types/client/presentation/chart-tooltip.d.ts +13 -0
  75. package/lib/types/client/presentation/chart-view.d.ts +23 -0
  76. package/lib/types/client/presentation/copy-context.d.ts +5 -0
  77. package/lib/types/client/presentation/delivery-model.d.ts +54 -0
  78. package/lib/types/client/presentation/delivery.d.ts +77 -0
  79. package/lib/types/client/presentation/editor-controls.d.ts +12 -0
  80. package/lib/types/client/presentation/global-filters.d.ts +6 -0
  81. package/lib/types/client/presentation/host-entry.d.ts +12 -0
  82. package/lib/types/client/presentation/icons.d.ts +4 -0
  83. package/lib/types/client/presentation/install.d.ts +15 -0
  84. package/lib/types/client/presentation/markdown.d.ts +5 -0
  85. package/lib/types/client/presentation/model.d.ts +62 -0
  86. package/lib/types/client/presentation/reader.d.ts +11 -0
  87. package/lib/types/client/presentation/source-code-model.d.ts +16 -0
  88. package/lib/types/client/presentation/source-code.d.ts +11 -0
  89. package/lib/types/client/presentation/source-dialog.d.ts +13 -0
  90. package/lib/types/client/presentation/source-facts.d.ts +20 -0
  91. package/lib/types/client/presentation/source-format.d.ts +5 -0
  92. package/lib/types/client/presentation/source-highlight.d.ts +7 -0
  93. package/lib/types/client/presentation/sources.d.ts +13 -0
  94. package/lib/types/client/presentation/styles.d.ts +1 -0
  95. package/lib/types/client/presentation/table.d.ts +12 -0
  96. package/lib/types/client/presentation/use-element-width.d.ts +5 -0
  97. package/lib/types/client/workspace-header-action.d.ts +7 -0
  98. package/lib/types/client.d.ts +4 -122
  99. package/lib/types/compatibility.d.ts +2 -2
  100. package/lib/types/datasource/authoring.d.ts +25 -0
  101. package/lib/types/datasource/bridge.d.ts +21 -3
  102. package/lib/types/datasource/index.d.ts +3 -5
  103. package/lib/types/datasource/python.d.ts +4 -0
  104. package/lib/types/datasource/resolver-program.d.ts +6 -0
  105. package/lib/types/datasource/rpc.d.ts +4 -0
  106. package/lib/types/datasource/service.d.ts +112 -0
  107. package/lib/types/datasource/shell-env.d.ts +0 -29
  108. package/lib/types/datasource/test.d.ts +6 -29
  109. package/lib/types/environment/binding.d.ts +5 -1
  110. package/lib/types/environment/errors.d.ts +1 -1
  111. package/lib/types/environment/runtime.d.ts +5 -5
  112. package/lib/types/environment/types.d.ts +13 -2
  113. package/lib/types/index.d.ts +1 -1
  114. package/lib/types/plugin.d.ts +11 -5
  115. package/lib/types/presentation/build/index.d.ts +11 -0
  116. package/lib/types/presentation/commit.d.ts +4 -0
  117. package/lib/types/presentation/contracts/charts.d.ts +13 -0
  118. package/lib/types/presentation/contracts/editing.d.ts +8 -0
  119. package/lib/types/presentation/contracts/index.d.ts +11 -0
  120. package/lib/types/presentation/contracts/interaction.d.ts +8 -0
  121. package/lib/types/presentation/contracts/types.d.ts +252 -0
  122. package/lib/types/presentation/contracts/values.d.ts +9 -0
  123. package/lib/types/presentation/delivery.d.ts +3 -0
  124. package/lib/types/presentation/files.d.ts +7 -0
  125. package/lib/types/presentation/index.d.ts +6 -0
  126. package/lib/types/presentation/lint.d.ts +13 -0
  127. package/lib/types/presentation/projection/files.d.ts +2 -0
  128. package/lib/types/presentation/projection/index.d.ts +20 -0
  129. package/lib/types/presentation/projection/program.d.ts +2 -0
  130. package/lib/types/presentation/projection/sql-code.d.ts +2 -0
  131. package/lib/types/presentation/receipt.d.ts +14 -0
  132. package/lib/types/presentation/reports.d.ts +5 -0
  133. package/lib/types/presentation/rpc.d.ts +24 -0
  134. package/lib/types/presentation/tool.d.ts +12 -0
  135. package/lib/types/python-execution-contracts.d.ts +10 -0
  136. package/lib/types/python-execution.d.ts +10 -0
  137. package/lib/types/semantic-browser/contracts.d.ts +40 -0
  138. package/lib/types/semantic-browser/definition.d.ts +20 -0
  139. package/lib/types/semantic-browser/program.d.ts +2 -0
  140. package/lib/types/semantic-browser/service.d.ts +20 -0
  141. package/lib/types/semantic-reference/bridge.d.ts +11 -0
  142. package/lib/types/semantic-reference/contracts.d.ts +51 -0
  143. package/lib/types/semantic-reference/index.d.ts +3 -0
  144. package/lib/types/semantic-reference/rpc.d.ts +15 -0
  145. package/lib/types/semantic-reference/search.d.ts +10 -0
  146. package/lib/types/semantic-reference/usage.d.ts +43 -0
  147. package/package.json +43 -19
  148. package/python/presentation-kit/dist/dsh_data_analysis_presentation_kit-1.1.0-py3-none-any.whl +0 -0
  149. package/skills/dsh-data-analysis-presentation/SKILL.md +24 -0
  150. package/skills/dsh-data-analysis-presentation/references/chart-examples.md +18 -0
  151. package/skills/dsh-data-analysis-presentation/references/charts.md +55 -0
  152. package/skills/dsh-data-analysis-presentation/references/examples/artifact.draft.json +27 -0
  153. package/skills/dsh-data-analysis-presentation/references/examples/charts-bins.dataset.json +33 -0
  154. package/skills/dsh-data-analysis-presentation/references/examples/charts-boxes.dataset.json +45 -0
  155. package/skills/dsh-data-analysis-presentation/references/examples/charts-composition.dataset.json +33 -0
  156. package/skills/dsh-data-analysis-presentation/references/examples/charts-funnel.dataset.json +27 -0
  157. package/skills/dsh-data-analysis-presentation/references/examples/charts-precision.dataset.json +21 -0
  158. package/skills/dsh-data-analysis-presentation/references/examples/charts-series.dataset.json +58 -0
  159. package/skills/dsh-data-analysis-presentation/references/examples/charts-shares.dataset.json +33 -0
  160. package/skills/dsh-data-analysis-presentation/references/examples/charts-waterfall.dataset.json +44 -0
  161. package/skills/dsh-data-analysis-presentation/references/examples/charts.draft.json +392 -0
  162. package/skills/dsh-data-analysis-presentation/references/examples/comparison-selected.dataset.json +24 -0
  163. package/skills/dsh-data-analysis-presentation/references/examples/comparison-summary.dataset.json +22 -0
  164. package/skills/dsh-data-analysis-presentation/references/examples/comparison.dataset.json +18 -0
  165. package/skills/dsh-data-analysis-presentation/references/examples/comparison.draft.json +79 -0
  166. package/skills/dsh-data-analysis-presentation/references/examples/computed-sources.draft.json +35 -0
  167. package/skills/dsh-data-analysis-presentation/references/examples/computed.dataset.json +12 -0
  168. package/skills/dsh-data-analysis-presentation/references/examples/computed.draft.json +57 -0
  169. package/skills/dsh-data-analysis-presentation/references/examples/interaction-detail.dataset.json +30 -0
  170. package/skills/dsh-data-analysis-presentation/references/examples/interaction-summary.dataset.json +22 -0
  171. package/skills/dsh-data-analysis-presentation/references/examples/interaction.draft.json +278 -0
  172. package/skills/dsh-data-analysis-presentation/references/examples/source-only.draft.json +19 -0
  173. package/skills/dsh-data-analysis-presentation/references/examples/write-charts.py +73 -0
  174. package/skills/dsh-data-analysis-presentation/references/examples/write-comparison.py +42 -0
  175. package/skills/dsh-data-analysis-presentation/references/examples/write-computed.py +21 -0
  176. package/skills/dsh-data-analysis-presentation/references/examples/write-interaction.py +33 -0
  177. package/skills/dsh-data-analysis-presentation/references/examples.md +42 -0
  178. package/skills/dsh-data-analysis-presentation/references/interaction.md +56 -0
  179. package/skills/dsh-data-analysis-presentation/references/narrative.md +37 -0
  180. package/skills/dsh-data-analysis-presentation/references/schema.md +138 -0
  181. package/lib/datasource/access.js +0 -60
  182. package/lib/datasource/credentials.js +0 -24
  183. package/lib/evidence/bridge-program.js +0 -153
  184. package/lib/evidence/bridge.js +0 -166
  185. package/lib/evidence/index.js +0 -2
  186. package/lib/evidence/sources.js +0 -263
  187. package/lib/types/datasource/access.d.ts +0 -27
  188. package/lib/types/evidence/bridge.d.ts +0 -40
  189. package/lib/types/evidence/index.d.ts +0 -4
  190. package/lib/types/evidence/sources.d.ts +0 -57
  191. package/python/report-kit/dist/dsh_data_analysis_report_kit-3.0.0-py3-none-any.whl +0 -0
  192. package/skills/dsh-data-analysis-report/SKILL.md +0 -57
  193. package/skills/dsh-data-analysis-report/assets/marivo-artifact.js +0 -113
  194. package/skills/dsh-data-analysis-report/assets/marivo-session-dag.js +0 -1201
  195. package/skills/dsh-data-analysis-report/assets/report-data.js +0 -449
@@ -0,0 +1,71 @@
1
+ // src/presentation/build/index.ts
2
+ import { createHash } from "node:crypto";
3
+ import {
4
+ PRESENTATION_BUDGETS,
5
+ PresentationContractError,
6
+ parsePresentationDocument
7
+ } from "../contracts/index.js";
8
+ var escapeHtml = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
9
+ var inlineJson = (value) => JSON.stringify(value).replaceAll("<", "\\u003c").replaceAll("\u2028", "\\u2028").replaceAll("\u2029", "\\u2029");
10
+ async function buildPresentation(value) {
11
+ parsePresentationDocument(value);
12
+ const documentBytes = Buffer.from(JSON.stringify(value), "utf8");
13
+ const document = parsePresentationDocument(JSON.parse(documentBytes.toString("utf8")));
14
+ const [portable, staticAssets] = await Promise.all([
15
+ import(new URL("../../../lib/presentation/assets/portable.js", import.meta.url).href),
16
+ import(new URL("../../../lib/presentation/assets/static.js", import.meta.url).href)
17
+ ]);
18
+ const fallback = staticAssets.renderFallback(document);
19
+ const script = portable.script.replace(/<\/script/gi, "<\\/script");
20
+ const scriptHash = createHash("sha256").update(script).digest("base64");
21
+ const csp = [
22
+ "default-src 'none'",
23
+ `script-src 'sha256-${scriptHash}' 'wasm-unsafe-eval'`,
24
+ "script-src-attr 'none'",
25
+ "style-src 'unsafe-inline'",
26
+ "connect-src 'none'",
27
+ "img-src 'none'",
28
+ "font-src 'none'",
29
+ "media-src 'none'",
30
+ "frame-src 'none'",
31
+ "worker-src 'none'",
32
+ "object-src 'none'",
33
+ "base-uri 'none'",
34
+ "form-action 'none'"
35
+ ].join("; ");
36
+ const htmlBytes = Buffer.from(
37
+ `<!doctype html>
38
+ <html lang="zh-CN">
39
+ <head>
40
+ <meta charset="utf-8">
41
+ <meta http-equiv="Content-Security-Policy" content="${escapeHtml(csp)}">
42
+ <meta name="viewport" content="width=device-width,initial-scale=1">
43
+ <meta name="color-scheme" content="light dark">
44
+ <meta name="referrer" content="no-referrer">
45
+ <title>${escapeHtml(document.title)}</title>
46
+ <style>${portable.styles.replace(/<\/style/gi, "<\\/style")}</style>
47
+ </head>
48
+ <body data-presentation-portable="true">
49
+ <div id="presentation-fallback">${fallback}</div>
50
+ <div id="reader"></div>
51
+ <script id="presentation-data" type="application/json">${inlineJson(document)}</script>
52
+ <script id="third-party-notices" type="application/json">${inlineJson(portable.notices)}</script>
53
+ <script id="presentation-runtime">${script}</script>
54
+ </body>
55
+ </html>
56
+ `,
57
+ "utf8"
58
+ );
59
+ if (htmlBytes.length > PRESENTATION_BUDGETS.htmlBytes) {
60
+ throw new PresentationContractError(
61
+ "budget",
62
+ "/html",
63
+ `HTML exceeds the ${PRESENTATION_BUDGETS.htmlBytes} byte budget.`,
64
+ "Reduce repeated blocks, displayed rows, or text before building again."
65
+ );
66
+ }
67
+ return { document, documentBytes, htmlBytes };
68
+ }
69
+ export {
70
+ buildPresentation
71
+ };
@@ -0,0 +1,156 @@
1
+ import { constants } from 'node:fs';
2
+ import { lstat, mkdir, mkdtemp, open, realpath, rename, rm } from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import { PRESENTATION_BUDGETS, parsePresentationDocument, parsePresentationReceipt, } from "./contracts/index.js";
5
+ import { presentationAssetPath, presentationSha256, readPresentationAsset } from "./files.js";
6
+ async function directory(filename) {
7
+ const stat = await lstat(filename);
8
+ if (!stat.isDirectory() || stat.isSymbolicLink() || (await realpath(filename)) !== filename)
9
+ throw new Error('presentation-directory-mismatch');
10
+ return stat;
11
+ }
12
+ async function syncDirectory(filename) {
13
+ const handle = await open(filename, constants.O_RDONLY | constants.O_NOFOLLOW);
14
+ try {
15
+ await handle.sync();
16
+ }
17
+ finally {
18
+ await handle.close();
19
+ }
20
+ }
21
+ async function sameDirectory(filename, expected) {
22
+ const actual = await directory(filename);
23
+ if (actual.dev !== expected.dev || actual.ino !== expected.ino)
24
+ throw new Error('presentation-directory-changed');
25
+ }
26
+ /** Owns only one newly-created build. A single directory rename publishes both complete files. */
27
+ export async function commitPresentation(workspaceRoot, input, assertOwner, signal) {
28
+ signal?.throwIfAborted();
29
+ const document = parsePresentationDocument(structuredClone(input.document));
30
+ const built = {
31
+ document,
32
+ documentBytes: Buffer.from(input.documentBytes),
33
+ htmlBytes: Buffer.from(input.htmlBytes),
34
+ };
35
+ if (built.documentBytes.length > PRESENTATION_BUDGETS.documentBytes ||
36
+ built.htmlBytes.length === 0 ||
37
+ built.htmlBytes.length > PRESENTATION_BUDGETS.htmlBytes)
38
+ throw new Error('presentation-build-budget');
39
+ if (!built.documentBytes.equals(Buffer.from(JSON.stringify(document))))
40
+ throw new Error('presentation-build-document-mismatch');
41
+ const root = await realpath(workspaceRoot);
42
+ if (root !== path.resolve(workspaceRoot))
43
+ throw new Error('presentation-workspace-mismatch');
44
+ const paths = [
45
+ root,
46
+ path.join(root, '.dsh-data-analysis'),
47
+ path.join(root, '.dsh-data-analysis', 'presentations'),
48
+ path.join(root, '.dsh-data-analysis', 'presentations', document.reportId),
49
+ path.join(root, '.dsh-data-analysis', 'presentations', document.reportId, 'builds'),
50
+ ];
51
+ const identities = [];
52
+ for (const [index, filename] of paths.entries()) {
53
+ if (index > 0) {
54
+ await sameDirectory(paths[index - 1], identities[index - 1]);
55
+ try {
56
+ await mkdir(filename, { mode: 0o700 });
57
+ await syncDirectory(paths[index - 1]);
58
+ }
59
+ catch (error) {
60
+ if (error.code !== 'EEXIST')
61
+ throw error;
62
+ }
63
+ }
64
+ identities.push(await directory(filename));
65
+ }
66
+ const check = async () => {
67
+ signal?.throwIfAborted();
68
+ await assertOwner();
69
+ for (const [index, filename] of paths.entries())
70
+ await sameDirectory(filename, identities[index]);
71
+ signal?.throwIfAborted();
72
+ };
73
+ await check();
74
+ const parent = paths.at(-1);
75
+ const temporary = await mkdtemp(path.join(parent, '.pending-'));
76
+ const ownedIdentity = await directory(temporary);
77
+ const final = path.dirname(presentationAssetPath(root, built.document.reportId, built.document.buildId, 'presentation.json'));
78
+ let owned = temporary;
79
+ try {
80
+ await check();
81
+ for (const [asset, bytes] of [
82
+ ['presentation.json', built.documentBytes],
83
+ ['index.html', built.htmlBytes],
84
+ ]) {
85
+ await sameDirectory(temporary, ownedIdentity);
86
+ signal?.throwIfAborted();
87
+ const file = await open(path.join(temporary, asset), constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 0o600);
88
+ try {
89
+ await file.writeFile(bytes, { signal });
90
+ await file.sync();
91
+ }
92
+ finally {
93
+ await file.close();
94
+ }
95
+ }
96
+ await check();
97
+ await sameDirectory(temporary, ownedIdentity);
98
+ await syncDirectory(temporary);
99
+ // Never overwrite a completed build (the caller creates an unpredictable build UUID).
100
+ try {
101
+ await lstat(final);
102
+ throw new Error('presentation-build-exists');
103
+ }
104
+ catch (error) {
105
+ if (error.code !== 'ENOENT')
106
+ throw error;
107
+ }
108
+ await rename(temporary, final);
109
+ owned = final;
110
+ for (const filename of [...paths].reverse())
111
+ await syncDirectory(filename);
112
+ await check();
113
+ await sameDirectory(final, ownedIdentity);
114
+ const document = await readPresentationAsset(root, built.document.reportId, built.document.buildId, 'presentation.json', signal);
115
+ const html = await readPresentationAsset(root, built.document.reportId, built.document.buildId, 'index.html', signal);
116
+ if (!document.equals(built.documentBytes) || !html.equals(built.htmlBytes))
117
+ throw new Error('presentation-build-changed');
118
+ await check();
119
+ return parsePresentationReceipt({
120
+ schemaVersion: 2,
121
+ reportId: built.document.reportId,
122
+ kind: 'marivo.presentation',
123
+ workspaceId: built.document.workspaceId,
124
+ buildId: built.document.buildId,
125
+ title: built.document.title,
126
+ summary: `${built.document.blocks.length} 个区块 · ${built.document.datasets.length} 份数据集 · ${built.document.sources.length} 个声明来源 · ${built.document.diagnostics.length} 条诊断`,
127
+ files: {
128
+ document: {
129
+ asset: 'presentation.json',
130
+ path: path.join(final, 'presentation.json'),
131
+ sha256: presentationSha256(document),
132
+ bytes: document.length,
133
+ },
134
+ html: {
135
+ asset: 'index.html',
136
+ path: path.join(final, 'index.html'),
137
+ sha256: presentationSha256(html),
138
+ bytes: html.length,
139
+ },
140
+ },
141
+ });
142
+ }
143
+ catch (error) {
144
+ // Cleanup only this invocation's unchanged directory; never follow a replaced parent.
145
+ try {
146
+ for (const [index, filename] of paths.entries())
147
+ await sameDirectory(filename, identities[index]);
148
+ await sameDirectory(owned, ownedIdentity);
149
+ await rm(owned, { recursive: true, force: true });
150
+ }
151
+ catch {
152
+ /* Failure cleanup must not hide the original cancellation/write error. */
153
+ }
154
+ throw error;
155
+ }
156
+ }