remult 0.21.1-exp.9 → 0.22.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.
Files changed (202) hide show
  1. package/SseSubscriptionServer.js +9 -9
  2. package/ably.js +1 -1
  3. package/esm/SseSubscriptionServer.js +11 -11
  4. package/esm/ably.js +2 -2
  5. package/esm/graphql.js +194 -71
  6. package/esm/index.d.ts +10 -10
  7. package/esm/index.js +8 -8
  8. package/esm/inputTypes.js +1 -1
  9. package/esm/live-query/data-provider-live-query-storage.d.ts +3 -3
  10. package/esm/live-query/data-provider-live-query-storage.js +12 -9
  11. package/esm/myLog.js +2 -2
  12. package/esm/postgres/postgres-data-provider.d.ts +2 -2
  13. package/esm/postgres/postgres-data-provider.js +20 -14
  14. package/esm/postgres/schema-builder.d.ts +1 -1
  15. package/esm/postgres/schema-builder.js +26 -19
  16. package/esm/remult-express.js +2 -2
  17. package/esm/remult-fastify.js +9 -7
  18. package/esm/remult-fresh.d.ts +1 -1
  19. package/esm/remult-fresh.js +5 -8
  20. package/esm/remult-knex/index.d.ts +3 -3
  21. package/esm/remult-knex/index.js +73 -57
  22. package/esm/remult-mongo.js +36 -27
  23. package/esm/remult-next.d.ts +3 -3
  24. package/esm/remult-next.js +14 -13
  25. package/esm/remult-sveltekit.js +10 -10
  26. package/esm/server/JsonEntityFileStorage.js +3 -1
  27. package/esm/server/core.d.ts +2 -2
  28. package/esm/server/core.js +2 -2
  29. package/esm/server/expressBridge.d.ts +3 -3
  30. package/esm/server/expressBridge.js +265 -247
  31. package/esm/server/index.d.ts +2 -2
  32. package/esm/server/index.js +5 -2
  33. package/esm/server/initDataProvider.js +1 -1
  34. package/esm/src/backend-tests/backend-database-test-setup.backend-spec.d.ts +1 -1
  35. package/esm/src/backend-tests/backend-database-test-setup.backend-spec.js +47 -38
  36. package/esm/src/buildRestDataProvider.d.ts +1 -1
  37. package/esm/src/buildRestDataProvider.js +21 -13
  38. package/esm/src/column-interfaces.d.ts +9 -9
  39. package/esm/src/column.js +14 -11
  40. package/esm/src/context.d.ts +8 -8
  41. package/esm/src/context.js +24 -23
  42. package/esm/src/data-api.d.ts +0 -1
  43. package/esm/src/data-api.js +38 -37
  44. package/esm/src/data-interfaces.js +1 -1
  45. package/esm/src/data-providers/array-entity-data-provider.js +9 -9
  46. package/esm/src/data-providers/in-memory-database.d.ts +1 -1
  47. package/esm/src/data-providers/in-memory-database.js +3 -1
  48. package/esm/src/data-providers/json-data-provider.js +8 -8
  49. package/esm/src/data-providers/rest-data-provider.js +51 -35
  50. package/esm/src/data-providers/sql-database.d.ts +5 -5
  51. package/esm/src/data-providers/sql-database.js +52 -35
  52. package/esm/src/data-providers/web-sql-data-provider.d.ts +4 -4
  53. package/esm/src/data-providers/web-sql-data-provider.js +15 -13
  54. package/esm/src/entity.d.ts +24 -24
  55. package/esm/src/filter/filter-consumer-bridge-to-sql-request.d.ts +4 -4
  56. package/esm/src/filter/filter-consumer-bridge-to-sql-request.js +35 -20
  57. package/esm/src/filter/filter-interfaces.d.ts +7 -7
  58. package/esm/src/filter/filter-interfaces.js +108 -88
  59. package/esm/src/live-query/LiveQueryClient.js +32 -29
  60. package/esm/src/live-query/SseSubscriptionClient.d.ts +1 -1
  61. package/esm/src/live-query/SseSubscriptionClient.js +14 -14
  62. package/esm/src/live-query/SubscriptionChannel.d.ts +3 -3
  63. package/esm/src/live-query/SubscriptionChannel.js +27 -25
  64. package/esm/src/live-query/SubscriptionServer.js +24 -20
  65. package/esm/src/remult-proxy.d.ts +1 -1
  66. package/esm/src/remult-proxy.js +86 -30
  67. package/esm/src/remult3/DecoratorReplacer.d.ts +1 -1
  68. package/esm/src/remult3/RepositoryImplementation.d.ts +18 -18
  69. package/esm/src/remult3/RepositoryImplementation.js +267 -183
  70. package/esm/src/remult3/remult3.d.ts +49 -49
  71. package/esm/src/remult3/remult3.js +0 -1
  72. package/esm/src/server-action.d.ts +3 -3
  73. package/esm/src/server-action.js +51 -37
  74. package/esm/src/shared-tests/db-tests-setup.d.ts +8 -8
  75. package/esm/src/shared-tests/db-tests-setup.js +10 -10
  76. package/esm/src/shared-tests/db-tests.db-tests.d.ts +1 -1
  77. package/esm/src/shared-tests/db-tests.db-tests.js +278 -176
  78. package/esm/src/shared-tests/deleteAll.d.ts +1 -1
  79. package/esm/src/shared-tests/deleteAll.js +1 -1
  80. package/esm/src/shared-tests/entityWithValidations.js +1 -1
  81. package/esm/src/shared-tests/test-custom-id-column.spec.js +4 -4
  82. package/esm/src/shared-tests/test-special-value.spec.js +12 -12
  83. package/esm/src/shared-tests/test-update-with-null.spec.js +10 -6
  84. package/esm/src/sort.d.ts +2 -2
  85. package/esm/src/sort.js +12 -10
  86. package/esm/src/tests/TestDataApiResponse.d.ts +1 -1
  87. package/esm/src/tests/TestDataApiResponse.js +3 -4
  88. package/esm/src/tests/createData.js +2 -2
  89. package/esm/src/tests/d.js +1 -1
  90. package/esm/src/tests/dWithPrefilter.js +1 -1
  91. package/esm/src/tests/entityForCustomFilter.d.ts +4 -4
  92. package/esm/src/tests/entityForCustomFilter.js +12 -4
  93. package/esm/src/tests/entityWithValidationsOnColumn.js +1 -1
  94. package/esm/src/tests/frontend-database-tests-setup.spec.d.ts +1 -1
  95. package/esm/src/tests/frontend-database-tests-setup.spec.js +14 -14
  96. package/esm/src/tests/h.js +4 -4
  97. package/esm/src/tests/remult-3-entities.d.ts +2 -2
  98. package/esm/src/tests/remult-3-entities.js +6 -6
  99. package/esm/src/tests/testHelper.spec.d.ts +6 -6
  100. package/esm/src/tests/testHelper.spec.js +49 -38
  101. package/esm/src/tests/testModel/models.js +4 -4
  102. package/esm/src/validators.d.ts +1 -1
  103. package/esm/src/validators.js +10 -7
  104. package/esm/src/valueConverters.d.ts +1 -1
  105. package/esm/src/valueConverters.js +68 -55
  106. package/graphql.js +157 -43
  107. package/index.d.ts +10 -10
  108. package/inputTypes.js +1 -1
  109. package/live-query/data-provider-live-query-storage.d.ts +3 -3
  110. package/live-query/data-provider-live-query-storage.js +7 -4
  111. package/myLog.js +2 -2
  112. package/package.json +1 -1
  113. package/postgres/postgres-data-provider.d.ts +2 -2
  114. package/postgres/postgres-data-provider.js +21 -16
  115. package/postgres/schema-builder.d.ts +1 -1
  116. package/postgres/schema-builder.js +21 -14
  117. package/remult-express.js +1 -1
  118. package/remult-fastify.js +7 -7
  119. package/remult-fresh.d.ts +1 -1
  120. package/remult-fresh.js +1 -4
  121. package/remult-knex/index.d.ts +3 -3
  122. package/remult-knex/index.js +49 -34
  123. package/remult-mongo.js +33 -23
  124. package/remult-next.d.ts +3 -3
  125. package/remult-next.js +12 -13
  126. package/remult-sveltekit.js +14 -15
  127. package/server/core.d.ts +2 -2
  128. package/server/expressBridge.d.ts +3 -3
  129. package/server/expressBridge.js +274 -242
  130. package/server/index.d.ts +2 -2
  131. package/server/index.js +5 -2
  132. package/server/initDataProvider.js +1 -1
  133. package/src/backend-tests/backend-database-test-setup.backend-spec.d.ts +1 -1
  134. package/src/backend-tests/backend-database-test-setup.backend-spec.js +40 -31
  135. package/src/buildRestDataProvider.d.ts +1 -1
  136. package/src/buildRestDataProvider.js +18 -10
  137. package/src/column-interfaces.d.ts +9 -9
  138. package/src/column.js +11 -8
  139. package/src/context.d.ts +8 -8
  140. package/src/context.js +17 -16
  141. package/src/data-api.d.ts +0 -1
  142. package/src/data-api.js +40 -43
  143. package/src/data-providers/array-entity-data-provider.js +2 -2
  144. package/src/data-providers/in-memory-database.d.ts +1 -1
  145. package/src/data-providers/in-memory-database.js +3 -1
  146. package/src/data-providers/json-data-provider.js +33 -15
  147. package/src/data-providers/rest-data-provider.js +46 -31
  148. package/src/data-providers/sql-database.d.ts +5 -5
  149. package/src/data-providers/sql-database.js +40 -23
  150. package/src/data-providers/web-sql-data-provider.d.ts +4 -4
  151. package/src/data-providers/web-sql-data-provider.js +10 -8
  152. package/src/entity.d.ts +24 -24
  153. package/src/filter/filter-consumer-bridge-to-sql-request.d.ts +4 -4
  154. package/src/filter/filter-consumer-bridge-to-sql-request.js +34 -17
  155. package/src/filter/filter-interfaces.d.ts +7 -7
  156. package/src/filter/filter-interfaces.js +73 -47
  157. package/src/live-query/LiveQueryClient.js +29 -24
  158. package/src/live-query/SseSubscriptionClient.d.ts +1 -1
  159. package/src/live-query/SseSubscriptionClient.js +80 -76
  160. package/src/live-query/SubscriptionChannel.d.ts +3 -3
  161. package/src/live-query/SubscriptionChannel.js +26 -18
  162. package/src/live-query/SubscriptionServer.js +23 -17
  163. package/src/remult-proxy.d.ts +1 -1
  164. package/src/remult-proxy.js +78 -30
  165. package/src/remult3/DecoratorReplacer.d.ts +1 -1
  166. package/src/remult3/RepositoryImplementation.d.ts +18 -18
  167. package/src/remult3/RepositoryImplementation.js +312 -209
  168. package/src/remult3/remult3.d.ts +49 -49
  169. package/src/remult3/remult3.js +0 -1
  170. package/src/server-action.d.ts +3 -3
  171. package/src/server-action.js +49 -31
  172. package/src/shared-tests/db-tests-setup.d.ts +8 -8
  173. package/src/shared-tests/db-tests-setup.js +6 -6
  174. package/src/shared-tests/db-tests.db-tests.d.ts +1 -1
  175. package/src/shared-tests/db-tests.db-tests.js +349 -152
  176. package/src/shared-tests/deleteAll.d.ts +1 -1
  177. package/src/shared-tests/entityWithValidations.js +1 -1
  178. package/src/shared-tests/test-custom-id-column.spec.js +4 -4
  179. package/src/shared-tests/test-special-value.spec.js +9 -9
  180. package/src/shared-tests/test-update-with-null.spec.js +8 -4
  181. package/src/sort.d.ts +2 -2
  182. package/src/sort.js +9 -7
  183. package/src/tests/TestDataApiResponse.d.ts +1 -1
  184. package/src/tests/TestDataApiResponse.js +3 -4
  185. package/src/tests/createData.js +1 -1
  186. package/src/tests/d.js +1 -1
  187. package/src/tests/dWithPrefilter.js +1 -1
  188. package/src/tests/entityForCustomFilter.d.ts +4 -4
  189. package/src/tests/entityForCustomFilter.js +16 -6
  190. package/src/tests/entityWithValidationsOnColumn.js +1 -1
  191. package/src/tests/frontend-database-tests-setup.spec.d.ts +1 -1
  192. package/src/tests/frontend-database-tests-setup.spec.js +8 -8
  193. package/src/tests/h.js +3 -3
  194. package/src/tests/remult-3-entities.d.ts +2 -2
  195. package/src/tests/remult-3-entities.js +8 -4
  196. package/src/tests/testHelper.spec.d.ts +6 -6
  197. package/src/tests/testHelper.spec.js +37 -26
  198. package/src/tests/testModel/models.js +3 -3
  199. package/src/validators.d.ts +1 -1
  200. package/src/validators.js +18 -9
  201. package/src/valueConverters.d.ts +1 -1
  202. package/src/valueConverters.js +38 -21
