@opengis/fastify-table 2.5.14 → 2.5.16

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AA8FA,iBAAe,MAAM,CAAC,OAAO,EAAE,GAAG,iBAkOjC;;AACD,wBAEG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AA8FA,iBAAe,MAAM,CAAC,OAAO,EAAE,GAAG,iBA2OjC;;AACD,wBAEG"}
package/dist/index.js CHANGED
@@ -164,13 +164,21 @@ async function plugin(fastify) {
164
164
  if (config.dblist) {
165
165
  fastify.register(dblistRoutes, opt);
166
166
  }
167
- fastify.addHook('preHandler', async (request, reply) => {
167
+ fastify.addHook("preValidation", async (request) => {
168
+ Object.keys(request.query || {})
169
+ .filter((key) => request.query[key] === "")
170
+ .forEach((key) => delete request.query[key]);
171
+ Object.keys(request.body || {})
172
+ .filter((key) => request.body[key] === "")
173
+ .forEach((key) => delete request.body[key]);
174
+ });
175
+ fastify.addHook("preHandler", async (request, reply) => {
168
176
  const q = request.query;
169
177
  if (q?.limit !== undefined) {
170
178
  const limit = Number(q.limit);
171
179
  if (!Number.isInteger(limit) || limit < 1 || limit > 1000) {
172
180
  reply.code(400).send({
173
- error: 'Invalid limit (1-100)'
181
+ error: "Invalid limit (1-100)",
174
182
  });
175
183
  }
176
184
  }
@@ -178,7 +186,7 @@ async function plugin(fastify) {
178
186
  const offset = Number(q.offset);
179
187
  if (!Number.isInteger(offset) || offset < 0) {
180
188
  reply.code(400).send({
181
- error: 'Invalid offset (>=0)'
189
+ error: "Invalid offset (>=0)",
182
190
  });
183
191
  }
184
192
  }
@@ -186,7 +194,7 @@ async function plugin(fastify) {
186
194
  const page = Number(q.page);
187
195
  if (!Number.isInteger(page) || page > 100000) {
188
196
  reply.code(400).send({
189
- error: 'Invalid page (<=100000)'
197
+ error: "Invalid page (<=100000)",
190
198
  });
191
199
  }
192
200
  }
@@ -1 +1 @@
1
- {"version":3,"file":"uploadMultiPart.d.ts","sourceRoot":"","sources":["../../../../server/plugins/file/uploadMultiPart.ts"],"names":[],"mappings":"AA6BA,MAAM,WAAW,KAAK;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AA2CD,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,mBAkBvE;AAED,wBAAsB,gBAAgB,CACpC,EACE,IAAI,EAAE,QAAQ,EACd,MAA2C,EAC3C,MAAM,GACP,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EACpD,MAAM,MAAW,mBA+BlB;AAED,wBAAsB,eAAe,CACnC,GAAG,EAAE,GAAG,EACR,EACE,UAAU,EACV,GAAG,EACH,MAAM,EACN,gBAAwB,GACzB,GAAE;IACD,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CACvB,GACL,OAAO,CAAC,KAAK,CAAC,CAiHhB;AAED,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"uploadMultiPart.d.ts","sourceRoot":"","sources":["../../../../server/plugins/file/uploadMultiPart.ts"],"names":[],"mappings":"AA6BA,MAAM,WAAW,KAAK;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AA2CD,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,mBAkBvE;AAED,wBAAsB,gBAAgB,CACpC,EACE,IAAI,EAAE,QAAQ,EACd,MAA2C,EAC3C,MAAM,GACP,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EACpD,MAAM,MAAW,mBA+BlB;AAED,wBAAsB,eAAe,CACnC,GAAG,EAAE,GAAG,EACR,EACE,UAAU,EACV,GAAG,EACH,MAAM,EACN,gBAAwB,GACzB,GAAE;IACD,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CACvB,GACL,OAAO,CAAC,KAAK,CAAC,CAmHhB;AAED,eAAe,eAAe,CAAC"}
@@ -105,9 +105,7 @@ export async function uploadMultiPart(req, { extensions, raw, subdir, originalFi
105
105
  throw new BadRequestError("file buffer is empty");
106
106
  }
107
107
  const { ext: fileExtension } = (await fileTypeFromBuffer(fileBuffer)) || {};
108
- if (fileExtension !== ext.substring(1)) {
109
- throw new ConflictError("file type spoofing attempt detected");
110
- }
108
+ const nameExt = ext.substring(1);
111
109
  // return buffer for custom upload
112
110
  if (raw) {
113
111
  return {
@@ -118,6 +116,9 @@ export async function uploadMultiPart(req, { extensions, raw, subdir, originalFi
118
116
  fields: value.fields,
119
117
  };
120
118
  }
119
+ if (fileExtension !== nameExt) {
120
+ throw new ConflictError("file type spoofing attempt detected");
121
+ }
121
122
  const dir = subdir != null ? subdir : req.params?.["*"] || "uploads";
122
123
  const yearMonthDay = subdir != null ? "" : new Date().toISOString().split("T")[0];
123
124
  const dbname = req.pg?.options?.database || req.pg?.database || config.pg?.database; // request / config params / default config params
@@ -1 +1 @@
1
- {"version":3,"file":"allowedExtensions.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/file/utils/allowedExtensions.ts"],"names":[],"mappings":"AAIA,QAAA,MAAM,GAAG,EAAE,MAAM,EAwBhB,CAAC;AAEF,QAAA,MAAM,MAAM,EAAE,MAAM,EAInB,CAAC;AAEF,QAAA,MAAM,MAAM,EAAE,MAAM,EAEnB,CAAC;AAEF,QAAA,MAAM,SAAS,EAAE,MAAM,EActB,CAAC;AAEF,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;;;;;;;AAE1C,wBAKE"}
1
+ {"version":3,"file":"allowedExtensions.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/file/utils/allowedExtensions.ts"],"names":[],"mappings":"AAIA,QAAA,MAAM,GAAG,EAAE,MAAM,EAyBhB,CAAC;AAEF,QAAA,MAAM,MAAM,EAAE,MAAM,EAInB,CAAC;AAEF,QAAA,MAAM,MAAM,EAAE,MAAM,EAEnB,CAAC;AAEF,QAAA,MAAM,SAAS,EAAE,MAAM,EAetB,CAAC;AAEF,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;;;;;;;AAE1C,wBAKE"}
@@ -25,6 +25,7 @@ const all = envExtensions || [
25
25
  "mp4",
26
26
  "mov",
27
27
  "xml",
28
+ "p7s"
28
29
  ];
29
30
  const images = all.filter((ext) => ["jpg", "jpeg", "png", "tiff", "tif", "ico", "svg", "heic", "webp"].includes(ext));
30
31
  const videos = all.filter((ext) => ["mp4", "mov", "avi"].includes(ext));
@@ -40,6 +41,7 @@ const documents = all.filter((ext) => [
40
41
  "xml",
41
42
  "ppt",
42
43
  "pptx",
44
+ "p7s"
43
45
  ].includes(ext));
44
46
  export { all, images, videos, documents };
45
47
  export default {
@@ -1 +1 @@
1
- {"version":3,"file":"suggest.d.ts","sourceRoot":"","sources":["../../../../../server/routes/table/controllers/suggest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAwBpD,wBAAsB,kBAAkB,CAAC,EACvC,KAAK,EACL,QAAQ,EACR,MAAM,EACN,UAAU,EACV,QAAQ,EACR,UAAU,EACV,GAAG,EACH,EAAqB,GACtB,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,GAAG,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,UAAU,CAAC;CACjB;;;;;UAwFA;AAED,wBAA8B,OAAO,CAAC,GAAG,EAAE,GAAG,gBAuX7C"}
1
+ {"version":3,"file":"suggest.d.ts","sourceRoot":"","sources":["../../../../../server/routes/table/controllers/suggest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAwBpD,wBAAsB,kBAAkB,CAAC,EACvC,KAAK,EACL,QAAQ,EACR,MAAM,EACN,UAAU,EACV,QAAQ,EACR,UAAU,EACV,GAAG,EACH,EAAqB,GACtB,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,GAAG,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,UAAU,CAAC;CACjB;;;;;UAwFA;AAED,wBAA8B,OAAO,CAAC,GAAG,EAAE,GAAG,gBAuY7C"}
@@ -141,9 +141,6 @@ export default async function suggest(req) {
141
141
  (metaColumns || []).find((col) => col?.name === column) ||
142
142
  {};
143
143
  const { dataTypeID } = (metaColumns || []).find((col) => col?.name === column) || {};
144
- // const filters =
145
- // hookBody?.filters ||
146
- // (body ? await getFilter({ pg, table }).then((el) => el.list) : null);
147
144
  if (table && (!column || !columnName)) {
148
145
  throw BadRequestError("param name is invalid: 2");
149
146
  }
@@ -239,32 +236,57 @@ export default async function suggest(req) {
239
236
  data,
240
237
  };
241
238
  }
239
+ const args = [];
240
+ const where = [];
242
241
  // select, with search by text support
243
- const search = query.key && typeof query.key === "string" ? searchQuery : null;
242
+ if (query.key && typeof query.key === "string") {
243
+ args.push(query.key.toLowerCase());
244
+ where.push(searchQuery);
245
+ }
246
+ // pk
247
+ if (meta.pk) {
248
+ where.push(`${meta.pk} is not null`);
249
+ }
244
250
  // filter by value
245
- const val = query.val
246
- ? `${meta.pk}=any('{${query.val.replace(/'/g, "''")}}')`
247
- : "";
248
- const filter = tableName && pg.pk?.[tableName] && columnName && dataTypeID
249
- ? `id in (select ${pg.pgType[dataTypeID]?.includes("[]")
251
+ if (meta.pk && typeof query.val === "string") {
252
+ args.push(query.val.split(","));
253
+ where.push(`${meta.pk}=any($${args.length})`);
254
+ }
255
+ // filter
256
+ if (tableName && pg.pk?.[tableName] && columnName && dataTypeID) {
257
+ where.push(`id in (select ${pg.pgType[dataTypeID]?.includes("[]")
250
258
  ? `unnest(${columnName})`
251
- : columnName} from ${tableName.replace(/'/g, "''")})`
252
- : "true";
253
- const where = [search, val, filter, meta.pk ? `${meta.pk} is not null` : null]
254
- .filter(Boolean)
255
- .join(" and ") || "true";
256
- const sqlSuggest = tableName && column
259
+ : columnName} from ${tableName.replace(/'/g, "''")})`);
260
+ }
261
+ // order by value if not specified explicitly
262
+ const order = meta.original.toLowerCase().includes("order by")
263
+ ? ""
264
+ : "order by 2";
265
+ const whereQuery = where.filter(Boolean).join(" and ") || "true";
266
+ args.push(Math.min(query.limit || meta.limit || limit, limit));
267
+ let sqlSuggest = tableName && column
257
268
  ? `${meta.original}
258
- WHERE EXISTS ( SELECT 1 FROM ${tableName} o WHERE o.${column} IS NOT DISTINCT FROM c.id ) and ${val || "true"} and ${search || "true"}
259
- ${meta.original.toLowerCase().includes("order by") ? "" : "order by 2"}
260
- LIMIT ${Math.min(query.limit || meta.limit || limit, limit)}`
261
- .replace(/{{parent}}/gi, parent)
262
- .replace(/{{uid}}/g, user?.uid || "0")
263
- : `with c(id,text) as ( ${meta.original.replace(/{{parent}}/gi, parent)} where ${where} ${meta.original.toLowerCase().includes("order by") ? "" : "order by 2"}) select * from c where ${filter} limit ${Math.min(query.limit || meta.limit || limit, limit)}`.replace(/{{uid}}/g, user?.uid || "0");
269
+ WHERE EXISTS ( SELECT 1 FROM ${tableName} o
270
+ WHERE o.${column} IS NOT DISTINCT FROM c.id ) and ${whereQuery || "true"}
271
+ ${order} LIMIT $${args.length}::int`
272
+ : `with c(id,text) as ( ${meta.original} where ${whereQuery} ${order}) select * from c LIMIT $${args.length}::int`;
273
+ if (sqlSuggest.includes("{{parent}}")) {
274
+ args.push(parent || "");
275
+ sqlSuggest = sqlSuggest.replace(/(['"]?){{parent}}\1/gi, `$${args.length}`);
276
+ }
277
+ if (sqlSuggest.includes("{{uid}}")) {
278
+ args.push(user?.uid || "0");
279
+ sqlSuggest = sqlSuggest.replace(/(['"]?){{uid}}\1/gi, `$${args.length}`);
280
+ }
264
281
  if (query.sql && debugMode) {
265
282
  return sqlSuggest;
266
283
  }
267
- const { rows: dataNew } = await pg.query(sqlSuggest, query.key && typeof query.key === "string" ? [query.key.toLowerCase()] : []);
284
+ if (config.trace) {
285
+ console.log("suggest", sqlSuggest, where, args);
286
+ }
287
+ const dataNew = await pg
288
+ .query(sqlSuggest, args)
289
+ .then((r) => r.rows || []);
268
290
  // in case id / text = Boolean
269
291
  const data = dataNew.filter((el) => Object.hasOwn(el, "id") && Object.hasOwn(el, "text"));
270
292
  data
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengis/fastify-table",
3
- "version": "2.5.14",
3
+ "version": "2.5.16",
4
4
  "type": "module",
5
5
  "description": "core-plugins",
6
6
  "keywords": [