s2cfgtojson 3.0.4 → 3.1.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/Struct.mts CHANGED
@@ -62,10 +62,63 @@ export class Struct {
62
62
  return this;
63
63
  }
64
64
 
65
+ addNode(value: any, key?: string | number): this {
66
+ if (this.__internal__.isArray !== true) {
67
+ throw new Error("Cannot add node to non-array struct.");
68
+ }
69
+ if (key === undefined) {
70
+ const nextIndex = Object.keys(this)
71
+ .map((k) => parseInt(k))
72
+ .filter((k) => !isNaN(k))
73
+ .sort((a, b) => a - b)
74
+ .pop();
75
+ this[nextIndex !== undefined ? nextIndex + 1 : 0] = value;
76
+ } else {
77
+ this[key] = value;
78
+ }
79
+ return this;
80
+ }
81
+
65
82
  clone() {
66
83
  return Struct.fromString(this.toString())[0] as this;
67
84
  }
68
85
 
86
+ forEach(callback: ([key, value]) => void): void {
87
+ Object.entries(this)
88
+ .filter(([key]) => key !== "__internal__")
89
+ .forEach(callback);
90
+ }
91
+
92
+ /**
93
+ * Filters the struct entries based on a callback function. Returns a copy.
94
+ * @param callback
95
+ */
96
+ filter(callback: ([key, value]) => boolean): Partial<this> & Struct {
97
+ const clone = this.clone();
98
+ Object.entries(clone)
99
+ .filter(([key]) => key !== "__internal__")
100
+ .forEach(([key, value]) => {
101
+ if (!callback([key, value])) {
102
+ delete clone[key];
103
+ }
104
+ });
105
+ return clone;
106
+ }
107
+
108
+ /**
109
+ * Maps the struct entries based on a callback function. Returns a copy.
110
+ * @param callback
111
+ */
112
+ map(callback: ([key, value]) => typeof value): this {
113
+ const clone = this.clone();
114
+ Object.entries(clone)
115
+ .filter(([key]) => key !== "__internal__")
116
+ .forEach(([key, value]) => {
117
+ clone[key] = callback([key, value]);
118
+ });
119
+ return clone;
120
+ }
121
+
69
122
  toString(): string {
70
123
  if (!(this.__internal__ instanceof Refs)) {
71
124
  this.__internal__ = new Refs(this.__internal__);
@@ -117,7 +170,7 @@ export class Refs implements DefaultEntries {
117
170
  isArray?: boolean;
118
171
  useAsterisk?: boolean;
119
172
 
120
- constructor(ref?: string | object) {
173
+ constructor(ref?: string | Refs) {
121
174
  if (typeof ref === "string") {
122
175
  ref
123
176
  .split(";")
@@ -151,7 +204,7 @@ export class Refs implements DefaultEntries {
151
204
  }
152
205
 
153
206
  const structHeadRegex = new RegExp(
154
- `^(.*)\\s*:\\s*struct\\.begin\\s*({\\s*((${KEYWORDS.join("|")})\\s*(=.+)?)\\s*})?`,
207
+ `^\s*(.*)\\s*:\\s*struct\\.begin\\s*({\\s*((${KEYWORDS.join("|")})\\s*(=.+)?)\\s*})?`,
155
208
  );
156
209
 
157
210
  function parseHead(line: string, index: number): Struct {
package/Struct.test.mts CHANGED
@@ -5,6 +5,7 @@ import {
5
5
  pad,
6
6
  Struct,
7
7
  ArmorPrototype,
8
+ Refs,
8
9
  } from "./Struct.mjs";
9
10
  import fs from "node:fs";
10
11
 
@@ -26,13 +27,21 @@ class TradePrototype extends Struct {
26
27
  TradeGenerators = new TradeGenerators();
27
28
  }
28
29
  class TradeGenerators extends Struct {
29
- "*" = new TradeGenerator();
30
+ __internal__ = new Refs({
31
+ isArray: true,
32
+ useAsterisk: true,
33
+ });
34
+ "0" = new TradeGenerator();
30
35
  }
31
36
  class TradeGenerator extends Struct {
32
37
  BuyLimitations = new BuyLimitations();
33
38
  }
34
39
 
35
40
  class BuyLimitations extends Struct {
41
+ __internal__ = new Refs({
42
+ rawName: "BuyLimitations",
43
+ isArray: true,
44
+ });
36
45
  [0] = "EItemType::Weapon";
37
46
  [1] = "EItemType::Armor";
38
47
  }
@@ -236,6 +245,55 @@ struct.end`;
236
245
  });
237
246
  });
238
247
 
248
+ describe("addNode", () => {
249
+ test("1", () => {
250
+ const a = new TradePrototype().fork(true);
251
+ expect(a.TradeGenerators[0].BuyLimitations[0]).toBe("EItemType::Weapon");
252
+ expect(a.TradeGenerators[0].BuyLimitations[1]).toBe("EItemType::Armor");
253
+ a.TradeGenerators[0].BuyLimitations.addNode("EItemType::Artifact");
254
+ expect(a.TradeGenerators[0].BuyLimitations[2]).toBe(
255
+ "EItemType::Artifact",
256
+ );
257
+ });
258
+ });
259
+
260
+ describe("forEach", () => {
261
+ test("1", () => {
262
+ const a = new TradePrototype().fork(true);
263
+ expect(a.TradeGenerators[0].BuyLimitations[0]).toBe("EItemType::Weapon");
264
+ expect(a.TradeGenerators[0].BuyLimitations[1]).toBe("EItemType::Armor");
265
+ a.TradeGenerators[0].BuyLimitations.forEach(([k]) => {
266
+ a.TradeGenerators[0].BuyLimitations[k] = "forEach";
267
+ });
268
+ expect(a.TradeGenerators[0].BuyLimitations[0]).toBe("forEach");
269
+ expect(a.TradeGenerators[0].BuyLimitations[1]).toBe("forEach");
270
+ });
271
+ });
272
+
273
+ describe("filter", () => {
274
+ test("1", () => {
275
+ const a = new TradePrototype().fork(true);
276
+ expect(a.TradeGenerators[0].BuyLimitations[0]).toBe("EItemType::Weapon");
277
+ expect(a.TradeGenerators[0].BuyLimitations[1]).toBe("EItemType::Armor");
278
+ const b = a.TradeGenerators[0].BuyLimitations.filter(([k]) => k === "0");
279
+ expect(b[0]).toBe("EItemType::Weapon");
280
+ expect(b[1]).toBeUndefined();
281
+ });
282
+ });
283
+
284
+ describe("map", () => {
285
+ test("1", () => {
286
+ const a = new TradePrototype();
287
+ expect(a.TradeGenerators[0].BuyLimitations[0]).toBe("EItemType::Weapon");
288
+ expect(a.TradeGenerators[0].BuyLimitations[1]).toBe("EItemType::Armor");
289
+ const b = a.TradeGenerators[0].BuyLimitations.map(
290
+ ([k, v]) => `${v}-mapped-${k}`,
291
+ );
292
+ expect(b[0]).toBe("EItemType::Weapon-mapped-0");
293
+ expect(b[1]).toBe("EItemType::Armor-mapped-1");
294
+ });
295
+ });
296
+
239
297
  describe("clone", () => {
240
298
  test("1", () => {
241
299
  const a = new TradePrototype();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "s2cfgtojson",
3
- "version": "3.0.4",
3
+ "version": "3.1.0",
4
4
  "description": "Converts Stalker 2 Cfg file into POJOs",
5
5
  "keywords": [
6
6
  "stalker",
package/types.mts CHANGED
@@ -756,7 +756,7 @@ export type DynamicItemGenerator = GetStructType<{
756
756
  Category: EItemGenerationCategory;
757
757
  PlayerRank: ERank;
758
758
  bAllowSameCategoryGeneration: boolean;
759
- ReputationThreshold: string;
759
+ ReputationThreshold: number;
760
760
  RefreshTime: string;
761
761
  PossibleItems: {
762
762
  ItemPrototypeSID: string;