@svadmin/surface 0.12.0 → 0.13.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 CHANGED
@@ -13,7 +13,7 @@ the `minimum-supported` strict install and consumer checks in `pack:check` to
13
13
  pass against registry artifacts; workspace tarballs do not replace that check.
14
14
 
15
15
  ```bash
16
- bun add @svadmin/surface @svadmin/core @svadmin/ui @tanstack/svelte-query svelte @sinclair/typebox
16
+ bun add @svadmin/surface @svadmin/core @svadmin/ui @tanstack/svelte-query svelte typebox
17
17
  ```
18
18
 
19
19
  Import protocol types and validation from the DOM-free root entry. Import rendering code from the Svelte subpath. Hosts do not need CSS compiler plugins to consume the package's static component styles.
@@ -157,8 +157,8 @@ Preview controls use local finite class helpers and maintained static CSS. `@sva
157
157
  The catalog version is `svadmin/v1`. `catalogVersion` must match exactly. Custom registrations use strict TypeBox props schemas and trusted Svelte components. Item widgets reading record fields must expose them through `getReferencedFields` so runtime validation checks `SurfacePolicy.readFields`.
158
158
 
159
159
  ```ts
160
- import { Type } from '@sinclair/typebox';
161
- import { Value } from '@sinclair/typebox/value';
160
+ import { Type } from 'typebox';
161
+ import { Value } from 'typebox/value';
162
162
 
163
163
  const statusProps = Type.Object({ statusField: Type.String() }, { additionalProperties: false });
