@snowtop/ent 0.1.27 → 0.2.0-alpha.10-test1
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/action/orchestrator.js +13 -7
- package/core/base.d.ts +1 -0
- package/core/clause.d.ts +44 -0
- package/core/clause.js +75 -2
- package/core/db.d.ts +1 -1
- package/core/db.js +2 -2
- package/core/ent.d.ts +10 -2
- package/core/ent.js +11 -18
- package/core/loaders/assoc_edge_loader.d.ts +1 -1
- package/core/loaders/assoc_edge_loader.js +3 -3
- package/core/query/assoc_query.d.ts +2 -2
- package/core/query/assoc_query.js +14 -2
- package/core/query/custom_clause_query.d.ts +8 -6
- package/core/query/custom_clause_query.js +22 -7
- package/core/query/custom_query.d.ts +2 -2
- package/core/query/custom_query.js +1 -1
- package/core/query/query.d.ts +3 -7
- package/core/query/query.js +73 -199
- package/core/query/shared_test.d.ts +3 -3
- package/core/query/shared_test.js +31 -23
- package/core/query_impl.d.ts +0 -1
- package/core/query_impl.js +18 -1
- package/graphql/graphql.js +3 -0
- package/graphql/query/edge_connection.d.ts +5 -4
- package/graphql/query/edge_connection.js +34 -14
- package/graphql/query/shared_edge_connection.d.ts +2 -2
- package/graphql/query/shared_edge_connection.js +26 -13
- package/names/names.d.ts +10 -0
- package/names/names.js +157 -0
- package/package.json +1 -1
- package/schema/base_schema.js +2 -2
- package/schema/field.d.ts +1 -1
- package/schema/field.js +9 -8
- package/schema/schema.d.ts +1 -3
- package/schema/schema.js +2 -5
- package/schema/struct_field.js +12 -9
- package/scripts/read_schema.js +2 -2
- package/testutils/builder.js +7 -9
- package/testutils/db/temp_db.js +2 -2
- package/testutils/db/value.d.ts +1 -0
- package/testutils/db/value.js +2 -1
- package/testutils/db_mock.d.ts +1 -1
- package/testutils/db_mock.js +1 -1
- package/testutils/ent-graphql-tests/index.d.ts +1 -1
- package/testutils/ent-graphql-tests/index.js +5 -5
- package/testutils/fake_data/fake_contact.js +2 -2
- package/testutils/fake_data/fake_event.js +1 -1
- package/testutils/fake_data/test_helpers.js +3 -3
- package/testutils/fake_data/user_query.d.ts +5 -5
- package/testutils/fake_data/user_query.js +11 -14
- package/testutils/soft_delete.js +0 -4
- package/testutils/test_edge_global_schema.js +0 -2
- package/tsc/compilerOptions.js +4 -1
- package/tsc/transform_action.js +2 -2
|
@@ -1,23 +1,38 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.GraphQLEdgeConnection = void 0;
|
|
4
|
+
const query_1 = require("../../core/query");
|
|
4
5
|
// TODO probably need to template Ent. maybe 2 ents?
|
|
5
6
|
class GraphQLEdgeConnection {
|
|
6
7
|
constructor(viewer, arg2, arg3, args) {
|
|
7
8
|
this.results = [];
|
|
8
9
|
this.viewer = viewer;
|
|
10
|
+
async function resolveQuery(query, source) {
|
|
11
|
+
const resolved = await query;
|
|
12
|
+
// To have pagination correctly work with CustomClauseQuery in GraphQL contexts, we need to
|
|
13
|
+
// pass the source to the query so that we can set the page info correctly
|
|
14
|
+
// See https://github.com/lolopinto/ent/issues/1836 for full details of how this breaks down
|
|
15
|
+
if (resolved instanceof query_1.CustomClauseQuery && source !== undefined) {
|
|
16
|
+
resolved.__maybeSetSource(source);
|
|
17
|
+
}
|
|
18
|
+
return resolved;
|
|
19
|
+
}
|
|
20
|
+
let query;
|
|
21
|
+
let source;
|
|
9
22
|
if (typeof arg2 === "function") {
|
|
10
|
-
|
|
23
|
+
query = arg2(this.viewer);
|
|
11
24
|
}
|
|
12
25
|
else {
|
|
13
26
|
this.source = arg2;
|
|
27
|
+
source = arg2;
|
|
14
28
|
}
|
|
15
29
|
if (typeof arg3 === "function") {
|
|
16
|
-
|
|
30
|
+
query = arg3(this.viewer, this.source);
|
|
17
31
|
}
|
|
18
32
|
else {
|
|
19
33
|
this.args = arg3;
|
|
20
34
|
}
|
|
35
|
+
this.query = Promise.resolve(resolveQuery(query, source));
|
|
21
36
|
if (args !== undefined) {
|
|
22
37
|
this.args = args;
|
|
23
38
|
}
|
|
@@ -29,27 +44,31 @@ class GraphQLEdgeConnection {
|
|
|
29
44
|
throw new Error("cannot process before without last");
|
|
30
45
|
}
|
|
31
46
|
if (this.args.first) {
|
|
32
|
-
|
|
47
|
+
const argFirst = this.args.first;
|
|
48
|
+
const argAfter = this.args.after;
|
|
49
|
+
this.query = this.query.then((query) => query.first(argFirst, argAfter));
|
|
33
50
|
}
|
|
34
51
|
if (this.args.last) {
|
|
35
|
-
|
|
52
|
+
const argLast = this.args.last;
|
|
53
|
+
const argBefore = this.args.before;
|
|
54
|
+
this.query = this.query.then((query) => query.last(argLast, argBefore));
|
|
36
55
|
}
|
|
37
56
|
// TODO custom args
|
|
38
57
|
// how to proceed
|
|
39
58
|
}
|
|
40
59
|
}
|
|
41
60
|
first(limit, cursor) {
|
|
42
|
-
this.query = this.query.first(limit, cursor);
|
|
61
|
+
this.query = this.query.then((query) => query.first(limit, cursor));
|
|
43
62
|
}
|
|
44
63
|
last(limit, cursor) {
|
|
45
|
-
this.query = this.query.last(limit, cursor);
|
|
64
|
+
this.query = this.query.then((query) => query.last(limit, cursor));
|
|
46
65
|
}
|
|
47
66
|
// any custom filters can be applied here...
|
|
48
67
|
modifyQuery(fn) {
|
|
49
|
-
this.query =
|
|
68
|
+
this.query = this.query.then((query) => fn(query));
|
|
50
69
|
}
|
|
51
70
|
async queryTotalCount() {
|
|
52
|
-
return this.query.queryRawCount();
|
|
71
|
+
return (await this.query).queryRawCount();
|
|
53
72
|
}
|
|
54
73
|
async queryEdges() {
|
|
55
74
|
// because of privacy, we need to query the node regardless of if the node is there
|
|
@@ -60,7 +79,7 @@ class GraphQLEdgeConnection {
|
|
|
60
79
|
// if nodes queried just return ents
|
|
61
80
|
// unlikely to query nodes and pageInfo so we just load this separately for now
|
|
62
81
|
async queryNodes() {
|
|
63
|
-
return this.query.queryEnts();
|
|
82
|
+
return (await this.query).queryEnts();
|
|
64
83
|
}
|
|
65
84
|
defaultPageInfo() {
|
|
66
85
|
return {
|
|
@@ -72,7 +91,7 @@ class GraphQLEdgeConnection {
|
|
|
72
91
|
}
|
|
73
92
|
async queryPageInfo() {
|
|
74
93
|
await this.queryData();
|
|
75
|
-
const paginationInfo = this.query.paginationInfo();
|
|
94
|
+
const paginationInfo = (await this.query).paginationInfo();
|
|
76
95
|
if (this.source !== undefined) {
|
|
77
96
|
return paginationInfo.get(this.source.id) || this.defaultPageInfo();
|
|
78
97
|
}
|
|
@@ -85,24 +104,25 @@ class GraphQLEdgeConnection {
|
|
|
85
104
|
return this.defaultPageInfo();
|
|
86
105
|
}
|
|
87
106
|
async queryData() {
|
|
107
|
+
const query = await this.query;
|
|
88
108
|
const [edges, ents] = await Promise.all([
|
|
89
109
|
// TODO need a test that this will only fetch edges once
|
|
90
110
|
// and then fetch ents afterward
|
|
91
|
-
|
|
92
|
-
|
|
111
|
+
query.queryEdges(),
|
|
112
|
+
query.queryEnts(),
|
|
93
113
|
]);
|
|
94
114
|
let entsMap = new Map();
|
|
95
115
|
ents.forEach((ent) => entsMap.set(ent.id, ent));
|
|
96
116
|
let results = [];
|
|
97
117
|
for (const edge of edges) {
|
|
98
|
-
const node = entsMap.get(
|
|
118
|
+
const node = entsMap.get(query.dataToID(edge));
|
|
99
119
|
if (!node) {
|
|
100
120
|
continue;
|
|
101
121
|
}
|
|
102
122
|
results.push({
|
|
103
123
|
edge,
|
|
104
124
|
node,
|
|
105
|
-
cursor:
|
|
125
|
+
cursor: query.getCursor(edge),
|
|
106
126
|
});
|
|
107
127
|
}
|
|
108
128
|
this.results = results;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { FakeContact } from "../../testutils/fake_data/index";
|
|
1
|
+
import { Data, Ent, Viewer } from "../../core/base";
|
|
3
2
|
import { EdgeQuery } from "../../core/query/query";
|
|
3
|
+
import { FakeContact } from "../../testutils/fake_data/index";
|
|
4
4
|
interface options<TEnt extends Ent, TEdge extends Data> {
|
|
5
5
|
getQuery: (v: Viewer, src: Ent) => EdgeQuery<TEnt, Ent, TEdge>;
|
|
6
6
|
tableName: string;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.commonTests = void 0;
|
|
4
|
-
const
|
|
4
|
+
const query_1 = require("../../core/query");
|
|
5
5
|
const ent_1 = require("../../core/ent");
|
|
6
|
-
const
|
|
6
|
+
const viewer_1 = require("../../core/viewer");
|
|
7
7
|
const index_1 = require("../../testutils/fake_data/index");
|
|
8
8
|
const test_helpers_1 = require("../../testutils/fake_data/test_helpers");
|
|
9
|
+
const edge_connection_1 = require("./edge_connection");
|
|
9
10
|
class TestConnection {
|
|
10
11
|
constructor(getQuery, ents, filter) {
|
|
11
12
|
this.getQuery = getQuery;
|
|
@@ -18,10 +19,20 @@ class TestConnection {
|
|
|
18
19
|
this.allContacts = this.allContacts.reverse();
|
|
19
20
|
this.conn = new edge_connection_1.GraphQLEdgeConnection(new viewer_1.IDViewer(this.user.id), this.user, (v, user) => this.getQuery(v, user));
|
|
20
21
|
if (this.filter) {
|
|
21
|
-
this.filter(this.conn, this.user, this.allContacts);
|
|
22
|
+
await this.filter(this.conn, this.user, this.allContacts);
|
|
22
23
|
}
|
|
23
24
|
this.filteredContacts = this.ents(this.allContacts);
|
|
24
25
|
}
|
|
26
|
+
async testAsyncConn() {
|
|
27
|
+
const asyncConn = new edge_connection_1.GraphQLEdgeConnection(new viewer_1.IDViewer(this.user.id), this.user, (v, user) => new Promise((resolve) => {
|
|
28
|
+
setTimeout(() => resolve(this.getQuery(v, user)), 0);
|
|
29
|
+
}));
|
|
30
|
+
if (this.filter) {
|
|
31
|
+
await this.filter(asyncConn, this.user, this.allContacts);
|
|
32
|
+
}
|
|
33
|
+
const count = await asyncConn.queryTotalCount();
|
|
34
|
+
expect(count).toBe(test_helpers_1.inputs.length);
|
|
35
|
+
}
|
|
25
36
|
async testTotalCount() {
|
|
26
37
|
const count = await this.conn.queryTotalCount();
|
|
27
38
|
expect(count).toBe(test_helpers_1.inputs.length);
|
|
@@ -39,7 +50,7 @@ class TestConnection {
|
|
|
39
50
|
for (let i = 0; i < this.filteredContacts.length; i++) {
|
|
40
51
|
const edge = edges[i];
|
|
41
52
|
expect(edge.node.id).toBe(this.filteredContacts[i].id);
|
|
42
|
-
expect(this.conn.query.dataToID(edge.edge)).toBe(this.filteredContacts[i].id);
|
|
53
|
+
expect((await this.conn.query).dataToID(edge.edge)).toBe(this.filteredContacts[i].id);
|
|
43
54
|
}
|
|
44
55
|
}
|
|
45
56
|
}
|
|
@@ -50,14 +61,16 @@ const commonTests = (opts) => {
|
|
|
50
61
|
q instanceof index_1.UserToContactsFkeyQueryDeprecated ||
|
|
51
62
|
q instanceof index_1.UserToContactsFkeyQueryAsc ||
|
|
52
63
|
q instanceof index_1.UserToContactsFkeyQueryDeletedAt ||
|
|
53
|
-
q instanceof index_1.UserToContactsFkeyQueryDeletedAtAsc
|
|
64
|
+
q instanceof index_1.UserToContactsFkeyQueryDeletedAtAsc ||
|
|
65
|
+
q instanceof query_1.CustomClauseQuery);
|
|
54
66
|
}
|
|
55
67
|
function getCursorFrom(q, contacts, idx) {
|
|
56
68
|
let opts;
|
|
57
69
|
if (isCustomQuery(q)) {
|
|
58
70
|
opts = {
|
|
59
71
|
row: contacts[idx],
|
|
60
|
-
|
|
72
|
+
cursorKeys: ["created_at", "id"],
|
|
73
|
+
rowKeys: ["createdAt", "id"],
|
|
61
74
|
};
|
|
62
75
|
}
|
|
63
76
|
else {
|
|
@@ -65,8 +78,8 @@ const commonTests = (opts) => {
|
|
|
65
78
|
// is from assoc_edge table id2 field and so cursor takes it from there
|
|
66
79
|
opts = {
|
|
67
80
|
row: contacts[idx],
|
|
68
|
-
|
|
69
|
-
|
|
81
|
+
cursorKeys: ["time", "id2"],
|
|
82
|
+
rowKeys: ["createdAt", "id"],
|
|
70
83
|
};
|
|
71
84
|
}
|
|
72
85
|
return (0, ent_1.getCursor)(opts);
|
|
@@ -92,7 +105,7 @@ const commonTests = (opts) => {
|
|
|
92
105
|
});
|
|
93
106
|
});
|
|
94
107
|
describe("filters. firstN", () => {
|
|
95
|
-
const filter = new TestConnection((v, user) => opts.getQuery(v, user), (contacts) => contacts.slice(0, 2), (conn) => {
|
|
108
|
+
const filter = new TestConnection((v, user) => opts.getQuery(v, user), (contacts) => contacts.slice(0, 2), async (conn) => {
|
|
96
109
|
conn.first(2);
|
|
97
110
|
});
|
|
98
111
|
beforeEach(async () => {
|
|
@@ -124,8 +137,8 @@ const commonTests = (opts) => {
|
|
|
124
137
|
const N = 3;
|
|
125
138
|
const filter = new TestConnection((v, user) => opts.getQuery(v, user),
|
|
126
139
|
// get the next 2
|
|
127
|
-
(contacts) => contacts.slice(idx + 1, idx + N), (conn, user, contacts) => {
|
|
128
|
-
const cursor = getCursorFrom(conn.query, contacts, idx);
|
|
140
|
+
(contacts) => contacts.slice(idx + 1, idx + N), async (conn, user, contacts) => {
|
|
141
|
+
const cursor = getCursorFrom(await conn.query, contacts, idx);
|
|
129
142
|
conn.first(2, cursor);
|
|
130
143
|
});
|
|
131
144
|
beforeEach(async () => {
|
|
@@ -153,9 +166,9 @@ const commonTests = (opts) => {
|
|
|
153
166
|
});
|
|
154
167
|
});
|
|
155
168
|
describe("filters. before cursor", () => {
|
|
156
|
-
const filter = new TestConnection((v, user) => opts.getQuery(v, user), (contacts) => contacts.slice(2, 4).reverse(), (conn, user, contacts) => {
|
|
169
|
+
const filter = new TestConnection((v, user) => opts.getQuery(v, user), (contacts) => contacts.slice(2, 4).reverse(), async (conn, user, contacts) => {
|
|
157
170
|
// get the 2 before it
|
|
158
|
-
const cursor = getCursorFrom(conn.query, contacts, 4);
|
|
171
|
+
const cursor = getCursorFrom(await conn.query, contacts, 4);
|
|
159
172
|
conn.last(2, cursor);
|
|
160
173
|
});
|
|
161
174
|
beforeEach(async () => {
|
package/names/names.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare function toDBColumnOrTable(...strs: string[]): string;
|
|
2
|
+
export declare function toFilePath(s: string): string;
|
|
3
|
+
export declare function toFieldName(...strs: string[]): string;
|
|
4
|
+
export declare function toClassName(str: string): string;
|
|
5
|
+
interface splitResult {
|
|
6
|
+
s: string;
|
|
7
|
+
type: "lower" | "upper" | "digit" | "other";
|
|
8
|
+
}
|
|
9
|
+
export declare function _splitCamelCase(s: string): splitResult[];
|
|
10
|
+
export {};
|
package/names/names.js
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports._splitCamelCase = exports.toClassName = exports.toFieldName = exports.toFilePath = exports.toDBColumnOrTable = void 0;
|
|
4
|
+
const camel_case_1 = require("camel-case");
|
|
5
|
+
const pascal_case_1 = require("pascal-case");
|
|
6
|
+
const snake_case_1 = require("snake-case");
|
|
7
|
+
// TODO tests and update functionality to match golang
|
|
8
|
+
function toDBColumnOrTable(...strs) {
|
|
9
|
+
let name = "";
|
|
10
|
+
for (let i = 0; i < strs.length; i++) {
|
|
11
|
+
const s = strs[i];
|
|
12
|
+
// this is to handle userIDs -> user_ids
|
|
13
|
+
const split = _splitCamelCase(s);
|
|
14
|
+
if (split.length > 2) {
|
|
15
|
+
const last = split[split.length - 1];
|
|
16
|
+
const nextLast = split[split.length - 2];
|
|
17
|
+
if (last.s === "s" && nextLast.type === "upper") {
|
|
18
|
+
// get the first n-2 words
|
|
19
|
+
name += (0, snake_case_1.snakeCase)(split
|
|
20
|
+
.map((v) => v.s)
|
|
21
|
+
.slice(0, split.length - 2)
|
|
22
|
+
.join(""));
|
|
23
|
+
name += "_";
|
|
24
|
+
// combine the last two
|
|
25
|
+
name += (0, snake_case_1.snakeCase)(nextLast.s);
|
|
26
|
+
name += last.s;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
name += (0, snake_case_1.snakeCase)(s);
|
|
31
|
+
if (i !== strs.length - 1) {
|
|
32
|
+
name += "_";
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return name;
|
|
36
|
+
}
|
|
37
|
+
exports.toDBColumnOrTable = toDBColumnOrTable;
|
|
38
|
+
function toFilePath(s) {
|
|
39
|
+
return (0, snake_case_1.snakeCase)(s);
|
|
40
|
+
}
|
|
41
|
+
exports.toFilePath = toFilePath;
|
|
42
|
+
function toFieldName(...strs) {
|
|
43
|
+
let name = "";
|
|
44
|
+
let hasDoneLower = false;
|
|
45
|
+
for (const s of strs) {
|
|
46
|
+
// same logic in toDBColumnOrTable
|
|
47
|
+
const split = _splitCamelCase(s);
|
|
48
|
+
if (split.length > 2) {
|
|
49
|
+
const last = split[split.length - 1];
|
|
50
|
+
const nextLast = split[split.length - 2];
|
|
51
|
+
if (last.s === "s" && nextLast.type === "upper") {
|
|
52
|
+
// get the first n-2 words
|
|
53
|
+
name += (0, camel_case_1.camelCase)(split
|
|
54
|
+
.map((v) => v.s)
|
|
55
|
+
.slice(0, split.length - 2)
|
|
56
|
+
.join(""));
|
|
57
|
+
// combine the last two
|
|
58
|
+
name += (0, pascal_case_1.pascalCase)(nextLast.s);
|
|
59
|
+
name += last.s;
|
|
60
|
+
hasDoneLower = true;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (!hasDoneLower) {
|
|
65
|
+
name += (0, camel_case_1.camelCase)(s);
|
|
66
|
+
hasDoneLower = true;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
name += (0, pascal_case_1.pascalCase)(s);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return name;
|
|
73
|
+
}
|
|
74
|
+
exports.toFieldName = toFieldName;
|
|
75
|
+
function toClassName(str) {
|
|
76
|
+
return (0, pascal_case_1.pascalCase)(str);
|
|
77
|
+
}
|
|
78
|
+
exports.toClassName = toClassName;
|
|
79
|
+
function isUpper(s) {
|
|
80
|
+
for (const c of s) {
|
|
81
|
+
if (!(c >= "A" && c <= "Z")) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
function isLower(s) {
|
|
88
|
+
for (const c of s) {
|
|
89
|
+
if (!(c >= "a" && c <= "z")) {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
function isDigit(s) {
|
|
96
|
+
return /^\d+$/.test(s);
|
|
97
|
+
}
|
|
98
|
+
// ported from golang in internal/names/names.go
|
|
99
|
+
function _splitCamelCase(s) {
|
|
100
|
+
const results = [];
|
|
101
|
+
let lastType;
|
|
102
|
+
let type;
|
|
103
|
+
for (let i = 0; i < s.length; i++) {
|
|
104
|
+
const c = s[i];
|
|
105
|
+
if (isLower(c)) {
|
|
106
|
+
type = "lower";
|
|
107
|
+
}
|
|
108
|
+
else if (isUpper(c)) {
|
|
109
|
+
type = "upper";
|
|
110
|
+
}
|
|
111
|
+
else if (isDigit(c)) {
|
|
112
|
+
type = "digit";
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
type = "other";
|
|
116
|
+
}
|
|
117
|
+
if (lastType == type) {
|
|
118
|
+
results[results.length - 1].s += c;
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
results.push({ s: c, type });
|
|
122
|
+
}
|
|
123
|
+
lastType = type;
|
|
124
|
+
}
|
|
125
|
+
// this is for handling the userIDs -> "user", "ID", "s" case
|
|
126
|
+
const isPlural = function (curr, next) {
|
|
127
|
+
return curr.length > 1 && next === "s";
|
|
128
|
+
};
|
|
129
|
+
for (let i = 0; i < results.length - 1; i++) {
|
|
130
|
+
if (isUpper(results[i].s[0]) &&
|
|
131
|
+
isLower(results[i + 1].s[0]) &&
|
|
132
|
+
!isPlural(results[i].s, results[i + 1].s)) {
|
|
133
|
+
// get last item from results[i] and add to front of results[i+1]
|
|
134
|
+
results[i + 1].s =
|
|
135
|
+
results[i].s[results[i].s.length - 1] + results[i + 1].s;
|
|
136
|
+
// now has a prefix and is not all of one case
|
|
137
|
+
results[i + 1].type = "other";
|
|
138
|
+
// remove last character from results[i]
|
|
139
|
+
results[i].s = results[i].s.slice(0, results[i].s.length - 1);
|
|
140
|
+
}
|
|
141
|
+
else if (isDigit(results[i].s[0]) && isLower(results[i + 1].s[0])) {
|
|
142
|
+
results[i].s = results[i].s + results[i + 1].s;
|
|
143
|
+
results[i].type = "other";
|
|
144
|
+
// remove
|
|
145
|
+
results[i + 1].s = "";
|
|
146
|
+
i++;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
for (let i = 0; i < results.length; i++) {
|
|
150
|
+
if (results[i].s === "") {
|
|
151
|
+
results.splice(i, 1);
|
|
152
|
+
i--;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return results;
|
|
156
|
+
}
|
|
157
|
+
exports._splitCamelCase = _splitCamelCase;
|
package/package.json
CHANGED
package/schema/base_schema.js
CHANGED
|
@@ -37,12 +37,12 @@ let nodeField = (0, field_1.UUIDType)({
|
|
|
37
37
|
});
|
|
38
38
|
let nodeFields = {
|
|
39
39
|
// inconsistent naming :(
|
|
40
|
-
|
|
40
|
+
id: nodeField,
|
|
41
41
|
...tsFields,
|
|
42
42
|
};
|
|
43
43
|
let nodeFieldsWithTZ = {
|
|
44
44
|
// inconsistent naming :(
|
|
45
|
-
|
|
45
|
+
id: nodeField,
|
|
46
46
|
createdAt: (0, field_1.TimestampType)({
|
|
47
47
|
hideFromGraphQL: true,
|
|
48
48
|
disableUserEditable: true,
|
package/schema/field.d.ts
CHANGED
|
@@ -100,7 +100,7 @@ interface PolymorphicStringOptions extends StringOptions {
|
|
|
100
100
|
}
|
|
101
101
|
export declare class PolymorphicStringField extends StringField {
|
|
102
102
|
private opts;
|
|
103
|
-
private
|
|
103
|
+
private fieldNameValues;
|
|
104
104
|
constructor(opts: PolymorphicStringOptions);
|
|
105
105
|
validateWithFullData(val: any, b: Builder<any>): boolean;
|
|
106
106
|
valid(val: any): boolean;
|
package/schema/field.js
CHANGED
|
@@ -25,7 +25,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
26
|
exports.UUIDListType = exports.IntegerEnumListType = exports.EnumListType = exports.DateListType = exports.TimetzListType = exports.TimeListType = exports.TimestamptzListType = exports.TimestampListType = exports.BooleanListType = exports.BigIntegerListType = exports.FloatListType = exports.IntegerListType = exports.IntListType = exports.StringListType = exports.ListField = exports.IntegerEnumType = exports.IntegerEnumField = exports.EnumType = exports.StringEnumField = exports.EnumField = exports.DateType = exports.DateField = exports.TimetzType = exports.TimeType = exports.TimeField = exports.leftPad = exports.TimestamptzType = exports.TimestampType = exports.TimestampField = exports.StringType = exports.PolymorphicStringField = exports.StringField = exports.BooleanType = exports.BooleanField = exports.FloatType = exports.FloatField = exports.BigIntegerType = exports.BigIntegerField = exports.IntegerType = exports.IntegerField = exports.NumberField = exports.UUIDType = exports.UUIDField = exports.BaseField = void 0;
|
|
27
27
|
const luxon_1 = require("luxon");
|
|
28
|
-
const camel_case_1 = require("camel-case");
|
|
29
28
|
const types_1 = require("util/types");
|
|
30
29
|
const uuid_1 = require("uuid");
|
|
31
30
|
const base_1 = require("../core/base");
|
|
@@ -33,6 +32,7 @@ const db_1 = __importStar(require("../core/db"));
|
|
|
33
32
|
const schema_1 = require("./schema");
|
|
34
33
|
const global_schema_1 = require("../core/global_schema");
|
|
35
34
|
const logger_1 = require("../core/logger");
|
|
35
|
+
const names_1 = require("../names/names");
|
|
36
36
|
class BaseField {
|
|
37
37
|
logValue(val) {
|
|
38
38
|
if (this.sensitive) {
|
|
@@ -57,6 +57,7 @@ class UUIDField extends BaseField {
|
|
|
57
57
|
const polymorphic = this.options?.polymorphic;
|
|
58
58
|
if (polymorphic) {
|
|
59
59
|
let name = "";
|
|
60
|
+
// TODO followup to https://github.com/lolopinto/ent/pull/1757
|
|
60
61
|
if (fieldName.endsWith("_id")) {
|
|
61
62
|
let idx = fieldName.indexOf("_id");
|
|
62
63
|
name = fieldName.substring(0, idx) + "_type";
|
|
@@ -328,7 +329,7 @@ class PolymorphicStringField extends StringField {
|
|
|
328
329
|
super(opts);
|
|
329
330
|
this.opts = opts;
|
|
330
331
|
if (opts.types) {
|
|
331
|
-
this.
|
|
332
|
+
this.fieldNameValues = opts.types.map((v) => (0, names_1.toFieldName)(v));
|
|
332
333
|
}
|
|
333
334
|
}
|
|
334
335
|
validateWithFullData(val, b) {
|
|
@@ -347,19 +348,19 @@ class PolymorphicStringField extends StringField {
|
|
|
347
348
|
return true;
|
|
348
349
|
}
|
|
349
350
|
valid(val) {
|
|
350
|
-
if (!this.
|
|
351
|
+
if (!this.fieldNameValues) {
|
|
351
352
|
return true;
|
|
352
353
|
}
|
|
353
|
-
let str = (0,
|
|
354
|
+
let str = (0, names_1.toFieldName)(String(val));
|
|
354
355
|
// allow different cases because it could be coming from different clients who don't have strong typing
|
|
355
|
-
return this.
|
|
356
|
+
return this.fieldNameValues.some((value) => value === str);
|
|
356
357
|
}
|
|
357
358
|
format(val) {
|
|
358
|
-
if (!this.
|
|
359
|
+
if (!this.fieldNameValues) {
|
|
359
360
|
return val;
|
|
360
361
|
}
|
|
361
|
-
const converted = (0,
|
|
362
|
-
for (const v of this.
|
|
362
|
+
const converted = (0, names_1.toFieldName)(String(val));
|
|
363
|
+
for (const v of this.fieldNameValues) {
|
|
363
364
|
if (v === val) {
|
|
364
365
|
return val;
|
|
365
366
|
}
|
package/schema/schema.d.ts
CHANGED
|
@@ -247,6 +247,7 @@ export interface FieldOptions {
|
|
|
247
247
|
getDerivedFields?(name: string): FieldMap;
|
|
248
248
|
convert?: ConvertType;
|
|
249
249
|
fetchOnDemand?: boolean;
|
|
250
|
+
disableBase64Encode?: boolean;
|
|
250
251
|
dbOnly?: boolean;
|
|
251
252
|
[x: string]: any;
|
|
252
253
|
}
|
|
@@ -271,9 +272,6 @@ export interface SchemaConstructor {
|
|
|
271
272
|
export type SchemaInputType = Schema | SchemaConstructor;
|
|
272
273
|
export declare function getSchema(value: SchemaInputType): Schema;
|
|
273
274
|
export declare function getFields(value: SchemaInputType): Map<string, Field>;
|
|
274
|
-
/**
|
|
275
|
-
* @deprecated should only be used by tests
|
|
276
|
-
*/
|
|
277
275
|
export declare function getStorageKey(field: Field, fieldName: string): string;
|
|
278
276
|
export declare function getFieldsWithPrivacy(value: SchemaInputType, fieldInfoMap: FieldInfoMap): Map<string, PrivacyPolicy>;
|
|
279
277
|
export declare function getFieldsWithEditPrivacy(value: SchemaInputType, fieldInfoMap: FieldInfoMap): Map<string, PrivacyPolicy>;
|
package/schema/schema.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ConstraintType = exports.optionalField = exports.requiredField = exports.NoFields = exports.ActionOperation = exports.getTransformedUpdateOp = exports.getObjectLoaderProperties = exports.getTransformedReadClause = exports.getFieldsForCreateAction = exports.getFieldsWithEditPrivacy = exports.getFieldsWithPrivacy = exports.getStorageKey = exports.getFields = exports.getSchema = exports.DBType = exports.SQLStatementOperation = void 0;
|
|
4
|
-
const
|
|
4
|
+
const names_1 = require("../names/names");
|
|
5
5
|
// we also want this transformation to exist on a per-action basis
|
|
6
6
|
// if it exists on an action, we don't do the global schema transformation
|
|
7
7
|
var SQLStatementOperation;
|
|
@@ -79,11 +79,8 @@ function getFields(value) {
|
|
|
79
79
|
return m;
|
|
80
80
|
}
|
|
81
81
|
exports.getFields = getFields;
|
|
82
|
-
/**
|
|
83
|
-
* @deprecated should only be used by tests
|
|
84
|
-
*/
|
|
85
82
|
function getStorageKey(field, fieldName) {
|
|
86
|
-
return field.storageKey || (0,
|
|
83
|
+
return field.storageKey || (0, names_1.toDBColumnOrTable)(fieldName);
|
|
87
84
|
}
|
|
88
85
|
exports.getStorageKey = getStorageKey;
|
|
89
86
|
// returns a mapping of storage key to field privacy
|
package/schema/struct_field.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.StructTypeAsList = exports.StructListType = exports.StructType = exports.StructField = void 0;
|
|
4
|
-
const camel_case_1 = require("camel-case");
|
|
5
4
|
const field_1 = require("./field");
|
|
6
5
|
const schema_1 = require("./schema");
|
|
7
6
|
const global_schema_1 = require("../core/global_schema");
|
|
8
7
|
const logger_1 = require("../core/logger");
|
|
8
|
+
const names_1 = require("../names/names");
|
|
9
9
|
class StructField extends field_1.BaseField {
|
|
10
10
|
constructor(options, jsonAsList) {
|
|
11
11
|
super();
|
|
@@ -40,10 +40,14 @@ class StructField extends field_1.BaseField {
|
|
|
40
40
|
const field = this.options.fields[k];
|
|
41
41
|
// check two values
|
|
42
42
|
// store in dbKey format
|
|
43
|
-
//
|
|
43
|
+
// check both fieldName and dbKey and store in dbKey for
|
|
44
|
+
// serialization to db
|
|
45
|
+
// we should only have if it in fieldName format for non-tests
|
|
46
|
+
// but checking for backwards compatibility and to make
|
|
47
|
+
// sure we don't break anything
|
|
44
48
|
let dbKey = (0, schema_1.getStorageKey)(field, k);
|
|
45
|
-
let
|
|
46
|
-
let val = obj[
|
|
49
|
+
let fieldName = (0, names_1.toFieldName)(k);
|
|
50
|
+
let val = obj[fieldName];
|
|
47
51
|
if (val === undefined && obj[dbKey] !== undefined) {
|
|
48
52
|
val = obj[dbKey];
|
|
49
53
|
}
|
|
@@ -114,20 +118,19 @@ class StructField extends field_1.BaseField {
|
|
|
114
118
|
let valid = true;
|
|
115
119
|
for (const k in this.options.fields) {
|
|
116
120
|
const field = this.options.fields[k];
|
|
117
|
-
// TODO more #510
|
|
118
121
|
let dbKey = (0, schema_1.getStorageKey)(field, k);
|
|
119
|
-
let
|
|
120
|
-
let val = obj[
|
|
122
|
+
let fieldName = (0, names_1.toFieldName)(k);
|
|
123
|
+
let val = obj[fieldName];
|
|
121
124
|
let uniqueKeyField = false;
|
|
122
125
|
if (this.validateUniqueKey !== undefined &&
|
|
123
|
-
(
|
|
126
|
+
(fieldName === this.validateUniqueKey ||
|
|
124
127
|
k === this.validateUniqueKey ||
|
|
125
128
|
dbKey === this.validateUniqueKey)) {
|
|
126
129
|
// this.validateUniqueKey = camelKey;
|
|
127
130
|
uniqueKeyField = true;
|
|
128
131
|
}
|
|
129
132
|
if (uniqueKeyField && this.checkUniqueKey) {
|
|
130
|
-
this.validateUniqueKey =
|
|
133
|
+
this.validateUniqueKey = fieldName;
|
|
131
134
|
}
|
|
132
135
|
if (val === undefined && obj[dbKey] !== undefined) {
|
|
133
136
|
if (uniqueKeyField && this.checkUniqueKey) {
|
package/scripts/read_schema.js
CHANGED
|
@@ -28,10 +28,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
29
|
const glob = __importStar(require("glob"));
|
|
30
30
|
const path = __importStar(require("path"));
|
|
31
|
-
const pascal_case_1 = require("pascal-case");
|
|
32
31
|
const minimist_1 = __importDefault(require("minimist"));
|
|
33
32
|
const parse_1 = require("../parse_schema/parse");
|
|
34
33
|
const ast_1 = require("../tsc/ast");
|
|
34
|
+
const names_1 = require("../names/names");
|
|
35
35
|
function main() {
|
|
36
36
|
const options = (0, minimist_1.default)(process.argv.slice(2));
|
|
37
37
|
if (!options.path) {
|
|
@@ -70,7 +70,7 @@ function main() {
|
|
|
70
70
|
if (relativePath !== undefined) {
|
|
71
71
|
s.schemaPath = relativePath;
|
|
72
72
|
}
|
|
73
|
-
potentialSchemas[(0,
|
|
73
|
+
potentialSchemas[(0, names_1.toClassName)(schema)] = s;
|
|
74
74
|
}
|
|
75
75
|
// console.log(potentialSchemas);
|
|
76
76
|
// NB: do not change this to async/await
|