@technicity/data-service-generator 0.5.3 → 0.5.7

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.
@@ -679,6 +679,11 @@ async function getJSONSchemaWhere(table) {
679
679
  properties: { $like: { type: "string", minLength: 1 } },
680
680
  additionalProperties: false,
681
681
  },
682
+ {
683
+ type: "object",
684
+ properties: { $nlike: { type: "string", minLength: 1 } },
685
+ additionalProperties: false,
686
+ },
682
687
  {
683
688
  type: "object",
684
689
  properties: { $in: { type: "array", items: v } },
@@ -814,14 +819,17 @@ function getTypeShared() {
814
819
  last: number;
815
820
  after?: string;
816
821
  before?: string;
822
+ } | {
823
+ limit: number;
824
+ offset?: number;
817
825
  }
818
826
 
819
827
  export type ListPaginated<T> = {
820
828
  paginationInfo: {
821
- hasPreviousPage: boolean,
822
- hasNextPage: boolean,
823
- startCursor: string | number,
824
- endCursor: string | number,
829
+ hasPreviousPage?: boolean,
830
+ hasNextPage?: boolean,
831
+ startCursor?: string | number,
832
+ endCursor?: string | number,
825
833
  totalCount: number,
826
834
  },
827
835
  results: Array<T>,
package/dist/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export { generate } from "./generation/generate";
2
2
  export { SDKNotFoundError } from "./runtime/lib/SDKNotFoundError";
3
+ export { traverseFieldArgs } from "./traverseFieldArgs";
package/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SDKNotFoundError = exports.generate = void 0;
3
+ exports.traverseFieldArgs = exports.SDKNotFoundError = exports.generate = void 0;
4
4
  var generate_1 = require("./generation/generate");
5
5
  Object.defineProperty(exports, "generate", { enumerable: true, get: function () { return generate_1.generate; } });
6
6
  var SDKNotFoundError_1 = require("./runtime/lib/SDKNotFoundError");
7
7
  Object.defineProperty(exports, "SDKNotFoundError", { enumerable: true, get: function () { return SDKNotFoundError_1.SDKNotFoundError; } });
8
+ var traverseFieldArgs_1 = require("./traverseFieldArgs");
9
+ Object.defineProperty(exports, "traverseFieldArgs", { enumerable: true, get: function () { return traverseFieldArgs_1.traverseFieldArgs; } });
@@ -88,29 +88,57 @@ async function getData(input, dbCall, formatQuery, dialect) {
88
88
  const context = {};
89
89
  const action = input.action;
90
90
  const primaryKey = input.artifacts[input.resource].primaryKey;
91
+ let paginationType;
92
+ let limit = undefined;
93
+ let offset = undefined;
91
94
  let rowWithMatchingCursor = undefined;
92
95
  if (action === "findManyPaginated") {
93
96
  if (input.args?.$paginate == null) {
94
97
  throw new Error("$paginate required but not supplied");
95
98
  }
96
- if (input.args.$paginate.after != null ||
97
- input.args.$paginate.before != null) {
98
- const cursor = input.args.$paginate.after != null
99
- ? input.args.$paginate.after
100
- : input.args.$paginate.before;
101
- rowWithMatchingCursor = await dbCall(formatQuery("SELECT * FROM ?? WHERE ?? = ?", [
102
- input.resource,
103
- primaryKey,
104
- cursor_1.decodeCursor(cursor),
105
- ])).then((xs) => xs[0]);
99
+ if (typeof input?.args?.$paginate?.limit === "number") {
100
+ paginationType = "limit-offset";
101
+ limit = input.args.$paginate.limit;
102
+ offset = input.args.$paginate.offset;
106
103
  }
104
+ else {
105
+ paginationType = "cursor";
106
+ limit = (typeof input?.args?.$paginate?.first === "number"
107
+ ? input?.args?.$paginate?.first
108
+ : input?.args?.$paginate?.last);
109
+ // + 1 to peek if there is more data
110
+ limit += 1;
111
+ if (input.args.$paginate.after != null ||
112
+ input.args.$paginate.before != null) {
113
+ const cursor = input.args.$paginate.after != null
114
+ ? input.args.$paginate.after
115
+ : input.args.$paginate.before;
116
+ rowWithMatchingCursor = await dbCall(formatQuery("SELECT * FROM ?? WHERE ?? = ?", [
117
+ input.resource,
118
+ primaryKey,
119
+ cursor_1.decodeCursor(cursor),
120
+ ])).then((xs) => xs[0]);
121
+ }
122
+ }
123
+ }
124
+ else if (action === "findMany") {
125
+ limit = input?.args?.$limit;
107
126
  }
108
127
  // we need to read the query AST and build a new "SQL AST" from which the SQL and
109
128
  // const sqlAST = queryAST.queryASTToSqlAST(resolveInfo, options, context);
110
129
  const fields = input.fields ?? getScalarFields(input.resource, input.artifacts);
111
- const orderByListPaginatedRootResult = action === "findManyPaginated"
112
- ? getOrderBy_1.getOrderBy(input.args, primaryKey)
113
- : undefined;
130
+ const orderByListPaginatedRootResult =
131
+ // MSSQL's OFFSET and FETCH requires ORDER BY, so we need to provide a fallback
132
+ dialect === "mssql" && paginationType === "limit-offset"
133
+ ? {
134
+ orderBy: getOrderBy_1.getOrderBy(input.args, primaryKey)?.orderBy ?? [
135
+ { column: primaryKey, direction: "asc" },
136
+ ],
137
+ flip: false,
138
+ }
139
+ : action === "findManyPaginated"
140
+ ? getOrderBy_1.getOrderBy(input.args, primaryKey)
141
+ : undefined;
114
142
  const grabMany = action === "findMany" ||
115
143
  action === "findManyPaginated" ||
116
144
  action === "updateMany" ||
@@ -134,23 +162,21 @@ async function getData(input, dbCall, formatQuery, dialect) {
134
162
  }
135
163
  // TODO - remove if limit support added for mysql dialect
136
164
  if (action === "findMany" || action === "findManyPaginated") {
137
- let limit = undefined;
138
- if (action === "findManyPaginated") {
139
- limit = (typeof input?.args?.$paginate?.first === "number"
140
- ? input?.args?.$paginate?.first
141
- : input?.args?.$paginate?.last);
142
- // + 1 to peek if there is more data
143
- limit += 1;
144
- }
145
- else {
146
- limit = input?.args?.$limit;
147
- }
148
165
  if (typeof limit === "number") {
149
- if (dialect === "mysql") {
150
- sql += ` LIMIT ${limit}`;
166
+ const escape = stringifyWhere_1.getEscape(dialect);
167
+ if (dialect === "mssql") {
168
+ if (typeof offset === "number") {
169
+ sql += ` OFFSET ${escape(offset)} ROWS FETCH NEXT ${escape(limit)} ROWS ONLY`;
170
+ }
171
+ else {
172
+ sql = sql.replace("SELECT", `SELECT TOP ${escape(limit)}`);
173
+ }
151
174
  }
152
175
  else {
153
- sql = sql.replace("SELECT", `SELECT TOP ${limit}`);
176
+ sql += ` LIMIT ${escape(limit)}`;
177
+ if (typeof offset === "number") {
178
+ sql += ` OFFSET ${escape(offset)}`;
179
+ }
154
180
  }
155
181
  }
156
182
  }
@@ -194,6 +220,8 @@ async function getData(input, dbCall, formatQuery, dialect) {
194
220
  // We don't want the where clause to include cursor-related stuff
195
221
  delete argsTotalCount.$paginate.after;
196
222
  delete argsTotalCount.$paginate.before;
223
+ // We don't need offset
224
+ delete argsTotalCount.$paginate.offset;
197
225
  }
198
226
  }
199
227
  const sqlASTTotalCount = getSqlAst_1.getSqlAst({
@@ -213,9 +241,16 @@ async function getData(input, dbCall, formatQuery, dialect) {
213
241
  // getOrderBy adds an element if paginating, so deleting args.$orderBy
214
242
  // isn't sufficient.
215
243
  delete sqlASTTotalCount.orderBy;
216
- data = await wrapListPaginated(data, input.args, orderByListPaginatedRootResult.flip, (xs) => {
217
- postProcess(xs, fields, shouldRemoveExtraKeys);
218
- }, sqlASTTotalCount, dbCall, input.artifacts[input.resource].primaryKey, context, options);
244
+ const totalCount = await getTotalCount(sqlASTTotalCount, dbCall, context, options);
245
+ if (paginationType === "cursor") {
246
+ data = wrapListPaginationCursor(data, input.args, orderByListPaginatedRootResult.flip, (xs) => {
247
+ postProcess(xs, fields, shouldRemoveExtraKeys);
248
+ }, input.artifacts[input.resource].primaryKey, totalCount);
249
+ }
250
+ else {
251
+ postProcess(data, fields, shouldRemoveExtraKeys);
252
+ data = wrapListPaginationLimitOffset(data, totalCount);
253
+ }
219
254
  }
220
255
  return data;
221
256
  }
@@ -224,10 +259,13 @@ async function getData(input, dbCall, formatQuery, dialect) {
224
259
  }
225
260
  return data;
226
261
  }
262
+ function wrapListPaginationLimitOffset(data, totalCount) {
263
+ return { paginationInfo: { totalCount }, results: data };
264
+ }
227
265
  // Not recursive at the moment; only supported at the root.
228
266
  // TODO - remove if support for pagination for mysql dialect
229
267
  // is added (I doubt it)
230
- async function wrapListPaginated(data, args, flip, cb, sqlASTTotalCount, dbCall, primaryKey, context, options) {
268
+ function wrapListPaginationCursor(data, args, flip, cb, primaryKey, totalCount) {
231
269
  const limit = flip ? args.$paginate.last : args.$paginate.first;
232
270
  const hasMoreResults = data.length === limit + 1;
233
271
  if (hasMoreResults) {
@@ -243,6 +281,19 @@ async function wrapListPaginated(data, args, flip, cb, sqlASTTotalCount, dbCall,
243
281
  const endKey = data?.[data.length - 1]?.[primaryKey];
244
282
  const startCursor = startKey == null ? null : cursor_1.encodeCursor(startKey);
245
283
  const endCursor = endKey == null ? null : cursor_1.encodeCursor(endKey);
284
+ cb(data);
285
+ return {
286
+ paginationInfo: {
287
+ hasPreviousPage,
288
+ hasNextPage,
289
+ startCursor,
290
+ endCursor,
291
+ totalCount,
292
+ },
293
+ results: data,
294
+ };
295
+ }
296
+ async function getTotalCount(sqlASTTotalCount, dbCall, context, options) {
246
297
  // Replace field selection with `COUNT(*)`
247
298
  const fieldNameTotalCount = "totalCount";
248
299
  sqlASTTotalCount.children = [
@@ -255,17 +306,7 @@ async function wrapListPaginated(data, args, flip, cb, sqlASTTotalCount, dbCall,
255
306
  ];
256
307
  const { sql: sqlTotalCount } = await util_1.compileSqlAST(sqlASTTotalCount, context, options);
257
308
  const totalCount = await dbCall(sqlTotalCount).then((xs) => xs[0][fieldNameTotalCount]);
258
- cb(data);
259
- return {
260
- paginationInfo: {
261
- hasPreviousPage,
262
- hasNextPage,
263
- startCursor,
264
- endCursor,
265
- totalCount,
266
- },
267
- results: data,
268
- };
309
+ return totalCount;
269
310
  }
270
311
  async function create(input, dbCall, formatQuery, dialect) {
271
312
  async function _create() {
@@ -667,6 +708,7 @@ const ops = [
667
708
  "$in",
668
709
  "$nin",
669
710
  "$like",
711
+ "$nlike",
670
712
  "$btwn",
671
713
  "$nbtwn",
672
714
  ];
@@ -111,6 +111,9 @@ function _stringifyWhere(where, table, escapeId, escape, result) {
111
111
  if (operator === "$like") {
112
112
  return `${table}.${escapeId(k)} LIKE ${printValue(operand)}`;
113
113
  }
114
+ if (operator === "$nlike") {
115
+ return `${table}.${escapeId(k)} NOT LIKE ${printValue(operand)}`;
116
+ }
114
117
  if (operator === "$in") {
115
118
  if (operand.length === 0) {
116
119
  // Would do "FALSE" instead, as it's more readable, but it
@@ -0,0 +1,2 @@
1
+ import { IArgs, IField } from "./runtime/IRuntime";
2
+ export declare function traverseFieldArgs(fields: IField[], cb: (args: IArgs | undefined) => IArgs): void;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.traverseFieldArgs = void 0;
4
+ function traverseFieldArgs(fields, cb) {
5
+ for (let x of fields) {
6
+ if (typeof x !== "object") {
7
+ continue;
8
+ }
9
+ x.args = cb(x.args);
10
+ traverseFieldArgs(x.fields, cb);
11
+ }
12
+ }
13
+ exports.traverseFieldArgs = traverseFieldArgs;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@technicity/data-service-generator",
3
- "version": "0.5.3",
3
+ "version": "0.5.7",
4
4
  "main": "./dist/index.js",
5
5
  "files": [
6
6
  "dist"