@datama/studio 0.0.0-stage → 1.0.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/README.md +298 -2
- package/dist/datama-studio.css +1994 -0
- package/dist/datama-studio.es.js +146656 -0
- package/dist/datama-studio.js +6646 -0
- package/dist/datama.min.css +1994 -0
- package/dist/datama.min.js +6646 -0
- package/dist/plotter.min.css +1 -0
- package/dist/plotter.min.js +717 -0
- package/package.json +41 -5
package/README.md
CHANGED
|
@@ -1,3 +1,299 @@
|
|
|
1
|
-
#
|
|
1
|
+
# DataMa Studio v2
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Standalone npm workspace (`@datama/studio`).
|
|
4
|
+
|
|
5
|
+
## Layout
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
studio/
|
|
9
|
+
src/ # App.ts, core/, components, dialogs, solutions, assets, dev/, docs/, types/
|
|
10
|
+
tests/ # Vitest, Playwright, perf
|
|
11
|
+
dist/
|
|
12
|
+
studio/ # datama-studio.* + index.html demo
|
|
13
|
+
plotter/ # plotter CDN bundle
|
|
14
|
+
tableau/ # Tableau viz: public/ | licence/
|
|
15
|
+
powerbi/ # Power BI visual: certified/ | pro/ | pro-manual/ (npm projects)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
| Topic | Location |
|
|
19
|
+
|-------|----------|
|
|
20
|
+
| Architecture (canonical) | [`archi.md`](archi.md) |
|
|
21
|
+
| Architecture (agents — one section) | [`.cursor/skills/studio-architecture/reference/README.md`](.cursor/skills/studio-architecture/reference/README.md) |
|
|
22
|
+
| TypeScript | `src/core/**` + rest of `src/**` as `.ts` — **`src/core/ui/**` remains `.js`** |
|
|
23
|
+
| Plotter CDN | `npm run build:plotter` → `dist/plotter/plotter.{es,iife}.js` |
|
|
24
|
+
|
|
25
|
+
## Commands (from repo root)
|
|
26
|
+
|
|
27
|
+
> **Shell** — this repo lives on a WSL path. The IDE shell is PowerShell on a UNC path where `&&`
|
|
28
|
+
> and inline `VAR=value` are invalid. Run every command below from a **WSL (Ubuntu) terminal**, or
|
|
29
|
+
> wrap it: `wsl -d Ubuntu-20.04 -e bash -lc '<cmd>'`. Node is pinned to 24 — `nvm use 24` first.
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
nvm use 24
|
|
33
|
+
npm ci # install exact dependencies (first checkout)
|
|
34
|
+
npm run serve # Vite :8095 + Sass watch (dev)
|
|
35
|
+
npm run typecheck # tsc -p tsconfig.json
|
|
36
|
+
npm run lint # ESLint (security invariants)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Interim chrome CSS lives under [`src/assets/css/legacy-chrome/`](src/assets/css/legacy-chrome/README.md) until native Studio styles replace it.
|
|
40
|
+
|
|
41
|
+
## Build commands (production, turn-key)
|
|
42
|
+
|
|
43
|
+
Four independent build targets, each emitting into `dist/`:
|
|
44
|
+
|
|
45
|
+
| Target | Script | Output | Deploy |
|
|
46
|
+
|--------|--------|--------|--------|
|
|
47
|
+
| Web bundle (embed/CDN) | `npm run build:prod` | `dist/studio/` + `dist/plotter/` | `npm run deploy:prod` (GCS) or `npm:publish` (npm) |
|
|
48
|
+
| Tableau Viz extension | `npm run build:tableau` | `dist/tableau/{public,licence}/` | `--bucket/--folder` (GCS) |
|
|
49
|
+
| Power BI custom visual | `npm run build:powerbi` | `dist/powerbi/{certified,pro,pro-manual}/` | local only (manual submit) |
|
|
50
|
+
| Looker Studio Community Viz | `npm run build:lookerstudio` | `dist/lookerstudio/` | `--bucket/--folder` (GCS) |
|
|
51
|
+
|
|
52
|
+
`TAG_NAME` (four-part `X.X.X.X`) stamps the version into Tableau/Power BI artifacts; defaults to `local`.
|
|
53
|
+
|
|
54
|
+
### 1. Web bundle (Studio core)
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Full production build (all registered solutions + plotter CDN bundle)
|
|
58
|
+
npm run build:prod # → dist/studio/datama-studio.{js,es.js,css} + dist/plotter/
|
|
59
|
+
|
|
60
|
+
# Staging context
|
|
61
|
+
npm run build:staging
|
|
62
|
+
|
|
63
|
+
# Subset of solutions (smaller bundle) — inline env + forward flags after --
|
|
64
|
+
STUDIO_CONTEXT=prod npm run build:all -- --solutions compare,detect
|
|
65
|
+
|
|
66
|
+
# Deploy the web bundle to GCS (requires gsutil auth)
|
|
67
|
+
npm run deploy:prod # or deploy:staging
|
|
68
|
+
|
|
69
|
+
# Publish the same web bundle to npm (from generated/npm/, never the private root)
|
|
70
|
+
export TAG_NAME=1.0.0.0
|
|
71
|
+
npm run npm:publish:build -- --package-name @datama/studio --npm-access public
|
|
72
|
+
# Dry-run (packs a .tgz under generated/npm/ without publishing):
|
|
73
|
+
npm run npm:publish:dry-run -- --package-name @datama/studio --build
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`build` = JS + CSS only · `build:all` = adds the plotter bundle · `build:prod`/`build:staging` set `STUDIO_CONTEXT`.
|
|
77
|
+
Flags: `--solutions <a,b,…>` (bundle subset, default all), `--clear`/`-c` (readable/non-minified output).
|
|
78
|
+
Public npm access uses Vite prod minify; restricted sets `STUDIO_CLEAR=1` (no Light-style `javascript-obfuscator` yet).
|
|
79
|
+
|
|
80
|
+
### 2. Tableau Viz extension
|
|
81
|
+
|
|
82
|
+
Mode is implicit: **licence** when `--api` is passed, otherwise **public**.
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
# Public (no backend license check)
|
|
86
|
+
TAG_NAME=1.4.0.0 npm run build:tableau -- \
|
|
87
|
+
--host https://cdn.datama.io/tableau # → dist/tableau/public/
|
|
88
|
+
|
|
89
|
+
# Licence (backend license + monitoring)
|
|
90
|
+
TAG_NAME=1.4.0.0 npm run build:tableau -- \
|
|
91
|
+
--api https://api.datama.io \
|
|
92
|
+
--host https://cdn.datama.io/tableau # → dist/tableau/licence/
|
|
93
|
+
|
|
94
|
+
# Build + deploy to GCS in one shot
|
|
95
|
+
TAG_NAME=1.4.0.0 npm run build:tableau -- \
|
|
96
|
+
--api https://api.datama.io \
|
|
97
|
+
--host https://cdn.datama.io/tableau \
|
|
98
|
+
--bucket datama-cdn --folder tableau/licence
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Flags: `--api/-l`, `--host`, `--bucket/-b` + `--folder/-f` (GCS deploy), `--solution/-s <a,b,…>` (default `compare,detect,explore,pivot`), `--dev/-d`, `--clear/-c`. See [`npm run build:tableau -- --help`].
|
|
102
|
+
|
|
103
|
+
### 3. Power BI custom visual
|
|
104
|
+
|
|
105
|
+
Emits a **complete, non-minified npm project** (reviewable by Microsoft certification) under
|
|
106
|
+
`dist/powerbi/<mode>/`. The `.pbiviz` is **not** produced here — it is built inside that project.
|
|
107
|
+
|
|
108
|
+
The visual version comes from `--version/-v` (or the `TAG_NAME` env var); it **must** be four-part
|
|
109
|
+
`X.X.X.X` for `pbiviz package` to accept it (otherwise the build warns and defaults to `local`).
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# Certified (AppSource, zero external network) — all solutions
|
|
113
|
+
npm run build:powerbi -- \
|
|
114
|
+
--mode certified -s compare,detect,explore,pivot -v 1.4.0.0 # → dist/powerbi/certified/
|
|
115
|
+
|
|
116
|
+
# Pro (listed on AppSource, backend license check) — --api required
|
|
117
|
+
npm run build:powerbi -- \
|
|
118
|
+
--mode pro --api https://api.datama.io -v 1.4.0.0 # → dist/powerbi/pro/
|
|
119
|
+
|
|
120
|
+
# Pro Manual Update (distributed from the Datama web app) — --api required
|
|
121
|
+
npm run build:powerbi -- \
|
|
122
|
+
--mode pro-manual --api https://api.datama.io -v 1.4.0.0 # → dist/powerbi/pro-manual/
|
|
123
|
+
|
|
124
|
+
# Equivalent: version via env instead of the flag
|
|
125
|
+
TAG_NAME=1.4.0.0 npm run build:powerbi -- --mode certified
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Then package / lint / audit **inside the generated project** (scripts live only there, never at the Studio root):
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
cd dist/powerbi/certified
|
|
132
|
+
npm ci # first run writes package-lock.json (commit it in the cert repo)
|
|
133
|
+
npm run lint # ESLint + eslint-plugin-powerbi-visuals (src/ only)
|
|
134
|
+
npm run audit # pbiviz package --certification-audit → must report 0 external requests
|
|
135
|
+
npm run package # → dist/datama_powerbi.pbiviz
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Flags: `--mode/-m <certified|pro|pro-manual>` (default `certified`), `--api/-l` (required for pro/pro-manual), `--solution/-s <a,b,…|all>`, `--version/-v <X.X.X.X>` (or `TAG_NAME`), `--guid <baseGuid>` (default reuses the Light GUID for in-place upgrade), `--dev/-d`, `--clear/-c`. See [`npm run build:powerbi -- --help`]. Full flow: [`src/platforms/powerbi/docs/README.md`](src/platforms/powerbi/docs/README.md).
|
|
139
|
+
|
|
140
|
+
### 4. Looker Studio Community Viz
|
|
141
|
+
|
|
142
|
+
Single **Datama Studio** package (all bundled solutions). Register in Looker with `gs://{bucket}/{folder}` after deploy.
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
npm run build:lookerstudio -- --help
|
|
146
|
+
npm run build:lookerstudio -- --version 1.4.0.0 -s compare,detect,explore,pivot
|
|
147
|
+
TAG_NAME=1.4.0.0 npm run build:lookerstudio -- --bucket app2.datama.io --folder looker-datama-studio-local
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Flags: `--solution/-s`, `--bucket/-b` + `--folder/-f` (GCS deploy when both set), `--app`, `--version/-v` (overrides `TAG_NAME`), `--dev/-d` (no minify), `--clear/-c`, `--lite`. Full flow: [`src/platforms/lookerstudio/docs/README.md`](src/platforms/lookerstudio/docs/README.md).
|
|
151
|
+
|
|
152
|
+
**Note:** Some migrated modules still use `// @ts-nocheck` while legacy types are tightened; remove incrementally after enriching `types/legacy-shim.d.ts`.
|
|
153
|
+
|
|
154
|
+
## Client usage (post-build)
|
|
155
|
+
|
|
156
|
+
Build the distributable bundle from the repo root:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
npm run build:css # if CSS is not already in src/assets/css/dist/
|
|
160
|
+
npm run build:prod # or build:staging
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Artifacts (under `studio/dist/studio/`):
|
|
164
|
+
|
|
165
|
+
| File | Role |
|
|
166
|
+
|------|------|
|
|
167
|
+
| `datama-studio.js` | IIFE bundle — global `DatamaStudio` |
|
|
168
|
+
| `datama-studio.es.js` | ES module — `import DatamaStudio from "./datama-studio.es.js"` |
|
|
169
|
+
| `datama-studio.css` | Required styles for the shell and chrome |
|
|
170
|
+
| `index.html` | Minimal post-build demo (inline sample data + Compare story) |
|
|
171
|
+
| `dist/tableau/public/` / `dist/tableau/licence/` | Tableau Viz extension bundle (`npm run build:tableau`) |
|
|
172
|
+
|
|
173
|
+
Plotter CDN: `studio/dist/plotter/plotter.{es,iife}.js` + `plotter.css`.
|
|
174
|
+
|
|
175
|
+
Quick local check after build:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
npm run build # from studio/
|
|
179
|
+
npx --yes serve dist/studio
|
|
180
|
+
# open index.html — or npm run preview (serves dist/studio)
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Serve the host page over HTTP(S) (local static server or CDN).
|
|
184
|
+
|
|
185
|
+
### Constructor parameters
|
|
186
|
+
|
|
187
|
+
`new DatamaStudio(params)` runs the full mount pipeline synchronously in the constructor (configuration → DOM → infra → stories → header chrome → first `refresh()`).
|
|
188
|
+
|
|
189
|
+
| Parameter | Type | Default | Description |
|
|
190
|
+
|-----------|------|---------|-------------|
|
|
191
|
+
| `container` | `string` \| `HTMLElement` | `"datama-studio"` | Host root element **or** id of an existing element. If omitted, a div with the default id is created on `document.body`. The element id becomes the instance `baseID`. |
|
|
192
|
+
| `configuration` | `object` \| `string` | `{}` | Story / workbook bag. Passed through `DataMaStory.unpack` (plain object, JSON string, or legacy packed `{ __datamaStory__, z }`). |
|
|
193
|
+
| `callbacks` | `Record<string, Function>` | `{}` | Host listeners registered on the instance event bus (`DatamaEvents`). Built-in wiring: `onLoad`, `onCreate`, and `onDelete` trigger `refresh()`. `refresh()` emits `onSuccess` or `onError`. `onFilterOnThis` fires when the user picks **Filter on this** on a Compare/Pivot segment (after the filters pin is updated). |
|
|
194
|
+
| `debug` | `boolean` | `false` | Enables `DatamaLog` and `DatamaI18n` debug output. |
|
|
195
|
+
| `infos` | `object` | — | Host metadata. `infos.debug === true` enables debug when `debug` is omitted. `infos.context` overrides the header host context (falls back to `context`). |
|
|
196
|
+
| `context` | `string` | `"dev"` | Host context string passed to header chrome (e.g. embed environment label). |
|
|
197
|
+
| `host` | `object` | — | `{ configurable?: … }` — host flags for header behavior. |
|
|
198
|
+
| `header` | `object` | — | Header configuration bag (forwarded to `DatamaHeader`). |
|
|
199
|
+
| `license` | `string` \| `object` | — | **v2** token (`DL2.…`), **legacy v1** LZW token, or resolved bag (`valid`, `user`, `expiration`, `solutions`, …). String tokens decode asynchronously in the constructor; prefer `DatamaStudio.create()` for a ready license before first paint. See [`src/core/license/docs/README.md`](src/core/license/docs/README.md). |
|
|
200
|
+
| `isDemo` | `boolean` | — | Demo mode flag for header chrome. |
|
|
201
|
+
| `allowSettingsExportWithoutLicense` | `boolean` | — | Allows settings export without a license when true. |
|
|
202
|
+
|
|
203
|
+
#### `configuration` shape (minimal)
|
|
204
|
+
|
|
205
|
+
Phase-1 Studio expects a **multi-story** bag compatible with `DataMaStory.hydrate`:
|
|
206
|
+
|
|
207
|
+
| Field | Type | Description |
|
|
208
|
+
|-------|------|-------------|
|
|
209
|
+
| `stories` | `object[]` \| `Record<string, object>` | Story list or id→story dictionary. Each story typically includes `id`, `title`, optional `emoji`, `preset`, `displayMode` (`"scroll"` \| `"slide"`; default `"scroll"`), optional `appearance` (default Flat; omit or pass official Default tokens), and `activeModules` (`{ instance, module }[]`). Use `displayMode: "slide"` for the carousel. |
|
|
210
|
+
| `activeStory` | `string` | Id of the story selected on load. |
|
|
211
|
+
| `preset` | `string` | Optional top-level preset when migrating empty workbooks (default `"compare"`). |
|
|
212
|
+
| `inputs` | `object` | Optional root inputs; `inputs.language` (string or `{ value: string }`) sets UI locale (`en-US`, `fr-FR`, …). |
|
|
213
|
+
|
|
214
|
+
Packed or legacy Light workbooks are accepted as long as `unpack` / `hydrate` can normalize them. Deeper story schema: [`src/resources/story/README.md`](../src/resources/story/README.md).
|
|
215
|
+
|
|
216
|
+
#### Instance surface (after construction)
|
|
217
|
+
|
|
218
|
+
| Member | Description |
|
|
219
|
+
|--------|-------------|
|
|
220
|
+
| `baseID` | Container element id for this instance. |
|
|
221
|
+
| `events` | `DatamaEvents` — `listen(event, fn)`, `emit(event, …)`. |
|
|
222
|
+
| `timer` | `DatamaTimer` — mount/refresh timings. |
|
|
223
|
+
| `nodeManager` | `DatamaNode` scoped to the studio frame. |
|
|
224
|
+
| `refresh()` | `Promise<void>` — re-applies active story appearance/display and re-renders story chrome. |
|
|
225
|
+
| `debug()` | Logs instance id and timer records (requires debug logging enabled for full detail). |
|
|
226
|
+
|
|
227
|
+
### Example — host embed
|
|
228
|
+
|
|
229
|
+
Host page co-located with the Studio bundle (e.g. inside `dist/studio/`, or adjust paths if you deploy elsewhere):
|
|
230
|
+
|
|
231
|
+
```html
|
|
232
|
+
<!DOCTYPE html>
|
|
233
|
+
<html lang="en">
|
|
234
|
+
<head>
|
|
235
|
+
<meta charset="UTF-8">
|
|
236
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
237
|
+
<title>Datama Studio embed</title>
|
|
238
|
+
<link rel="stylesheet" href="./datama-studio.css">
|
|
239
|
+
<style>
|
|
240
|
+
html, body { margin: 0; height: 100%; }
|
|
241
|
+
#datama-studio { height: 100%; }
|
|
242
|
+
</style>
|
|
243
|
+
</head>
|
|
244
|
+
<body>
|
|
245
|
+
<div id="datama-studio"></div>
|
|
246
|
+
<script src="./datama-studio.js"></script>
|
|
247
|
+
<script>
|
|
248
|
+
// With an encoded license string, prefer create() so decode finishes before chrome:
|
|
249
|
+
// DatamaStudio.create({ license: "DL2....", container: "datama-studio", ... }).then(function (studio) { ... });
|
|
250
|
+
|
|
251
|
+
var studio = new DatamaStudio({
|
|
252
|
+
container: "datama-studio",
|
|
253
|
+
configuration: {
|
|
254
|
+
inputs: { language: "fr-FR" },
|
|
255
|
+
stories: [
|
|
256
|
+
{
|
|
257
|
+
id: "story-revenue",
|
|
258
|
+
title: "Revenue drop",
|
|
259
|
+
emoji: "📉",
|
|
260
|
+
preset: "compare",
|
|
261
|
+
displayMode: "scroll",
|
|
262
|
+
activeModules: [
|
|
263
|
+
{ instance: "compare.waterfall", module: "compare.waterfall" },
|
|
264
|
+
],
|
|
265
|
+
},
|
|
266
|
+
],
|
|
267
|
+
activeStory: "story-revenue",
|
|
268
|
+
},
|
|
269
|
+
debug: false,
|
|
270
|
+
callbacks: {
|
|
271
|
+
onSuccess: function () {
|
|
272
|
+
/* first refresh completed */
|
|
273
|
+
},
|
|
274
|
+
onError: function (err) {
|
|
275
|
+
console.error(err);
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
});
|
|
279
|
+
</script>
|
|
280
|
+
</body>
|
|
281
|
+
</html>
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
ES module variant (`datama-studio.es.js`):
|
|
285
|
+
|
|
286
|
+
```html
|
|
287
|
+
<script type="module">
|
|
288
|
+
import DatamaStudio from "./datama-studio.es.js";
|
|
289
|
+
|
|
290
|
+
const studio = await DatamaStudio.create({
|
|
291
|
+
container: "datama-studio",
|
|
292
|
+
configuration: {},
|
|
293
|
+
});
|
|
294
|
+
</script>
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
With an empty `configuration`, Studio bootstraps **one default story per registered solution** (Compare, Detect, Pivot when all are in the bundle).
|
|
298
|
+
|
|
299
|
+
Further orchestrator notes: [`src/docs/resources/DatamaStudio.md`](src/docs/resources/DatamaStudio.md) and [`archi.md`](archi.md).
|