@sequenceholdings/artifact-studio 0.2.5 → 0.3.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 +35 -0
- package/VERSION-PIN.md +14 -3
- package/dist/api.d.ts +11 -1
- package/dist/api.js +26 -9
- package/dist/atlas-ui-css-plugin.d.ts +11 -7
- package/dist/atlas-ui-css-plugin.js +38 -10
- package/dist/build.d.ts +2 -2
- package/dist/build.js +14 -6
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +108 -37
- package/dist/dev-link.d.ts +1 -1
- package/dist/dev-link.js +2 -1
- package/dist/gateway/admission.d.ts +55 -0
- package/dist/gateway/admission.js +132 -0
- package/dist/gateway/control.d.ts +91 -0
- package/dist/gateway/control.js +113 -0
- package/dist/gateway/hosted-proxy.d.ts +36 -0
- package/dist/gateway/hosted-proxy.js +347 -0
- package/dist/gateway/release-admission.d.ts +23 -0
- package/dist/gateway/release-admission.js +259 -0
- package/dist/gateway/server.d.ts +29 -0
- package/dist/gateway/server.js +298 -0
- package/dist/gateway/session.d.ts +71 -0
- package/dist/gateway/session.js +143 -0
- package/dist/gateway/usage.d.ts +37 -0
- package/dist/gateway/usage.js +46 -0
- package/dist/gateway-main.d.ts +1 -0
- package/dist/gateway-main.js +84 -0
- package/dist/git-clone.d.ts +23 -1
- package/dist/git-clone.js +32 -15
- package/dist/manifest-next.d.ts +217 -0
- package/dist/manifest-next.js +120 -0
- package/dist/manifest-static.d.ts +76 -0
- package/dist/manifest-static.js +124 -0
- package/dist/manifest.d.ts +124 -19
- package/dist/manifest.js +12 -118
- package/dist/next/bridge.d.ts +47 -0
- package/dist/next/bridge.js +229 -0
- package/dist/next/browser-logs.d.ts +7 -0
- package/dist/next/browser-logs.js +51 -0
- package/dist/next/browser.d.ts +6 -0
- package/dist/next/browser.js +57 -0
- package/dist/next/protocol.d.ts +73 -0
- package/dist/next/protocol.js +56 -0
- package/dist/next/release.d.ts +15 -0
- package/dist/next/release.js +46 -0
- package/dist/next/requests.d.ts +15 -0
- package/dist/next/requests.js +59 -0
- package/dist/next/routes.d.ts +4 -0
- package/dist/next/routes.js +21 -0
- package/dist/next/streams.d.ts +16 -0
- package/dist/next/streams.js +132 -0
- package/dist/next/theme.d.ts +10 -0
- package/dist/next/theme.js +45 -0
- package/dist/next/transport.d.ts +15 -0
- package/dist/next/transport.js +13 -0
- package/dist/next-build.d.ts +29 -0
- package/dist/next-build.js +129 -0
- package/dist/next-cache/adapter-runtime.d.ts +51 -0
- package/dist/next-cache/adapter-runtime.js +73 -0
- package/dist/next-cache/component-handler.d.ts +3 -0
- package/dist/next-cache/component-handler.js +10 -0
- package/dist/next-cache/components.d.ts +20 -0
- package/dist/next-cache/components.js +113 -0
- package/dist/next-cache/config.d.ts +9 -0
- package/dist/next-cache/config.js +78 -0
- package/dist/next-cache/incremental-handler.d.ts +18 -0
- package/dist/next-cache/incremental-handler.js +17 -0
- package/dist/next-cache/incremental.d.ts +27 -0
- package/dist/next-cache/incremental.js +99 -0
- package/dist/next-cache/index.d.ts +18 -0
- package/dist/next-cache/index.js +16 -0
- package/dist/next-cache/memory-store.d.ts +27 -0
- package/dist/next-cache/memory-store.js +118 -0
- package/dist/next-cache/redis-scripts.d.ts +3 -0
- package/dist/next-cache/redis-scripts.js +85 -0
- package/dist/next-cache/redis-store.d.ts +18 -0
- package/dist/next-cache/redis-store.js +56 -0
- package/dist/next-cache/runtime.d.ts +29 -0
- package/dist/next-cache/runtime.js +63 -0
- package/dist/next-cache/serialization.d.ts +39 -0
- package/dist/next-cache/serialization.js +333 -0
- package/dist/next-cache/store.d.ts +54 -0
- package/dist/next-cache/store.js +45 -0
- package/dist/next-cache/valkey-transport.d.ts +52 -0
- package/dist/next-cache/valkey-transport.js +189 -0
- package/dist/next-dev-control.d.ts +48 -0
- package/dist/next-dev-control.js +63 -0
- package/dist/next-dev-process.d.ts +17 -0
- package/dist/next-dev-process.js +110 -0
- package/dist/next-dev.d.ts +12 -0
- package/dist/next-dev.js +267 -0
- package/dist/next-image-config.d.ts +9 -0
- package/dist/next-image-config.js +101 -0
- package/dist/next-project.d.ts +22 -0
- package/dist/next-project.js +64 -0
- package/dist/next-public-fonts-local.d.ts +7 -0
- package/dist/next-public-fonts-local.js +64 -0
- package/dist/next-public-fonts.d.ts +13 -0
- package/dist/next-public-fonts.js +49 -0
- package/dist/next-source-hash.d.ts +14 -0
- package/dist/next-source-hash.js +18 -0
- package/dist/next-source.d.ts +35 -0
- package/dist/next-source.js +155 -0
- package/dist/next.d.ts +9 -0
- package/dist/next.js +5 -0
- package/dist/project.d.ts +3 -0
- package/dist/project.js +9 -1
- package/dist/runtime-contracts.d.ts +229 -0
- package/dist/runtime-contracts.js +224 -0
- package/dist/sdk.d.ts +420 -1
- package/dist/sdk.js +35 -0
- package/dist/server/broker-contract.d.ts +68 -0
- package/dist/server/broker-contract.js +33 -0
- package/dist/server/client.d.ts +67 -0
- package/dist/server/client.js +159 -0
- package/dist/server/logger.d.ts +26 -0
- package/dist/server/logger.js +24 -0
- package/dist/server/release-forms.d.ts +13 -0
- package/dist/server/release-forms.js +124 -0
- package/dist/server/request-context.d.ts +74 -0
- package/dist/server/request-context.js +103 -0
- package/dist/server/runtime-config.d.ts +53 -0
- package/dist/server/runtime-config.js +64 -0
- package/dist/server.d.ts +8 -0
- package/dist/server.js +4 -0
- package/dist/templates/nextjs/.artifactignore +14 -0
- package/dist/templates/nextjs/README.md +151 -0
- package/dist/templates/nextjs/app/about/page.tsx +26 -0
- package/dist/templates/nextjs/app/actions.ts +18 -0
- package/dist/templates/nextjs/app/api/health/route.ts +6 -0
- package/dist/templates/nextjs/app/components/counter.tsx +19 -0
- package/dist/templates/nextjs/app/components/greeting-form.tsx +38 -0
- package/dist/templates/nextjs/app/globals.css +4 -0
- package/dist/templates/nextjs/app/layout.tsx +27 -0
- package/dist/templates/nextjs/app/page.tsx +51 -0
- package/dist/templates/nextjs/app/providers.tsx +107 -0
- package/dist/templates/nextjs/artifact.bundle.yml +55 -0
- package/dist/templates/nextjs/next.config.mjs +27 -0
- package/dist/templates/nextjs/package.json +32 -0
- package/dist/templates/nextjs/pnpm-workspace.yaml +8 -0
- package/dist/templates/nextjs/postcss.config.mjs +5 -0
- package/dist/templates/nextjs/tsconfig.json +20 -0
- package/dist/templates/react-vite/artifact.bundle.yml +0 -1
- package/dist/templates/react-vite/package.json +1 -1
- package/dist/tunnel/broker.d.ts +75 -0
- package/dist/tunnel/broker.js +451 -0
- package/dist/tunnel/client.d.ts +22 -0
- package/dist/tunnel/client.js +177 -0
- package/dist/tunnel/index.d.ts +6 -0
- package/dist/tunnel/index.js +4 -0
- package/dist/tunnel/io.d.ts +33 -0
- package/dist/tunnel/io.js +108 -0
- package/dist/tunnel/peer.d.ts +25 -0
- package/dist/tunnel/peer.js +147 -0
- package/dist/tunnel/protocol.d.ts +69 -0
- package/dist/tunnel/protocol.js +196 -0
- package/dist/tunnel/redis-ownership.d.ts +38 -0
- package/dist/tunnel/redis-ownership.js +100 -0
- package/dist/tunnel/redis-socket.d.ts +13 -0
- package/dist/tunnel/redis-socket.js +48 -0
- package/dist/tunnel/redis-types.d.ts +70 -0
- package/dist/tunnel/redis-types.js +9 -0
- package/dist/tunnel/redis.d.ts +53 -0
- package/dist/tunnel/redis.js +391 -0
- package/dist/tunnel/transport.d.ts +17 -0
- package/dist/tunnel/transport.js +1 -0
- package/package.json +68 -4
- package/templates/nextjs/.artifactignore +14 -0
- package/templates/nextjs/README.md +151 -0
- package/templates/nextjs/app/about/page.tsx +26 -0
- package/templates/nextjs/app/actions.ts +18 -0
- package/templates/nextjs/app/api/health/route.ts +6 -0
- package/templates/nextjs/app/components/counter.tsx +19 -0
- package/templates/nextjs/app/components/greeting-form.tsx +38 -0
- package/templates/nextjs/app/globals.css +4 -0
- package/templates/nextjs/app/layout.tsx +27 -0
- package/templates/nextjs/app/page.tsx +51 -0
- package/templates/nextjs/app/providers.tsx +107 -0
- package/templates/nextjs/artifact.bundle.yml +55 -0
- package/templates/nextjs/next.config.mjs +27 -0
- package/templates/nextjs/package.json +32 -0
- package/templates/nextjs/pnpm-workspace.yaml +8 -0
- package/templates/nextjs/postcss.config.mjs +5 -0
- package/templates/nextjs/tsconfig.json +20 -0
- package/templates/react-vite/artifact.bundle.yml +0 -1
- package/templates/react-vite/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Artifact Studio SDK
|
|
2
|
+
|
|
3
|
+
`@sequenceholdings/artifact-studio` exposes the host-provided `seq` client. Runtime
|
|
4
|
+
requests use the current user's normal permissions.
|
|
5
|
+
|
|
6
|
+
Artifact Studio is a workflow-agnostic platform primitive. The host, SDK, and
|
|
7
|
+
deployer provide generic application capabilities; each deployed artifact owns
|
|
8
|
+
its product behavior. Primitive code must not branch on an artifact ID or import
|
|
9
|
+
an application's services. See [Platform primitive boundaries](../../../docs/platform/platform-primitives.md).
|
|
10
|
+
|
|
11
|
+
## Grouping calls into a trace
|
|
12
|
+
|
|
13
|
+
The Artifact host supplies tracing context automatically for supported platform
|
|
14
|
+
requests. Use an explicit action scope to correlate several calls from one UI
|
|
15
|
+
action and supply a readable intent key:
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { withTraceAction } from '@sequenceholdings/artifact-studio'
|
|
19
|
+
|
|
20
|
+
await withTraceAction(
|
|
21
|
+
{ key: 'application.refresh' },
|
|
22
|
+
async ({ api, functions }) => {
|
|
23
|
+
await functions.invoke('my-function', { refresh: true })
|
|
24
|
+
await api.get('/api/my-application/summary')
|
|
25
|
+
},
|
|
26
|
+
)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Use a stable operation label, never an identifier, customer value or payload. Each
|
|
30
|
+
scope gets its own correlation ID, so concurrent actions remain separate. The
|
|
31
|
+
helper scopes JSON `api.fetch/get/post/put/patch/delete` and `functions.invoke`;
|
|
32
|
+
streaming and file-transfer helpers retain their ordinary host tracing behavior.
|
|
33
|
+
Tracing does not grant permissions, change service-account behavior or guarantee
|
|
34
|
+
that every transport is instrumented. Traces availability depends on the deployed
|
|
35
|
+
platform version and your app/resource permissions.
|
package/VERSION-PIN.md
CHANGED
|
@@ -4,12 +4,19 @@ 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.
|
|
7
|
+
Artifact Studio 0.2.7 (Studio CLI 0.1.36) pins Atlas UI 3.3.0 exactly.
|
|
8
8
|
Ordinary builds now use its canonical, mode-aware `tokens.css`. Rebuilding an
|
|
9
9
|
existing artifact adopts this toolchain; previously uploaded immutable bundles
|
|
10
10
|
keep their original CSS. Migrate retired numbered black/white utilities to
|
|
11
11
|
semantic roles and verify a preview before activating a rebuilt artifact.
|
|
12
12
|
|
|
13
|
+
Artifact Studio 0.3.0 (Studio CLI 0.2.0) adds the opt-in Next.js runtime. The
|
|
14
|
+
static compiler continues to pin Atlas UI 3.3.0. Next.js applications own their
|
|
15
|
+
React 19 dependencies and use the `/next` client boundary that Atlas UI 3.4.0
|
|
16
|
+
introduces; they do not inherit the static compiler's aliases. The new packages must be published
|
|
17
|
+
before a fresh external Next.js scaffold can be installed. A local candidate
|
|
18
|
+
build is not evidence of registry availability.
|
|
19
|
+
|
|
13
20
|
## What this means
|
|
14
21
|
|
|
15
22
|
`shared/services/artifact-studio/src/build.ts` force-aliases platform peers via
|
|
@@ -53,8 +60,12 @@ never claims `no-op` for a deploy that would actually rebuild.
|
|
|
53
60
|
|
|
54
61
|
`tokens.css` is the canonical stylesheet and includes semantic roles plus the
|
|
55
62
|
Tailwind utility bridge. The legacy `tokens.v2.css` and `theme.v2.css` paths are
|
|
56
|
-
temporary forwarding aliases; the compiler normalizes their
|
|
57
|
-
canonical layer and reports a migration warning
|
|
63
|
+
temporary forwarding aliases in current packages; the compiler normalizes their
|
|
64
|
+
source imports to one canonical layer and reports a migration warning only after
|
|
65
|
+
checking that both selected files are forwarding aliases. Older packages carry
|
|
66
|
+
independent styles in those files, so their imports and provenance entries are
|
|
67
|
+
preserved. This prevents CRM spacing and corner utilities from disappearing when
|
|
68
|
+
rebuilding with a split-sheet package. An explicit
|
|
58
69
|
`seq-studio artifact dev --link <atlas-ui-package-dir>` preview additionally
|
|
59
70
|
reports retired numbered black/white opacity utilities and uncertain dynamic
|
|
60
71
|
class construction. Legacy stylesheet aliases normalize to canonical tokens;
|
package/dist/api.d.ts
CHANGED
|
@@ -2,13 +2,23 @@ export interface ApiClientOptions {
|
|
|
2
2
|
baseUrl: string;
|
|
3
3
|
token: string;
|
|
4
4
|
}
|
|
5
|
+
export declare class ArtifactApiError extends Error {
|
|
6
|
+
readonly status: number;
|
|
7
|
+
constructor(message: string, status: number);
|
|
8
|
+
}
|
|
5
9
|
export declare function getJson<T>({ baseUrl, token, path }: ApiClientOptions & {
|
|
6
10
|
path: string;
|
|
7
11
|
}): Promise<T>;
|
|
8
12
|
export declare function getJsonOr404<T>({ baseUrl, token, path }: ApiClientOptions & {
|
|
9
13
|
path: string;
|
|
10
14
|
}): Promise<T | null>;
|
|
11
|
-
export declare function postJson<T>({ baseUrl, token, path, body, }: ApiClientOptions & {
|
|
15
|
+
export declare function postJson<T>({ baseUrl, token, path, body, retry503, signal, }: ApiClientOptions & {
|
|
12
16
|
path: string;
|
|
13
17
|
body?: unknown;
|
|
18
|
+
retry503?: boolean;
|
|
19
|
+
signal?: AbortSignal;
|
|
14
20
|
}): Promise<T>;
|
|
21
|
+
export declare function deleteJson({ baseUrl, token, path, signal }: ApiClientOptions & {
|
|
22
|
+
path: string;
|
|
23
|
+
signal?: AbortSignal;
|
|
24
|
+
}): Promise<void>;
|
package/dist/api.js
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
|
+
import { setTimeout as delay } from 'node:timers/promises';
|
|
1
2
|
import { authenticatedRequestUrl } from './deployment-validation.js';
|
|
3
|
+
export class ArtifactApiError extends Error {
|
|
4
|
+
status;
|
|
5
|
+
constructor(message, status) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.status = status;
|
|
8
|
+
this.name = 'ArtifactApiError';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
2
11
|
const MAX_503_RETRIES = 5;
|
|
3
12
|
const DEFAULT_RETRY_AFTER_SECONDS = 2;
|
|
4
13
|
/**
|
|
@@ -36,19 +45,20 @@ function extraHeaders() {
|
|
|
36
45
|
return {};
|
|
37
46
|
}
|
|
38
47
|
}
|
|
39
|
-
async function fetchWith503Retry(input, init) {
|
|
48
|
+
async function fetchWith503Retry(input, init, maxRetries = MAX_503_RETRIES) {
|
|
40
49
|
let attempt = 0;
|
|
41
50
|
while (true) {
|
|
42
51
|
const response = await fetch(input, init);
|
|
43
|
-
if (response.status !== 503 || attempt >=
|
|
52
|
+
if (response.status !== 503 || attempt >= maxRetries)
|
|
44
53
|
return response;
|
|
45
54
|
const retryAfter = Number(response.headers.get('Retry-After')) || DEFAULT_RETRY_AFTER_SECONDS;
|
|
46
55
|
attempt += 1;
|
|
47
56
|
console.warn(`[seq-studio] backend warming up (503); retrying in ${retryAfter}s (attempt ${attempt}/${MAX_503_RETRIES})`);
|
|
48
|
-
|
|
57
|
+
// An aborted caller (e.g. artifact dev shutting down) must not wait out a Retry-After.
|
|
58
|
+
await delay(retryAfter * 1000, undefined, init.signal ? { signal: init.signal } : undefined);
|
|
49
59
|
}
|
|
50
60
|
}
|
|
51
|
-
async function authenticatedFetch({ baseUrl, init = {}, path, token, }) {
|
|
61
|
+
async function authenticatedFetch({ baseUrl, init = {}, path, token, retry503 = true, }) {
|
|
52
62
|
const url = authenticatedRequestUrl({ baseUrl, path });
|
|
53
63
|
return fetchWith503Retry(url, {
|
|
54
64
|
...init,
|
|
@@ -58,12 +68,12 @@ async function authenticatedFetch({ baseUrl, init = {}, path, token, }) {
|
|
|
58
68
|
...init.headers,
|
|
59
69
|
Authorization: `Bearer ${token}`,
|
|
60
70
|
},
|
|
61
|
-
});
|
|
71
|
+
}, retry503 ? MAX_503_RETRIES : 0);
|
|
62
72
|
}
|
|
63
73
|
export async function getJson({ baseUrl, token, path }) {
|
|
64
74
|
const response = await authenticatedFetch({ baseUrl, token, path });
|
|
65
75
|
if (!response.ok)
|
|
66
|
-
throw new
|
|
76
|
+
throw new ArtifactApiError(await responseError('GET', path, response), response.status);
|
|
67
77
|
return response.json();
|
|
68
78
|
}
|
|
69
79
|
export async function getJsonOr404({ baseUrl, token, path }) {
|
|
@@ -71,24 +81,31 @@ export async function getJsonOr404({ baseUrl, token, path }) {
|
|
|
71
81
|
if (response.status === 404)
|
|
72
82
|
return null;
|
|
73
83
|
if (!response.ok)
|
|
74
|
-
throw new
|
|
84
|
+
throw new ArtifactApiError(await responseError('GET', path, response), response.status);
|
|
75
85
|
return response.json();
|
|
76
86
|
}
|
|
77
|
-
export async function postJson({ baseUrl, token, path, body, }) {
|
|
87
|
+
export async function postJson({ baseUrl, token, path, body, retry503 = true, signal, }) {
|
|
78
88
|
const response = await authenticatedFetch({
|
|
79
89
|
baseUrl,
|
|
80
90
|
token,
|
|
81
91
|
path,
|
|
92
|
+
retry503,
|
|
82
93
|
init: {
|
|
83
94
|
method: 'POST',
|
|
84
95
|
headers: { 'Content-Type': 'application/json' },
|
|
85
96
|
body: body === undefined ? undefined : JSON.stringify(body),
|
|
97
|
+
...(signal ? { signal } : {}),
|
|
86
98
|
},
|
|
87
99
|
});
|
|
88
100
|
if (!response.ok)
|
|
89
|
-
throw new
|
|
101
|
+
throw new ArtifactApiError(await responseError('POST', path, response), response.status);
|
|
90
102
|
return response.json();
|
|
91
103
|
}
|
|
104
|
+
export async function deleteJson({ baseUrl, token, path, signal }) {
|
|
105
|
+
const response = await authenticatedFetch({ baseUrl, token, path, init: { method: 'DELETE', ...(signal ? { signal } : {}) } });
|
|
106
|
+
if (!response.ok)
|
|
107
|
+
throw new ArtifactApiError(await responseError('DELETE', path, response), response.status);
|
|
108
|
+
}
|
|
92
109
|
/**
|
|
93
110
|
* Build an actionable error message from a failed response: which request
|
|
94
111
|
* failed, with what status, and what the server said. A deploy runs several
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import type { Plugin } from 'vite';
|
|
2
2
|
export interface AtlasUiResolvedTokenSelection {
|
|
3
|
-
specifier:
|
|
3
|
+
specifier: string;
|
|
4
4
|
injectedBy: string | null;
|
|
5
5
|
}
|
|
6
|
+
/** Only collapse aliases when the selected package makes them forwarding sheets.
|
|
7
|
+
* Older releases define independent semantic tokens and the Tailwind bridge there.
|
|
8
|
+
*/
|
|
9
|
+
export declare function hasUnifiedAtlasUiTokens(atlasUiDir: string): boolean;
|
|
6
10
|
/**
|
|
7
|
-
*
|
|
8
|
-
* expands
|
|
11
|
+
* For packages with forwarding aliases, collapse imports before Tailwind
|
|
12
|
+
* expands them. The aliases remain package-compatible, but are no longer allowed
|
|
9
13
|
* to create duplicate token layers in an Artifact Studio bundle (DES-437).
|
|
10
14
|
*/
|
|
11
15
|
export declare function normalizeAtlasUiTokenImports(code: string): {
|
|
@@ -13,10 +17,10 @@ export declare function normalizeAtlasUiTokenImports(code: string): {
|
|
|
13
17
|
deprecatedImports: string[];
|
|
14
18
|
};
|
|
15
19
|
/**
|
|
16
|
-
* Evidence mirrors the
|
|
17
|
-
*
|
|
20
|
+
* Evidence mirrors the selected package: split sheets remain separate entries;
|
|
21
|
+
* forwarding aliases are normalized to the canonical entry point.
|
|
18
22
|
*/
|
|
19
|
-
export declare function collectAtlasUiResolvedTokenSelections({ cssModules, }: {
|
|
23
|
+
export declare function collectAtlasUiResolvedTokenSelections({ cssModules, atlasUiDir, }: {
|
|
20
24
|
cssModules: readonly {
|
|
21
25
|
id: string;
|
|
22
26
|
code: string;
|
|
@@ -25,7 +29,7 @@ export declare function collectAtlasUiResolvedTokenSelections({ cssModules, }: {
|
|
|
25
29
|
atlasUiDist: string;
|
|
26
30
|
formRendererDist: string | null;
|
|
27
31
|
}): AtlasUiResolvedTokenSelection[];
|
|
28
|
-
export declare function atlasUiCssResolverPlugin({ atlasUiDir
|
|
32
|
+
export declare function atlasUiCssResolverPlugin({ atlasUiDir, atlasUiDist, formRendererDist, onTransform, }: {
|
|
29
33
|
atlasUiDir: string;
|
|
30
34
|
atlasUiDist: string;
|
|
31
35
|
formRendererDist: string | null;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync } from 'node:fs';
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { dirname, resolve } from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
@@ -19,14 +19,26 @@ function resolveTwAnimateCssPath() {
|
|
|
19
19
|
}
|
|
20
20
|
const CANONICAL_TOKEN_IMPORT = '@import "@sequenceholdings/atlas-ui/tokens.css";';
|
|
21
21
|
const ATLAS_UI_TOKEN_IMPORT = /@import\s+(?:url\(\s*)?(?:["'][^"']*?@sequenceholdings\/atlas-ui\/|[^"'()\s;]*@sequenceholdings\/atlas-ui\/)(tokens\.css|tokens\.v2\.css|theme\.v2\.css)(?:["'])?\s*\)?[^;\n]*;/gi;
|
|
22
|
+
/** Only collapse aliases when the selected package makes them forwarding sheets.
|
|
23
|
+
* Older releases define independent semantic tokens and the Tailwind bridge there.
|
|
24
|
+
*/
|
|
25
|
+
export function hasUnifiedAtlasUiTokens(atlasUiDir) {
|
|
26
|
+
return ['tokens.v2.css', 'theme.v2.css'].every((sheet) => {
|
|
27
|
+
const path = resolve(atlasUiDir, sheet);
|
|
28
|
+
if (!existsSync(path))
|
|
29
|
+
return false;
|
|
30
|
+
const content = readFileSync(path, 'utf8').replace(/\/\*[\s\S]*?\*\//g, '').trim();
|
|
31
|
+
return /^@import\s+["']@sequenceholdings\/atlas-ui\/tokens\.css["'];$/.test(content);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
22
34
|
function atlasUiTokenImportSheets(code) {
|
|
23
35
|
return [...code.matchAll(ATLAS_UI_TOKEN_IMPORT)]
|
|
24
36
|
.map((match) => match[1]?.toLowerCase())
|
|
25
37
|
.filter((sheet) => sheet !== undefined);
|
|
26
38
|
}
|
|
27
39
|
/**
|
|
28
|
-
*
|
|
29
|
-
* expands
|
|
40
|
+
* For packages with forwarding aliases, collapse imports before Tailwind
|
|
41
|
+
* expands them. The aliases remain package-compatible, but are no longer allowed
|
|
30
42
|
* to create duplicate token layers in an Artifact Studio bundle (DES-437).
|
|
31
43
|
*/
|
|
32
44
|
export function normalizeAtlasUiTokenImports(code) {
|
|
@@ -43,16 +55,23 @@ export function normalizeAtlasUiTokenImports(code) {
|
|
|
43
55
|
};
|
|
44
56
|
}
|
|
45
57
|
/**
|
|
46
|
-
* Evidence mirrors the
|
|
47
|
-
*
|
|
58
|
+
* Evidence mirrors the selected package: split sheets remain separate entries;
|
|
59
|
+
* forwarding aliases are normalized to the canonical entry point.
|
|
48
60
|
*/
|
|
49
|
-
export function collectAtlasUiResolvedTokenSelections({ cssModules, }) {
|
|
61
|
+
export function collectAtlasUiResolvedTokenSelections({ cssModules, atlasUiDir, }) {
|
|
50
62
|
for (const { code } of cssModules) {
|
|
51
63
|
if (!code.includes('@import "tailwindcss"'))
|
|
52
64
|
continue;
|
|
65
|
+
const sheets = atlasUiTokenImportSheets(code);
|
|
66
|
+
if (!hasUnifiedAtlasUiTokens(atlasUiDir)) {
|
|
67
|
+
return [...new Set(['tokens.css', ...sheets])].map((sheet) => ({
|
|
68
|
+
specifier: `@sequenceholdings/atlas-ui/${sheet}`,
|
|
69
|
+
injectedBy: sheets.includes(sheet) ? null : 'atlas-ui-css-resolver',
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
53
72
|
return [{
|
|
54
73
|
specifier: '@sequenceholdings/atlas-ui/tokens.css',
|
|
55
|
-
injectedBy:
|
|
74
|
+
injectedBy: sheets.includes('tokens.css') ? null : 'atlas-ui-css-resolver',
|
|
56
75
|
}];
|
|
57
76
|
}
|
|
58
77
|
return [];
|
|
@@ -70,7 +89,8 @@ function insertAfterImports(code, lines) {
|
|
|
70
89
|
const end = lastImport.index + lastImport[0].length;
|
|
71
90
|
return `${code.slice(0, end)}${block}${code.slice(end)}`;
|
|
72
91
|
}
|
|
73
|
-
export function atlasUiCssResolverPlugin({ atlasUiDir
|
|
92
|
+
export function atlasUiCssResolverPlugin({ atlasUiDir, atlasUiDist, formRendererDist, onTransform, }) {
|
|
93
|
+
const unifiedTokens = hasUnifiedAtlasUiTokens(atlasUiDir);
|
|
74
94
|
return {
|
|
75
95
|
name: 'atlas-ui-css-resolver',
|
|
76
96
|
enforce: 'pre',
|
|
@@ -88,8 +108,16 @@ export function atlasUiCssResolverPlugin({ atlasUiDir: _atlasUiDir, atlasUiDist,
|
|
|
88
108
|
if (formRendererDist) {
|
|
89
109
|
sources.push(`@source ${JSON.stringify(formRendererDist)};`);
|
|
90
110
|
}
|
|
91
|
-
|
|
92
|
-
|
|
111
|
+
if (unifiedTokens) {
|
|
112
|
+
result = normalizeAtlasUiTokenImports(result).code;
|
|
113
|
+
}
|
|
114
|
+
else if (!atlasUiTokenImportSheets(result).includes('tokens.css')) {
|
|
115
|
+
const firstTokenImport = result.match(ATLAS_UI_TOKEN_IMPORT)?.[0];
|
|
116
|
+
// The old base must precede the semantic overrides in split packages.
|
|
117
|
+
result = firstTokenImport
|
|
118
|
+
? result.replace(firstTokenImport, `${CANONICAL_TOKEN_IMPORT}\n${firstTokenImport}`)
|
|
119
|
+
: insertAfterImports(result, [CANONICAL_TOKEN_IMPORT]);
|
|
120
|
+
}
|
|
93
121
|
result = insertAfterImports(result, sources);
|
|
94
122
|
}
|
|
95
123
|
if (result.includes('@import "tw-animate-css"')) {
|
package/dist/build.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ObservedBuildEvidence } from './build-provenance.js';
|
|
2
2
|
import { type ArtifactStudioSourceFile } from './project.js';
|
|
3
|
-
import type
|
|
3
|
+
import { type ArtifactStudioStaticManifest } from './manifest.js';
|
|
4
4
|
import { type ArtifactStudioPeerVersions } from './peer-versions.js';
|
|
5
5
|
/**
|
|
6
6
|
* Released Atlas UI 2.0.1 exports its canonical sheet from dist, while the
|
|
@@ -17,7 +17,7 @@ export interface ArtifactStudioRuntimeChunk {
|
|
|
17
17
|
}
|
|
18
18
|
export type ArtifactStudioBundleFormat = 'esm';
|
|
19
19
|
export interface ArtifactStudioBuildResult {
|
|
20
|
-
manifest:
|
|
20
|
+
manifest: ArtifactStudioStaticManifest;
|
|
21
21
|
files: ArtifactStudioSourceFile[];
|
|
22
22
|
/** Entry module (ESM). Lazy routes land in `chunks`. */
|
|
23
23
|
bundle: string;
|
package/dist/build.js
CHANGED
|
@@ -3,13 +3,14 @@ import { mkdir, writeFile } from 'node:fs/promises';
|
|
|
3
3
|
import { createRequire } from 'node:module';
|
|
4
4
|
import { dirname, relative, resolve } from 'node:path';
|
|
5
5
|
import { build as viteBuild } from 'vite';
|
|
6
|
-
import { atlasUiCssResolverPlugin, collectAtlasUiResolvedTokenSelections } from './atlas-ui-css-plugin.js';
|
|
6
|
+
import { atlasUiCssResolverPlugin, collectAtlasUiResolvedTokenSelections, hasUnifiedAtlasUiTokens } from './atlas-ui-css-plugin.js';
|
|
7
7
|
import { validateAtlasUiTokenStylesheetContract } from './atlas-ui-package-contract.js';
|
|
8
8
|
import { createObservedBuildEvidence } from './build-provenance.js';
|
|
9
9
|
import { collectResolvedStylesheets } from './resolved-stylesheets.js';
|
|
10
10
|
import { sha256Hex } from './hash.js';
|
|
11
11
|
import { isArtifactIgnoredPath } from './artifact-ignore.js';
|
|
12
12
|
import { readArtifactStudioSource } from './project.js';
|
|
13
|
+
import { isNextArtifactManifest } from './manifest.js';
|
|
13
14
|
import { normalizeArtifactPath } from './paths.js';
|
|
14
15
|
import { resolveArtifactStudioPeerVersions, } from './peer-versions.js';
|
|
15
16
|
import { ARTIFACT_RUNTIME_CHUNK_DIR, assertSafeRuntimeChunkFileName } from './runtime-chunks.js';
|
|
@@ -31,6 +32,7 @@ const reactRouterDomDir = dirname(cliRequire.resolve('react-router-dom/package.j
|
|
|
31
32
|
const sonnerDir = dirname(cliRequire.resolve('sonner'));
|
|
32
33
|
const atlasUiDir = dirname(cliRequire.resolve('@sequenceholdings/atlas-ui/package.json'));
|
|
33
34
|
const atlasUiDist = resolve(atlasUiDir, 'dist');
|
|
35
|
+
const artifactSdkEntry = cliRequire.resolve('@sequenceholdings/artifact-studio');
|
|
34
36
|
/**
|
|
35
37
|
* Released Atlas UI 2.0.1 exports its canonical sheet from dist, while the
|
|
36
38
|
* candidate layout puts the generated entry at package root so it can be read
|
|
@@ -75,6 +77,7 @@ function createPeerResolveAlias({ atlasUiPackageDir = atlasUiDir } = {}) {
|
|
|
75
77
|
'@tanstack/react-query': reactQueryDir,
|
|
76
78
|
'react-router-dom': reactRouterDomDir,
|
|
77
79
|
sonner: sonnerDir,
|
|
80
|
+
'@sequenceholdings/storage': cliRequire.resolve('@sequenceholdings/storage'),
|
|
78
81
|
// Candidate Atlas UI exposes canonical tokens at the package root; released
|
|
79
82
|
// 2.0.1 keeps them in dist. Preserve explicit alias resolution so legacy
|
|
80
83
|
// source reaches the normalizer instead of falling through to the bare alias.
|
|
@@ -101,8 +104,13 @@ export async function buildArtifactStudioProject(rootDir, { candidateTokenCompat
|
|
|
101
104
|
const selectedAtlasUiDist = resolve(atlasUiPackageDir ?? atlasUiDir, 'dist');
|
|
102
105
|
const selectedAtlasUiTokens = resolveAtlasUiTokensPath(selectedAtlasUiDir);
|
|
103
106
|
const source = await readArtifactStudioSource(rootDir);
|
|
107
|
+
if (isNextArtifactManifest(source.manifest)) {
|
|
108
|
+
throw new Error('Next.js applications are built by Atlas. Run seq-studio artifact build --env <env>.');
|
|
109
|
+
}
|
|
104
110
|
const diagnostics = [
|
|
105
|
-
...
|
|
111
|
+
...(hasUnifiedAtlasUiTokens(selectedAtlasUiDir)
|
|
112
|
+
? collectDeprecatedTokenImportDiagnostics({ files: source.files })
|
|
113
|
+
: []),
|
|
106
114
|
...(candidateTokenCompatibility
|
|
107
115
|
? collectCandidateTokenCompatibilityDiagnostics({ files: source.files })
|
|
108
116
|
: []),
|
|
@@ -116,7 +124,7 @@ export async function buildArtifactStudioProject(rootDir, { candidateTokenCompat
|
|
|
116
124
|
plugins: [
|
|
117
125
|
rejectOutsideSourcePlugin({
|
|
118
126
|
root,
|
|
119
|
-
trustedExternalRoots: Object.values(peerResolveAlias).map((target) => dirname(target)),
|
|
127
|
+
trustedExternalRoots: [...Object.values(peerResolveAlias).map((target) => dirname(target)), dirname(artifactSdkEntry)],
|
|
120
128
|
}),
|
|
121
129
|
rejectIgnoredSourcePlugin(root, source.ignorePatterns),
|
|
122
130
|
artifactSdkVirtualModule(),
|
|
@@ -267,8 +275,8 @@ function artifactSdkVirtualModule() {
|
|
|
267
275
|
// host-injected `window.seq`, so a tree that happens to be `pnpm install`ed
|
|
268
276
|
// must produce the same bundle as a bare tree (e.g. one materialized from a
|
|
269
277
|
// git repo) — otherwise the same source yields different bytes depending on
|
|
270
|
-
// whether node_modules exists.
|
|
271
|
-
//
|
|
278
|
+
// whether node_modules exists. Use the CLI's SDK entry so runtime helpers
|
|
279
|
+
// stay in sync with the types instead of maintaining a partial export stub.
|
|
272
280
|
enforce: 'pre',
|
|
273
281
|
resolveId(id) {
|
|
274
282
|
return virtualIds.has(id) ? resolved : undefined;
|
|
@@ -276,7 +284,7 @@ function artifactSdkVirtualModule() {
|
|
|
276
284
|
load(id) {
|
|
277
285
|
if (id !== resolved)
|
|
278
286
|
return undefined;
|
|
279
|
-
return
|
|
287
|
+
return `export * from ${JSON.stringify(artifactSdkEntry)}; export { default } from ${JSON.stringify(artifactSdkEntry)};`;
|
|
280
288
|
},
|
|
281
289
|
};
|
|
282
290
|
}
|