@sequenceholdings/artifact-studio 0.2.3 → 0.2.4
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/VERSION-PIN.md +9 -2
- package/dist/atlas-ui-package-contract.d.ts +7 -0
- package/dist/atlas-ui-package-contract.js +60 -0
- package/dist/build-provenance.d.ts +6 -1
- package/dist/build-provenance.js +2 -1
- package/dist/build.js +19 -7
- package/dist/resolved-stylesheets.d.ts +21 -0
- package/dist/resolved-stylesheets.js +33 -0
- package/dist/templates/react-vite/package.json +2 -2
- package/package.json +3 -3
- package/templates/react-vite/package.json +2 -2
package/VERSION-PIN.md
CHANGED
|
@@ -4,6 +4,12 @@ A (re)built Artifact Studio app gets whatever `@sequenceholdings/atlas-ui` the
|
|
|
4
4
|
**building CLI** carries — not a semver the artifact's own `package.json`
|
|
5
5
|
declares.
|
|
6
6
|
|
|
7
|
+
Artifact Studio 0.2.4 (Studio CLI 0.1.30) pins Atlas UI 3.1.1 exactly.
|
|
8
|
+
Ordinary builds now use its canonical, mode-aware `tokens.css`. Rebuilding an
|
|
9
|
+
existing artifact adopts this toolchain; previously uploaded immutable bundles
|
|
10
|
+
keep their original CSS. Migrate retired numbered black/white utilities to
|
|
11
|
+
semantic roles and verify a preview before activating a rebuilt artifact.
|
|
12
|
+
|
|
7
13
|
## What this means
|
|
8
14
|
|
|
9
15
|
`shared/services/artifact-studio/src/build.ts` force-aliases platform peers via
|
|
@@ -51,7 +57,8 @@ temporary forwarding aliases; the compiler normalizes their source imports to on
|
|
|
51
57
|
canonical layer and reports a migration warning. An explicit
|
|
52
58
|
`seq-studio artifact dev --link <atlas-ui-package-dir>` preview additionally
|
|
53
59
|
reports retired numbered black/white opacity utilities and uncertain dynamic
|
|
54
|
-
class construction
|
|
55
|
-
|
|
60
|
+
class construction. Legacy stylesheet aliases normalize to canonical tokens;
|
|
61
|
+
they do not restore retired utility scales. The runtime forwards brand variables
|
|
62
|
+
independently of `data-tokens`.
|
|
56
63
|
Import `tokens.css` for standalone/`vite dev` compatibility. **Do not** import
|
|
57
64
|
`tokens.v2.tenants.css`.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare class AtlasUiPackageContractError extends Error {
|
|
2
|
+
constructor(message: string);
|
|
3
|
+
}
|
|
4
|
+
export declare function validateAtlasUiTokenStylesheetContract({ packageDir, resolvedTokensCssPath, }: {
|
|
5
|
+
packageDir: string;
|
|
6
|
+
resolvedTokensCssPath: string;
|
|
7
|
+
}): string;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
const ATLAS_UI_PACKAGE = '@sequenceholdings/atlas-ui';
|
|
4
|
+
const TOKENS_CSS_EXPORT = './tokens.css';
|
|
5
|
+
export class AtlasUiPackageContractError extends Error {
|
|
6
|
+
constructor(message) {
|
|
7
|
+
super(`Atlas UI package contract error: ${message}`);
|
|
8
|
+
this.name = 'AtlasUiPackageContractError';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
function isRecord(value) {
|
|
12
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
13
|
+
}
|
|
14
|
+
function readExportTarget(value) {
|
|
15
|
+
if (typeof value === 'string')
|
|
16
|
+
return value;
|
|
17
|
+
if (isRecord(value)) {
|
|
18
|
+
for (const key of ['style', 'default', 'import']) {
|
|
19
|
+
const target = value[key];
|
|
20
|
+
if (typeof target === 'string')
|
|
21
|
+
return target;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
export function validateAtlasUiTokenStylesheetContract({ packageDir, resolvedTokensCssPath, }) {
|
|
27
|
+
const packageJsonPath = resolve(packageDir, 'package.json');
|
|
28
|
+
let parsed;
|
|
29
|
+
try {
|
|
30
|
+
parsed = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
throw new AtlasUiPackageContractError(`unable to read ${packageJsonPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
34
|
+
}
|
|
35
|
+
if (!isRecord(parsed)) {
|
|
36
|
+
throw new AtlasUiPackageContractError(`${packageJsonPath} is not a JSON object`);
|
|
37
|
+
}
|
|
38
|
+
if (parsed.name !== ATLAS_UI_PACKAGE) {
|
|
39
|
+
throw new AtlasUiPackageContractError(`${packageJsonPath} must be ${ATLAS_UI_PACKAGE}, got ${String(parsed.name)}`);
|
|
40
|
+
}
|
|
41
|
+
const exportsMap = parsed.exports;
|
|
42
|
+
if (!isRecord(exportsMap)) {
|
|
43
|
+
throw new AtlasUiPackageContractError(`${ATLAS_UI_PACKAGE} package.json must declare an exports map`);
|
|
44
|
+
}
|
|
45
|
+
const exportTarget = readExportTarget(exportsMap[TOKENS_CSS_EXPORT]);
|
|
46
|
+
if (!exportTarget) {
|
|
47
|
+
throw new AtlasUiPackageContractError(`${ATLAS_UI_PACKAGE} must export ${TOKENS_CSS_EXPORT} to a CSS file included in the package`);
|
|
48
|
+
}
|
|
49
|
+
const declaredPath = resolve(packageDir, exportTarget);
|
|
50
|
+
if (!existsSync(declaredPath)) {
|
|
51
|
+
throw new AtlasUiPackageContractError(`${ATLAS_UI_PACKAGE}${TOKENS_CSS_EXPORT} points to ${exportTarget}, but ${declaredPath} does not exist`);
|
|
52
|
+
}
|
|
53
|
+
if (!existsSync(resolvedTokensCssPath)) {
|
|
54
|
+
throw new AtlasUiPackageContractError(`${ATLAS_UI_PACKAGE}${TOKENS_CSS_EXPORT} resolved to ${resolvedTokensCssPath}, but that file does not exist`);
|
|
55
|
+
}
|
|
56
|
+
if (resolve(resolvedTokensCssPath) !== declaredPath) {
|
|
57
|
+
throw new AtlasUiPackageContractError(`${ATLAS_UI_PACKAGE}${TOKENS_CSS_EXPORT} export target (${declaredPath}) and build resolver (${resolvedTokensCssPath}) disagree`);
|
|
58
|
+
}
|
|
59
|
+
return declaredPath;
|
|
60
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ResolvedStylesheet } from './resolved-stylesheets.js';
|
|
1
2
|
import type { ArtifactStudioPeerVersions } from './peer-versions.js';
|
|
2
3
|
import type { AtlasUiResolvedTokenSelection } from './atlas-ui-css-plugin.js';
|
|
3
4
|
export declare const ARTIFACT_BUILD_PROVENANCE_VERSION = 1;
|
|
@@ -17,6 +18,7 @@ export interface ArtifactTokenResolution {
|
|
|
17
18
|
export interface ObservedBuildEvidence {
|
|
18
19
|
schemaVersion: typeof ARTIFACT_BUILD_PROVENANCE_VERSION;
|
|
19
20
|
channel: 'active' | 'preview';
|
|
21
|
+
/** `cliVersion` is retained for historical records and identifies Artifact Studio. */
|
|
20
22
|
toolchain: {
|
|
21
23
|
cliVersion: string;
|
|
22
24
|
selection: 'published' | 'linked';
|
|
@@ -29,6 +31,8 @@ export interface ObservedBuildEvidence {
|
|
|
29
31
|
modelVersion: 1;
|
|
30
32
|
entries: ArtifactTokenResolution[];
|
|
31
33
|
};
|
|
34
|
+
/** CSS modules that actually contribute to this artifact's visible cascade. */
|
|
35
|
+
stylesheets: ResolvedStylesheet[];
|
|
32
36
|
sourceRevision: ArtifactSourceRevision;
|
|
33
37
|
}
|
|
34
38
|
/**
|
|
@@ -37,7 +41,7 @@ export interface ObservedBuildEvidence {
|
|
|
37
41
|
* migration generation; future canonical token entry points need no schema
|
|
38
42
|
* change.
|
|
39
43
|
*/
|
|
40
|
-
export declare function createObservedBuildEvidence({ atlasUiDir, atlasUiDist, atlasUiTokens, channel, linked, peerVersions, sourceRevision, tokenSelections }: {
|
|
44
|
+
export declare function createObservedBuildEvidence({ atlasUiDir, atlasUiDist, atlasUiTokens, channel, linked, peerVersions, sourceRevision, stylesheets, tokenSelections }: {
|
|
41
45
|
atlasUiDir: string;
|
|
42
46
|
atlasUiDist: string;
|
|
43
47
|
/** Exact tokens.css alias target; releases and linked candidates use different layouts. */
|
|
@@ -46,5 +50,6 @@ export declare function createObservedBuildEvidence({ atlasUiDir, atlasUiDist, a
|
|
|
46
50
|
linked: boolean;
|
|
47
51
|
peerVersions: ArtifactStudioPeerVersions;
|
|
48
52
|
sourceRevision: ArtifactSourceRevision;
|
|
53
|
+
stylesheets?: ResolvedStylesheet[];
|
|
49
54
|
tokenSelections: readonly AtlasUiResolvedTokenSelection[];
|
|
50
55
|
}): ObservedBuildEvidence;
|
package/dist/build-provenance.js
CHANGED
|
@@ -14,7 +14,7 @@ function contentIdentity(entries) {
|
|
|
14
14
|
* migration generation; future canonical token entry points need no schema
|
|
15
15
|
* change.
|
|
16
16
|
*/
|
|
17
|
-
export function createObservedBuildEvidence({ atlasUiDir, atlasUiDist, atlasUiTokens, channel, linked, peerVersions, sourceRevision, tokenSelections }) {
|
|
17
|
+
export function createObservedBuildEvidence({ atlasUiDir, atlasUiDist, atlasUiTokens, channel, linked, peerVersions, sourceRevision, stylesheets = [], tokenSelections }) {
|
|
18
18
|
const knownTargets = new Map([
|
|
19
19
|
['@sequenceholdings/atlas-ui/tokens.css', { filePath: atlasUiTokens }],
|
|
20
20
|
['@sequenceholdings/atlas-ui/tokens.v2.css', { filePath: `${atlasUiDir}/tokens.v2.css` }],
|
|
@@ -39,6 +39,7 @@ export function createObservedBuildEvidence({ atlasUiDir, atlasUiDist, atlasUiTo
|
|
|
39
39
|
toolchain: { cliVersion: peerVersions.cliVersion, selection: linked ? 'linked' : 'published' },
|
|
40
40
|
atlasUi: { version: peerVersions.atlasUiVersion, contentHash: contentIdentity(identityEntries) },
|
|
41
41
|
tokenResolution: { modelVersion: 1, entries },
|
|
42
|
+
stylesheets,
|
|
42
43
|
sourceRevision,
|
|
43
44
|
};
|
|
44
45
|
}
|
package/dist/build.js
CHANGED
|
@@ -4,7 +4,9 @@ import { createRequire } from 'node:module';
|
|
|
4
4
|
import { dirname, relative, resolve } from 'node:path';
|
|
5
5
|
import { build as viteBuild } from 'vite';
|
|
6
6
|
import { atlasUiCssResolverPlugin, collectAtlasUiResolvedTokenSelections } from './atlas-ui-css-plugin.js';
|
|
7
|
+
import { validateAtlasUiTokenStylesheetContract } from './atlas-ui-package-contract.js';
|
|
7
8
|
import { createObservedBuildEvidence } from './build-provenance.js';
|
|
9
|
+
import { collectResolvedStylesheets } from './resolved-stylesheets.js';
|
|
8
10
|
import { sha256Hex } from './hash.js';
|
|
9
11
|
import { isArtifactIgnoredPath } from './artifact-ignore.js';
|
|
10
12
|
import { readArtifactStudioSource } from './project.js';
|
|
@@ -37,7 +39,8 @@ const atlasUiDist = resolve(atlasUiDir, 'dist');
|
|
|
37
39
|
*/
|
|
38
40
|
export function resolveAtlasUiTokensPath(packageDir) {
|
|
39
41
|
const rootEntry = resolve(packageDir, 'tokens.css');
|
|
40
|
-
|
|
42
|
+
const resolvedTokensCssPath = existsSync(rootEntry) ? rootEntry : resolve(packageDir, 'dist', 'tokens.css');
|
|
43
|
+
return validateAtlasUiTokenStylesheetContract({ packageDir, resolvedTokensCssPath });
|
|
41
44
|
}
|
|
42
45
|
const atlasUiTokens = resolveAtlasUiTokensPath(atlasUiDir);
|
|
43
46
|
// The shared Lattice form renderer is aliased the same way as atlas-ui (it is
|
|
@@ -156,20 +159,28 @@ export async function buildArtifactStudioProject(rootDir, { candidateTokenCompat
|
|
|
156
159
|
const chunks = collectRuntimeChunks(output);
|
|
157
160
|
const sourceMap = fitSourceMapForDeploy(collectSourceMap(output));
|
|
158
161
|
const peerVersions = resolveArtifactStudioPeerVersions();
|
|
162
|
+
const cssModules = [...transformedCssModules].map(([id, code]) => ({ id, code }));
|
|
163
|
+
const tokenSelections = collectAtlasUiResolvedTokenSelections({
|
|
164
|
+
cssModules,
|
|
165
|
+
atlasUiDir: selectedAtlasUiDir,
|
|
166
|
+
atlasUiDist: selectedAtlasUiDist,
|
|
167
|
+
formRendererDist,
|
|
168
|
+
});
|
|
159
169
|
const observedBuildEvidence = createObservedBuildEvidence({
|
|
160
170
|
atlasUiDir: selectedAtlasUiDir,
|
|
161
171
|
atlasUiDist: selectedAtlasUiDist,
|
|
162
172
|
atlasUiTokens: selectedAtlasUiTokens,
|
|
163
173
|
channel: 'active',
|
|
174
|
+
stylesheets: collectResolvedStylesheets({
|
|
175
|
+
root,
|
|
176
|
+
atlasUiTokens: selectedAtlasUiTokens,
|
|
177
|
+
cssModules,
|
|
178
|
+
tokenSelections,
|
|
179
|
+
}),
|
|
164
180
|
linked: atlasUiPackageDir !== undefined,
|
|
165
181
|
peerVersions,
|
|
166
182
|
sourceRevision: { commit: null, branch: null, dirty: null },
|
|
167
|
-
tokenSelections
|
|
168
|
-
cssModules: [...transformedCssModules].map(([id, code]) => ({ id, code })),
|
|
169
|
-
atlasUiDir: selectedAtlasUiDir,
|
|
170
|
-
atlasUiDist: selectedAtlasUiDist,
|
|
171
|
-
formRendererDist,
|
|
172
|
-
}),
|
|
183
|
+
tokenSelections,
|
|
173
184
|
});
|
|
174
185
|
return {
|
|
175
186
|
manifest: source.manifest,
|
|
@@ -187,6 +198,7 @@ export async function buildArtifactStudioProject(rootDir, { candidateTokenCompat
|
|
|
187
198
|
toolchain: observedBuildEvidence.toolchain,
|
|
188
199
|
atlasUi: observedBuildEvidence.atlasUi,
|
|
189
200
|
tokenResolution: observedBuildEvidence.tokenResolution,
|
|
201
|
+
stylesheets: observedBuildEvidence.stylesheets,
|
|
190
202
|
},
|
|
191
203
|
};
|
|
192
204
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { AtlasUiResolvedTokenSelection } from './atlas-ui-css-plugin.js';
|
|
2
|
+
export interface ResolvedStylesheet {
|
|
3
|
+
/** Stable display identifier, never an absolute local path. */
|
|
4
|
+
identifier: string;
|
|
5
|
+
contentHash: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Records CSS modules Vite actually transformed for the artifact, plus the
|
|
9
|
+
* canonical Atlas UI sheet selected by the resolver. It deliberately excludes
|
|
10
|
+
* JavaScript/TypeScript and `?raw` imports: neither participates in CSS
|
|
11
|
+
* cascade order.
|
|
12
|
+
*/
|
|
13
|
+
export declare function collectResolvedStylesheets({ root, cssModules, tokenSelections, atlasUiTokens, }: {
|
|
14
|
+
root: string;
|
|
15
|
+
cssModules: readonly {
|
|
16
|
+
id: string;
|
|
17
|
+
code: string;
|
|
18
|
+
}[];
|
|
19
|
+
tokenSelections: readonly AtlasUiResolvedTokenSelection[];
|
|
20
|
+
atlasUiTokens: string;
|
|
21
|
+
}): ResolvedStylesheet[];
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { relative } from 'node:path';
|
|
3
|
+
import { sha256Hex } from './hash.js';
|
|
4
|
+
const MAX_RECORDED_STYLESHEETS = 100;
|
|
5
|
+
/**
|
|
6
|
+
* Records CSS modules Vite actually transformed for the artifact, plus the
|
|
7
|
+
* canonical Atlas UI sheet selected by the resolver. It deliberately excludes
|
|
8
|
+
* JavaScript/TypeScript and `?raw` imports: neither participates in CSS
|
|
9
|
+
* cascade order.
|
|
10
|
+
*/
|
|
11
|
+
export function collectResolvedStylesheets({ root, cssModules, tokenSelections, atlasUiTokens, }) {
|
|
12
|
+
const stylesheets = new Map();
|
|
13
|
+
if (tokenSelections.some((selection) => selection.specifier === '@sequenceholdings/atlas-ui/tokens.css')) {
|
|
14
|
+
stylesheets.set('@sequenceholdings/atlas-ui/tokens.css', {
|
|
15
|
+
identifier: '@sequenceholdings/atlas-ui/tokens.css',
|
|
16
|
+
contentHash: sha256Hex(readFileSync(atlasUiTokens, 'utf8')),
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
for (const { id, code } of cssModules) {
|
|
20
|
+
if (id.includes('?'))
|
|
21
|
+
continue;
|
|
22
|
+
const identifier = relative(root, id).replaceAll('\\', '/');
|
|
23
|
+
if (!identifier.endsWith('.css') || identifier === '' || identifier.startsWith('../'))
|
|
24
|
+
continue;
|
|
25
|
+
stylesheets.set(identifier, { identifier, contentHash: sha256Hex(code) });
|
|
26
|
+
}
|
|
27
|
+
// The deployment API accepts at most 100 evidence records. Evidence is
|
|
28
|
+
// observational, so it must never turn an otherwise valid build into a
|
|
29
|
+
// failed deployment merely because Vite transformed many stylesheets.
|
|
30
|
+
return [...stylesheets.values()]
|
|
31
|
+
.sort((left, right) => left.identifier.localeCompare(right.identifier))
|
|
32
|
+
.slice(0, MAX_RECORDED_STYLESHEETS);
|
|
33
|
+
}
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {},
|
|
11
11
|
"devDependencies": {
|
|
12
|
-
"@sequenceholdings/artifact-studio": "^0.2.
|
|
13
|
-
"@sequenceholdings/atlas-ui": "^
|
|
12
|
+
"@sequenceholdings/artifact-studio": "^0.2.4",
|
|
13
|
+
"@sequenceholdings/atlas-ui": "^3.1.1",
|
|
14
14
|
"@tailwindcss/postcss": "^4.2.2",
|
|
15
15
|
"@tailwindcss/vite": "^4.2.2",
|
|
16
16
|
"@tanstack/react-query": "^4.36.1",
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"publishConfig": {
|
|
10
10
|
"access": "public"
|
|
11
11
|
},
|
|
12
|
-
"version": "0.2.
|
|
12
|
+
"version": "0.2.4",
|
|
13
13
|
"description": "SDK types and CLI library for building Artifact Studio apps. Driven via `seq-studio artifact <sub>` (@sequenceholdings/studio-cli), which runs the `./cli` runCli export.",
|
|
14
14
|
"type": "module",
|
|
15
15
|
"exports": {
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"VERSION-PIN.md"
|
|
73
73
|
],
|
|
74
74
|
"dependencies": {
|
|
75
|
-
"@sequenceholdings/atlas-ui": "
|
|
75
|
+
"@sequenceholdings/atlas-ui": "3.1.1",
|
|
76
76
|
"@tailwindcss/postcss": "^4.1.8",
|
|
77
77
|
"@tailwindcss/vite": "^4.1.8",
|
|
78
78
|
"@tanstack/react-query": "^4.36.1",
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
"tw-animate-css": "^1.4.0",
|
|
86
86
|
"vite": "8.0.16",
|
|
87
87
|
"zod": "^4.1.13",
|
|
88
|
-
"@sequenceholdings/lattice-form-renderer": "0.1.
|
|
88
|
+
"@sequenceholdings/lattice-form-renderer": "0.1.3"
|
|
89
89
|
},
|
|
90
90
|
"devDependencies": {
|
|
91
91
|
"@types/js-yaml": "^4.0.9",
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {},
|
|
11
11
|
"devDependencies": {
|
|
12
|
-
"@sequenceholdings/artifact-studio": "^0.2.
|
|
13
|
-
"@sequenceholdings/atlas-ui": "^
|
|
12
|
+
"@sequenceholdings/artifact-studio": "^0.2.4",
|
|
13
|
+
"@sequenceholdings/atlas-ui": "^3.1.1",
|
|
14
14
|
"@tailwindcss/postcss": "^4.2.2",
|
|
15
15
|
"@tailwindcss/vite": "^4.2.2",
|
|
16
16
|
"@tanstack/react-query": "^4.36.1",
|