164
164
  const catalog = defineSurfaceCatalog({
@@ -1,5 +1,5 @@
1
1
  {
2
- "surface": "0.12.x",
2
+ "surface": "0.13.x",
3
3
  "minimumSupported": {
4
4
  "@svadmin/core": "0.53.0",
5
5
  "@svadmin/ui": "0.73.0",
@@ -1,4 +1,4 @@
1
- import { type TSchema } from '@sinclair/typebox';
1
+ import { Type, type TSchema } from 'typebox';
2
2
  import { type JsonObject, type SurfaceCatalog, type SurfacePolicy } from './types.js';
3
3
  export declare const SURFACE_CATALOG_SCHEMA_VERSION: "surface-catalog/v1";
4
4
  export declare const SURFACE_AGENT_SCHEMA_VERSION: "surface-agent/v1";
@@ -29,9 +29,9 @@ export declare function createSurfaceCatalogManifest(catalog: SurfaceCatalog): S
29
29
  /** 生成约束缩小候选空间,不能代替绑定/字段关联校验,更不能代替后端授权。 */
30
30
  export declare function createSurfaceGenerationSpecSchema(catalog: SurfaceCatalog, policy: SurfacePolicy): TSchema;
31
31
  export declare function createSurfaceAgentResponseSchema(catalog: SurfaceCatalog, policy: SurfacePolicy): JsonObject;
32
- export declare const surfaceCannotFulfillSchema: import("@sinclair/typebox").TObject<{
33
- schemaVersion: import("@sinclair/typebox").TLiteral<"surface-agent/v2">;
34
- action: import("@sinclair/typebox").TLiteral<"cannot-fulfill">;
35
- reason: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"unsupported_request">, import("@sinclair/typebox").TLiteral<"insufficient_permissions">, import("@sinclair/typebox").TLiteral<"insufficient_context">]>;
36
- message: import("@sinclair/typebox").TString;
32
+ export declare const surfaceCannotFulfillSchema: Type.TObject<{
33
+ schemaVersion: Type.TLiteral<"surface-agent/v2">;
34
+ action: Type.TLiteral<"cannot-fulfill">;
35
+ reason: Type.TUnion<[Type.TLiteral<"unsupported_request">, Type.TLiteral<"insufficient_permissions">, Type.TLiteral<"insufficient_context">]>;
36
+ message: Type.TString;
37
37
  }>;
@@ -1,5 +1,5 @@
1
- import { Kind, OptionalKind, ReadonlyKind, Type } from '@sinclair/typebox';
2
- import { Value } from '@sinclair/typebox/value';
1
+ import { Type } from 'typebox';
2
+ import { Value } from 'typebox/value';
3
3
  import { escapedJsonPointerToken, jsonValueIssue } from './json.js';
4
4
  import { surfaceFilterSchema, surfaceIdSchema, surfaceListSourceSchema, surfaceOneSourceSchema, surfaceSpecSchema, surfaceWidgetSchema, } from './schema.js';
5
5
  import { SURFACE_LIMITS, SURFACE_SCHEMA_VERSION, } from './types.js';
@@ -11,6 +11,8 @@ export const SURFACE_AGENT_LIMITS = {
11
11
  maxRequestCharacters: 16_384,
12
12
  maxContractCharacters: 131_072,
13
13
  };
14
+ /** Scalar TypeBox 1.x markers that are dropped when serializing a schema to JSON. */
15
+ const SURFACE_MARKERS = new Set(['~kind', '~optional', '~readonly', '~immutable']);
14
16
  /** 不把 Transform、函数或引用 schema 静默降级为宽松的 JSON schema。 */
15
17
  export function surfaceSchemaToJson(schema) {
16
18
  const ancestors = new Set();
@@ -37,10 +39,14 @@ export function surfaceSchemaToJson(schema) {
37
39
  if (Array.isArray(value) && key === 'length')
38
40
  continue;
39
41
  if (typeof key === 'symbol') {
40
- if (key === Kind || key === OptionalKind || key === ReadonlyKind)
41
- continue;
42
42
  throw new Error('Surface schema contains unsupported symbol metadata or a transform');
43
43
  }
44
+ if (key.startsWith('~')) {
45
+ if (!SURFACE_MARKERS.has(key)) {
46
+ throw new Error('Surface schema contains unsupported transform or metadata');
47
+ }
48
+ continue;
49
+ }
44
50
  if (['__proto__', 'constructor', 'prototype', '$ref', '$dynamicRef', '$recursiveRef'].includes(key)) {
45
51
  throw new Error(`Surface schema key "${key}" is not supported; use an inline schema`);
46
52
  }
package/dist/agent.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type Static } from '@sinclair/typebox';
1
+ import { type Static } from 'typebox';
2
2
  import { SURFACE_AGENT_RESPONSE_SCHEMA_VERSION, SURFACE_AGENT_SCHEMA_VERSION, surfaceCannotFulfillSchema } from './agent-contract.js';
3
3
  import type { SurfaceCatalog, SurfacePolicy, SurfaceSpec, SurfaceValidationIssue } from './types.js';
4
4
  export { SURFACE_AGENT_SCHEMA_VERSION } from './agent-contract.js';
package/dist/agent.js CHANGED
@@ -1,7 +1,7 @@
1
- import { Type } from '@sinclair/typebox';
2
- import { TypeCompiler } from '@sinclair/typebox/compiler';
1
+ import { Type } from 'typebox';
2
+ import { Compile } from 'typebox/compile';
3
3
  import { SURFACE_AGENT_LIMITS, SURFACE_AGENT_RESPONSE_SCHEMA_VERSION, SURFACE_AGENT_SCHEMA_VERSION, createSurfaceAgentResponseSchema, createSurfaceCatalogManifest, createSurfaceGenerationSpecSchema, surfaceCannotFulfillSchema, surfaceSchemaToJson, } from './agent-contract.js';
4
- import { validateSurfaceSpec } from './validation.js';
4
+ import { validateSurfaceSpec, surfaceSchemaIssues } from './validation.js';
5
5
  import { parseSurfaceJson, surfaceWireError } from './wire.js';
6
6
  export { SURFACE_AGENT_SCHEMA_VERSION } from './agent-contract.js';
7
7
  const proposalFields = {
@@ -15,12 +15,12 @@ const responseProposalSchema = Type.Object({
15
15
  ...proposalFields,
16
16
  schemaVersion: Type.Literal(SURFACE_AGENT_RESPONSE_SCHEMA_VERSION),
17
17
  }, { additionalProperties: false });
18
- const compiledProposalSchema = TypeCompiler.Compile(proposalSchema);
19
- const compiledResponseSchema = TypeCompiler.Compile(Type.Union([
18
+ const compiledProposalSchema = Compile(proposalSchema);
19
+ const compiledResponseSchema = Compile(Type.Union([
20
20
  proposalSchema, responseProposalSchema, surfaceCannotFulfillSchema,
21
21
  ]));
22
22
  function schemaIssues(errors) {
23
- return [...errors].map((issue) => ({ code: 'invalid_json', path: issue.path || '', message: issue.message }));
23
+ return surfaceSchemaIssues(errors).map((issue) => ({ code: 'invalid_json', path: issue.path || '', message: issue.message }));
24
24
  }
25
25
  /** 保留 v1 的函数签名、返回类型以及带说明文字的 fenced JSON 兼容行为。 */
26
26
  export function parseSurfaceAgentProposal(input, catalog, policy) {
@@ -1,4 +1,4 @@
1
- import { Value } from '@sinclair/typebox/value';
1
+ import { Value } from 'typebox/value';
2
2
  import { styledMetricPropsSchema, styledResourceTablePropsSchema, barChartPropsSchema, lineChartPropsSchema, metricPropsSchema, resourceTablePropsSchema, } from './builtin-schemas.js';
3
3
  export const DEFAULT_SURFACE_CATALOG_VERSION = 'svadmin/v1';
4
4
  export const STYLED_SURFACE_CATALOG_VERSION = 'svadmin/styled-v1';
@@ -1,63 +1,63 @@
1
- import { type Static } from "@sinclair/typebox";
2
- export declare const metricPropsSchema: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
3
- label: import("@sinclair/typebox").TString;
4
- format: import("@sinclair/typebox").TLiteral<"currency">;
5
- currency: import("@sinclair/typebox").TString;
6
- description: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
7
- }>, import("@sinclair/typebox").TObject<{
8
- label: import("@sinclair/typebox").TString;
9
- format: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"number">, import("@sinclair/typebox").TLiteral<"percent">]>;
10
- currency: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNever>;
11
- description: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
1
+ import { Type, type Static } from "typebox";
2
+ export declare const metricPropsSchema: Type.TUnion<[Type.TObject<{
3
+ label: Type.TString;
4
+ format: Type.TLiteral<"currency">;
5
+ currency: Type.TString;
6
+ description: Type.TOptional<Type.TString>;
7
+ }>, Type.TObject<{
8
+ label: Type.TString;
9
+ format: Type.TUnion<[Type.TLiteral<"number">, Type.TLiteral<"percent">]>;
10
+ currency: Type.TOptional<Type.TNever>;
11
+ description: Type.TOptional<Type.TString>;
12
12
  }>]>;
13
- export declare const resourceTablePropsSchema: import("@sinclair/typebox").TObject<{
14
- title: import("@sinclair/typebox").TString;
15
- emptyLabel: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
16
- columns: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
17
- field: import("@sinclair/typebox").TString;
18
- label: import("@sinclair/typebox").TString;
19
- format: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"text">, import("@sinclair/typebox").TLiteral<"number">, import("@sinclair/typebox").TLiteral<"date">, import("@sinclair/typebox").TLiteral<"boolean">]>>;
13
+ export declare const resourceTablePropsSchema: Type.TObject<{
14
+ title: Type.TString;
15
+ emptyLabel: Type.TOptional<Type.TString>;
16
+ columns: Type.TArray<Type.TObject<{
17
+ field: Type.TString;
18
+ label: Type.TString;
19
+ format: Type.TOptional<Type.TUnion<[Type.TLiteral<"text">, Type.TLiteral<"number">, Type.TLiteral<"date">, Type.TLiteral<"boolean">]>>;
20
20
  }>>;
21
21
  }>;
22
- export declare const barChartPropsSchema: import("@sinclair/typebox").TObject<{
23
- title: import("@sinclair/typebox").TString;
24
- labelField: import("@sinclair/typebox").TString;
25
- valueField: import("@sinclair/typebox").TString;
26
- showValues: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
22
+ export declare const barChartPropsSchema: Type.TObject<{
23
+ title: Type.TString;
24
+ labelField: Type.TString;
25
+ valueField: Type.TString;
26
+ showValues: Type.TOptional<Type.TBoolean>;
27
27
  }>;
28
- export declare const lineChartPropsSchema: import("@sinclair/typebox").TObject<{
29
- title: import("@sinclair/typebox").TString;
30
- labelField: import("@sinclair/typebox").TString;
31
- valueField: import("@sinclair/typebox").TString;
32
- showDots: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
33
- fill: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
28
+ export declare const lineChartPropsSchema: Type.TObject<{
29
+ title: Type.TString;
30
+ labelField: Type.TString;
31
+ valueField: Type.TString;
32
+ showDots: Type.TOptional<Type.TBoolean>;
33
+ fill: Type.TOptional<Type.TBoolean>;
34
34
  }>;
35
35
  export type MetricProps = Static<typeof metricPropsSchema>;
36
36
  export type ResourceTableProps = Static<typeof resourceTablePropsSchema>;
37
37
  export type BarChartProps = Static<typeof barChartPropsSchema>;
38
38
  export type LineChartProps = Static<typeof lineChartPropsSchema>;
39
- export declare const styledMetricPropsSchema: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
40
- tone: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<import("@sinclair/typebox").TLiteral<"info" | "warning" | "success" | "neutral" | "danger">[]>>;
41
- density: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<import("@sinclair/typebox").TLiteral<"compact" | "comfortable">[]>>;
42
- label: import("@sinclair/typebox").TString;
43
- format: import("@sinclair/typebox").TLiteral<"currency">;
44
- currency: import("@sinclair/typebox").TString;
45
- description: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
46
- }>, import("@sinclair/typebox").TObject<{
47
- tone: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<import("@sinclair/typebox").TLiteral<"info" | "warning" | "success" | "neutral" | "danger">[]>>;
48
- density: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<import("@sinclair/typebox").TLiteral<"compact" | "comfortable">[]>>;
49
- label: import("@sinclair/typebox").TString;
50
- format: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"number">, import("@sinclair/typebox").TLiteral<"percent">]>;
51
- currency: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNever>;
52
- description: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
39
+ export declare const styledMetricPropsSchema: Type.TUnion<[Type.TObject<{
40
+ tone: Type.TOptional<Type.TUnion<Type.TLiteral<"info" | "warning" | "success" | "neutral" | "danger">[]>>;
41
+ density: Type.TOptional<Type.TUnion<Type.TLiteral<"compact" | "comfortable">[]>>;
42
+ label: Type.TString;
43
+ format: Type.TLiteral<"currency">;
44
+ currency: Type.TString;
45
+ description: Type.TOptional<Type.TString>;
46
+ }>, Type.TObject<{
47
+ tone: Type.TOptional<Type.TUnion<Type.TLiteral<"info" | "warning" | "success" | "neutral" | "danger">[]>>;
48
+ density: Type.TOptional<Type.TUnion<Type.TLiteral<"compact" | "comfortable">[]>>;
49
+ label: Type.TString;
50
+ format: Type.TUnion<[Type.TLiteral<"number">, Type.TLiteral<"percent">]>;
51
+ currency: Type.TOptional<Type.TNever>;
52
+ description: Type.TOptional<Type.TString>;
53
53
  }>]>;
54
- export declare const styledResourceTablePropsSchema: import("@sinclair/typebox").TObject<{
55
- density: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<import("@sinclair/typebox").TLiteral<"compact" | "comfortable">[]>>;
56
- title: import("@sinclair/typebox").TString;
57
- emptyLabel: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
58
- columns: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
59
- field: import("@sinclair/typebox").TString;
60
- label: import("@sinclair/typebox").TString;
61
- format: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"text">, import("@sinclair/typebox").TLiteral<"number">, import("@sinclair/typebox").TLiteral<"date">, import("@sinclair/typebox").TLiteral<"boolean">]>>;
54
+ export declare const styledResourceTablePropsSchema: Type.TObject<{
55
+ density: Type.TOptional<Type.TUnion<Type.TLiteral<"compact" | "comfortable">[]>>;
56
+ title: Type.TString;
57
+ emptyLabel: Type.TOptional<Type.TString>;
58
+ columns: Type.TArray<Type.TObject<{
59
+ field: Type.TString;
60
+ label: Type.TString;
61
+ format: Type.TOptional<Type.TUnion<[Type.TLiteral<"text">, Type.TLiteral<"number">, Type.TLiteral<"date">, Type.TLiteral<"boolean">]>>;
62
62
  }>>;
63
63
  }>;
@@ -1,5 +1,5 @@
1
1
  import { surfaceDesignContract } from './design-contract.js';
2
- import { Type } from "@sinclair/typebox";
2
+ import { Type } from "typebox";
3
3
  const catalogFieldSchema = Type.String({
4
4
  minLength: 1,
5
5
  maxLength: 64,
@@ -1,26 +1,26 @@
1
- import { type Static } from '@sinclair/typebox';
1
+ import { Type, type Static } from 'typebox';
2
2
  import type { SurfaceCatalog } from './types.js';
3
- export declare const resourceDetailPropsSchema: import("@sinclair/typebox").TObject<{
4
- fields: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
5
- field: import("@sinclair/typebox").TString;
6
- label: import("@sinclair/typebox").TString;
7
- format: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<import("@sinclair/typebox").TLiteral<string>[]>>;
3
+ export declare const resourceDetailPropsSchema: Type.TObject<{
4
+ fields: Type.TArray<Type.TObject<{
5
+ field: Type.TString;
6
+ label: Type.TString;
7
+ format: Type.TOptional<Type.TUnion<Type.TLiteral<string>[]>>;
8
8
  }>>;
9
- title: import("@sinclair/typebox").TString;
10
- tone: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<import("@sinclair/typebox").TLiteral<"info" | "warning" | "success" | "neutral" | "danger">[]>>;
11
- density: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<import("@sinclair/typebox").TLiteral<"compact" | "comfortable">[]>>;
9
+ title: Type.TString;
10
+ tone: Type.TOptional<Type.TUnion<Type.TLiteral<"info" | "warning" | "success" | "neutral" | "danger">[]>>;
11
+ density: Type.TOptional<Type.TUnion<Type.TLiteral<"compact" | "comfortable">[]>>;
12
12
  }>;
13
- export declare const activityFeedPropsSchema: import("@sinclair/typebox").TObject<{
14
- idField: import("@sinclair/typebox").TString;
15
- actionField: import("@sinclair/typebox").TString;
16
- timestampField: import("@sinclair/typebox").TString;
17
- actorField: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
18
- targetField: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
19
- commentField: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
20
- statusField: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
21
- title: import("@sinclair/typebox").TString;
22
- tone: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<import("@sinclair/typebox").TLiteral<"info" | "warning" | "success" | "neutral" | "danger">[]>>;
23
- density: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<import("@sinclair/typebox").TLiteral<"compact" | "comfortable">[]>>;
13
+ export declare const activityFeedPropsSchema: Type.TObject<{
14
+ idField: Type.TString;
15
+ actionField: Type.TString;
16
+ timestampField: Type.TString;
17
+ actorField: Type.TOptional<Type.TString>;
18
+ targetField: Type.TOptional<Type.TString>;
19
+ commentField: Type.TOptional<Type.TString>;
20
+ statusField: Type.TOptional<Type.TString>;
21
+ title: Type.TString;
22
+ tone: Type.TOptional<Type.TUnion<Type.TLiteral<"info" | "warning" | "success" | "neutral" | "danger">[]>>;
23
+ density: Type.TOptional<Type.TUnion<Type.TLiteral<"compact" | "comfortable">[]>>;
24
24
  }>;
25
25
  export type ResourceDetailProps = Static<typeof resourceDetailPropsSchema>;
26
26
  export type ActivityFeedProps = Static<typeof activityFeedPropsSchema>;
@@ -1,5 +1,5 @@
1
- import { Type } from '@sinclair/typebox';
2
- import { Value } from '@sinclair/typebox/value';
1
+ import { Type } from 'typebox';
2
+ import { Value } from 'typebox/value';
3
3
  import { styledSurfaceDefinitions } from './builtin-definitions.js';
4
4
  import { surfaceDesignContract } from './design-contract.js';
5
5
  const field = Type.String({ minLength: 1, maxLength: 64, pattern: '^[A-Za-z][A-Za-z0-9_-]*$' });
package/dist/catalog.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Value } from '@sinclair/typebox/value';
1
+ import { Value } from 'typebox/value';
2
2
  import BarChartWidget from './components/BarChartWidget.svelte';
3
3
  import LineChartWidget from './components/LineChartWidget.svelte';
4
4
  import MetricWidget from './components/MetricWidget.svelte';
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import { Value } from '@sinclair/typebox/value';
2
+ import { Value } from 'typebox/value';
3
3
  import ActivityFeed from '@svadmin/ui/components/ActivityFeed.svelte';
4
4
  import { activityFeedPropsSchema } from '../business-definitions.js';
5
5
  import { asSurfaceActivities } from '../business-data.js';
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import { Value } from '@sinclair/typebox/value';
2
+ import { Value } from 'typebox/value';
3
3
  import BarChart from '@svadmin/ui/components/charts/BarChart.svelte';
4
4
  import CardContent from '@svadmin/ui/components/ui/card/card-content.svelte';
5
5
  import CardHeader from '@svadmin/ui/components/ui/card/card-header.svelte';
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import { Value } from '@sinclair/typebox/value';
2
+ import { Value } from 'typebox/value';
3
3
  import LineChart from '@svadmin/ui/components/charts/LineChart.svelte';
4
4
  import CardContent from '@svadmin/ui/components/ui/card/card-content.svelte';
5
5
  import CardHeader from '@svadmin/ui/components/ui/card/card-header.svelte';
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import { Value } from '@sinclair/typebox/value';
2
+ import { Value } from 'typebox/value';
3
3
  import { surfaceMetric } from '../recipes.js';
4
4
  import '../styles.css';
5
5
  import StatsCard from '@svadmin/ui/components/StatsCard.svelte';
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import { Value } from '@sinclair/typebox/value';
2
+ import { Value } from 'typebox/value';
3
3
  import Card from '@svadmin/ui/components/ui/card/card.svelte';
4
4
  import CardHeader from '@svadmin/ui/components/ui/card/card-header.svelte';
5
5
  import CardTitle from '@svadmin/ui/components/ui/card/card-title.svelte';
@@ -1,6 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { onDestroy, untrack } from 'svelte';
3
- import { Value } from '@sinclair/typebox/value';
3
+ import { Value } from 'typebox/value';
4
4
  import JsonSchemaForm from '@svadmin/ui/components/JsonSchemaForm.svelte';
5
5
  import { createSurfaceFormController, type SurfaceWorkflowClientState } from '../workflows/client.js';
6
6
  import type { SurfaceWorkflowHost } from '../workflows/context.js';
@@ -49,7 +49,7 @@
49
49
  // wire representation. The server repeats JSON and schema validation.
50
50
  const args: unknown = JSON.parse(JSON.stringify(input));
51
51
  if (!Value.Check(action.inputSchema, args)) {
52
- errors = [...Value.Errors(action.inputSchema, args)].slice(0, 12).map((error) => `${error.path}: ${error.message}`);
52
+ errors = Value.Errors(action.inputSchema, args).slice(0, 12).map((error) => `${error.instancePath}: ${error.message}`);
53
53
  return;
54
54
  }
55
55
  errors = [];
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import { Value } from '@sinclair/typebox/value';
2
+ import { Value } from 'typebox/value';
3
3
  import { surfaceTable } from '../recipes.js';
4
4
  import '../styles.css';
5
5
  import CardContent from '@svadmin/ui/components/ui/card/card-content.svelte';
package/dist/edits.js CHANGED
@@ -1,5 +1,5 @@
1
- import { Type } from '@sinclair/typebox';
2
- import { TypeCompiler } from '@sinclair/typebox/compiler';
1
+ import { Type } from 'typebox';
2
+ import { Compile } from 'typebox/compile';
3
3
  import { createSurfaceCatalogManifest, SURFACE_AGENT_LIMITS, surfaceSchemaToJson } from './agent-contract.js';
4
4
  import { surfaceIdSchema, surfaceLayoutSchema, surfaceListSourceSchema, surfaceOneSourceSchema, surfaceSpecSchema, surfaceWidgetSchema, } from './schema.js';
5
5
  import { SURFACE_LIMITS } from './types.js';
@@ -23,8 +23,8 @@ const editSchema = Type.Object({
23
23
  Type.Object({ op: Type.Literal('reorder-widgets'), ids: Type.Array(surfaceIdSchema, { maxItems: SURFACE_LIMITS.maxWidgets, uniqueItems: true }) }, { additionalProperties: false }),
24
24
  ]), { minItems: 1, maxItems: SURFACE_EDIT_LIMITS.maxOperations }),
25
25
  }, { additionalProperties: false });
26
- const compiledEdit = TypeCompiler.Compile(editSchema);
27
- const compiledRevision = TypeCompiler.Compile(Type.Object({ revision: revisionSchema, spec: surfaceSpecSchema }, { additionalProperties: false }));
26
+ const compiledEdit = Compile(editSchema);
27
+ const compiledRevision = Compile(Type.Object({ revision: revisionSchema, spec: surfaceSpecSchema }, { additionalProperties: false }));
28
28
  function editError(code, path, message) {
29
29
  return { ok: false, issues: [{ code, path, message }] };
30
30
  }
@@ -1,54 +1,54 @@
1
- import { type Static } from '@sinclair/typebox';
1
+ import { Type, type Static } from 'typebox';
2
2
  import type { SurfaceCatalog, SurfacePolicy, SurfaceSpec } from './types.js';
3
3
  /** json-render 的标准扁平 Spec 子集;业务字段仍由 Surface 的 TypeBox 契约校验。 */
4
- export declare const jsonRenderSurfaceRootPropsSchema: import("@sinclair/typebox").TObject<{
5
- layout: import("@sinclair/typebox").TObject<{
6
- type: import("@sinclair/typebox").TLiteral<"grid">;
7
- columns: import("@sinclair/typebox").TLiteral<12>;
8
- gap: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"sm">, import("@sinclair/typebox").TLiteral<"md">, import("@sinclair/typebox").TLiteral<"lg">]>>;
4
+ export declare const jsonRenderSurfaceRootPropsSchema: Type.TObject<{
5
+ layout: Type.TObject<{
6
+ type: Type.TLiteral<"grid">;
7
+ columns: Type.TLiteral<12>;
8
+ gap: Type.TOptional<Type.TUnion<[Type.TLiteral<"sm">, Type.TLiteral<"md">, Type.TLiteral<"lg">]>>;
9
9
  }>;
10
- title: import("@sinclair/typebox").TString;
11
- catalogVersion: import("@sinclair/typebox").TString;
12
- surfaceId: import("@sinclair/typebox").TString;
13
- dataSources: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
14
- id: import("@sinclair/typebox").TString;
15
- type: import("@sinclair/typebox").TLiteral<"resource-list">;
16
- resource: import("@sinclair/typebox").TString;
17
- pageSize: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
18
- sorters: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
19
- field: import("@sinclair/typebox").TString;
20
- order: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"asc">, import("@sinclair/typebox").TLiteral<"desc">]>;
10
+ title: Type.TString;
11
+ catalogVersion: Type.TString;
12
+ surfaceId: Type.TString;
13
+ dataSources: Type.TArray<Type.TUnion<[Type.TObject<{
14
+ id: Type.TString;
15
+ type: Type.TLiteral<"resource-list">;
16
+ resource: Type.TString;
17
+ pageSize: Type.TOptional<Type.TInteger>;
18
+ sorters: Type.TOptional<Type.TArray<Type.TObject<{
19
+ field: Type.TString;
20
+ order: Type.TUnion<[Type.TLiteral<"asc">, Type.TLiteral<"desc">]>;
21
21
  }>>>;
22
- filters: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
23
- field: import("@sinclair/typebox").TString;
24
- operator: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"eq">, import("@sinclair/typebox").TLiteral<"ne">, import("@sinclair/typebox").TLiteral<"lt">, import("@sinclair/typebox").TLiteral<"lte">, import("@sinclair/typebox").TLiteral<"gt">, import("@sinclair/typebox").TLiteral<"gte">, import("@sinclair/typebox").TLiteral<"contains">, import("@sinclair/typebox").TLiteral<"startswith">, import("@sinclair/typebox").TLiteral<"endswith">]>;
25
- value: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNumber, import("@sinclair/typebox").TBoolean, import("@sinclair/typebox").TNull]>;
26
- }>, import("@sinclair/typebox").TObject<{
27
- field: import("@sinclair/typebox").TString;
28
- operator: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"in">, import("@sinclair/typebox").TLiteral<"nin">]>;
29
- value: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNumber, import("@sinclair/typebox").TBoolean, import("@sinclair/typebox").TNull]>>;
30
- }>, import("@sinclair/typebox").TObject<{
31
- field: import("@sinclair/typebox").TString;
32
- operator: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"null">, import("@sinclair/typebox").TLiteral<"nnull">]>;
22
+ filters: Type.TOptional<Type.TArray<Type.TUnion<[Type.TObject<{
23
+ field: Type.TString;
24
+ operator: Type.TUnion<[Type.TLiteral<"eq">, Type.TLiteral<"ne">, Type.TLiteral<"lt">, Type.TLiteral<"lte">, Type.TLiteral<"gt">, Type.TLiteral<"gte">, Type.TLiteral<"contains">, Type.TLiteral<"startswith">, Type.TLiteral<"endswith">]>;
25
+ value: Type.TUnion<[Type.TString, Type.TNumber, Type.TBoolean, Type.TNull]>;
26
+ }>, Type.TObject<{
27
+ field: Type.TString;
28
+ operator: Type.TUnion<[Type.TLiteral<"in">, Type.TLiteral<"nin">]>;
29
+ value: Type.TArray<Type.TUnion<[Type.TString, Type.TNumber, Type.TBoolean, Type.TNull]>>;
30
+ }>, Type.TObject<{
31
+ field: Type.TString;
32
+ operator: Type.TUnion<[Type.TLiteral<"null">, Type.TLiteral<"nnull">]>;
33
33
  }>]>>>;
34
- }>, import("@sinclair/typebox").TObject<{
35
- id: import("@sinclair/typebox").TString;
36
- type: import("@sinclair/typebox").TLiteral<"resource-one">;
37
- resource: import("@sinclair/typebox").TString;
38
- recordId: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNumber]>;
34
+ }>, Type.TObject<{
35
+ id: Type.TString;
36
+ type: Type.TLiteral<"resource-one">;
37
+ resource: Type.TString;
38
+ recordId: Type.TUnion<[Type.TString, Type.TNumber]>;
39
39
  }>]>>;
40
40
  }>;
41
- export declare const jsonRenderUiElementSchema: import("@sinclair/typebox").TObject<{
42
- type: import("@sinclair/typebox").TString;
43
- props: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TUnknown>;
44
- children: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
41
+ export declare const jsonRenderUiElementSchema: Type.TObject<{
42
+ type: Type.TString;
43
+ props: Type.TRecord<"^.*$", Type.TUnknown>;
44
+ children: Type.TOptional<Type.TArray<Type.TString>>;
45
45
  }>;
46
- export declare const jsonRenderSpecSchema: import("@sinclair/typebox").TObject<{
47
- root: import("@sinclair/typebox").TString;
48
- elements: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TObject<{
49
- type: import("@sinclair/typebox").TString;
50
- props: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TUnknown>;
51
- children: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
46
+ export declare const jsonRenderSpecSchema: Type.TObject<{
47
+ root: Type.TString;
48
+ elements: Type.TRecord<"^.*$", Type.TObject<{
49
+ type: Type.TString;
50
+ props: Type.TRecord<"^.*$", Type.TUnknown>;
51
+ children: Type.TOptional<Type.TArray<Type.TString>>;
52
52
  }>>;
53
53
  }>;
54
54
  export type JsonRenderSurfaceElement = Static<typeof jsonRenderUiElementSchema>;
@@ -1,11 +1,11 @@
1
- import { Type } from '@sinclair/typebox';
2
- import { Value } from '@sinclair/typebox/value';
1
+ import { Type, ObjectOptions } from 'typebox';
2
+ import { Value } from 'typebox/value';
3
3
  import { validateSurfaceSpec } from './validation.js';
4
4
  import { jsonPointer } from './json.js';
5
5
  import { parseSurfaceJson } from './wire.js';
6
6
  import { surfaceSpecSchema, surfaceWidgetSchema } from './schema.js';
7
7
  /** json-render 的标准扁平 Spec 子集;业务字段仍由 Surface 的 TypeBox 契约校验。 */
8
- export const jsonRenderSurfaceRootPropsSchema = Type.Omit(surfaceSpecSchema, ['schemaVersion', 'widgets']);
8
+ export const jsonRenderSurfaceRootPropsSchema = Type.Omit(surfaceSpecSchema, ['schemaVersion', 'widgets'], ObjectOptions(surfaceSpecSchema));
9
9
  export const jsonRenderUiElementSchema = Type.Object({
10
10
  type: Type.String({ minLength: 1 }),
11
11
  props: Type.Record(Type.String(), Type.Unknown()),
package/dist/schema.d.ts CHANGED
@@ -1,108 +1,109 @@
1
- export declare const surfaceIdSchema: import("@sinclair/typebox").TString;
2
- export declare const surfaceFilterSchema: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
3
- field: import("@sinclair/typebox").TString;
4
- operator: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"eq">, import("@sinclair/typebox").TLiteral<"ne">, import("@sinclair/typebox").TLiteral<"lt">, import("@sinclair/typebox").TLiteral<"lte">, import("@sinclair/typebox").TLiteral<"gt">, import("@sinclair/typebox").TLiteral<"gte">, import("@sinclair/typebox").TLiteral<"contains">, import("@sinclair/typebox").TLiteral<"startswith">, import("@sinclair/typebox").TLiteral<"endswith">]>;
5
- value: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNumber, import("@sinclair/typebox").TBoolean, import("@sinclair/typebox").TNull]>;
6
- }>, import("@sinclair/typebox").TObject<{
7
- field: import("@sinclair/typebox").TString;
8
- operator: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"in">, import("@sinclair/typebox").TLiteral<"nin">]>;
9
- value: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNumber, import("@sinclair/typebox").TBoolean, import("@sinclair/typebox").TNull]>>;
10
- }>, import("@sinclair/typebox").TObject<{
11
- field: import("@sinclair/typebox").TString;
12
- operator: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"null">, import("@sinclair/typebox").TLiteral<"nnull">]>;
1
+ import { Type } from 'typebox';
2
+ export declare const surfaceIdSchema: Type.TString;
3
+ export declare const surfaceFilterSchema: Type.TUnion<[Type.TObject<{
4
+ field: Type.TString;
5
+ operator: Type.TUnion<[Type.TLiteral<"eq">, Type.TLiteral<"ne">, Type.TLiteral<"lt">, Type.TLiteral<"lte">, Type.TLiteral<"gt">, Type.TLiteral<"gte">, Type.TLiteral<"contains">, Type.TLiteral<"startswith">, Type.TLiteral<"endswith">]>;
6
+ value: Type.TUnion<[Type.TString, Type.TNumber, Type.TBoolean, Type.TNull]>;
7
+ }>, Type.TObject<{
8
+ field: Type.TString;
9
+ operator: Type.TUnion<[Type.TLiteral<"in">, Type.TLiteral<"nin">]>;
10
+ value: Type.TArray<Type.TUnion<[Type.TString, Type.TNumber, Type.TBoolean, Type.TNull]>>;
11
+ }>, Type.TObject<{
12
+ field: Type.TString;
13
+ operator: Type.TUnion<[Type.TLiteral<"null">, Type.TLiteral<"nnull">]>;
13
14
  }>]>;
14
- export declare const surfaceListSourceSchema: import("@sinclair/typebox").TObject<{
15
- id: import("@sinclair/typebox").TString;
16
- type: import("@sinclair/typebox").TLiteral<"resource-list">;
17
- resource: import("@sinclair/typebox").TString;
18
- pageSize: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
19
- sorters: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
20
- field: import("@sinclair/typebox").TString;
21
- order: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"asc">, import("@sinclair/typebox").TLiteral<"desc">]>;
15
+ export declare const surfaceListSourceSchema: Type.TObject<{
16
+ id: Type.TString;
17
+ type: Type.TLiteral<"resource-list">;
18
+ resource: Type.TString;
19
+ pageSize: Type.TOptional<Type.TInteger>;
20
+ sorters: Type.TOptional<Type.TArray<Type.TObject<{
21
+ field: Type.TString;
22
+ order: Type.TUnion<[Type.TLiteral<"asc">, Type.TLiteral<"desc">]>;
22
23
  }>>>;
23
- filters: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
24
- field: import("@sinclair/typebox").TString;
25
- operator: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"eq">, import("@sinclair/typebox").TLiteral<"ne">, import("@sinclair/typebox").TLiteral<"lt">, import("@sinclair/typebox").TLiteral<"lte">, import("@sinclair/typebox").TLiteral<"gt">, import("@sinclair/typebox").TLiteral<"gte">, import("@sinclair/typebox").TLiteral<"contains">, import("@sinclair/typebox").TLiteral<"startswith">, import("@sinclair/typebox").TLiteral<"endswith">]>;
26
- value: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNumber, import("@sinclair/typebox").TBoolean, import("@sinclair/typebox").TNull]>;
27
- }>, import("@sinclair/typebox").TObject<{
28
- field: import("@sinclair/typebox").TString;
29
- operator: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"in">, import("@sinclair/typebox").TLiteral<"nin">]>;
30
- value: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNumber, import("@sinclair/typebox").TBoolean, import("@sinclair/typebox").TNull]>>;
31
- }>, import("@sinclair/typebox").TObject<{
32
- field: import("@sinclair/typebox").TString;
33
- operator: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"null">, import("@sinclair/typebox").TLiteral<"nnull">]>;
24
+ filters: Type.TOptional<Type.TArray<Type.TUnion<[Type.TObject<{
25
+ field: Type.TString;
26
+ operator: Type.TUnion<[Type.TLiteral<"eq">, Type.TLiteral<"ne">, Type.TLiteral<"lt">, Type.TLiteral<"lte">, Type.TLiteral<"gt">, Type.TLiteral<"gte">, Type.TLiteral<"contains">, Type.TLiteral<"startswith">, Type.TLiteral<"endswith">]>;
27
+ value: Type.TUnion<[Type.TString, Type.TNumber, Type.TBoolean, Type.TNull]>;
28
+ }>, Type.TObject<{
29
+ field: Type.TString;
30
+ operator: Type.TUnion<[Type.TLiteral<"in">, Type.TLiteral<"nin">]>;
31
+ value: Type.TArray<Type.TUnion<[Type.TString, Type.TNumber, Type.TBoolean, Type.TNull]>>;
32
+ }>, Type.TObject<{
33
+ field: Type.TString;
34
+ operator: Type.TUnion<[Type.TLiteral<"null">, Type.TLiteral<"nnull">]>;
34
35
  }>]>>>;
