@fraym/crud 0.7.0 → 0.8.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/README.md +3 -0
- package/dist/cmd/crud.js +40 -21
- package/dist/delivery/getDataList.js +4 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -22,6 +22,8 @@ Use the `crud` cli command to automatically apply your crud schemas to the crud
|
|
|
22
22
|
Your type schemas have to match the glob you specify in the `CRUD_SCHEMA_GLOB` env variable (default: `./src/**/*.graphql`).
|
|
23
23
|
You can specify the address (and port) of the crud service instance you use in the `CRUD_SERVER_ADDRESS` env variable (default: `127.0.0.1:9000`).
|
|
24
24
|
|
|
25
|
+
Use the `CRUD_NAMESPACE` env variable to restrict all migrations to your namespace. This is useful if multiple apps share the crud service. Note: You cannot name your crud type or namespace by a `Fraym` prefix. This is a reserved prefix for fraym apps.
|
|
26
|
+
|
|
25
27
|
You need to add a file that contains all built-in directives to your type schemas. The latest version of this file can be found [here](default.graphql).
|
|
26
28
|
|
|
27
29
|
### Config
|
|
@@ -31,6 +33,7 @@ Use a `.env` file or env variables to configure cte clients and the command:
|
|
|
31
33
|
```env
|
|
32
34
|
CRUD_SERVER_ADDRESS=127.0.0.1:9000
|
|
33
35
|
CRUD_SCHEMA_GLOB=./src/crud/*.graphql
|
|
36
|
+
CRUD_NAMESPACE=
|
|
34
37
|
```
|
|
35
38
|
|
|
36
39
|
## Usage
|
package/dist/cmd/crud.js
CHANGED
|
@@ -14,47 +14,60 @@ const dotenv_1 = require("dotenv");
|
|
|
14
14
|
const run = async () => {
|
|
15
15
|
(0, dotenv_1.config)();
|
|
16
16
|
const argv = await (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
|
|
17
|
-
.config({
|
|
17
|
+
.config({
|
|
18
|
+
schemaGlob: "./src/**/*.graphql",
|
|
19
|
+
serverAddress: "127.0.0.1:9000",
|
|
20
|
+
namespace: "",
|
|
21
|
+
})
|
|
18
22
|
.pkgConf("crud").argv;
|
|
19
23
|
let schemaGlob = argv.schemaGlob;
|
|
20
24
|
let serverAddress = argv.serverAddress;
|
|
25
|
+
let namespace = argv.namespace;
|
|
21
26
|
if (process.env.CRUD_SCHEMA_GLOB) {
|
|
22
27
|
schemaGlob = process.env.CRUD_SCHEMA_GLOB;
|
|
23
28
|
}
|
|
24
29
|
if (process.env.CRUD_SERVER_ADDRESS) {
|
|
25
30
|
serverAddress = process.env.CRUD_SERVER_ADDRESS;
|
|
26
31
|
}
|
|
32
|
+
if (process.env.CRUD_NAMESPACE) {
|
|
33
|
+
namespace = process.env.CRUD_NAMESPACE;
|
|
34
|
+
}
|
|
35
|
+
if (namespace === "Fraym") {
|
|
36
|
+
throw new Error("Cannot use Fraym as namespace prefix as it is reserved for fraym apps");
|
|
37
|
+
}
|
|
27
38
|
const schema = await (0, load_1.loadSchema)(`${schemaGlob}`, {
|
|
28
39
|
loaders: [new graphql_file_loader_1.GraphQLFileLoader()],
|
|
29
40
|
});
|
|
30
|
-
const definitions = getTypeDefinition(schema);
|
|
31
|
-
await migrateSchemas(definitions, serverAddress);
|
|
41
|
+
const definitions = getTypeDefinition(schema, namespace);
|
|
42
|
+
await migrateSchemas(definitions, serverAddress, namespace);
|
|
32
43
|
};
|
|
33
44
|
run();
|
|
34
|
-
const getTypeDefinition = (schema) => {
|
|
45
|
+
const getTypeDefinition = (schema, namespace) => {
|
|
35
46
|
const definitions = {};
|
|
36
47
|
schema.toConfig().types.forEach(t => {
|
|
37
48
|
if (!(t instanceof graphql_1.GraphQLObjectType) && !(t instanceof graphql_1.GraphQLEnumType)) {
|
|
38
49
|
return;
|
|
39
50
|
}
|
|
40
|
-
const name = t.toString()
|
|
51
|
+
const name = `${namespace}${t.toString()}`;
|
|
52
|
+
ensureValidName(name);
|
|
41
53
|
if (definitions[name]) {
|
|
42
54
|
throw new Error(`duplicate definition for type "${name}" detected, try renaming one of them as they have to be uniquely named`);
|
|
43
55
|
}
|
|
44
56
|
if (t instanceof graphql_1.GraphQLObjectType) {
|
|
45
|
-
definitions[name] = getTypeDefinitionFromGraphQLObjectType(t);
|
|
57
|
+
definitions[name] = getTypeDefinitionFromGraphQLObjectType(t, namespace);
|
|
46
58
|
return;
|
|
47
59
|
}
|
|
48
60
|
if (t instanceof graphql_1.GraphQLEnumType) {
|
|
49
|
-
definitions[name] = getTypeDefinitionFromGraphQLEnumType(t);
|
|
61
|
+
definitions[name] = getTypeDefinitionFromGraphQLEnumType(t, namespace);
|
|
50
62
|
return;
|
|
51
63
|
}
|
|
52
64
|
});
|
|
53
65
|
return definitions;
|
|
54
66
|
};
|
|
55
|
-
const getTypeDefinitionFromGraphQLEnumType = (t) => {
|
|
67
|
+
const getTypeDefinitionFromGraphQLEnumType = (t, namespace) => {
|
|
56
68
|
var _a, _b;
|
|
57
|
-
const name = t.toString()
|
|
69
|
+
const name = `${namespace}${t.toString()}`;
|
|
70
|
+
ensureValidName(name);
|
|
58
71
|
let enumValuesString = "";
|
|
59
72
|
(_b = (_a = t.astNode) === null || _a === void 0 ? void 0 : _a.values) === null || _b === void 0 ? void 0 : _b.forEach(value => {
|
|
60
73
|
enumValuesString += `\n\t${value.name.value}`;
|
|
@@ -66,12 +79,12 @@ const getTypeDefinitionFromGraphQLEnumType = (t) => {
|
|
|
66
79
|
schema,
|
|
67
80
|
};
|
|
68
81
|
};
|
|
69
|
-
const getTypeDefinitionFromGraphQLObjectType = (t) => {
|
|
82
|
+
const getTypeDefinitionFromGraphQLObjectType = (t, namespace) => {
|
|
70
83
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
71
84
|
const isCrudType = (_c = (((_a = t.astNode) === null || _a === void 0 ? void 0 : _a.directives) &&
|
|
72
85
|
((_b = t.astNode) === null || _b === void 0 ? void 0 : _b.directives.length) > 0 &&
|
|
73
86
|
t.astNode.directives[0].name.value === "crudType")) !== null && _c !== void 0 ? _c : false;
|
|
74
|
-
const name = t.toString()
|
|
87
|
+
const name = `${namespace}${t.toString()}`;
|
|
75
88
|
let objectDirectivesString = "";
|
|
76
89
|
let objectFieldsString = "";
|
|
77
90
|
let nestedTypes = [];
|
|
@@ -79,7 +92,7 @@ const getTypeDefinitionFromGraphQLObjectType = (t) => {
|
|
|
79
92
|
objectDirectivesString += getDirectiveString(d);
|
|
80
93
|
});
|
|
81
94
|
(_g = (_f = t.astNode) === null || _f === void 0 ? void 0 : _f.fields) === null || _g === void 0 ? void 0 : _g.forEach(f => {
|
|
82
|
-
const { str, nestedTypes: newNestedTypes } = getFieldStringAndNestedTypes(f);
|
|
95
|
+
const { str, nestedTypes: newNestedTypes } = getFieldStringAndNestedTypes(f, namespace);
|
|
83
96
|
objectFieldsString += str;
|
|
84
97
|
newNestedTypes.forEach(nested => {
|
|
85
98
|
if (nestedTypes.indexOf(nested) === -1) {
|
|
@@ -94,13 +107,13 @@ const getTypeDefinitionFromGraphQLObjectType = (t) => {
|
|
|
94
107
|
schema,
|
|
95
108
|
};
|
|
96
109
|
};
|
|
97
|
-
const getFieldStringAndNestedTypes = (f) => {
|
|
110
|
+
const getFieldStringAndNestedTypes = (f, namespace) => {
|
|
98
111
|
var _a;
|
|
99
112
|
let directivesString = "";
|
|
100
113
|
(_a = f.directives) === null || _a === void 0 ? void 0 : _a.forEach(d => {
|
|
101
114
|
directivesString += getDirectiveString(d);
|
|
102
115
|
});
|
|
103
|
-
const { nestedType, str: typeString } = getTypeData(f.type);
|
|
116
|
+
const { nestedType, str: typeString } = getTypeData(f.type, namespace);
|
|
104
117
|
const nestedTypes = [];
|
|
105
118
|
if (nestedType) {
|
|
106
119
|
nestedTypes.push(nestedType);
|
|
@@ -110,10 +123,11 @@ const getFieldStringAndNestedTypes = (f) => {
|
|
|
110
123
|
nestedTypes,
|
|
111
124
|
};
|
|
112
125
|
};
|
|
113
|
-
const getTypeData = (t) => {
|
|
126
|
+
const getTypeData = (t, namespace) => {
|
|
114
127
|
switch (t.kind) {
|
|
115
128
|
case graphql_1.Kind.NAMED_TYPE:
|
|
116
129
|
const name = t.name.value;
|
|
130
|
+
ensureValidName(`${namespace}${name}`);
|
|
117
131
|
return name === "String" ||
|
|
118
132
|
name === "Float" ||
|
|
119
133
|
name === "ID" ||
|
|
@@ -124,17 +138,17 @@ const getTypeData = (t) => {
|
|
|
124
138
|
str: name,
|
|
125
139
|
}
|
|
126
140
|
: {
|
|
127
|
-
str: name
|
|
128
|
-
nestedType: name
|
|
141
|
+
str: `${namespace}${name}`,
|
|
142
|
+
nestedType: `${namespace}${name}`,
|
|
129
143
|
};
|
|
130
144
|
case graphql_1.Kind.LIST_TYPE:
|
|
131
|
-
const { nestedType: listNestedType, str: listStr } = getTypeData(t.type);
|
|
145
|
+
const { nestedType: listNestedType, str: listStr } = getTypeData(t.type, namespace);
|
|
132
146
|
return {
|
|
133
147
|
str: `[${listStr}]`,
|
|
134
148
|
nestedType: listNestedType,
|
|
135
149
|
};
|
|
136
150
|
case graphql_1.Kind.NON_NULL_TYPE:
|
|
137
|
-
const { nestedType: nonNullNestedType, str: nonNullStr } = getTypeData(t.type);
|
|
151
|
+
const { nestedType: nonNullNestedType, str: nonNullStr } = getTypeData(t.type, namespace);
|
|
138
152
|
return {
|
|
139
153
|
str: `${nonNullStr}!`,
|
|
140
154
|
nestedType: nonNullNestedType,
|
|
@@ -186,9 +200,9 @@ const getValueString = (v) => {
|
|
|
186
200
|
throw new Error(`values of kind ${v.kind} are currently not supported`);
|
|
187
201
|
}
|
|
188
202
|
};
|
|
189
|
-
const migrateSchemas = async (definitions, serverAddress) => {
|
|
203
|
+
const migrateSchemas = async (definitions, serverAddress, namespace) => {
|
|
190
204
|
const managementClient = await (0, client_1.newManagementClient)({ serverAddress });
|
|
191
|
-
const existingTypeNames = await managementClient.getAllTypes();
|
|
205
|
+
const existingTypeNames = (await managementClient.getAllTypes()).filter(name => name.startsWith(namespace));
|
|
192
206
|
let createSchema = "";
|
|
193
207
|
let updateSchema = "";
|
|
194
208
|
const typesToCreate = [];
|
|
@@ -244,3 +258,8 @@ const migrateSchemas = async (definitions, serverAddress) => {
|
|
|
244
258
|
console.log(`Removed ${typesToRemove.length} types`);
|
|
245
259
|
}
|
|
246
260
|
};
|
|
261
|
+
const ensureValidName = (name) => {
|
|
262
|
+
if (name.startsWith("Fraym")) {
|
|
263
|
+
throw new Error("Cannot use Fraym as type name prefix as it is reserved for fraym apps");
|
|
264
|
+
}
|
|
265
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getCrudDataList = void 0;
|
|
4
|
-
const
|
|
4
|
+
const getProtobufEntryFilter = (filter) => {
|
|
5
5
|
const fields = {};
|
|
6
6
|
for (const fieldName in filter.fields) {
|
|
7
7
|
const field = filter.fields[fieldName];
|
|
@@ -20,8 +20,8 @@ const getProtobufDataFilter = (filter) => {
|
|
|
20
20
|
}
|
|
21
21
|
return {
|
|
22
22
|
fields: fields,
|
|
23
|
-
and: filter.and.map(and =>
|
|
24
|
-
or: filter.or.map(or =>
|
|
23
|
+
and: filter.and.map(and => getProtobufEntryFilter(and)),
|
|
24
|
+
or: filter.or.map(or => getProtobufEntryFilter(or)),
|
|
25
25
|
};
|
|
26
26
|
};
|
|
27
27
|
const getCrudDataList = async (tenantId, type, limit, page, filter, serviceClient) => {
|
|
@@ -33,7 +33,7 @@ const getCrudDataList = async (tenantId, type, limit, page, filter, serviceClien
|
|
|
33
33
|
limit,
|
|
34
34
|
page,
|
|
35
35
|
returnEmptyDataIfNotFound: false,
|
|
36
|
-
filter:
|
|
36
|
+
filter: getProtobufEntryFilter(filter),
|
|
37
37
|
}, (error, response) => {
|
|
38
38
|
if (error) {
|
|
39
39
|
reject(error.message);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fraym/crud",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"homepage": "https://github.com/fraym/crud-nodejs",
|
|
6
6
|
"repository": {
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"crud": "dist/cmd/crud.js"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@fraym/crud-proto": "^1.0.0-alpha.
|
|
30
|
+
"@fraym/crud-proto": "^1.0.0-alpha.8",
|
|
31
31
|
"@graphql-tools/graphql-file-loader": "^7.5.11",
|
|
32
32
|
"@graphql-tools/load": "^7.8.6",
|
|
33
33
|
"@grpc/grpc-js": "^1.7.2",
|