diff --git a/packages/apollo-wind/package.json b/packages/apollo-wind/package.json index b578d810b..50d583c69 100644 --- a/packages/apollo-wind/package.json +++ b/packages/apollo-wind/package.json @@ -62,7 +62,7 @@ ], "scripts": { "dev": "rslib build --watch", - "build": "rslib build && npm run build:css", + "build": "node scripts/generate-version-css.mjs && rslib build && npm run build:css", "build:css": "npx @tailwindcss/cli -i ./src/styles/tailwind.css -o ./dist/styles.css", "test": "vitest run", "test:ui": "vitest --ui", diff --git a/packages/apollo-wind/rslib.config.ts b/packages/apollo-wind/rslib.config.ts index 135cb72c6..8c5cdf301 100644 --- a/packages/apollo-wind/rslib.config.ts +++ b/packages/apollo-wind/rslib.config.ts @@ -63,8 +63,9 @@ export default defineConfig({ copy: [ // Copy tailwind.consumer.css to dist/tailwind.css { from: './src/styles/tailwind.consumer.css', to: './tailwind.css' }, - // tailwind.consumer.css imports this via relative path + // tailwind.consumer.css imports these via relative path { from: './src/styles/tailwind.utilities.css', to: './tailwind.utilities.css' }, + { from: './src/styles/version.generated.css', to: './version.generated.css' }, ], }, tools: { diff --git a/packages/apollo-wind/scripts/generate-version-css.mjs b/packages/apollo-wind/scripts/generate-version-css.mjs new file mode 100644 index 000000000..868722361 --- /dev/null +++ b/packages/apollo-wind/scripts/generate-version-css.mjs @@ -0,0 +1,50 @@ +// Generates src/styles/version.generated.css from this package's version. +// +// Exposes the current @uipath/apollo-wind version as a CSS custom property +// (`--apollo-wind-version`) so consumers can detect at runtime both that the +// Wind stylesheet is present and which version is loaded (e.g. traceview +// checks this before self-injecting its utility sheet in light-DOM hosts). +// +// package.json is the single source of truth. This runs as the first step of +// `build`, so the published value always matches the released version. The +// generated file is committed too, because the source CSS is imported directly +// by Storybook and apollo-react's canvas styles, which never run this script. + +import { readFileSync, writeFileSync } from 'node:fs'; +import { dirname, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const scriptDir = dirname(fileURLToPath(import.meta.url)); +const packageRoot = resolve(scriptDir, '..'); +const packageJsonPath = resolve(packageRoot, 'package.json'); +const outputPath = resolve(packageRoot, 'src/styles/version.generated.css'); + +/** Render the version stylesheet body for a given version string. */ +export function renderVersionCss(version) { + return `/** + * AUTO-GENERATED by scripts/generate-version-css.mjs — do not edit by hand. + * Regenerated from package.json on every build. See the script for rationale. + */ + +:root { + --apollo-wind-version: "${version}"; +} +`; +} + +/** Read package.json, write version.generated.css, and return the version. */ +export function generateVersionCss() { + const { version } = JSON.parse(readFileSync(packageJsonPath, 'utf8')); + if (!version) { + throw new Error(`No "version" field found in ${packageJsonPath}`); + } + writeFileSync(outputPath, renderVersionCss(version)); + return version; +} + +// Run when invoked directly (e.g. `node scripts/generate-version-css.mjs`), +// but not when imported by a test. +if (import.meta.url === `file://${process.argv[1]}`) { + const version = generateVersionCss(); + console.log(`Wrote --apollo-wind-version: "${version}" to src/styles/version.generated.css`); +} diff --git a/packages/apollo-wind/src/styles/tailwind.consumer.css b/packages/apollo-wind/src/styles/tailwind.consumer.css index 6efd04b0d..e5cfc3eab 100644 --- a/packages/apollo-wind/src/styles/tailwind.consumer.css +++ b/packages/apollo-wind/src/styles/tailwind.consumer.css @@ -15,6 +15,9 @@ @import "./tailwind.utilities.css"; +/* Exposes --apollo-wind-version (auto-generated from package.json on build). */ +@import "./version.generated.css"; + :root { --radius: 0.75rem; /* 12px — base border-radius for buttons and UI elements */ diff --git a/packages/apollo-wind/src/styles/version.generated.css b/packages/apollo-wind/src/styles/version.generated.css new file mode 100644 index 000000000..f7a71b8c3 --- /dev/null +++ b/packages/apollo-wind/src/styles/version.generated.css @@ -0,0 +1,8 @@ +/** + * AUTO-GENERATED by scripts/generate-version-css.mjs — do not edit by hand. + * Regenerated from package.json on every build. See the script for rationale. + */ + +:root { + --apollo-wind-version: "2.29.0"; +} diff --git a/packages/apollo-wind/src/styles/version.test.ts b/packages/apollo-wind/src/styles/version.test.ts new file mode 100644 index 000000000..8b34155d8 --- /dev/null +++ b/packages/apollo-wind/src/styles/version.test.ts @@ -0,0 +1,21 @@ +import { readFileSync } from 'node:fs'; +import { resolve } from 'node:path'; +import { describe, expect, it } from 'vitest'; + +import { renderVersionCss } from '../../scripts/generate-version-css.mjs'; + +const packageRoot = resolve(__dirname, '../..'); +const version = JSON.parse(readFileSync(resolve(packageRoot, 'package.json'), 'utf8')) + .version as string; +const generatedCss = readFileSync(resolve(packageRoot, 'src/styles/version.generated.css'), 'utf8'); + +describe('--apollo-wind-version', () => { + it('exposes the token in the generated stylesheet', () => { + expect(generatedCss).toContain('--apollo-wind-version:'); + }); + + it('matches the current package.json version (regenerate via `pnpm build` if this fails)', () => { + expect(generatedCss).toBe(renderVersionCss(version)); + expect(generatedCss).toContain(`--apollo-wind-version: "${version}";`); + }); +});