@mxtommy/kip 4.4.0 → 4.5.0-beta.1
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/.github/copilot-instructions.md +3 -0
- package/.github/instructions/best-practices.instructions.md +4 -0
- package/.github/instructions/project.instructions.md +6 -5
- package/package.json +1 -1
- package/plugin/index.js +128 -68
- package/plugin/openApi.json +8 -20
- package/public/chunk-2OB7ZJBR.js +3 -0
- package/public/{chunk-PSF2OKKT.js → chunk-5FEX27I4.js} +1 -1
- package/public/{chunk-MMIOUKLI.js → chunk-6GGJZDRE.js} +1 -1
- package/public/{chunk-XEJJOWK6.js → chunk-6V4GGGXE.js} +1 -1
- package/public/{chunk-7HLFWAA7.js → chunk-A5BW6BUM.js} +1 -1
- package/public/{chunk-IWK4FHBL.js → chunk-DGE5YFPU.js} +1 -1
- package/public/{chunk-3BGR52TW.js → chunk-G6M3Z3BY.js} +6 -6
- package/public/{chunk-5DLSQ773.js → chunk-GMGZLXY7.js} +1 -1
- package/public/{chunk-PESXPDBT.js → chunk-GUZ3BDVZ.js} +1 -1
- package/public/{chunk-BNIQFWQ6.js → chunk-HMOOTAEA.js} +1 -1
- package/public/{chunk-J4IGUIZA.js → chunk-ICDGHQFP.js} +2 -2
- package/public/{chunk-PDYVZHOK.js → chunk-IXQ7KIFY.js} +1 -1
- package/public/{chunk-TGGJAGV7.js → chunk-JCNE4QHQ.js} +12 -12
- package/public/chunk-K6XYUNG4.js +8 -0
- package/public/chunk-KFFAA7DL.js +10 -0
- package/public/{chunk-VH4ZIU4T.js → chunk-LGCQEN7V.js} +1 -1
- package/public/{chunk-UVAQADRE.js → chunk-M2B5OYGO.js} +1 -1
- package/public/{chunk-557F3J5T.js → chunk-O3JH7UTR.js} +1 -1
- package/public/{chunk-2KMYPGX4.js → chunk-Q3USFT4F.js} +1 -1
- package/public/{chunk-TKC7ROZ7.js → chunk-QVCLOCEC.js} +1 -1
- package/public/chunk-QZKCRH3H.js +1 -0
- package/public/{chunk-HJQQWPGC.js → chunk-T6TFVZVM.js} +1 -1
- package/public/{chunk-PKATAZA2.js → chunk-VIKU7BH7.js} +1 -1
- package/public/chunk-XMQPXXLW.js +8 -0
- package/public/{chunk-PGELIHBX.js → chunk-YIYYVDFO.js} +1 -1
- package/public/{chunk-KIR67PZ2.js → chunk-ZQER6AIQ.js} +1 -1
- package/public/index.html +1 -1
- package/public/main-4URMGBQS.js +1 -0
- package/public/chunk-2MWBAYPJ.js +0 -8
- package/public/chunk-4IHRH3BQ.js +0 -9
- package/public/chunk-JP7ZAJ6C.js +0 -3
- package/public/chunk-KKJXPB75.js +0 -8
- package/public/main-I7M3MAJT.js +0 -1
|
@@ -132,6 +132,7 @@ Template:
|
|
|
132
132
|
- CommonJS deps are explicitly allowed (js-quantities). Avoid introducing new CJS without adding to allowedCommonJsDependencies.
|
|
133
133
|
- Use standalone components, signals, @if/@for; follow .github/instructions/angular.instructions.md for style.
|
|
134
134
|
- Widget config UIs live under src/app/widget-config; path controls use custom validators (no Validators.required). Respect isPathConfigurable and pathRequired.
|
|
135
|
+
- Documentation standard: Every public property and public method in TypeScript code MUST include full JSDoc with: purpose, parameters, return value, and at least one usage example. Apply this by default for all generated/edited code unless a file explicitly cannot use comments.
|
|
135
136
|
|
|
136
137
|
## Widgets: do this, not that (Host2)
|
|
137
138
|
- Do: Provide a complete `DEFAULT_CONFIG` with all paths & options. Don’t: Scatter defaults across lifecycle hooks.
|
|
@@ -143,10 +144,12 @@ Template:
|
|
|
143
144
|
|
|
144
145
|
## Key files/dirs
|
|
145
146
|
- Core services: `src/app/core/services/` (DataService, SignalKConnectionService, SignalKDeltaService, AppNetworkInitService, UnitsService, DataSetService, NotificationsService)
|
|
147
|
+
- Plugin config foundation: `src/app/core/services/signalk-plugin-config.service.ts` (plugin-only detection, dependency validation, schema normalization metadata, and config persistence via `/plugins` endpoints)
|
|
146
148
|
- Directives: `src/app/core/directives/` (widget-runtime, widget-streams, widget-metadata)
|
|
147
149
|
- Widgets: `src/app/widgets/` (e.g., widget-numeric, widget-gauge-ng-*, widget-data-chart, widget-windtrends-chart, widget-autopilot)
|
|
148
150
|
- Embedded host: `src/app/core/components/widget-embedded/`
|
|
149
151
|
- Config UI: `src/app/widget-config/`
|
|
152
|
+
- Plugin management (server plugins) is handled separately through `SignalkPluginConfigService` and `/plugins` REST endpoints. Keep install/uninstall out of scope unless explicitly added.
|
|
150
153
|
- Build: `angular.json`, `package.json` scripts
|
|
151
154
|
|
|
152
155
|
## Debugging
|
|
@@ -53,3 +53,7 @@ You are an expert in TypeScript, Angular, and scalable web application developme
|
|
|
53
53
|
- Design services around a single responsibility
|
|
54
54
|
- Use the `providedIn: 'root'` option for singleton services
|
|
55
55
|
- Use the `inject()` function instead of constructor injection
|
|
56
|
+
|
|
57
|
+
## Documentation
|
|
58
|
+
|
|
59
|
+
- Every public TypeScript property and public method MUST include full JSDoc with: purpose, parameters, return value, and at least one usage example.
|
|
@@ -53,6 +53,7 @@ KIP Instrument MFD is an advanced and versatile marine instrumentation package d
|
|
|
53
53
|
## 6. Documentation & Comments
|
|
54
54
|
- **Document all custom validators and business rules.**
|
|
55
55
|
- **Update this file and the README with any major changes or new patterns.**
|
|
56
|
+
- **JSDoc requirement:** Every public TypeScript property and public method must include full JSDoc containing: purpose, parameters, return value, and at least one usage example.
|
|
56
57
|
|
|
57
58
|
---
|
|
58
59
|
|
|
@@ -136,11 +137,11 @@ All major services in `src/app/core/services/` are summarized below for Copilot
|
|
|
136
137
|
- Key methods: Data set CRUD, data source updates.
|
|
137
138
|
- Dependencies: DataService, StorageService.
|
|
138
139
|
|
|
139
|
-
- **
|
|
140
|
-
- Purpose:
|
|
141
|
-
- Key methods:
|
|
142
|
-
- Dependencies:
|
|
143
|
-
- Usage:
|
|
140
|
+
- **SignalkPluginConfigService (`signalk-plugin-config.service.ts`)**
|
|
141
|
+
- Purpose: Plugin configuration foundation service for dependency checks and plugin state/config persistence via Signal K `/plugins` endpoints.
|
|
142
|
+
- Key methods: `listPlugins()`, `getPlugin()`, `getPluginConfig()`, `savePluginConfig()`, `setPluginEnabled()`, `validateDependency()`, `normalizePluginSchema()`.
|
|
143
|
+
- Dependencies: HttpClient, SignalKConnectionService.
|
|
144
|
+
- Usage: Source of truth for plugin detection and config save flows; no plugin install/uninstall support.
|
|
144
145
|
|
|
145
146
|
- **SignalKRequestsService (`signalk-requests.service.ts`)**
|
|
146
147
|
- Purpose: Handles requests to the Signal K server, such as PUT/POST operations and custom actions.
|
package/package.json
CHANGED
package/plugin/index.js
CHANGED
|
@@ -36,11 +36,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
const server_api_1 = require("@signalk/server-api");
|
|
37
37
|
const openapi = __importStar(require("./openApi.json"));
|
|
38
38
|
const start = (server) => {
|
|
39
|
+
const mutableOpenApi = JSON.parse(JSON.stringify(openapi.default ?? openapi));
|
|
39
40
|
const API_PATHS = {
|
|
40
41
|
DISPLAYS: `/displays`,
|
|
41
42
|
INSTANCE: `/displays/:displayId`,
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
SCREEN_INDEX: `/displays/:displayId/screenIndex`,
|
|
44
|
+
ACTIVATE_SCREEN: `/displays/:displayId/activeScreen`
|
|
45
|
+
};
|
|
46
|
+
const PUT_CONTEXT = 'vessels.self';
|
|
47
|
+
const COMMAND_PATHS = {
|
|
48
|
+
SET_DISPLAY: 'kip.remote.setDisplay',
|
|
49
|
+
SET_SCREEN_INDEX: 'kip.remote.setScreenIndex',
|
|
50
|
+
REQUEST_ACTIVE_SCREEN: 'kip.remote.requestActiveScreen'
|
|
44
51
|
};
|
|
45
52
|
const CONFIG_SCHEMA = {
|
|
46
53
|
properties: {
|
|
@@ -64,11 +71,6 @@ const start = (server) => {
|
|
|
64
71
|
server.debug(`getAvailableDisplays: fullPath=${JSON.stringify(fullPath)}`);
|
|
65
72
|
return typeof fullPath === 'object' && fullPath !== null ? fullPath : undefined;
|
|
66
73
|
}
|
|
67
|
-
function pathToDotNotation(path) {
|
|
68
|
-
const dottedPath = path.replace(/\//g, '.').replace(/^\./, '');
|
|
69
|
-
server.debug(`pathToDotNotation: input path=${path}, dottedPath=${dottedPath}`);
|
|
70
|
-
return dottedPath;
|
|
71
|
-
}
|
|
72
74
|
function sendOk(res, body) {
|
|
73
75
|
if (body === undefined)
|
|
74
76
|
return res.status(204).end();
|
|
@@ -77,12 +79,91 @@ const start = (server) => {
|
|
|
77
79
|
function sendFail(res, statusCode, message) {
|
|
78
80
|
return res.status(statusCode).json({ state: 'FAILED', statusCode, message });
|
|
79
81
|
}
|
|
82
|
+
function completed(statusCode, message) {
|
|
83
|
+
return { state: 'COMPLETED', statusCode, message };
|
|
84
|
+
}
|
|
85
|
+
function isValidDisplayId(displayId) {
|
|
86
|
+
return typeof displayId === 'string' && /^[A-Za-z0-9-]+$/.test(displayId);
|
|
87
|
+
}
|
|
88
|
+
function applyDisplayWrite(displayId, suffix, value) {
|
|
89
|
+
const path = suffix ? `displays.${displayId}.${suffix}` : `displays.${displayId}`;
|
|
90
|
+
try {
|
|
91
|
+
server.handleMessage(plugin.id, {
|
|
92
|
+
updates: [
|
|
93
|
+
{
|
|
94
|
+
values: [
|
|
95
|
+
{
|
|
96
|
+
path: path,
|
|
97
|
+
value: value ?? null
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
}
|
|
101
|
+
]
|
|
102
|
+
}, server_api_1.SKVersion.v1);
|
|
103
|
+
return completed(200);
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
const message = error?.message ?? 'Unable to write display path';
|
|
107
|
+
return completed(400, message);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function handleSetDisplay(value) {
|
|
111
|
+
const command = value;
|
|
112
|
+
if (!command || typeof command !== 'object') {
|
|
113
|
+
return completed(400, 'Command payload is required');
|
|
114
|
+
}
|
|
115
|
+
if (!isValidDisplayId(command.displayId)) {
|
|
116
|
+
return completed(400, 'Invalid displayId format');
|
|
117
|
+
}
|
|
118
|
+
const displayValue = command.display ?? null;
|
|
119
|
+
if (displayValue !== null && typeof displayValue !== 'object') {
|
|
120
|
+
return completed(400, 'display must be an object or null');
|
|
121
|
+
}
|
|
122
|
+
return applyDisplayWrite(command.displayId, null, displayValue);
|
|
123
|
+
}
|
|
124
|
+
function handleScreenWrite(value, suffix) {
|
|
125
|
+
const command = value;
|
|
126
|
+
if (!command || typeof command !== 'object') {
|
|
127
|
+
return completed(400, 'Command payload is required');
|
|
128
|
+
}
|
|
129
|
+
if (!isValidDisplayId(command.displayId)) {
|
|
130
|
+
return completed(400, 'Invalid displayId format');
|
|
131
|
+
}
|
|
132
|
+
const screenIdxValue = command.screenIdx ?? null;
|
|
133
|
+
if (screenIdxValue !== null && typeof screenIdxValue !== 'number') {
|
|
134
|
+
return completed(400, 'screenIdx must be a number or null');
|
|
135
|
+
}
|
|
136
|
+
return applyDisplayWrite(command.displayId, suffix, screenIdxValue);
|
|
137
|
+
}
|
|
138
|
+
function sendActionAsRest(res, result) {
|
|
139
|
+
if (result.statusCode === 200) {
|
|
140
|
+
return res.status(200).json({ state: 'SUCCESS', statusCode: 200 });
|
|
141
|
+
}
|
|
142
|
+
return sendFail(res, result.statusCode || 400, result.message || 'Command failed');
|
|
143
|
+
}
|
|
80
144
|
const plugin = {
|
|
81
145
|
id: 'kip',
|
|
82
146
|
name: 'KIP',
|
|
83
147
|
description: 'KIP server plugin',
|
|
84
148
|
start: (settings) => {
|
|
85
149
|
server.debug(`Starting plugin with settings: ${JSON.stringify(settings)}`);
|
|
150
|
+
if (server.registerPutHandler) {
|
|
151
|
+
server.registerPutHandler(PUT_CONTEXT, COMMAND_PATHS.SET_DISPLAY, (context, path, value) => {
|
|
152
|
+
void context;
|
|
153
|
+
void path;
|
|
154
|
+
return handleSetDisplay(value);
|
|
155
|
+
}, plugin.id);
|
|
156
|
+
server.registerPutHandler(PUT_CONTEXT, COMMAND_PATHS.SET_SCREEN_INDEX, (context, path, value) => {
|
|
157
|
+
void context;
|
|
158
|
+
void path;
|
|
159
|
+
return handleScreenWrite(value, 'screenIndex');
|
|
160
|
+
}, plugin.id);
|
|
161
|
+
server.registerPutHandler(PUT_CONTEXT, COMMAND_PATHS.REQUEST_ACTIVE_SCREEN, (context, path, value) => {
|
|
162
|
+
void context;
|
|
163
|
+
void path;
|
|
164
|
+
return handleScreenWrite(value, 'activeScreen');
|
|
165
|
+
}, plugin.id);
|
|
166
|
+
}
|
|
86
167
|
server.setPluginStatus(`Starting...`);
|
|
87
168
|
},
|
|
88
169
|
stop: () => {
|
|
@@ -92,7 +173,7 @@ const start = (server) => {
|
|
|
92
173
|
},
|
|
93
174
|
schema: () => CONFIG_SCHEMA,
|
|
94
175
|
registerWithRouter(router) {
|
|
95
|
-
server.debug(`Registering plugin routes: ${API_PATHS.DISPLAYS}, ${API_PATHS.INSTANCE}, ${API_PATHS.
|
|
176
|
+
server.debug(`Registering plugin routes: ${API_PATHS.DISPLAYS}, ${API_PATHS.INSTANCE}, ${API_PATHS.SCREEN_INDEX}, ${API_PATHS.ACTIVATE_SCREEN}`);
|
|
96
177
|
// Validate/normalize :displayId where present
|
|
97
178
|
router.param('displayId', (req, res, next, displayId) => {
|
|
98
179
|
if (displayId == null)
|
|
@@ -135,21 +216,12 @@ const start = (server) => {
|
|
|
135
216
|
router.put(`${API_PATHS.INSTANCE}`, async (req, res) => {
|
|
136
217
|
server.debug(`** PUT ${API_PATHS.INSTANCE}. Params: ${JSON.stringify(req.params)} Body: ${JSON.stringify(req.body)}`);
|
|
137
218
|
try {
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
{
|
|
145
|
-
path: dottedPath,
|
|
146
|
-
value: req.body ?? null
|
|
147
|
-
}
|
|
148
|
-
]
|
|
149
|
-
}
|
|
150
|
-
]
|
|
151
|
-
}, server_api_1.SKVersion.v1);
|
|
152
|
-
return res.status(200).json({ state: 'SUCCESS', statusCode: 200 });
|
|
219
|
+
const displayId = req.displayId;
|
|
220
|
+
if (!displayId) {
|
|
221
|
+
return sendFail(res, 400, 'Missing displayId parameter');
|
|
222
|
+
}
|
|
223
|
+
const result = handleSetDisplay({ displayId, display: req.body ?? null });
|
|
224
|
+
return sendActionAsRest(res, result);
|
|
153
225
|
}
|
|
154
226
|
catch (error) {
|
|
155
227
|
const msg = `HandleMessage failed with errors!`;
|
|
@@ -158,24 +230,18 @@ const start = (server) => {
|
|
|
158
230
|
return sendFail(res, 400, error.message);
|
|
159
231
|
}
|
|
160
232
|
});
|
|
161
|
-
router.put(`${API_PATHS.
|
|
162
|
-
server.debug(`** PUT ${API_PATHS.
|
|
233
|
+
router.put(`${API_PATHS.SCREEN_INDEX}`, async (req, res) => {
|
|
234
|
+
server.debug(`** PUT ${API_PATHS.SCREEN_INDEX}. Params: ${JSON.stringify(req.params)} Body: ${JSON.stringify(req.body)}`);
|
|
163
235
|
try {
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
174
|
-
]
|
|
175
|
-
}
|
|
176
|
-
]
|
|
177
|
-
}, server_api_1.SKVersion.v1);
|
|
178
|
-
return res.status(200).json({ state: 'SUCCESS', statusCode: 200 });
|
|
236
|
+
const displayId = req.displayId;
|
|
237
|
+
if (!displayId) {
|
|
238
|
+
return sendFail(res, 400, 'Missing displayId parameter');
|
|
239
|
+
}
|
|
240
|
+
const result = handleScreenWrite({
|
|
241
|
+
displayId,
|
|
242
|
+
screenIdx: req.body?.screenIdx !== undefined ? req.body.screenIdx : null
|
|
243
|
+
}, 'screenIndex');
|
|
244
|
+
return sendActionAsRest(res, result);
|
|
179
245
|
}
|
|
180
246
|
catch (error) {
|
|
181
247
|
const msg = `HandleMessage failed with errors!`;
|
|
@@ -184,24 +250,18 @@ const start = (server) => {
|
|
|
184
250
|
return sendFail(res, 400, error.message);
|
|
185
251
|
}
|
|
186
252
|
});
|
|
187
|
-
router.put(`${API_PATHS.
|
|
188
|
-
server.debug(`** PUT ${API_PATHS.
|
|
253
|
+
router.put(`${API_PATHS.ACTIVATE_SCREEN}`, async (req, res) => {
|
|
254
|
+
server.debug(`** PUT ${API_PATHS.ACTIVATE_SCREEN}. Params: ${JSON.stringify(req.params)} Body: ${JSON.stringify(req.body)}`);
|
|
189
255
|
try {
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}
|
|
200
|
-
]
|
|
201
|
-
}
|
|
202
|
-
]
|
|
203
|
-
}, server_api_1.SKVersion.v1);
|
|
204
|
-
return res.status(200).json({ state: 'SUCCESS', statusCode: 200 });
|
|
256
|
+
const displayId = req.displayId;
|
|
257
|
+
if (!displayId) {
|
|
258
|
+
return sendFail(res, 400, 'Missing displayId parameter');
|
|
259
|
+
}
|
|
260
|
+
const result = handleScreenWrite({
|
|
261
|
+
displayId,
|
|
262
|
+
screenIdx: req.body?.screenIdx !== undefined ? req.body.screenIdx : null
|
|
263
|
+
}, 'activeScreen');
|
|
264
|
+
return sendActionAsRest(res, result);
|
|
205
265
|
}
|
|
206
266
|
catch (error) {
|
|
207
267
|
const msg = `HandleMessage failed with errors!`;
|
|
@@ -252,8 +312,8 @@ const start = (server) => {
|
|
|
252
312
|
return sendFail(res, 400, error.message);
|
|
253
313
|
}
|
|
254
314
|
});
|
|
255
|
-
router.get(`${API_PATHS.
|
|
256
|
-
server.debug(`*** GET
|
|
315
|
+
router.get(`${API_PATHS.SCREEN_INDEX}`, (req, res) => {
|
|
316
|
+
server.debug(`*** GET SCREEN_INDEX ${API_PATHS.SCREEN_INDEX}. Params: ${JSON.stringify(req.params)}`);
|
|
257
317
|
try {
|
|
258
318
|
const displayId = req.displayId;
|
|
259
319
|
if (!displayId) {
|
|
@@ -272,23 +332,23 @@ const start = (server) => {
|
|
|
272
332
|
return sendFail(res, 400, error.message);
|
|
273
333
|
}
|
|
274
334
|
});
|
|
275
|
-
router.get(`${API_PATHS.
|
|
276
|
-
server.debug(`*** GET
|
|
335
|
+
router.get(`${API_PATHS.ACTIVATE_SCREEN}`, (req, res) => {
|
|
336
|
+
server.debug(`*** GET ACTIVATE_SCREEN ${API_PATHS.ACTIVATE_SCREEN}. Params: ${JSON.stringify(req.params)}`);
|
|
277
337
|
try {
|
|
278
|
-
const
|
|
279
|
-
if (!
|
|
280
|
-
return sendFail(res, 400, 'Missing
|
|
338
|
+
const displayId = req.displayId;
|
|
339
|
+
if (!displayId) {
|
|
340
|
+
return sendFail(res, 400, 'Missing displayId parameter');
|
|
281
341
|
}
|
|
282
|
-
const node = getDisplaySelfPath(
|
|
342
|
+
const node = getDisplaySelfPath(displayId, 'activeScreen');
|
|
283
343
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
284
344
|
const idx = node?.value ?? null;
|
|
285
345
|
if (idx === undefined) {
|
|
286
|
-
return sendFail(res, 404, `Change display screen Id ${
|
|
346
|
+
return sendFail(res, 404, `Change display screen Id ${displayId} not found in path`);
|
|
287
347
|
}
|
|
288
348
|
return sendOk(res, idx);
|
|
289
349
|
}
|
|
290
350
|
catch (error) {
|
|
291
|
-
server.error(`Error reading activeScreen for ${req.params?.
|
|
351
|
+
server.error(`Error reading activeScreen for ${req.params?.displayId}: ${String(error.message || error)}`);
|
|
292
352
|
return sendFail(res, 400, error.message);
|
|
293
353
|
}
|
|
294
354
|
});
|
|
@@ -302,7 +362,7 @@ const start = (server) => {
|
|
|
302
362
|
}
|
|
303
363
|
server.setPluginStatus(`Providing remote display screen control`);
|
|
304
364
|
},
|
|
305
|
-
getOpenApi: () =>
|
|
365
|
+
getOpenApi: () => mutableOpenApi
|
|
306
366
|
};
|
|
307
367
|
return plugin;
|
|
308
368
|
};
|
package/plugin/openApi.json
CHANGED
|
@@ -63,17 +63,11 @@
|
|
|
63
63
|
]
|
|
64
64
|
},
|
|
65
65
|
"ScreenListOrNull": {
|
|
66
|
-
"
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
"type": "null"
|
|
75
|
-
}
|
|
76
|
-
]
|
|
66
|
+
"type": "array",
|
|
67
|
+
"nullable": true,
|
|
68
|
+
"items": {
|
|
69
|
+
"$ref": "#/components/schemas/ScreenItem"
|
|
70
|
+
}
|
|
77
71
|
},
|
|
78
72
|
"SuccessResponse": {
|
|
79
73
|
"type": "object",
|
|
@@ -129,15 +123,9 @@
|
|
|
129
123
|
}
|
|
130
124
|
},
|
|
131
125
|
"AnyObjectOrNull": {
|
|
132
|
-
"
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
"additionalProperties": true
|
|
136
|
-
},
|
|
137
|
-
{
|
|
138
|
-
"type": "null"
|
|
139
|
-
}
|
|
140
|
-
]
|
|
126
|
+
"type": "object",
|
|
127
|
+
"nullable": true,
|
|
128
|
+
"additionalProperties": true
|
|
141
129
|
}
|
|
142
130
|
},
|
|
143
131
|
"parameters": {
|