35
36
  }>;
36
- export declare const surfaceOneSourceSchema: import("@sinclair/typebox").TObject<{
37
- id: import("@sinclair/typebox").TString;
38
- type: import("@sinclair/typebox").TLiteral<"resource-one">;
39
- resource: import("@sinclair/typebox").TString;
40
- recordId: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNumber]>;
37
+ export declare const surfaceOneSourceSchema: Type.TObject<{
38
+ id: Type.TString;
39
+ type: Type.TLiteral<"resource-one">;
40
+ resource: Type.TString;
41
+ recordId: Type.TUnion<[Type.TString, Type.TNumber]>;
41
42
  }>;
42
- export declare const surfaceLayoutSchema: import("@sinclair/typebox").TObject<{
43
- type: import("@sinclair/typebox").TLiteral<"grid">;
44
- columns: import("@sinclair/typebox").TLiteral<12>;
45
- gap: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"sm">, import("@sinclair/typebox").TLiteral<"md">, import("@sinclair/typebox").TLiteral<"lg">]>>;
43
+ export declare const surfaceLayoutSchema: Type.TObject<{
44
+ type: Type.TLiteral<"grid">;
45
+ columns: Type.TLiteral<12>;
46
+ gap: Type.TOptional<Type.TUnion<[Type.TLiteral<"sm">, Type.TLiteral<"md">, Type.TLiteral<"lg">]>>;
46
47
  }>;
