osu-stable-db 0.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/README.md ADDED
@@ -0,0 +1,141 @@
1
+ # osu-stable-db
2
+
3
+ TypeScript reader and writer for osu!stable database files.
4
+
5
+ This library currently supports the latest database structure from version 20250107 onward for:
6
+
7
+ - osu!.db
8
+ - collection.db
9
+ - scores.db
10
+
11
+ The core binary and database logic is browser-compatible. A separate Node-only subpath is provided for direct file reads and writes.
12
+
13
+ ## Scope
14
+
15
+ - Supports only 20250107 and later database structures
16
+ - Preserves null string semantics used by the stable database format
17
+ - Uses bigint for 64-bit values such as DateTime ticks
18
+ - Exposes byte-array database APIs from the main entry
19
+ - Exposes direct file APIs from the ./node subpath
20
+
21
+ Older stable database versions are intentionally out of scope.
22
+
23
+ ## Install
24
+
25
+ ```bash
26
+ pnpm add osu-stable-db
27
+ ```
28
+
29
+ ## Browser Usage
30
+
31
+ Use the main entry when you already have bytes in memory.
32
+
33
+ ```ts
34
+ import {
35
+ readOsuDatabase,
36
+ writeCollectionDatabase,
37
+ type CollectionDatabase,
38
+ } from 'osu-stable-db'
39
+
40
+ const osuBytes: ArrayBuffer = bytesFromSomewhere
41
+ const osuDatabase = readOsuDatabase(osuBytes)
42
+
43
+ const collectionDatabase: CollectionDatabase = {
44
+ version: osuDatabase.version,
45
+ collections: [
46
+ {
47
+ name: 'Favorites',
48
+ beatmapMd5Hashes: ['d41d8cd98f00b204e9800998ecf8427e'],
49
+ },
50
+ ],
51
+ }
52
+
53
+ const collectionBytes = writeCollectionDatabase(collectionDatabase)
54
+ ```
55
+
56
+ Main entry exports:
57
+
58
+ - All public types and constants
59
+ - readOsuDatabase and writeOsuDatabase
60
+ - readCollectionDatabase and writeCollectionDatabase
61
+ - readScoresDatabase and writeScoresDatabase
62
+
63
+ ## Node Usage
64
+
65
+ Use the Node subpath when you want direct file reads and writes through node:fs/promises.
66
+
67
+ ```ts
68
+ import {
69
+ readOsuDatabaseFile,
70
+ writeCollectionDatabaseFile,
71
+ } from 'osu-stable-db/node'
72
+
73
+ const osuDatabase = await readOsuDatabaseFile('path/to/osu!.db')
74
+
75
+ await writeCollectionDatabaseFile(
76
+ 'path/to/collection.db',
77
+ {
78
+ version: osuDatabase.version,
79
+ collections: [],
80
+ },
81
+ )
82
+ ```
83
+
84
+ Node subpath exports:
85
+
86
+ - readOsuDatabaseFile and writeOsuDatabaseFile
87
+ - readCollectionDatabaseFile and writeCollectionDatabaseFile
88
+ - readScoresDatabaseFile and writeScoresDatabaseFile
89
+
90
+ ## Types And Time Values
91
+
92
+ - Date-like 64-bit values are exposed as DateTimeTicks, backed by bigint
93
+ - Helper functions for DateTimeTicks and mod flags live in [src/core/utils.ts](src/core/utils.ts)
94
+
95
+ JavaScript Date is not used as the storage type because it loses sub-millisecond tick precision.
96
+
97
+ ## AI Disclosure
98
+
99
+ This project is 100% AI-generated.
100
+
101
+ ## Tests And Fixtures
102
+
103
+ Committed minimal fixtures live in [tests/files](tests/files).
104
+
105
+ Large real-world local fixtures can be placed in:
106
+
107
+ - [tests/files/local](tests/files/local)
108
+
109
+ That directory is git-ignored. When those files are present, the test suite will:
110
+
111
+ - parse them
112
+ - verify byte-for-byte round-trip for osu!.db, collection.db, and scores.db
113
+
114
+ You can also generate a local inspection report for a specific beatmap identifier with:
115
+
116
+ ```bash
117
+ pnpm run local:inspect -- 5288868
118
+ ```
119
+
120
+ The generated report is written to:
121
+
122
+ - [tests/files/local/reports](tests/files/local/reports)
123
+
124
+ ## Development
125
+
126
+ ```bash
127
+ pnpm install
128
+ pnpm run typecheck
129
+ pnpm test -- --run
130
+ pnpm run build
131
+ ```
132
+
133
+ ## Notes On Validation
134
+
135
+ Local validation also passes against private real-world database files in [tests/files/local](tests/files/local):
136
+
137
+ - osu!.db: 58,295,932 bytes, 72,038 beatmaps
138
+ - collection.db: 195,402 bytes, 11 collections, 5,743 stored beatmap references
139
+ - scores.db: 3,714,272 bytes, 11,331 beatmap score groups, 26,481 scores
140
+
141
+ Those local tests passed with parsing and byte-for-byte round-trip verification enabled.
@@ -0,0 +1,15 @@
1
+ import { C as UserPermissionFlags, S as UserPermission, _ as ScoreAdditionalModInfo, a as GameplayMode, b as ScoresDatabase, c as Grades, d as Mod, f as ModFlags, g as RankedStatuses, h as RankedStatus, i as DateTimeTicks, l as IntFloatPair, m as OsuDatabase, n as CollectionDatabase, o as GameplayModes, p as Mods, r as CollectionEntry, s as Grade, t as BeatmapEntry, u as MINIMUM_SUPPORTED_VERSION, v as ScoreEntry, w as UserPermissions, x as TimingPoint, y as ScoresBeatmapEntry } from "./types-DiZMN3fQ.mjs";
2
+
3
+ //#region src/db/collection.d.ts
4
+ declare function readCollectionDatabase(input: ArrayBuffer | Uint8Array): CollectionDatabase;
5
+ declare function writeCollectionDatabase(database: CollectionDatabase): Uint8Array;
6
+ //#endregion
7
+ //#region src/db/osu.d.ts
8
+ declare function readOsuDatabase(input: ArrayBuffer | Uint8Array): OsuDatabase;
9
+ declare function writeOsuDatabase(database: OsuDatabase): Uint8Array;
10
+ //#endregion
11
+ //#region src/db/scores.d.ts
12
+ declare function readScoresDatabase(input: ArrayBuffer | Uint8Array): ScoresDatabase;
13
+ declare function writeScoresDatabase(database: ScoresDatabase): Uint8Array;
14
+ //#endregion
15
+ export { BeatmapEntry, CollectionDatabase, CollectionEntry, DateTimeTicks, GameplayMode, GameplayModes, Grade, Grades, IntFloatPair, MINIMUM_SUPPORTED_VERSION, Mod, ModFlags, Mods, OsuDatabase, RankedStatus, RankedStatuses, ScoreAdditionalModInfo, ScoreEntry, ScoresBeatmapEntry, ScoresDatabase, TimingPoint, UserPermission, UserPermissionFlags, UserPermissions, readCollectionDatabase, readOsuDatabase, readScoresDatabase, writeCollectionDatabase, writeOsuDatabase, writeScoresDatabase };
package/dist/index.mjs ADDED
@@ -0,0 +1,2 @@
1
+ import { a as readCollectionDatabase, c as Grades, d as RankedStatuses, f as UserPermissions, i as writeOsuDatabase, l as MINIMUM_SUPPORTED_VERSION, n as writeScoresDatabase, o as writeCollectionDatabase, r as readOsuDatabase, s as GameplayModes, t as readScoresDatabase, u as Mods } from "./scores-7qsAMzUc.mjs";
2
+ export { GameplayModes, Grades, MINIMUM_SUPPORTED_VERSION, Mods, RankedStatuses, UserPermissions, readCollectionDatabase, readOsuDatabase, readScoresDatabase, writeCollectionDatabase, writeOsuDatabase, writeScoresDatabase };
@@ -0,0 +1,12 @@
1
+ import { b as ScoresDatabase, m as OsuDatabase, n as CollectionDatabase } from "./types-DiZMN3fQ.mjs";
2
+
3
+ //#region src/node.d.ts
4
+ type DatabaseFilePath = string | URL;
5
+ declare function readOsuDatabaseFile(path: DatabaseFilePath): Promise<OsuDatabase>;
6
+ declare function writeOsuDatabaseFile(path: DatabaseFilePath, database: OsuDatabase): Promise<void>;
7
+ declare function readCollectionDatabaseFile(path: DatabaseFilePath): Promise<CollectionDatabase>;
8
+ declare function writeCollectionDatabaseFile(path: DatabaseFilePath, database: CollectionDatabase): Promise<void>;
9
+ declare function readScoresDatabaseFile(path: DatabaseFilePath): Promise<ScoresDatabase>;
10
+ declare function writeScoresDatabaseFile(path: DatabaseFilePath, database: ScoresDatabase): Promise<void>;
11
+ //#endregion
12
+ export { DatabaseFilePath, readCollectionDatabaseFile, readOsuDatabaseFile, readScoresDatabaseFile, writeCollectionDatabaseFile, writeOsuDatabaseFile, writeScoresDatabaseFile };
package/dist/node.mjs ADDED
@@ -0,0 +1,23 @@
1
+ import { a as readCollectionDatabase, i as writeOsuDatabase, n as writeScoresDatabase, o as writeCollectionDatabase, r as readOsuDatabase, t as readScoresDatabase } from "./scores-7qsAMzUc.mjs";
2
+ import { readFile, writeFile } from "node:fs/promises";
3
+ //#region src/node.ts
4
+ async function readOsuDatabaseFile(path) {
5
+ return readOsuDatabase(new Uint8Array(await readFile(path)));
6
+ }
7
+ async function writeOsuDatabaseFile(path, database) {
8
+ await writeFile(path, writeOsuDatabase(database));
9
+ }
10
+ async function readCollectionDatabaseFile(path) {
11
+ return readCollectionDatabase(new Uint8Array(await readFile(path)));
12
+ }
13
+ async function writeCollectionDatabaseFile(path, database) {
14
+ await writeFile(path, writeCollectionDatabase(database));
15
+ }
16
+ async function readScoresDatabaseFile(path) {
17
+ return readScoresDatabase(new Uint8Array(await readFile(path)));
18
+ }
19
+ async function writeScoresDatabaseFile(path, database) {
20
+ await writeFile(path, writeScoresDatabase(database));
21
+ }
22
+ //#endregion
23
+ export { readCollectionDatabaseFile, readOsuDatabaseFile, readScoresDatabaseFile, writeCollectionDatabaseFile, writeOsuDatabaseFile, writeScoresDatabaseFile };