fix(packages): ship web and theme assets
This commit is contained in:
@@ -8,6 +8,9 @@
|
|||||||
"./dist/*": "./dist/*",
|
"./dist/*": "./dist/*",
|
||||||
"./package.json": "./package.json"
|
"./package.json": "./package.json"
|
||||||
},
|
},
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
"types": "./lib/types/client/index.d.ts",
|
"types": "./lib/types/client/index.d.ts",
|
||||||
"default": "./lib/client.js"
|
"default": "./lib/client.js"
|
||||||
},
|
},
|
||||||
"./styles/*": "./src/styles/*",
|
"./styles/*": "./lib/styles/*",
|
||||||
"./src/*": "./src/*",
|
"./src/*": "./src/*",
|
||||||
"./package.json": "./package.json"
|
"./package.json": "./package.json"
|
||||||
},
|
},
|
||||||
@@ -56,6 +56,7 @@
|
|||||||
"lib/index.js",
|
"lib/index.js",
|
||||||
"lib/invariant.js",
|
"lib/invariant.js",
|
||||||
"lib/client.js",
|
"lib/client.js",
|
||||||
|
"lib/styles",
|
||||||
"lib/types/**/*.d.ts",
|
"lib/types/**/*.d.ts",
|
||||||
"lib/types/**/*.d.ts.map",
|
"lib/types/**/*.d.ts.map",
|
||||||
"src"
|
"src"
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
import { clientBundle } from '../tsdown.client.ts'
|
import { clientBundle } from '../tsdown.client.ts'
|
||||||
|
|
||||||
export default clientBundle('@deepseek-ai/dsh-client-ui-theme', ['lib/types/index.js', 'lib/types/invariant.js'])
|
const [lib, client] = clientBundle(
|
||||||
|
'@deepseek-ai/dsh-client-ui-theme',
|
||||||
|
['lib/types/index.js', 'lib/types/invariant.js'],
|
||||||
|
)
|
||||||
|
|
||||||
|
export default [{
|
||||||
|
...lib,
|
||||||
|
copy: [{ from: 'src/styles/*', to: 'lib/styles' }],
|
||||||
|
}, client]
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ import { describe, expect, it } from 'vitest'
|
|||||||
|
|
||||||
const THEME_PACKAGE = '@deepseek-ai/dsh-client-ui-theme'
|
const THEME_PACKAGE = '@deepseek-ai/dsh-client-ui-theme'
|
||||||
const baseCss = readFileSync(fileURLToPath(new URL('../src/base.css', import.meta.url)), 'utf8')
|
const baseCss = readFileSync(fileURLToPath(new URL('../src/base.css', import.meta.url)), 'utf8')
|
||||||
|
const themeManifest = JSON.parse(
|
||||||
|
readFileSync(fileURLToPath(new URL('../../ui-theme/package.json', import.meta.url)), 'utf8'),
|
||||||
|
) as { exports: Record<string, string>; files: string[] }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Import specifiers of the sheet, in source order. Quote style and surrounding
|
* Import specifiers of the sheet, in source order. Quote style and surrounding
|
||||||
@@ -24,9 +27,9 @@ function importOrder(css: string): string[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve a `<package>/styles/<file>` specifier to its path in the workspace.
|
* Resolve a `<package>/styles/<file>` specifier to its source path for a
|
||||||
* The theme package maps `./styles/*` to `./src/styles/*`, so the sheets stay
|
* clean-tree test. The package build copies these sheets to their public
|
||||||
* on the source plane rather than needing a build.
|
* `lib/styles` export.
|
||||||
* @param specifier - import specifier from base.css.
|
* @param specifier - import specifier from base.css.
|
||||||
* @returns absolute path of the file the specifier names.
|
* @returns absolute path of the file the specifier names.
|
||||||
*/
|
*/
|
||||||
@@ -38,6 +41,11 @@ function resolveThemeSheet(specifier: string): string {
|
|||||||
const imports = importOrder(baseCss)
|
const imports = importOrder(baseCss)
|
||||||
|
|
||||||
describe('web shell base.css', () => {
|
describe('web shell base.css', () => {
|
||||||
|
it('publishes theme sheets from the built artifact plane', () => {
|
||||||
|
expect(themeManifest.exports['./styles/*']).toBe('./lib/styles/*')
|
||||||
|
expect(themeManifest.files).toContain('lib/styles')
|
||||||
|
})
|
||||||
|
|
||||||
it('imports every sheet from the theme package and each one exists', () => {
|
it('imports every sheet from the theme package and each one exists', () => {
|
||||||
expect(imports.length).toBeGreaterThan(0)
|
expect(imports.length).toBeGreaterThan(0)
|
||||||
for (const specifier of imports) {
|
for (const specifier of imports) {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ const root = resolve(import.meta.dirname, '..')
|
|||||||
const workspaceGlobs = [
|
const workspaceGlobs = [
|
||||||
{ dir: 'vendor', depth: 1 },
|
{ dir: 'vendor', depth: 1 },
|
||||||
{ dir: 'packages', depth: 2 },
|
{ dir: 'packages', depth: 2 },
|
||||||
|
{ dir: 'apps', depth: 1 },
|
||||||
] as const
|
] as const
|
||||||
const vendoredPackages = new Set([
|
const vendoredPackages = new Set([
|
||||||
'cordis',
|
'cordis',
|
||||||
@@ -28,6 +29,10 @@ const vendoredPackages = new Set([
|
|||||||
])
|
])
|
||||||
|
|
||||||
const localArtifactDirs = new Set(['node_modules'])
|
const localArtifactDirs = new Set(['node_modules'])
|
||||||
|
const appPackageFiles: Readonly<Record<string, readonly string[]>> = {
|
||||||
|
'@deepseek-ai/dsh': ['lib/*.js', 'config', 'src'],
|
||||||
|
'@deepseek-ai/dsh-frontend': ['dist'],
|
||||||
|
}
|
||||||
|
|
||||||
/** The subset of package.json fields this constraint check cares about. */
|
/** The subset of package.json fields this constraint check cares about. */
|
||||||
interface PackageManifest {
|
interface PackageManifest {
|
||||||
@@ -96,6 +101,7 @@ function workspaceManifests(): WorkspaceManifest[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const packageFileExtras: Readonly<Record<string, readonly string[]>> = {
|
const packageFileExtras: Readonly<Record<string, readonly string[]>> = {
|
||||||
|
'@deepseek-ai/dsh-client-ui-theme': ['lib/styles'],
|
||||||
'@deepseek-ai/dsh-helper': ['lib/assets'],
|
'@deepseek-ai/dsh-helper': ['lib/assets'],
|
||||||
'@deepseek-ai/dsh-pty-local': ['scripts/ensure-spawn-helper.mjs'],
|
'@deepseek-ai/dsh-pty-local': ['scripts/ensure-spawn-helper.mjs'],
|
||||||
'@deepseek-ai/dsh-scripts': [
|
'@deepseek-ai/dsh-scripts': [
|
||||||
@@ -165,7 +171,16 @@ function checkWorkspace({ dir, manifest }: WorkspaceManifest): string[] {
|
|||||||
return errors
|
return errors
|
||||||
}
|
}
|
||||||
|
|
||||||
if (manifest.name?.startsWith('@deepseek-ai/dsh-') && manifest.name !== '@deepseek-ai/dsh-root') {
|
if (dir.startsWith('apps/') && manifest.name?.startsWith('@deepseek-ai/')) {
|
||||||
|
const expectedFiles = appPackageFiles[manifest.name]
|
||||||
|
if (expectedFiles === undefined) {
|
||||||
|
errors.push(`${label}: app package has no publication files policy`)
|
||||||
|
} else if (!sameStringList(manifest.files, expectedFiles)) {
|
||||||
|
errors.push(`${label}: package.json files must be ${JSON.stringify(expectedFiles)}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dir.startsWith('packages/') && manifest.name?.startsWith('@deepseek-ai/dsh-')) {
|
||||||
const peer = manifest.peerDependencies?.cordis
|
const peer = manifest.peerDependencies?.cordis
|
||||||
const dev = manifest.devDependencies?.cordis
|
const dev = manifest.devDependencies?.cordis
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user