@ultimat3/admin 7.0.0 → 9.0.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/CLAUDE.md +1 -0
- package/package.json +16 -16
- package/src/inert-jsx.ts +21 -26
package/CLAUDE.md
CHANGED
|
@@ -34,6 +34,7 @@ Two products, one package, **two entry points**: `@ultimat3/admin/dev` (`src/dev
|
|
|
34
34
|
- **One cursor codec.** `pagination.ts` is the only file calling core's `encodeCursor`/`decodeCursor`; it wraps them as `encodeAdminCursor`/`decodeAdminCursor`, scoped `admin:<resource>`. An invalid cursor is page one here, not an error page — but the signature is checked first, so a forged one cannot seek.
|
|
35
35
|
- Labels are i18n keys derived in `resource.ts` (`admin.<entity>.field.<name>`); only `.tsx` calls `t()`. MCP tool descriptions are literal English (protocol payload, not UI copy).
|
|
36
36
|
- Colours only via `ThemeTokenRef` (`--x-*`). Raw hex does not typecheck.
|
|
37
|
+
- **One owner of `globalThis.React`, and it is `@ultimat3/ui`'s.** `inert-jsx.ts` keeps the walkers (`nodesOf`, `shallowNodesOf`, `renderNodes`, `renderHtml`) and delegates install/restore to `probe`/`unprobe` from `@ultimat3/ui/jsx-probe` — tier 5 → tier 4, downward, no declared edge needed. It kept its own `depth`/`saved` pair until 2026-08-22 and two counters over one property restore in the wrong order: admin installs (saving the real binding), ui installs (saving ADMIN's factory), admin restores, ui restores admin's factory back over the top. `bun test` seats both packages in one process, so the interleave is reachable; `inert-jsx.test.ts` drives it in both orders.
|
|
37
38
|
- Views are pure functions of props — no `createSignal`, no local state; the route owns it.
|
|
38
39
|
|
|
39
40
|
## Layout
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ultimat3/admin",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.0.0",
|
|
4
4
|
"description": "Two dashboards: the /_x framework dev panels and the generated, AI-first app admin",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -32,20 +32,20 @@
|
|
|
32
32
|
"test": "bun test"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@ultimat3/action": "
|
|
36
|
-
"@ultimat3/ai": "
|
|
37
|
-
"@ultimat3/cache": "
|
|
38
|
-
"@ultimat3/core": "
|
|
39
|
-
"@ultimat3/db": "
|
|
40
|
-
"@ultimat3/entity": "
|
|
41
|
-
"@ultimat3/i18n": "
|
|
42
|
-
"@ultimat3/jobs": "
|
|
43
|
-
"@ultimat3/mcp": "
|
|
44
|
-
"@ultimat3/money": "
|
|
45
|
-
"@ultimat3/policy": "
|
|
46
|
-
"@ultimat3/query": "
|
|
47
|
-
"@ultimat3/render": "
|
|
48
|
-
"@ultimat3/schema": "
|
|
49
|
-
"@ultimat3/ui": "
|
|
35
|
+
"@ultimat3/action": "9.0.0",
|
|
36
|
+
"@ultimat3/ai": "9.0.0",
|
|
37
|
+
"@ultimat3/cache": "9.0.0",
|
|
38
|
+
"@ultimat3/core": "9.0.0",
|
|
39
|
+
"@ultimat3/db": "9.0.0",
|
|
40
|
+
"@ultimat3/entity": "9.0.0",
|
|
41
|
+
"@ultimat3/i18n": "9.0.0",
|
|
42
|
+
"@ultimat3/jobs": "9.0.0",
|
|
43
|
+
"@ultimat3/mcp": "9.0.0",
|
|
44
|
+
"@ultimat3/money": "9.0.0",
|
|
45
|
+
"@ultimat3/policy": "9.0.0",
|
|
46
|
+
"@ultimat3/query": "9.0.0",
|
|
47
|
+
"@ultimat3/render": "9.0.0",
|
|
48
|
+
"@ultimat3/schema": "9.0.0",
|
|
49
|
+
"@ultimat3/ui": "9.0.0"
|
|
50
50
|
}
|
|
51
51
|
}
|
package/src/inert-jsx.ts
CHANGED
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
// both and the run's file order stops deciding. Recognising neither is what falls through to
|
|
9
9
|
// `String(value)` and asserts against `"[object Object]"`.
|
|
10
10
|
|
|
11
|
+
// The subpath, never the barrel: this is a test harness and the design system's `index.ts` is its
|
|
12
|
+
// semver'd contract (`packages/ui/CLAUDE.md`). It is imported for `globalThis.React`'s ONE counter.
|
|
13
|
+
import { probe, unprobe } from '@ultimat3/ui/jsx-probe';
|
|
14
|
+
|
|
11
15
|
/** `@ultimat3/render`'s node brand, read off the GLOBAL symbol registry rather than imported. */
|
|
12
16
|
const RENDER_NODE: symbol = Symbol.for('ultimate.render.jsx');
|
|
13
17
|
|
|
@@ -23,7 +27,11 @@ export function isInertNode(value: unknown): value is InertNode {
|
|
|
23
27
|
return 'inert' in value || RENDER_NODE in value;
|
|
24
28
|
}
|
|
25
29
|
|
|
26
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* Build a node by hand, the shape the installed factory builds. NOT the installed factory — that is
|
|
32
|
+
* `@ultimat3/ui`'s, so there is one owner of `globalThis.React` (see `installFactory` below). This
|
|
33
|
+
* is what a test uses to construct a tree it did not render.
|
|
34
|
+
*/
|
|
27
35
|
export function h(
|
|
28
36
|
type: string | InertComponent,
|
|
29
37
|
props: Record<string, unknown> | null,
|
|
@@ -35,37 +43,24 @@ export function h(
|
|
|
35
43
|
}
|
|
36
44
|
|
|
37
45
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
46
|
+
* Install the classic-factory global, through `@ultimat3/ui`'s ONE counter over `globalThis.React`.
|
|
47
|
+
*
|
|
48
|
+
* This package kept its own `depth`/`saved` pair until 2026-08-22, and two counters over one
|
|
49
|
+
* property restore in the wrong order: admin installs (saving the real binding), ui installs
|
|
50
|
+
* (saving ADMIN's factory), admin restores (its counter hits 0 → the real binding is back), ui
|
|
51
|
+
* restores (its counter hits 0 → admin's factory goes back over it). `bun test` is one process and
|
|
52
|
+
* `packages/ui` and `packages/admin` are one run, so the interleave is reachable, and the global
|
|
53
|
+
* was left holding a harness the run had already torn down. `admin` is tier 5 and `ui` is tier 4,
|
|
54
|
+
* so importing down is the fix; the two factories build the same `{ inert, type, props }` shape,
|
|
55
|
+
* which is what `isInertNode` recognises.
|
|
42
56
|
*/
|
|
43
|
-
let depth = 0;
|
|
44
|
-
let saved: PropertyDescriptor | undefined;
|
|
45
|
-
|
|
46
57
|
export function installFactory(): void {
|
|
47
|
-
|
|
48
|
-
// The descriptor, not the value: the property may be a getter or non-writable, and `assign`
|
|
49
|
-
// onto either throws or silently loses.
|
|
50
|
-
saved = Object.getOwnPropertyDescriptor(globalThis, 'React');
|
|
51
|
-
Object.defineProperty(globalThis, 'React', {
|
|
52
|
-
value: { createElement: h },
|
|
53
|
-
configurable: true,
|
|
54
|
-
writable: true,
|
|
55
|
-
enumerable: true,
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
depth += 1;
|
|
58
|
+
probe();
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
/** Undo the matching `installFactory()`. Unbalanced calls are inert. */
|
|
62
62
|
export function restoreFactory(): void {
|
|
63
|
-
|
|
64
|
-
depth -= 1;
|
|
65
|
-
if (depth > 0) return;
|
|
66
|
-
if (saved === undefined) Reflect.deleteProperty(globalThis, 'React');
|
|
67
|
-
else Object.defineProperty(globalThis, 'React', saved);
|
|
68
|
-
saved = undefined;
|
|
63
|
+
unprobe();
|
|
69
64
|
}
|
|
70
65
|
|
|
71
66
|
/**
|