@px-lsp/protocol 0.1.0 → 0.2.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.
@@ -1,101 +1,101 @@
1
- /**
2
- * Reader and writer for the newer Paradox mod descriptor convention:
3
- * `<mod>/.metadata/metadata.json` (newer titles) instead of the launcher
4
- * `.mod` file. Fail-soft on read: any read/parse problem yields null.
5
- *
6
- * The field set is copied from three real workshop mods (2026-08-12: name, id,
7
- * version, supported_game_version, tags, relationships, game_custom_data;
8
- * `game_id` appears in one of the three and is left out here because the other
9
- * two load without it). The relationship shape is the one the Community Mod
10
- * Framework documents for the mods that depend on it.
11
- */
12
- import * as fs from "fs";
13
- import * as path from "path";
14
-
15
- /** Mod-root-relative path of the descriptor, forward slashes. */
16
- export const METADATA_REL_PATH = ".metadata/metadata.json";
17
-
18
- /** One entry of `relationships`: a link to another mod. */
19
- export interface MetadataRelationship {
20
- /** "dependency", "incompatible_with", "load_before", "load_after". */
21
- rel_type: string;
22
- /** The other mod's `id` field (NOT its Workshop number). */
23
- id: string;
24
- /** Shown when the other mod is not on disk. */
25
- display_name?: string;
26
- /** Only "mod" is supported by the launcher today. */
27
- resource_type: string;
28
- /** Version of the other mod, `*` for any. */
29
- version?: string;
30
- }
31
-
32
- /** The fields of a mod's metadata.json this toolkit reads or writes. */
33
- export interface ModMetadata {
34
- name?: string;
35
- id?: string;
36
- version?: string;
37
- supported_game_version?: string;
38
- short_description?: string;
39
- tags?: string[];
40
- relationships?: MetadataRelationship[];
41
- game_custom_data?: { multiplayer_synchronized?: boolean; replace_paths?: string[] };
42
- }
43
-
44
- /** The parsed `<dir>/.metadata/metadata.json`, or null when absent/unreadable. */
45
- export function readMetadata(dir: string): ModMetadata | null {
46
- try {
47
- const file = path.join(dir, ".metadata", "metadata.json");
48
- if (!fs.existsSync(file)) return null;
49
- return JSON.parse(fs.readFileSync(file, "utf8")) as ModMetadata;
50
- } catch {
51
- return null;
52
- }
53
- }
54
-
55
- /** The mod's display name from `<dir>/.metadata/metadata.json`, or null. */
56
- export function readMetadataName(dir: string): string | null {
57
- const name = readMetadata(dir)?.name;
58
- return typeof name === "string" && name.trim() !== "" ? name : null;
59
- }
60
-
61
- /** True when `dir` carries a metadata-style descriptor. */
62
- export function hasMetadataDescriptor(dir: string): boolean {
63
- try {
64
- return fs.existsSync(path.join(dir, ".metadata", "metadata.json"));
65
- } catch {
66
- return false;
67
- }
68
- }
69
-
70
- export interface MetadataScaffold {
71
- name: string;
72
- /** Stable identifier other mods point their relationships at. */
73
- id: string;
74
- /** The mod's own version, not the game's. */
75
- version?: string;
76
- /** Game version the mod is for, `*` when unknown. */
77
- supportedGameVersion: string;
78
- shortDescription?: string;
79
- tags?: string[];
80
- relationships?: MetadataRelationship[];
81
- /** Vanilla folders the mod unloads wholesale (total conversions). */
82
- replacePaths?: string[];
83
- }
84
-
85
- /** A launcher-correct starter metadata.json, in the corpus's field order. */
86
- export function scaffoldMetadata(opts: MetadataScaffold): string {
87
- const body: ModMetadata = {
88
- name: opts.name,
89
- id: opts.id,
90
- version: opts.version ?? "0.1.0",
91
- supported_game_version: opts.supportedGameVersion,
92
- ...(opts.shortDescription ? { short_description: opts.shortDescription } : {}),
93
- tags: opts.tags ?? [],
94
- relationships: opts.relationships ?? [],
95
- game_custom_data: {
96
- multiplayer_synchronized: true,
97
- ...(opts.replacePaths && opts.replacePaths.length > 0 ? { replace_paths: opts.replacePaths } : {}),
98
- },
99
- };
100
- return JSON.stringify(body, null, 2) + "\n";
101
- }
1
+ /**
2
+ * Reader and writer for the newer Paradox mod descriptor convention:
3
+ * `<mod>/.metadata/metadata.json` (newer titles) instead of the launcher
4
+ * `.mod` file. Fail-soft on read: any read/parse problem yields null.
5
+ *
6
+ * The field set is copied from three real workshop mods (2026-08-12: name, id,
7
+ * version, supported_game_version, tags, relationships, game_custom_data;
8
+ * `game_id` appears in one of the three and is left out here because the other
9
+ * two load without it). The relationship shape is the one the Community Mod
10
+ * Framework documents for the mods that depend on it.
11
+ */
12
+ import * as fs from "fs";
13
+ import * as path from "path";
14
+
15
+ /** Mod-root-relative path of the descriptor, forward slashes. */
16
+ export const METADATA_REL_PATH = ".metadata/metadata.json";
17
+
18
+ /** One entry of `relationships`: a link to another mod. */
19
+ export interface MetadataRelationship {
20
+ /** "dependency", "incompatible_with", "load_before", "load_after". */
21
+ rel_type: string;
22
+ /** The other mod's `id` field (NOT its Workshop number). */
23
+ id: string;
24
+ /** Shown when the other mod is not on disk. */
25
+ display_name?: string;
26
+ /** Only "mod" is supported by the launcher today. */
27
+ resource_type: string;
28
+ /** Version of the other mod, `*` for any. */
29
+ version?: string;
30
+ }
31
+
32
+ /** The fields of a mod's metadata.json this toolkit reads or writes. */
33
+ export interface ModMetadata {
34
+ name?: string;
35
+ id?: string;
36
+ version?: string;
37
+ supported_game_version?: string;
38
+ short_description?: string;
39
+ tags?: string[];
40
+ relationships?: MetadataRelationship[];
41
+ game_custom_data?: { multiplayer_synchronized?: boolean; replace_paths?: string[] };
42
+ }
43
+
44
+ /** The parsed `<dir>/.metadata/metadata.json`, or null when absent/unreadable. */
45
+ export function readMetadata(dir: string): ModMetadata | null {
46
+ try {
47
+ const file = path.join(dir, ".metadata", "metadata.json");
48
+ if (!fs.existsSync(file)) return null;
49
+ return JSON.parse(fs.readFileSync(file, "utf8")) as ModMetadata;
50
+ } catch {
51
+ return null;
52
+ }
53
+ }
54
+
55
+ /** The mod's display name from `<dir>/.metadata/metadata.json`, or null. */
56
+ export function readMetadataName(dir: string): string | null {
57
+ const name = readMetadata(dir)?.name;
58
+ return typeof name === "string" && name.trim() !== "" ? name : null;
59
+ }
60
+
61
+ /** True when `dir` carries a metadata-style descriptor. */
62
+ export function hasMetadataDescriptor(dir: string): boolean {
63
+ try {
64
+ return fs.existsSync(path.join(dir, ".metadata", "metadata.json"));
65
+ } catch {
66
+ return false;
67
+ }
68
+ }
69
+
70
+ export interface MetadataScaffold {
71
+ name: string;
72
+ /** Stable identifier other mods point their relationships at. */
73
+ id: string;
74
+ /** The mod's own version, not the game's. */
75
+ version?: string;
76
+ /** Game version the mod is for, `*` when unknown. */
77
+ supportedGameVersion: string;
78
+ shortDescription?: string;
79
+ tags?: string[];
80
+ relationships?: MetadataRelationship[];
81
+ /** Vanilla folders the mod unloads wholesale (total conversions). */
82
+ replacePaths?: string[];
83
+ }
84
+
85
+ /** A launcher-correct starter metadata.json, in the corpus's field order. */
86
+ export function scaffoldMetadata(opts: MetadataScaffold): string {
87
+ const body: ModMetadata = {
88
+ name: opts.name,
89
+ id: opts.id,
90
+ version: opts.version ?? "0.1.0",
91
+ supported_game_version: opts.supportedGameVersion,
92
+ ...(opts.shortDescription ? { short_description: opts.shortDescription } : {}),
93
+ tags: opts.tags ?? [],
94
+ relationships: opts.relationships ?? [],
95
+ game_custom_data: {
96
+ multiplayer_synchronized: true,
97
+ ...(opts.replacePaths && opts.replacePaths.length > 0 ? { replace_paths: opts.replacePaths } : {}),
98
+ },
99
+ };
100
+ return JSON.stringify(body, null, 2) + "\n";
101
+ }