openuispec 0.1.9 → 0.1.11
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 +36 -0
- package/cli/init.ts +70 -39
- package/package.json +1 -1
- package/schema/validate.ts +36 -2
package/README.md
CHANGED
|
@@ -119,6 +119,42 @@ openuispec/
|
|
|
119
119
|
└── README.md
|
|
120
120
|
```
|
|
121
121
|
|
|
122
|
+
## File formats and schemas
|
|
123
|
+
|
|
124
|
+
Every file type has a corresponding JSON Schema in `schema/`. **Read the schema before creating or editing a file** — do not guess the structure.
|
|
125
|
+
|
|
126
|
+
| File | Schema | Root key | Example |
|
|
127
|
+
|------|--------|----------|---------|
|
|
128
|
+
| `openuispec.yaml` | `openuispec.schema.json` | `spec_version` | [openuispec.yaml](./examples/taskflow/openuispec.yaml) |
|
|
129
|
+
| `screens/*.yaml` | `screen.schema.json` | `<screen_id>` | [home.yaml](./examples/taskflow/screens/home.yaml) |
|
|
130
|
+
| `flows/*.yaml` | `flow.schema.json` | `<flow_id>` | [create_task.yaml](./examples/taskflow/flows/create_task.yaml) |
|
|
131
|
+
| `platform/*.yaml` | `platform.schema.json` | `platform` | [ios.yaml](./examples/taskflow/platform/ios.yaml) |
|
|
132
|
+
| `locales/*.json` | `locale.schema.json` | (object) | [en.json](./examples/taskflow/locales/en.json) |
|
|
133
|
+
| `contracts/x_*.yaml` | `custom-contract.schema.json` | `contract` | [x_media_player.yaml](./examples/taskflow/contracts/x_media_player.yaml) |
|
|
134
|
+
| `tokens/color.yaml` | `tokens/color.schema.json` | `color` | [color.yaml](./examples/taskflow/tokens/color.yaml) |
|
|
135
|
+
| `tokens/typography.yaml` | `tokens/typography.schema.json` | `typography` | [typography.yaml](./examples/taskflow/tokens/typography.yaml) |
|
|
136
|
+
| `tokens/spacing.yaml` | `tokens/spacing.schema.json` | `spacing` | [spacing.yaml](./examples/taskflow/tokens/spacing.yaml) |
|
|
137
|
+
| `tokens/elevation.yaml` | `tokens/elevation.schema.json` | `elevation` | [elevation.yaml](./examples/taskflow/tokens/elevation.yaml) |
|
|
138
|
+
| `tokens/motion.yaml` | `tokens/motion.schema.json` | `motion` | [motion.yaml](./examples/taskflow/tokens/motion.yaml) |
|
|
139
|
+
| `tokens/layout.yaml` | `tokens/layout.schema.json` | `layout` | [layout.yaml](./examples/taskflow/tokens/layout.yaml) |
|
|
140
|
+
| `tokens/themes.yaml` | `tokens/themes.schema.json` | `themes` | [themes.yaml](./examples/taskflow/tokens/themes.yaml) |
|
|
141
|
+
| `tokens/icons.yaml` | `tokens/icons.schema.json` | `icons` | [icons.yaml](./examples/taskflow/tokens/icons.yaml) |
|
|
142
|
+
|
|
143
|
+
Every token file **must** have a single root wrapper key matching its type:
|
|
144
|
+
|
|
145
|
+
```yaml
|
|
146
|
+
# Correct — tokens/color.yaml
|
|
147
|
+
color:
|
|
148
|
+
brand:
|
|
149
|
+
primary: ...
|
|
150
|
+
|
|
151
|
+
# Wrong — missing root key
|
|
152
|
+
brand:
|
|
153
|
+
primary: ...
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Validate with: `openuispec validate`
|
|
157
|
+
|
|
122
158
|
## Spec at a glance
|
|
123
159
|
|
|
124
160
|
| Section | What it defines |
|
package/cli/init.ts
CHANGED
|
@@ -181,38 +181,47 @@ If the package is not in node_modules, fetch the full reference from:
|
|
|
181
181
|
- \`https://openuispec.rsteam.uz/llms-full.txt\` — complete spec + all JSON schemas in one file
|
|
182
182
|
- \`https://openuispec.rsteam.uz/llms.txt\` — concise summary with links
|
|
183
183
|
|
|
184
|
-
##
|
|
184
|
+
## Token file structure — root wrapper key required
|
|
185
185
|
|
|
186
|
-
|
|
186
|
+
Every token file must have a single root key matching the token type. Do NOT put properties at the top level.
|
|
187
187
|
|
|
188
|
+
\`\`\`yaml
|
|
189
|
+
# ✅ Correct — tokens/typography.yaml
|
|
190
|
+
typography:
|
|
191
|
+
font_family: ...
|
|
192
|
+
scale: ...
|
|
193
|
+
|
|
194
|
+
# ❌ Wrong — missing root wrapper key
|
|
195
|
+
font_family: ...
|
|
196
|
+
scale: ...
|
|
188
197
|
\`\`\`
|
|
189
|
-
node_modules/openuispec/schema/
|
|
190
|
-
├── openuispec.schema.json ← root manifest (openuispec.yaml)
|
|
191
|
-
├── screen.schema.json ← screen files (screens/*.yaml)
|
|
192
|
-
├── flow.schema.json ← flow files (flows/*.yaml)
|
|
193
|
-
├── platform.schema.json ← platform overrides (platform/*.yaml)
|
|
194
|
-
├── locale.schema.json ← locale files (locales/*.json)
|
|
195
|
-
├── custom-contract.schema.json ← custom contracts (contracts/*.yaml)
|
|
196
|
-
├── tokens/
|
|
197
|
-
│ ├── color.schema.json ← tokens/color.yaml
|
|
198
|
-
│ ├── typography.schema.json ← tokens/typography.yaml
|
|
199
|
-
│ ├── spacing.schema.json ← tokens/spacing.yaml
|
|
200
|
-
│ ├── elevation.schema.json ← tokens/elevation.yaml
|
|
201
|
-
│ ├── motion.schema.json ← tokens/motion.yaml
|
|
202
|
-
│ ├── layout.schema.json ← tokens/layout.yaml
|
|
203
|
-
│ ├── themes.schema.json ← tokens/themes.yaml
|
|
204
|
-
│ └── icons.schema.json ← tokens/icons.yaml
|
|
205
|
-
└── defs/
|
|
206
|
-
├── common.schema.json ← shared types (icons, badges, etc.)
|
|
207
|
-
├── action.schema.json ← 13 action types (discriminated union)
|
|
208
|
-
├── data-binding.schema.json ← data sources, state, params
|
|
209
|
-
├── adaptive.schema.json ← adaptive override pattern
|
|
210
|
-
└── validation.schema.json ← validation rule definitions
|
|
211
|
-
\`\`\`
|
|
212
198
|
|
|
213
|
-
|
|
199
|
+
Root keys: \`color\`, \`typography\`, \`spacing\`, \`elevation\`, \`motion\`, \`layout\`, \`themes\`, \`icons\`.
|
|
200
|
+
|
|
201
|
+
## File formats and schemas
|
|
202
|
+
|
|
203
|
+
**IMPORTANT:** Before creating or editing any spec file, read the corresponding JSON Schema to understand the valid structure. Do not guess the file format.
|
|
204
|
+
|
|
205
|
+
| File | Schema | Root key |
|
|
206
|
+
|------|--------|----------|
|
|
207
|
+
| \`openuispec.yaml\` | \`openuispec.schema.json\` | \`spec_version\` |
|
|
208
|
+
| \`screens/*.yaml\` | \`screen.schema.json\` | \`<screen_id>\` |
|
|
209
|
+
| \`flows/*.yaml\` | \`flow.schema.json\` | \`<flow_id>\` |
|
|
210
|
+
| \`platform/*.yaml\` | \`platform.schema.json\` | \`platform\` |
|
|
211
|
+
| \`locales/*.json\` | \`locale.schema.json\` | (object) |
|
|
212
|
+
| \`contracts/x_*.yaml\` | \`custom-contract.schema.json\` | \`contract\` |
|
|
213
|
+
| \`tokens/color.yaml\` | \`tokens/color.schema.json\` | \`color\` |
|
|
214
|
+
| \`tokens/typography.yaml\` | \`tokens/typography.schema.json\` | \`typography\` |
|
|
215
|
+
| \`tokens/spacing.yaml\` | \`tokens/spacing.schema.json\` | \`spacing\` |
|
|
216
|
+
| \`tokens/elevation.yaml\` | \`tokens/elevation.schema.json\` | \`elevation\` |
|
|
217
|
+
| \`tokens/motion.yaml\` | \`tokens/motion.schema.json\` | \`motion\` |
|
|
218
|
+
| \`tokens/layout.yaml\` | \`tokens/layout.schema.json\` | \`layout\` |
|
|
219
|
+
| \`tokens/themes.yaml\` | \`tokens/themes.schema.json\` | \`themes\` |
|
|
220
|
+
| \`tokens/icons.yaml\` | \`tokens/icons.schema.json\` | \`icons\` |
|
|
221
|
+
|
|
222
|
+
All schemas are in \`node_modules/openuispec/schema/\`. Shared type definitions (actions, data-binding, adaptive, validation, common) are in \`schema/defs/\`.
|
|
214
223
|
|
|
215
|
-
**
|
|
224
|
+
**Workflow:** read the schema → read an example from \`node_modules/openuispec/examples/taskflow/\` → create the YAML → run \`openuispec validate\`.
|
|
216
225
|
|
|
217
226
|
## Spec format quick reference
|
|
218
227
|
|
|
@@ -309,18 +318,40 @@ If the package is not in node_modules, fetch the full reference from:
|
|
|
309
318
|
- \`https://openuispec.rsteam.uz/llms-full.txt\` — complete spec + all JSON schemas in one file
|
|
310
319
|
- \`https://openuispec.rsteam.uz/llms.txt\` — concise summary with links
|
|
311
320
|
|
|
312
|
-
##
|
|
313
|
-
|
|
314
|
-
- \`
|
|
315
|
-
- \`
|
|
316
|
-
- \`
|
|
317
|
-
- \`
|
|
318
|
-
- \`
|
|
319
|
-
- \`
|
|
320
|
-
- \`
|
|
321
|
-
- \`
|
|
322
|
-
|
|
323
|
-
|
|
321
|
+
## Token file structure — root wrapper key required
|
|
322
|
+
Every token file must have a single root key matching the token type. Do NOT put properties at the top level.
|
|
323
|
+
- \`tokens/color.yaml\` → root key: \`color\`
|
|
324
|
+
- \`tokens/typography.yaml\` → root key: \`typography\`
|
|
325
|
+
- \`tokens/spacing.yaml\` → root key: \`spacing\`
|
|
326
|
+
- \`tokens/elevation.yaml\` → root key: \`elevation\`
|
|
327
|
+
- \`tokens/motion.yaml\` → root key: \`motion\`
|
|
328
|
+
- \`tokens/layout.yaml\` → root key: \`layout\`
|
|
329
|
+
- \`tokens/themes.yaml\` → root key: \`themes\`
|
|
330
|
+
- \`tokens/icons.yaml\` → root key: \`icons\`
|
|
331
|
+
|
|
332
|
+
## File formats and schemas — read before creating spec files
|
|
333
|
+
Before creating or editing any spec file, read the corresponding JSON Schema. Do not guess the file format.
|
|
334
|
+
|
|
335
|
+
| File | Schema (in \`node_modules/openuispec/schema/\`) | Root key |
|
|
336
|
+
|------|--------|----------|
|
|
337
|
+
| \`openuispec.yaml\` | \`openuispec.schema.json\` | \`spec_version\` |
|
|
338
|
+
| \`screens/*.yaml\` | \`screen.schema.json\` | \`<screen_id>\` |
|
|
339
|
+
| \`flows/*.yaml\` | \`flow.schema.json\` | \`<flow_id>\` |
|
|
340
|
+
| \`platform/*.yaml\` | \`platform.schema.json\` | \`platform\` |
|
|
341
|
+
| \`locales/*.json\` | \`locale.schema.json\` | (object) |
|
|
342
|
+
| \`contracts/x_*.yaml\` | \`custom-contract.schema.json\` | \`contract\` |
|
|
343
|
+
| \`tokens/color.yaml\` | \`tokens/color.schema.json\` | \`color\` |
|
|
344
|
+
| \`tokens/typography.yaml\` | \`tokens/typography.schema.json\` | \`typography\` |
|
|
345
|
+
| \`tokens/spacing.yaml\` | \`tokens/spacing.schema.json\` | \`spacing\` |
|
|
346
|
+
| \`tokens/elevation.yaml\` | \`tokens/elevation.schema.json\` | \`elevation\` |
|
|
347
|
+
| \`tokens/motion.yaml\` | \`tokens/motion.schema.json\` | \`motion\` |
|
|
348
|
+
| \`tokens/layout.yaml\` | \`tokens/layout.schema.json\` | \`layout\` |
|
|
349
|
+
| \`tokens/themes.yaml\` | \`tokens/themes.schema.json\` | \`themes\` |
|
|
350
|
+
| \`tokens/icons.yaml\` | \`tokens/icons.schema.json\` | \`icons\` |
|
|
351
|
+
|
|
352
|
+
Shared type definitions (actions, data-binding, adaptive, validation, common) are in \`schema/defs/\`.
|
|
353
|
+
|
|
354
|
+
Workflow: read the schema → read an example from \`node_modules/openuispec/examples/taskflow/\` → create the YAML → run \`openuispec validate\`.
|
|
324
355
|
|
|
325
356
|
## Spec format reference
|
|
326
357
|
- 7 contract families: nav_container, surface, action_trigger, input_field, data_display, collection, feedback
|
package/package.json
CHANGED
package/schema/validate.ts
CHANGED
|
@@ -71,6 +71,8 @@ function buildAjv(): AjvInstance {
|
|
|
71
71
|
return ajv;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
const BASE = "https://openuispec.org/schema/";
|
|
75
|
+
|
|
74
76
|
// ── validate one file ────────────────────────────────────────────────
|
|
75
77
|
|
|
76
78
|
function validateFile(
|
|
@@ -94,6 +96,12 @@ function validateFile(
|
|
|
94
96
|
return 0;
|
|
95
97
|
}
|
|
96
98
|
|
|
99
|
+
// Convert schema URL to a local path for display
|
|
100
|
+
const schemaLocalPath = schemaId.replace(
|
|
101
|
+
BASE,
|
|
102
|
+
"node_modules/openuispec/schema/",
|
|
103
|
+
);
|
|
104
|
+
|
|
97
105
|
const errors: ErrorObject[] = validate.errors ?? [];
|
|
98
106
|
console.log(` FAIL ${name} (${errors.length} error(s))`);
|
|
99
107
|
for (const e of errors.slice(0, 5)) {
|
|
@@ -109,13 +117,39 @@ function validateFile(
|
|
|
109
117
|
if (errors.length > 5) {
|
|
110
118
|
console.log(` ... and ${errors.length - 5} more`);
|
|
111
119
|
}
|
|
120
|
+
|
|
121
|
+
// Show hint when root-level structure is wrong (missing wrapper key)
|
|
122
|
+
const hasRootRequired = errors.some(
|
|
123
|
+
(e) => !e.instancePath && e.keyword === "required",
|
|
124
|
+
);
|
|
125
|
+
const hasRootAdditional = errors.some(
|
|
126
|
+
(e) => !e.instancePath && e.keyword === "additionalProperties",
|
|
127
|
+
);
|
|
128
|
+
if (hasRootRequired || hasRootAdditional) {
|
|
129
|
+
const expectedKey = errors.find(
|
|
130
|
+
(e) => !e.instancePath && e.keyword === "required",
|
|
131
|
+
)?.params?.missingProperty as string | undefined;
|
|
132
|
+
if (expectedKey) {
|
|
133
|
+
console.log(
|
|
134
|
+
`\n Hint: "${name}" needs a root "${expectedKey}:" wrapper key.`,
|
|
135
|
+
);
|
|
136
|
+
console.log(` Example:`);
|
|
137
|
+
console.log(` ${expectedKey}:`);
|
|
138
|
+
console.log(` ...your content here...`);
|
|
139
|
+
} else {
|
|
140
|
+
console.log(
|
|
141
|
+
`\n Hint: This file has unexpected top-level properties.`,
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
console.log(` Schema: ${schemaLocalPath}`);
|
|
147
|
+
|
|
112
148
|
return errors.length;
|
|
113
149
|
}
|
|
114
150
|
|
|
115
151
|
// ── validation groups ────────────────────────────────────────────────
|
|
116
152
|
|
|
117
|
-
const BASE = "https://openuispec.org/schema/";
|
|
118
|
-
|
|
119
153
|
interface ValidationGroup {
|
|
120
154
|
label: string;
|
|
121
155
|
run(ajv: AjvInstance, projectDir: string): number;
|