snbt-js 1.0.4 → 1.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snbt-js",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "JavaScript library for parsing and manipulating Minecraft SNBT data",
5
5
  "main": "src/snbt.js",
6
6
  "type": "module",
package/src/snbt.d.ts CHANGED
@@ -51,7 +51,7 @@ export declare class NbtString extends NbtValue {
51
51
  }
52
52
 
53
53
  export declare class NbtBool extends NbtValue {
54
- value: string;
54
+ value: boolean;
55
55
  constructor(value: boolean);
56
56
  }
57
57
 
package/src/snbt.js CHANGED
@@ -43,7 +43,11 @@ export class NbtObject {
43
43
  if (args.length == 1) {
44
44
  return this.childs[args[0]];
45
45
  } else if (args.length > 1) {
46
- return this.childs[args[0]].get(args.slice(1));
46
+ var child = this.childs[args[0]];
47
+ if (child === undefined) {
48
+ return undefined;
49
+ }
50
+ return child.get(args.slice(1));
47
51
  } else {
48
52
  return this;
49
53
  };
@@ -55,7 +59,10 @@ export class NbtObject {
55
59
  if (index.length == 1) {
56
60
  this.childs[index[0]] = value;
57
61
  } else if (index.length > 1) {
58
- this.get(index.slice(0, -1)).set(index.slice(-1), value);
62
+ var parent = this.get(index.slice(0, -1));
63
+ if (parent !== undefined) {
64
+ parent.set(index.slice(-1), value);
65
+ }
59
66
  };
60
67
  };
61
68
  };
@@ -94,7 +101,11 @@ export class NbtList {
94
101
  if (args.length == 1) {
95
102
  return this.childs[args[0]];
96
103
  } else if (args.length > 1) {
97
- return this.childs[args[0]].get(args.slice(1));
104
+ var child = this.childs[args[0]];
105
+ if (child === undefined) {
106
+ return undefined;
107
+ }
108
+ return child.get(args.slice(1));
98
109
  } else {
99
110
  return this;
100
111
  };
@@ -106,7 +117,10 @@ export class NbtList {
106
117
  if (index.length == 1) {
107
118
  this.childs[index[0]] = value;
108
119
  } else if (index.length > 1) {
109
- this.get(index.slice(0, -1)).set(index.slice(-1), value);
120
+ var parent = this.get(index.slice(0, -1));
121
+ if (parent !== undefined) {
122
+ parent.set(index.slice(-1), value);
123
+ }
110
124
  };
111
125
  };
112
126
  };
