@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 CHANGED
@@ -1,3 +1,299 @@
1
- # Temporary Holding Version
1
+ # DataMa Studio v2
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
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).