@magicvr/schema-ui-protocol 0.2.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/index.js +7654 -0
- package/lib/fetch-timeout.d.ts +13 -0
- package/package.json +23 -0
- package/protocol/app-manifest.d.ts +117 -0
- package/protocol/conformance/actions-outcome.d.ts +4 -0
- package/protocol/conformance/component-format.d.ts +13 -0
- package/protocol/conformance/query-serialize.d.ts +24 -0
- package/protocol/conformance/request-construction.d.ts +42 -0
- package/protocol/conformance/request-lifecycle.d.ts +27 -0
- package/protocol/conformance/response-mapping.d.ts +4 -0
- package/protocol/conformance/runtime-defaults.d.ts +5 -0
- package/protocol/conformance/runtime-schema-validate.d.ts +23 -0
- package/protocol/conformance/schema-validate.d.ts +16 -0
- package/protocol/conformance/search-table.d.ts +14 -0
- package/protocol/conformance/static-data.d.ts +27 -0
- package/protocol/conformance/table-sort.d.ts +4 -0
- package/protocol/conformance/upload-orchestration.d.ts +102 -0
- package/protocol/conformance/version-negotiate.d.ts +4 -0
- package/protocol/conformance-claim.json +81 -0
- package/protocol/conformance-claim.json.sha256 +1 -0
- package/protocol/conformance-local-report.json +60 -0
- package/protocol/index.d.ts +8 -0
- package/protocol/load-page.d.ts +45 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* W10 F-002: fetch timeout wrapper.
|
|
3
|
+
*
|
|
4
|
+
* Wraps a fetch implementation so a hung request (slow network, stalled
|
|
5
|
+
* server) aborts after a bounded window instead of pending forever. The
|
|
6
|
+
* returned function is drop-in compatible with `typeof fetch`; a caller-
|
|
7
|
+
* provided AbortSignal in `init` is composed with the timeout signal (either
|
|
8
|
+
* firing aborts the request). Timers are cleared once the request settles, so
|
|
9
|
+
* no handles leak on the happy path.
|
|
10
|
+
*/
|
|
11
|
+
/** Default ceiling for a single request (30s). */
|
|
12
|
+
export declare const DEFAULT_FETCH_TIMEOUT_MS = 30000;
|
|
13
|
+
export declare function withTimeout(fetchImpl?: typeof fetch, timeoutMs?: number): typeof fetch;
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@magicvr/schema-ui-protocol",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "schema-ui-core 协议面(v0.2.0 · R4 升级演练=normalizePageID additive)",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"types": "./protocol/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./protocol/index.d.ts",
|
|
11
|
+
"import": "./index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"index.js",
|
|
16
|
+
"protocol/",
|
|
17
|
+
"lib/"
|
|
18
|
+
],
|
|
19
|
+
"license": "UNLICENSED",
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
export declare const DEFAULT_MANIFEST_PATH = "/.well-known/schema-ui/app-manifest.json";
|
|
2
|
+
/**
|
|
3
|
+
* Host manifest-version support set (strict negotiation, ADR-0009): 2.7 for
|
|
4
|
+
* existing production manifests, 2.8 for Host/App interoperability manifests
|
|
5
|
+
* (returnIntentQueryKeys etc.), 2.9 for ADR-0039/ADR-0040 (data.route-binding /
|
|
6
|
+
* form.controls.readonly). Kept additive — older manifests stay accepted.
|
|
7
|
+
*/
|
|
8
|
+
export declare const APP_MANIFEST_SUPPORTED_PROTOCOL_VERSIONS: readonly ["2.7", "2.8", "2.9"];
|
|
9
|
+
export declare const APP_MANIFEST_PROTOCOL_VERSION: "2.9";
|
|
10
|
+
export declare const MANIFEST_SOURCE_HEADER = "X-Schema-UI-Manifest-Source";
|
|
11
|
+
export declare const APP_MANIFEST_SOURCE = "https://github.com/magicvr/schema-ui-docs/tree/81aa1d8";
|
|
12
|
+
/** True when `expression` matches the frozen $context expression grammar. */
|
|
13
|
+
export declare function isValidExpression(expression: string): boolean;
|
|
14
|
+
export type ManifestErrorCode = "MANIFEST_LOAD_FAILED" | "MISSING_PROTOCOL_VERSION" | "INVALID_PROTOCOL_VERSION" | "UNSUPPORTED_PROTOCOL_VERSION" | "PROTOCOL_VERSION_TOO_LOW" | "MISSING_REQUIRED_CAPABILITY" | "CAPABILITY_REQUIRED" | "UNKNOWN_MANIFEST_FIELD" | "INVALID_MANIFEST" | "INVALID_PATH" | "MANIFEST_HOME_PAGE_UNKNOWN" | "MANIFEST_HOME_ROUTE_PARAMETRIC" | "PAGE_REF_WITH_EMPTY_PAGES" | "MISSING_PATH_BINDING" | "MANIFEST_PAGE_ID_MISMATCH" | "INVALID_LOGO_URL" | "UNKNOWN_NAV_SLOT" | "NAV_LINK_MUTEX" | "NAV_GROUP_NESTED" | "NAV_PAGE_REF_UNKNOWN" | "INVALID_RETURN_INTENT_QUERY_KEYS" | "FORBIDDEN_VARIABLE" | "SYNTAX";
|
|
15
|
+
export declare class ManifestError extends Error {
|
|
16
|
+
readonly code: ManifestErrorCode;
|
|
17
|
+
readonly path: string;
|
|
18
|
+
/** Optional machine detail (e.g. the missing capability id). */
|
|
19
|
+
readonly detail?: string;
|
|
20
|
+
constructor(code: ManifestErrorCode, path: string, message: string, detail?: string);
|
|
21
|
+
}
|
|
22
|
+
export interface AppInfo {
|
|
23
|
+
appId: string;
|
|
24
|
+
name?: string;
|
|
25
|
+
nameKey?: string;
|
|
26
|
+
homePageRef?: string;
|
|
27
|
+
logo?: {
|
|
28
|
+
light: string;
|
|
29
|
+
dark?: string;
|
|
30
|
+
};
|
|
31
|
+
description?: string;
|
|
32
|
+
descriptionKey?: string;
|
|
33
|
+
}
|
|
34
|
+
export interface PageEntry {
|
|
35
|
+
pageId: string;
|
|
36
|
+
title?: string;
|
|
37
|
+
titleKey?: string;
|
|
38
|
+
schemaUrl: string;
|
|
39
|
+
route: string;
|
|
40
|
+
/** v2.8+ (ADR-0036): auth-return intent allowlist extension for this page. */
|
|
41
|
+
returnIntentQueryKeys?: string[];
|
|
42
|
+
}
|
|
43
|
+
export interface VisibleWhen {
|
|
44
|
+
when: string;
|
|
45
|
+
}
|
|
46
|
+
export interface NavPermissions {
|
|
47
|
+
view?: string;
|
|
48
|
+
}
|
|
49
|
+
export interface NavLink {
|
|
50
|
+
pageRef?: string;
|
|
51
|
+
url?: string;
|
|
52
|
+
label?: string;
|
|
53
|
+
labelKey?: string;
|
|
54
|
+
icon?: string;
|
|
55
|
+
visibleWhen?: VisibleWhen;
|
|
56
|
+
permissions?: NavPermissions;
|
|
57
|
+
}
|
|
58
|
+
export interface NavGroup {
|
|
59
|
+
label?: string;
|
|
60
|
+
labelKey?: string;
|
|
61
|
+
icon?: string;
|
|
62
|
+
items: NavLink[];
|
|
63
|
+
visibleWhen?: VisibleWhen;
|
|
64
|
+
permissions?: NavPermissions;
|
|
65
|
+
}
|
|
66
|
+
export type NavItem = NavLink | NavGroup;
|
|
67
|
+
export interface Navigation {
|
|
68
|
+
top?: NavItem[];
|
|
69
|
+
sidebar?: NavItem[];
|
|
70
|
+
user?: NavItem[];
|
|
71
|
+
}
|
|
72
|
+
export interface AppManifest {
|
|
73
|
+
protocolVersion: string;
|
|
74
|
+
requiredCapabilities: string[];
|
|
75
|
+
app: AppInfo;
|
|
76
|
+
pages: PageEntry[];
|
|
77
|
+
navigation?: Navigation;
|
|
78
|
+
}
|
|
79
|
+
export interface RouteMatch {
|
|
80
|
+
page: PageEntry;
|
|
81
|
+
index: number;
|
|
82
|
+
params: Record<string, string>;
|
|
83
|
+
}
|
|
84
|
+
export interface ResolvedRoute extends RouteMatch {
|
|
85
|
+
path: string;
|
|
86
|
+
query: Record<string, string>;
|
|
87
|
+
source: "home" | "deepLink";
|
|
88
|
+
}
|
|
89
|
+
export interface NavigationContext {
|
|
90
|
+
user?: Record<string, unknown>;
|
|
91
|
+
features?: Record<string, unknown>;
|
|
92
|
+
}
|
|
93
|
+
export declare function validateAppManifest(value: unknown): AppManifest;
|
|
94
|
+
export declare function matchRoute(pages: PageEntry[], path: string): RouteMatch | undefined;
|
|
95
|
+
export declare function stripPathQuery(path: string): string;
|
|
96
|
+
export declare function resolveInitialRoute(manifest: AppManifest, requestedPath: string): ResolvedRoute | undefined;
|
|
97
|
+
export declare function resolveSchemaUrl(baseURL: string, schemaUrl: string, params: Record<string, string>): string;
|
|
98
|
+
export declare function resolveRoutePath(route: string, params: Record<string, string>): string;
|
|
99
|
+
export declare function resolveLogoUrl(baseURL: string, logoUrl: string): string;
|
|
100
|
+
export declare function pageIdMatches(page: PageEntry, schemaPageId: string): boolean;
|
|
101
|
+
export declare function loadAppManifest(options?: {
|
|
102
|
+
url?: string;
|
|
103
|
+
fetcher?: typeof fetch;
|
|
104
|
+
}): Promise<AppManifest>;
|
|
105
|
+
/** Loads the manifest with its raw 200 bytes (bootstrap integrity, ADR-0035 D6). */
|
|
106
|
+
export declare function loadAppManifestBytes(options?: {
|
|
107
|
+
url?: string;
|
|
108
|
+
fetcher?: typeof fetch;
|
|
109
|
+
}): Promise<{
|
|
110
|
+
manifest: AppManifest;
|
|
111
|
+
bytes: Uint8Array;
|
|
112
|
+
}>;
|
|
113
|
+
export declare function evaluateExpression(expression: string, context: NavigationContext): boolean;
|
|
114
|
+
export declare function isNavigationItemVisible(item: NavLink | NavGroup, context: NavigationContext): boolean;
|
|
115
|
+
/** Normalizes a page identifier for contribution-key matching (trim + lowercase).
|
|
116
|
+
* Added in the R4 zero-conflict upgrade drill as a protocol additive sample. */
|
|
117
|
+
export declare function normalizePageID(id: string): string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* D-COMP component-format fixture adapter (schema-ui-docs v2.7.0).
|
|
3
|
+
* Validates format wire types without coercion.
|
|
4
|
+
*/
|
|
5
|
+
export type ComponentFormat = "currency" | "percent" | "datetime" | string;
|
|
6
|
+
export type FormatResult = {
|
|
7
|
+
ok: true;
|
|
8
|
+
value: unknown;
|
|
9
|
+
} | {
|
|
10
|
+
ok: false;
|
|
11
|
+
code: "COMPONENT_DATA_TYPE_MISMATCH";
|
|
12
|
+
};
|
|
13
|
+
export declare function applyComponentFormat(format: ComponentFormat, value: unknown): FormatResult;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ADR-0010 query-serialization adapter (schema-ui-docs v2.7.0 fixtures).
|
|
3
|
+
*
|
|
4
|
+
* Merges base URL query with ordered source layers; encodes keys/values per
|
|
5
|
+
* RFC 3986 (unreserved A-Za-z0-9-._~); sorts final keys by Unicode code point.
|
|
6
|
+
*/
|
|
7
|
+
export type QueryScalar = string | number | boolean | null;
|
|
8
|
+
export type QueryPair = [string, unknown];
|
|
9
|
+
export type QuerySource = QueryPair[];
|
|
10
|
+
export type QuerySerializeResult = {
|
|
11
|
+
ok: true;
|
|
12
|
+
url: string;
|
|
13
|
+
} | {
|
|
14
|
+
ok: false;
|
|
15
|
+
code: "INVALID_BASE_URL_QUERY" | "INVALID_QUERY_KEY" | "INVALID_QUERY_VALUE";
|
|
16
|
+
};
|
|
17
|
+
/** RFC3986 encode: percent-encode everything except unreserved. */
|
|
18
|
+
export declare function encodeRFC3986(value: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* JCS-style number serialization used by query-serialization fixtures.
|
|
21
|
+
* Matches JSON number text for typical finite values (1e+21, 1e-7, 0.000001).
|
|
22
|
+
*/
|
|
23
|
+
export declare function serializeQueryNumber(value: number): string;
|
|
24
|
+
export declare function serializeQuery(baseUrl: string, sources: QuerySource[]): QuerySerializeResult;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* request-construction fixture adapter (schema-ui-docs v2.7.0).
|
|
3
|
+
*
|
|
4
|
+
* Builds HTTP request / navigation / modal outcomes from declarative mappings.
|
|
5
|
+
* Batch kinds are out of scope for MVP callers (Q1); this module still implements
|
|
6
|
+
* non-batch kinds used by stage3 execution.
|
|
7
|
+
*/
|
|
8
|
+
export type RequestConstructionResult = {
|
|
9
|
+
ok: true;
|
|
10
|
+
request?: {
|
|
11
|
+
method: string;
|
|
12
|
+
url: string;
|
|
13
|
+
body: unknown;
|
|
14
|
+
headers?: Record<string, string>;
|
|
15
|
+
};
|
|
16
|
+
navigation?: {
|
|
17
|
+
url: string;
|
|
18
|
+
};
|
|
19
|
+
modalOpen?: {
|
|
20
|
+
modalId: string;
|
|
21
|
+
};
|
|
22
|
+
resolvedBase?: string;
|
|
23
|
+
/** Batch triggers: selection snapshot after a successful reload (ADR-0022 D2). */
|
|
24
|
+
selectionAfterSuccessReload?: {
|
|
25
|
+
keys: unknown[];
|
|
26
|
+
count: number;
|
|
27
|
+
};
|
|
28
|
+
} | {
|
|
29
|
+
ok: false;
|
|
30
|
+
code: string;
|
|
31
|
+
path: string;
|
|
32
|
+
};
|
|
33
|
+
/** D3 invariants: scalar keys only, dedupe preserving order, count = keys.length. */
|
|
34
|
+
export declare function normalizeSelection(keys: unknown[]): {
|
|
35
|
+
keys: unknown[];
|
|
36
|
+
count: number;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Run one request-construction fixture case.
|
|
40
|
+
* Batch kinds return a structured error; stage3 excludes them via Q1.
|
|
41
|
+
*/
|
|
42
|
+
export declare function constructRequest(input: Record<string, unknown>): RequestConstructionResult;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* request-lifecycle fixture adapter (latest-wins / hide-drop).
|
|
3
|
+
*/
|
|
4
|
+
type LifecycleEvent = {
|
|
5
|
+
type: "start";
|
|
6
|
+
} | {
|
|
7
|
+
type: "response";
|
|
8
|
+
generation: number;
|
|
9
|
+
state: unknown;
|
|
10
|
+
} | {
|
|
11
|
+
type: "hide";
|
|
12
|
+
} | {
|
|
13
|
+
type: "show";
|
|
14
|
+
} | {
|
|
15
|
+
type: "unmount";
|
|
16
|
+
};
|
|
17
|
+
export interface LifecycleResult {
|
|
18
|
+
generation: number;
|
|
19
|
+
active: boolean;
|
|
20
|
+
state: unknown;
|
|
21
|
+
committed: Array<{
|
|
22
|
+
generation: number;
|
|
23
|
+
state: unknown;
|
|
24
|
+
}>;
|
|
25
|
+
}
|
|
26
|
+
export declare function runRequestLifecycle(initialState: unknown, events: LifecycleEvent[]): LifecycleResult;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-safe structural validation for vendored page/node/action/reaction
|
|
3
|
+
* schemas. Mirrors `protocol/conformance/schema-validate.ts` but imports the
|
|
4
|
+
* pinned `docs/schemas/*.json` at build time (Vite `@schemas` alias) instead of
|
|
5
|
+
* reading them from disk, so the runtime loader can enforce D-VAL in the
|
|
6
|
+
* browser. The schema set is identical, so runtime and test-time validators
|
|
7
|
+
* stay aligned and neither redefines upstream node/page semantics.
|
|
8
|
+
*/
|
|
9
|
+
export type RuntimeSchemaKind = "node" | "page" | "action" | "reaction";
|
|
10
|
+
export interface RuntimeSchemaValidationResult {
|
|
11
|
+
ok: boolean;
|
|
12
|
+
errors: Array<{
|
|
13
|
+
path: string;
|
|
14
|
+
message: string;
|
|
15
|
+
keyword?: string;
|
|
16
|
+
}>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Structural validation of a fetched page document against the pinned page/node
|
|
20
|
+
* schemas. `ok: false` means the document must fail closed and never reach the
|
|
21
|
+
* renderer.
|
|
22
|
+
*/
|
|
23
|
+
export declare function validatePageDocument(document: unknown): RuntimeSchemaValidationResult;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structural validation entry for vendored node/page/action/reaction schemas.
|
|
3
|
+
* Uses Ajv draft-07 against pinned schema-ui-docs@2.7.0 artifacts in docs/schemas/.
|
|
4
|
+
*/
|
|
5
|
+
export type SchemaKind = "node" | "page" | "action" | "reaction";
|
|
6
|
+
export interface SchemaValidationResult {
|
|
7
|
+
ok: boolean;
|
|
8
|
+
errors: Array<{
|
|
9
|
+
path: string;
|
|
10
|
+
message: string;
|
|
11
|
+
keyword?: string;
|
|
12
|
+
}>;
|
|
13
|
+
}
|
|
14
|
+
export declare function validateAgainstSchema(kind: SchemaKind, document: unknown): SchemaValidationResult;
|
|
15
|
+
/** Minimal valid page document using §5 whitelist types (for structural smoke). */
|
|
16
|
+
export declare function sampleWhitelistedPage(): Record<string, unknown>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* search-table fixture adapter — four-layer query merge + selection events.
|
|
3
|
+
*/
|
|
4
|
+
export interface TableState {
|
|
5
|
+
filters: Record<string, unknown>;
|
|
6
|
+
page: number;
|
|
7
|
+
pageSize: number;
|
|
8
|
+
sort: string | null;
|
|
9
|
+
}
|
|
10
|
+
export interface SelectionState {
|
|
11
|
+
keys: unknown[];
|
|
12
|
+
count: number;
|
|
13
|
+
}
|
|
14
|
+
export declare function runSearchTable(input: Record<string, unknown>): Record<string, unknown>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* static-data fixture adapter (schema-ui-docs v2.7.0).
|
|
3
|
+
*/
|
|
4
|
+
type Json = unknown;
|
|
5
|
+
export type StaticDataResult = {
|
|
6
|
+
ok: true;
|
|
7
|
+
value: Json;
|
|
8
|
+
network: false;
|
|
9
|
+
} | {
|
|
10
|
+
ok: false;
|
|
11
|
+
code: "STATIC_DATA_SHAPE_MISMATCH" | "STATIC_DATA_REF_INVALID" | "STATIC_RESPONSE_MAPPING_NOT_ALLOWED";
|
|
12
|
+
};
|
|
13
|
+
interface DataRef {
|
|
14
|
+
source: "static" | "ref" | "api";
|
|
15
|
+
value?: Json;
|
|
16
|
+
ref?: string;
|
|
17
|
+
responseMapping?: unknown;
|
|
18
|
+
}
|
|
19
|
+
export declare function resolveStaticData(input: {
|
|
20
|
+
component: string;
|
|
21
|
+
data: DataRef;
|
|
22
|
+
datasources?: Record<string, unknown>;
|
|
23
|
+
props?: {
|
|
24
|
+
valueField?: string;
|
|
25
|
+
};
|
|
26
|
+
}): StaticDataResult;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Upload orchestration (schema-ui-docs@2.7.0 · docs/07-actions-contract.md §7
|
|
3
|
+
* + ADR-0012). I-PROTO-FULL-001 D-UPLOAD include.
|
|
4
|
+
*
|
|
5
|
+
* Client contract:
|
|
6
|
+
* - one multipart request per file (fieldName default "file"; method POST
|
|
7
|
+
* default, PUT allowed)
|
|
8
|
+
* - constraints (multiple / maxSize / accept) are checked BEFORE any
|
|
9
|
+
* request; any violation rejects the whole batch atomically
|
|
10
|
+
* - accept tokens: ".ext" matches the file extension case-insensitively,
|
|
11
|
+
* "type/*" matches the MIME main type, other tokens match MIME exactly
|
|
12
|
+
* (case-insensitive)
|
|
13
|
+
* - serial uploads in selection order; any failure stops the batch and no
|
|
14
|
+
* partial field value is committed
|
|
15
|
+
* - field value: url (priority) or id; multiple → array in selection order
|
|
16
|
+
* - retryPolicy idempotent → Idempotency-Key header "{invocationId}:{index}"
|
|
17
|
+
*/
|
|
18
|
+
export interface UploadFile {
|
|
19
|
+
name: string;
|
|
20
|
+
type: string;
|
|
21
|
+
size: number;
|
|
22
|
+
contentId: string;
|
|
23
|
+
}
|
|
24
|
+
/** Real-transport file: an UploadFile plus the bytes to send (browser File). */
|
|
25
|
+
export interface UploadableFile extends UploadFile {
|
|
26
|
+
blob: Blob;
|
|
27
|
+
}
|
|
28
|
+
export interface UploadActionResult {
|
|
29
|
+
url?: string;
|
|
30
|
+
id?: string;
|
|
31
|
+
method?: string;
|
|
32
|
+
fieldName?: string;
|
|
33
|
+
accept?: string;
|
|
34
|
+
maxSize?: number;
|
|
35
|
+
multiple?: boolean;
|
|
36
|
+
retryPolicy?: string;
|
|
37
|
+
}
|
|
38
|
+
export interface UploadRequestPart {
|
|
39
|
+
name: string;
|
|
40
|
+
fileName: string;
|
|
41
|
+
contentId: string;
|
|
42
|
+
}
|
|
43
|
+
export interface UploadRequest {
|
|
44
|
+
method: string;
|
|
45
|
+
url: string;
|
|
46
|
+
part: UploadRequestPart;
|
|
47
|
+
headers?: Record<string, string>;
|
|
48
|
+
}
|
|
49
|
+
export type UploadResult = {
|
|
50
|
+
type: "success";
|
|
51
|
+
response: {
|
|
52
|
+
url?: string;
|
|
53
|
+
id?: string;
|
|
54
|
+
};
|
|
55
|
+
} | {
|
|
56
|
+
type: "failure";
|
|
57
|
+
status?: number;
|
|
58
|
+
};
|
|
59
|
+
export interface UploadBatchResultOk {
|
|
60
|
+
ok: true;
|
|
61
|
+
requests: UploadRequest[];
|
|
62
|
+
fieldValue: string | string[] | null;
|
|
63
|
+
}
|
|
64
|
+
export interface UploadBatchResultError {
|
|
65
|
+
ok: false;
|
|
66
|
+
code: string;
|
|
67
|
+
fileIndex: number;
|
|
68
|
+
requests: UploadRequest[];
|
|
69
|
+
fieldValue: null;
|
|
70
|
+
}
|
|
71
|
+
export type UploadBatchResult = UploadBatchResultOk | UploadBatchResultError;
|
|
72
|
+
/** accept token matching (ADR-0012 D2): ".ext", "type/*", exact MIME. */
|
|
73
|
+
export declare function acceptTokenMatches(token: string, file: UploadFile): boolean;
|
|
74
|
+
/** Client-side constraints (ADR-0012 D2); returns the first violation. */
|
|
75
|
+
export declare function validateUploadSelection(action: UploadActionResult, files: UploadFile[]): {
|
|
76
|
+
ok: true;
|
|
77
|
+
} | {
|
|
78
|
+
ok: false;
|
|
79
|
+
code: string;
|
|
80
|
+
fileIndex: number;
|
|
81
|
+
};
|
|
82
|
+
/** Builds the per-file multipart request descriptors (pre-request). */
|
|
83
|
+
export declare function buildUploadRequests(action: UploadActionResult, files: UploadFile[], invocationId?: string): UploadBatchResultError | {
|
|
84
|
+
ok: true;
|
|
85
|
+
requests: UploadRequest[];
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Fixture-driven orchestration: replays pre-recorded transport results
|
|
89
|
+
* (`conformance/fixtures/uploads/cases.json` contract).
|
|
90
|
+
*/
|
|
91
|
+
export declare function runUploadBatch(input: {
|
|
92
|
+
action: UploadActionResult;
|
|
93
|
+
files: UploadFile[];
|
|
94
|
+
results?: UploadResult[];
|
|
95
|
+
invocationId?: string;
|
|
96
|
+
}): UploadBatchResult;
|
|
97
|
+
/**
|
|
98
|
+
* Real transport orchestration used by the Renderer's upload control: the
|
|
99
|
+
* same constraints and request shape, executed against a live fetch with
|
|
100
|
+
* multipart FormData carrying the actual file bytes (ADR-0012 D4).
|
|
101
|
+
*/
|
|
102
|
+
export declare function uploadFilesWithFetch(action: UploadActionResult, files: UploadableFile[], fetcher: typeof fetch, invocationId?: string): Promise<UploadBatchResult>;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
{
|
|
2
|
+
"claimVersion": "1.0",
|
|
3
|
+
"host": {
|
|
4
|
+
"hostId": "schema-ui-web",
|
|
5
|
+
"hostVersion": "0.1.0",
|
|
6
|
+
"buildId": "git:9337fd841c4256733acc3856fa518e2af4b4d33f"
|
|
7
|
+
},
|
|
8
|
+
"protocolArtifact": {
|
|
9
|
+
"artifactVersion": "2.9.0",
|
|
10
|
+
"contentSha256": "c87c22ad2ab4f4f19b93253312d6906b085ae6cd273168cc435d9863809d1c22"
|
|
11
|
+
},
|
|
12
|
+
"support": {
|
|
13
|
+
"pageVersions": [
|
|
14
|
+
"2.7",
|
|
15
|
+
"2.9"
|
|
16
|
+
],
|
|
17
|
+
"manifestVersions": [
|
|
18
|
+
"2.7",
|
|
19
|
+
"2.8",
|
|
20
|
+
"2.9"
|
|
21
|
+
],
|
|
22
|
+
"capabilities": [
|
|
23
|
+
"app.manifest",
|
|
24
|
+
"app.navigation",
|
|
25
|
+
"host.bootstrap",
|
|
26
|
+
"host.failure-recovery",
|
|
27
|
+
"host.conformance-claim",
|
|
28
|
+
"data.route-binding",
|
|
29
|
+
"form.controls.readonly"
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
"conformance": {
|
|
33
|
+
"fixtureVersion": "1.0",
|
|
34
|
+
"fixtureSha256": "89baddbc2879b0c183bcb50fbc730257df5786eee316b645e8238876fe0ca3e7",
|
|
35
|
+
"suites": [
|
|
36
|
+
{
|
|
37
|
+
"suiteId": "app-manifest",
|
|
38
|
+
"suiteVersion": "1.0",
|
|
39
|
+
"result": "pass"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"suiteId": "app-navigation",
|
|
43
|
+
"suiteVersion": "1.0",
|
|
44
|
+
"result": "pass"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"suiteId": "host-bootstrap",
|
|
48
|
+
"suiteVersion": "1.0",
|
|
49
|
+
"result": "pass"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"suiteId": "host-failure",
|
|
53
|
+
"suiteVersion": "1.0",
|
|
54
|
+
"result": "pass"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"suiteId": "host-conformance-claim",
|
|
58
|
+
"suiteVersion": "1.0",
|
|
59
|
+
"result": "pass"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"suiteId": "request-construction",
|
|
63
|
+
"suiteVersion": "1.0",
|
|
64
|
+
"result": "pass"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"suiteId": "component-format",
|
|
68
|
+
"suiteVersion": "1.0",
|
|
69
|
+
"result": "pass"
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
"evidence": [
|
|
74
|
+
{
|
|
75
|
+
"kind": "local-report",
|
|
76
|
+
"subjectBuildId": "git:9337fd841c4256733acc3856fa518e2af4b4d33f",
|
|
77
|
+
"uri": "/protocol/conformance-local-report.json",
|
|
78
|
+
"sha256": "3823b20137d448a6f43a4601cfacd830f918b83141c043ef3bd5cf64b52132c7"
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3b4c81afa0358e871caacda15ba3d7d93c63b2010a8fef450902516d656e2ad3
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"reportVersion": "1.0",
|
|
3
|
+
"subjectBuildId": "git:9337fd841c4256733acc3856fa518e2af4b4d33f",
|
|
4
|
+
"host": {
|
|
5
|
+
"hostId": "schema-ui-web",
|
|
6
|
+
"hostVersion": "0.1.0"
|
|
7
|
+
},
|
|
8
|
+
"suites": [
|
|
9
|
+
{
|
|
10
|
+
"suiteId": "app-manifest",
|
|
11
|
+
"fixtures": 41,
|
|
12
|
+
"suiteVersion": "1.0",
|
|
13
|
+
"result": "pass"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"suiteId": "app-navigation",
|
|
17
|
+
"fixtures": 16,
|
|
18
|
+
"suiteVersion": "1.0",
|
|
19
|
+
"result": "pass"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"suiteId": "host-bootstrap",
|
|
23
|
+
"fixtures": 23,
|
|
24
|
+
"suiteVersion": "1.0",
|
|
25
|
+
"result": "pass"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"suiteId": "host-failure",
|
|
29
|
+
"fixtures": 43,
|
|
30
|
+
"suiteVersion": "1.0",
|
|
31
|
+
"result": "pass"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"suiteId": "host-conformance-claim",
|
|
35
|
+
"fixtures": 30,
|
|
36
|
+
"suiteVersion": "1.0",
|
|
37
|
+
"result": "pass"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"suiteId": "request-construction",
|
|
41
|
+
"fixtures": 81,
|
|
42
|
+
"suiteVersion": "1.0",
|
|
43
|
+
"result": "pass"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"suiteId": "component-format",
|
|
47
|
+
"fixtures": 5,
|
|
48
|
+
"suiteVersion": "1.0",
|
|
49
|
+
"result": "pass"
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
"pinnedUpstream": {
|
|
53
|
+
"sourceRepo": "https://github.com/magicvr/schema-ui-docs",
|
|
54
|
+
"sourceCommit": "81aa1d8",
|
|
55
|
+
"artifactVersion": "2.8.0",
|
|
56
|
+
"fixtureSha256": "89baddbc2879b0c183bcb50fbc730257df5786eee316b645e8238876fe0ca3e7",
|
|
57
|
+
"protocolContentSha256": "c87c22ad2ab4f4f19b93253312d6906b085ae6cd273168cc435d9863809d1c22"
|
|
58
|
+
},
|
|
59
|
+
"residuals": []
|
|
60
|
+
}
|