47
- export declare const surfaceWidgetSchema: import("@sinclair/typebox").TObject<{
48
- id: import("@sinclair/typebox").TString;
49
- type: import("@sinclair/typebox").TString;
50
- props: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TUnknown>;
51
- binding: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
52
- sourceId: import("@sinclair/typebox").TString;
53
- pointer: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
48
+ export declare const surfaceWidgetSchema: Type.TObject<{
49
+ id: Type.TString;
50
+ type: Type.TString;
51
+ props: Type.TRecord<"^.*$", Type.TUnknown>;
52
+ binding: Type.TOptional<Type.TObject<{
53
+ sourceId: Type.TString;
54
+ pointer: Type.TOptional<Type.TString>;
54
55
  }>>;
55
- placement: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
56
- columnSpan: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
56
+ placement: Type.TOptional<Type.TObject<{
57
+ columnSpan: Type.TOptional<Type.TInteger>;
57
58
  }>>;
58
59
  }>;
59
- export declare const surfaceSpecSchema: import("@sinclair/typebox").TObject<{
60
- schemaVersion: import("@sinclair/typebox").TString;
61
- catalogVersion: import("@sinclair/typebox").TString;
62
- surfaceId: import("@sinclair/typebox").TString;
63
- title: import("@sinclair/typebox").TString;
64
- layout: import("@sinclair/typebox").TObject<{
65
- type: import("@sinclair/typebox").TLiteral<"grid">;
66
- columns: import("@sinclair/typebox").TLiteral<12>;
67
- gap: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"sm">, import("@sinclair/typebox").TLiteral<"md">, import("@sinclair/typebox").TLiteral<"lg">]>>;
60
+ export declare const surfaceSpecSchema: Type.TObject<{
61
+ schemaVersion: Type.TString;
62
+ catalogVersion: Type.TString;
63
+ surfaceId: Type.TString;
64
+ title: Type.TString;
65
+ layout: Type.TObject<{
66
+ type: Type.TLiteral<"grid">;
67
+ columns: Type.TLiteral<12>;
68
+ gap: Type.TOptional<Type.TUnion<[Type.TLiteral<"sm">, Type.TLiteral<"md">, Type.TLiteral<"lg">]>>;
68
69
  }>;
69
- dataSources: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
70
- id: import("@sinclair/typebox").TString;
71
- type: import("@sinclair/typebox").TLiteral<"resource-list">;
72
- resource: import("@sinclair/typebox").TString;
73
- pageSize: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
74
- sorters: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
75
- field: import("@sinclair/typebox").TString;
76
- order: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"asc">, import("@sinclair/typebox").TLiteral<"desc">]>;
70
+ dataSources: Type.TArray<Type.TUnion<[Type.TObject<{
71
+ id: Type.TString;
72
+ type: Type.TLiteral<"resource-list">;
73
+ resource: Type.TString;
74
+ pageSize: Type.TOptional<Type.TInteger>;
75
+ sorters: Type.TOptional<Type.TArray<Type.TObject<{
76
+ field: Type.TString;
77
+ order: Type.TUnion<[Type.TLiteral<"asc">, Type.TLiteral<"desc">]>;
77
78
  }>>>;
78
- filters: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
79
- field: import("@sinclair/typebox").TString;
80
- operator: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"eq">, import("@sinclair/typebox").TLiteral<"ne">, import("@sinclair/typebox").TLiteral<"lt">, import("@sinclair/typebox").TLiteral<"lte">, import("@sinclair/typebox").TLiteral<"gt">, import("@sinclair/typebox").TLiteral<"gte">, import("@sinclair/typebox").TLiteral<"contains">, import("@sinclair/typebox").TLiteral<"startswith">, import("@sinclair/typebox").TLiteral<"endswith">]>;
81
- value: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNumber, import("@sinclair/typebox").TBoolean, import("@sinclair/typebox").TNull]>;
82
- }>, import("@sinclair/typebox").TObject<{
83
- field: import("@sinclair/typebox").TString;
84
- operator: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"in">, import("@sinclair/typebox").TLiteral<"nin">]>;
85
- value: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNumber, import("@sinclair/typebox").TBoolean, import("@sinclair/typebox").TNull]>>;
86
- }>, import("@sinclair/typebox").TObject<{
87
- field: import("@sinclair/typebox").TString;
88
- operator: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"null">, import("@sinclair/typebox").TLiteral<"nnull">]>;
79
+ filters: Type.TOptional<Type.TArray<Type.TUnion<[Type.TObject<{
80
+ field: Type.TString;
81
+ operator: Type.TUnion<[Type.TLiteral<"eq">, Type.TLiteral<"ne">, Type.TLiteral<"lt">, Type.TLiteral<"lte">, Type.TLiteral<"gt">, Type.TLiteral<"gte">, Type.TLiteral<"contains">, Type.TLiteral<"startswith">, Type.TLiteral<"endswith">]>;
82
+ value: Type.TUnion<[Type.TString, Type.TNumber, Type.TBoolean, Type.TNull]>;
83
+ }>, Type.TObject<{
84
+ field: Type.TString;
85
+ operator: Type.TUnion<[Type.TLiteral<"in">, Type.TLiteral<"nin">]>;
86
+ value: Type.TArray<Type.TUnion<[Type.TString, Type.TNumber, Type.TBoolean, Type.TNull]>>;
87
+ }>, Type.TObject<{
88
+ field: Type.TString;
89
+ operator: Type.TUnion<[Type.TLiteral<"null">, Type.TLiteral<"nnull">]>;
89
90
  }>]>>>;
