tsondb 0.20.9 → 0.21.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/dist/src/node/index.js +4 -2
- package/dist/src/node/renderers/ts/render.d.ts +9 -0
- package/dist/src/node/renderers/ts/render.js +11 -5
- package/dist/src/node/schema/treeOperations/format.d.ts +1 -1
- package/dist/src/node/schema/treeOperations/format.js +47 -7
- package/dist/src/node/utils/files.js +1 -1
- package/package.json +1 -1
package/dist/src/node/index.js
CHANGED
|
@@ -294,6 +294,7 @@ export class TSONDB {
|
|
|
294
294
|
async checkFormat() {
|
|
295
295
|
debug("Check database formatting ...");
|
|
296
296
|
let counter = 0;
|
|
297
|
+
let total = 0;
|
|
297
298
|
await this.#data.forEachInstance(async (entityName, instance) => {
|
|
298
299
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
299
300
|
const entity = this.#schema.getEntity(entityName);
|
|
@@ -303,13 +304,14 @@ export class TSONDB {
|
|
|
303
304
|
console.log(`Instance ${styleText("yellow", instance.id)} of entity ${styleText("cyan", entityName)} is not formatted correctly.`);
|
|
304
305
|
counter++;
|
|
305
306
|
}
|
|
307
|
+
total++;
|
|
306
308
|
}, true);
|
|
307
309
|
if (counter === 0) {
|
|
308
|
-
console.log(styleText("green",
|
|
310
|
+
console.log(styleText("green", `All ${total.toFixed()} instance${total === 1 ? "" : "s"} are formatted correctly`));
|
|
309
311
|
return true;
|
|
310
312
|
}
|
|
311
313
|
else {
|
|
312
|
-
console.error(styleText("red", `${counter.toFixed()}
|
|
314
|
+
console.error(styleText("red", `${counter.toFixed()} instance${counter === 1 ? "" : "s"} of ${total.toFixed()} instance${total === 1 ? "" : "s"} are not formatted correctly`, {
|
|
313
315
|
stream: stderr,
|
|
314
316
|
}));
|
|
315
317
|
return false;
|
|
@@ -27,6 +27,15 @@ export type TypeScriptRendererOptions = {
|
|
|
27
27
|
*/
|
|
28
28
|
inferTranslationParameters?: {
|
|
29
29
|
format: "mf2";
|
|
30
|
+
/**
|
|
31
|
+
* The default type to use for translation parameters when the type cannot be inferred from the message string.
|
|
32
|
+
* @default "string"
|
|
33
|
+
*/
|
|
34
|
+
defaultTranslationParameterType?: "string" | "StringableTranslationParameter";
|
|
30
35
|
};
|
|
36
|
+
/**
|
|
37
|
+
* The generated type to use for Date types. The data is always stored as a string, but Date can be helpful if you need to differenciate between a string and a date in code. Defaults to `string`.
|
|
38
|
+
*/
|
|
39
|
+
dateType: "string" | "Date";
|
|
31
40
|
};
|
|
32
41
|
export declare const render: (options: Partial<TypeScriptRendererOptions> | undefined, declarations: readonly Decl[]) => string;
|
|
@@ -22,7 +22,9 @@ const defaultOptions = {
|
|
|
22
22
|
preserveFiles: false,
|
|
23
23
|
generateHelpers: {},
|
|
24
24
|
addIdentifierToEntities: false,
|
|
25
|
+
dateType: "string",
|
|
25
26
|
};
|
|
27
|
+
const defaultTranslationParameterType = "string";
|
|
26
28
|
const renderDocumentation = (comment, isDeprecated) => syntax `${comment === undefined
|
|
27
29
|
? ""
|
|
28
30
|
: syntax `/**
|
|
@@ -55,7 +57,7 @@ const renderObjectType = (options, type) => {
|
|
|
55
57
|
.map(([name, config]) => syntax `${renderDocumentation(config.comment, config.isDeprecated)}${name}${config.isRequired ? "" : "?"}: ${renderType(options, config.type)}`), Object.values(type.properties).some(prop => prop.comment !== undefined) ? EOL + EOL : EOL));
|
|
56
58
|
};
|
|
57
59
|
const renderBooleanType = (_options, _type) => syntax `boolean`;
|
|
58
|
-
const renderDateType = (
|
|
60
|
+
const renderDateType = (options, _type) => options.dateType === "Date" ? syntax `Date` : syntax `string`;
|
|
59
61
|
const renderFloatType = (_options, _type) => syntax `number`;
|
|
60
62
|
const renderIntegerType = (_options, _type) => syntax `number`;
|
|
61
63
|
const renderStringType = (_options, _type) => syntax `string`;
|
|
@@ -75,7 +77,7 @@ const renderEnumType = (options, type) => combineSyntaxes(Object.entries(type.va
|
|
|
75
77
|
? ""
|
|
76
78
|
: syntax `${EOL}${caseName}: ${renderType(options, caseDef.type)}`}`)}${EOL}}`)));
|
|
77
79
|
const renderChildEntitiesType = () => syntax `never`;
|
|
78
|
-
const mapTypeNameToType = (typeName) => {
|
|
80
|
+
const mapTypeNameToType = (options, typeName) => {
|
|
79
81
|
switch (typeName) {
|
|
80
82
|
case "string":
|
|
81
83
|
return "string";
|
|
@@ -88,7 +90,8 @@ const mapTypeNameToType = (typeName) => {
|
|
|
88
90
|
return "Date";
|
|
89
91
|
case null:
|
|
90
92
|
default:
|
|
91
|
-
return
|
|
93
|
+
return (options.inferTranslationParameters?.defaultTranslationParameterType ??
|
|
94
|
+
defaultTranslationParameterType);
|
|
92
95
|
}
|
|
93
96
|
};
|
|
94
97
|
const renderTranslationParameterBrand = (options, params) => {
|
|
@@ -102,7 +105,7 @@ const renderTranslationParameterBrand = (options, params) => {
|
|
|
102
105
|
return syntax ` & { __params: { ${entries.map(([name, type]) => `"${name}": ${type}`).join("; ")} } }`;
|
|
103
106
|
};
|
|
104
107
|
const renderTranslationObjectType = (options, type) => {
|
|
105
|
-
return wrapAsObject(options, combineSyntaxes(Object.entries(type.properties).map(([name, config]) => syntax `"${name.replace('"', '\\"')}"${type.allKeysAreRequired ? "" : "?"}: ${renderType(options, getTypeOfKey(config, type))}${renderTranslationParameterBrand(options, mapParameterTypeNames(extractParameterTypeNamesFromMessage(name), mapTypeNameToType))}`), EOL));
|
|
108
|
+
return wrapAsObject(options, combineSyntaxes(Object.entries(type.properties).map(([name, config]) => syntax `"${name.replace('"', '\\"')}"${type.allKeysAreRequired ? "" : "?"}: ${renderType(options, getTypeOfKey(config, type))}${renderTranslationParameterBrand(options, mapParameterTypeNames(extractParameterTypeNamesFromMessage(name), typeName => mapTypeNameToType(options, typeName)))}`), EOL));
|
|
106
109
|
};
|
|
107
110
|
const renderType = (options, type) => {
|
|
108
111
|
switch (type.kind) {
|
|
@@ -187,7 +190,10 @@ const renderEntityMapType = (options, declarations) => renderMapHelperType(optio
|
|
|
187
190
|
const renderChildEntityMapType = (options, declarations) => renderMapHelperType(options, declarations, "childEntityMap", "ChildEntityMap", decl => isEntityDecl(decl) && isEntityDeclWithParentReference(decl), decl => `${decl.name}: [${decl.name}, "${decl.parentReferenceKey}", ${decl.name}["${decl.parentReferenceKey}"]]`);
|
|
188
191
|
const renderEnumMapType = (options, declarations) => renderMapHelperType(options, declarations, "enumMap", "EnumMap", isEnumDecl);
|
|
189
192
|
const renderTypeAliasMapType = (options, declarations) => renderMapHelperType(options, declarations, "typeAliasMap", "TypeAliasMap", isTypeAliasDecl);
|
|
190
|
-
const renderStringableTranslationParameterType = (options) => options.inferTranslationParameters?.format === "mf2"
|
|
193
|
+
const renderStringableTranslationParameterType = (options) => options.inferTranslationParameters?.format === "mf2" &&
|
|
194
|
+
(options.inferTranslationParameters.defaultTranslationParameterType === undefined ||
|
|
195
|
+
options.inferTranslationParameters.defaultTranslationParameterType ===
|
|
196
|
+
"StringableTranslationParameter")
|
|
191
197
|
? "export type StringableTranslationParameter = {" +
|
|
192
198
|
EOL +
|
|
193
199
|
prefixLines(getIndentation(options.indentation, 1), "toString(): string") +
|
|
@@ -3,4 +3,4 @@ import type { Type } from "../dsl/index.ts";
|
|
|
3
3
|
/**
|
|
4
4
|
* Format the structure of a value to always look the same when serialized as JSON.
|
|
5
5
|
*/
|
|
6
|
-
export declare const formatValue: (type: Type, value: unknown, options: Partial<FormatterOptions> | undefined) => unknown;
|
|
6
|
+
export declare const formatValue: (type: Type, value: unknown, typeArguments: Record<string, Type>, options: Partial<FormatterOptions> | undefined) => unknown;
|
|
@@ -9,24 +9,56 @@ const formatTranslationObjectValue = (type, value) => typeof value === "object"
|
|
|
9
9
|
type[key] ? formatTranslationObjectValue(type[key], item) : item,
|
|
10
10
|
])), Object.keys(type))
|
|
11
11
|
: value;
|
|
12
|
+
const resolveNestedTypeArguments = (type, typeArguments) => {
|
|
13
|
+
switch (type.kind) {
|
|
14
|
+
case NodeKind.TypeArgumentType:
|
|
15
|
+
return typeArguments[type.argument.name] ?? type;
|
|
16
|
+
case NodeKind.IncludeIdentifierType:
|
|
17
|
+
return {
|
|
18
|
+
...type,
|
|
19
|
+
args: type.args.map(arg => resolveNestedTypeArguments(arg, typeArguments)),
|
|
20
|
+
};
|
|
21
|
+
case NodeKind.ArrayType:
|
|
22
|
+
case NodeKind.BooleanType:
|
|
23
|
+
case NodeKind.ChildEntitiesType:
|
|
24
|
+
case NodeKind.DateType:
|
|
25
|
+
case NodeKind.EnumType:
|
|
26
|
+
case NodeKind.FloatType:
|
|
27
|
+
case NodeKind.IntegerType:
|
|
28
|
+
case NodeKind.NestedEntityMapType:
|
|
29
|
+
case NodeKind.ObjectType:
|
|
30
|
+
case NodeKind.ReferenceIdentifierType:
|
|
31
|
+
case NodeKind.StringType:
|
|
32
|
+
case NodeKind.TranslationObjectType:
|
|
33
|
+
return type;
|
|
34
|
+
default:
|
|
35
|
+
return assertExhaustive(type);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
12
38
|
/**
|
|
13
39
|
* Format the structure of a value to always look the same when serialized as JSON.
|
|
14
40
|
*/
|
|
15
|
-
export const formatValue = (type, value, options) => {
|
|
41
|
+
export const formatValue = (type, value, typeArguments, options) => {
|
|
16
42
|
switch (type.kind) {
|
|
17
43
|
case NodeKind.ArrayType:
|
|
18
44
|
return Array.isArray(value)
|
|
19
|
-
? value.map(item => formatValue(type.items, item, options))
|
|
45
|
+
? value.map(item => formatValue(type.items, item, typeArguments, options))
|
|
20
46
|
: value;
|
|
21
47
|
case NodeKind.ObjectType:
|
|
22
48
|
return typeof value === "object" && value !== null && !Array.isArray(value)
|
|
23
|
-
? sortObjectKeysByIndex(mapObject(value, (item, key) => type.properties[key]
|
|
49
|
+
? sortObjectKeysByIndex(mapObject(value, (item, key) => type.properties[key]
|
|
50
|
+
? formatValue(type.properties[key].type, item, typeArguments, options)
|
|
51
|
+
: item), Object.keys(type.properties))
|
|
24
52
|
: value;
|
|
25
53
|
case NodeKind.IncludeIdentifierType:
|
|
26
|
-
return formatValue(type.reference.type.value, value,
|
|
54
|
+
return formatValue(type.reference.type.value, value, Object.fromEntries(type.args.map((arg, index) => [
|
|
55
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
56
|
+
type.reference.parameters[index].name,
|
|
57
|
+
resolveNestedTypeArguments(arg, typeArguments),
|
|
58
|
+
])), options);
|
|
27
59
|
case NodeKind.NestedEntityMapType:
|
|
28
60
|
return typeof value === "object" && value !== null && !Array.isArray(value)
|
|
29
|
-
? sortObjectKeys(mapObject(value, item => formatValue(type.type.value, item, options)))
|
|
61
|
+
? sortObjectKeys(mapObject(value, item => formatValue(type.type.value, item, typeArguments, options)))
|
|
30
62
|
: value;
|
|
31
63
|
case NodeKind.EnumType: {
|
|
32
64
|
if (typeof value === "object" &&
|
|
@@ -41,7 +73,7 @@ export const formatValue = (type, value, options) => {
|
|
|
41
73
|
[ENUM_DISCRIMINATOR_KEY]: caseName,
|
|
42
74
|
...(caseValue == null || caseType == null
|
|
43
75
|
? {}
|
|
44
|
-
: { [caseName]: formatValue(caseType, caseValue, options) }),
|
|
76
|
+
: { [caseName]: formatValue(caseType, caseValue, typeArguments, options) }),
|
|
45
77
|
};
|
|
46
78
|
}
|
|
47
79
|
return value;
|
|
@@ -65,11 +97,19 @@ export const formatValue = (type, value, options) => {
|
|
|
65
97
|
return value;
|
|
66
98
|
}
|
|
67
99
|
}
|
|
100
|
+
case NodeKind.TypeArgumentType: {
|
|
101
|
+
const typeArgument = typeArguments[type.argument.name];
|
|
102
|
+
if (typeArgument === undefined) {
|
|
103
|
+
return value;
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
return formatValue(typeArgument, value, typeArguments, options);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
68
109
|
case NodeKind.BooleanType:
|
|
69
110
|
case NodeKind.DateType:
|
|
70
111
|
case NodeKind.FloatType:
|
|
71
112
|
case NodeKind.IntegerType:
|
|
72
|
-
case NodeKind.TypeArgumentType:
|
|
73
113
|
case NodeKind.ReferenceIdentifierType:
|
|
74
114
|
return value;
|
|
75
115
|
default:
|
|
@@ -11,4 +11,4 @@ export const writeInstance = (dataRoot, entity, id, instance, formatterOptions)
|
|
|
11
11
|
encoding: "utf-8",
|
|
12
12
|
});
|
|
13
13
|
export const deleteInstance = (dataRoot, entityName, id) => rm(getPathToInstance(dataRoot, entityName, id));
|
|
14
|
-
export const formatInstance = (entity, instanceContent, options) => JSON.stringify(formatValue(entity.type.value, instanceContent, options), undefined, 2) + "\n";
|
|
14
|
+
export const formatInstance = (entity, instanceContent, options) => JSON.stringify(formatValue(entity.type.value, instanceContent, {}, options), undefined, 2) + "\n";
|