@delurio/cli 0.1.0 → 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/CHANGELOG.md +21 -0
- package/README.md +48 -7
- package/SPEC.md +9 -7
- package/dist/check.js +26 -2
- package/dist/cli.js +98 -18
- package/dist/index-page.js +50 -0
- package/dist/schemas.js +256 -0
- package/dist/watch.js +114 -0
- package/package.json +4 -2
- package/schemas/catalog.schema.json +13 -0
- package/schemas/domain.schema.json +305 -0
- package/schemas/flow.schema.json +346 -0
- package/schemas/nav.schema.json +292 -0
- package/schemas/ui.schema.json +250 -0
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://unpkg.com/@delurio/cli@0.2.0/schemas/ui.schema.json",
|
|
4
|
+
"title": "delurio UI graph (ui.yaml)",
|
|
5
|
+
"description": "What each state of a flow shows, in delurio-graph/0 (SPEC.md §4): the nodes of the screen, their WAI-ARIA roles, accessible names, visible texts and the events they send. Every word a user sees comes from the catalog, by key.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["schema", "kind", "id", "catalog", "nodes"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"schema": { "$ref": "#/$defs/formatVersion" },
|
|
11
|
+
"kind": { "description": "The kind of graph file. A ui.yaml is `ui`.", "const": "ui" },
|
|
12
|
+
"id": { "$ref": "#/$defs/graphId", "description": "The UI graph's id; its flow names it with `ui:`.", "examples": ["qauth.authorize"] },
|
|
13
|
+
"flow": { "$ref": "#/$defs/graphId", "description": "The id of the flow whose states the nodes are shown in." },
|
|
14
|
+
"title": { "type": "string", "description": "The UI graph in plain words, for people." },
|
|
15
|
+
"summary": { "type": "string", "description": "What the screens are, in a few plain sentences." },
|
|
16
|
+
"status": { "$ref": "#/$defs/status" },
|
|
17
|
+
"source": { "$ref": "#/$defs/sourceAnchor" },
|
|
18
|
+
"catalog": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"description": "The catalog the page uses, relative to this file: `catalog/<locale>.json`, a locale being a BCP 47 tag.",
|
|
21
|
+
"pattern": "\\.json$",
|
|
22
|
+
"examples": ["catalog/en.json", "catalog/tr.json"]
|
|
23
|
+
},
|
|
24
|
+
"locales": {
|
|
25
|
+
"type": "array",
|
|
26
|
+
"description": "The locales the UI is written in, as BCP 47 tags; each has a catalog beside `catalog`, named `<locale>.json`.",
|
|
27
|
+
"minItems": 1,
|
|
28
|
+
"uniqueItems": true,
|
|
29
|
+
"items": { "$ref": "#/$defs/locale" },
|
|
30
|
+
"examples": [["en"], ["tr", "en"]]
|
|
31
|
+
},
|
|
32
|
+
"kit": { "type": "string", "description": "The kit the screens are drawn with (SPEC.md §8), relative to the graph; `--kit` wins.", "examples": ["../kit"] },
|
|
33
|
+
"samples": {
|
|
34
|
+
"type": "object",
|
|
35
|
+
"description": "Values for catalog parameters, on the page and in videos: `{client}` in a message is filled with `samples.client`.",
|
|
36
|
+
"additionalProperties": { "type": "string", "description": "The sample value." },
|
|
37
|
+
"examples": [{ "client": "Acme Notes" }]
|
|
38
|
+
},
|
|
39
|
+
"changes": {
|
|
40
|
+
"type": "object",
|
|
41
|
+
"description": "What the flow changes and what follows, in its users' own words: what is created, sent, charged or removed, who sees it, and whether it can be undone. Required under --strict when the flow's steps invoke a writing action of its domain.",
|
|
42
|
+
"required": ["key"],
|
|
43
|
+
"additionalProperties": false,
|
|
44
|
+
"properties": {
|
|
45
|
+
"key": { "$ref": "#/$defs/catalogKey", "description": "The catalog key of the note; every locale's catalog must have it.", "examples": ["Changes.note"] }
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"nodes": {
|
|
49
|
+
"type": "object",
|
|
50
|
+
"description": "The nodes of the screens, by id. A node is shown in a state when the state is in `in`, not in `unless`, and `when` holds.",
|
|
51
|
+
"propertyNames": { "$ref": "#/$defs/identifier" },
|
|
52
|
+
"additionalProperties": { "$ref": "#/$defs/node" }
|
|
53
|
+
},
|
|
54
|
+
"edges": {
|
|
55
|
+
"type": "array",
|
|
56
|
+
"description": "Relations the page and the checks use: a node labelled by another, an action that leads to a state.",
|
|
57
|
+
"items": { "$ref": "#/$defs/edge" }
|
|
58
|
+
},
|
|
59
|
+
"rules": {
|
|
60
|
+
"type": "array",
|
|
61
|
+
"description": "Rules the screens must keep, in words. Written but no tool reads them yet (#3).",
|
|
62
|
+
"items": {
|
|
63
|
+
"type": "object",
|
|
64
|
+
"description": "A rule of the screens.",
|
|
65
|
+
"required": ["id", "rule"],
|
|
66
|
+
"additionalProperties": false,
|
|
67
|
+
"properties": {
|
|
68
|
+
"id": { "type": "string", "description": "The rule's id." },
|
|
69
|
+
"rule": { "type": "string", "description": "The rule, in words." }
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"$defs": {
|
|
75
|
+
"formatVersion": {
|
|
76
|
+
"description": "The format and its version. Every graph file starts with it.",
|
|
77
|
+
"const": "delurio-graph/0"
|
|
78
|
+
},
|
|
79
|
+
"status": {
|
|
80
|
+
"description": "`proposed`: written before or apart from the code, nobody has approved it. `captured`: read from existing code (capture mode, every element carries `source`). `approved`: the owner reviewed and accepted it.",
|
|
81
|
+
"enum": ["proposed", "captured", "approved"]
|
|
82
|
+
},
|
|
83
|
+
"graphId": {
|
|
84
|
+
"type": "string",
|
|
85
|
+
"description": "The id of a graph.",
|
|
86
|
+
"pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*$"
|
|
87
|
+
},
|
|
88
|
+
"identifier": {
|
|
89
|
+
"type": "string",
|
|
90
|
+
"description": "An identifier of the graph: English camelCase (SPEC.md §1, Text).",
|
|
91
|
+
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
92
|
+
},
|
|
93
|
+
"stateRef": {
|
|
94
|
+
"type": "string",
|
|
95
|
+
"description": "The id of a state of the flow.",
|
|
96
|
+
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
97
|
+
},
|
|
98
|
+
"nodeRef": {
|
|
99
|
+
"type": "string",
|
|
100
|
+
"description": "The id of a node of this UI graph.",
|
|
101
|
+
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
102
|
+
},
|
|
103
|
+
"states": {
|
|
104
|
+
"type": "array",
|
|
105
|
+
"description": "States of the flow, by id.",
|
|
106
|
+
"uniqueItems": true,
|
|
107
|
+
"items": { "$ref": "#/$defs/stateRef" }
|
|
108
|
+
},
|
|
109
|
+
"catalogKey": {
|
|
110
|
+
"type": "string",
|
|
111
|
+
"description": "A key of the catalog (catalog/<locale>.json).",
|
|
112
|
+
"minLength": 1,
|
|
113
|
+
"examples": ["Consent.title"]
|
|
114
|
+
},
|
|
115
|
+
"locale": {
|
|
116
|
+
"type": "string",
|
|
117
|
+
"description": "A BCP 47 language tag.",
|
|
118
|
+
"pattern": "^[A-Za-z]{2,3}(-[A-Za-z0-9]{1,8})*$",
|
|
119
|
+
"examples": ["en", "tr", "pt-BR"]
|
|
120
|
+
},
|
|
121
|
+
"expression": {
|
|
122
|
+
"type": "string",
|
|
123
|
+
"description": "An expression of delurio's own language (SPEC.md §3) over the flow's context: or, and, not, ==, !=, in, not in, ( ), [lists], 'strings', numbers, true, false, null, and names (a context variable, a named guard of the flow, or `state`).",
|
|
124
|
+
"minLength": 1,
|
|
125
|
+
"examples": ["retryNote", "repo == 'behind'"]
|
|
126
|
+
},
|
|
127
|
+
"sourceAnchor": {
|
|
128
|
+
"type": "string",
|
|
129
|
+
"description": "A source anchor (SPEC.md §9): `<repo-relative path>:<line>`, or a bare `<path>` for a whole file, naming the code that draws the element.",
|
|
130
|
+
"pattern": "^[^\\s:]+(:[0-9]+)?$",
|
|
131
|
+
"examples": ["src/consent/ConsentPage.tsx:42"]
|
|
132
|
+
},
|
|
133
|
+
"label": {
|
|
134
|
+
"$comment": "exactly one of key, labelledBy, literal or oneOf",
|
|
135
|
+
"type": "object",
|
|
136
|
+
"description": "Words of a node, in one of these forms: `{ key, params }` from the catalog, `{ labelledBy: <node> }`, `{ literal }`, or `{ oneOf: [keys] }`.",
|
|
137
|
+
"additionalProperties": false,
|
|
138
|
+
"properties": {
|
|
139
|
+
"key": { "$ref": "#/$defs/catalogKey", "description": "The catalog key of the message." },
|
|
140
|
+
"params": {
|
|
141
|
+
"type": "object",
|
|
142
|
+
"description": "The data each `{param}` of the message stands for (e.g. `client: client.name`); the page fills it from `samples`.",
|
|
143
|
+
"additionalProperties": { "type": "string", "description": "The data the parameter stands for." }
|
|
144
|
+
},
|
|
145
|
+
"labelledBy": { "$ref": "#/$defs/nodeRef", "description": "The node whose text gives these words." },
|
|
146
|
+
"literal": { "type": "string", "description": "Words that are not translated (a product name, a code)." },
|
|
147
|
+
"oneOf": {
|
|
148
|
+
"type": "array",
|
|
149
|
+
"description": "Catalog keys of which one is shown, depending on the data.",
|
|
150
|
+
"minItems": 1,
|
|
151
|
+
"items": { "$ref": "#/$defs/catalogKey" }
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
"oneOf": [
|
|
155
|
+
{ "required": ["key"] },
|
|
156
|
+
{ "required": ["labelledBy"] },
|
|
157
|
+
{ "required": ["literal"] },
|
|
158
|
+
{ "required": ["oneOf"] }
|
|
159
|
+
],
|
|
160
|
+
"allOf": [
|
|
161
|
+
{
|
|
162
|
+
"$comment": "params go with key or oneOf",
|
|
163
|
+
"if": { "anyOf": [{ "required": ["labelledBy"] }, { "required": ["literal"] }] },
|
|
164
|
+
"then": { "properties": { "params": false } }
|
|
165
|
+
}
|
|
166
|
+
]
|
|
167
|
+
},
|
|
168
|
+
"node": {
|
|
169
|
+
"type": "object",
|
|
170
|
+
"description": "A node of a screen.",
|
|
171
|
+
"required": ["type"],
|
|
172
|
+
"additionalProperties": false,
|
|
173
|
+
"properties": {
|
|
174
|
+
"type": {
|
|
175
|
+
"description": "What the node is.",
|
|
176
|
+
"enum": ["page", "text", "action", "field", "list", "status", "alert"]
|
|
177
|
+
},
|
|
178
|
+
"component": {
|
|
179
|
+
"description": "A kit-neutral component; a kit maps it to the product's own (SPEC.md §8). A `TextField`'s `text` is its label, and the field is named by it.",
|
|
180
|
+
"enum": ["Page", "Heading", "Text", "Button", "LinkButton", "TextField", "List", "ListItem", "Status", "Alert"]
|
|
181
|
+
},
|
|
182
|
+
"role": {
|
|
183
|
+
"description": "The WAI-ARIA 1.2 role the node exposes; `kit check` reads it from the browser's accessibility tree.",
|
|
184
|
+
"enum": [
|
|
185
|
+
"alert", "alertdialog", "application", "article", "banner", "blockquote", "button", "caption", "cell", "checkbox",
|
|
186
|
+
"code", "columnheader", "combobox", "complementary", "contentinfo", "definition", "deletion", "dialog", "directory",
|
|
187
|
+
"document", "emphasis", "feed", "figure", "form", "generic", "grid", "gridcell", "group", "heading", "img",
|
|
188
|
+
"insertion", "link", "list", "listbox", "listitem", "log", "main", "marquee", "math", "menu", "menubar", "menuitem",
|
|
189
|
+
"menuitemcheckbox", "menuitemradio", "meter", "navigation", "none", "note", "option", "paragraph", "presentation",
|
|
190
|
+
"progressbar", "radio", "radiogroup", "region", "row", "rowgroup", "rowheader", "scrollbar", "search", "searchbox",
|
|
191
|
+
"separator", "slider", "spinbutton", "status", "strong", "subscript", "superscript", "switch", "tab", "table",
|
|
192
|
+
"tablist", "tabpanel", "term", "textbox", "time", "timer", "toolbar", "tooltip", "tree", "treegrid", "treeitem"
|
|
193
|
+
]
|
|
194
|
+
},
|
|
195
|
+
"intent": {
|
|
196
|
+
"description": "For actions: `confirm`, `dismiss` or `secondary`.",
|
|
197
|
+
"enum": ["confirm", "dismiss", "secondary"]
|
|
198
|
+
},
|
|
199
|
+
"name": { "$ref": "#/$defs/label", "description": "The accessible name (Accessible Name and Description Computation 1.2), kept apart from `text` so that \"the visible text is in the name\" (WCAG 2.5.3) is checkable." },
|
|
200
|
+
"text": { "$ref": "#/$defs/label", "description": "The visible text." },
|
|
201
|
+
"in": { "$ref": "#/$defs/states", "description": "The flow states the node is shown in." },
|
|
202
|
+
"unless": { "$ref": "#/$defs/states", "description": "The flow states the node is not shown in." },
|
|
203
|
+
"when": { "$ref": "#/$defs/expression", "description": "A guard or context flag of the flow that must hold for the node to show." },
|
|
204
|
+
"disabledIn": { "$ref": "#/$defs/states", "description": "The states where the node is shown but disabled." },
|
|
205
|
+
"emits": {
|
|
206
|
+
"type": "string",
|
|
207
|
+
"description": "The event the node sends when pressed: an event of the flow, UPPER_SNAKE.",
|
|
208
|
+
"pattern": "^[A-Z][A-Z0-9_]*$"
|
|
209
|
+
},
|
|
210
|
+
"initialFocus": { "$ref": "#/$defs/nodeRef", "description": "On a page: the node that has focus when it opens." },
|
|
211
|
+
"repeat": { "type": "string", "description": "The node is drawn once per item of this data.", "examples": ["request.scopes"] },
|
|
212
|
+
"frame": {
|
|
213
|
+
"description": "For a page: whether it may be framed; `never` (served with CSP frame-ancestors 'none').",
|
|
214
|
+
"const": "never"
|
|
215
|
+
},
|
|
216
|
+
"source": { "$ref": "#/$defs/sourceAnchor" }
|
|
217
|
+
},
|
|
218
|
+
"allOf": [
|
|
219
|
+
{
|
|
220
|
+
"$comment": "initialFocus and frame are only on a page",
|
|
221
|
+
"if": { "not": { "properties": { "type": { "const": "page" } } } },
|
|
222
|
+
"then": { "properties": { "initialFocus": false, "frame": false } }
|
|
223
|
+
}
|
|
224
|
+
]
|
|
225
|
+
},
|
|
226
|
+
"edge": {
|
|
227
|
+
"type": "object",
|
|
228
|
+
"description": "A relation between nodes: `{ labelledBy: [node, labelNode] }` or `{ triggers: [node, state] }`.",
|
|
229
|
+
"minProperties": 1,
|
|
230
|
+
"maxProperties": 1,
|
|
231
|
+
"additionalProperties": false,
|
|
232
|
+
"properties": {
|
|
233
|
+
"labelledBy": {
|
|
234
|
+
"type": "array",
|
|
235
|
+
"description": "A node and the node that labels it.",
|
|
236
|
+
"prefixItems": [{ "$ref": "#/$defs/nodeRef" }, { "$ref": "#/$defs/nodeRef" }],
|
|
237
|
+
"minItems": 2,
|
|
238
|
+
"maxItems": 2
|
|
239
|
+
},
|
|
240
|
+
"triggers": {
|
|
241
|
+
"type": "array",
|
|
242
|
+
"description": "An action and the state it leads to.",
|
|
243
|
+
"prefixItems": [{ "$ref": "#/$defs/nodeRef" }, { "$ref": "#/$defs/stateRef" }],
|
|
244
|
+
"minItems": 2,
|
|
245
|
+
"maxItems": 2
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|