90
- }>, import("@sinclair/typebox").TObject<{
91
- id: import("@sinclair/typebox").TString;
92
- type: import("@sinclair/typebox").TLiteral<"resource-one">;
93
- resource: import("@sinclair/typebox").TString;
94
- recordId: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNumber]>;
91
+ }>, Type.TObject<{
92
+ id: Type.TString;
93
+ type: Type.TLiteral<"resource-one">;
94
+ resource: Type.TString;
95
+ recordId: Type.TUnion<[Type.TString, Type.TNumber]>;
95
96
  }>]>>;
96
- widgets: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
97
- id: import("@sinclair/typebox").TString;
98
- type: import("@sinclair/typebox").TString;
99
- props: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TUnknown>;
100
- binding: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
101
- sourceId: import("@sinclair/typebox").TString;
102
- pointer: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
97
+ widgets: Type.TArray<Type.TObject<{
98
+ id: Type.TString;
99
+ type: Type.TString;
100
+ props: Type.TRecord<"^.*$", Type.TUnknown>;
101
+ binding: Type.TOptional<Type.TObject<{
102
+ sourceId: Type.TString;
103
+ pointer: Type.TOptional<Type.TString>;
103
104
  }>>;
104
- placement: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
105
- columnSpan: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
105
+ placement: Type.TOptional<Type.TObject<{
106
+ columnSpan: Type.TOptional<Type.TInteger>;
106
107
  }>>;
107
108
  }>>;
