From 399313e093acdcf64c4532cbffe609b8431e17d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Chalifour?= Date: Fri, 2 Oct 2026 15:00:21 +0200 Subject: [PATCH] chore(apps): update data-app consumers to 0.65.0 Pin the starter and browser tests to the published runtime and regenerate their frozen lockfiles. Adapt generated apps to style injection and typed appearance configuration, and provide required story and CSV export callbacks in analytical fixtures. --- CHANGELOG.md | 6 ++++++ cli/src/commands/app/lib/distribution.test.ts | 2 +- data-app/AGENTS.md | 2 +- data-app/README.md | 2 +- data-app/starter/app.json | 2 +- data-app/starter/bun.lock | 6 ++++-- data-app/starter/fixtures/main.tsx | 10 +++++++--- data-app/starter/fixtures/view.tsx | 20 +++++++++++++++++-- data-app/starter/package.json | 2 +- data-app/starter/src/App.tsx | 2 +- data-app/starter/src/config.ts | 9 +++++++++ data-app/starter/src/main.tsx | 6 +++--- data-app/starter/src/server.ts | 2 +- data-app/tests/bun.lock | 6 ++++-- data-app/tests/package.json | 2 +- data-app/tests/starter.spec.ts | 10 ++++++---- 16 files changed, 65 insertions(+), 24 deletions(-) create mode 100644 data-app/starter/src/config.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index a3e8c0cf..a100cd0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Changed + +- Update generated and upgraded data apps to `@altertable/data-app` 0.65.0. + ## [1.9.0](https://github.com/altertable-ai/altertable-cli/compare/v1.8.0...v1.9.0) (2026-10-01) diff --git a/cli/src/commands/app/lib/distribution.test.ts b/cli/src/commands/app/lib/distribution.test.ts index 71997606..c30e09a0 100644 --- a/cli/src/commands/app/lib/distribution.test.ts +++ b/cli/src/commands/app/lib/distribution.test.ts @@ -40,7 +40,7 @@ test("distribution embeds a deterministic starter with an exact package pin and ); expect(files["src/App.tsx"]).toBe(payload.starter["src/App.tsx"]); expect(files["src/server.ts"]).toContain("@altertable/data-app/server/bun"); - expect(files["src/main.tsx"]).toContain("@altertable/data-app/react/styles.css"); + expect(files["src/main.tsx"]).toContain("injectDataAppStyles();"); expect(files["bun.lock"]).toContain('"name": "example"'); }); diff --git a/data-app/AGENTS.md b/data-app/AGENTS.md index 3cfe60bf..943e14f6 100644 --- a/data-app/AGENTS.md +++ b/data-app/AGENTS.md @@ -9,6 +9,6 @@ See [development commands](README.md#develop). Keep SQL and metric definitions in app-owned source. Import only public package exports; local Bun serving uses `/server/bun`, and each browser entry -imports `/react/styles.css`. Keep starter and browser-test package pins aligned, commit their +calls `injectDataAppStyles()` before mounting. Keep starter and browser-test package pins aligned, commit their lockfiles, and preserve documentation links to installed package docs. Do not copy runtime source into this repository or generated apps. diff --git a/data-app/README.md b/data-app/README.md index e2687f4d..c183c638 100644 --- a/data-app/README.md +++ b/data-app/README.md @@ -27,7 +27,7 @@ Generated projects commit their source, package manifest, and lockfile; they do source. Public imports use `@altertable/data-app/...`. The starter owns React, ReactDOM, and its authoring tools. The package owns its implementation -dependencies. Its stylesheet is imported explicitly by the browser entry. The app's `AGENTS.md` +dependencies. The browser entry calls `injectDataAppStyles()` before mounting. The app's `AGENTS.md` points to the installed package guide and docs; dependency guides are not assumed to load automatically. To adopt a package release, update its exact pin in both `starter/package.json` and diff --git a/data-app/starter/app.json b/data-app/starter/app.json index 818f4643..68e19974 100644 --- a/data-app/starter/app.json +++ b/data-app/starter/app.json @@ -3,7 +3,7 @@ "title": "Getting started", "scope": { "organization": "Your organization", "environment": "your environment" }, "appearance": { - "mode": "light", + "theme": "light", "baseColor": "neutral", "accentColor": "#405d47", "density": "comfortable", diff --git a/data-app/starter/bun.lock b/data-app/starter/bun.lock index 4c47ce3b..bf60d004 100644 --- a/data-app/starter/bun.lock +++ b/data-app/starter/bun.lock @@ -5,7 +5,7 @@ "": { "name": "data-app-starter", "dependencies": { - "@altertable/data-app": "0.61.0", + "@altertable/data-app": "0.65.0", "react": "19.3.0", "react-dom": "19.3.0", }, @@ -21,7 +21,7 @@ }, }, "packages": { - "@altertable/data-app": ["@altertable/data-app@0.61.0", "", { "dependencies": { "@floating-ui/react": "0.27.20", "@internationalized/date": "3.12.4", "@tanstack/react-query": "5.104.0", "fuzzysort": "4.0.2", "lucide-react": "1.48.0", "react-aria-components": "1.21.1" }, "peerDependencies": { "react": ">=19.2.0", "react-dom": ">=19.2.0" } }, "sha512-68nAEv/G0C7ZJ6P+Y0kAEBXEG4cMvEqORJYqR1/9dd+CeEYHMJDN4v20/7VUnYnEfz6reXJGyuKq3MMv6zbhpA=="], + "@altertable/data-app": ["@altertable/data-app@0.65.0", "", { "dependencies": { "@floating-ui/react": "0.27.20", "@internationalized/date": "3.12.4", "@tanstack/react-query": "5.104.0", "fflate": "0.8.3", "fuzzysort": "4.0.2", "lucide-react": "1.48.0", "react-aria-components": "1.21.1" }, "peerDependencies": { "react": ">=19.2.0", "react-dom": ">=19.2.0" } }, "sha512-BvaUwOhjUx0PzQbc8DUf5NUPpXL4VBcZ5LGegFB8Y41rQnmJIQk81AmP+Dg5iz1j/NwlsuiB8ABBUE6nY6e1aQ=="], "@floating-ui/core": ["@floating-ui/core@1.8.0", "", { "dependencies": { "@floating-ui/utils": "^0.2.12" } }, "sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ=="], @@ -193,6 +193,8 @@ "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], + "fflate": ["fflate@0.8.3", "", {}, "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA=="], + "fuzzysort": ["fuzzysort@4.0.2", "", {}, "sha512-3c7yD6rK1EXIsqpcu1ZVzXJugODWNMzvUij6yTiziaAHrpNS8kzFOI9mJLE8pmG4K9JOaVgzQRgklfOEk8f4Tg=="], "lucide-react": ["lucide-react@1.48.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-R0CIKY/fXiC6y9xRBADgsK+VW2p/pcTJOMhLZf1T+uG+vJUvyUR02nGOgmIIC7MPkiNK4Ox8QDnbqF8rJYWPZQ=="], diff --git a/data-app/starter/fixtures/main.tsx b/data-app/starter/fixtures/main.tsx index d3dd39fe..eb7ff00c 100644 --- a/data-app/starter/fixtures/main.tsx +++ b/data-app/starter/fixtures/main.tsx @@ -1,5 +1,4 @@ -import "@altertable/data-app/react/styles.css"; -import { mountDataApp } from "@altertable/data-app/react"; +import { injectDataAppStyles, mountDataApp } from "@altertable/data-app/react"; import { useState } from "react"; import { createDataHooks } from "@altertable/data-app/react"; import { createDataClient } from "@altertable/data-app/client"; @@ -30,7 +29,7 @@ const { defineDataView, useView } = createDataHooks<{ const config = { title: "Orders exploration", scope: { organization: "Acme", environment: "production" }, - appearance: { mode: "light" }, + appearance: { theme: "light" as const }, }; const identifiers = defineDataIdentifiers({ tables: { @@ -105,6 +104,10 @@ function Fixture() { } + csvExport={() => ({ + filename: "orders.csv", + tables: [{ name: "Orders", columns: ["Orders", "Customers"], rows: [[120, 80]] }], + })} story={() => [ { id: "orders", @@ -200,4 +203,5 @@ function Fixture() { ); } +injectDataAppStyles(); mountDataApp({ config, component: Fixture }); diff --git a/data-app/starter/fixtures/view.tsx b/data-app/starter/fixtures/view.tsx index 3d51b4c3..e9550dc8 100644 --- a/data-app/starter/fixtures/view.tsx +++ b/data-app/starter/fixtures/view.tsx @@ -1,7 +1,7 @@ -import "@altertable/data-app/react/styles.css"; import { createDataClient } from "@altertable/data-app/client"; import { createDataHooks, + injectDataAppStyles, mountDataApp, } from "@altertable/data-app/react"; import { @@ -24,7 +24,7 @@ import { type Activity = { count: number; features: string[] }; const config = { - appearance: { mode: "light" }, + appearance: { theme: "light" as const }, title: "Usage exploration", scope: { organization: "Acme", environment: "production" }, }; @@ -98,8 +98,24 @@ function Fixture() { request={activity} dataContext={context} aboutEmpty={{ glossary: { title: "No definitions" }, queries: { title: "No SQL" } }} + story={({ data }) => [ + context.finding({ + id: "activity", + headline: `${data.count} recorded actions`, + visual:

