@1agh/maude 0.17.1 → 0.18.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/cli/cli-wrapper.cjs +0 -0
- package/cli/commands/design.mjs +248 -43
- package/package.json +8 -8
- package/plugins/design/dev-server/bin/screenshot.sh +12 -0
- package/plugins/design/dev-server/boot-self-heal.ts +90 -0
- package/plugins/design/dev-server/build.ts +136 -8
- package/plugins/design/dev-server/canvas-pipeline.ts +5 -0
- package/plugins/design/dev-server/config.schema.json +12 -0
- package/plugins/design/dev-server/dist/client.bundle.js +3 -3
- package/plugins/design/dev-server/runtime-bundle.ts +29 -1
- package/plugins/design/dev-server/server.ts +6 -0
- package/plugins/design/dev-server/test/boot-self-heal.test.ts +112 -0
- package/plugins/design/dev-server/test/compile-entry.test.ts +134 -0
- package/plugins/design/dev-server/test/runtime-bundle-error-mapping.test.ts +43 -0
- package/plugins/design/templates/canvas.tsx.template +7 -7
- package/plugins/design/templates/design-system-inspiration/audience-pro/colors-presence.html +1 -1
- package/plugins/design/templates/design-system-inspiration/core/README.philosophy.md.tpl +11 -7
- package/plugins/design/templates/design-system-inspiration/core/SKILL.md.tpl +4 -3
- package/plugins/design/templates/design-system-inspiration/core/colors_and_type.css.tpl +61 -57
- package/plugins/design/templates/design-system-inspiration/core/config.json.tpl +2 -0
- package/plugins/design/templates/design-system-inspiration/core/preview/colors-accent.html +4 -4
- package/plugins/design/templates/design-system-inspiration/meta/presence-multiplayer.html +1 -1
- package/plugins/design/templates/design-system-inspiration/platform-desktop/ui_kits-desktop-showcase.html +3 -0
- package/plugins/design/templates/design-system-inspiration/platform-mobile/ui_kits-mobile-showcase.html +1 -1
- package/plugins/design/templates/design-system-inspiration/theme-both/colors-themes-side-by-side.html +6 -6
- package/plugins/design/templates/design-system-inspiration/universal/components-dialogs.html +3 -2
- package/plugins/design/templates/design-system-inspiration/universal/logo.html +2 -1
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
//
|
|
16
16
|
// Per DDR-009 (Bun runtime authoritative) + DDR-012 (React 19 unified) + DDR-014 (Lightning CSS).
|
|
17
17
|
|
|
18
|
-
import { existsSync, mkdirSync } from 'node:fs';
|
|
19
|
-
import { dirname, join, resolve } from 'node:path';
|
|
18
|
+
import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
19
|
+
import { dirname, join, relative, resolve } from 'node:path';
|
|
20
20
|
import { fileURLToPath } from 'node:url';
|
|
21
21
|
|
|
22
22
|
import { browserslistToTargets, bundle as lcssBundle } from 'lightningcss';
|
|
@@ -65,13 +65,29 @@ function ensureDist() {
|
|
|
65
65
|
if (!existsSync(DIST)) mkdirSync(DIST, { recursive: true });
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
async function readPluginVersion(): Promise<{ version: string }> {
|
|
69
|
+
// plugins/design/dev-server/ → plugins/design/.claude-plugin/plugin.json
|
|
70
|
+
const manifest = join(ROOT, '..', '.claude-plugin', 'plugin.json');
|
|
71
|
+
try {
|
|
72
|
+
const parsed = JSON.parse(await Bun.file(manifest).text()) as { version?: unknown };
|
|
73
|
+
if (typeof parsed.version === 'string') return { version: parsed.version };
|
|
74
|
+
} catch {
|
|
75
|
+
/* fall through to dev default */
|
|
76
|
+
}
|
|
77
|
+
return { version: 'dev' };
|
|
78
|
+
}
|
|
79
|
+
|
|
68
80
|
// ---------- (a) Client JSX bundle ----------
|
|
69
81
|
|
|
70
82
|
async function buildClient(): Promise<{ outBytes: number; outPath: string }> {
|
|
71
83
|
ensureDist();
|
|
72
84
|
const outPath = join(DIST, 'client.bundle.js');
|
|
73
|
-
//
|
|
74
|
-
|
|
85
|
+
// Wordmark sub-line version. Read from plugins/design/.claude-plugin/plugin.json —
|
|
86
|
+
// that file ships in both npm installs AND marketplace-cache clones (it's the
|
|
87
|
+
// plugin manifest, always present). The old `../../../package.json` hop
|
|
88
|
+
// resolved to the repo root in dev but ENOENT'd in marketplace caches where
|
|
89
|
+
// the maude bundle isn't installed as a package. DDR-044, Phase 19.
|
|
90
|
+
const pkg = await readPluginVersion();
|
|
75
91
|
const result = await Bun.build({
|
|
76
92
|
entrypoints: [join(ROOT, 'client/app.jsx')],
|
|
77
93
|
outdir: DIST,
|
|
@@ -122,14 +138,117 @@ async function buildCss(): Promise<{ outBytes: number; outPath: string }> {
|
|
|
122
138
|
|
|
123
139
|
// ---------- (c) Server binary (bun build --compile, per-platform) ----------
|
|
124
140
|
|
|
141
|
+
// Per-target oxc-parser binding embed. Bun 1.3.4+ regressed `--compile` NAPI
|
|
142
|
+
// native-binding embedding (see DDR-042-oxc-parser-bun-compile-workaround.md).
|
|
143
|
+
// `with { type: 'file' }` requires a literal string path, so we generate one
|
|
144
|
+
// thin entry file per --target whose only purpose is to (1) embed the matching
|
|
145
|
+
// platform binding as an asset, (2) set NAPI_RS_NATIVE_LIBRARY_PATH from the
|
|
146
|
+
// runtime virtual path, then (3) hand off to the real server.ts. ESM
|
|
147
|
+
// evaluation order guarantees the env var is set before any downstream module
|
|
148
|
+
// touches oxc-parser.
|
|
149
|
+
|
|
150
|
+
// oxc-parser's NAPI-RS binding packages use a richer slug than our build
|
|
151
|
+
// target slug — Linux needs the libc kind suffix, Windows needs the toolchain
|
|
152
|
+
// suffix. Mirrored from oxc-parser/src-js/bindings.js loader cases.
|
|
153
|
+
function oxcBindingSlug(slug: string): string {
|
|
154
|
+
if (slug === 'linux-x64') return 'linux-x64-gnu';
|
|
155
|
+
if (slug === 'linux-arm64') return 'linux-arm64-gnu';
|
|
156
|
+
if (slug === 'win32-x64') return 'win32-x64-msvc';
|
|
157
|
+
// darwin-arm64 / darwin-x64 / linux-x64-musl / linux-arm64-musl already match.
|
|
158
|
+
return slug;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// npm/bun's installer respects each package's `os`/`cpu` fields and skips
|
|
162
|
+
// platform sub-packages whose filter doesn't match the host (the bindings
|
|
163
|
+
// declare e.g. `"cpu": ["x64"]`). For cross-compile targets — most notably
|
|
164
|
+
// darwin-x64 built on a darwin-arm64 CI runner — this means the matching
|
|
165
|
+
// `@oxc-parser/binding-<oxcSlug>` is NOT in node_modules even though it's
|
|
166
|
+
// listed as a direct devDependency. Fetch + extract the tarball manually so
|
|
167
|
+
// `with { type: 'file' }` resolution succeeds during `bun build --compile`.
|
|
168
|
+
async function ensureBindingForTarget(oxcSlug: string): Promise<void> {
|
|
169
|
+
const bindingDir = join(ROOT, 'node_modules', '@oxc-parser', `binding-${oxcSlug}`);
|
|
170
|
+
const bindingFile = join(bindingDir, `parser.${oxcSlug}.node`);
|
|
171
|
+
if (existsSync(bindingFile)) return; // host install already placed it
|
|
172
|
+
|
|
173
|
+
// Read the installed oxc-parser version so the tarball URL stays in sync.
|
|
174
|
+
// Walk up from build.ts to find the workspace-visible oxc-parser package.json
|
|
175
|
+
// (pnpm hoists it under node_modules/.pnpm, then symlinks at workspace level).
|
|
176
|
+
let oxcVersion = '0.131.0';
|
|
177
|
+
const candidates = [
|
|
178
|
+
join(ROOT, 'node_modules', 'oxc-parser', 'package.json'),
|
|
179
|
+
join(ROOT, '..', '..', '..', 'node_modules', 'oxc-parser', 'package.json'),
|
|
180
|
+
];
|
|
181
|
+
for (const c of candidates) {
|
|
182
|
+
if (existsSync(c)) {
|
|
183
|
+
oxcVersion = JSON.parse(readFileSync(c, 'utf8')).version;
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
console.log(`[build] cross-compile: fetching @oxc-parser/binding-${oxcSlug}@${oxcVersion}`);
|
|
189
|
+
const tarballUrl = `https://registry.npmjs.org/@oxc-parser/binding-${oxcSlug}/-/binding-${oxcSlug}-${oxcVersion}.tgz`;
|
|
190
|
+
const response = await fetch(tarballUrl);
|
|
191
|
+
if (!response.ok) {
|
|
192
|
+
throw new Error(`failed to fetch ${tarballUrl}: HTTP ${response.status}`);
|
|
193
|
+
}
|
|
194
|
+
const tmpTgz = join(ROOT, `.binding-${oxcSlug}.tgz`);
|
|
195
|
+
await Bun.write(tmpTgz, await response.arrayBuffer());
|
|
196
|
+
mkdirSync(bindingDir, { recursive: true });
|
|
197
|
+
// npm pack output: `package/parser.<oxcSlug>.node` + `package/package.json`.
|
|
198
|
+
// --strip-components=1 drops the leading `package/` so files land in bindingDir.
|
|
199
|
+
const tarProc = Bun.spawn(['tar', 'xf', tmpTgz, '-C', bindingDir, '--strip-components=1'], {
|
|
200
|
+
stdout: 'inherit',
|
|
201
|
+
stderr: 'inherit',
|
|
202
|
+
});
|
|
203
|
+
const tarCode = await tarProc.exited;
|
|
204
|
+
if (tarCode !== 0)
|
|
205
|
+
throw new Error(`tar extraction failed for binding-${oxcSlug} (exit ${tarCode})`);
|
|
206
|
+
unlinkSync(tmpTgz);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export function writeCompileEntry(target: PlatformTarget): string {
|
|
210
|
+
const slug = platformSlug(target);
|
|
211
|
+
const oxcSlug = oxcBindingSlug(slug);
|
|
212
|
+
const entryDir = join(DIST, '.compile-entries');
|
|
213
|
+
mkdirSync(entryDir, { recursive: true });
|
|
214
|
+
|
|
215
|
+
// ESM hoists `import` statements above top-level code, so the env-var
|
|
216
|
+
// assignment MUST live in a separate leaf module that's imported BEFORE
|
|
217
|
+
// server.ts — otherwise server.ts (and transitively oxc-parser) evaluates
|
|
218
|
+
// first and reads NAPI_RS_NATIVE_LIBRARY_PATH before we set it.
|
|
219
|
+
const initPath = join(entryDir, `init-oxc-${slug}.ts`);
|
|
220
|
+
const entryPath = join(entryDir, `server-${slug}.ts`);
|
|
221
|
+
const bindingSpec = `@oxc-parser/binding-${oxcSlug}/parser.${oxcSlug}.node`;
|
|
222
|
+
const initContent = `// AUTO-GENERATED by build.ts — do not edit by hand.
|
|
223
|
+
// Per-target oxc-parser binding embed (Bun 1.3.4+ --compile NAPI regression
|
|
224
|
+
// workaround — see .ai/decisions/DDR-042-oxc-parser-bun-compile-workaround.md).
|
|
225
|
+
// Side-effect module: must be imported BEFORE any oxc-parser usage.
|
|
226
|
+
import bindingPath from ${JSON.stringify(bindingSpec)} with { type: 'file' };
|
|
227
|
+
process.env.NAPI_RS_NATIVE_LIBRARY_PATH = bindingPath;
|
|
228
|
+
`;
|
|
229
|
+
writeFileSync(initPath, initContent);
|
|
230
|
+
|
|
231
|
+
// Forward slashes for the import specifier even on Windows hosts — ESM uses
|
|
232
|
+
// POSIX-style paths, not the host's filesystem separator.
|
|
233
|
+
const realServerRel = relative(entryDir, join(ROOT, 'server.ts')).split('\\').join('/');
|
|
234
|
+
const entryContent = `// AUTO-GENERATED by build.ts — do not edit by hand.
|
|
235
|
+
// Per-target compile entry — see DDR-042-oxc-parser-bun-compile-workaround.md.
|
|
236
|
+
import './init-oxc-${slug}.ts';
|
|
237
|
+
import ${JSON.stringify(realServerRel)};
|
|
238
|
+
`;
|
|
239
|
+
writeFileSync(entryPath, entryContent);
|
|
240
|
+
return entryPath;
|
|
241
|
+
}
|
|
242
|
+
|
|
125
243
|
async function buildServerBinary(target: PlatformTarget): Promise<{ outPath: string }> {
|
|
126
244
|
ensureDist();
|
|
127
245
|
const slug = platformSlug(target);
|
|
128
246
|
const ext = slug.startsWith('win32') ? '.exe' : '';
|
|
129
247
|
const outPath = join(DIST, `maude-${slug}${ext}`);
|
|
130
|
-
const
|
|
131
|
-
if (!existsSync(
|
|
132
|
-
//
|
|
248
|
+
const realEntry = join(ROOT, 'server.ts');
|
|
249
|
+
if (!existsSync(realEntry)) {
|
|
250
|
+
// Legacy fallback — pre-DDR-009 .mjs path. Doesn't use oxc-parser, so the
|
|
251
|
+
// 1.3.4+ regression doesn't apply; entry stub generator is skipped.
|
|
133
252
|
const legacy = join(ROOT, 'server.mjs');
|
|
134
253
|
if (!existsSync(legacy)) throw new Error(`Neither server.ts nor server.mjs exists in ${ROOT}`);
|
|
135
254
|
const proc = Bun.spawn(
|
|
@@ -150,6 +269,10 @@ async function buildServerBinary(target: PlatformTarget): Promise<{ outPath: str
|
|
|
150
269
|
throw new Error(`bun build --compile (legacy) failed for ${target} (exit ${code})`);
|
|
151
270
|
return { outPath };
|
|
152
271
|
}
|
|
272
|
+
// Make sure the target's NAPI binding is on disk even if bun/npm's os/cpu
|
|
273
|
+
// filter skipped it (cross-compile case — see ensureBindingForTarget docs).
|
|
274
|
+
await ensureBindingForTarget(oxcBindingSlug(slug));
|
|
275
|
+
const entry = writeCompileEntry(target);
|
|
153
276
|
const proc = Bun.spawn(
|
|
154
277
|
[
|
|
155
278
|
'bun',
|
|
@@ -262,6 +385,11 @@ async function main() {
|
|
|
262
385
|
}
|
|
263
386
|
}
|
|
264
387
|
|
|
265
|
-
|
|
388
|
+
// Only run the build when invoked directly — importers (e.g. the test suite,
|
|
389
|
+
// which calls `writeCompileEntry` from build.ts) should not trigger a dev
|
|
390
|
+
// build as a side effect.
|
|
391
|
+
if (import.meta.main) {
|
|
392
|
+
await main();
|
|
393
|
+
}
|
|
266
394
|
|
|
267
395
|
export { buildClient, buildCss, buildServerBinary, PLATFORM_MATRIX, type PlatformTarget };
|
|
@@ -16,6 +16,11 @@
|
|
|
16
16
|
// Toolchain matches scripts/migrate-canvases.ts (codemod) and canvas-edit.ts
|
|
17
17
|
// (AST-aware /design:edit element edits) — same oxc-parser + magic-string pair
|
|
18
18
|
// in three call sites, one mental model.
|
|
19
|
+
//
|
|
20
|
+
// `bun build --compile` requires a per-target entry stub that sets
|
|
21
|
+
// NAPI_RS_NATIVE_LIBRARY_PATH before this file's transitive imports load
|
|
22
|
+
// oxc-parser. The pipeline itself is unaware of the workaround — it's a
|
|
23
|
+
// build-layer concern. See DDR-042-oxc-parser-bun-compile-workaround.md.
|
|
19
24
|
|
|
20
25
|
import MagicString from 'magic-string';
|
|
21
26
|
import { parseSync } from 'oxc-parser';
|
|
@@ -116,6 +116,18 @@
|
|
|
116
116
|
},
|
|
117
117
|
"default": ["accent"]
|
|
118
118
|
},
|
|
119
|
+
"accentStrategy": {
|
|
120
|
+
"type": "string",
|
|
121
|
+
"description": "How many --accent* families exist. The completeness-critic C7 gates the actual family count against this declaration. Default: 'single' (backwards-compatible). 'chromatic-N' is parameterized — write the literal N (e.g. 'chromatic-5'). Per DDR-043.",
|
|
122
|
+
"pattern": "^(single|paired|chromatic-[1-9][0-9]?)$",
|
|
123
|
+
"default": "single"
|
|
124
|
+
},
|
|
125
|
+
"colorSpace": {
|
|
126
|
+
"type": "string",
|
|
127
|
+
"enum": ["oklch", "hsl", "hex", "lab"],
|
|
128
|
+
"description": "Color space the project uses in tokens CSS. The completeness-critic V2 gates the actual token format against this declaration. Default: 'oklch' (backwards-compatible). Per DDR-043.",
|
|
129
|
+
"default": "oklch"
|
|
130
|
+
},
|
|
119
131
|
"designSystems": {
|
|
120
132
|
"type": "array",
|
|
121
133
|
"description": "Design systems available in this project. Single-DS projects have one entry; multi-DS projects (marketing vs. admin vs. mobile) list each here. Each canvas's .meta.json declares which DS it uses via the 'designSystem' field.",
|