108
109
  }>;
package/dist/schema.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Type } from '@sinclair/typebox';
1
+ import { Type } from 'typebox';
2
2
  import { SURFACE_LIMITS } from './types.js';
3
3
  // 结构定义只维护一份:运行时校验与 AI 输出 schema 共用,策略校验仍在 validation.ts。
4
4
  export const surfaceIdSchema = Type.String({
@@ -1,19 +1,19 @@
1
- import { type Static } from '@sinclair/typebox';
1
+ import { Type, type Static } from 'typebox';
2
2
  import type { JsonObject, SurfaceWidgetDefinition } from './types.js';
3
3
  /** JSON-only 契约;宿主引擎、回调、URL 和写操作不属于 AI 可以生成的属性。 */
4
- export declare const svarGridPropsSchema: import("@sinclair/typebox").TObject<{
5
- title: import("@sinclair/typebox").TString;
6
- rowKey: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
7
- height: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
8
- density: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"compact">, import("@sinclair/typebox").TLiteral<"comfortable">]>>;
9
- freezeLeft: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
10
- freezeRight: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
11
- emptyLabel: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
12
- columns: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
13
- field: import("@sinclair/typebox").TString;
14
- label: import("@sinclair/typebox").TString;
15
- width: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
16
- format: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"plain">, import("@sinclair/typebox").TLiteral<"number">, import("@sinclair/typebox").TLiteral<"percent">, import("@sinclair/typebox").TLiteral<"date">, import("@sinclair/typebox").TLiteral<"datetime">, import("@sinclair/typebox").TLiteral<"boolean">]>>;
4
+ export declare const svarGridPropsSchema: Type.TObject<{
5
+ title: Type.TString;
6
+ rowKey: Type.TOptional<Type.TString>;
7
+ height: Type.TOptional<Type.TInteger>;
8
+ density: Type.TOptional<Type.TUnion<[Type.TLiteral<"compact">, Type.TLiteral<"comfortable">]>>;
9
+ freezeLeft: Type.TOptional<Type.TInteger>;
10
+ freezeRight: Type.TOptional<Type.TInteger>;
11
+ emptyLabel: Type.TOptional<Type.TString>;
12
+ columns: Type.TArray<Type.TObject<{
13
+ field: Type.TString;
14
+ label: Type.TString;
15
+ width: Type.TOptional<Type.TInteger>;
16
+ format: Type.TOptional<Type.TUnion<[Type.TLiteral<"plain">, Type.TLiteral<"number">, Type.TLiteral<"percent">, Type.TLiteral<"date">, Type.TLiteral<"datetime">, Type.TLiteral<"boolean">]>>;
17
17
  }>>;
18
18
  }>;
19
19
  export type SvarGridProps = Static<typeof svarGridPropsSchema>;
@@ -1,5 +1,5 @@
1
- import { Type } from '@sinclair/typebox';
2
- import { Value } from '@sinclair/typebox/value';
1
+ import { Type } from 'typebox';
2
+ import { Value } from 'typebox/value';
3
3
  const field = Type.String({ minLength: 1, maxLength: 64, pattern: '^[A-Za-z][A-Za-z0-9_-]*$' });
4
4
  /** JSON-only 契约;宿主引擎、回调、URL 和写操作不属于 AI 可以生成的属性。 */
5
5
  export const svarGridPropsSchema = Type.Object({
package/dist/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { DataProvider } from '@svadmin/core';
2
- import type { TSchema } from '@sinclair/typebox';
2
+ import type { TSchema } from 'typebox';
3
3
  export declare const SURFACE_SCHEMA_VERSION: "surface/v1";
4
4
  export declare const SURFACE_LIMITS: {
5
5
  readonly maxDataSources: 8;
@@ -1,2 +1,15 @@
1
1
  import { type SurfaceCatalog, type SurfacePolicy, type SurfaceValidationResult } from "./types.js";
2
+ interface SchemaErrorLike {
3
+ instancePath?: string;
4
+ path?: string;
5
+ keyword?: string;
6
+ params?: Record<string, unknown>;
7
+ message: string;
8
+ }
9
+ /** TypeBox 1.x groups missing properties into one Ajv-style error; split them per field. */
10
+ export declare function surfaceSchemaIssues(errors: Iterable<SchemaErrorLike>): {
11
+ path: string;
12
+ message: string;
13
+ }[];
2
14
  export declare function validateSurfaceSpec(input: unknown, catalog: SurfaceCatalog, policy: SurfacePolicy): SurfaceValidationResult;
15
+ export {};
@@ -1,9 +1,9 @@
1
- import { TypeCompiler } from "@sinclair/typebox/compiler";
2
- import { Value } from "@sinclair/typebox/value";
1
+ import { Compile } from "typebox/compile";
2
+ import { Value } from "typebox/value";
3
3
  import { decodedJsonPointerToken, jsonPointer, jsonValueIssue } from "./json.js";
4
4
  import { surfaceSpecSchema } from './schema.js';
5
5
  import { SURFACE_LIMITS, SURFACE_SCHEMA_VERSION, } from "./types.js";
6
- const compiledSurfaceSpec = TypeCompiler.Compile(surfaceSpecSchema);
6
+ const compiledSurfaceSpec = Compile(surfaceSpecSchema);
7
7
  const forbiddenPropertyNames = new Set([
8
8
  "class", "className", "color", "href", "html", "innerHTML", "src", "style", "url",
9
9
  ]);
@@ -11,17 +11,38 @@ const strictSchemaProbeKey = "__surface_unknown_property_probe__";
11
11
  function invalidJsonIssue(pathSegments, message) {
12
12
  return { code: "invalid_json", path: jsonPointer(pathSegments), message };
13
13
  }
14
- function schemaErrors(errors) {
14
+ function escapePointerSegment(segment) {
15
+ return segment.replaceAll('~', '~0').replaceAll('/', '~1');
16
+ }
17
+ /** TypeBox 1.x groups missing properties into one Ajv-style error; split them per field. */
18
+ export function surfaceSchemaIssues(errors) {
15
19
  const issues = [];
16
- for (const err of errors) {
20
+ for (const error of errors) {
21
+ const base = error.instancePath ?? error.path ?? '';
22
+ const required = error.params?.['requiredProperties'];
23
+ if (error.keyword === 'required' && Array.isArray(required)) {
24
+ for (const property of required) {
25
+ if (typeof property !== 'string')
26
+ continue;
27
+ issues.push({ path: `${base}/${escapePointerSegment(property)}`, message: `must have required property '${property}'` });
28
+ }
29
+ continue;
30
+ }
31
+ const additional = error.params?.['additionalProperty'];
17
32
  issues.push({
18
- code: "invalid_json",
19
- path: err.path || "",
20
- message: err.message,
33
+ path: typeof additional === 'string' ? `${base}/${escapePointerSegment(additional)}` : base,
34
+ message: error.message,
21
35
  });
22
36
  }
23
37
  return issues;
24
38
  }
39
+ function schemaErrors(errors) {
40
+ return surfaceSchemaIssues(errors).map((issue) => ({
41
+ code: "invalid_json",
42
+ path: issue.path,
43
+ message: issue.message,
44
+ }));
45
+ }
25
46
  function catalogDefinitions(catalog) {
26
47
  return new Map(catalog.widgets.map((widgetDefinition) => [widgetDefinition.type, widgetDefinition]));
27
48
  }
@@ -1,4 +1,4 @@
1
- import { Value } from '@sinclair/typebox/value';
1
+ import { Value } from 'typebox/value';
2
2
  import { surfaceSchemaToJson } from '../agent-contract.js';
3
3
  /** Only the form subset actually rendered by JsonSchemaForm is advertised.
4
4
  * No refs, transforms, secret inputs, arbitrary unions or computed fields.
@@ -10,29 +10,30 @@ export function validateSurfaceActionDescriptor(action) {
10
10
  }
11
11
  surfaceSchemaToJson(action.inputSchema);
12
12
  let fields = 0;
13
- function visit(schema, depth) {
13
+ function visit(input, depth) {
14
+ const schema = input;
14
15
  if (++fields > 128 || depth > 8)
15
16
  throw new Error('Surface form schema exceeds supported limits');
16
- if (schema['anyOf'] || schema['oneOf'] || schema['allOf'] || schema['not'] || schema['if'] || schema.writeOnly
17
- || !['object', 'array', 'string', 'number', 'integer', 'boolean'].includes(schema['type'])) {
17
+ if (schema.anyOf || schema.oneOf || schema.allOf || schema.not || schema.if || schema.writeOnly
18
+ || !['object', 'array', 'string', 'number', 'integer', 'boolean'].includes(schema.type ?? '')) {
18
19
  throw new Error('Unsupported Surface form schema; use a registered custom widget instead');
19
20
  }
20
- if (schema['type'] === 'object') {
21
- if (schema['additionalProperties'] !== false || !schema['properties'])
21
+ if (schema.type === 'object') {
22
+ if (schema.additionalProperties !== false || !schema.properties)
22
23
  throw new Error('Surface actions require closed object schemas');
23
- for (const [name, child] of Object.entries(schema['properties'])) {
24
+ for (const [name, child] of Object.entries(schema.properties)) {
24
25
  if (!/^[A-Za-z][A-Za-z0-9_-]{0,63}$/u.test(name))
25
26
  throw new Error('Invalid Surface form field');
26
27
  visit(child, depth + 1);
27
28
  }
28
29
  }
29
- else if (schema['type'] === 'array') {
30
- if (!schema['items'] || Array.isArray(schema['items']))
30
+ else if (schema.type === 'array') {
31
+ if (!schema.items || Array.isArray(schema.items))
31
32
  throw new Error('Surface forms require homogeneous array items');
32
- visit(schema['items'], depth + 1);
33
+ visit(schema.items, depth + 1);
33
34
  }
34
35
  }
35
- if (action.inputSchema['type'] !== 'object')
36
+ if (action.inputSchema.type !== 'object')
36
37
  throw new Error('Surface actions require an object input schema');
37
38
  visit(action.inputSchema, 0);
38
39
  }
@@ -1,8 +1,9 @@
1
+ import { Type } from 'typebox';
1
2
  import type { SurfaceCatalog, SurfaceWidgetDefinition, JsonObject } from '../types.js';
2
3
  import type { SurfaceActionDescriptor } from './types.js';
3
- export declare const surfaceAppearanceSchema: import("@sinclair/typebox").TObject<{
4
- tone: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<import("@sinclair/typebox").TLiteral<"info" | "warning" | "success" | "neutral" | "danger">[]>>;
5
- density: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<import("@sinclair/typebox").TLiteral<"compact" | "comfortable">[]>>;
4
+ export declare const surfaceAppearanceSchema: Type.TObject<{
5
+ tone: Type.TOptional<Type.TUnion<Type.TLiteral<"info" | "warning" | "success" | "neutral" | "danger">[]>>;
6
+ density: Type.TOptional<Type.TUnion<Type.TLiteral<"compact" | "comfortable">[]>>;
6
7
  }>;
7
8
  export declare function withoutSurfaceAppearance(props: JsonObject): JsonObject;
8
9
  /** Adds frame-level semantic appearance to every registered widget without
@@ -1,4 +1,4 @@
1
- import { Type } from '@sinclair/typebox';
1
+ import { Type } from 'typebox';
2
2
  import { surfaceDesignContract } from '../design-contract.js';
3
3
  import { validateSurfaceActionDescriptor } from './action-contracts.js';
4
4
  export const surfaceAppearanceSchema = Type.Object({
@@ -8,13 +8,14 @@ export const surfaceAppearanceSchema = Type.Object({
8
8
  export function withoutSurfaceAppearance(props) {
9
9
  return Object.fromEntries(Object.entries(props).filter(([key]) => key !== 'appearance'));
10
10
  }
11
- function withAppearance(schema) {
12
- if (Array.isArray(schema['anyOf']))
13
- return { ...schema, anyOf: schema['anyOf'].map((part) => withAppearance(part)) };
14
- if (schema['type'] !== 'object' || schema['additionalProperties'] !== false || !schema['properties'] || 'appearance' in schema['properties']) {
11
+ function withAppearance(input) {
12
+ const schema = input;
13
+ if (Array.isArray(schema.anyOf))
14
+ return { ...input, anyOf: schema.anyOf.map((part) => withAppearance(part)) };
15
+ if (schema.type !== 'object' || schema.additionalProperties !== false || !schema.properties || 'appearance' in schema.properties) {
15
16
  throw new Error('Surface appearance requires closed object schemas without a reserved appearance property');
16
17
  }
17
- return { ...schema, properties: { ...schema['properties'], appearance: Type.Optional(surfaceAppearanceSchema) } };
18
+ return { ...input, properties: { ...schema.properties, appearance: Type.Optional(surfaceAppearanceSchema) } };
18
19
  }
19
20
  /** Adds frame-level semantic appearance to every registered widget without
20
21
  * leaking presentation props into its existing component implementation.
@@ -1,4 +1,4 @@
1
- import type { TSchema } from '@sinclair/typebox';
1
+ import type { TSchema } from 'typebox';
2
2
  import type { JsonObject, JsonValue, SurfaceCatalog, SurfacePolicy, SurfaceSpec } from '../types.js';
3
3
  /** Identity comes from authenticated server middleware, never from model JSON. */
4
4
  export interface SurfaceWorkflowContext {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@svadmin/surface",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "Validated declarative surfaces for svadmin dashboards",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -74,12 +74,12 @@
74
74
  }
75
75
  },
76
76
  "peerDependencies": {
77
- "@svadmin/core": ">=0.53.0 <0.59.0",
78
- "@svadmin/ui": ">=0.73.0 <0.82.0",
77
+ "@svadmin/core": ">=0.53.0 <0.60.0",
78
+ "@svadmin/ui": ">=0.73.0 <0.83.0",
79
79
  "svelte": "^5.56.10"
80
80
  },
81
81
  "dependencies": {
82
- "@sinclair/typebox": "^0.34.52"
82
+ "typebox": "^1.3.34"
83
83
  },
84
84
  "devDependencies": {
85
85
  "@sveltejs/vite-plugin-svelte": "^7.3.0",