@object-ui/cli 17.3.0 → 17.6.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/CHANGELOG.md CHANGED
@@ -1,5 +1,535 @@
1
1
  # @object-ui/cli
2
2
 
3
+ ## 17.6.0
4
+
5
+ ### Patch Changes
6
+
7
+ - 195b9e4: The routed temp app's generated manifest now asks for the same `lucide-react` range this repo installs.
8
+
9
+ `utils/app-generator.ts` writes the routed variant's `dependencies` with two
10
+ quoted third-party ranges, and `lucide-react` had fossilised a minor behind the
11
+ 22 sibling manifests that declare it: the generated manifest said `^1.29.0`
12
+ while the repo had moved to `^1.31.0`. A generated app therefore asked npm for
13
+ an icon library older than the one every `@object-ui/*` package it installs
14
+ alongside was built against.
15
+
16
+ The drift was not silent — `app-generator.test.ts` derives its expectation from
17
+ the in-repo range precisely so a bump on one side and not the other fails a
18
+ test, and both of its pins were red. What went wrong is that they went red too
19
+ late to stop anything: the dependency PR that moved the repo range merged while
20
+ those shards were still running, so the failure surfaced on `main` and then on
21
+ the merge ref of every unrelated open PR. The range is now caught up; the
22
+ reporting hole and the merge-ordering hole are filed separately (objectui#4968).
23
+
24
+ The remaining eleven anchored ranges were swept against the same dependabot
25
+ batch and are all in sync, so this is the batch's only consumer-side follow-up.
26
+ Deriving the value from the workspace instead of quoting it was considered and
27
+ rejected: nine of the thirteen anchored ranges quote the repo root manifest,
28
+ which is not published with this CLI, so no single derivation can serve the
29
+ table and a bespoke one for this one name would leave the class untouched.
30
+ - 68d9e28: `objectui check`: the known-type list is now derived from the component registry instead of being a hand-written copy, which had drifted in both directions at once.
31
+
32
+ The command judged a schema's `type` against a seventeen-entry array typed by
33
+ hand into `packages/cli/src/commands/check.ts`. Nothing held that array against
34
+ the registry, and measured on `origin/main` @ `8378e9954` it was wrong in both
35
+ directions simultaneously:
36
+
37
+ - **Two phantoms.** `crud` and `gallery` were on the list and are registered by
38
+ nothing. `objectui check` passed `{ "type": "crud" }` in silence while
39
+ `SchemaRenderer` painted the OBJUI-001 "Unknown component type" panel for the
40
+ very same file — measured, both halves. `CRUDSchema` still has its interface,
41
+ zod mirror, validator branch and builder; what it has never had is a
42
+ registration. For `gallery`, the registered spelling is `object-gallery`.
43
+ - **221 bare keys missing, plus every namespaced spelling.** `object-grid`,
44
+ `object-form`, `card`, `div` and `view:grid` were all reported as
45
+ `⚠️ Unknown schema type`. False warnings at that volume are not a cosmetic
46
+ problem: they train authors to skip the output, which costs the phantom
47
+ direction its only reader.
48
+
49
+ The list now lives in `packages/cli/src/utils/known-schema-types.ts`, generated
50
+ by `node scripts/regenerate-known-schema-types.mjs` from the same
51
+ `deriveRegistryKeys` derivation that judges documentation snippets, and held to
52
+ it by a bidirectional pin in
53
+ `scripts/__tests__/known-schema-types-derivation-5115.test.ts` — a key the
54
+ registry has and the list lacks fails, and so does a key the list has and the
55
+ registry lacks. Bare and namespaced spellings are both carried, because
56
+ `register('grid', C, { namespace: 'view' })` really does store both.
57
+
58
+ A runtime lookup through `ComponentRegistry` was measured and rejected: eleven
59
+ of the fifteen genuinely-registered entries come from plugin packages the CLI
60
+ does not depend on, and a published CLI runs against a user project whose plugin
61
+ set this repository cannot know either way.
62
+
63
+ **Behaviour change, in both directions.** `{ "type": "crud" }` and
64
+ `{ "type": "gallery" }` now produce the `Unknown schema type` warning they
65
+ always should have, and a large number of real component types stop producing
66
+ one. The warning remains advisory — it never changes the command's exit code,
67
+ which is still driven only by files that fail to parse — so no run that passed
68
+ before fails now.
69
+
70
+ `check()` additionally takes the directory to scan as an optional argument
71
+ (defaulting, as before, to `process.cwd()`), so the behaviour can be tested
72
+ against a fixture tree.
73
+ - e6a8960: `objectui check` reads `.json` as JSONC, so a `tsconfig.json` no longer fails the run.
74
+
75
+ `check` globbed every `**/*.{json,yaml,yml}` and handed each `.json` straight to
76
+ `JSON.parse`. A throw there is the only thing that increments the error count, and
77
+ a non-zero error count is the only thing that calls `process.exit(1)` — so a `//`
78
+ comment or a trailing comma, which is how TypeScript documents `tsconfig.json`,
79
+ was reported as a malformed file and **failed the command**. Every TypeScript
80
+ project hit this: `objectui check` exited 1 for anyone who ran it, and at this
81
+ repository's own root it reported 64 errors, all of them `tsconfig*.json`
82
+ (objectui#5237).
83
+
84
+ `.json` on disk means JSONC in practice — `tsconfig.json`, `.eslintrc.json`,
85
+ `devcontainer.json` and VS Code's own settings are all written that way — so the
86
+ file is now read with `jsonc-parser`, which permits comments and trailing commas.
87
+ No new package enters what users install: `jsonc-parser` is already a runtime
88
+ dependency of `@object-ui/app-shell`, it is already at the version the lockfile
89
+ resolves, and it declares no dependencies of its own.
90
+
91
+ The reader is a real JSONC parser and **not** a comment-stripping regex, because
92
+ a `//` inside a string value — a URL, say — is not a comment, and a stripper that
93
+ cannot tell the difference corrupts valid files instead of reading them.
94
+
95
+ Genuinely malformed JSON still errors and still exits 1. That needed saying in
96
+ code as well as in tests: `jsonc-parser`'s reader is error-tolerant and returns a
97
+ best-effort value rather than throwing, so the command consults its reported-error
98
+ array instead of inferring success from the absence of a throw. Error output now
99
+ names the reason and the line and column.
100
+
101
+ The unknown-schema-type warning arm is deliberately untouched: it still warns, and
102
+ it still does not affect the exit code. Files that previously died at the parse
103
+ step now reach it, so a JSONC file carrying an unrecognised root `type` warns
104
+ where it used to error — the verdict and the exit-code neutrality are unchanged.
105
+ - 51e65d4: `dev`, `serve` and `build` accept the documented directory argument from anywhere, and refuse a non-project directory in plain language.
106
+
107
+ `content/docs/utilities/cli.mdx` has recorded the positional argument as "Path
108
+ to JSON/YAML schema file or `pages/` directory" and printed `objectui dev
109
+ pages/` as the file-system-routing example. That promise had never actually been
110
+ parsed. Detection's first step required `statSync(...).isFile()`, so a directory
111
+ argument fell straight through it; the one spelling that worked — `objectui dev
112
+ pages/` from inside the project — worked by coincidence of position, caught by
113
+ the working-directory fallback rather than read as an argument. Every pathful
114
+ spelling reached single-schema mode and handed a directory to `readFileSync`:
115
+
116
+ ```
117
+ $ objectui dev my-app/pages
118
+ Error: Invalid schema file: EISDIR: illegal operation on a directory, read
119
+ ```
120
+
121
+ A directory argument now resolves through file-system routing in the shared
122
+ resolution step the three commands were centralized on (objectui#4923), in
123
+ either of the two shapes a user can mean: the directory **is** a `pages`
124
+ directory, or it **contains** one. Both produce the same routed answer as naming
125
+ the app config beside them — same project root, same routes, same app config —
126
+ so `objectui dev my-app/pages`, `objectui dev my-app` and `objectui dev
127
+ my-app/app.json` agree, from any working directory, across all three commands.
128
+ The limb lives in the shared resolver, not in three command branches.
129
+
130
+ The remaining directory-shaped miss is now diagnosed instead of leaking a
131
+ `readFileSync` errno: a directory that is neither shape is refused by name,
132
+ saying what would have been accepted. The refusal sits **after** the
133
+ working-directory fallback, so nothing that resolves today stops resolving: this
134
+ change accepts strictly more than before and rejects nothing that worked.
135
+ - bbfbc54: `objectui serve` and `objectui build` now locate the project the way `dev` does, instead of looking only in the current directory.
136
+
137
+ For a project with an app config and a `pages/` directory beside it, the three
138
+ commands answered one invocation two different ways. `dev` anchored on the
139
+ schema argument — `dirname(<schema>)` is the project root, `pages/` beside it
140
+ means file-system routing, the named file is the app config. `serve` and `build`
141
+ looked for a `pages/` directory in the current working directory and nowhere
142
+ else, so from any directory above the project they fell through to single-schema
143
+ mode and handed the app config to the renderer as if it were a page.
144
+
145
+ Measured on the reported fixture (`<root>/app.json` + `<root>/pages/index.json`,
146
+ invoked from the directory above): `dev` reported the project and one route,
147
+ `serve` reported `Loading schema: <root>/app.json`, and `build` did the same and
148
+ **exited 0** — the emitted bundle embedded the app config as the page schema and
149
+ contained no page from `pages/` at all. A wrong artifact, produced silently.
150
+
151
+ The detection now lives in one helper the three commands share
152
+ (`utils/project-source.ts`), resolving in a fixed order: a `pages/` directory
153
+ beside the schema argument, else one under the current directory, else
154
+ single-schema mode. `serve` and `build` also pass the resolved app config to the
155
+ routed app generator, which they never did, so a routed project keeps its layout
156
+ under all three commands.
157
+
158
+ A lone schema file with no `pages/` beside it is unchanged — that is the
159
+ fallback, and it is still a supported way to run.
160
+ - 82fbc09: `objectui serve` gains `--no-open`, matching the flag `objectui dev` already ships, and no
161
+ longer prints a bare `Error: spawn xdg-open ENOENT` stack after its success banner in a
162
+ headless environment.
163
+
164
+ **`--no-open`.** `serve` hardcoded Vite's `open: true` and its only options were
165
+ `--port`/`--host` — `dev` already had `--no-open` (`options.open !== false`), so the same
166
+ invocation behaved inconsistently across the two commands. `serve` now threads the same
167
+ flag the same way; the default is unchanged — with the flag omitted, `serve` still opens a
168
+ browser exactly as it always has (objectui#4924).
169
+
170
+ **The headless spawn failure.** Vite's own browser-open step already catches a failed
171
+ `open(url)`, but reports it via `logger.error(err.stack || err.message)` with no
172
+ `{ timestamp: true }`, so the default logger prints the bare Node `ChildProcess` stack with
173
+ no `[vite]` prefix and no context — and because that promise chain is fire-and-forget from
174
+ `server.listen()`, it lands *after* the "✓ Server started successfully!" banner, reading
175
+ like a crash even though the server is fine. There's nothing in `serve.ts` to try/catch —
176
+ the error never leaves Vite. `serve` now supplies a `customLogger` that wraps Vite's default
177
+ logger and replaces exactly that message with a short, contextual line naming the missing
178
+ opener binary (`(could not open the browser automatically — 'xdg-open' is not available in
179
+ this environment; open the URL above manually)`); every other log call — including
180
+ unrelated errors — passes through unchanged.
181
+
182
+ Sibling card objectui#4923 (project-root detection on the same command) is intentionally
183
+ untouched here; it is a separate defect with a separate PR.
184
+ - 4102bfc: Inside a pnpm workspace, `objectui dev` / `serve` / `build` now resolve every platform package
185
+ from workspace source (objectui#3890).
186
+
187
+ The temp app these commands generate installs nothing inside a workspace — it resolves by
188
+ hoisting, and the repo root declares no `@object-ui/*` — so a Vite alias table is the only thing
189
+ that resolves a platform package there. That table was a hand-kept list of eleven names in
190
+ `dev`, which is not a list of what the app imports but of what it imports *transitively*:
191
+ measured on the reported commit, the generated entry closes over 21 packages, ten were unlisted,
192
+ and every module whose transform hit one of them answered 500 with a blank page behind it. Vite's
193
+ dependency scan named only four of the ten, because a scan stops at the first layer it cannot
194
+ resolve.
195
+
196
+ The table is now derived from `pnpm-workspace.yaml` — every scoped workspace package that exposes
197
+ a source barrel, targeting its `src` directory — and a test reconciles it against the manifest so
198
+ it cannot drift again. `serve` and `build` had no workspace branch at all (no aliases, and an
199
+ unconditional `npm install` against a manifest that is empty here); all three commands now share
200
+ one helper. The `lucide-react` entry moved from a resolved entry file to the package root, so
201
+ subpath imports of it stop being rewritten into a path that cannot exist.
202
+
203
+ Measured with the reported repro, from the repo root: 8 of the first 400 modules a browser walk
204
+ reaches answered 500 before, 0 of 2498 after, and the page renders its schema instead of nothing.
205
+ - Updated dependencies [88085e3]
206
+ - Updated dependencies [516663d]
207
+ - Updated dependencies [460c4d0]
208
+ - Updated dependencies [0ae27f7]
209
+ - Updated dependencies [78c0f9a]
210
+ - Updated dependencies [bbe8b86]
211
+ - Updated dependencies [279fb13]
212
+ - Updated dependencies [2e82ab2]
213
+ - Updated dependencies [40d3a33]
214
+ - Updated dependencies [8b9dc62]
215
+ - Updated dependencies [1184192]
216
+ - Updated dependencies [a2a9747]
217
+ - Updated dependencies [a1609a6]
218
+ - Updated dependencies [53f23bc]
219
+ - Updated dependencies [c4533dc]
220
+ - Updated dependencies [be60815]
221
+ - Updated dependencies [37f6844]
222
+ - Updated dependencies [93de4f6]
223
+ - Updated dependencies [2b50261]
224
+ - Updated dependencies [384f30d]
225
+ - Updated dependencies [ac600e5]
226
+ - Updated dependencies [97fba31]
227
+ - Updated dependencies [232f61a]
228
+ - Updated dependencies [d374caf]
229
+ - Updated dependencies [5673576]
230
+ - Updated dependencies [911ceaa]
231
+ - Updated dependencies [98eab36]
232
+ - Updated dependencies [af5e292]
233
+ - Updated dependencies [3fbbea1]
234
+ - Updated dependencies [7f96b10]
235
+ - Updated dependencies [167ec42]
236
+ - Updated dependencies [616a2a5]
237
+ - Updated dependencies [0046d8f]
238
+ - Updated dependencies [f1d4748]
239
+ - Updated dependencies [578e025]
240
+ - Updated dependencies [598c89a]
241
+ - Updated dependencies [4a0bd17]
242
+ - Updated dependencies [b8b9af4]
243
+ - Updated dependencies [8c0d52e]
244
+ - Updated dependencies [aff10e2]
245
+ - Updated dependencies [70a774b]
246
+ - Updated dependencies [7458a41]
247
+ - Updated dependencies [d971e51]
248
+ - Updated dependencies [97abb24]
249
+ - Updated dependencies [deb157a]
250
+ - Updated dependencies [d2ce342]
251
+ - Updated dependencies [9695da7]
252
+ - Updated dependencies [75444e3]
253
+ - Updated dependencies [58b8346]
254
+ - Updated dependencies [2d0bd16]
255
+ - Updated dependencies [dad51e5]
256
+ - Updated dependencies [1c9c342]
257
+ - Updated dependencies [787c738]
258
+ - Updated dependencies [8396656]
259
+ - Updated dependencies [dbbd38a]
260
+ - Updated dependencies [93fe362]
261
+ - Updated dependencies [dfc6975]
262
+ - Updated dependencies [3cf4de0]
263
+ - Updated dependencies [c9dc811]
264
+ - Updated dependencies [144ef9b]
265
+ - Updated dependencies [138ab04]
266
+ - Updated dependencies [a0b9e91]
267
+ - Updated dependencies [99bd015]
268
+ - @object-ui/types@17.6.0
269
+ - @object-ui/react@17.6.0
270
+ - @object-ui/components@17.6.0
271
+
272
+ ## 17.5.0
273
+
274
+ ### Patch Changes
275
+
276
+ - 64cda47: Fix `objectui init`'s scaffold failing its own `npm run build`, and put the third generator under the real `tsc` gate
277
+
278
+ The scaffold `objectui init` writes declares `"build": "tsc && vite build"`, so `tsc` runs on the way to a production build — and its `src/main.tsx` did `import './index.css'` with no ambient declaration behind it. Any user who followed the generated README (`objectui init`, then `npm run build`) got `TS2882: Cannot find module or type declarations for side-effect import of './index.css'` in a file the tool had just written for them, before Vite was ever reached.
279
+
280
+ Fixed the same way objectui#3853 fixed the two temp-app generators: the scaffold now writes `src/vite-env.d.ts` (`/// <reference types="vite/client" />`), where the `declare module '*.css'` declarations live. `vite` was already in the scaffold's `devDependencies`, so nothing new is declared.
281
+
282
+ Measured rather than assumed: this scaffold had that one error and none of the other four classes objectui#3853 found in the temp apps — those live in a `src/Layout.tsx` this scaffold does not have. The `tsc` gate in `app-generator.test.ts` now covers the init scaffold too, so the strictness its own `tsconfig.json` declares is enforced instead of decorative.
283
+
284
+ - 9b9fa49: Make the generated temp app pass the strict `tsconfig.json` the generator writes beside it, and gate it with a real `tsc`
285
+
286
+ Both app generators (`createTempApp`, `createTempAppWithRouting`) emit a `tsconfig.json` carrying `strict`, `noUnusedLocals` and `noUnusedParameters`, but nothing had ever run it — `dev`/`serve`/`build` go through Vite, which transpiles without type-checking — so the generated sources had drifted 17 errors past their own declared config. A user who copies the temp app out as a scaffold, or runs `tsc` in it, met all 17 at once.
287
+
288
+ Fixed at the templates: dropped five imports that were declared and never used (`Link` in `src/App.tsx`; `cn`, `Button`, `SidebarGroupContent`, `SidebarGroupLabel` in `src/Layout.tsx`), typed `DynamicIcon`'s and `AppLayout`'s props (which also types the `menu`/`children` map callbacks by inference, and makes `className` optional so the two call sites that omit it are legal), and added the `src/vite-env.d.ts` every Vite TS scaffold carries — without it the entry's `import './index.css'` has no declaration behind it, in both generators.
289
+
290
+ The Lucide lookup no longer needs `@ts-expect-error`: the namespace is narrowed to the component-by-name shape the layout actually uses. No `any` was added.
291
+
292
+ A real `tsc -p` over a generated app now runs in the package's tests, so the declared strictness is enforced rather than decorative.
293
+
294
+ - Updated dependencies [ceccdcf]
295
+ - Updated dependencies [d6e5124]
296
+ - Updated dependencies [debad27]
297
+ - Updated dependencies [dc2aa3e]
298
+ - Updated dependencies [ee26e65]
299
+ - Updated dependencies [f650253]
300
+ - Updated dependencies [3d9769a]
301
+ - Updated dependencies [8f85f8b]
302
+ - Updated dependencies [d0c3b26]
303
+ - Updated dependencies [4dadf0d]
304
+ - Updated dependencies [ae10a01]
305
+ - Updated dependencies [92876f0]
306
+ - Updated dependencies [4b70d28]
307
+ - Updated dependencies [d9d3463]
308
+ - Updated dependencies [2a40f69]
309
+ - Updated dependencies [bec3e14]
310
+ - Updated dependencies [b4d3c22]
311
+ - Updated dependencies [1f9b905]
312
+ - Updated dependencies [cb13400]
313
+ - Updated dependencies [bc64bfe]
314
+ - Updated dependencies [abb0f81]
315
+ - Updated dependencies [38ab505]
316
+ - Updated dependencies [3e19fe7]
317
+ - Updated dependencies [b953a97]
318
+ - Updated dependencies [d7f3e30]
319
+ - Updated dependencies [7e4f0e5]
320
+ - Updated dependencies [a84385b]
321
+ - Updated dependencies [45e1949]
322
+ - Updated dependencies [c1d939f]
323
+ - Updated dependencies [a3ae404]
324
+ - Updated dependencies [bfdf3d4]
325
+ - Updated dependencies [bb68488]
326
+ - Updated dependencies [b1e42d0]
327
+ - Updated dependencies [3f5f87c]
328
+ - Updated dependencies [f5e1143]
329
+ - Updated dependencies [f148a64]
330
+ - Updated dependencies [bb68488]
331
+ - Updated dependencies [47f551b]
332
+ - Updated dependencies [ab04728]
333
+ - Updated dependencies [5bf09fd]
334
+ - @object-ui/react@17.5.0
335
+ - @object-ui/components@17.5.0
336
+ - @object-ui/types@17.5.0
337
+
338
+ ## 17.4.0
339
+
340
+ ### Patch Changes
341
+
342
+ - c32323e: Generated temp apps now declare every package they import, at ranges anchored to this repo
343
+
344
+ `objectui dev` / `serve` / `build` write a throwaway app into `<cwd>/.objectui-tmp`,
345
+ and the `package.json` they wrote named neither `lucide-react` nor any of the seven
346
+ `@object-ui/plugin-*` packages the generated sources import — while pinning
347
+ `@object-ui/react` and `@object-ui/components` at `^0.1.0`, a range that resolves to
348
+ nothing at all for packages published at 17.x (the registry has no 0.1.0). Outside
349
+ this workspace that manifest could not install; inside it, hoisting to the root
350
+ `node_modules` satisfied every missing name, so nothing was ever red.
351
+
352
+ **`lucide-react` is now declared** (objectui#3827). Both of its imports in the
353
+ generated layout are live — `import * as LucideIcons` feeds a `DynamicIcon` lookup
354
+ and four `LucideIcons.*` icons, and the named `{ Moon, Sun }` renders the theme
355
+ toggle — so this is the opposite disposition from the sibling generator, where
356
+ objectui#3755 removed an equivalent declaration precisely because nothing imported
357
+ it. Anchored to `^1.28.0`, the range all 23 in-repo manifests that import lucide
358
+ agree on. `commands/dev.ts` had been covering the gap in the consumer, aliasing
359
+ `lucide-react` to a path resolved out of `packages/components` "to avoid dependency
360
+ not found in temp app" — but only in monorepo mode, leaving every other path with an
361
+ unsatisfiable import. The declaration belongs at the producer; the alias is now a
362
+ workspace convenience rather than the only thing holding the import up.
363
+
364
+ **The seven plugin packages are now declared too**, in both generators. Measuring
365
+ the reported defect turned up that `src/App.tsx` side-effect-imports
366
+ `@object-ui/plugin-charts`, `-editor`, `-kanban`, `-markdown`, `-form`, `-grid` and
367
+ `-view` to register their components, and no manifest ever named them: the
368
+ undeclared set was eight packages, not the one the issue reported.
369
+
370
+ **`@object-ui/*` ranges are derived from this CLI's own version** instead of being
371
+ written out as literals. `.changeset/config.json` puts `@object-ui/cli` in the same
372
+ `fixed` group as every platform package a generated app depends on, so they always
373
+ publish at one version — which makes `^<own version>` both current and guaranteed to
374
+ exist on the registry. A literal here is not merely a fossil risk but a fossil
375
+ generator: that group re-versions on every release, so any hard-coded range is stale
376
+ the next day. This is how `^0.1.0` survived to sit 16 majors behind.
377
+
378
+ **The toolchain ranges are anchored to in-repo manifests**, the discipline
379
+ objectui#3742/objectui#3754 established: `vite ^5.0.0` → `^8.2.0`, `typescript
380
+ ~5.7.3` → `^6.0.3`, `@vitejs/plugin-react ^4.2.1` → `^6.0.5`, `react`/`react-dom`
381
+ `^18.3.1` → `19.2.8` with `@types/*` to match, `react-router-dom ^7.12.0` →
382
+ `^7.18.2`, `postcss ^8.5.6` → `^8.5.26`, `autoprefixer ^10.4.23` → `^10.5.4`. React
383
+ quotes the root's installed version rather than the wider `^18 || ^19` the platform
384
+ packages accept as a peer: the peer says what can work, the root says what the
385
+ generated code has actually run against, and inside this workspace the temp app
386
+ resolves React by hoisting to the root.
387
+
388
+ `tailwindcss` is deliberately left at `^3.4.19`. This repo is on Tailwind 4 and
389
+ `@object-ui/components` peers `^4.2.1`, so the range is not merely behind — it
390
+ conflicts. But re-anchoring it is not a version edit: the generated `index.css` uses
391
+ v3 directives, the generated `postcss.config.js` names the plugin key v4 moved to
392
+ `@tailwindcss/postcss`, and the generated `tailwind.config.js` is a v3 config. Raising
393
+ the range without rewriting those three files yields an app that installs and renders
394
+ unstyled, which looks fixed and is worse. Filed separately as objectui#3852; kept
395
+ internally consistent at v3 until then, and pinned as a deliberate deferral rather
396
+ than left to read as drift.
397
+
398
+ The generators now build their output as a file map that the writers spill to disk,
399
+ so tests assert over the same artifact the CLI writes. Three structural gates port
400
+ the ones the sibling generator grew: every bare import must be declared, no versioned
401
+ runtime dependency may be declared that nothing imports, and no generated `src/**`
402
+ file may be unreachable from `src/main.tsx` — the one module `index.html` loads. Each
403
+ is paired with a self-test that plants the defect back. Note for the next port: the
404
+ `create-plugin` import scanner matches single-quoted specifiers only, and these
405
+ templates mix quote styles, so a verbatim copy would have been blind to
406
+ `from "lucide-react"` — one of the two lines this issue reports.
407
+
408
+ - 8277053: 修复 `objectui dev` 生成的临时 app 的 CSS 管线:整套从 Tailwind 3 迁到 Tailwind 4
409
+
410
+ 生成器写出的样式面此前是完整的 v3 三件套 —— `src/index.css` 用 `@tailwind base/components/utilities` 指令、`postcss.config.js` 写 v3 的 `tailwindcss: {}` 插件键、外加一份 `tailwind.config.js` —— 而仓内与 `@object-ui/components` 都已在 v4(components 的 peer 是 `tailwindcss ^4.2.1`)。两个后果都是真的:
411
+
412
+ - **仓内 `objectui dev` 今天不出样式。** `commands/dev.ts` 的 monorepo 分支把 `require('tailwindcss')(configPath)` 当 PostCSS 插件调用,v4 下这条路径只会抛 "moved to `@tailwindcss/postcss`",而该异常被 `try/catch` 吞成一行黄字警告;`css.postcss` 因此没被设上,Vite 退回去搜配置文件,`/src/index.css` 请求最终 500(实测:`Failed to load PostCSS config … Cannot find module '@tailwindcss/postcss'`),浏览器里一条样式都没有。
413
+ - **仓外一次干净安装会 ERESOLVE。** 生成清单声明 `tailwindcss ^3.4.19`,与它依赖的 `@object-ui/components` 的 v4 peer 冲突。
414
+
415
+ 改动:
416
+
417
+ - `src/index.css` 改为仓内惯用的 v4 CSS-first 写法(`@import 'tailwindcss'` + `@custom-variant dark` + `@source` + `@theme`),`@theme` 的 token 集与 `packages/components/src/index.css` 逐条对齐 —— 包含 v3 config 一直缺、而生成的 `src/Layout.tsx` 自己就在用的 8 个 `sidebar-*` token。
418
+ - `postcss.config.js` 改写 `'@tailwindcss/postcss': {}`;`tailwind.config.js` 不再生成(v4 下没有 `@config` 指向它时它就是死文件,仓内本身也零个 `tailwind.config.*`),v3 的 `content` 扫描面等价迁为 `@source`。
419
+ - 清单:`tailwindcss` 抬到 `^4.3.3` 并新增 `@tailwindcss/postcss ^4.3.3`,两者都锚回仓内(#3827 记的 `TAILWIND_V3_DEFERRED` 记账钉随之翻转)。
420
+ - `commands/dev.ts` 改用 `@tailwindcss/postcss`,并由 `@object-ui/cli` 自己声明这两个插件包;加载失败不再吞成警告,而是带修法响亮报错 —— 静默无样式正是这个缺陷能潜伏这么久的原因。
421
+
422
+ - 59df371: `objectui doctor` now diagnoses Tailwind 4 instead of Tailwind 3
423
+
424
+ The Tailwind section of `objectui doctor` was written against v3 and got every
425
+ question backwards on a v4 project — which is every project this repo ships.
426
+
427
+ **It counted a missing `tailwind.config.js` as an issue.** In v4 that file is not
428
+ part of the setup: the engine reads CSS-first configuration (`@import
429
+ 'tailwindcss'`, `@theme`, `@source`) and only loads a JS config when a stylesheet
430
+ opts in with `@config`. So the command reported a problem that did not exist and
431
+ pushed the reader toward creating a file Tailwind would never read. Measured on
432
+ `examples/console-starter`, a correct v4 app: before, `Found 1 issue(s)` —
433
+ `⚠️ tailwind.config.js not found`; after, `Everything looks good! ✨`. The repo's
434
+ own root reproduced it identically.
435
+
436
+ **It then graded that file on its `content` array**, the v3 key `@source`
437
+ replaced. The two `tailwind.config.*` files still tracked here are exactly that
438
+ trap: `apps/console` and `examples/byo-backend-console` both declare a `content`
439
+ array, no stylesheet in the repo contains `@config`, so both files are inert —
440
+ and the old check answered `✓ Tailwind content paths configured` for them. A
441
+ false green on a dead file. `apps/console` before: `Everything looks good! ✨`;
442
+ after: one finding saying the config is inert and what to do about it.
443
+
444
+ **It never checked `@tailwindcss/postcss`**, the one dependency a v4 build cannot
445
+ start without — v4 moved the PostCSS plugin out of `tailwindcss` into that
446
+ package, and naming the old `tailwindcss` key in a PostCSS config resolves to a
447
+ shim whose only job is to throw. That is the failure form objectui#3852 measured
448
+ on the generated app, and doctor printed `✓ Tailwind CSS installed` straight
449
+ through it.
450
+
451
+ The checks are now the v4 contract, matching what `objectui init` scaffolds:
452
+ `@tailwindcss/postcss` declared or installed, a PostCSS config naming it rather
453
+ than the v3 `tailwindcss` key, and a CSS entry running `@import 'tailwindcss'`
454
+ (with `@source` acknowledged when present). The declared `tailwindcss` major is
455
+ read too, so a v3 range is named as migration debt instead of passing as
456
+ `✓ installed`.
457
+
458
+ Two deliberate silences, because objectui#3891 is about doctor asserting things
459
+ it cannot see. A **missing** `tailwind.config.*` produces no finding of any level
460
+ — only a _present_ one does, and only when nothing opts into it via `@config`.
461
+ And when no recognised CSS entry exists at all (a monorepo root, a bespoke
462
+ layout), the CSS verdicts are skipped rather than guessed.
463
+
464
+ A v3-tolerant dual path — branching on the declared major and running two sets of
465
+ checks — was considered and deliberately not built: it widens the product surface
466
+ past this repo's v4-only posture. v3 spellings are diagnosed as migration debt,
467
+ not supported as a second mode.
468
+
469
+ Internally `runDiagnostics(cwd)` now returns structured findings carrying a
470
+ stable `id`, and `doctor()` only renders and counts them. That split is what
471
+ makes the matrix testable against real fixture directories instead of scraped
472
+ console output; the tests pin verdicts by `id`, so wording can improve without
473
+ the coverage evaporating.
474
+
475
+ - 85fb95b: Fix `objectui init` scaffolding an app that renders neither components nor styles.
476
+
477
+ The generated `src/App.tsx` imported only `SchemaRenderer` from `@object-ui/react`, which does not depend on `@object-ui/components` — and registration is a side effect of importing that package. The component registry was therefore empty in every scaffolded project, and each node of all three templates (`simple`, `form`, `dashboard`) rendered "Unknown component type". The manifest already declared `@object-ui/components`; it was declared and never imported. The generated `src/App.tsx` now performs the side-effect import.
478
+
479
+ The generated `src/index.css` was a bare `@import 'tailwindcss';` and never loaded the library's published stylesheet, so the theme utilities the templates lean on had no tokens behind them. It now also does `@import '@object-ui/components/style.css';`, matching what the quick-start guide teaches hand-rolled consumers.
480
+
481
+ `objectui init` is unchanged in every other respect: the same eleven files, byte for byte, apart from these two lines.
482
+
483
+ - c29ceff: Move the generator templates' dependency ranges onto the repo's current ones
484
+
485
+ The dependabot wave of 2026-08-10 bumped `lucide-react` to `1.29.0` and `vite`
486
+ to `8.2.1` in this repo's own manifests, but the ranges hard-coded in the
487
+ scaffold generators do not move with it — dependabot does not know the
488
+ templates exist. A project scaffolded by `objectui init` / `objectui dev` or by
489
+ `create-plugin` therefore declared a range the repo itself had already moved
490
+ past.
491
+
492
+ Three ranges are re-anchored: `lucide-react` `^1.28.0` → `^1.29.0` in the routed
493
+ app generator, and `vite` `^8.2.0` → `^8.2.1` in both the shared CLI scaffold
494
+ devDependencies and the create-plugin template.
495
+
496
+ - 0a09793: `objectui init` now versions the project it scaffolds against the CLI that wrote it, and stops writing a `tailwind.config.js` Tailwind 4 never reads.
497
+
498
+ The generated `package.json` asked for `@object-ui/components` and `@object-ui/react` at `^2.0.0` while those packages publish at 17.x, so `npm install` in a fresh scaffold resolved a major unrelated to the CLI that produced it. Both ranges are now derived from the CLI's own version, which is sound because `.changeset/config.json` releases the CLI and every platform package from one `fixed` group. The scaffold's toolchain ranges had drifted the same way — vite `^7.3.1` against the repo's `^8.2.0`, typescript `^5.9.3` against `^6.0.3`, and seven more — and now read from the same table the temp-app generators use rather than from literals of their own.
499
+
500
+ The scaffold's CSS pipeline was already Tailwind 4 (`@tailwindcss/postcss`, `@import 'tailwindcss'`), and v4 reads a JS config only when a stylesheet points `@config` at one. The `tailwind.config.js` written beside it was therefore inert — an authoritative-looking `content` list nothing consumed — and is no longer written.
501
+
502
+ - Updated dependencies [794c497]
503
+ - Updated dependencies [993336f]
504
+ - Updated dependencies [f0a625a]
505
+ - Updated dependencies [b5980f4]
506
+ - Updated dependencies [8aad9fd]
507
+ - Updated dependencies [0cbdca8]
508
+ - Updated dependencies [d229dfa]
509
+ - Updated dependencies [ecae400]
510
+ - Updated dependencies [d3e738a]
511
+ - Updated dependencies [c3b01a7]
512
+ - Updated dependencies [7ed3360]
513
+ - Updated dependencies [0fa5e4d]
514
+ - Updated dependencies [5bfaabd]
515
+ - Updated dependencies [e06810e]
516
+ - Updated dependencies [ab3ad4f]
517
+ - Updated dependencies [c2fd122]
518
+ - Updated dependencies [e24d767]
519
+ - Updated dependencies [aca561a]
520
+ - Updated dependencies [48132f7]
521
+ - Updated dependencies [0ef9dfd]
522
+ - Updated dependencies [0109f54]
523
+ - Updated dependencies [7e5bb5d]
524
+ - Updated dependencies [e6fdbdc]
525
+ - Updated dependencies [54233b1]
526
+ - Updated dependencies [97b63d7]
527
+ - Updated dependencies [7e2b7e9]
528
+ - Updated dependencies [c1e1e6b]
529
+ - @object-ui/components@17.4.0
530
+ - @object-ui/react@17.4.0
531
+ - @object-ui/types@17.4.0
532
+
3
533
  ## 17.3.0
4
534
 
5
535
  ### Patch Changes
@@ -864,6 +1394,7 @@ undefined` — swallowing the very errors the command exists to print. Now reads
864
1394
  - fd15918: Comprehensive i18n refactor + CI test fix.
865
1395
 
866
1396
  **i18n (`@object-ui/i18n`)**
1397
+
867
1398
  - Added ~130 new keys under 12 new top-level namespaces: `layout`, `search`,
868
1399
  `empty`, `renderer`, `actionDialog`, `rowAction`, `navigationSync`,
869
1400
  `objectActions`, `objectViewActions`, `dashboardActions`, `recordDetail`,
@@ -875,6 +1406,7 @@ undefined` — swallowing the very errors the command exists to print. Now reads
875
1406
 
876
1407
  **App shell (`@object-ui/app-shell`)** — replaced hardcoded English in 14
877
1408
  files with `useObjectTranslation`:
1409
+
878
1410
  - Layout: `AppSidebar`, `ActivityFeed` (locale-aware relative time),
879
1411
  `MetadataInspector`.
880
1412
  - Views: `SearchResultsPage`, `ActionParamDialog`, `RecordFormPage`,
@@ -886,12 +1418,14 @@ undefined` — swallowing the very errors the command exists to print. Now reads
886
1418
  `useObjectActions` (delete confirm + success / failure toasts).
887
1419
 
888
1420
  **Plugin grid (`@object-ui/plugin-grid`)**
1421
+
889
1422
  - `ObjectGrid` record-detail panel now translates Empty / Yes / No / System
890
1423
  via the existing `useGridTranslation` safe-fallback wrapper.
891
1424
  - `RowActionMenu` adopts a local safe-fallback i18n wrapper for
892
1425
  `Open menu` / `Edit` / `Delete`, preserving standalone-usage guarantees.
893
1426
 
894
1427
  **CLI test fix (`@object-ui/cli`)**
1428
+
895
1429
  - `cli-bin.test.ts` auto-builds the package on first run when `dist/cli.js`
896
1430
  is missing, instead of throwing. This unbreaks `pnpm test:coverage` in CI
897
1431
  (root vitest run does not honor turbo's `^build` deps) and removes the
@@ -1142,6 +1676,7 @@ undefined` — swallowing the very errors the command exists to print. Now reads
1142
1676
  - New plugin-object and ObjectQL SDK updates
1143
1677
 
1144
1678
  **Added:**
1679
+
1145
1680
  - New Plugin: @object-ui/plugin-object - ObjectQL plugin for automatic table and form generation
1146
1681
  - ObjectTable: Auto-generates tables from ObjectQL object schemas
1147
1682
  - ObjectForm: Auto-generates forms from ObjectQL object schemas with create/edit/view modes
@@ -1150,6 +1685,7 @@ undefined` — swallowing the very errors the command exists to print. Now reads
1150
1685
  - ObjectQL Integration: Enhanced ObjectQLDataSource with getObjectSchema() method using MetadataApiClient
1151
1686
 
1152
1687
  **Changed:**
1688
+
1153
1689
  - Updated @objectql/sdk from ^1.8.3 to ^1.9.1
1154
1690
  - Updated @objectql/types from ^1.8.3 to ^1.9.1
1155
1691
 
@@ -1164,6 +1700,7 @@ undefined` — swallowing the very errors the command exists to print. Now reads
1164
1700
  - Patch release: Add automated changeset workflow and CI/CD improvements
1165
1701
 
1166
1702
  This release includes infrastructure improvements:
1703
+
1167
1704
  - Added changeset-based version management
1168
1705
  - Enhanced CI/CD workflows with GitHub Actions
1169
1706
  - Improved documentation for contributing and releasing
package/README.md CHANGED
@@ -49,6 +49,12 @@ objectui dev --no-open
49
49
  - `-h, --host <host>` — default `localhost`
50
50
  - `--no-open` — do not open browser
51
51
 
52
+ `dev`, `serve` and `build` locate the project the same way: a `pages/` directory
53
+ beside the schema argument means file-system routing (with that file as the app
54
+ config), otherwise a `pages/` directory in the current directory, otherwise the
55
+ named file is rendered on its own. So `objectui build my-app/app.json` from above
56
+ `my-app/` builds the same routes `objectui dev my-app/app.json` serves.
57
+
52
58
  ### `objectui build [schema]`
53
59
 
54
60
  Build the application for production.
@@ -132,14 +138,6 @@ await serve('app.json', { port: '3000', host: 'localhost' });
132
138
  await init('my-app', { template: 'dashboard' });
133
139
  ```
134
140
 
135
- ## Compatibility
136
-
137
- - **Node.js** ≥ 18
138
- - **TypeScript** ≥ 5.0 (strict mode)
139
- - **`@objectstack/spec`** ^3.3.0
140
- - **`@objectstack/client`** ^3.3.0
141
- - **Tailwind CSS** ≥ 3.4
142
-
143
141
  ## Links
144
142
 
145
143
  - 📚 [Documentation](https://www.objectui.org/docs/utilities/cli)