@object-ui/core 11.2.0 → 11.4.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,40 @@
1
1
  # @object-ui/core
2
2
 
3
+ ## 11.4.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [8bf6295]
8
+ - Updated dependencies [1948c5b]
9
+ - Updated dependencies [c38d107]
10
+ - @object-ui/types@11.4.0
11
+
12
+ ## 11.3.0
13
+
14
+ ### Minor Changes
15
+
16
+ - d23d6eb: Three-tier AI page authoring: `kind:'html'` and a trusted `kind:'react'` tier.
17
+
18
+ - **`@object-ui/react-runtime`** (new) — the trusted runtime-React tier for
19
+ `kind:'react'` pages (vendored react-runner: Sucrase transpile + scope-eval,
20
+ no sandbox). Renders real JSX/TSX (any HTML + JS + hooks/useState/map/onClick)
21
+ in the main React tree with an injected scope (React, the public data blocks,
22
+ page data) and a built-in error boundary.
23
+ - **`@object-ui/core`** — new runtime capability gate (`enableCapability` /
24
+ `disableCapability` / `isCapabilityEnabled`, `CAP_REACT_PAGES`). `react-pages`
25
+ defaults **ON** (the platform trusts reviewed, draft-gated authors); a
26
+ deployment turns it OFF server-side (the runtime injects the disable global
27
+ when `OS_DISABLE_REACT_PAGES` is set). Never controlled from authored metadata.
28
+ - **`@object-ui/components`** — PageRenderer now routes `kind:'react'`
29
+ (capability-gated, lazy-loads the runtime) and renders `kind:'html'` (the
30
+ former `kind:'jsx'`, still accepted as a deprecated alias). The `html` tier
31
+ now resolves the full safe native HTML tag set (h1–h6, p, a, ul/ol/li, img,
32
+ blockquote, pre, strong/em, …) so authored HTML lives up to its name.
33
+
34
+ ### Patch Changes
35
+
36
+ - @object-ui/types@11.3.0
37
+
3
38
  ## 11.2.0
4
39
 
5
40
  ### Minor Changes
package/dist/index.d.ts CHANGED
@@ -29,6 +29,7 @@ export * from './utils/merge-views-into-objects.js';
29
29
  export * from './utils/freeze-schema.js';
30
30
  export * from './protocols/index.js';
31
31
  export * from './styling/scoped-styles.js';
