config2ts 2.5.4 → 2.5.6
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 +4 -0
- package/lib/config2ts.js +58 -28
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -27,6 +27,7 @@ config2ts -d config -o dist -n csv.ts -a public
|
|
|
27
27
|
| RefEnum | namespace.type |
|
|
28
28
|
| RefEnum[] | namespace.type[] |
|
|
29
29
|
| Object | type (Record) |
|
|
30
|
+
| Object[] | type[] (Record[]) |
|
|
30
31
|
|
|
31
32
|
* `Number` support Infinity and NaN
|
|
32
33
|
* `Enum` support empty string type
|
|
@@ -34,6 +35,9 @@ config2ts -d config -o dist -n csv.ts -a public
|
|
|
34
35
|
* `EnumIndex` will generate index type, and will use `Enum` type to generate interface
|
|
35
36
|
* `Ref` / `RefEnum` reference another csv's Record/type by id
|
|
36
37
|
* `Object` parse `key:value,key:value` format, auto-infer value types (number/boolean/string), generates a dedicated `type` that merges all keys
|
|
38
|
+
* `Object[]` parse `key:value,key:value;key:value,key:value` format (`;` separates objects, `,` separates key-value pairs), empty value generates `[]`, generates a dedicated element `type` with the field typed as `type[]`
|
|
39
|
+
* Array empty-data convention (`String[]`/`Number[]`/`Enum[]`/`RefEnum[...] []`/`Object[]`): an empty cell generates `[]`; empty segments from stray, leading or trailing separators (e.g. `"a,,b"`, `"1,,3"`, `"x:1;;y:2"`) are skipped — no phantom `""`, `0` or `{}` elements
|
|
40
|
+
* unrecognized field types fall back to `string` and print a warning (check for typos)
|
|
37
41
|
|
|
38
42
|
## assets2ts
|
|
39
43
|
|
package/lib/config2ts.js
CHANGED
|
@@ -50,6 +50,7 @@ const EnumIndexStr = "EnumIndex";
|
|
|
50
50
|
const EnumArrayString = "Enum[]";
|
|
51
51
|
const IndexStr = "Index";
|
|
52
52
|
const ObjectStr = "Object";
|
|
53
|
+
const ObjectArrayString = "Object[]";
|
|
53
54
|
const RefPrefix = "Ref[";
|
|
54
55
|
const RefSuffix = "]";
|
|
55
56
|
const RefEnumPrefix = "RefEnum[";
|
|
@@ -82,6 +83,9 @@ function csv2ts(csvString, moduleName) {
|
|
|
82
83
|
if (parseRefEnum(convert[k])) {
|
|
83
84
|
refEnumFields.push(k);
|
|
84
85
|
}
|
|
86
|
+
if (!isKnownType(convert[k])) {
|
|
87
|
+
console.warn(`[config2ts] warning: ${moduleName} field "${k}" has unrecognized type "${convert[k]}", values will be treated as string`);
|
|
88
|
+
}
|
|
85
89
|
}
|
|
86
90
|
return null;
|
|
87
91
|
}
|
|
@@ -90,27 +94,17 @@ function csv2ts(csvString, moduleName) {
|
|
|
90
94
|
if (convert[k] === ObjectStr) {
|
|
91
95
|
d[k] = parseObject(d[k]);
|
|
92
96
|
}
|
|
97
|
+
else if (convert[k] === ObjectArrayString) {
|
|
98
|
+
d[k] = parseObjectArray(d[k]);
|
|
99
|
+
}
|
|
93
100
|
else if (typeof global[convert[k]] === "function") {
|
|
94
101
|
d[k] = global[convert[k]](d[k]);
|
|
95
102
|
}
|
|
96
|
-
else if (convert[k] === "String[]") {
|
|
97
|
-
|
|
98
|
-
d[k] = [];
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
d[k] = d[k].trim().split(",").map((v) => v.trim());
|
|
102
|
-
}
|
|
103
|
+
else if (convert[k] === "String[]" || convert[k] === "Enum[]") {
|
|
104
|
+
d[k] = splitArrayValues(d[k]);
|
|
103
105
|
}
|
|
104
106
|
else if (convert[k] === "Number[]") {
|
|
105
|
-
d[k] = d[k]
|
|
106
|
-
}
|
|
107
|
-
else if (convert[k] === "Enum[]") {
|
|
108
|
-
if (d[k] === "") {
|
|
109
|
-
d[k] = [];
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
d[k] = d[k].trim().split(",").map((v) => v.trim());
|
|
113
|
-
}
|
|
107
|
+
d[k] = splitArrayValues(d[k]).map((val) => Number(val));
|
|
114
108
|
}
|
|
115
109
|
else if (convert[k].startsWith(RefPrefix) && convert[k].endsWith(RefSuffix)) {
|
|
116
110
|
if (d[k] === "") {
|
|
@@ -120,12 +114,7 @@ function csv2ts(csvString, moduleName) {
|
|
|
120
114
|
else if (parseRefEnum(convert[k])) {
|
|
121
115
|
const refEnum = parseRefEnum(convert[k]);
|
|
122
116
|
if (refEnum.isArray) {
|
|
123
|
-
|
|
124
|
-
d[k] = [];
|
|
125
|
-
}
|
|
126
|
-
else {
|
|
127
|
-
d[k] = d[k].trim().split(",").map((v) => v.trim());
|
|
128
|
-
}
|
|
117
|
+
d[k] = splitArrayValues(d[k]);
|
|
129
118
|
}
|
|
130
119
|
else {
|
|
131
120
|
if (d[k] === "") {
|
|
@@ -172,15 +161,18 @@ function csv2ts(csvString, moduleName) {
|
|
|
172
161
|
template += ` export type ${field} = ${enumValueStrings.join(" | ")};\n`;
|
|
173
162
|
template += ` export const ${field}List: ${field}[] = [${enumValueStrings.join(", ")}];\n\n`;
|
|
174
163
|
}
|
|
175
|
-
else if (convert[field] == ObjectStr) {
|
|
164
|
+
else if (convert[field] == ObjectStr || convert[field] == ObjectArrayString) {
|
|
176
165
|
const keyTypes = {};
|
|
166
|
+
const isArray = convert[field] == ObjectArrayString;
|
|
177
167
|
for (const row of result) {
|
|
178
|
-
const
|
|
179
|
-
for (const
|
|
180
|
-
|
|
181
|
-
keyTypes[key]
|
|
168
|
+
const objValues = isArray ? row[field] : [row[field]];
|
|
169
|
+
for (const objValue of objValues) {
|
|
170
|
+
for (const key in objValue) {
|
|
171
|
+
if (!keyTypes[key]) {
|
|
172
|
+
keyTypes[key] = new Set();
|
|
173
|
+
}
|
|
174
|
+
keyTypes[key].add(getTypeName(objValue[key]));
|
|
182
175
|
}
|
|
183
|
-
keyTypes[key].add(getTypeName(objValue[key]));
|
|
184
176
|
}
|
|
185
177
|
}
|
|
186
178
|
template += ` export type ${field} = {\n`;
|
|
@@ -212,6 +204,9 @@ function csv2ts(csvString, moduleName) {
|
|
|
212
204
|
else if (convert[field] == ObjectStr) {
|
|
213
205
|
fieldType = field;
|
|
214
206
|
}
|
|
207
|
+
else if (convert[field] == ObjectArrayString) {
|
|
208
|
+
fieldType = field + "[]";
|
|
209
|
+
}
|
|
215
210
|
else if (convert[field].startsWith(RefPrefix) && convert[field].endsWith(RefSuffix)) {
|
|
216
211
|
const refModule = convert[field].slice(RefPrefix.length, -RefSuffix.length);
|
|
217
212
|
const refModuleName = changeCase.pascalCase(refModule);
|
|
@@ -291,6 +286,22 @@ function parseObject(str) {
|
|
|
291
286
|
}
|
|
292
287
|
return result;
|
|
293
288
|
}
|
|
289
|
+
function parseObjectArray(str) {
|
|
290
|
+
return str
|
|
291
|
+
.split(";")
|
|
292
|
+
.map((part) => part.trim())
|
|
293
|
+
.filter((part) => part !== "")
|
|
294
|
+
.map((part) => parseObject(part));
|
|
295
|
+
}
|
|
296
|
+
// Split a comma-separated array cell, trimming and dropping empty segments
|
|
297
|
+
// so stray/leading/trailing commas never produce phantom elements.
|
|
298
|
+
// An empty cell resolves to an empty array.
|
|
299
|
+
function splitArrayValues(str) {
|
|
300
|
+
return str
|
|
301
|
+
.split(",")
|
|
302
|
+
.map((v) => v.trim())
|
|
303
|
+
.filter((v) => v !== "");
|
|
304
|
+
}
|
|
294
305
|
function parseObjectValue(value) {
|
|
295
306
|
if (value === "true")
|
|
296
307
|
return true;
|
|
@@ -311,6 +322,25 @@ function getTypeName(value) {
|
|
|
311
322
|
return "boolean";
|
|
312
323
|
return "string";
|
|
313
324
|
}
|
|
325
|
+
function isKnownType(typeStr) {
|
|
326
|
+
if (typeStr === "") {
|
|
327
|
+
return true;
|
|
328
|
+
}
|
|
329
|
+
const knownTypes = [EnumStr, EnumIndexStr, EnumArrayString, IndexStr, ObjectStr, ObjectArrayString, "String[]", "Number[]"];
|
|
330
|
+
if (knownTypes.includes(typeStr)) {
|
|
331
|
+
return true;
|
|
332
|
+
}
|
|
333
|
+
if (typeStr.startsWith(RefPrefix) && typeStr.endsWith(RefSuffix)) {
|
|
334
|
+
return true;
|
|
335
|
+
}
|
|
336
|
+
if (parseRefEnum(typeStr)) {
|
|
337
|
+
return true;
|
|
338
|
+
}
|
|
339
|
+
if (typeof global[typeStr] === "function") {
|
|
340
|
+
return true;
|
|
341
|
+
}
|
|
342
|
+
return false;
|
|
343
|
+
}
|
|
314
344
|
function parseRefEnum(typeStr) {
|
|
315
345
|
if (typeStr.startsWith(RefEnumPrefix)) {
|
|
316
346
|
let isArray = false;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "config2ts",
|
|
3
|
-
"version": "2.5.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.5.6",
|
|
4
|
+
"description": "Generate type-safe TypeScript from CSV/INI/TOML config tables — inferred types, enums, cross-table references, and a typed asset index, all from one CLI command.",
|
|
5
5
|
"main": "lib/config2ts.js",
|
|
6
6
|
"types": "lib/config2ts.d.ts",
|
|
7
7
|
"bin": {
|