@infuro/cms-core 1.0.4 → 1.0.5
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/dist/admin.cjs +3205 -1349
- package/dist/admin.cjs.map +1 -1
- package/dist/admin.d.cts +44 -2
- package/dist/admin.d.ts +44 -2
- package/dist/admin.js +3219 -1359
- package/dist/admin.js.map +1 -1
- package/dist/api.cjs +296 -4
- package/dist/api.cjs.map +1 -1
- package/dist/api.d.cts +1 -1
- package/dist/api.d.ts +1 -1
- package/dist/api.js +297 -5
- package/dist/api.js.map +1 -1
- package/dist/{index-DP3LK1XN.d.cts → index-BPnATEXW.d.cts} +3 -0
- package/dist/{index-DP3LK1XN.d.ts → index-BPnATEXW.d.ts} +3 -0
- package/dist/index.cjs +1521 -105
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +270 -13
- package/dist/index.d.ts +270 -13
- package/dist/index.js +1512 -107
- package/dist/index.js.map +1 -1
- package/package.json +9 -3
package/dist/api.cjs
CHANGED
|
@@ -201,14 +201,156 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
201
201
|
if (!resource || !entity) {
|
|
202
202
|
return json({ error: "Invalid resource" }, { status: 400 });
|
|
203
203
|
}
|
|
204
|
-
const repo = dataSource.getRepository(entity);
|
|
205
204
|
const { searchParams } = new URL(req.url);
|
|
206
205
|
const page = Number(searchParams.get("page")) || 1;
|
|
207
|
-
const limit = Number(searchParams.get("limit")) || 10;
|
|
206
|
+
const limit = Math.min(Number(searchParams.get("limit")) || 10, 100);
|
|
208
207
|
const skip = (page - 1) * limit;
|
|
209
|
-
const
|
|
208
|
+
const sortFieldRaw = searchParams.get("sortField") || "createdAt";
|
|
210
209
|
const sortOrder = searchParams.get("sortOrder") === "desc" ? "DESC" : "ASC";
|
|
211
210
|
const search = searchParams.get("search");
|
|
211
|
+
if (resource === "orders") {
|
|
212
|
+
const repo2 = dataSource.getRepository(entity);
|
|
213
|
+
const allowedSort = ["id", "orderNumber", "contactId", "status", "total", "currency", "createdAt", "updatedAt"];
|
|
214
|
+
const sortField = allowedSort.includes(sortFieldRaw) ? sortFieldRaw : "createdAt";
|
|
215
|
+
const sortOrderOrders = searchParams.get("sortOrder") === "asc" ? "ASC" : "DESC";
|
|
216
|
+
const statusFilter = searchParams.get("status")?.trim();
|
|
217
|
+
const dateFrom = searchParams.get("dateFrom")?.trim();
|
|
218
|
+
const dateTo = searchParams.get("dateTo")?.trim();
|
|
219
|
+
const paymentRef = searchParams.get("paymentRef")?.trim();
|
|
220
|
+
let orderIdsFromPayment = null;
|
|
221
|
+
if (paymentRef && entityMap["payments"]) {
|
|
222
|
+
const paymentRepo = dataSource.getRepository(entityMap["payments"]);
|
|
223
|
+
const payments = await paymentRepo.createQueryBuilder("p").select("p.orderId").where("p.externalReference = :ref", { ref: paymentRef }).orWhere("p.metadata->>'razorpayPaymentId' = :ref", { ref: paymentRef }).getRawMany();
|
|
224
|
+
orderIdsFromPayment = payments.map((r) => r.orderId);
|
|
225
|
+
if (orderIdsFromPayment.length === 0) {
|
|
226
|
+
return json({ total: 0, page, limit, totalPages: 0, data: [] });
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
const qb = repo2.createQueryBuilder("order").leftJoinAndSelect("order.contact", "contact").leftJoinAndSelect("order.items", "items").leftJoinAndSelect("items.product", "product").leftJoinAndSelect("product.collection", "collection").orderBy(`order.${sortField}`, sortOrderOrders).skip(skip).take(limit);
|
|
230
|
+
if (search && typeof search === "string" && search.trim()) {
|
|
231
|
+
const term = `%${search.trim()}%`;
|
|
232
|
+
qb.andWhere(
|
|
233
|
+
"(order.orderNumber ILIKE :term OR contact.name ILIKE :term OR contact.email ILIKE :term)",
|
|
234
|
+
{ term }
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
if (statusFilter) qb.andWhere("order.status = :status", { status: statusFilter });
|
|
238
|
+
if (dateFrom) qb.andWhere("order.createdAt >= :dateFrom", { dateFrom: /* @__PURE__ */ new Date(dateFrom + "T00:00:00.000Z") });
|
|
239
|
+
if (dateTo) qb.andWhere("order.createdAt <= :dateTo", { dateTo: /* @__PURE__ */ new Date(dateTo + "T23:59:59.999Z") });
|
|
240
|
+
if (orderIdsFromPayment && orderIdsFromPayment.length) qb.andWhere("order.id IN (:...orderIds)", { orderIds: orderIdsFromPayment });
|
|
241
|
+
const [rows, total2] = await qb.getManyAndCount();
|
|
242
|
+
const data2 = rows.map((order) => {
|
|
243
|
+
const contact = order.contact;
|
|
244
|
+
const items = order.items ?? [];
|
|
245
|
+
const itemsSummary = items.map((i) => {
|
|
246
|
+
const label = i.product?.collection?.name ?? i.product?.name ?? "Product";
|
|
247
|
+
return `${label} \xD7 ${i.quantity}`;
|
|
248
|
+
}).join(", ") || "\u2014";
|
|
249
|
+
return {
|
|
250
|
+
...order,
|
|
251
|
+
contact: contact ? { id: contact.id, name: contact.name, email: contact.email, phone: contact.phone } : null,
|
|
252
|
+
itemsSummary
|
|
253
|
+
};
|
|
254
|
+
});
|
|
255
|
+
return json({ total: total2, page, limit, totalPages: Math.ceil(total2 / limit), data: data2 });
|
|
256
|
+
}
|
|
257
|
+
if (resource === "payments") {
|
|
258
|
+
const repo2 = dataSource.getRepository(entity);
|
|
259
|
+
const allowedSort = ["id", "orderId", "amount", "currency", "status", "method", "paidAt", "createdAt", "updatedAt"];
|
|
260
|
+
const sortField = allowedSort.includes(sortFieldRaw) ? sortFieldRaw : "createdAt";
|
|
261
|
+
const sortOrderPayments = searchParams.get("sortOrder") === "asc" ? "ASC" : "DESC";
|
|
262
|
+
const statusFilter = searchParams.get("status")?.trim();
|
|
263
|
+
const dateFrom = searchParams.get("dateFrom")?.trim();
|
|
264
|
+
const dateTo = searchParams.get("dateTo")?.trim();
|
|
265
|
+
const methodFilter = searchParams.get("method")?.trim();
|
|
266
|
+
const orderNumberParam = searchParams.get("orderNumber")?.trim();
|
|
267
|
+
const qb = repo2.createQueryBuilder("payment").leftJoinAndSelect("payment.order", "ord").leftJoinAndSelect("ord.contact", "orderContact").leftJoinAndSelect("payment.contact", "contact").orderBy(`payment.${sortField}`, sortOrderPayments).skip(skip).take(limit);
|
|
268
|
+
if (search && typeof search === "string" && search.trim()) {
|
|
269
|
+
const term = `%${search.trim()}%`;
|
|
270
|
+
qb.andWhere(
|
|
271
|
+
"(orderContact.name ILIKE :term OR orderContact.email ILIKE :term OR contact.name ILIKE :term OR contact.email ILIKE :term)",
|
|
272
|
+
{ term }
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
if (statusFilter) qb.andWhere("payment.status = :status", { status: statusFilter });
|
|
276
|
+
if (dateFrom) qb.andWhere("payment.createdAt >= :dateFrom", { dateFrom: /* @__PURE__ */ new Date(dateFrom + "T00:00:00.000Z") });
|
|
277
|
+
if (dateTo) qb.andWhere("payment.createdAt <= :dateTo", { dateTo: /* @__PURE__ */ new Date(dateTo + "T23:59:59.999Z") });
|
|
278
|
+
if (methodFilter) qb.andWhere("payment.method = :method", { method: methodFilter });
|
|
279
|
+
if (orderNumberParam) qb.andWhere("ord.orderNumber ILIKE :orderNumber", { orderNumber: `%${orderNumberParam}%` });
|
|
280
|
+
const [rows, total2] = await qb.getManyAndCount();
|
|
281
|
+
const data2 = rows.map((payment) => {
|
|
282
|
+
const order = payment.order;
|
|
283
|
+
const orderContact = order?.contact;
|
|
284
|
+
const contact = payment.contact;
|
|
285
|
+
const customer = orderContact ?? contact;
|
|
286
|
+
return {
|
|
287
|
+
...payment,
|
|
288
|
+
order: order ? { id: order.id, orderNumber: order.orderNumber, contact: orderContact ? { name: orderContact.name, email: orderContact.email } : null } : null,
|
|
289
|
+
contact: customer ? { id: customer.id, name: customer.name, email: customer.email } : null
|
|
290
|
+
};
|
|
291
|
+
});
|
|
292
|
+
return json({ total: total2, page, limit, totalPages: Math.ceil(total2 / limit), data: data2 });
|
|
293
|
+
}
|
|
294
|
+
if (resource === "products") {
|
|
295
|
+
const repo2 = dataSource.getRepository(entity);
|
|
296
|
+
const statusFilter = searchParams.get("status")?.trim();
|
|
297
|
+
const inventory = searchParams.get("inventory")?.trim();
|
|
298
|
+
const productWhere = {};
|
|
299
|
+
if (statusFilter) productWhere.status = statusFilter;
|
|
300
|
+
if (inventory === "in_stock") productWhere.quantity = (0, import_typeorm.MoreThan)(0);
|
|
301
|
+
if (inventory === "out_of_stock") productWhere.quantity = 0;
|
|
302
|
+
if (search && typeof search === "string" && search.trim()) {
|
|
303
|
+
productWhere.name = (0, import_typeorm.ILike)(`%${search.trim()}%`);
|
|
304
|
+
}
|
|
305
|
+
const [data2, total2] = await repo2.findAndCount({
|
|
306
|
+
where: Object.keys(productWhere).length ? productWhere : void 0,
|
|
307
|
+
skip,
|
|
308
|
+
take: limit,
|
|
309
|
+
order: { [sortFieldRaw]: sortOrder }
|
|
310
|
+
});
|
|
311
|
+
return json({ total: total2, page, limit, totalPages: Math.ceil(total2 / limit), data: data2 });
|
|
312
|
+
}
|
|
313
|
+
if (resource === "contacts") {
|
|
314
|
+
const repo2 = dataSource.getRepository(entity);
|
|
315
|
+
const allowedSort = ["id", "name", "email", "createdAt", "type"];
|
|
316
|
+
const sortField = allowedSort.includes(sortFieldRaw) ? sortFieldRaw : "createdAt";
|
|
317
|
+
const sortOrderContacts = searchParams.get("sortOrder") === "asc" ? "ASC" : "DESC";
|
|
318
|
+
const typeFilter2 = searchParams.get("type")?.trim();
|
|
319
|
+
const orderIdParam = searchParams.get("orderId")?.trim();
|
|
320
|
+
const includeSummary = searchParams.get("includeSummary") === "1";
|
|
321
|
+
const qb = repo2.createQueryBuilder("contact").orderBy(`contact.${sortField}`, sortOrderContacts).skip(skip).take(limit);
|
|
322
|
+
if (search && typeof search === "string" && search.trim()) {
|
|
323
|
+
const term = `%${search.trim()}%`;
|
|
324
|
+
qb.andWhere("(contact.name ILIKE :term OR contact.email ILIKE :term OR contact.phone ILIKE :term)", { term });
|
|
325
|
+
}
|
|
326
|
+
if (typeFilter2) qb.andWhere("contact.type = :type", { type: typeFilter2 });
|
|
327
|
+
if (orderIdParam) {
|
|
328
|
+
const orderId = Number(orderIdParam);
|
|
329
|
+
if (!Number.isNaN(orderId)) {
|
|
330
|
+
qb.andWhere('contact.id IN (SELECT "contactId" FROM orders WHERE id = :orderId)', { orderId });
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
if (includeSummary && entityMap["orders"] && entityMap["payments"]) {
|
|
334
|
+
qb.loadRelationCountAndMap("contact._orderCount", "contact.orders");
|
|
335
|
+
const [rows, total3] = await qb.getManyAndCount();
|
|
336
|
+
const contactIds = rows.map((c) => c.id);
|
|
337
|
+
const paymentRepo = dataSource.getRepository(entityMap["payments"]);
|
|
338
|
+
const paidByContact = await paymentRepo.createQueryBuilder("p").select("p.contactId", "contactId").addSelect("COALESCE(SUM(CAST(p.amount AS DECIMAL)), 0)", "total").where("p.contactId IN (:...ids)", { ids: contactIds.length ? contactIds : [0] }).andWhere("p.status = :status", { status: "completed" }).groupBy("p.contactId").getRawMany();
|
|
339
|
+
const totalPaidMap = new Map(paidByContact.map((r) => [r.contactId, Number(r.total)]));
|
|
340
|
+
const data3 = rows.map((c) => {
|
|
341
|
+
const { _orderCount, ...rest } = c;
|
|
342
|
+
return {
|
|
343
|
+
...rest,
|
|
344
|
+
orderCount: _orderCount ?? 0,
|
|
345
|
+
totalPaid: totalPaidMap.get(rest.id) ?? 0
|
|
346
|
+
};
|
|
347
|
+
});
|
|
348
|
+
return json({ total: total3, page, limit, totalPages: Math.ceil(total3 / limit), data: data3 });
|
|
349
|
+
}
|
|
350
|
+
const [data2, total2] = await qb.getManyAndCount();
|
|
351
|
+
return json({ total: total2, page, limit, totalPages: Math.ceil(total2 / limit), data: data2 });
|
|
352
|
+
}
|
|
353
|
+
const repo = dataSource.getRepository(entity);
|
|
212
354
|
const typeFilter = searchParams.get("type");
|
|
213
355
|
let where = {};
|
|
214
356
|
if (resource === "media") {
|
|
@@ -222,7 +364,7 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
222
364
|
const [data, total] = await repo.findAndCount({
|
|
223
365
|
skip,
|
|
224
366
|
take: limit,
|
|
225
|
-
order: { [
|
|
367
|
+
order: { [sortFieldRaw]: sortOrder },
|
|
226
368
|
where
|
|
227
369
|
});
|
|
228
370
|
return json({ total, page, limit, totalPages: Math.ceil(total / limit), data });
|
|
@@ -242,6 +384,107 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
242
384
|
sanitizeBodyForEntity(repo, body);
|
|
243
385
|
const created = await repo.save(repo.create(body));
|
|
244
386
|
return json(created, { status: 201 });
|
|
387
|
+
},
|
|
388
|
+
async GET_METADATA(req, resource) {
|
|
389
|
+
const authError = await requireAuth(req);
|
|
390
|
+
if (authError) return authError;
|
|
391
|
+
const entity = entityMap[resource];
|
|
392
|
+
if (!resource || !entity) {
|
|
393
|
+
return json({ error: "Invalid resource" }, { status: 400 });
|
|
394
|
+
}
|
|
395
|
+
const repo = dataSource.getRepository(entity);
|
|
396
|
+
const meta = repo.metadata;
|
|
397
|
+
const uniqueFromIndices = /* @__PURE__ */ new Set();
|
|
398
|
+
for (const idx of meta.indices) {
|
|
399
|
+
if (idx.isUnique && idx.columns.length === 1) {
|
|
400
|
+
uniqueFromIndices.add(idx.columns[0].propertyName);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
for (const uniq of meta.uniques) {
|
|
404
|
+
if (uniq.columns.length === 1) {
|
|
405
|
+
uniqueFromIndices.add(uniq.columns[0].propertyName);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
const columns = meta.columns.map((col) => ({
|
|
409
|
+
name: col.propertyName,
|
|
410
|
+
type: typeof col.type === "string" ? col.type : col.type?.name ?? "unknown",
|
|
411
|
+
nullable: col.isNullable,
|
|
412
|
+
isUnique: uniqueFromIndices.has(col.propertyName),
|
|
413
|
+
isPrimary: col.isPrimary,
|
|
414
|
+
default: col.default
|
|
415
|
+
}));
|
|
416
|
+
const uniqueColumns = [...uniqueFromIndices];
|
|
417
|
+
return json({ columns, uniqueColumns });
|
|
418
|
+
},
|
|
419
|
+
async BULK_POST(req, resource) {
|
|
420
|
+
const authError = await requireAuth(req);
|
|
421
|
+
if (authError) return authError;
|
|
422
|
+
const entity = entityMap[resource];
|
|
423
|
+
if (!resource || !entity) {
|
|
424
|
+
return json({ error: "Invalid resource" }, { status: 400 });
|
|
425
|
+
}
|
|
426
|
+
const body = await req.json();
|
|
427
|
+
const { records, upsertKey = "id" } = body;
|
|
428
|
+
if (!Array.isArray(records) || records.length === 0) {
|
|
429
|
+
return json({ error: "Records array is required" }, { status: 400 });
|
|
430
|
+
}
|
|
431
|
+
const repo = dataSource.getRepository(entity);
|
|
432
|
+
for (const record of records) {
|
|
433
|
+
sanitizeBodyForEntity(repo, record);
|
|
434
|
+
}
|
|
435
|
+
try {
|
|
436
|
+
const result = await repo.upsert(records, {
|
|
437
|
+
conflictPaths: [upsertKey],
|
|
438
|
+
skipUpdateIfNoValuesChanged: true
|
|
439
|
+
});
|
|
440
|
+
return json({
|
|
441
|
+
success: true,
|
|
442
|
+
imported: result.identifiers.length,
|
|
443
|
+
identifiers: result.identifiers
|
|
444
|
+
});
|
|
445
|
+
} catch (error) {
|
|
446
|
+
const message = error instanceof Error ? error.message : "Bulk import failed";
|
|
447
|
+
return json({ error: message }, { status: 400 });
|
|
448
|
+
}
|
|
449
|
+
},
|
|
450
|
+
async GET_EXPORT(req, resource) {
|
|
451
|
+
const authError = await requireAuth(req);
|
|
452
|
+
if (authError) return authError;
|
|
453
|
+
const entity = entityMap[resource];
|
|
454
|
+
if (!resource || !entity) {
|
|
455
|
+
return json({ error: "Invalid resource" }, { status: 400 });
|
|
456
|
+
}
|
|
457
|
+
const { searchParams } = new URL(req.url);
|
|
458
|
+
const format = searchParams.get("format") || "csv";
|
|
459
|
+
const repo = dataSource.getRepository(entity);
|
|
460
|
+
const meta = repo.metadata;
|
|
461
|
+
const hasDeleted = meta.columns.some((c) => c.propertyName === "deleted");
|
|
462
|
+
const where = hasDeleted ? { deleted: false } : {};
|
|
463
|
+
const data = await repo.find({ where });
|
|
464
|
+
const excludeCols = /* @__PURE__ */ new Set(["deletedAt", "deletedBy", "deleted"]);
|
|
465
|
+
const columns = meta.columns.filter((c) => !excludeCols.has(c.propertyName)).map((c) => c.propertyName);
|
|
466
|
+
if (format === "json") {
|
|
467
|
+
return json(data);
|
|
468
|
+
}
|
|
469
|
+
const escapeCSV = (val) => {
|
|
470
|
+
if (val === null || val === void 0) return "";
|
|
471
|
+
const str = typeof val === "object" ? JSON.stringify(val) : String(val);
|
|
472
|
+
if (str.includes(",") || str.includes('"') || str.includes("\n")) {
|
|
473
|
+
return `"${str.replace(/"/g, '""')}"`;
|
|
474
|
+
}
|
|
475
|
+
return str;
|
|
476
|
+
};
|
|
477
|
+
const header = columns.join(",");
|
|
478
|
+
const rows = data.map(
|
|
479
|
+
(row) => columns.map((col) => escapeCSV(row[col])).join(",")
|
|
480
|
+
);
|
|
481
|
+
const csv = [header, ...rows].join("\n");
|
|
482
|
+
return new Response(csv, {
|
|
483
|
+
headers: {
|
|
484
|
+
"Content-Type": "text/csv; charset=utf-8",
|
|
485
|
+
"Content-Disposition": `attachment; filename="${resource}.csv"`
|
|
486
|
+
}
|
|
487
|
+
});
|
|
245
488
|
}
|
|
246
489
|
};
|
|
247
490
|
}
|
|
@@ -254,6 +497,44 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
254
497
|
const entity = entityMap[resource];
|
|
255
498
|
if (!entity) return json({ error: "Invalid resource" }, { status: 400 });
|
|
256
499
|
const repo = dataSource.getRepository(entity);
|
|
500
|
+
if (resource === "orders") {
|
|
501
|
+
const order = await repo.findOne({
|
|
502
|
+
where: { id: Number(id) },
|
|
503
|
+
relations: ["contact", "billingAddress", "shippingAddress", "items", "items.product", "items.product.collection", "payments"]
|
|
504
|
+
});
|
|
505
|
+
if (!order) return json({ message: "Not found" }, { status: 404 });
|
|
506
|
+
return json(order);
|
|
507
|
+
}
|
|
508
|
+
if (resource === "contacts") {
|
|
509
|
+
const contact = await repo.findOne({
|
|
510
|
+
where: { id: Number(id) },
|
|
511
|
+
relations: ["form_submissions", "form_submissions.form", "orders", "payments", "addresses"]
|
|
512
|
+
});
|
|
513
|
+
if (!contact) return json({ message: "Not found" }, { status: 404 });
|
|
514
|
+
const orders = contact.orders ?? [];
|
|
515
|
+
const payments = contact.payments ?? [];
|
|
516
|
+
const totalPaid = payments.filter((p) => p.status === "completed").reduce((sum, p) => sum + Number(p.amount ?? 0), 0);
|
|
517
|
+
const lastOrderAt = orders.length > 0 ? orders.reduce((latest, o) => {
|
|
518
|
+
const t = o.createdAt ? new Date(o.createdAt).getTime() : 0;
|
|
519
|
+
return t > latest ? t : latest;
|
|
520
|
+
}, 0) : null;
|
|
521
|
+
return json({
|
|
522
|
+
...contact,
|
|
523
|
+
summary: {
|
|
524
|
+
totalOrders: orders.length,
|
|
525
|
+
totalPaid,
|
|
526
|
+
lastOrderAt: lastOrderAt ? new Date(lastOrderAt).toISOString() : null
|
|
527
|
+
}
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
if (resource === "payments") {
|
|
531
|
+
const payment = await repo.findOne({
|
|
532
|
+
where: { id: Number(id) },
|
|
533
|
+
relations: ["order", "order.contact", "contact"]
|
|
534
|
+
});
|
|
535
|
+
if (!payment) return json({ message: "Not found" }, { status: 404 });
|
|
536
|
+
return json(payment);
|
|
537
|
+
}
|
|
257
538
|
const item = await repo.findOne({ where: { id: Number(id) } });
|
|
258
539
|
return item ? json(item) : json({ message: "Not found" }, { status: 404 });
|
|
259
540
|
},
|
|
@@ -1119,6 +1400,17 @@ function createCmsApiHandler(config) {
|
|
|
1119
1400
|
if (path.length === 0) return config.json({ error: "Not found" }, { status: 404 });
|
|
1120
1401
|
const resource = resolveResource(path[0]);
|
|
1121
1402
|
if (!crudResources.includes(resource)) return config.json({ error: "Invalid resource" }, { status: 400 });
|
|
1403
|
+
if (path.length === 2) {
|
|
1404
|
+
if (path[1] === "metadata" && method === "GET") {
|
|
1405
|
+
return crud.GET_METADATA(req, resource);
|
|
1406
|
+
}
|
|
1407
|
+
if (path[1] === "bulk" && method === "POST") {
|
|
1408
|
+
return crud.BULK_POST(req, resource);
|
|
1409
|
+
}
|
|
1410
|
+
if (path[1] === "export" && method === "GET") {
|
|
1411
|
+
return crud.GET_EXPORT(req, resource);
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1122
1414
|
if (path.length === 1) {
|
|
1123
1415
|
if (method === "GET") return crud.GET(req, resource);
|
|
1124
1416
|
if (method === "POST") return crud.POST(req, resource);
|