@@ -251,7 +265,7 @@ export class NbtString {
251
265
 
252
266
  export class NbtBool {
253
267
  constructor(value) {
254
- this.value = value ? "true" : "false";
268
+ this.value = !!value;
255
269
  this.text = function (ispretty) {
256
270
  if (ispretty) {
257
271
  return highlightCode(`${this.value}`, "bool")
@@ -0,0 +1,81 @@
1
+ import { expect } from 'chai';
2
+ import { parseNbtString, NbtBool, NbtObject } from '../src/snbt.js';
3
+
4
+ describe('NbtBool Tests', () => {
5
+ it('should store boolean value as boolean, not string', () => {
6
+ const boolTrue = new NbtBool(true);
7
+ const boolFalse = new NbtBool(false);
8
+
9
+ expect(boolTrue.value).to.be.a('boolean');
10
+ expect(boolTrue.value).to.equal(true);
11
+
12
+ expect(boolFalse.value).to.be.a('boolean');
13
+ expect(boolFalse.value).to.equal(false);
14
+ });
15
+
16
+ it('should parse true boolean from SNBT', () => {
17
+ const result = parseNbtString('{ flag: true }');
18
+ const flag = result.get('flag');
19
+
20
+ expect(flag).to.be.instanceOf(NbtBool);
21
+ expect(flag.value).to.be.a('boolean');
22
+ expect(flag.value).to.equal(true);
23
+ });
24
+
25
+ it('should parse false boolean from SNBT', () => {
26
+ const result = parseNbtString('{ flag: false }');
27
+ const flag = result.get('flag');
28
+
29
+ expect(flag).to.be.instanceOf(NbtBool);
30
+ expect(flag.value).to.be.a('boolean');
31
+ expect(flag.value).to.equal(false);
32
+ });
33
+
34
+ it('should convert truthy values to true', () => {
35
+ const bool1 = new NbtBool(1);
36
+ const bool2 = new NbtBool("yes");
37
+ const bool3 = new NbtBool({});
38
+
39
+ expect(bool1.value).to.equal(true);
40
+ expect(bool2.value).to.equal(true);
41
+ expect(bool3.value).to.equal(true);
42
+ });
43
+
44
+ it('should convert falsy values to false', () => {
45
+ const bool1 = new NbtBool(0);
46
+ const bool2 = new NbtBool("");
47
+ const bool3 = new NbtBool(null);
48
+ const bool4 = new NbtBool(undefined);
49
+
50
+ expect(bool1.value).to.equal(false);
51
+ expect(bool2.value).to.equal(false);
52
+ expect(bool3.value).to.equal(false);
53
+ expect(bool4.value).to.equal(false);
54
+ });
55
+
56
+ it('should output boolean as string in text() method', () => {
57
+ const boolTrue = new NbtBool(true);
58
+ const boolFalse = new NbtBool(false);
59
+
60
+ expect(boolTrue.text()).to.equal('true');
61
+ expect(boolFalse.text()).to.equal('false');
62
+ });
63
+
64
+ it('should handle boolean in nested objects', () => {
65
+ const result = parseNbtString(`{
66
+ player: {
67
+ isAlive: true,
68
+ isFlying: false
69
+ }
70
+ }`);
71
+
72
+ const isAlive = result.get('player.isAlive');
73
+ const isFlying = result.get('player.isFlying');
74
+
75
+ expect(isAlive.value).to.be.a('boolean');
76
+ expect(isAlive.value).to.equal(true);
77
+
78
+ expect(isFlying.value).to.be.a('boolean');
79
+ expect(isFlying.value).to.equal(false);
80
+ });
81
+ });
@@ -0,0 +1,176 @@
1
+ import { expect } from 'chai';
2
+ import { parseNbtString, NbtObject, NbtList, NbtString, NbtNumber } from '../src/snbt.js';
3
+
4
+ describe('Path Access Tests', () => {
5
+ describe('NbtObject.get() with non-existent paths', () => {
6
+ it('should return undefined when accessing non-existent key', () => {
7
+ const nbt = new NbtObject({
8
+ 'minecraft:enchantments': new NbtObject()
9
+ });
10
+
11
+ const result = nbt.get(['minecraft:enchantments', 'levels']);
12
+ expect(result).to.be.undefined;
13
+ });
14
+
15
+ it('should return undefined when accessing nested non-existent path', () => {
16
+ const nbt = parseNbtString(`{
17
+ player: {
18
+ name: "Steve"
19
+ }
20
+ }`);
21
+
22
+ const result = nbt.get(['player', 'inventory', 0]);
23
+ expect(result).to.be.undefined;
24
+ });
25
+
26
+ it('should return undefined when accessing non-existent top-level key', () => {
27
+ const nbt = new NbtObject({
28
+ name: new NbtString('Steve')
29
+ });
30
+
31
+ const result = nbt.get('age');
32
+ expect(result).to.be.undefined;
33
+ });
34
+
35
+ it('should return undefined when using dot notation on non-existent path', () => {
36
+ const nbt = parseNbtString(`{ player: { name: "Steve" } }`);
37
+
38
+ const result = nbt.get('player.health');
39
+ expect(result).to.be.undefined;
40
+ });
41
+
42
+ it('should return undefined when accessing deeply nested non-existent path', () => {
43
+ const nbt = parseNbtString(`{
44
+ level1: {
45
+ level2: {
46
+ level3: "value"
47
+ }
48
+ }
49
+ }`);
50
+
51
+ const result = nbt.get(['level1', 'level2', 'level4', 'level5']);
52
+ expect(result).to.be.undefined;
53
+ });
54
+ });
55
+
56
+ describe('NbtList.get() with non-existent paths', () => {
57
+ it('should return undefined when accessing non-existent index in nested list', () => {
58
+ const nbt = parseNbtString(`{
59
+ items: [
60
+ { id: "diamond" }
61
+ ]
62
+ }`);
63
+
64
+ const result = nbt.get(['items', 5, 'id']);
65
+ expect(result).to.be.undefined;
66
+ });
67
+
68
+ it('should return undefined when accessing property on undefined array element', () => {
69
+ const nbt = new NbtObject({
70
+ inventory: new NbtList([
71
+ new NbtObject({ id: new NbtString('sword') })
72
+ ])
73
+ });
74
+
75
+ const result = nbt.get(['inventory', 10, 'id']);
76
+ expect(result).to.be.undefined;
77
+ });
78
+
79
+ it('should return undefined when list element exists but nested path does not', () => {
80
+ const nbt = parseNbtString(`{
81
+ items: [
82
+ { name: "item1" },
83
+ { name: "item2" }
84
+ ]
85
+ }`);
86
+
87
+ const result = nbt.get(['items', 0, 'count']);
88
+ expect(result).to.be.undefined;
89
+ });
90
+ });
91
+
92
+ describe('NbtObject.set() with non-existent paths', () => {
93
+ it('should not throw error when setting on non-existent intermediate path', () => {
94
+ const nbt = new NbtObject({
95
+ player: new NbtObject()
96
+ });
97
+
98
+ // This should not throw an error, but also should not set the value
99
+ // since 'inventory' doesn't exist on the player object (parent is undefined)
100
+ expect(() => {
101
+ nbt.set(['player', 'inventory', 'count'], new NbtNumber(5));
102
+ }).to.not.throw();
103
+
104
+ // Verify the value was not set (because 'inventory' doesn't exist)
105
+ const result = nbt.get(['player', 'inventory', 'count']);
106
+ expect(result).to.be.undefined;
107
+ });
108
+
109
+ it('should handle setting on deeply nested non-existent path gracefully', () => {
110
+ const nbt = parseNbtString(`{ level1: { level2: {} } }`);
111
+
112
+ expect(() => {
113
+ nbt.set(['level1', 'level2', 'level3', 'value'], new NbtString('test'));
114
+ }).to.not.throw();
115
+ });
116
+ });
117
+
118
+ describe('NbtList.set() with non-existent paths', () => {
119
+ it('should not throw error when setting on non-existent array index path', () => {
120
+ const nbt = new NbtObject({
121
+ items: new NbtList([
122
+ new NbtObject({ id: new NbtString('item1') })
123
+ ])
124
+ });
125
+
126
+ expect(() => {
127
+ nbt.set(['items', 5, 'id'], new NbtString('item2'));
128
+ }).to.not.throw();
129
+
130
+ // The value at index 5 should still be undefined
131
+ const result = nbt.get(['items', 5]);
132
+ expect(result).to.be.undefined;
133
+ });
134
+ });
135
+
136
+ describe('Valid path access should still work', () => {
137
+ it('should correctly access existing nested paths', () => {
138
+ const nbt = parseNbtString(`{
139
+ "minecraft:enchantments": {
140
+ levels: {
141
+ sharpness: 5
142
+ }
143
+ }
144
+ }`);
145
+
146
+ const result = nbt.get(['minecraft:enchantments', 'levels', 'sharpness']);
147
+ expect(result).to.not.be.undefined;
148
+ expect(result.value).to.equal(5);
149
+ });
150
+
151
+ it('should correctly access array elements', () => {
152
+ const nbt = parseNbtString(`{
153
+ items: [
154
+ { id: "diamond", count: 5 },
155
+ { id: "gold", count: 10 }
156
+ ]
157
+ }`);
158
+
159
+ const result = nbt.get(['items', 1, 'id']);
160
+ expect(result).to.not.be.undefined;
161
+ expect(result.value).to.equal('gold');
162
+ });
163
+
164
+ it('should correctly set values on existing paths', () => {
165
+ const nbt = new NbtObject({
166
+ player: new NbtObject({
167
+ health: new NbtNumber(20)
168
+ })
169
+ });
170
+
171
+ nbt.set(['player', 'health'], new NbtNumber(15));
172
+ const result = nbt.get(['player', 'health']);
173
+ expect(result.value).to.equal(15);
174
+ });
175
+ });
176
+ });