{data.features.join(", ")}

, + evidence: { id: "activity", queryNames: ["activity"] }, + }), + ]} + csvExport={({ data }) => ({ + filename: "activity.csv", + tables: [ + { name: "Actions", columns: ["Count"], rows: [[data.count]] }, + { name: "Features", columns: ["Feature"], rows: data.features.map((feature) => [feature]) }, + ], + })} {...content} /> ); } +injectDataAppStyles(); mountDataApp({ config, component: Fixture }); diff --git a/data-app/starter/package.json b/data-app/starter/package.json index f29418fb..961bda35 100644 --- a/data-app/starter/package.json +++ b/data-app/starter/package.json @@ -15,7 +15,7 @@ "build": "bun build src/index.html --outdir=dist --production" }, "dependencies": { - "@altertable/data-app": "0.61.0", + "@altertable/data-app": "0.65.0", "react": "19.3.0", "react-dom": "19.3.0" }, diff --git a/data-app/starter/src/App.tsx b/data-app/starter/src/App.tsx index a8c25502..e621cc0a 100644 --- a/data-app/starter/src/App.tsx +++ b/data-app/starter/src/App.tsx @@ -1,6 +1,6 @@ import { GettingStarted } from "@altertable/data-app/react"; import { dataContext } from "#app/data-context.ts"; -import app from "#config"; +import app from "#app/config.ts"; /** Connectivity-only screen. Investigate the requested question, then replace this with a view * that leads with a supported finding and explores the useful angles behind it. */ diff --git a/data-app/starter/src/config.ts b/data-app/starter/src/config.ts new file mode 100644 index 00000000..a7cfa69c --- /dev/null +++ b/data-app/starter/src/config.ts @@ -0,0 +1,9 @@ +import { parseAppearance } from "@altertable/data-app/appearance"; +import type { DataAppConfig } from "@altertable/data-app/config"; +import app from "#config"; + +export default { + title: app.title, + scope: app.scope, + appearance: parseAppearance(app.appearance), +} satisfies DataAppConfig; diff --git a/data-app/starter/src/main.tsx b/data-app/starter/src/main.tsx index 6d36cdf8..c6d1cca3 100644 --- a/data-app/starter/src/main.tsx +++ b/data-app/starter/src/main.tsx @@ -1,6 +1,6 @@ -import "@altertable/data-app/react/styles.css"; -import { mountDataApp } from "@altertable/data-app/react"; +import { injectDataAppStyles, mountDataApp } from "@altertable/data-app/react"; import { App } from "#app/App.tsx"; -import app from "#config"; +import app from "#app/config.ts"; +injectDataAppStyles(); mountDataApp({ config: app, component: App }); diff --git a/data-app/starter/src/server.ts b/data-app/starter/src/server.ts index 265bd0e4..a0a817b4 100644 --- a/data-app/starter/src/server.ts +++ b/data-app/starter/src/server.ts @@ -1,6 +1,6 @@ import page from "#app/index.html"; import { serveLocalApp } from "@altertable/data-app/server/bun"; import { operations } from "#app/operations.ts"; -import app from "#config"; +import app from "#app/config.ts"; serveLocalApp({ page, operations, title: app.title }); diff --git a/data-app/tests/bun.lock b/data-app/tests/bun.lock index fb858745..146cb2f8 100644 --- a/data-app/tests/bun.lock +++ b/data-app/tests/bun.lock @@ -5,7 +5,7 @@ "": { "name": "data-app-browser-tests", "dependencies": { - "@altertable/data-app": "0.61.0", + "@altertable/data-app": "0.65.0", }, "devDependencies": { "@playwright/test": "1.63.0", @@ -16,7 +16,7 @@ }, }, "packages": { - "@altertable/data-app": ["@altertable/data-app@0.61.0", "", { "dependencies": { "@floating-ui/react": "0.27.20", "@internationalized/date": "3.12.4", "@tanstack/react-query": "5.104.0", "fuzzysort": "4.0.2", "lucide-react": "1.48.0", "react-aria-components": "1.21.1" }, "peerDependencies": { "react": ">=19.2.0", "react-dom": ">=19.2.0" } }, "sha512-68nAEv/G0C7ZJ6P+Y0kAEBXEG4cMvEqORJYqR1/9dd+CeEYHMJDN4v20/7VUnYnEfz6reXJGyuKq3MMv6zbhpA=="], + "@altertable/data-app": ["@altertable/data-app@0.65.0", "", { "dependencies": { "@floating-ui/react": "0.27.20", "@internationalized/date": "3.12.4", "@tanstack/react-query": "5.104.0", "fflate": "0.8.3", "fuzzysort": "4.0.2", "lucide-react": "1.48.0", "react-aria-components": "1.21.1" }, "peerDependencies": { "react": ">=19.2.0", "react-dom": ">=19.2.0" } }, "sha512-BvaUwOhjUx0PzQbc8DUf5NUPpXL4VBcZ5LGegFB8Y41rQnmJIQk81AmP+Dg5iz1j/NwlsuiB8ABBUE6nY6e1aQ=="], "@floating-ui/core": ["@floating-ui/core@1.8.0", "", { "dependencies": { "@floating-ui/utils": "^0.2.12" } }, "sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ=="], @@ -108,6 +108,8 @@ "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], + "fflate": ["fflate@0.8.3", "", {}, "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA=="], + "fuzzysort": ["fuzzysort@4.0.2", "", {}, "sha512-3c7yD6rK1EXIsqpcu1ZVzXJugODWNMzvUij6yTiziaAHrpNS8kzFOI9mJLE8pmG4K9JOaVgzQRgklfOEk8f4Tg=="], "lucide-react": ["lucide-react@1.48.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-R0CIKY/fXiC6y9xRBADgsK+VW2p/pcTJOMhLZf1T+uG+vJUvyUR02nGOgmIIC7MPkiNK4Ox8QDnbqF8rJYWPZQ=="], diff --git a/data-app/tests/package.json b/data-app/tests/package.json index 2285efc0..4753eb6c 100644 --- a/data-app/tests/package.json +++ b/data-app/tests/package.json @@ -15,6 +15,6 @@ "typescript": "7.0.2" }, "dependencies": { - "@altertable/data-app": "0.61.0" + "@altertable/data-app": "0.65.0" } } diff --git a/data-app/tests/starter.spec.ts b/data-app/tests/starter.spec.ts index b815ab99..266f0d35 100644 --- a/data-app/tests/starter.spec.ts +++ b/data-app/tests/starter.spec.ts @@ -147,7 +147,7 @@ test("data view keeps the last result visible when refresh fails", async ({ await page.goto("/components"); const error = page.getByRole("alert"); await expect(error).toContainText("Couldn’t load results"); - await expect(error).toContainText("The data request failed."); + await expect(error).toContainText("The lakehouse isn’t responding."); await expect(error.getByRole("button", { name: "Retry" })).toBeVisible(); expect( await error.evaluate((element) => element.getBoundingClientRect().width), @@ -197,10 +197,12 @@ test("table pages show bounded rows and reset when filtering changes", async ({ await page.getByRole("searchbox", { name: "Search orders" }).fill("Order"); await expect(pagination).toContainText("1–4 of 11 results"); await page.getByRole("searchbox", { name: "Search orders" }).fill("Order 5"); - await expect(pagination).toContainText("1–1 of 1 result"); - await expect(pagination.getByRole("button", { name: "Previous page" })).toBeDisabled(); - await expect(pagination.getByRole("button", { name: "Next page" })).toBeDisabled(); + await expect(pagination).toHaveCount(0); await expect(table.getByText("Order 5")).toBeVisible(); + await expect(table.locator("tbody tr")).toHaveCount(1); + await page.getByRole("searchbox", { name: "Search orders" }).fill(""); + await expect(pagination).toContainText("1–4 of 11 results"); + await expect(pagination.getByRole("button", { name: "Previous page" })).toBeDisabled(); }); test("request progress appears before Refresh", async ({ page }) => {