32
+ export * from './runtime/capabilities.js';
32
33
  /**
33
34
  * @deprecated Import `composeStacks` from `@objectstack/spec` instead.
34
35
  *
@@ -41,3 +42,4 @@ export * from './utils/date-macros.js';
41
42
  export * from './utils/compare-to.js';
42
43
  export * from './utils/chart-series.js';
43
44
  export * from './utils/dataset-format.js';
45
+ export * from './utils/record-title.js';
package/dist/index.js CHANGED
@@ -28,6 +28,7 @@ export * from './utils/merge-views-into-objects.js';
28
28
  export * from './utils/freeze-schema.js';
29
29
  export * from './protocols/index.js';
30
30
  export * from './styling/scoped-styles.js';
31
+ export * from './runtime/capabilities.js';
31
32
  /**
32
33
  * @deprecated Import `composeStacks` from `@objectstack/spec` instead.
33
34
  *
@@ -40,3 +41,4 @@ export * from './utils/date-macros.js';
40
41
  export * from './utils/compare-to.js';
41
42
  export * from './utils/chart-series.js';
42
43
  export * from './utils/dataset-format.js';
44
+ export * from './utils/record-title.js';
@@ -0,0 +1,35 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ *
8
+ * Runtime capability gates — switches a *host* controls, never authored
9
+ * metadata. Each capability has a default; a host can flip it explicitly
10
+ * (`enableCapability`/`disableCapability`) or seed it from globals before any
11
+ * bundle code runs.
12
+ *
13
+ * {@link CAP_REACT_PAGES} (`kind:'react'` — execute author JavaScript in the
14
+ * main React tree) defaults **ON**: ObjectStack pages are authored by trusted
15
+ * authors and pass human review (draft-gating, ADR-0033), so the platform
16
+ * trusts them by default. A deployment that does NOT trust its page authors
17
+ * turns it off server-side — the ObjectStack runtime injects the disable global
18
+ * when `OS_PAGE_REACT=off` (see framework cli/utils/console.ts).
19
+ *
20
+ * Globals a host/server can set in the page before the bundle runs:
21
+ * - `globalThis.__OBJECTUI_CAPABILITIES__` — string[] to force ON
22
+ * - `globalThis.__OBJECTUI_CAPABILITIES_DISABLED__` — string[] to force OFF
23
+ */
24
+ /** Turn a capability on. Call from the host process only (not from metadata). */
25
+ export declare function enableCapability(name: string): void;
26
+ /** Turn a capability off. */
27
+ export declare function disableCapability(name: string): void;
28
+ /** Whether a capability is enabled. Host/global override wins over the default. */
29
+ export declare function isCapabilityEnabled(name: string): boolean;
30
+ /**
31
+ * `kind:'react'` — execute trusted author JavaScript (full React: hooks, event
32
+ * handlers, arbitrary JS) directly in the main React tree. Default ON; a
33
+ * deployment disables it server-side with `OS_PAGE_REACT=off`.
34
+ */
35
+ export declare const CAP_REACT_PAGES = "react-pages";
@@ -0,0 +1,72 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ *
8
+ * Runtime capability gates — switches a *host* controls, never authored
9
+ * metadata. Each capability has a default; a host can flip it explicitly
10
+ * (`enableCapability`/`disableCapability`) or seed it from globals before any
11
+ * bundle code runs.
12
+ *
13
+ * {@link CAP_REACT_PAGES} (`kind:'react'` — execute author JavaScript in the
14
+ * main React tree) defaults **ON**: ObjectStack pages are authored by trusted
15
+ * authors and pass human review (draft-gating, ADR-0033), so the platform
16
+ * trusts them by default. A deployment that does NOT trust its page authors
17
+ * turns it off server-side — the ObjectStack runtime injects the disable global
18
+ * when `OS_PAGE_REACT=off` (see framework cli/utils/console.ts).
19
+ *
20
+ * Globals a host/server can set in the page before the bundle runs:
21
+ * - `globalThis.__OBJECTUI_CAPABILITIES__` — string[] to force ON
22
+ * - `globalThis.__OBJECTUI_CAPABILITIES_DISABLED__` — string[] to force OFF
23
+ */
24
+ /** Default state per capability when neither the host nor a global overrides it. */
25
+ const DEFAULTS = {
26
+ 'react-pages': true,
27
+ };
28
+ // Explicit host overrides (enable/disable) — win over defaults and globals.
29
+ const overrides = new Map();
30
+ let _seeded = false;
31
+ function seedFromGlobals() {
32
+ if (_seeded)
33
+ return;
34
+ _seeded = true;
35
+ const g = globalThis;
36
+ if (Array.isArray(g.__OBJECTUI_CAPABILITIES__)) {
37
+ for (const c of g.__OBJECTUI_CAPABILITIES__)
38
+ if (typeof c === 'string' && !overrides.has(c))
39
+ overrides.set(c, true);
40
+ }
41
+ if (Array.isArray(g.__OBJECTUI_CAPABILITIES_DISABLED__)) {
42
+ // Disable wins: a server that turned something off must not be overridden
43
+ // by a stale enable-list left in the same page.
44
+ for (const c of g.__OBJECTUI_CAPABILITIES_DISABLED__)
45
+ if (typeof c === 'string')
46
+ overrides.set(c, false);
47
+ }
48
+ }
49
+ /** Turn a capability on. Call from the host process only (not from metadata). */
50
+ export function enableCapability(name) {
51
+ seedFromGlobals();
52
+ overrides.set(name, true);
53
+ }
54
+ /** Turn a capability off. */
55
+ export function disableCapability(name) {
56
+ seedFromGlobals();
57
+ overrides.set(name, false);
58
+ }
59
+ /** Whether a capability is enabled. Host/global override wins over the default. */
60
+ export function isCapabilityEnabled(name) {
61
+ seedFromGlobals();
62
+ const o = overrides.get(name);
63
+ if (o !== undefined)
64
+ return o;
65
+ return DEFAULTS[name] ?? false;
66
+ }
67
+ /**
68
+ * `kind:'react'` — execute trusted author JavaScript (full React: hooks, event
69
+ * handlers, arbitrary JS) directly in the main React tree. Default ON; a
70
+ * deployment disables it server-side with `OS_PAGE_REACT=off`.
71
+ */
72
+ export const CAP_REACT_PAGES = 'react-pages';
@@ -0,0 +1,98 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ /**
9
+ * Render a record title from a `titleFormat` pattern.
10
+ *
11
+ * Accepts either a legacy string template or an Expression envelope
12
+ * (`{ dialect: 'template', source: string }`) emitted by `@objectstack/spec`'s
13
+ * normalized templates. Both single-brace (`{field}`) and double-brace
14
+ * (`{{field}}`, the handlebars-style some authoring paths emit) placeholders are
15
+ * supported. Dotted paths (`{account.name}`) walk `$expanded` lookup objects; a
16
+ * placeholder that resolves to a whole object is reduced to its display name.
17
+ *
18
+ * Empty placeholders (missing / null / empty fields) are stripped along with
19
+ * any orphan separator they leave behind, so `"{full_name} - {company}"`
20
+ * evaluated against `{ company: "Acme" }` yields `"Acme"`, not `" - Acme"`.
21
+ * Returns an empty string when no placeholder resolved.
22
+ */
23
+ export declare function formatTitleTemplate(titleFormat: string | {
24
+ source?: string;
25
+ } | undefined | null, record: any): string;
26
+ /**
27
+ * Decide whether a field definition can serve as a record title. Excludes the
28
+ * {@link NON_TITLE_TYPES} (dates, numbers, pickers, lookups, binary, …); a
29
+ * `formula` is eligible only when it returns text. A field with no declared
30
+ * type is treated as eligible (text-by-default), so loosely-typed metadata
31
+ * still produces a name rather than falling through to `Record #…`.
32
+ */
33
+ export declare function isTitleEligibleField(def: any): boolean;
34
+ /**
35
+ * Type-aware derivation (precedence step 4): pick the best title-eligible field
36
+ * name from `objectDef.fields`, ranked:
37
+ *
38
+ * 1. name-ish exact — `name`,`title`,`subject`,`label`,`full_name`,
39
+ * `display_name` (case-insensitive)
40
+ * 2. name-ish affix — `*_name`, `*_title`, `name_*` (case-insensitive)
41
+ * 3. declaration order — first remaining title-eligible field
42
+ *
43
+ * Returns the field name, or undefined when `fields` is absent/empty or holds
44
+ * no title-eligible field.
45
+ *
46
+ * Memoized per `objectDef` identity (see {@link deriveTitleFieldCache}): the
47
+ * field scan runs once per object definition, not once per record. The result is
48
+ * byte-identical to the uncached computation — only the scan is cached, and only
49
+ * when `objectDef` is a non-null object (the WeakMap key requirement).
50
+ */
51
+ export declare function deriveTitleField(objectDef: any): string | undefined;
52
+ export interface RecordDisplayNameOptions {
53
+ /**
54
+ * Optional explicit title field (e.g. a view's `titleField` / gallery
55
+ * `titleField` / kanban `cardTitle`). When set and it yields a non-empty
56
+ * value on the record, it wins over everything — preserving each view's
57
+ * author-chosen field. Pass nothing to use the object-level precedence only.
58
+ */
59
+ titleField?: string;
60
+ /** Floor when the record has no id at all. Defaults to `'Untitled'`. */
61
+ fallback?: string;
62
+ /**
63
+ * Whether to probe standard name-ish keys (`name`/`title`/…) directly on the
64
+ * record when `objectDef.fields` is absent (precedence step 3b). Defaults to
65
+ * `true`. Callers that have a better generic fallback to interleave (e.g. the
66
+ * detail header prefers `schema.title`, the object label, over a guessed
67
+ * record key) pass `false` so this step is skipped and the resolver returns
68
+ * its `Record #<id>` floor instead — letting the caller decide.
69
+ */
70
+ deriveFromRecordKeys?: boolean;
71
+ }
72
+ /**
73
+ * THE unified record display-name resolver (ADR-0079).
74
+ *
75
+ * Precedence (ADR-0079 Phase 2 makes the object's declared field canonical and
76
+ * de-prioritizes the legacy `titleFormat` template):
77
+ * 0. `options.titleField`, then `objectDef.titleField` (when provided &
78
+ * non-empty on the record) — lets a view / object keep its author-chosen
79
+ * title field.
80
+ * 1. `objectDef.nameField` — the NEW canonical record-title pointer
81
+ * (ADR-0079). A field name the server can return and query.
82
+ * 2. `objectDef.displayNameField` / `objectDef.NAME_FIELD_KEY` — the
83
+ * deprecated alias of `nameField`, kept for back-compat.
84
+ * 3. `objectDef.titleFormat` (rendered template) — LEGACY, render-only, kept
85
+ * for back-compat only; an explicitly-declared field (1/2) now wins over
86
+ * it. See the deprecation note on the branch below.
87
+ * 4. type-aware derivation from `objectDef.fields` ({@link deriveTitleField}).
88
+ * 4b. standard name-ish keys probed directly on the record
89
+ * ({@link NAME_ISH_RECORD_KEYS}) — the safety net for when `fields` is
90
+ * absent so derivation can't run.
91
+ * 5. `Record #<id>` (using `record.id ?? record._id`), else `options.fallback`
92
+ * (default `'Untitled'`) for a truly id-less record.
93
+ *
94
+ * @param objectDef Object definition (may be `any`/partial — every field is
95
+ * read defensively).
96
+ * @param record The record data.
97
+ */
98
+ export declare function getRecordDisplayName(objectDef: any, record: any, options?: RecordDisplayNameOptions): string;
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@object-ui/core",
3
- "version": "11.2.0",
3
+ "version": "11.4.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "license": "MIT",
@@ -25,11 +25,11 @@
25
25
  }
26
26
  },
27
27
  "dependencies": {
28
- "@objectstack/formula": "^11.0.0",
29
- "@objectstack/spec": "^11.0.0",
28
+ "@objectstack/formula": "^11.5.0",
29
+ "@objectstack/spec": "^11.7.0",
30
30
  "lodash": "^4.18.1",
31
31
  "zod": "^4.4.3",
32
- "@object-ui/types": "11.2.0"
32
+ "@object-ui/types": "11.4.0"
33
33
  },
34
34
  "devDependencies": {
35
35
  "typescript": "^6.0.3",