@deterministic-code/datasources-cli 0.1.4 → 0.1.5
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/generate/RepositoryPlan.js +12 -7
- package/node_modules/@deterministic-code/datasources-code-generators/package.json +7 -7
- package/node_modules/@deterministic-code/deterministic-generators-common/typescript/parser/dist/specification-parser.js +8 -3
- package/node_modules/@deterministic-code/deterministic-generators-common/typescript/parser/parser/specification-parser.ts +7 -4
- package/node_modules/@deterministic-code/deterministic-generators-common/typescript/parser/specification.ts +1 -1
- package/node_modules/@deterministic-code/deterministic-generators-common/typescript/parser/yaml-node.ts +12 -0
- package/node_modules/@deterministic-code/generators-common/dist/spec-types.d.ts +1 -1
- package/node_modules/@deterministic-code/generators-common/dist/spec-types.js +22 -14
- package/node_modules/@deterministic-code/generators-common/src/spec-types.ts +24 -22
- package/package.json +8 -8
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createCasingStrategy } from "@deterministic-code/generators-common/casing-strategy";
|
|
2
2
|
import { createDatasourceNaming } from "@deterministic-code/generators-common/datasource-naming";
|
|
3
|
-
import { identityColumns, isCollectionField,
|
|
3
|
+
import { identityColumns, isCollectionField, persistedColumnFields } from "@deterministic-code/generators-common/spec-types";
|
|
4
4
|
const referenceOf = (references) => {
|
|
5
5
|
if (references === void 0) return void 0;
|
|
6
6
|
const [type, field] = [references].flat().join(".").split(".");
|
|
@@ -55,7 +55,7 @@ const planRepositories = (spec, dialect, settings) => {
|
|
|
55
55
|
const tableType = expanded.get(table.name) ?? types.get(table.name) ?? full;
|
|
56
56
|
const overlays = new Map(table.fields.map((field) => [field.name, field]));
|
|
57
57
|
const projected = new Set(Object.values(authored.mapping ?? {}));
|
|
58
|
-
const columns =
|
|
58
|
+
const columns = persistedColumnFields(tableType, expanded).filter((field) => !projected.has(field.name));
|
|
59
59
|
return [
|
|
60
60
|
{
|
|
61
61
|
specName: authored.name,
|
|
@@ -101,16 +101,21 @@ const relations = (authored, full, casing, types, expanded, repoName, identity)
|
|
|
101
101
|
if (!isCollectionField(field)) continue;
|
|
102
102
|
if (field.isMap === true) {
|
|
103
103
|
const dict = expanded.get(field.base) ?? types.get(field.base);
|
|
104
|
-
const owner =
|
|
104
|
+
const owner = referenceOf(field.references);
|
|
105
105
|
if (dict === void 0 || owner === void 0) continue;
|
|
106
|
-
const via = named(
|
|
106
|
+
const via = named(owner.type);
|
|
107
107
|
const value = dict.fields.find((item) => item.name === "value");
|
|
108
|
-
const nested = value
|
|
108
|
+
const nested = value !== void 0 && value.kind === "type" && !value.isArray && value.isMap !== true ? expanded.get(value.base) ?? types.get(value.base) : void 0;
|
|
109
|
+
const roleColumn = (role) => {
|
|
110
|
+
const item = dict.fields.find((entry) => entry.name === role);
|
|
111
|
+
const ref2 = referenceOf(item?.references);
|
|
112
|
+
return ref2?.type === owner.type ? ref2.field : role;
|
|
113
|
+
};
|
|
109
114
|
planned.push({
|
|
110
115
|
destination: property(field.name),
|
|
111
116
|
source,
|
|
112
|
-
relatedKey: property(owner.
|
|
113
|
-
relatedProperty: nested === void 0 ? property("value") : void 0,
|
|
117
|
+
relatedKey: property(owner.field),
|
|
118
|
+
relatedProperty: nested === void 0 ? property(roleColumn("value")) : void 0,
|
|
114
119
|
kind: "dictionary",
|
|
115
120
|
via: via.via,
|
|
116
121
|
viaType: via.viaType
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deterministic-code/datasources-code-generators",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dist/generateSql.js",
|
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
"./sql/dialect-converters": "./dist/sql/dialect-converters.js"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@deterministic-code/datasources": "^0.1.
|
|
14
|
-
"@deterministic-code/datasources-mysql": "^0.1.
|
|
15
|
-
"@deterministic-code/datasources-oracle": "^0.1.
|
|
16
|
-
"@deterministic-code/datasources-postgres": "^0.1.
|
|
17
|
-
"@deterministic-code/datasources-sqlite": "^0.1.
|
|
18
|
-
"@deterministic-code/datasources-sqlserver": "^0.1.
|
|
13
|
+
"@deterministic-code/datasources": "^0.1.5",
|
|
14
|
+
"@deterministic-code/datasources-mysql": "^0.1.5",
|
|
15
|
+
"@deterministic-code/datasources-oracle": "^0.1.5",
|
|
16
|
+
"@deterministic-code/datasources-postgres": "^0.1.5",
|
|
17
|
+
"@deterministic-code/datasources-sqlite": "^0.1.5",
|
|
18
|
+
"@deterministic-code/datasources-sqlserver": "^0.1.5",
|
|
19
19
|
"@deterministic-code/deterministic-generators-common": "0.1.0",
|
|
20
20
|
"@deterministic-code/generators-common": "0.0.1",
|
|
21
21
|
"pluralize": "^8.0.0",
|
|
@@ -488,7 +488,10 @@ var isMap = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
|
488
488
|
var isString = (v) => typeof v === "string";
|
|
489
489
|
var isFiniteNumber = (v) => typeof v === "number" && Number.isFinite(v);
|
|
490
490
|
var isFiniteInt = (v) => isFiniteNumber(v) && Number.isInteger(v);
|
|
491
|
+
var isEmptyList = (v) => Array.isArray(v) && v.length === 0;
|
|
492
|
+
var isEmptyMap = (v) => isMap(v) && Object.keys(v).length === 0;
|
|
491
493
|
var isLiteral = (v) => v === null || typeof v === "string" || typeof v === "number" || typeof v === "boolean";
|
|
494
|
+
var isFieldDefault = (v) => isLiteral(v) || isEmptyList(v) || isEmptyMap(v);
|
|
492
495
|
var yamlNode = (value, path = "$") => {
|
|
493
496
|
const record = isMap(value) ? value : void 0;
|
|
494
497
|
const at = (key) => record?.[key];
|
|
@@ -509,6 +512,7 @@ var yamlNode = (value, path = "$") => {
|
|
|
509
512
|
finiteNumber: pick(isFiniteNumber),
|
|
510
513
|
finiteInt: pick(isFiniteInt),
|
|
511
514
|
literal: pick(isLiteral),
|
|
515
|
+
fieldDefault: pick(isFieldDefault),
|
|
512
516
|
strings: (key) => {
|
|
513
517
|
const v = at(key);
|
|
514
518
|
return Array.isArray(v) ? v.filter(isString) : [];
|
|
@@ -614,7 +618,7 @@ var Parser = class {
|
|
|
614
618
|
constructor(reader) {
|
|
615
619
|
this.#reader = reader;
|
|
616
620
|
}
|
|
617
|
-
async parse(
|
|
621
|
+
async parse(_settings, opts) {
|
|
618
622
|
const reader = this.#reader;
|
|
619
623
|
const serviceClassName = opts?.serviceClassName ?? ((entity) => entity);
|
|
620
624
|
const [hasTypes, hasDs, hasSeeds, hasServices, hasRoutes] = await Promise.all([
|
|
@@ -693,6 +697,7 @@ var Parser = class {
|
|
|
693
697
|
const references = referencesOf(node);
|
|
694
698
|
const size = sizeOf(node);
|
|
695
699
|
const minSize = node.finiteInt("min_size");
|
|
700
|
+
const collectionDefault = parsed.isArray ? [] : parsed.isMap ? {} : void 0;
|
|
696
701
|
return {
|
|
697
702
|
name,
|
|
698
703
|
type: rawType,
|
|
@@ -705,7 +710,7 @@ var Parser = class {
|
|
|
705
710
|
...size !== void 0 ? { size } : {},
|
|
706
711
|
...minSize !== void 0 ? { minSize } : {},
|
|
707
712
|
...references !== void 0 ? { references } : {},
|
|
708
|
-
...node.has("default_value") ? { hasDefault: true, defaultValue: node.
|
|
713
|
+
...node.has("default_value") ? { hasDefault: true, defaultValue: node.fieldDefault("default_value") } : collectionDefault !== void 0 ? { hasDefault: true, defaultValue: collectionDefault } : {}
|
|
709
714
|
};
|
|
710
715
|
}
|
|
711
716
|
#parseDatasource(yaml, types) {
|
|
@@ -1105,7 +1110,7 @@ var Parser = class {
|
|
|
1105
1110
|
}
|
|
1106
1111
|
}
|
|
1107
1112
|
}
|
|
1108
|
-
#extractCustomRoutes(root,
|
|
1113
|
+
#extractCustomRoutes(root, _dsByName, typeByName) {
|
|
1109
1114
|
const customs = [];
|
|
1110
1115
|
for (const entry of root.child("routes").items()) {
|
|
1111
1116
|
if (entry.record === void 0) continue;
|
|
@@ -179,7 +179,7 @@ class Parser {
|
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
async parse(
|
|
182
|
-
|
|
182
|
+
_settings: Record<string, string>,
|
|
183
183
|
opts?: { serviceClassName?: (entity: string) => string },
|
|
184
184
|
): Promise<IDeterministic> {
|
|
185
185
|
const reader = this.#reader;
|
|
@@ -285,6 +285,7 @@ class Parser {
|
|
|
285
285
|
const references = referencesOf(node);
|
|
286
286
|
const size = sizeOf(node);
|
|
287
287
|
const minSize = node.finiteInt("min_size");
|
|
288
|
+
const collectionDefault = parsed.isArray ? [] : parsed.isMap ? {} : undefined;
|
|
288
289
|
return {
|
|
289
290
|
name,
|
|
290
291
|
type: rawType,
|
|
@@ -298,8 +299,10 @@ class Parser {
|
|
|
298
299
|
...(minSize !== undefined ? { minSize } : {}),
|
|
299
300
|
...(references !== undefined ? { references } : {}),
|
|
300
301
|
...(node.has("default_value")
|
|
301
|
-
? { hasDefault: true, defaultValue: node.
|
|
302
|
-
:
|
|
302
|
+
? { hasDefault: true, defaultValue: node.fieldDefault("default_value") }
|
|
303
|
+
: collectionDefault !== undefined
|
|
304
|
+
? { hasDefault: true, defaultValue: collectionDefault }
|
|
305
|
+
: {}),
|
|
303
306
|
};
|
|
304
307
|
}
|
|
305
308
|
|
|
@@ -838,7 +841,7 @@ class Parser {
|
|
|
838
841
|
|
|
839
842
|
#extractCustomRoutes(
|
|
840
843
|
root: YamlNode,
|
|
841
|
-
|
|
844
|
+
_dsByName: Map<string, DatasourceTable>,
|
|
842
845
|
typeByName: Map<string, Type>,
|
|
843
846
|
): CustomRouteEntry[] {
|
|
844
847
|
const customs: CustomRouteEntry[] = [];
|
|
@@ -21,7 +21,7 @@ export type TypeField = {
|
|
|
21
21
|
minSize?: number;
|
|
22
22
|
references?: string | [string, string];
|
|
23
23
|
hasDefault?: boolean;
|
|
24
|
-
defaultValue?: string | number | boolean | null;
|
|
24
|
+
defaultValue?: string | number | boolean | null | object;
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
/** Primary label. `inherit` may also carry `union` — those members compose. */
|
|
@@ -3,6 +3,7 @@ import { parse } from "yaml";
|
|
|
3
3
|
type YamlLiteral = string | number | boolean | null;
|
|
4
4
|
type YamlMap = { readonly [key: string]: YamlValue };
|
|
5
5
|
type YamlValue = YamlLiteral | YamlValue[] | YamlMap;
|
|
6
|
+
type FieldDefault = YamlLiteral | YamlValue[] | YamlMap;
|
|
6
7
|
type Named = { name: string; node: YamlNode };
|
|
7
8
|
|
|
8
9
|
const isMap = (v: YamlValue | undefined): v is YamlMap =>
|
|
@@ -16,12 +17,21 @@ const isFiniteNumber = (v: YamlValue | undefined): v is number =>
|
|
|
16
17
|
const isFiniteInt = (v: YamlValue | undefined): v is number =>
|
|
17
18
|
isFiniteNumber(v) && Number.isInteger(v);
|
|
18
19
|
|
|
20
|
+
const isEmptyList = (v: YamlValue | undefined): v is YamlValue[] =>
|
|
21
|
+
Array.isArray(v) && v.length === 0;
|
|
22
|
+
|
|
23
|
+
const isEmptyMap = (v: YamlValue | undefined): v is YamlMap =>
|
|
24
|
+
isMap(v) && Object.keys(v).length === 0;
|
|
25
|
+
|
|
19
26
|
const isLiteral = (v: YamlValue | undefined): v is YamlLiteral =>
|
|
20
27
|
v === null ||
|
|
21
28
|
typeof v === "string" ||
|
|
22
29
|
typeof v === "number" ||
|
|
23
30
|
typeof v === "boolean";
|
|
24
31
|
|
|
32
|
+
const isFieldDefault = (v: YamlValue | undefined): v is FieldDefault =>
|
|
33
|
+
isLiteral(v) || isEmptyList(v) || isEmptyMap(v);
|
|
34
|
+
|
|
25
35
|
/** Typed cursor over a YAML value. Missing keys are empty nodes, not throws. */
|
|
26
36
|
export type YamlNode = {
|
|
27
37
|
readonly value: YamlValue | undefined;
|
|
@@ -34,6 +44,7 @@ export type YamlNode = {
|
|
|
34
44
|
finiteNumber: (key: string) => number | undefined;
|
|
35
45
|
finiteInt: (key: string) => number | undefined;
|
|
36
46
|
literal: (key: string) => YamlLiteral | undefined;
|
|
47
|
+
fieldDefault: (key: string) => FieldDefault | undefined;
|
|
37
48
|
strings: (key: string) => string[];
|
|
38
49
|
items: () => YamlNode[];
|
|
39
50
|
namedItems: () => Named[];
|
|
@@ -66,6 +77,7 @@ const yamlNode = (value: YamlValue | undefined, path = "$"): YamlNode => {
|
|
|
66
77
|
finiteNumber: pick(isFiniteNumber),
|
|
67
78
|
finiteInt: pick(isFiniteInt),
|
|
68
79
|
literal: pick(isLiteral),
|
|
80
|
+
fieldDefault: pick(isFieldDefault),
|
|
69
81
|
strings: (key) => {
|
|
70
82
|
const v = at(key);
|
|
71
83
|
return Array.isArray(v) ? v.filter(isString) : [];
|
|
@@ -32,6 +32,6 @@ export declare const dictionaryEntryFields: (dict: Type) => {
|
|
|
32
32
|
value: TypeField;
|
|
33
33
|
} | undefined;
|
|
34
34
|
export declare const dictionaryOfField: (field: TypeField, byName: Map<string, Type>) => Type | undefined;
|
|
35
|
-
export declare const persistedColumnFields: (type: Type,
|
|
35
|
+
export declare const persistedColumnFields: (type: Type, _byName?: Map<string, Type>) => TypeField[];
|
|
36
36
|
export declare const dictionaryUniqueColumns: (type: Type, byName: Map<string, Type>) => string[];
|
|
37
37
|
export {};
|
|
@@ -112,23 +112,31 @@ const dictionaryOfField = (field, byName) => {
|
|
|
112
112
|
const dict = byName.get(field.base);
|
|
113
113
|
return isDictionaryType(dict) ? dict : void 0;
|
|
114
114
|
};
|
|
115
|
-
const persistedColumnFields = (type,
|
|
116
|
-
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
115
|
+
const persistedColumnFields = (type, _byName) => columnFields(type.fields);
|
|
116
|
+
const roleColumn = (dict, role, tableName) => {
|
|
117
|
+
const field = dict.fields.find((item) => item.name === role);
|
|
118
|
+
const references = field?.references;
|
|
119
|
+
if (typeof references === "string") {
|
|
120
|
+
const [table, column] = references.split(".");
|
|
121
|
+
if (table === tableName && column !== void 0 && column.length > 0) {
|
|
122
|
+
return column;
|
|
123
|
+
}
|
|
120
124
|
}
|
|
121
|
-
|
|
122
|
-
if (nested === void 0) return columnFields(type.fields);
|
|
123
|
-
return [
|
|
124
|
-
...columnFields(type.fields.filter((f) => f.name !== "value")),
|
|
125
|
-
...columnFields(nested.fields)
|
|
126
|
-
];
|
|
125
|
+
return role;
|
|
127
126
|
};
|
|
128
127
|
const dictionaryUniqueColumns = (type, byName) => {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
128
|
+
for (const candidate of byName.values()) {
|
|
129
|
+
for (const field of candidate.fields) {
|
|
130
|
+
if (field.isMap !== true) continue;
|
|
131
|
+
const dict = byName.get(field.base);
|
|
132
|
+
if (!isDictionaryType(dict) || dict === void 0) continue;
|
|
133
|
+
if (typeof field.references !== "string") continue;
|
|
134
|
+
const [table, owner] = field.references.split(".");
|
|
135
|
+
if (table !== type.name || owner === void 0 || owner.length === 0) continue;
|
|
136
|
+
return [owner, roleColumn(dict, "key", type.name)];
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return [];
|
|
132
140
|
};
|
|
133
141
|
export {
|
|
134
142
|
DATASOURCE_SEEDS_YAML,
|
|
@@ -202,33 +202,35 @@ export const dictionaryOfField = (
|
|
|
202
202
|
|
|
203
203
|
export const persistedColumnFields = (
|
|
204
204
|
type: Type,
|
|
205
|
-
|
|
206
|
-
): TypeField[] =>
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
205
|
+
_byName?: Map<string, Type>,
|
|
206
|
+
): TypeField[] => columnFields(type.fields);
|
|
207
|
+
|
|
208
|
+
const roleColumn = (dict: Type, role: string, tableName: string): string => {
|
|
209
|
+
const field = dict.fields.find((item) => item.name === role);
|
|
210
|
+
const references = field?.references;
|
|
211
|
+
if (typeof references === "string") {
|
|
212
|
+
const [table, column] = references.split(".");
|
|
213
|
+
if (table === tableName && column !== undefined && column.length > 0) {
|
|
214
|
+
return column;
|
|
215
|
+
}
|
|
216
216
|
}
|
|
217
|
-
|
|
218
|
-
if (nested === undefined) return columnFields(type.fields);
|
|
219
|
-
return [
|
|
220
|
-
...columnFields(type.fields.filter((f) => f.name !== "value")),
|
|
221
|
-
...columnFields(nested.fields),
|
|
222
|
-
];
|
|
217
|
+
return role;
|
|
223
218
|
};
|
|
224
219
|
|
|
225
220
|
export const dictionaryUniqueColumns = (
|
|
226
221
|
type: Type,
|
|
227
222
|
byName: Map<string, Type>,
|
|
228
223
|
): string[] => {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
224
|
+
for (const candidate of byName.values()) {
|
|
225
|
+
for (const field of candidate.fields) {
|
|
226
|
+
if (field.isMap !== true) continue;
|
|
227
|
+
const dict = byName.get(field.base);
|
|
228
|
+
if (!isDictionaryType(dict) || dict === undefined) continue;
|
|
229
|
+
if (typeof field.references !== "string") continue;
|
|
230
|
+
const [table, owner] = field.references.split(".");
|
|
231
|
+
if (table !== type.name || owner === undefined || owner.length === 0) continue;
|
|
232
|
+
return [owner, roleColumn(dict, "key", type.name)];
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return [];
|
|
234
236
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deterministic-code/datasources-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"datasources": "./bin/datasources.mjs"
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"access": "public"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@deterministic-code/datasources-code-generators": "0.1.
|
|
16
|
+
"@deterministic-code/datasources-code-generators": "0.1.5",
|
|
17
17
|
"@deterministic-code/generators-common": "0.0.1",
|
|
18
18
|
"@deterministic-code/deterministic-generators-common": "0.1.0",
|
|
19
19
|
"@deterministic-code/typescript-generators": "0.0.1",
|
|
@@ -21,12 +21,12 @@
|
|
|
21
21
|
"@deterministic-code/rust-generators": "0.0.1",
|
|
22
22
|
"@deterministic-code/generators-openapi": "0.0.1",
|
|
23
23
|
"@deterministic-code/patch-merger": "0.1.0",
|
|
24
|
-
"@deterministic-code/datasources": "^0.1.
|
|
25
|
-
"@deterministic-code/datasources-sqlite": "^0.1.
|
|
26
|
-
"@deterministic-code/datasources-mysql": "^0.1.
|
|
27
|
-
"@deterministic-code/datasources-postgres": "^0.1.
|
|
28
|
-
"@deterministic-code/datasources-sqlserver": "^0.1.
|
|
29
|
-
"@deterministic-code/datasources-oracle": "^0.1.
|
|
24
|
+
"@deterministic-code/datasources": "^0.1.5",
|
|
25
|
+
"@deterministic-code/datasources-sqlite": "^0.1.5",
|
|
26
|
+
"@deterministic-code/datasources-mysql": "^0.1.5",
|
|
27
|
+
"@deterministic-code/datasources-postgres": "^0.1.5",
|
|
28
|
+
"@deterministic-code/datasources-sqlserver": "^0.1.5",
|
|
29
|
+
"@deterministic-code/datasources-oracle": "^0.1.5",
|
|
30
30
|
"@inquirer/prompts": "^7.8.0",
|
|
31
31
|
"yaml": "^2.6.0",
|
|
32
32
|
"mustache": "^4.2.0",
|