@emeryld/rrroutes-contract 2.2.3 → 2.2.5

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/dist/index.cjs CHANGED
@@ -562,6 +562,21 @@ body {
562
562
  box-shadow: 0 10px 30px -10px rgba(0,0,0,0.5);
563
563
  }
564
564
 
565
+ .schema-indent {
566
+ display: inline-block;
567
+ }
568
+
569
+ .schema-branch {
570
+ opacity: 0.6;
571
+ font-family: var(--font-mono);
572
+ margin-right: 2px;
573
+ }
574
+
575
+ .schema-meta code {
576
+ font-family: var(--font-mono);
577
+ font-size: 11px;
578
+ }
579
+
565
580
  /* Top Row: Filters */
566
581
  .filters-row {
567
582
  display: flex;
@@ -653,6 +668,15 @@ body {
653
668
  font-weight: 700;
654
669
  margin-right: 4px;
655
670
  }
671
+ .schema-indent {
672
+ display: inline-block;
673
+ }
674
+
675
+ .schema-branch {
676
+ opacity: 0.6;
677
+ font-family: var(--font-mono);
678
+ margin-right: 2px;
679
+ }
656
680
 
657
681
  /* Chips/Pills */
658
682
  .pill-checkbox { cursor: pointer; user-select: none; }
@@ -1187,30 +1211,209 @@ var DOCS_JS = `
1187
1211
  );
1188
1212
  }
1189
1213
 
1190
- function renderSchemaTable(node, title) {
1191
- let rows = '';
1192
- if (node.kind === 'object' && node.properties) {
1193
- Object.keys(node.properties).forEach(function(key) {
1194
- const prop = node.properties[key];
1195
- const reqClass = prop.optional ? 'req-false' : 'req-true';
1196
- const reqText = prop.optional ? 'OPT' : 'REQ';
1197
- rows +=
1198
- '<tr>' +
1199
- '<td class="col-name">' + escapeHtml(key) + '</td>' +
1200
- '<td class="col-type">' + escapeHtml(getTypeLabel(prop)) + '</td>' +
1201
- '<td><span class="req-badge ' + reqClass + '">' + reqText + '</span></td>' +
1202
- '<td>' + escapeHtml(prop.description || '') + '</td>' +
1203
- '</tr>';
1204
- });
1205
- } else {
1206
- rows = '<tr><td colspan="4">Type: ' + escapeHtml(getTypeLabel(node)) + '</td></tr>';
1214
+ // Recursive schema renderer with proper depth-based indentation.
1215
+
1216
+ function renderSchemaTable(node, title) {
1217
+ let rows = '';
1218
+
1219
+ if (node.kind === 'object' && node.properties) {
1220
+ // Start at depth -1 so first level of properties shows at depth 0
1221
+ rows = renderObjectChildren(node, -1);
1222
+ } else {
1223
+ rows = renderNodeRow('(root)', node, 0);
1224
+ }
1225
+
1226
+ return (
1227
+ (title
1228
+ ? '<div class="schema-subtitle">' + escapeHtml(title) + '</div>'
1229
+ : '') +
1230
+ '<table class="schema-table">' +
1231
+ rows +
1232
+ '</table>'
1233
+ );
1234
+ }
1235
+
1236
+ function renderObjectChildren(node, depth) {
1237
+ if (!node.properties) return '';
1238
+
1239
+ let rows = '';
1240
+ Object.keys(node.properties).forEach(function (key) {
1241
+ rows += renderNodeRow(key, node.properties[key], depth + 1);
1242
+ });
1243
+ return rows;
1244
+ }
1245
+
1246
+ function renderNodeRow(name, node, depth) {
1247
+ const reqClass = node.optional ? 'req-false' : 'req-true';
1248
+ const reqText = node.optional ? 'OPT' : 'REQ';
1249
+
1250
+ const indentPx = depth * 16; // increase this if you want more spacing per level
1251
+ const nameCell =
1252
+ '<span class="schema-indent" style="padding-left:' +
1253
+ indentPx +
1254
+ 'px;"></span>' +
1255
+ (depth > 0 ? '<span class="schema-branch">\u2514\u2500 </span>' : '') +
1256
+ escapeHtml(name);
1257
+
1258
+ const typeLabel = getTypeLabel(node);
1259
+ const descriptionHtml = renderNodeDescription(node);
1260
+
1261
+ let rows =
1262
+ '<tr>' +
1263
+ '<td class="col-name">' + nameCell + '</td>' +
1264
+ '<td class="col-type">' + escapeHtml(typeLabel) + '</td>' +
1265
+ '<td><span class="req-badge ' + reqClass + '">' + reqText + '</span></td>' +
1266
+ '<td>' + descriptionHtml + '</td>' +
1267
+ '</tr>';
1268
+
1269
+ // 1) Object properties
1270
+ if (node.kind === 'object' && node.properties) {
1271
+ rows += renderObjectChildren(node, depth);
1272
+ }
1273
+
1274
+ // 2) Array element type
1275
+ if (node.kind === 'array' && node.element) {
1276
+ const element = node.element;
1277
+ if (isComplexNode(element)) {
1278
+ // element rendered one level deeper than the array itself
1279
+ rows += renderNodeRow('[items]', element, depth + 1);
1207
1280
  }
1208
- return (
1209
- (title ? '<div class="schema-subtitle">' + escapeHtml(title) + '</div>' : '') +
1210
- '<table class="schema-table">' + rows + '</table>'
1281
+ }
1282
+
1283
+ // 3) Union variants
1284
+ if (node.kind === 'union' && Array.isArray(node.union)) {
1285
+ node.union.forEach(function (variant, index) {
1286
+ rows += renderNodeRow('option ' + (index + 1), variant, depth + 1);
1287
+ });
1288
+ }
1289
+
1290
+ return rows;
1291
+ }
1292
+
1293
+ /**
1294
+ * Decide if a node is \u201Ccomplex\u201D enough to warrant a nested expansion row.
1295
+ */
1296
+ function isComplexNode(node) {
1297
+ return (
1298
+ node.kind === 'object' ||
1299
+ node.kind === 'array' ||
1300
+ node.kind === 'union' ||
1301
+ node.kind === 'record' ||
1302
+ node.kind === 'tuple'
1303
+ );
1304
+ }
1305
+
1306
+ /**
1307
+ * Helper: simple vs complex node, for compact type labels.
1308
+ */
1309
+ function isSimpleNode(node) {
1310
+ return !isComplexNode(node);
1311
+ }
1312
+
1313
+ /**
1314
+ * Type label shown in the "Type" column.
1315
+ */
1316
+ function getTypeLabel(node) {
1317
+ let base;
1318
+
1319
+ switch (node.kind) {
1320
+ case 'object':
1321
+ base = 'object';
1322
+ break;
1323
+
1324
+ case 'array':
1325
+ if (!node.element) {
1326
+ base = 'array';
1327
+ } else if (isSimpleNode(node.element)) {
1328
+ base = 'array<' + getTypeLabel(node.element) + '>';
1329
+ } else {
1330
+ base = 'array<object>';
1331
+ }
1332
+ break;
1333
+
1334
+ case 'union':
1335
+ if (node.union && node.union.length) {
1336
+ const parts = node.union.map(function (u) {
1337
+ return isSimpleNode(u) ? getTypeLabel(u) : 'object';
1338
+ });
1339
+ base = parts.join(' | ');
1340
+ } else {
1341
+ base = 'union';
1342
+ }
1343
+ break;
1344
+
1345
+ case 'literal':
1346
+ base = 'literal';
1347
+ break;
1348
+
1349
+ case 'enum':
1350
+ base = 'enum';
1351
+ break;
1352
+
1353
+ case 'record':
1354
+ base = 'record';
1355
+ break;
1356
+
1357
+ case 'tuple':
1358
+ base = 'tuple';
1359
+ break;
1360
+
1361
+ default:
1362
+ base = node.kind || 'unknown';
1363
+ break;
1364
+ }
1365
+
1366
+ if (node.nullable) {
1367
+ base = base + ' | null';
1368
+ }
1369
+ return base;
1370
+ }
1371
+
1372
+ /**
1373
+ * Description cell content:
1374
+ * - main description text
1375
+ * - for enum: allowed values
1376
+ * - for literal: literal value
1377
+ */
1378
+ function renderNodeDescription(node) {
1379
+ const parts = [];
1380
+
1381
+ if (node.description) {
1382
+ parts.push(escapeHtml(node.description));
1383
+ }
1384
+
1385
+ if (node.kind === 'enum' && node.enumValues && node.enumValues.length) {
1386
+ const values = node.enumValues
1387
+ .map(function (v) {
1388
+ return '<code>' + escapeHtml(String(v)) + '</code>';
1389
+ })
1390
+ .join(' | ');
1391
+ parts.push('<div class="schema-meta">Allowed: ' + values + '</div>');
1392
+ }
1393
+
1394
+ if (node.kind === 'literal' && typeof node.literal !== 'undefined') {
1395
+ const valueStr = escapeHtml(JSON.stringify(node.literal));
1396
+ parts.push(
1397
+ '<div class="schema-meta">Literal: <code>' + valueStr + '</code></div>'
1211
1398
  );
1212
1399
  }
1213
1400
 
1401
+ return parts.join('<br>');
1402
+ }
1403
+
1404
+ /**
1405
+ * Escape HTML helper.
1406
+ */
1407
+ function escapeHtml(str) {
1408
+ return String(str)
1409
+ .replace(/&/g, '&amp;')
1410
+ .replace(/</g, '&lt;')
1411
+ .replace(/>/g, '&gt;')
1412
+ .replace(/"/g, '&quot;')
1413
+ .replace(/'/g, '&#39;');
1414
+ }
1415
+
1416
+
1214
1417
  function getTypeLabel(node) {
1215
1418
  if (!node) return 'any';
1216
1419
  if (node.kind === 'array') return getTypeLabel(node.element) + '[]';