@@ -31,7 +31,7 @@ var SseSubscriptionServer = /** @class */ (function () {
31
31
  delete c.channels[channel];
32
32
  else
33
33
  c.channels[channel] = true;
34
- res.success({ status: "ok" });
34
+ res.success({ status: 'ok' });
35
35
  this.debug();
36
36
  return;
37
37
  }
@@ -84,14 +84,14 @@ var SseSubscriptionServer = /** @class */ (function () {
84
84
  res.writeHead(200, {
85
85
  'Content-Type': 'text/event-stream',
86
86
  'Cache-Control': 'no-cache',
87
- 'Connection': 'keep-alive'
87
+ Connection: 'keep-alive',
88
88
  });
89
89
  var cc = new clientConnection(res);
90
90
  //const lastEventId = req.headers['last-event-id'];
91
91
  this.connections.push(cc);
92
92
  this.debug();
93
93
  //@ts-ignore
94
- req.on("close", function () {
94
+ req.on('close', function () {
95
95
  cc.close();
96
96
  _this.connections = _this.connections.filter(function (s) { return s !== cc; });
97
97
  _this.debug();
@@ -102,7 +102,7 @@ var SseSubscriptionServer = /** @class */ (function () {
102
102
  SseSubscriptionServer.prototype.debug = function () {
103
103
  this.debugFileSaver(this.connections.map(function (x) { return ({
104
104
  id: x.connectionId,
105
- channels: x.channels
105
+ channels: x.channels,
106
106
  }); }));
107
107
  };
108
108
  return SseSubscriptionServer;
@@ -114,7 +114,7 @@ var clientConnection = /** @class */ (function () {
114
114
  this.channels = {};
115
115
  this.closed = false;
116
116
  this.connectionId = uuid_1.v4();
117
- this.write(this.connectionId, "connectionId");
117
+ this.write(this.connectionId, 'connectionId');
118
118
  this.sendLiveMessage();
119
119
  }
120
120
  clientConnection.prototype.close = function () {
@@ -123,11 +123,11 @@ var clientConnection = /** @class */ (function () {
123
123
  this.closed = true;
124
124
  };
125
125
  clientConnection.prototype.write = function (eventData, eventType) {
126
- if (eventType === void 0) { eventType = "message"; }
127
- var event = "event:" + eventType;
126
+ if (eventType === void 0) { eventType = 'message'; }
127
+ var event = 'event:' + eventType;
128
128
  // if (id != undefined)
129
129
  // event += "\nid:" + id;
130
- this.response.write(event + "\ndata:" + eventData + "\n\n");
130
+ this.response.write(event + '\ndata:' + eventData + '\n\n');
131
131
  if (this.response.flush)
132
132
  this.response.flush();
133
133
  };
@@ -135,7 +135,7 @@ var clientConnection = /** @class */ (function () {
135
135
  var _this = this;
136
136
  if (this.closed)
137
137
  return;
138
- this.write("", "keep-alive");
138
+ this.write('', 'keep-alive');
139
139
  this.timeOutRef = setTimeout(function () {
140
140
  _this.sendLiveMessage();
141
141
  }, 45000);
package/ably.js CHANGED
@@ -30,7 +30,7 @@ var AblySubscriptionClient = /** @class */ (function () {
30
30
  }];
31
31
  }
32
32
  });
33
- }); }
33
+ }); },
34
34
  }];
35
35
  });
36
36
  });
