nayota-show-sdk 1.3.88 → 1.3.90

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nayota-show-sdk",
3
- "version": "1.3.88",
3
+ "version": "1.3.90",
4
4
  "description": "nayota-show-server rest-api",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -257,6 +257,40 @@ function normalizeHierarchyField(data = {}, field) {
257
257
  return getNestedValue(data, `relationInfo.${field}`)
258
258
  }
259
259
 
260
+ function normalizeHierarchyFloorPlanForWrite(data = {}) {
261
+ const relationInfo = data.relationInfo
262
+ const hasLegacyImage = hasOwn(relationInfo, 'image')
263
+
264
+ if (hasLegacyImage) {
265
+ const image = relationInfo.image
266
+
267
+ if (image == null) {
268
+ return null
269
+ }
270
+
271
+ if (typeof image !== 'object') {
272
+ return image
273
+ }
274
+
275
+ const hasImagePath = Boolean(image.imagePath || image.url)
276
+ const hasDimensions = Number(image.width || 0) > 0 && Number(image.height || 0) > 0
277
+ const hasCorners = Array.isArray(image.corners) && image.corners.length > 0
278
+ const hasImageIdentity = Boolean(image.id)
279
+
280
+ if (!hasImagePath && !hasDimensions && !hasCorners && !hasImageIdentity) {
281
+ return null
282
+ }
283
+
284
+ return image
285
+ }
286
+
287
+ if (hasOwn(data, 'floorPlan')) {
288
+ return data.floorPlan
289
+ }
290
+
291
+ return undefined
292
+ }
293
+
260
294
  function normalizeLegacyHierarchyRelationInfo(item = {}) {
261
295
  const relationInfo = removeUndefinedFields({
262
296
  ...(item.relationInfo || {}),
@@ -314,7 +348,7 @@ function mapDepartsToIotBody(data = {}) {
314
348
  latlng: normalizeHierarchyField(data, 'latlng'),
315
349
  zooms: normalizeHierarchyField(data, 'zooms'),
316
350
  powers: normalizeHierarchyField(data, 'powers'),
317
- floorPlan: data.floorPlan,
351
+ floorPlan: normalizeHierarchyFloorPlanForWrite(data),
318
352
  metadata: Object.keys(metadata).length ? metadata : undefined
319
353
  })
320
354
  }
@@ -477,6 +511,90 @@ function normalizeLegacyValueStr(value, fallback = '') {
477
511
  return ''
478
512
  }
479
513
 
514
+ function normalizeLegacyEasyListPropTypeValue(value) {
515
+ if (value == null || value === '') {
516
+ return undefined
517
+ }
518
+
519
+ const normalized = String(value).trim().replace(/[\s_-]/g, '').toLowerCase()
520
+
521
+ if (['operate', 'operation', 'control', 'controller', 'write', 'writable', 'readwrite', 'writeonly', 'rw', 'wr', 'w'].includes(normalized)) {
522
+ return 'Operate'
523
+ }
524
+
525
+ if (['check', 'monitor', 'sensor', 'read', 'readonly', 'ro', 'r'].includes(normalized)) {
526
+ return 'Check'
527
+ }
528
+
529
+ if (['控制', '控制器', '读写', '只写', '可写'].includes(normalized)) {
530
+ return 'Operate'
531
+ }
532
+
533
+ if (['监测', '监测器', '只读'].includes(normalized)) {
534
+ return 'Check'
535
+ }
536
+
537
+ if ((normalized.includes('write') || normalized.includes('写')) && normalized !== 'readonly' && normalized !== '只读') {
538
+ return 'Operate'
539
+ }
540
+
541
+ if (normalized.includes('read') || normalized.includes('读') || normalized.includes('check')) {
542
+ return 'Check'
543
+ }
544
+
545
+ return undefined
546
+ }
547
+
548
+ function resolveLegacyEasyListPropType(source = {}, prop = {}) {
549
+ const explicitCandidates = [
550
+ source.propType,
551
+ source.type,
552
+ source.propertyType,
553
+ prop.propType,
554
+ prop.type,
555
+ prop.propertyType,
556
+ getNestedValue(source, 'metadata.propType'),
557
+ getNestedValue(prop, 'metadata.propType')
558
+ ]
559
+
560
+ const explicitPropType = explicitCandidates
561
+ .map(normalizeLegacyEasyListPropTypeValue)
562
+ .find(Boolean)
563
+
564
+ if (explicitPropType) {
565
+ return explicitPropType
566
+ }
567
+
568
+ const accessCandidates = [
569
+ source.access,
570
+ source.propertyAccess,
571
+ source.accessMode,
572
+ source.permission,
573
+ source.permissions,
574
+ source.accessPermission,
575
+ prop.access,
576
+ prop.propertyAccess,
577
+ prop.accessMode,
578
+ prop.permission,
579
+ prop.permissions,
580
+ prop.accessPermission,
581
+ getNestedValue(source, 'metadata.access'),
582
+ getNestedValue(source, 'metadata.propertyAccess'),
583
+ getNestedValue(source, 'typeProperty.access'),
584
+ getNestedValue(source, 'deviceProperty.access'),
585
+ getNestedValue(source, 'deviceTypeProperty.access'),
586
+ getNestedValue(prop, 'metadata.access'),
587
+ getNestedValue(prop, 'metadata.propertyAccess'),
588
+ getNestedValue(prop, 'typeProperty.access'),
589
+ getNestedValue(prop, 'deviceProperty.access'),
590
+ getNestedValue(prop, 'deviceTypeProperty.access')
591
+ ]
592
+
593
+ return accessCandidates
594
+ .map(normalizeLegacyEasyListPropTypeValue)
595
+ .find(Boolean)
596
+ }
597
+
480
598
  function normalizeLegacyPropLine(source = {}, prop = {}, row = {}) {
481
599
  if (typeof source.line === 'boolean') {
482
600
  return source.line
@@ -630,10 +748,12 @@ function normalizeLegacyEasyListProp(source = {}, row = {}) {
630
748
  const isStatus = Boolean(source.isStatus)
631
749
  const isNumber = Boolean(source.isNumber)
632
750
  const isImport = Boolean(source.isImport || isMain || isStatus || isNumber)
751
+ const propType = resolveLegacyEasyListPropType(source, prop)
633
752
 
634
753
  const legacyProp = removeUndefinedFields({
635
754
  ...prop,
636
755
  _id: propId,
756
+ propType,
637
757
  deviceId: prop.deviceId || source.deviceId || '',
638
758
  key: prop.key || source.propertyKey,
639
759
  name: prop.name || source.propName || source.name || source.code || source.propertyKey,
@@ -664,6 +784,7 @@ function normalizeLegacyEasyListProp(source = {}, row = {}) {
664
784
  isMain,
665
785
  isStatus,
666
786
  isNumber,
787
+ propType,
667
788
  line,
668
789
  value,
669
790
  valueStr,
@@ -233,6 +233,47 @@ describe('iotModuleSpecs departs hierarchy compatibility', () => {
233
233
  expect(request.data.metadata).toEqual({ keep: 'value' })
234
234
  })
235
235
 
236
+ test('clears official floorPlan when legacy relationInfo image is explicitly removed', () => {
237
+ const request = departs.updateOne.toRequest({
238
+ _id: 'e245a3f6-d2c7-4ce1-9e02-ba9bbb347ed7',
239
+ floorPlan: {
240
+ imagePath: 'stale.svg',
241
+ width: 100,
242
+ height: 80
243
+ },
244
+ relationInfo: {
245
+ image: null
246
+ }
247
+ })
248
+
249
+ expect(request.data.relationInfo).toEqual({
250
+ image: null
251
+ })
252
+ expect(request.data.floorPlan).toBeNull()
253
+ })
254
+
255
+ test('clears official floorPlan when legacy relationInfo image is emptied by old BMS editor', () => {
256
+ const request = departs.updateOne.toRequest({
257
+ _id: 'e245a3f6-d2c7-4ce1-9e02-ba9bbb347ed7',
258
+ floorPlan: {
259
+ imagePath: 'stale.svg',
260
+ width: 100,
261
+ height: 80
262
+ },
263
+ relationInfo: {
264
+ image: {
265
+ imagePath: '',
266
+ width: 0,
267
+ height: 0,
268
+ zIndex: 0,
269
+ corners: []
270
+ }
271
+ }
272
+ })
273
+
274
+ expect(request.data.floorPlan).toBeNull()
275
+ })
276
+
236
277
  test('rebuilds legacy relationInfo from official hierarchy fields and ignores metadata fallbacks', () => {
237
278
  const response = departs.list.fromResponse({
238
279
  code: 0,
@@ -595,6 +636,60 @@ describe('iotModuleSpecs devices easyList legacy compatibility', () => {
595
636
  })
596
637
  )
597
638
  })
639
+
640
+ test('maps writable access permissions to legacy BMS Operate props', () => {
641
+ const response = easyList.fromResponse({
642
+ code: 0,
643
+ data: {
644
+ total: 1,
645
+ rows: [
646
+ {
647
+ id: 'twin-1',
648
+ props: [
649
+ {
650
+ id: 'write-only-prop',
651
+ propertyKey: 'reset',
652
+ name: '复位',
653
+ access: 'write_only',
654
+ interval: '[["复位"],[1]]',
655
+ prop: {
656
+ id: 'device-prop-reset'
657
+ }
658
+ },
659
+ {
660
+ id: 'read-write-prop',
661
+ propertyKey: 'reply',
662
+ name: '回复',
663
+ propertyAccess: '读写',
664
+ interval: '[["确认"],[1]]',
665
+ prop: {
666
+ id: 'device-prop-reply'
667
+ }
668
+ },
669
+ {
670
+ id: 'read-only-prop',
671
+ propertyKey: 'version',
672
+ name: '版本',
673
+ access: 'read_only',
674
+ prop: {
675
+ id: 'device-prop-version'
676
+ }
677
+ }
678
+ ]
679
+ }
680
+ ]
681
+ }
682
+ })
683
+
684
+ const [writeOnlyProp, readWriteProp, readOnlyProp] = response.data.rows[0].props
685
+
686
+ expect(writeOnlyProp).toEqual(expect.objectContaining({ propType: 'Operate' }))
687
+ expect(writeOnlyProp.prop).toEqual(expect.objectContaining({ propType: 'Operate' }))
688
+ expect(readWriteProp).toEqual(expect.objectContaining({ propType: 'Operate' }))
689
+ expect(readWriteProp.prop).toEqual(expect.objectContaining({ propType: 'Operate' }))
690
+ expect(readOnlyProp).toEqual(expect.objectContaining({ propType: 'Check' }))
691
+ expect(readOnlyProp.prop).toEqual(expect.objectContaining({ propType: 'Check' }))
692
+ })
598
693
  })
599
694
 
600
695
  describe('iotModuleSpecs devices getPropHistoryData legacy compatibility', () => {