@table-bro/mcp 0.0.0-stage → 1.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/LICENSE +21 -0
- package/README.md +97 -2
- package/dist/docs/docs.d.ts +21 -0
- package/dist/docs/docs.js +103 -0
- package/dist/docs/pages.d.ts +28 -0
- package/dist/docs/pages.js +2734 -0
- package/dist/docs/topics.d.ts +11 -0
- package/dist/docs/topics.js +410 -0
- package/dist/extension.d.ts +23 -0
- package/dist/extension.js +1 -0
- package/dist/generate/angular.d.ts +26 -0
- package/dist/generate/angular.js +241 -0
- package/dist/generate/cells.d.ts +22 -0
- package/dist/generate/cells.js +157 -0
- package/dist/generate/code.d.ts +48 -0
- package/dist/generate/code.js +153 -0
- package/dist/generate/config.d.ts +16 -0
- package/dist/generate/config.js +95 -0
- package/dist/generate/fillings.d.ts +49 -0
- package/dist/generate/fillings.js +130 -0
- package/dist/generate/filters.d.ts +36 -0
- package/dist/generate/filters.js +254 -0
- package/dist/generate/generate-code.d.ts +34 -0
- package/dist/generate/generate-code.js +59 -0
- package/dist/generate/names.d.ts +52 -0
- package/dist/generate/names.js +93 -0
- package/dist/generate/rows.d.ts +5 -0
- package/dist/generate/rows.js +22 -0
- package/dist/generate/scaffold.d.ts +35 -0
- package/dist/generate/scaffold.js +62 -0
- package/dist/generate/service.d.ts +16 -0
- package/dist/generate/service.js +320 -0
- package/dist/generate/setup.d.ts +34 -0
- package/dist/generate/setup.js +158 -0
- package/dist/generate/vanilla.d.ts +10 -0
- package/dist/generate/vanilla.js +160 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +10 -0
- package/dist/project/inspect-project.d.ts +53 -0
- package/dist/project/inspect-project.js +223 -0
- package/dist/server/main.d.ts +2 -0
- package/dist/server/main.js +8 -0
- package/dist/server/server.d.ts +17 -0
- package/dist/server/server.js +212 -0
- package/dist/spec/builtin-specs.d.ts +13 -0
- package/dist/spec/builtin-specs.js +167 -0
- package/dist/spec/css-variables.d.ts +22 -0
- package/dist/spec/css-variables.js +54 -0
- package/dist/spec/schema.d.ts +19 -0
- package/dist/spec/schema.js +278 -0
- package/dist/spec/skin-config.d.ts +30 -0
- package/dist/spec/skin-config.js +67 -0
- package/dist/spec/spec.d.ts +157 -0
- package/dist/spec/spec.js +2 -0
- package/dist/spec/validate-spec.d.ts +54 -0
- package/dist/spec/validate-spec.js +979 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +2 -0
- package/package.json +71 -4
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import { cssVariables } from './css-variables.js';
|
|
2
|
+
const string = { type: 'string' };
|
|
3
|
+
const boolean = { type: 'boolean' };
|
|
4
|
+
const button = {
|
|
5
|
+
type: 'object',
|
|
6
|
+
properties: {
|
|
7
|
+
title: string,
|
|
8
|
+
action: { type: 'string', description: 'The action of the bro-action event on a click, as export' },
|
|
9
|
+
icon: { type: 'string', description: 'The name of a Material icon, as download: in the mat skin a button of the toolbar is an icon with a tooltip, the other skins show the title' }
|
|
10
|
+
},
|
|
11
|
+
required: ['title', 'action'],
|
|
12
|
+
additionalProperties: false
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* The JSON Schema of BroTableSpec, for the tools of the MCP server and the reference. It gives the form; validateSpec
|
|
16
|
+
* checks the meaning: the names of the fields, the cells and the filters, the values of the CSS variables.
|
|
17
|
+
*/
|
|
18
|
+
export const specSchema = {
|
|
19
|
+
'$schema': 'https://json-schema.org/draft/2020-12/schema',
|
|
20
|
+
title: 'BroTableSpec',
|
|
21
|
+
description: 'A Table, Bro table as data: columns, custom cells, filters, rows, config and CSS variables, without functions and without the tags of a skin',
|
|
22
|
+
type: 'object',
|
|
23
|
+
properties: {
|
|
24
|
+
specVersion: { const: 1 },
|
|
25
|
+
rowType: { type: 'string', description: 'The name of the type of a row in PascalCase, as Order' },
|
|
26
|
+
fields: {
|
|
27
|
+
type: 'array',
|
|
28
|
+
description: 'The fields of a row',
|
|
29
|
+
items: {
|
|
30
|
+
type: 'object',
|
|
31
|
+
properties: {
|
|
32
|
+
name: { type: 'string', description: 'An identifier, as customerName' },
|
|
33
|
+
type: { enum: ['string', 'number', 'boolean', 'string[]'] },
|
|
34
|
+
values: { type: 'array', items: string, description: 'All values of a string field: the rows take only them, a select filter offers them' },
|
|
35
|
+
source: { type: 'string', description: 'With an API: the path of the value in an item of its answer, as price or meta.createdAt' }
|
|
36
|
+
},
|
|
37
|
+
required: ['name', 'type'],
|
|
38
|
+
additionalProperties: false
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
cols: {
|
|
42
|
+
type: 'array',
|
|
43
|
+
items: {
|
|
44
|
+
type: 'object',
|
|
45
|
+
properties: {
|
|
46
|
+
title: string,
|
|
47
|
+
name: { type: 'string', description: 'The field of the row the column shows' },
|
|
48
|
+
shortTitle: { type: 'string', description: 'The title for the narrowest width of the column; the default is the first word of the title' },
|
|
49
|
+
tooltip: string,
|
|
50
|
+
dataType: { enum: ['string', 'number', 'boolean'], description: 'By default the type of the field' },
|
|
51
|
+
sortKey: { type: 'string', description: 'The field the column sorts by' },
|
|
52
|
+
component: {
|
|
53
|
+
description: 'A custom cell of cells, or a ready element of the skins: tags, switch or details-button',
|
|
54
|
+
oneOf: [
|
|
55
|
+
{ type: 'object', properties: { cell: string }, required: ['cell'], additionalProperties: false },
|
|
56
|
+
{ type: 'object', properties: { element: { enum: ['tags', 'switch', 'details-button'] } }, required: ['element'], additionalProperties: false }
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
required: ['title'],
|
|
61
|
+
additionalProperties: false
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
cells: {
|
|
65
|
+
type: 'array',
|
|
66
|
+
description: 'The contracts of the custom cells and of the row details',
|
|
67
|
+
items: {
|
|
68
|
+
type: 'object',
|
|
69
|
+
properties: {
|
|
70
|
+
name: { type: 'string', description: 'In kebab-case, as status' },
|
|
71
|
+
kind: { enum: ['cell', 'details'], description: 'A cell of a column, or the element of the row details' },
|
|
72
|
+
shows: { type: 'string', description: 'What the cell shows, in words' },
|
|
73
|
+
fields: { type: 'array', items: string, description: 'The fields of the row the cell reads' },
|
|
74
|
+
actions: { type: 'array', items: string, description: 'The actions the cell sends, as edit' }
|
|
75
|
+
},
|
|
76
|
+
required: ['name', 'shows', 'fields'],
|
|
77
|
+
additionalProperties: false
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
filters: {
|
|
81
|
+
type: 'array',
|
|
82
|
+
description: 'The filters of the Filter Drawer next to the table',
|
|
83
|
+
items: {
|
|
84
|
+
type: 'object',
|
|
85
|
+
properties: {
|
|
86
|
+
name: { type: 'string', description: 'The key in the object of the filters; a range has the keys <name>From and <name>To' },
|
|
87
|
+
label: string,
|
|
88
|
+
control: { enum: ['text', 'select', 'range', 'checkbox'] },
|
|
89
|
+
field: { type: 'string', description: 'The field of the row the filter compares' },
|
|
90
|
+
match: { enum: ['contains', 'startsWith', 'eq', 'custom'], description: 'text: contains or startsWith; select and checkbox: eq; range compares itself' },
|
|
91
|
+
rule: { type: 'string', description: 'The rule of the match custom, in words' }
|
|
92
|
+
},
|
|
93
|
+
required: ['name', 'label', 'control'],
|
|
94
|
+
additionalProperties: false
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
rows: {
|
|
98
|
+
type: 'array',
|
|
99
|
+
description: 'The rows of the spec: objects with the fields of the row',
|
|
100
|
+
items: { type: 'object' }
|
|
101
|
+
},
|
|
102
|
+
config: {
|
|
103
|
+
type: 'object',
|
|
104
|
+
properties: {
|
|
105
|
+
toolbarTitle: string,
|
|
106
|
+
pageSize: { type: 'integer', minimum: 1, description: 'The rows on a page' },
|
|
107
|
+
server: { type: 'boolean', description: 'The rows come from the server by the query of the table' },
|
|
108
|
+
rowCounter: boolean,
|
|
109
|
+
shadowsEnabled: boolean,
|
|
110
|
+
theme: { enum: ['light', 'dark', 'auto'] },
|
|
111
|
+
rowDetailsComponent: { type: 'object', properties: { cell: string }, required: ['cell'], additionalProperties: false, description: 'A cell of the kind details' },
|
|
112
|
+
rowDetailsServer: boolean,
|
|
113
|
+
rowDetailsMotion: { enum: ['kinetic', 'eased'], description: 'The motion of the row details: kinetic by default, eased opens them in --bro-details-duration' }
|
|
114
|
+
},
|
|
115
|
+
additionalProperties: false
|
|
116
|
+
},
|
|
117
|
+
toolbar: {
|
|
118
|
+
type: 'object',
|
|
119
|
+
properties: {
|
|
120
|
+
buttons: { type: 'array', items: button },
|
|
121
|
+
menu: {
|
|
122
|
+
type: 'object',
|
|
123
|
+
properties: { title: string, items: { type: 'array', items: button } },
|
|
124
|
+
required: ['title', 'items'],
|
|
125
|
+
additionalProperties: false
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
additionalProperties: false
|
|
129
|
+
},
|
|
130
|
+
stateMessages: {
|
|
131
|
+
type: 'object',
|
|
132
|
+
properties: { loading: string, 'no-data': string, 'not-found': string, fail: string },
|
|
133
|
+
additionalProperties: false
|
|
134
|
+
},
|
|
135
|
+
skinConfig: {
|
|
136
|
+
type: 'object',
|
|
137
|
+
description: 'The settings of the components of one skin, with the names of BroConfig',
|
|
138
|
+
properties: Object.fromEntries(['mat', 'bs', 'nv'].map(skin => [skin, {
|
|
139
|
+
type: 'object',
|
|
140
|
+
properties: {
|
|
141
|
+
css: { type: 'object', description: 'Values of BroConfig.css' },
|
|
142
|
+
components: { type: 'object', description: 'Values of BroConfig.components, without functions' },
|
|
143
|
+
callbacks: {
|
|
144
|
+
type: 'array',
|
|
145
|
+
items: {
|
|
146
|
+
type: 'object',
|
|
147
|
+
properties: {
|
|
148
|
+
path: { type: 'string', description: 'The path of the function, as components.sortHeader.afterRender' },
|
|
149
|
+
does: { type: 'string', description: 'What the function does, in words' }
|
|
150
|
+
},
|
|
151
|
+
required: ['path', 'does'],
|
|
152
|
+
additionalProperties: false
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
additionalProperties: false
|
|
157
|
+
}])),
|
|
158
|
+
additionalProperties: false
|
|
159
|
+
},
|
|
160
|
+
api: {
|
|
161
|
+
type: 'object',
|
|
162
|
+
description: 'The GET endpoint that gives the rows',
|
|
163
|
+
properties: {
|
|
164
|
+
url: { type: 'string', description: 'The address of the endpoint, http or https' },
|
|
165
|
+
rows: { type: 'string', description: 'The path of the array of the rows in the answer, as products; empty for an answer that is the array' },
|
|
166
|
+
paging: {
|
|
167
|
+
type: 'object',
|
|
168
|
+
description: 'An API that gives the rows page by page: the query parameters of the size of a page and of its offset or number',
|
|
169
|
+
properties: { size: string, offset: string, page: string },
|
|
170
|
+
required: ['size'],
|
|
171
|
+
additionalProperties: false
|
|
172
|
+
},
|
|
173
|
+
total: { type: 'string', description: 'The path of the number of all rows in the answer of a page, as total: an API that gives pages has it' },
|
|
174
|
+
search: { type: 'string', description: 'An API that gives pages: the query parameter of its text search, as search' },
|
|
175
|
+
sort: {
|
|
176
|
+
type: 'object',
|
|
177
|
+
description: 'An API that gives pages: the query parameters of the sort, of the field and of the direction, asc or desc; without order a minus before the field sorts down',
|
|
178
|
+
properties: { field: string, order: string },
|
|
179
|
+
required: ['field'],
|
|
180
|
+
additionalProperties: false
|
|
181
|
+
},
|
|
182
|
+
filters: {
|
|
183
|
+
type: 'object',
|
|
184
|
+
description: 'An API that gives pages: the query parameter of every key of the filters, as {"newsSite": "news_site"}; a range has the keys <name>From and <name>To',
|
|
185
|
+
additionalProperties: string
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
required: ['url', 'rows'],
|
|
189
|
+
additionalProperties: false
|
|
190
|
+
},
|
|
191
|
+
cssVars: {
|
|
192
|
+
type: 'object',
|
|
193
|
+
description: 'The CSS variables of the table',
|
|
194
|
+
properties: Object.fromEntries(cssVariables.map(variable => [variable.name, { type: 'string', description: variable.description }])),
|
|
195
|
+
additionalProperties: false
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
required: ['specVersion', 'rowType', 'fields', 'cols'],
|
|
199
|
+
additionalProperties: false
|
|
200
|
+
};
|
|
201
|
+
/** The JSON Schema of a filter of the Filter Drawer, as in the spec. */
|
|
202
|
+
export const filterSchema = specSchema['properties']['filters']['items'];
|
|
203
|
+
/** The JSON Schema of the filling of one cell or of the row details, BroCellFilling, for the tools of the MCP server. */
|
|
204
|
+
export const cellFillingSchema = {
|
|
205
|
+
type: 'object',
|
|
206
|
+
properties: {
|
|
207
|
+
imports: {
|
|
208
|
+
type: 'array',
|
|
209
|
+
description: 'Angular: the components of the project that the template uses; the classes of Angular Material and the pipes of Angular come from the template',
|
|
210
|
+
items: {
|
|
211
|
+
anyOf: [
|
|
212
|
+
{ type: 'object', properties: { name: string, from: { type: 'string', description: 'The path of the module, as ./order-badge' } }, required: ['name', 'from'], additionalProperties: false },
|
|
213
|
+
{ type: 'string', description: 'The name of a class of Angular Material or of a pipe of Angular, as DatePipe' }
|
|
214
|
+
]
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
template: { type: 'string', description: 'Angular: the template of the component, in every skin' },
|
|
218
|
+
styles: { type: 'string', description: 'Angular: the styles of the component' },
|
|
219
|
+
render: { type: 'string', description: 'Vanilla JS: the body of render(), which builds the DOM of the cell' },
|
|
220
|
+
members: { type: 'string', description: 'The members of the class: computed values, handlers' }
|
|
221
|
+
},
|
|
222
|
+
additionalProperties: false
|
|
223
|
+
};
|
|
224
|
+
const skinBodies = { type: 'object', additionalProperties: string };
|
|
225
|
+
/** The JSON Schema of BroSpecFillings, the parts of the code that a model writes, for the tools of the MCP server. */
|
|
226
|
+
export const fillingsSchema = {
|
|
227
|
+
title: 'BroSpecFillings',
|
|
228
|
+
description: 'The parts of the code that you write: the templates of the cells, the rules of the custom filters and the bodies of the functions of the skin config; get_docs, topic fillings',
|
|
229
|
+
type: 'object',
|
|
230
|
+
properties: {
|
|
231
|
+
cells: {
|
|
232
|
+
type: 'object',
|
|
233
|
+
description: 'The cells and the row details by their names, for each skin',
|
|
234
|
+
additionalProperties: { type: 'object', properties: { mat: cellFillingSchema, bs: cellFillingSchema, nv: cellFillingSchema }, additionalProperties: false }
|
|
235
|
+
},
|
|
236
|
+
filterRules: { type: 'object', description: 'The conditions of the filters with the match custom, by their names: the body of (row, value) => boolean', additionalProperties: string },
|
|
237
|
+
callbacks: {
|
|
238
|
+
type: 'object',
|
|
239
|
+
description: 'The bodies of the functions of the skin config, by the skin and the path, as components.sortHeader.afterRender',
|
|
240
|
+
properties: { mat: skinBodies, bs: skinBodies, nv: skinBodies },
|
|
241
|
+
additionalProperties: false
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
additionalProperties: false
|
|
245
|
+
};
|
|
246
|
+
/**
|
|
247
|
+
* The JSON Schema of the rows for the fields of a spec. A strict schema of a model has no object with free keys, so
|
|
248
|
+
* the site asks the model for the rows by this schema, after the spec: every value gets the type of its field.
|
|
249
|
+
*/
|
|
250
|
+
export function rowsSchema(fields) {
|
|
251
|
+
return {
|
|
252
|
+
type: 'object',
|
|
253
|
+
properties: {
|
|
254
|
+
rows: {
|
|
255
|
+
type: 'array',
|
|
256
|
+
items: {
|
|
257
|
+
type: 'object',
|
|
258
|
+
properties: Object.fromEntries(fields.map(field => [field.name, fieldSchema(field)])),
|
|
259
|
+
required: fields.map(field => field.name),
|
|
260
|
+
additionalProperties: false
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
required: ['rows'],
|
|
265
|
+
additionalProperties: false
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
function fieldSchema(field) {
|
|
269
|
+
const value = field.values ? { type: 'string', enum: field.values } : { type: 'string' };
|
|
270
|
+
switch (field.type) {
|
|
271
|
+
case 'string[]':
|
|
272
|
+
return { type: 'array', items: value };
|
|
273
|
+
case 'string':
|
|
274
|
+
return value;
|
|
275
|
+
default:
|
|
276
|
+
return { type: field.type };
|
|
277
|
+
}
|
|
278
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { BroSpecSkin } from './spec.js';
|
|
2
|
+
/**
|
|
3
|
+
* The values of BroConfig['css'] and BroConfig['components'] a spec may set for one skin, by the types of Table, Bro
|
|
4
|
+
* (types/table-bro.ts). The config of the application lies over a copy of the config of the skin, so it may change
|
|
5
|
+
* any of them before init, without a new build of the skin: nested objects are merged, arrays are replaced.
|
|
6
|
+
*/
|
|
7
|
+
export type BroSkinConfigShape = 'string' | 'boolean' | 'state' | {
|
|
8
|
+
[key: string]: BroSkinConfigShape;
|
|
9
|
+
};
|
|
10
|
+
export declare const skinConfigShape: {
|
|
11
|
+
css: BroSkinConfigShape;
|
|
12
|
+
components: BroSkinConfigShape;
|
|
13
|
+
};
|
|
14
|
+
/** The fields of the config that the spec gives in other places: the generator writes them from there. */
|
|
15
|
+
export declare const skinConfigElsewhere: Record<string, string>;
|
|
16
|
+
/**
|
|
17
|
+
* The contracts of the elements of a skin: a custom element in place of one of them follows its contract,
|
|
18
|
+
* a type of Table, Bro. The application defines the element, the generator does not write it.
|
|
19
|
+
*/
|
|
20
|
+
export declare const skinElementContracts: Record<string, string>;
|
|
21
|
+
export interface BroSkinCallback {
|
|
22
|
+
path: string;
|
|
23
|
+
signature: string;
|
|
24
|
+
/** The skins that call it: the elements of the mat skin are Angular components and call none of their own. */
|
|
25
|
+
skins: BroSpecSkin[];
|
|
26
|
+
description: string;
|
|
27
|
+
}
|
|
28
|
+
export declare const skinCallbacks: BroSkinCallback[];
|
|
29
|
+
/** Functions of the config that the config of a table cannot change, with the reason. */
|
|
30
|
+
export declare const skinCallbacksElsewhere: Record<string, string>;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
const className = { className: 'string' };
|
|
2
|
+
const states = { loading: 'state', 'no-data': 'state', 'not-found': 'state', fail: 'state' };
|
|
3
|
+
export const skinConfigShape = {
|
|
4
|
+
css: {
|
|
5
|
+
table: {
|
|
6
|
+
className: 'string',
|
|
7
|
+
thead: { className: 'string', tr: { className: 'string', th: className } },
|
|
8
|
+
tbody: { className: 'string', tr: { className: 'string', td: className } }
|
|
9
|
+
},
|
|
10
|
+
shadow: className
|
|
11
|
+
},
|
|
12
|
+
components: {
|
|
13
|
+
button: { selector: 'string', iconSelector: 'string' },
|
|
14
|
+
dropdown: { selector: 'string', css: { button: className } },
|
|
15
|
+
paginator: {
|
|
16
|
+
selector: 'string',
|
|
17
|
+
inputsAsProperties: 'boolean',
|
|
18
|
+
recreateOnReplaceRows: 'boolean',
|
|
19
|
+
css: { ul: { className: 'string', li: { className: 'string', a: className } } }
|
|
20
|
+
},
|
|
21
|
+
progressBar: { selector: 'string' },
|
|
22
|
+
sortHeader: { selector: 'string', titleAsContent: 'boolean', contentSelector: 'string' },
|
|
23
|
+
state: { fontIcon: 'boolean', lottie: 'boolean', states, statesDark: states },
|
|
24
|
+
switch: { selector: 'string', css: { div: { className: 'string', input: className } } },
|
|
25
|
+
textEllipsis: { selector: 'string' },
|
|
26
|
+
toolbar: { selector: 'string', css: { nav: { className: 'string', div: className } } },
|
|
27
|
+
toolbarMain: {
|
|
28
|
+
selector: 'string',
|
|
29
|
+
css: {
|
|
30
|
+
toolbarTitle: className,
|
|
31
|
+
navbarCollapse: { className: 'string', ul: { className: 'string', li: { className: 'string', a: className } } }
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
/** The fields of the config that the spec gives in other places: the generator writes them from there. */
|
|
37
|
+
export const skinConfigElsewhere = {
|
|
38
|
+
'components.toolbarMain.buttons': 'the buttons of the toolbar go into toolbar of the spec'
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* The contracts of the elements of a skin: a custom element in place of one of them follows its contract,
|
|
42
|
+
* a type of Table, Bro. The application defines the element, the generator does not write it.
|
|
43
|
+
*/
|
|
44
|
+
export const skinElementContracts = {
|
|
45
|
+
button: 'BroButton',
|
|
46
|
+
dropdown: 'BroDropdown',
|
|
47
|
+
paginator: 'BroPaginatorElement',
|
|
48
|
+
progressBar: 'BroProgressBar',
|
|
49
|
+
sortHeader: 'BroSortHeader',
|
|
50
|
+
textEllipsis: 'BroTextEllipsis',
|
|
51
|
+
toolbar: 'BroToolbarElement',
|
|
52
|
+
toolbarMain: 'BroToolbarMain'
|
|
53
|
+
};
|
|
54
|
+
export const skinCallbacks = [
|
|
55
|
+
{ path: 'components.button.beforeRender', signature: '(element: Element, value: string) => void', skins: ['mat', 'bs', 'nv'], description: 'before the details button of the core renders' },
|
|
56
|
+
{ path: 'components.sortHeader.beforeRender', signature: '(element: Element, value: string) => void', skins: ['mat', 'bs', 'nv'], description: 'before the header of a column renders' },
|
|
57
|
+
{ path: 'components.sortHeader.afterRender', signature: '(element: Element, value: string) => void | (() => void)', skins: ['bs', 'nv'], description: 'after the header of a column renders, for example to add a tooltip; a returned function cleans up' },
|
|
58
|
+
{ path: 'components.textEllipsis.afterRender', signature: '(element: Element, value: string) => void | (() => void)', skins: ['bs', 'nv'], description: 'after a cut value renders, for example to add a tooltip; a returned function cleans up' },
|
|
59
|
+
{ path: 'components.toolbarMain.beforeRender', signature: '(searchButton: Element, value: string) => void', skins: ['bs', 'nv'], description: 'before the search button of the toolbar renders; value is its word, texts.toolbarMain.search' },
|
|
60
|
+
{ path: 'components.toolbarSearch.beforeRender', signature: '(backButton: Element, clearButton: Element) => void', skins: ['mat', 'bs', 'nv'], description: 'before the buttons of the search line render' },
|
|
61
|
+
{ path: 'components.fontIcon.html', signature: '(iconName: string) => string', skins: ['mat', 'bs', 'nv'], description: 'the markup of a state icon with components.state.fontIcon' },
|
|
62
|
+
{ path: 'components.state.lottieHTML', signature: '(iconSrc: string) => string', skins: ['mat', 'bs', 'nv'], description: 'the markup of a state icon with components.state.lottie' }
|
|
63
|
+
];
|
|
64
|
+
/** Functions of the config that the config of a table cannot change, with the reason. */
|
|
65
|
+
export const skinCallbacksElsewhere = {
|
|
66
|
+
'components.filterDrawer.beforeRender': 'the Filter Drawer is outside of the table and takes it from the registered config of the skin, not from the config of the table'
|
|
67
|
+
};
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/** An identifier of JavaScript: the names of the fields, the cells and the filters, and a key of an object literal. */
|
|
2
|
+
export declare const specIdentifier: RegExp;
|
|
3
|
+
/**
|
|
4
|
+
* BroTableSpec: the table as data, without functions and without the tags of a skin. It repeats the names of BroCol and
|
|
5
|
+
* BroConfig of Table, Bro, so a model and a developer learn no second vocabulary. The generator writes the code of the
|
|
6
|
+
* table from it for a target and a skin, and the site renders it with the switch of the skins.
|
|
7
|
+
*/
|
|
8
|
+
export interface BroTableSpec {
|
|
9
|
+
/** The version of this format. */
|
|
10
|
+
specVersion: 1;
|
|
11
|
+
/** The name of the type of a row, as Order: the generator writes the type with it. */
|
|
12
|
+
rowType: string;
|
|
13
|
+
/** The fields of a row: the type of the row, the schema of the rows on the site, the checks of the columns. */
|
|
14
|
+
fields: BroSpecField[];
|
|
15
|
+
cols: BroSpecCol[];
|
|
16
|
+
/** The contracts of the custom cells and of the row details: what they show, read, and send. */
|
|
17
|
+
cells?: BroSpecCell[];
|
|
18
|
+
/** The filters of the Filter Drawer next to the table. */
|
|
19
|
+
filters?: BroSpecFilter[];
|
|
20
|
+
/** The rows of the spec; locally the generator writes the loading of the data without them. */
|
|
21
|
+
rows?: BroSpecRow[];
|
|
22
|
+
config?: BroSpecConfig;
|
|
23
|
+
/** The buttons and the menu of the toolbar of the table. */
|
|
24
|
+
toolbar?: BroSpecToolbar;
|
|
25
|
+
/** The messages of the states of the table; every skin keeps its own icon. */
|
|
26
|
+
stateMessages?: Partial<Record<BroSpecState, string>>;
|
|
27
|
+
/** The settings of the components of one skin, with the names of the fields of BroConfig. */
|
|
28
|
+
skinConfig?: Partial<Record<BroSpecSkin, BroSpecSkinConfig>>;
|
|
29
|
+
/** The CSS custom properties of the table, as --bro-row-height: 64px. */
|
|
30
|
+
cssVars?: Record<string, string>;
|
|
31
|
+
/** The GET endpoint that gives the rows; the source of every field is the path of its value in an item of the answer. */
|
|
32
|
+
api?: BroSpecApi;
|
|
33
|
+
}
|
|
34
|
+
export interface BroSpecApi {
|
|
35
|
+
/** The address of the endpoint, http or https. */
|
|
36
|
+
url: string;
|
|
37
|
+
/** The path of the array of the rows in the answer, as products or data.items; empty for an answer that is the array. */
|
|
38
|
+
rows: string;
|
|
39
|
+
/** An API that gives the rows page by page: the query parameters of the size of a page and of its offset or number. */
|
|
40
|
+
paging?: {
|
|
41
|
+
size: string;
|
|
42
|
+
offset?: string;
|
|
43
|
+
page?: string;
|
|
44
|
+
};
|
|
45
|
+
/** The path of the number of all rows in the answer of a page, as total: an API that gives pages has it. */
|
|
46
|
+
total?: string;
|
|
47
|
+
/** An API that gives pages also searches, sorts and filters: the query parameter of its text search, as search. */
|
|
48
|
+
search?: string;
|
|
49
|
+
/** The query parameters of the sort: of the field, and of the direction, asc or desc; without it a minus before the field sorts down. */
|
|
50
|
+
sort?: {
|
|
51
|
+
field: string;
|
|
52
|
+
order?: string;
|
|
53
|
+
};
|
|
54
|
+
/** The query parameter of every key of the filters, as {"newsSite": "news_site"}; a range has the keys <name>From and <name>To. */
|
|
55
|
+
filters?: Record<string, string>;
|
|
56
|
+
}
|
|
57
|
+
export type BroSpecSkin = 'mat' | 'bs' | 'nv';
|
|
58
|
+
export type BroSpecFieldType = 'string' | 'number' | 'boolean' | 'string[]';
|
|
59
|
+
export interface BroSpecField {
|
|
60
|
+
/** An identifier: it becomes a field of the type of the row. */
|
|
61
|
+
name: string;
|
|
62
|
+
type: BroSpecFieldType;
|
|
63
|
+
/** All values of a string field: the rows take only them, a select filter offers them, a cell knows every variant. */
|
|
64
|
+
values?: string[];
|
|
65
|
+
/** With an API: the path of the value in an item of its answer, as price or meta.createdAt. */
|
|
66
|
+
source?: string;
|
|
67
|
+
}
|
|
68
|
+
export interface BroSpecCol {
|
|
69
|
+
title: string;
|
|
70
|
+
/** The field of the row the column shows; a column of a custom cell may have none. */
|
|
71
|
+
name?: string;
|
|
72
|
+
/** The title for the narrowest width of the column; the default is the first word of the title. */
|
|
73
|
+
shortTitle?: string;
|
|
74
|
+
tooltip?: string;
|
|
75
|
+
dataType?: 'string' | 'number' | 'boolean';
|
|
76
|
+
sortKey?: string;
|
|
77
|
+
component?: BroSpecColComponent;
|
|
78
|
+
}
|
|
79
|
+
/** A custom cell by the name of its contract, or a ready element of the skins: its tag depends on the skin. */
|
|
80
|
+
export type BroSpecColComponent = {
|
|
81
|
+
cell: string;
|
|
82
|
+
} | {
|
|
83
|
+
element: BroSpecElement;
|
|
84
|
+
};
|
|
85
|
+
export type BroSpecElement = 'tags' | 'switch' | 'details-button';
|
|
86
|
+
export interface BroSpecCell {
|
|
87
|
+
/** In kebab-case: a part of the tag, the class, and the file of the component. */
|
|
88
|
+
name: string;
|
|
89
|
+
/** A cell of a column, or the element of the row details named by config.rowDetailsComponent. */
|
|
90
|
+
kind?: 'cell' | 'details';
|
|
91
|
+
/** What the cell shows, in words: the task for its template. */
|
|
92
|
+
shows: string;
|
|
93
|
+
/** The fields of the row the cell reads. */
|
|
94
|
+
fields: string[];
|
|
95
|
+
/** The actions the cell sends: the page tells them by event.action. */
|
|
96
|
+
actions?: string[];
|
|
97
|
+
}
|
|
98
|
+
export type BroSpecFilterControl = 'text' | 'select' | 'range' | 'checkbox';
|
|
99
|
+
export type BroSpecFilterMatch = 'contains' | 'startsWith' | 'eq' | 'custom';
|
|
100
|
+
export interface BroSpecFilter {
|
|
101
|
+
/** The key in the object of the filters; a range has the keys <name>From and <name>To. */
|
|
102
|
+
name: string;
|
|
103
|
+
label: string;
|
|
104
|
+
control: BroSpecFilterControl;
|
|
105
|
+
/** The field of the row the filter compares; a custom rule may read other fields. */
|
|
106
|
+
field?: string;
|
|
107
|
+
/** How the value matches the field; a range compares with gte and lte. */
|
|
108
|
+
match?: BroSpecFilterMatch;
|
|
109
|
+
/** The rule of a custom match in words: the model writes the condition for one row. */
|
|
110
|
+
rule?: string;
|
|
111
|
+
}
|
|
112
|
+
export type BroSpecRow = Record<string, string | number | boolean | string[] | null>;
|
|
113
|
+
export interface BroSpecConfig {
|
|
114
|
+
toolbarTitle?: string;
|
|
115
|
+
pageSize?: number;
|
|
116
|
+
server?: boolean;
|
|
117
|
+
rowCounter?: boolean;
|
|
118
|
+
shadowsEnabled?: boolean;
|
|
119
|
+
theme?: 'light' | 'dark' | 'auto';
|
|
120
|
+
/** The custom element of the row details: a cell of the kind details. */
|
|
121
|
+
rowDetailsComponent?: {
|
|
122
|
+
cell: string;
|
|
123
|
+
};
|
|
124
|
+
rowDetailsServer?: boolean;
|
|
125
|
+
/** The motion of the row details: kinetic by default, as the pages move; eased opens them in --bro-details-duration. */
|
|
126
|
+
rowDetailsMotion?: 'kinetic' | 'eased';
|
|
127
|
+
}
|
|
128
|
+
export interface BroSpecToolbar {
|
|
129
|
+
buttons?: BroSpecToolbarButton[];
|
|
130
|
+
/** One menu: the toolbar of the mat skin shows one. */
|
|
131
|
+
menu?: {
|
|
132
|
+
title: string;
|
|
133
|
+
items: BroSpecToolbarButton[];
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
export interface BroSpecToolbarButton {
|
|
137
|
+
title: string;
|
|
138
|
+
/** The action of the bro-action event on a click. */
|
|
139
|
+
action: string;
|
|
140
|
+
/** The name of a Material icon: a button of the toolbar of the mat skin is an icon. */
|
|
141
|
+
icon?: string;
|
|
142
|
+
}
|
|
143
|
+
export type BroSpecState = 'loading' | 'no-data' | 'not-found' | 'fail';
|
|
144
|
+
export interface BroSpecSkinConfig {
|
|
145
|
+
/** Values of BroConfig['css']. */
|
|
146
|
+
css?: Record<string, unknown>;
|
|
147
|
+
/** Values of BroConfig['components'], without functions. */
|
|
148
|
+
components?: Record<string, unknown>;
|
|
149
|
+
/** The functions of the skin config: the model writes their bodies. */
|
|
150
|
+
callbacks?: BroSpecCallback[];
|
|
151
|
+
}
|
|
152
|
+
export interface BroSpecCallback {
|
|
153
|
+
/** The path of the function in the config, as components.sortHeader.afterRender. */
|
|
154
|
+
path: string;
|
|
155
|
+
/** What the function does, in words. */
|
|
156
|
+
does: string;
|
|
157
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { BroMcpExtension } from '../extension.js';
|
|
2
|
+
import { type BroSpecSkin } from './spec.js';
|
|
3
|
+
export interface BroSpecIssue {
|
|
4
|
+
/** The path of the field in the spec, as cols[3].component.cell; empty for the spec itself. */
|
|
5
|
+
path: string;
|
|
6
|
+
/** What is wrong. */
|
|
7
|
+
message: string;
|
|
8
|
+
/** How it should be, when it is known. */
|
|
9
|
+
fix?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface BroSpecReport {
|
|
12
|
+
valid: boolean;
|
|
13
|
+
errors: BroSpecIssue[];
|
|
14
|
+
warnings: BroSpecIssue[];
|
|
15
|
+
/** The issues after the first 100 errors and the first 100 warnings, which the report leaves out. */
|
|
16
|
+
omitted?: {
|
|
17
|
+
errors?: number;
|
|
18
|
+
warnings?: number;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/** The sizes that a host of the generator renders: a strict JSON Schema of a model checks no sizes. */
|
|
22
|
+
export interface BroSpecLimits {
|
|
23
|
+
cols?: number;
|
|
24
|
+
rows?: number;
|
|
25
|
+
cells?: number;
|
|
26
|
+
filters?: number;
|
|
27
|
+
/** The length of a string value of a row. */
|
|
28
|
+
valueLength?: number;
|
|
29
|
+
}
|
|
30
|
+
export interface BroValidateOptions {
|
|
31
|
+
/** The skin of the project; without it the spec is checked for the three skins. */
|
|
32
|
+
skin?: BroSpecSkin;
|
|
33
|
+
/** A host that renders the table of the spec, as a preview, requires its rows. */
|
|
34
|
+
rowsRequired?: boolean;
|
|
35
|
+
limits?: BroSpecLimits;
|
|
36
|
+
/** The paid modules of the project: their fields of the config are known. */
|
|
37
|
+
extensions?: BroMcpExtension[];
|
|
38
|
+
}
|
|
39
|
+
export declare class BroSpecIssues {
|
|
40
|
+
readonly errors: BroSpecIssue[];
|
|
41
|
+
readonly warnings: BroSpecIssue[];
|
|
42
|
+
error(path: string, message: string, fix?: string): void;
|
|
43
|
+
warning(path: string, message: string, fix?: string): void;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Every table has row details by default: validate_spec and generate_code warn about a table without them, as a request
|
|
47
|
+
* may ask for such a table.
|
|
48
|
+
*/
|
|
49
|
+
export declare function rowDetailsByDefault(spec: unknown): BroSpecIssue[];
|
|
50
|
+
/**
|
|
51
|
+
* Checks a table spec and tells for every problem where it is, what is wrong and how it should be. The site runs it
|
|
52
|
+
* on every answer of the model, the MCP server before the generator.
|
|
53
|
+
*/
|
|
54
|
+
export declare function validateSpec(spec: unknown, options?: BroValidateOptions): BroSpecReport;
|