@@ -22,7 +22,7 @@ export class SseSubscriptionServer {
22
22
  delete c.channels[channel];
23
23
  else
24
24
  c.channels[channel] = true;
25
- res.success({ status: "ok" });
25
+ res.success({ status: 'ok' });
26
26
  this.debug();
27
27
  return;
28
28
  }
@@ -49,25 +49,25 @@ export class SseSubscriptionServer {
49
49
  res.writeHead(200, {
50
50
  'Content-Type': 'text/event-stream',
51
51
  'Cache-Control': 'no-cache',
52
- 'Connection': 'keep-alive'
52
+ Connection: 'keep-alive',
53
53
  });
54
54
  const cc = new clientConnection(res);
55
55
  //const lastEventId = req.headers['last-event-id'];
56
56
  this.connections.push(cc);
57
57
  this.debug();
58
58
  //@ts-ignore
59
- req.on("close", () => {
59
+ req.on('close', () => {
60
60
  cc.close();
61
- this.connections = this.connections.filter(s => s !== cc);
61
+ this.connections = this.connections.filter((s) => s !== cc);
62
62
  this.debug();
63
63
  });
64
64
  return cc;
65
65
  }
66
66
  //@internal
67
67
  debug() {
68
- this.debugFileSaver(this.connections.map(x => ({
68
+ this.debugFileSaver(this.connections.map((x) => ({
69
69
  id: x.connectionId,
70
- channels: x.channels
70
+ channels: x.channels,
71
71
  })));
72
72
  }
73
73
  }
@@ -77,7 +77,7 @@ export class clientConnection {
77
77
  this.channels = {};
78
78
  this.closed = false;
79
79
  this.connectionId = uuid();
80
- this.write(this.connectionId, "connectionId");
80
+ this.write(this.connectionId, 'connectionId');
81
81
  this.sendLiveMessage();
82
82
  }
83
83
  close() {
@@ -85,18 +85,18 @@ export class clientConnection {
85
85
  clearTimeout(this.timeOutRef);
86
86
  this.closed = true;
87
87
  }
88
- write(eventData, eventType = "message") {
89
- let event = "event:" + eventType;
88
+ write(eventData, eventType = 'message') {
89
+ let event = 'event:' + eventType;
90
90
  // if (id != undefined)
91
91
  // event += "\nid:" + id;
92
- this.response.write(event + "\ndata:" + eventData + "\n\n");
92
+ this.response.write(event + '\ndata:' + eventData + '\n\n');
93
93
  if (this.response.flush)
94
94
  this.response.flush();
95
95
  }
96
96
  sendLiveMessage() {
97
97
  if (this.closed)
98
98
  return;
99
- this.write("", "keep-alive");
99
+ this.write('', 'keep-alive');
100
100
  this.timeOutRef = setTimeout(() => {
101
101
  this.sendLiveMessage();
102
102
  }, 45000);
package/esm/ably.js CHANGED
@@ -9,12 +9,12 @@ export class AblySubscriptionClient {
9
9
  },
10
10
  subscribe: async (channel, handler) => {
11
11
  let myHandler = (y) => handler(y.data);
12
- await this.ably.channels.get(channel).subscribe(y => myHandler(y));
12
+ await this.ably.channels.get(channel).subscribe((y) => myHandler(y));
13
13
  return () => {
14
14
  myHandler = () => { };
15
15
  this.ably.channels.get(channel).unsubscribe();
16
16
  };
17
- }
17
+ },
18
18
  };
19
19
  }
20
20
  }
package/esm/graphql.js CHANGED
@@ -16,7 +16,7 @@ export function remultGraphql(options) {
16
16
  }
17
17
  const entities = (() => {
18
18
  const remult = new Remult();
19
- return options.entities?.map(x => remult.repo(x).metadata) || [];
19
+ return options.entities?.map((x) => remult.repo(x).metadata) || [];
20
20
  })();
21
21
  const types = [];
22
22
  const root = {};
@@ -24,7 +24,7 @@ export function remultGraphql(options) {
24
24
  const resolversMutation = {};
25
25
  const resolvers = { Query: resolversQuery, Mutation: resolversMutation };
26
26
  function upsertTypes(key, kind = 'type', order = 0) {
27
- let t = types.find(t => t.key === key);
27
+ let t = types.find((t) => t.key === key);
28
28
  if (!t) {
29
29
  types.push((t = {
30
30
  key,
@@ -49,6 +49,13 @@ export function remultGraphql(options) {
49
49
  }
50
50
  return t;
51
51
  }
52
+ function upsertUnion(key, values, order) {
53
+ const u = upsertTypes(key, 'union', order);
54
+ u.fields = values.map((value) => {
55
+ return { key: value, value: { Union: true } };
56
+ });
57
+ return u;
58
+ }
52
59
  // Where - GraphQL primitives
53
60
  for (const whereType of ['String', 'Int', 'Float', 'Boolean', 'ID']) {
54
61
  const currentWhere = upsertTypes(`Where${whereType}`, 'input', 20);
@@ -59,13 +66,17 @@ export function remultGraphql(options) {
59
66
  for (const operator of [...operatorType, ...operatorTypeArray]) {
60
67
  const field = {
61
68
  key: operator,
62
- value: operatorTypeArray.includes(operator) ? `[${whereType}!]` : whereType,
69
+ value: operatorTypeArray.includes(operator)
70
+ ? `[${whereType}!]`
71
+ : whereType,
63
72
  };
64
73
  currentWhere.fields.push(field);
65
74
  currentWhereNullable.fields.push(field);
66
75
  }
67
76
  // only for specific types
68
- if (whereType === 'String' || whereType === 'Int' || whereType === 'Float') {
77
+ if (whereType === 'String' ||
78
+ whereType === 'Int' ||
79
+ whereType === 'Float') {
69
80
  for (const operator of ['gt', 'gte', 'lt', 'lte']) {
70
81
  const field = {
71
82
  key: operator,
@@ -101,6 +112,7 @@ export function remultGraphql(options) {
101
112
  comment: `The globally unique \`ID\` _(_typename:id)_`,
102
113
  };
103
114
  const argClientMutationId = { key: 'clientMutationId', value: `String` };
115
+ const argErrorDetail = { key: 'error', value: `ErrorDetail` };
104
116
  for (const meta of entities) {
105
117
  const orderByFields = [];
106
118
  const key = meta.key;
@@ -126,7 +138,7 @@ export function remultGraphql(options) {
126
138
  notFound: () => (err = 'not found'),
127
139
  progress: () => { },
128
140
  };
129
- work(response, x => (result = x), arg1, req)
141
+ work(response, (x) => (result = x), arg1, req)
130
142
  .then(() => {
131
143
  if (err) {
132
144
  error(err);
@@ -134,7 +146,7 @@ export function remultGraphql(options) {
134
146
  }
135
147
  res(result);
136
148
  })
137
- .catch(err => error(err));
149
+ .catch((err) => error(err));
138
150
  });
139
151
  };
140
152
  };
@@ -146,49 +158,103 @@ export function remultGraphql(options) {
146
158
  await work(dApi, response, setResult, arg1, meta);
147
159
  });
148
160
  };
161
+ const handleMutationWithErrors = (work) => {
162
+ return handleRequestWithDataApiContext(async (dApi, response, origSetResult, arg1, req) => {
163
+ const setResult = (item) => {
164
+ origSetResult({
165
+ clientMutationId: arg1.clientMutationId,
166
+ ...item,
167
+ });
168
+ };
169
+ return work(dApi, {
170
+ ...response,
171
+ forbidden: () => {
172
+ setResult({
173
+ error: {
174
+ __typename: 'ForbiddenError',
175
+ message: 'forbidden',
176
+ },
177
+ });
178
+ },
179
+ notFound: () => {
180
+ setResult({
181
+ error: {
182
+ __typename: 'NotFoundError',
183
+ message: 'not found',
184
+ },
185
+ });
186
+ },
187
+ error: (err) => {
188
+ const modelState = [];
189
+ if (err.modelState)
190
+ for (const key in err.modelState) {
191
+ modelState.push({
192
+ field: key,
193
+ message: err.modelState[key],
194
+ });
195
+ }
196
+ setResult({
197
+ error: {
198
+ __typename: 'ValidationError',
199
+ message: err.message,
200
+ modelState,
201
+ },
202
+ });
203
+ },
204
+ }, setResult, arg1, req);
205
+ });
206
+ };
149
207
  const queryArgsConnection = [
150
208
  {
151
209
  key: 'limit',
152
210
  value: 'Int',
153
- comment: `
154
- For **page by page** pagination.
155
- Limit the number of result.
211
+ comment: `
212
+ For **page by page** pagination.
213
+ Limit the number of result.
156
214
  _Side note: \`Math.ceil(totalCount / limit)\` to determine how many pages there are._`,
157
215
  },
158
216
  {
159
217
  key: 'page',
160
218
  value: 'Int',
161
- comment: `
162
- For **page by page** pagination.
219
+ comment: `
220
+ For **page by page** pagination.
163
221
  Select a dedicated page.`,
164
222
  },
165
- { key: 'orderBy', value: `${key}OrderBy`, comment: `Remult sorting options` },
166
- { key: 'where', value: `${key}Where`, comment: `Remult filtering options` },
223
+ {
224
+ key: 'orderBy',
225
+ value: `${key}OrderBy`,
226
+ comment: `Remult sorting options`,
227
+ },
228
+ {
229
+ key: 'where',
230
+ value: `${key}Where`,
231
+ comment: `Remult filtering options`,
232
+ },
167
233
  ];
168
234
  if (v2ConnectionAndPagination) {
169
235
  queryArgsConnection.push({
170
236
  key: 'first',
171
237
  value: 'Int',
172
- comment: `
173
- For **forward cursor** pagination
238
+ comment: `
239
+ For **forward cursor** pagination
174
240
  Takes the \`first\`: \`n\` elements from the list.`,
175
241
  }, {
176
242
  key: 'after',
177
243
  value: 'String',
178
- comment: `
179
- For **forward cursor** pagination
244
+ comment: `
245
+ For **forward cursor** pagination
180
246
  \`after\` this \`cursor\`.`,
181
247
  }, {
182
248
  key: 'last',
183
249
  value: 'Int',
184
- comment: `
185
- For **backward cursor** pagination
250
+ comment: `
251
+ For **backward cursor** pagination
186
252
  Takes the \`last\`: \`n\` elements from the list.`,
187
253
  }, {
188
254
  key: 'before',
189
255
  value: 'String',
190
- comment: `
191
- For **backward cursor** pagination
256
+ comment: `
257
+ For **backward cursor** pagination
192
258
  \`before\` this \`cursor\`.`,
193
259
  });
194
260
  }
@@ -202,8 +268,8 @@ Select a dedicated page.`,
202
268
  root[getSingleEntityKey] = handleRequestWithDataApiContext(async (dApi, response, setResult, arg1, req) => {
203
269
  await dApi.get({
204
270
  ...response,
205
- success: y => {
206
- currentType.query.resultProcessors.forEach(z => z(y));
271
+ success: (y) => {
272
+ currentType.query.resultProcessors.forEach((z) => z(y));
207
273
  setResult(y);
208
274
  },
209
275
  }, arg1.id);
@@ -259,7 +325,7 @@ Select a dedicated page.`,
259
325
  ...response,
260
326
  success: (x) => {
261
327
  setResult(x.map((y) => {
262
- currentType.query.resultProcessors.forEach(z => z(y));
328
+ currentType.query.resultProcessors.forEach((z) => z(y));
263
329
  return y;
264
330
  }));
265
331
  },
@@ -270,7 +336,7 @@ Select a dedicated page.`,
270
336
  [totalCountKey]: createResultPromise(async (response, setResult) => {
271
337
  await dApi.count({
272
338
  ...response,
273
- success: x => setResult(x.count),
339
+ success: (x) => setResult(x.count),
274
340
  }, {
275
341
  get: bridgeQueryOptionsToDataApiGet(arg1),
276
342
  }, translateWhereToRestBody(meta.fields, arg1));
@@ -282,15 +348,21 @@ Select a dedicated page.`,
282
348
  };
283
349
  // Mutation
284
350
  const root_mutation = upsertTypes('Mutation', 'type', -9);
285
- const checkCanExist = (rule) => rule !== false && !(rule === undefined && (meta.options.allowApiCrud === false || meta.options.allowApiCrud === undefined));
351
+ const checkCanExist = (rule) => rule !== false &&
352
+ !(rule === undefined &&
353
+ (meta.options.allowApiCrud === false ||
354
+ meta.options.allowApiCrud === undefined));
286
355
  if (checkCanExist(meta.options.allowApiInsert)) {
287
356
  // create
357
+ const createResolverKey = `create${getMetaType(meta)}`;
288
358
  const createInput = `Create${getMetaType(meta)}Input`;
289
359
  const createPayload = `Create${getMetaType(meta)}Payload`;
290
- const createResolverKey = `create${getMetaType(meta)}`;
291
360
  root_mutation.fields.push({
292
361
  key: createResolverKey,
293
- args: [{ key: 'input', value: `${createInput}!` }, argClientMutationId],
362
+ args: [
363
+ { key: 'input', value: `${createInput}!` },
364
+ argClientMutationId,
365
+ ],
294
366
  value: `${createPayload}`,
295
367
  comment: `Create a new \`${getMetaType(meta)}\``,
296
368
  });
@@ -298,13 +370,13 @@ Select a dedicated page.`,
298
370
  currentType.mutation.create.payload = upsertTypes(createPayload);
299
371
  currentType.mutation.create.payload.fields.push({
300
372
  key: `${toCamelCase(getMetaType(meta))}`,
301
- value: `${getMetaType(meta)}`,
302
- }, argClientMutationId);
303
- root[createResolverKey] = handleRequestWithDataApiContext(async (dApi, response, setResult, arg1, req) => {
373
+ value: getMetaType(meta),
374
+ }, argErrorDetail, argClientMutationId);
375
+ root[createResolverKey] = handleMutationWithErrors(async (dApi, response, setResult, arg1, req) => {
304
376
  await dApi.post({
305
377
  ...response,
306
- created: y => {
307
- currentType.query.resultProcessors.forEach(z => z(y));
378
+ created: (y) => {
379
+ currentType.query.resultProcessors.forEach((z) => z(y));
308
380
  setResult({
309
381
  [toCamelCase(getMetaType(meta))]: y,
310
382
  });
@@ -320,7 +392,11 @@ Select a dedicated page.`,
320
392
  const updateResolverKey = `update${getMetaType(meta)}`;
321
393
  root_mutation.fields.push({
322
394
  key: updateResolverKey,
323
- args: [argId, { key: 'patch', value: `${updateInput}!` }, argClientMutationId],
395
+ args: [
396
+ argId,
397
+ { key: 'patch', value: `${updateInput}!` },
398
+ argClientMutationId,
399
+ ],
324
400
  value: `${updatePayload}`,
325
401
  comment: `Update a \`${getMetaType(meta)}\``,
326
402
  });
@@ -329,12 +405,12 @@ Select a dedicated page.`,
329
405
  currentType.mutation.update.payload.fields.push({
330
406
  key: `${toCamelCase(getMetaType(meta))}`,
331
407
  value: `${getMetaType(meta)}`,
332
- }, argClientMutationId);
333
- root[updateResolverKey] = handleRequestWithDataApiContext(async (dApi, response, setResult, arg1, req) => {
408
+ }, argErrorDetail, argClientMutationId);
409
+ root[updateResolverKey] = handleMutationWithErrors(async (dApi, response, setResult, arg1, req) => {
334
410
  await dApi.put({
335
411
  ...response,
336
- success: y => {
337
- currentType.query.resultProcessors.forEach(z => z(y));
412
+ success: (y) => {
413
+ currentType.query.resultProcessors.forEach((z) => z(y));
338
414
  setResult({
339
415
  [toCamelCase(getMetaType(meta))]: y,
340
416
  });
@@ -358,8 +434,8 @@ Select a dedicated page.`,
358
434
  currentType.mutation.delete.payload.fields.push({
359
435
  key: deletedResultKey,
360
436
  value: 'ID',
361
- }, argClientMutationId);
362
- root[deleteResolverKey] = handleRequestWithDataApiContext(async (dApi, response, setResult, arg1, req) => {
437
+ }, argErrorDetail, argClientMutationId);
438
+ root[deleteResolverKey] = handleMutationWithErrors(async (dApi, response, setResult, arg1, req) => {
363
439
  await dApi.delete({
364
440
  ...response,
365
441
  deleted: () => {
@@ -389,7 +465,7 @@ Select a dedicated page.`,
389
465
  break;
390
466
  }
391
467
  const ref = entities.find((i) => i.entityType === f.valueType);
392
- currentType.query.resultProcessors.push(r => {
468
+ currentType.query.resultProcessors.push((r) => {
393
469
  r[nodeIdKey] = () => getMetaType(meta) + ':' + meta.idMetadata.getId(r);
394
470
  });
395
471
  if (ref !== undefined) {
@@ -400,7 +476,7 @@ Select a dedicated page.`,
400
476
  comment: f.caption,
401
477
  });
402
478
  const refKey = ref.key;
403
- currentType.query.resultProcessors.push(r => {
479
+ currentType.query.resultProcessors.push((r) => {
404
480
  const val = r[f.key];
405
481
  if (val === null || val === undefined)
406
482
  return null;
@@ -424,7 +500,7 @@ Select a dedicated page.`,
424
500
  order: 10,
425
501
  comment: `List all \`${getMetaType(meta)}\` of \`${refKey}\``,
426
502
  });
427
- refT.query.resultProcessors.push(r => {
503
+ refT.query.resultProcessors.push((r) => {
428
504
  const val = r.id;
429
505
  r[key] = async (args, req, gqlInfo) => {
430
506
  return await root[key]({
@@ -522,6 +598,46 @@ Select a dedicated page.`,
522
598
  const nodeInterface = upsertTypes('Node', 'interface', 31);
523
599
  nodeInterface.comment = `Node interface of remult entities (eg: nodeId: \`Task:1\` so \`__typename:id\`)`;
524
600
  nodeInterface.fields.push(argNodeId);
601
+ upsertUnion(argErrorDetail.value, ['ValidationError', 'ForbiddenError', 'NotFoundError'], 32);
602
+ const errorInterface = upsertTypes('Error', 'interface', 33);
603
+ errorInterface.comment = `Error interface of remult entities`;
604
+ errorInterface.fields.push({
605
+ key: 'message',
606
+ value: 'String!',
607
+ });
608
+ const validationErrorInterface = upsertTypes('ValidationError', 'type_impl_error', 34);
609
+ validationErrorInterface.comment = `Validation Error`;
610
+ validationErrorInterface.fields.push({
611
+ key: 'message',
612
+ value: 'String!',
613
+ });
614
+ validationErrorInterface.fields.push({
615
+ key: 'modelState',
616
+ value: '[ValidationErrorModelState!]!',
617
+ });
618
+ const validationErrorModelStateInterface = upsertTypes('ValidationErrorModelState', 'type', 34);
619
+ validationErrorModelStateInterface.comment = `Validation Error Model State`;
620
+ validationErrorModelStateInterface.fields.push({
621
+ key: 'field',
622
+ value: 'String!',
623
+ });
624
+ validationErrorModelStateInterface.fields.push({
625
+ key: 'message',
626
+ value: 'String!',
627
+ });
628
+ // progress: () => { },
629
+ const forbiddenErrorInterface = upsertTypes('ForbiddenError', 'type_impl_error', 34);
630
+ forbiddenErrorInterface.comment = `Forbidden Error`;
631
+ forbiddenErrorInterface.fields.push({
632
+ key: 'message',
633
+ value: 'String!',
634
+ });
635
+ const notFoundErrorInterface = upsertTypes('NotFoundError', 'type_impl_error', 34);
636
+ notFoundErrorInterface.comment = `Not Found Error`;
637
+ notFoundErrorInterface.fields.push({
638
+ key: 'message',
639
+ value: 'String!',
640
+ });
525
641
  return {
526
642
  resolvers,
527
643
  rootValue: root,
@@ -533,19 +649,26 @@ Select a dedicated page.`,
533
649
  if (kind === 'type_impl_node') {
534
650
  prefix = `type ${key} implements Node`;
535
651
  }
536
- const type = blockFormat({
537
- prefix,
538
- data: fields
539
- .sort((a, b) => (a.order ? a.order : 0) - (b.order ? b.order : 0))
540
- .map(field => fieldFormat(field)),
541
- comment: comment ?? `The ${kind} for \`${key}\``,
542
- });
652
+ if (kind === 'type_impl_error') {
653
+ prefix = `type ${key} implements Error`;
654
+ }
655
+ const type = kind === 'union'
656
+ ? `union ${key} = ${fields.map((field) => field.key).join(' | ')}`
657
+ : blockFormat({
658
+ prefix,
659
+ data: fields
660
+ .sort((a, b) => (a.order ? a.order : 0) - (b.order ? b.order : 0))
661
+ .map((field) => fieldFormat(field)),
662
+ comment: comment ?? `The ${kind} for \`${key}\``,
663
+ });
543
664
  const orderByStr = orderBy.length > 0 ? `\n\n${orderBy.join('\n\n')}` : ``;
544
665
  const whereTypeStr = whereType.length > 0 ? `\n\n${whereType.join('\n\n')}` : ``;
545
- const whereTypeSubFieldsStr = whereTypeSubFields.length > 0 ? `\n\n${whereTypeSubFields.join('\n\n')}` : ``;
666
+ const whereTypeSubFieldsStr = whereTypeSubFields.length > 0
667
+ ? `\n\n${whereTypeSubFields.join('\n\n')}`
668
+ : ``;
546
669
  return `${type}${orderByStr}${whereTypeStr}${whereTypeSubFieldsStr}`;
547
670
  })
548
- .join(`\n\n`)}
671
+ .join(`\n\n`)}
549
672
  `,
550
673
  };
551
674
  }
@@ -567,12 +690,12 @@ function blockFormat(obj) {
567
690
  if (obj.data.length === 0) {
568
691
  return ``;
569
692
  }
570
- const str = `${obj.prefix} {
571
- ${obj.data.join('\n ')}
693
+ const str = `${obj.prefix} {
694
+ ${obj.data.join('\n ')}
572
695
  }`;
573
- let commentsStr = `"""
574
- ${obj.comment}
575
- """
696
+ let commentsStr = `"""
697
+ ${obj.comment}
698
+ """
576
699
  `;
577
700
  if (_removeComments) {
578
701
  commentsStr = ``;
@@ -582,17 +705,17 @@ ${obj.comment}
582
705
  function argsFormat(args) {
583
706
  if (args) {
584
707
  return `(${args
585
- .map(arg => {
586
- let strComment = `
587
- """
588
- ${arg.comment}
589
- """
708
+ .map((arg) => {
709
+ let strComment = `
710
+ """
711
+ ${arg.comment}
712
+ """
590
713
  `;
591
714
  if (_removeComments || !arg.comment) {
592
715
  strComment = ``;
593
716
  }
594
717
  if (strComment) {
595
- return `${strComment} ${arg.key}: ${arg.value}
718
+ return `${strComment} ${arg.key}: ${arg.value}
596
719
  `;
597
720
  }
598
721
  return `${arg.key}: ${arg.value}`;
@@ -603,9 +726,9 @@ function argsFormat(args) {
603
726
  }
604
727
  function fieldFormat(field) {
605
728
  // First, the comment
606
- let strComment = `"""
607
- ${field.comment}
608
- """
729
+ let strComment = `"""
730
+ ${field.comment}
731
+ """
609
732
  `;
610
733
  if (_removeComments || !field.comment) {
611
734
  strComment = ``;
@@ -638,7 +761,7 @@ function bridgeQueryOptionsToDataApiGet(arg1) {
638
761
  if (orderBy) {
639
762
  if (key === '_sort') {
640
763
  const sort_keys = [];
641
- Object.keys(orderBy).forEach(sort_key => {
764
+ Object.keys(orderBy).forEach((sort_key) => {
642
765
  sort_keys.push(sort_key);
643
766
  });
644
767
  if (sort_keys.length > 0) {
@@ -647,7 +770,7 @@ function bridgeQueryOptionsToDataApiGet(arg1) {
647
770
  }
648
771
  else if (key === '_order') {
649
772
  const sort_directions = [];
650
- Object.keys(orderBy).forEach(sort_key => {
773
+ Object.keys(orderBy).forEach((sort_key) => {
651
774
  const direction = orderBy[sort_key].toLowerCase();
652
775
  sort_directions.push(direction);
653
776
  });
@@ -674,10 +797,10 @@ export function translateWhereToRestBody(fields, { where }) {
674
797
  what(val);
675
798
  };
676
799
  for (const op of ['gt', 'gte', 'lt', 'lte', 'ne', 'in']) {
677
- tr(op, val => (result[field.key + '.' + op] = val));
800
+ tr(op, (val) => (result[field.key + '.' + op] = val));
678
801
  }
679
- tr('nin', x => (result[field.key + '.ne'] = x));
680
- tr('eq', x => (result[field.key] = x));
802
+ tr('nin', (x) => (result[field.key + '.ne'] = x));
803
+ tr('eq', (x) => (result[field.key] = x));
681
804
  }
682
805
  }
683
806
  if (where.OR) {