@zebbedaja/er-save-parser 0.1.1 → 0.1.2

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/README.md CHANGED
@@ -33,8 +33,14 @@ import { parse, type Save, type Slot, type Character } from '@zebbedaja/er-save-
33
33
  import { readFileSync } from 'fs'
34
34
 
35
35
  const buffer = readFileSync('ER0000.sl2').buffer
36
+
37
+ // Default: only errors are logged (logLevel: 'error')
36
38
  const save: Save = parse(buffer)
37
39
 
40
+ // Optional: configure logging with one of 'debug', 'info', 'warn', 'error', 'none'
41
+ // const save: Save = parse(buffer, { logLevel: 'debug' }) // Verbose progress logs
42
+ // const save: Save = parse(buffer, { logLevel: 'none' }) // Silent
43
+
38
44
  console.log(save.steamId)
39
45
  console.log(save.settings?.hud)
40
46
 
@@ -65,8 +71,14 @@ import { parse } from '@zebbedaja/er-save-parser'
65
71
  import { readFileSync } from 'node:fs'
66
72
 
67
73
  const buffer = readFileSync('ER0000.sl2').buffer
74
+
75
+ // Default: only errors are logged (logLevel: 'error')
68
76
  const save = parse(buffer)
69
77
 
78
+ // Optional: configure logging with one of 'debug', 'info', 'warn', 'error', 'none'
79
+ // const save = parse(buffer, { logLevel: 'debug' }) // Verbose progress logs
80
+ // const save = parse(buffer, { logLevel: 'none' }) // Silent
81
+
70
82
  console.log(save.steamId)
71
83
  console.log(save.settings?.hud)
72
84
 
package/dist/index.d.mts CHANGED
@@ -1,4 +1,8 @@
1
1
  //#region src/types.d.ts
2
+ type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'none';
3
+ interface ParseOptions {
4
+ logLevel?: LogLevel;
5
+ }
2
6
  interface Save {
3
7
  magicBytes?: string;
4
8
  checksum?: string;
@@ -139,6 +143,14 @@ interface EventFlag {
139
143
  }
140
144
  //#endregion
141
145
  //#region src/parser.d.ts
142
- declare function parse(buffer: ArrayBuffer): Save;
146
+ /**
147
+ * Parse an Elden Ring save file buffer.
148
+ *
149
+ * @param buffer - The ArrayBuffer containing the save file data
150
+ * @param options - Optional configuration for parsing
151
+ * @param options.logLevel - Log level threshold: 'debug', 'info', 'warn', 'error', or 'none'. Defaults to 'error'
152
+ * @returns A Save object containing parsed slot and profile data
153
+ */
154
+ declare function parse(buffer: ArrayBuffer, options?: ParseOptions): Save;
143
155
  //#endregion
144
- export { type Character, type EventFlag, type ProfileSummary, type Save, type Settings, type Slot, parse };
156
+ export { type Character, type EventFlag, type LogLevel, type ParseOptions, type ProfileSummary, type Save, type Settings, type Slot, parse };
package/dist/index.mjs CHANGED
@@ -6540,6 +6540,38 @@ const eventFlags = [
6540
6540
  }
6541
6541
  ];
6542
6542
  //#endregion
6543
+ //#region src/logger.ts
6544
+ const levelValues = {
6545
+ debug: 0,
6546
+ info: 1,
6547
+ warn: 2,
6548
+ error: 3,
6549
+ none: 4
6550
+ };
6551
+ /**
6552
+ * Factory for creating a logger instance with the specified log level threshold.
6553
+ *
6554
+ * @param level - The minimum log level to output. Defaults to 'error'
6555
+ * @returns A logger object with debug, info, warn, and error methods
6556
+ */
6557
+ function createLogger(level = "error") {
6558
+ const threshold = levelValues[level];
6559
+ return {
6560
+ debug: (msg) => {
6561
+ if (levelValues.debug >= threshold) console.log(`[DEBUG] ${msg}`);
6562
+ },
6563
+ info: (msg) => {
6564
+ if (levelValues.info >= threshold) console.log(`[INFO] ${msg}`);
6565
+ },
6566
+ warn: (msg) => {
6567
+ if (levelValues.warn >= threshold) console.warn(`[WARN] ${msg}`);
6568
+ },
6569
+ error: (msg) => {
6570
+ if (levelValues.error >= threshold) console.error(`[ERROR] ${msg}`);
6571
+ }
6572
+ };
6573
+ }
6574
+ //#endregion
6543
6575
  //#region src/bst-map.ts
6544
6576
  const bstFile = `1045540,6223
6545
6577
  1037495,3951
@@ -18466,7 +18498,16 @@ const bstFile = `1045540,6223
18466
18498
  const USER_10_DATA_START = 26215328;
