@amxts/config-core 0.1.0 → 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/src/ini.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  * part of the API: a TypeScript plugin reads a config with `load()` or
7
7
  * `read()`.
8
8
  */
9
- import * as fs from "~/fs";
9
+ import * as fs from "@amxts/core/fs";
10
10
  import { configPath, writeLines } from "./files";
11
11
  import { writeComments } from "./tree";
12
12
 
package/src/natives.ts CHANGED
@@ -1,271 +1,271 @@
1
- /**
2
- * Config Core for Pawn plugins: the 28 cfg_* natives of the original
3
- * universal_config.amxx, as include/universal_config.inc declares them.
4
- */
5
- import { Player, plugin, print, server } from "~/facade";
6
- import { console_print } from "~/natives";
7
- import { setBaseDir } from "./index";
8
- import * as ini from "./ini";
9
-
10
- plugin({ name: "Config Core", version: "0.1.0", author: "kukson777", description: "INI configs for plugins: the cfg_* natives", include: "universal_config.inc" });
11
-
12
- /** A loaded config file. */
13
- export enum ConfigFile {
14
- CFG_FILE_INVALID = -1,
15
- }
16
-
17
- /** A section of a loaded file. */
18
- export enum ConfigSection {
19
- CFG_SECTION_INVALID = -1,
20
- }
21
-
22
- /** What a key is: a `key = value` line or a `key = { ... }` block. */
23
- export enum EntryType {
24
- CFG_ENTRY_SIMPLE,
25
- CFG_ENTRY_BRACKET,
26
- }
27
-
28
- /** What a key holds: one value, a line of strings, or rows - one value is a line of one string. */
29
- export enum ContentType {
30
- CFG_CONTENT_SIMPLE,
31
- CFG_CONTENT_STRINGS,
32
- CFG_CONTENT_ENTRIES,
33
- }
34
-
35
- server.addEventListener("init", () => {
36
- console.log("[ConfigCore] Plugin initialized (v0.1.0)");
37
- });
38
-
39
- server.addCommand("dump_config", dumpConfig, { access: "Cvar", description: "Dumps all configurations" });
40
-
41
- /** Every loaded section and its entries: headings to the admin's console, entries to the server's, as the original does. */
42
- function dumpConfig(player: Player) {
43
- print(player, "Current Configuration Dump:", "console");
44
- for (const section of ini.dump()) {
45
- print(player, section.heading, "console");
46
- for (const line of section.lines) console_print(0, line);
47
- }
48
- }
49
-
50
- /**
51
- * Loads a config file from `configs/<base dir>/`; ".ini" is added when the
52
- * name has none. A file that is not there still gets a handle, empty.
53
- */
54
- export function cfg_load_file(fileName: string) {
55
- return ini.configHandle(ini.loadFile(fileName));
56
- }
57
-
58
- /** A section of a loaded file by its name, or CFG_SECTION_INVALID. */
59
- export function cfg_get_section(cfg: ConfigFile, sectionName: string) {
60
- const config = ini.configByHandle(cfg);
61
- const found = config != null ? ini.section(config, sectionName) : null;
62
- return found != null ? ini.sectionHandle(found) : -1;
63
- }
64
-
65
- /**
66
- * The value of a key, or of a path ("block/subkey"), into value[]; index is
67
- * the value's place in its line. false when there is none.
68
- */
69
- export function cfg_get_value(section: ConfigSection, key: string, index = 0) {
70
- const found = ini.sectionByHandle(section);
71
- return found != null ? ini.getValue(found, key, index) : null;
72
- }
73
-
74
- /** A value by a path: index is its place in the line, lineIndex the row of the block. */
75
- export function cfg_get_value_by_path(section: ConfigSection, path: string, index = 0, lineIndex = 0) {
76
- const found = ini.sectionByHandle(section);
77
- return found != null ? ini.getValueByPath(found, path, index, lineIndex) : null;
78
- }
79
-
80
- /** The whole number a key or path holds; 0 when there is none. */
81
- export function cfg_get_int(section: ConfigSection, key: string, index = 0) {
82
- const found = ini.sectionByHandle(section);
83
- return found != null ? ini.getInt(found, key, index) : 0;
84
- }
85
-
86
- /** The number a key or path holds; 0.0 when there is none. */
87
- export function cfg_get_float(section: ConfigSection, key: string, index = 0) {
88
- const found = ini.sectionByHandle(section);
89
- return found != null ? ini.getNumber(found, key, index) : 0;
90
- }
91
-
92
- /** true when the value is a whole number other than 0. */
93
- export function cfg_get_bool(section: ConfigSection, key: string, index = 0) {
94
- const found = ini.sectionByHandle(section);
95
- return found != null ? ini.getBoolean(found, key, index) : false;
96
- }
97
-
98
- /**
99
- * The words of a key's line (index: which line, when the key is there more
100
- * than once); for a block, every value of every row. The caller destroys the
101
- * array; Invalid_Array when there are no words.
102
- */
103
- export function cfg_get_value_array(section: ConfigSection, key: string, index = 0) {
104
- const found = ini.sectionByHandle(section);
105
- if (found == null) return null;
106
- return ini.getWords(found, key, index);
107
- }
108
-
109
- /** The numbers of value index as an array of Floats; the caller destroys it. Invalid_Array when there are none. */
110
- export function cfg_get_float_array(section: ConfigSection, key: string, index = 0) {
111
- const found = ini.sectionByHandle(section);
112
- if (found == null) return null;
113
- const numbers = ini.getNumbers(found, key, index);
114
- return numbers != null && numbers.length > 0 ? numbers : null;
115
- }
116
-
117
- /**
118
- * Every value of the line a path leads to (lineIndex: the row of a block), as
119
- * written. The caller destroys the array.
120
- */
121
- export function cfg_get_value_array_by_path(section: ConfigSection, path: string, index = 0, lineIndex = 0) {
122
- const found = ini.sectionByHandle(section);
123
- if (found == null) return null;
124
- return ini.getValues(found, path, index, lineIndex);
125
- }
126
-
127
- /** The section's keys in file order; Invalid_Array when it has none. */
128
- export function cfg_get_top_level_keys(section: ConfigSection) {
129
- const found = ini.sectionByHandle(section);
130
- if (found == null) return null;
131
- const keys = ini.keys(found);
132
- return keys.length > 0 ? keys : null;
133
- }
134
-
135
- /**
136
- * The whole section, as an array of three: the keys, the values (an array of
137
- * strings per key, "{block}" for a block) and [key, value] index pairs.
138
- */
139
- export function cfg_get_section_data(section: ConfigSection) {
140
- const found = ini.sectionByHandle(section);
141
- if (found == null) return null;
142
- const entries = ini.entries(found);
143
- if (entries.length == 0) return null;
144
-
145
- const pairs: number[][] = [];
146
- for (let i = 0; i < entries.length; i++) pairs.push([i, i]);
147
- const data: SectionData = {
148
- keys: entries.map(entry => entry.key),
149
- values: entries.map(entry => (entry.block ? ["{block}"] : entry.values)),
150
- pairs,
151
- };
152
- return data;
153
- }
154
-
155
- /** What cfg_get_section_data hands Pawn: an Array of these three, in this order. */
156
- interface SectionData {
157
- keys: string[];
158
- values: string[][];
159
- /** [key, value] index pairs. */
160
- pairs: number[][];
161
- }
162
-
163
- /** How many values a line has, rows a block has, or - for a key that is there more than once - how many times it is. */
164
- export function cfg_get_array_size(section: ConfigSection, key: string) {
165
- const found = ini.sectionByHandle(section);
166
- return found != null ? ini.size(found, key) : 0;
167
- }
168
-
169
- /** Sets a value; a key that is not there is made. For a block, lineIndex is the row. */
170
- export function cfg_set_value(section: ConfigSection, key: string, value: string, index = 0, lineIndex = 0) {
171
- const found = ini.sectionByHandle(section);
172
- return found != null ? ini.set(found, key, value, index, lineIndex) : false;
173
- }
174
-
175
- /** Sets a whole number. */
176
- export function cfg_set_int(section: ConfigSection, key: string, value: number, index = 0) {
177
- const found = ini.sectionByHandle(section);
178
- return found != null ? ini.setInt(found, key, value, index) : false;
179
- }
180
-
181
- /** Sets a number; it is written as it was given, 2.5 as "2.5". */
182
- export function cfg_set_float(section: ConfigSection, key: string, value: number, index = 0) {
183
- const found = ini.sectionByHandle(section);
184
- return found != null ? ini.setNumber(found, key, value, index) : false;
185
- }
186
-
187
- /** Sets 1 or 0. */
188
- export function cfg_set_bool(section: ConfigSection, key: string, value: boolean, index = 0) {
189
- const found = ini.sectionByHandle(section);
190
- return found != null ? ini.setBoolean(found, key, value, index) : false;
191
- }
192
-
193
- /** Removes every entry of the key; false when there was none. */
194
- export function cfg_delete_key(section: ConfigSection, key: string) {
195
- const found = ini.sectionByHandle(section);
196
- return found != null ? ini.remove(found, key) : false;
197
- }
198
-
199
- /** Whether the section has the key. */
200
- export function cfg_has_key(section: ConfigSection, key: string) {
201
- const found = ini.sectionByHandle(section);
202
- return found != null ? ini.has(found, key) : false;
203
- }
204
-
205
- /** A section of the file; one that is not there is made, in memory. */
206
- export function cfg_create_section(cfg: ConfigFile, sectionName: string) {
207
- const config = ini.configByHandle(cfg);
208
- return config != null ? ini.sectionHandle(ini.createSection(config, sectionName)) : -1;
209
- }
210
-
211
- /** Makes the key a line of values or a block; a key that is not there is made. */
212
- export function cfg_set_entry_type(section: ConfigSection, key: string, entryType: EntryType) {
213
- const kind = entryType == EntryType.CFG_ENTRY_BRACKET ? "block" : "value";
214
- const found = ini.sectionByHandle(section);
215
- if (found == null) return false;
216
- ini.setKind(found, key, kind);
217
- return true;
218
- }
219
-
220
- /** Says what the key holds; a key that is not there is made. */
221
- export function cfg_set_entry_content_type(section: ConfigSection, key: string, contentType: ContentType) {
222
- const content = contentType == ContentType.CFG_CONTENT_ENTRIES ? "entries" : "strings";
223
- const found = ini.sectionByHandle(section);
224
- if (found == null) return false;
225
- ini.setContent(found, key, content);
226
- return true;
227
- }
228
-
229
- /**
230
- * Writes one section to a file; the file's other sections are not in it.
231
- * With cfg = CFG_FILE_INVALID the section is looked for in every loaded file.
232
- */
233
- export function cfg_write_file(cfg: ConfigFile, fileName: string, sectionName: string) {
234
- const config = ini.configByHandle(cfg);
235
- // No file named: the section of that name in any file, the last one loaded.
236
- const found = config != null ? ini.section(config, sectionName) : ini.findSection(sectionName);
237
- return found != null && ini.writeSection(found, fileName);
238
- }
239
-
240
- /**
241
- * Saves every section of the file with the comments it was read with. The
242
- * file name has to be given: without one it returns false.
243
- */
244
- export function cfg_save_config(cfg: ConfigFile, fileName?: string) {
245
- const config = ini.configByHandle(cfg);
246
- return config != null && ini.saveFile(config, fileName ?? "");
247
- }
248
-
249
- /** The folder under configs/ that file names are relative to. */
250
- export function cfg_set_base_dir(dir: string) {
251
- setBaseDir(dir);
252
- }
253
-
254
- /** How many sections are loaded, across every file. */
255
- export function cfg_get_sections_count() {
256
- return ini.sectionCount();
257
- }
258
-
259
- /** A section's name by its number, 0 .. cfg_get_sections_count() - 1. */
260
- export function cfg_get_section_name(index: number) {
261
- return ini.sectionByHandle(index)?.name ?? null;
262
- }
263
-
264
- /**
265
- * The comment line written above row `row` of the block `key` - "; ID | VALUE",
266
- * say; "" removes it. false when there is no such block or row.
267
- */
268
- export function cfg_set_row_comment(section: ConfigSection, key: string, row: number, comment: string) {
269
- const found = ini.sectionByHandle(section);
270
- return found != null ? ini.setRowComment(found, key, row, comment) : false;
271
- }
1
+ /**
2
+ * Config Core for Pawn plugins: the 28 cfg_* natives of the original
3
+ * universal_config.amxx, as include/universal_config.inc declares them.
4
+ */
5
+ import { Player, plugin, print, server } from "@amxts/core";
6
+ import { console_print } from "@amxts/core/natives";
7
+ import { setBaseDir } from "./index";
8
+ import * as ini from "./ini";
9
+
10
+ plugin({ name: "Config Core", version: "0.1.2", author: "kukson777", description: "INI configs for plugins: the cfg_* natives", include: "universal_config.inc" });
11
+
12
+ /** A loaded config file. */
13
+ export enum ConfigFile {
14
+ CFG_FILE_INVALID = -1,
15
+ }
16
+
17
+ /** A section of a loaded file. */
18
+ export enum ConfigSection {
19
+ CFG_SECTION_INVALID = -1,
20
+ }
21
+
22
+ /** What a key is: a `key = value` line or a `key = { ... }` block. */
23
+ export enum EntryType {
24
+ CFG_ENTRY_SIMPLE,
25
+ CFG_ENTRY_BRACKET,
26
+ }
27
+
28
+ /** What a key holds: one value, a line of strings, or rows - one value is a line of one string. */
29
+ export enum ContentType {
30
+ CFG_CONTENT_SIMPLE,
31
+ CFG_CONTENT_STRINGS,
32
+ CFG_CONTENT_ENTRIES,
33
+ }
34
+
35
+ server.addEventListener("init", () => {
36
+ console.log("[ConfigCore] Plugin initialized (v0.1.2)");
37
+ });
38
+
39
+ server.addCommand("dump_config", ({ player }) => dumpConfig(player), { access: "cvar", description: "Dumps all configurations" });
40
+
41
+ /** Every loaded section and its entries: headings to the admin's console, entries to the server's, as the original does. */
42
+ function dumpConfig(player: Player) {
43
+ print(player, "Current Configuration Dump:", "console");
44
+ for (const section of ini.dump()) {
45
+ print(player, section.heading, "console");
46
+ for (const line of section.lines) console_print(0, line);
47
+ }
48
+ }
49
+
50
+ /**
51
+ * Loads a config file from `configs/<base dir>/`; ".ini" is added when the
52
+ * name has none. A file that is not there still gets a handle, empty.
53
+ */
54
+ export function cfg_load_file(fileName: string) {
55
+ return ini.configHandle(ini.loadFile(fileName));
56
+ }
57
+
58
+ /** A section of a loaded file by its name, or CFG_SECTION_INVALID. */
59
+ export function cfg_get_section(cfg: ConfigFile, sectionName: string) {
60
+ const config = ini.configByHandle(cfg);
61
+ const found = config != null ? ini.section(config, sectionName) : null;
62
+ return found != null ? ini.sectionHandle(found) : -1;
63
+ }
64
+
65
+ /**
66
+ * The value of a key, or of a path ("block/subkey"), into value[]; index is
67
+ * the value's place in its line. false when there is none.
68
+ */
69
+ export function cfg_get_value(section: ConfigSection, key: string, index = 0) {
70
+ const found = ini.sectionByHandle(section);
71
+ return found != null ? ini.getValue(found, key, index) : null;
72
+ }
73
+
74
+ /** A value by a path: index is its place in the line, lineIndex the row of the block. */
75
+ export function cfg_get_value_by_path(section: ConfigSection, path: string, index = 0, lineIndex = 0) {
76
+ const found = ini.sectionByHandle(section);
77
+ return found != null ? ini.getValueByPath(found, path, index, lineIndex) : null;
78
+ }
79
+
80
+ /** The whole number a key or path holds; 0 when there is none. */
81
+ export function cfg_get_int(section: ConfigSection, key: string, index = 0) {
82
+ const found = ini.sectionByHandle(section);
83
+ return found != null ? ini.getInt(found, key, index) : 0;
84
+ }
85
+
86
+ /** The number a key or path holds; 0.0 when there is none. */
87
+ export function cfg_get_float(section: ConfigSection, key: string, index = 0) {
88
+ const found = ini.sectionByHandle(section);
89
+ return found != null ? ini.getNumber(found, key, index) : 0;
90
+ }
91
+
92
+ /** true when the value is a whole number other than 0. */
93
+ export function cfg_get_bool(section: ConfigSection, key: string, index = 0) {
94
+ const found = ini.sectionByHandle(section);
95
+ return found != null ? ini.getBoolean(found, key, index) : false;
96
+ }
97
+
98
+ /**
99
+ * The words of a key's line (index: which line, when the key is there more
100
+ * than once); for a block, every value of every row. The caller destroys the
101
+ * array; Invalid_Array when there are no words.
102
+ */
103
+ export function cfg_get_value_array(section: ConfigSection, key: string, index = 0) {
104
+ const found = ini.sectionByHandle(section);
105
+ if (found == null) return null;
106
+ return ini.getWords(found, key, index);
107
+ }
108
+
109
+ /** The numbers of value index as an array of Floats; the caller destroys it. Invalid_Array when there are none. */
110
+ export function cfg_get_float_array(section: ConfigSection, key: string, index = 0) {
111
+ const found = ini.sectionByHandle(section);
112
+ if (found == null) return null;
113
+ const numbers = ini.getNumbers(found, key, index);
114
+ return numbers != null && numbers.length > 0 ? numbers : null;
115
+ }
116
+
117
+ /**
118
+ * Every value of the line a path leads to (lineIndex: the row of a block), as
119
+ * written. The caller destroys the array.
120
+ */
121
+ export function cfg_get_value_array_by_path(section: ConfigSection, path: string, index = 0, lineIndex = 0) {
122
+ const found = ini.sectionByHandle(section);
123
+ if (found == null) return null;
124
+ return ini.getValues(found, path, index, lineIndex);
125
+ }
126
+
127
+ /** The section's keys in file order; Invalid_Array when it has none. */
128
+ export function cfg_get_top_level_keys(section: ConfigSection) {
129
+ const found = ini.sectionByHandle(section);
130
+ if (found == null) return null;
131
+ const keys = ini.keys(found);
132
+ return keys.length > 0 ? keys : null;
133
+ }
134
+
135
+ /**
136
+ * The whole section, as an array of three: the keys, the values (an array of
137
+ * strings per key, "{block}" for a block) and [key, value] index pairs.
138
+ */
139
+ export function cfg_get_section_data(section: ConfigSection) {
140
+ const found = ini.sectionByHandle(section);
141
+ if (found == null) return null;
142
+ const entries = ini.entries(found);
143
+ if (entries.length == 0) return null;
144
+
145
+ const pairs: number[][] = [];
146
+ for (let i = 0; i < entries.length; i++) pairs.push([i, i]);
147
+ const data: SectionData = {
148
+ keys: entries.map(entry => entry.key),
149
+ values: entries.map(entry => (entry.block ? ["{block}"] : entry.values)),
150
+ pairs,
151
+ };
152
+ return data;
153
+ }
154
+
155
+ /** What cfg_get_section_data hands Pawn: an Array of these three, in this order. */
156
+ interface SectionData {
157
+ keys: string[];
158
+ values: string[][];
159
+ /** [key, value] index pairs. */
160
+ pairs: number[][];
161
+ }
162
+
163
+ /** How many values a line has, rows a block has, or - for a key that is there more than once - how many times it is. */
164
+ export function cfg_get_array_size(section: ConfigSection, key: string) {
165
+ const found = ini.sectionByHandle(section);
166
+ return found != null ? ini.size(found, key) : 0;
167
+ }
168
+
169
+ /** Sets a value; a key that is not there is made. For a block, lineIndex is the row. */
170
+ export function cfg_set_value(section: ConfigSection, key: string, value: string, index = 0, lineIndex = 0) {
171
+ const found = ini.sectionByHandle(section);
172
+ return found != null ? ini.set(found, key, value, index, lineIndex) : false;
173
+ }
174
+
175
+ /** Sets a whole number. */
176
+ export function cfg_set_int(section: ConfigSection, key: string, value: number, index = 0) {
177
+ const found = ini.sectionByHandle(section);
178
+ return found != null ? ini.setInt(found, key, value, index) : false;
179
+ }
180
+
181
+ /** Sets a number; it is written as it was given, 2.5 as "2.5". */
182
+ export function cfg_set_float(section: ConfigSection, key: string, value: number, index = 0) {
183
+ const found = ini.sectionByHandle(section);
184
+ return found != null ? ini.setNumber(found, key, value, index) : false;
185
+ }
186
+
187
+ /** Sets 1 or 0. */
188
+ export function cfg_set_bool(section: ConfigSection, key: string, value: boolean, index = 0) {
189
+ const found = ini.sectionByHandle(section);
190
+ return found != null ? ini.setBoolean(found, key, value, index) : false;
191
+ }
192
+
193
+ /** Removes every entry of the key; false when there was none. */
194
+ export function cfg_delete_key(section: ConfigSection, key: string) {
195
+ const found = ini.sectionByHandle(section);
196
+ return found != null ? ini.remove(found, key) : false;
197
+ }
198
+
199
+ /** Whether the section has the key. */
200
+ export function cfg_has_key(section: ConfigSection, key: string) {
201
+ const found = ini.sectionByHandle(section);
202
+ return found != null ? ini.has(found, key) : false;
203
+ }
204
+
205
+ /** A section of the file; one that is not there is made, in memory. */
206
+ export function cfg_create_section(cfg: ConfigFile, sectionName: string) {
207
+ const config = ini.configByHandle(cfg);
208
+ return config != null ? ini.sectionHandle(ini.createSection(config, sectionName)) : -1;
209
+ }
210
+
211
+ /** Makes the key a line of values or a block; a key that is not there is made. */
212
+ export function cfg_set_entry_type(section: ConfigSection, key: string, entryType: EntryType) {
213
+ const kind = entryType == EntryType.CFG_ENTRY_BRACKET ? "block" : "value";
214
+ const found = ini.sectionByHandle(section);
215
+ if (found == null) return false;
216
+ ini.setKind(found, key, kind);
217
+ return true;
218
+ }
219
+
220
+ /** Says what the key holds; a key that is not there is made. */
221
+ export function cfg_set_entry_content_type(section: ConfigSection, key: string, contentType: ContentType) {
222
+ const content = contentType == ContentType.CFG_CONTENT_ENTRIES ? "entries" : "strings";
223
+ const found = ini.sectionByHandle(section);
224
+ if (found == null) return false;
225
+ ini.setContent(found, key, content);
226
+ return true;
227
+ }
228
+
229
+ /**
230
+ * Writes one section to a file; the file's other sections are not in it.
231
+ * With cfg = CFG_FILE_INVALID the section is looked for in every loaded file.
232
+ */
233
+ export function cfg_write_file(cfg: ConfigFile, fileName: string, sectionName: string) {
234
+ const config = ini.configByHandle(cfg);
235
+ // No file named: the section of that name in any file, the last one loaded.
236
+ const found = config != null ? ini.section(config, sectionName) : ini.findSection(sectionName);
237
+ return found != null && ini.writeSection(found, fileName);
238
+ }
239
+
240
+ /**
241
+ * Saves every section of the file with the comments it was read with. The
242
+ * file name has to be given: without one it returns false.
243
+ */
244
+ export function cfg_save_config(cfg: ConfigFile, fileName?: string) {
245
+ const config = ini.configByHandle(cfg);
246
+ return config != null && ini.saveFile(config, fileName ?? "");
247
+ }
248
+
249
+ /** The folder under configs/ that file names are relative to. */
250
+ export function cfg_set_base_dir(dir: string) {
251
+ setBaseDir(dir);
252
+ }
253
+
254
+ /** How many sections are loaded, across every file. */
255
+ export function cfg_get_sections_count() {
256
+ return ini.sectionCount();
257
+ }
258
+
259
+ /** A section's name by its number, 0 .. cfg_get_sections_count() - 1. */
260
+ export function cfg_get_section_name(index: number) {
261
+ return ini.sectionByHandle(index)?.name ?? null;
262
+ }
263
+
264
+ /**
265
+ * The comment line written above row `row` of the block `key` - "; ID | VALUE",
266
+ * say; "" removes it. false when there is no such block or row.
267
+ */
268
+ export function cfg_set_row_comment(section: ConfigSection, key: string, row: number, comment: string) {
269
+ const found = ini.sectionByHandle(section);
270
+ return found != null ? ini.setRowComment(found, key, row, comment) : false;
271
+ }