18467
18499
  const ACTIVE_PROFILES_START = 26221828;
18468
18500
  const SLOT_COUNT = 10;
18469
- function parse(buffer) {
18501
+ /**
18502
+ * Parse an Elden Ring save file buffer.
18503
+ *
18504
+ * @param buffer - The ArrayBuffer containing the save file data
18505
+ * @param options - Optional configuration for parsing
18506
+ * @param options.logLevel - Log level threshold: 'debug', 'info', 'warn', 'error', or 'none'. Defaults to 'error'
18507
+ * @returns A Save object containing parsed slot and profile data
18508
+ */
18509
+ function parse(buffer, options = { logLevel: "error" }) {
18510
+ const logger = createLogger(options.logLevel);
18470
18511
  const dataView = new DataView(buffer);
18471
18512
  const utf16leDecoder = new TextDecoder("utf-16le");
18472
18513
  const utf8Decoder = new TextDecoder("utf-8");
@@ -18479,6 +18520,7 @@ function parse(buffer) {
18479
18520
  offset += 764;
18480
18521
  save.slots = [];
18481
18522
  for (let i = 0; i < SLOT_COUNT; i++) {
18523
+ logger.debug(`Parsing slot ${i}`);
18482
18524
  offset = 768 + i * 2621456;
18483
18525
  const slot = {};
18484
18526
  slot.checksum = toHexString(buffer.slice(offset, offset + 16));
@@ -18488,6 +18530,7 @@ function parse(buffer) {
18488
18530
  slot.mapId = toHexString(buffer.slice(offset, offset + 4));
18489
18531
  offset += 4;
18490
18532
  offset += 24;
18533
+ logger.debug(`Reading GaItems for slot ${i}`);
18491
18534
  for (let i = 0; i < 5120; i++) {
18492
18535
  const gaitemHandle = dataView.getUint32(offset, true);
18493
18536
  offset += 4;
@@ -18498,6 +18541,7 @@ function parse(buffer) {
18498
18541
  if (gaitemHandleType === 2147483648) offset += 5;
18499
18542
  }
18500
18543
  }
18544
+ logger.debug(`Reading character data for slot ${i}`);
18501
18545
  slot.character = {};
18502
18546
  slot.character.unk0x0 = dataView.getUint32(offset, true);
18503
18547
  offset += 4;
@@ -18651,6 +18695,7 @@ function parse(buffer) {
18651
18695
  slot.inGameCountdownTimer = dataView.getUint32(offset, true);
18652
18696
  offset += 4;
18653
18697
  offset += 4;
18698
+ logger.debug(`Reading event flags for slot ${i} with offset ${offset}`);
18654
18699
  const eventFlagUint8Array = new Uint8Array(buffer, offset, 1833375);
18655
18700
  const bstMap = parseToMap(bstFile);
18656
18701
  const slotEventFlags = [];
@@ -18663,6 +18708,7 @@ function parse(buffer) {
18663
18708
  offset += 1833375;
18664
18709
  save.slots?.push(slot);
18665
18710
  }
18711
+ logger.debug("Reading User_10 data");
18666
18712
  offset = USER_10_DATA_START;
18667
18713
  save.checksum = toHexString(buffer.slice(offset, offset + 16));
18668
18714
  offset += 16;
@@ -18670,6 +18716,7 @@ function parse(buffer) {
18670
18716
  offset += 4;
18671
18717
  save.steamId = dataView.getBigUint64(offset, true).toString();
18672
18718
  offset += 8;
18719
+ logger.debug("Reading settings");
18673
18720
  save.settings = {};
18674
18721
  save.settings.cameraSpeed = dataView.getUint8(offset++);
18675
18722
  save.settings.controllerVibration = dataView.getUint8(offset++);
@@ -18709,6 +18756,7 @@ function parse(buffer) {
18709
18756
  save.settings.show_recent_tabs = dataView.getUint8(offset++);
18710
18757
  offset = ACTIVE_PROFILES_START;
18711
18758
  save.activeProfiles = Array.from({ length: SLOT_COUNT }, () => dataView.getUint8(offset++));
18759
+ logger.debug("Reading profile summaries");
18712
18760
  save.profileSummaries = [];
18713
18761
  for (let i = 0; i < SLOT_COUNT; i++) {
18714
18762
  const profileSummary = {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@zebbedaja/er-save-parser",
3
3
  "type": "module",
4
- "version": "0.1.1",
4
+ "version": "0.1.2",
5
5
  "description": "A parser for Elden Ring save files written in TypesScript.",
6
6
  "author": "zebbedaja",
7
7
  "license": "MIT",