@restura/core 0.1.0-alpha.19 → 0.1.0-alpha.20
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/index.d.mts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +184 -83
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +177 -76
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -2
package/dist/index.d.mts
CHANGED
|
@@ -42,18 +42,21 @@ declare const resturaConfigSchema: z.ZodObject<{
|
|
|
42
42
|
schemaFilePath: z.ZodDefault<z.ZodString>;
|
|
43
43
|
customApiFolderPath: z.ZodDefault<z.ZodString>;
|
|
44
44
|
generatedTypesPath: z.ZodDefault<z.ZodString>;
|
|
45
|
+
fileTempCachePath: z.ZodOptional<z.ZodString>;
|
|
45
46
|
}, "strip", z.ZodTypeAny, {
|
|
46
47
|
authToken: string;
|
|
47
48
|
sendErrorStackTrace: boolean;
|
|
48
49
|
schemaFilePath: string;
|
|
49
50
|
customApiFolderPath: string;
|
|
50
51
|
generatedTypesPath: string;
|
|
52
|
+
fileTempCachePath?: string | undefined;
|
|
51
53
|
}, {
|
|
52
54
|
authToken: string;
|
|
53
55
|
sendErrorStackTrace?: boolean | undefined;
|
|
54
56
|
schemaFilePath?: string | undefined;
|
|
55
57
|
customApiFolderPath?: string | undefined;
|
|
56
58
|
generatedTypesPath?: string | undefined;
|
|
59
|
+
fileTempCachePath?: string | undefined;
|
|
57
60
|
}>;
|
|
58
61
|
type ResturaConfigSchema = z.infer<typeof resturaConfigSchema>;
|
|
59
62
|
|
|
@@ -2377,6 +2380,7 @@ declare class PsqlPool extends PsqlConnection {
|
|
|
2377
2380
|
|
|
2378
2381
|
declare class ResturaEngine {
|
|
2379
2382
|
resturaConfig: ResturaConfigSchema;
|
|
2383
|
+
private multerCommonUpload;
|
|
2380
2384
|
private resturaRouter;
|
|
2381
2385
|
private publicEndpoints;
|
|
2382
2386
|
private expressApp;
|
|
@@ -2455,6 +2459,7 @@ declare class ResturaEngine {
|
|
|
2455
2459
|
private updateTypes;
|
|
2456
2460
|
private getSchema;
|
|
2457
2461
|
private getSchemaAndTypes;
|
|
2462
|
+
private getMulterFilesIfAny;
|
|
2458
2463
|
private executeRouteLogic;
|
|
2459
2464
|
private isCustomRoute;
|
|
2460
2465
|
private runCustomRouteLogic;
|
package/dist/index.d.ts
CHANGED
|
@@ -42,18 +42,21 @@ declare const resturaConfigSchema: z.ZodObject<{
|
|
|
42
42
|
schemaFilePath: z.ZodDefault<z.ZodString>;
|
|
43
43
|
customApiFolderPath: z.ZodDefault<z.ZodString>;
|
|
44
44
|
generatedTypesPath: z.ZodDefault<z.ZodString>;
|
|
45
|
+
fileTempCachePath: z.ZodOptional<z.ZodString>;
|
|
45
46
|
}, "strip", z.ZodTypeAny, {
|
|
46
47
|
authToken: string;
|
|
47
48
|
sendErrorStackTrace: boolean;
|
|
48
49
|
schemaFilePath: string;
|
|
49
50
|
customApiFolderPath: string;
|
|
50
51
|
generatedTypesPath: string;
|
|
52
|
+
fileTempCachePath?: string | undefined;
|
|
51
53
|
}, {
|
|
52
54
|
authToken: string;
|
|
53
55
|
sendErrorStackTrace?: boolean | undefined;
|
|
54
56
|
schemaFilePath?: string | undefined;
|
|
55
57
|
customApiFolderPath?: string | undefined;
|
|
56
58
|
generatedTypesPath?: string | undefined;
|
|
59
|
+
fileTempCachePath?: string | undefined;
|
|
57
60
|
}>;
|
|
58
61
|
type ResturaConfigSchema = z.infer<typeof resturaConfigSchema>;
|
|
59
62
|
|
|
@@ -2377,6 +2380,7 @@ declare class PsqlPool extends PsqlConnection {
|
|
|
2377
2380
|
|
|
2378
2381
|
declare class ResturaEngine {
|
|
2379
2382
|
resturaConfig: ResturaConfigSchema;
|
|
2383
|
+
private multerCommonUpload;
|
|
2380
2384
|
private resturaRouter;
|
|
2381
2385
|
private publicEndpoints;
|
|
2382
2386
|
private expressApp;
|
|
@@ -2455,6 +2459,7 @@ declare class ResturaEngine {
|
|
|
2455
2459
|
private updateTypes;
|
|
2456
2460
|
private getSchema;
|
|
2457
2461
|
private getSchemaAndTypes;
|
|
2462
|
+
private getMulterFilesIfAny;
|
|
2458
2463
|
private executeRouteLogic;
|
|
2459
2464
|
private isCustomRoute;
|
|
2460
2465
|
private runCustomRouteLogic;
|
package/dist/index.js
CHANGED
|
@@ -95,12 +95,17 @@ var import_zod = require("zod");
|
|
|
95
95
|
var loggerConfigSchema = import_zod.z.object({
|
|
96
96
|
level: import_zod.z.enum(["info", "warn", "error", "debug", "silly"]).default("info")
|
|
97
97
|
});
|
|
98
|
+
var _a;
|
|
99
|
+
var isTsx = (_a = process.argv[1]) == null ? void 0 : _a.endsWith(".ts");
|
|
100
|
+
var isTsNode = process.env.TS_NODE_DEV || process.env.TS_NODE_PROJECT;
|
|
101
|
+
var customApiFolderPath = isTsx || isTsNode ? "/src/api" : "/dist/api";
|
|
98
102
|
var resturaConfigSchema = import_zod.z.object({
|
|
99
103
|
authToken: import_zod.z.string().min(1, "Missing Restura Auth Token"),
|
|
100
104
|
sendErrorStackTrace: import_zod.z.boolean().default(false),
|
|
101
105
|
schemaFilePath: import_zod.z.string().default(process.cwd() + "/restura.schema.json"),
|
|
102
|
-
customApiFolderPath: import_zod.z.string().default(process.cwd() +
|
|
103
|
-
generatedTypesPath: import_zod.z.string().default(process.cwd() + "/src/@types")
|
|
106
|
+
customApiFolderPath: import_zod.z.string().default(process.cwd() + customApiFolderPath),
|
|
107
|
+
generatedTypesPath: import_zod.z.string().default(process.cwd() + "/src/@types"),
|
|
108
|
+
fileTempCachePath: import_zod.z.string().optional()
|
|
104
109
|
});
|
|
105
110
|
|
|
106
111
|
// src/logger/logger.ts
|
|
@@ -205,8 +210,8 @@ var htmlStatusMap = {
|
|
|
205
210
|
};
|
|
206
211
|
|
|
207
212
|
// src/restura/restura.ts
|
|
208
|
-
var
|
|
209
|
-
var
|
|
213
|
+
var import_core_utils7 = require("@redskytech/core-utils");
|
|
214
|
+
var import_internal4 = require("@restura/internal");
|
|
210
215
|
|
|
211
216
|
// ../../node_modules/.pnpm/autobind-decorator@2.4.0/node_modules/autobind-decorator/lib/esm/index.js
|
|
212
217
|
function _typeof(obj) {
|
|
@@ -260,8 +265,8 @@ var import_compression = __toESM(require("compression"));
|
|
|
260
265
|
var import_cookie_parser = __toESM(require("cookie-parser"));
|
|
261
266
|
var import_crypto = require("crypto");
|
|
262
267
|
var express = __toESM(require("express"));
|
|
263
|
-
var
|
|
264
|
-
var
|
|
268
|
+
var import_fs4 = __toESM(require("fs"));
|
|
269
|
+
var import_path5 = __toESM(require("path"));
|
|
265
270
|
var import_pg3 = __toESM(require("pg"));
|
|
266
271
|
var prettier3 = __toESM(require("prettier"));
|
|
267
272
|
|
|
@@ -356,9 +361,9 @@ var ResponseValidator = class _ResponseValidator {
|
|
|
356
361
|
return { validator: "any" };
|
|
357
362
|
}
|
|
358
363
|
getTypeFromTable(selector, name) {
|
|
359
|
-
const
|
|
360
|
-
if (
|
|
361
|
-
const tableName =
|
|
364
|
+
const path5 = selector.split(".");
|
|
365
|
+
if (path5.length === 0 || path5.length > 2 || path5[0] === "") return { validator: "any", isOptional: false };
|
|
366
|
+
const tableName = path5.length == 2 ? path5[0] : name, columnName = path5.length == 2 ? path5[1] : path5[0];
|
|
362
367
|
const table = this.database.find((t) => t.name == tableName);
|
|
363
368
|
const column = table == null ? void 0 : table.columns.find((c) => c.name == columnName);
|
|
364
369
|
if (!table || !column) return { validator: "any", isOptional: false };
|
|
@@ -574,10 +579,10 @@ var ApiTree = class _ApiTree {
|
|
|
574
579
|
return `${p.name}:${responseType}${array ? "[]" : ""}${isNullable ? " | null" : ""}`;
|
|
575
580
|
}
|
|
576
581
|
getTypeFromTable(selector, name) {
|
|
577
|
-
const
|
|
578
|
-
if (
|
|
579
|
-
let tableName =
|
|
580
|
-
const columnName =
|
|
582
|
+
const path5 = selector.split(".");
|
|
583
|
+
if (path5.length === 0 || path5.length > 2 || path5[0] === "") return { responseType: "any", isNullable: false };
|
|
584
|
+
let tableName = path5.length == 2 ? path5[0] : name;
|
|
585
|
+
const columnName = path5.length == 2 ? path5[1] : path5[0];
|
|
581
586
|
let table = this.database.find((t) => t.name == tableName);
|
|
582
587
|
if (!table && tableName.includes("_")) {
|
|
583
588
|
const tableAliasSplit = tableName.split("_");
|
|
@@ -592,8 +597,8 @@ var ApiTree = class _ApiTree {
|
|
|
592
597
|
};
|
|
593
598
|
}
|
|
594
599
|
};
|
|
595
|
-
function pathToNamespaces(
|
|
596
|
-
return
|
|
600
|
+
function pathToNamespaces(path5) {
|
|
601
|
+
return path5.split("/").map((e) => import_core_utils.StringUtils.toPascalCasing(e)).filter((e) => e);
|
|
597
602
|
}
|
|
598
603
|
function apiGenerator(schema, schemaHash) {
|
|
599
604
|
let apiString = `/** Auto generated file from Schema Hash (${schemaHash}). DO NOT MODIFY **/`;
|
|
@@ -629,6 +634,8 @@ function apiGenerator(schema, schemaHash) {
|
|
|
629
634
|
// src/restura/customApiFactory.ts
|
|
630
635
|
var import_fs = __toESM(require("fs"));
|
|
631
636
|
var import_path = __toESM(require("path"));
|
|
637
|
+
var import_bluebird = __toESM(require("bluebird"));
|
|
638
|
+
var import_internal2 = require("@restura/internal");
|
|
632
639
|
var CustomApiFactory = class {
|
|
633
640
|
constructor() {
|
|
634
641
|
this.customApis = {};
|
|
@@ -637,7 +644,8 @@ var CustomApiFactory = class {
|
|
|
637
644
|
const apiVersions = ["v1"];
|
|
638
645
|
for (const apiVersion of apiVersions) {
|
|
639
646
|
const apiVersionFolderPath = import_path.default.join(baseFolderPath, apiVersion);
|
|
640
|
-
|
|
647
|
+
const directoryExists = await import_internal2.fileUtils.existDir(apiVersionFolderPath);
|
|
648
|
+
if (!directoryExists) continue;
|
|
641
649
|
await this.addDirectory(apiVersionFolderPath, apiVersion);
|
|
642
650
|
}
|
|
643
651
|
}
|
|
@@ -645,12 +653,17 @@ var CustomApiFactory = class {
|
|
|
645
653
|
return this.customApis[customApiName];
|
|
646
654
|
}
|
|
647
655
|
async addDirectory(directoryPath, apiVersion) {
|
|
648
|
-
|
|
656
|
+
var _a2;
|
|
657
|
+
const entries = await import_fs.default.promises.readdir(directoryPath, {
|
|
649
658
|
withFileTypes: true
|
|
650
659
|
});
|
|
651
|
-
|
|
660
|
+
const isTsx2 = (_a2 = process.argv[1]) == null ? void 0 : _a2.endsWith(".ts");
|
|
661
|
+
const isTsNode2 = process.env.TS_NODE_DEV || process.env.TS_NODE_PROJECT;
|
|
662
|
+
const extension = isTsx2 || isTsNode2 ? "ts" : "js";
|
|
663
|
+
const shouldEndWith = `.api.${apiVersion}.${extension}`;
|
|
664
|
+
await import_bluebird.default.map(entries, async (entry) => {
|
|
652
665
|
if (entry.isFile()) {
|
|
653
|
-
if (entry.name.endsWith(
|
|
666
|
+
if (entry.name.endsWith(shouldEndWith) === false) return;
|
|
654
667
|
try {
|
|
655
668
|
const importPath = `${import_path.default.join(directoryPath, entry.name)}`;
|
|
656
669
|
const ApiImport = await import(importPath);
|
|
@@ -662,7 +675,7 @@ var CustomApiFactory = class {
|
|
|
662
675
|
console.error(e);
|
|
663
676
|
}
|
|
664
677
|
}
|
|
665
|
-
}
|
|
678
|
+
});
|
|
666
679
|
}
|
|
667
680
|
bindMethodsToInstance(instance) {
|
|
668
681
|
const proto = Object.getPrototypeOf(instance);
|
|
@@ -1463,11 +1476,11 @@ var SqlEngine = class {
|
|
|
1463
1476
|
return returnValue;
|
|
1464
1477
|
}
|
|
1465
1478
|
replaceLocalParamKeywords(value, routeData, req, sqlParams) {
|
|
1466
|
-
var
|
|
1479
|
+
var _a2;
|
|
1467
1480
|
if (!routeData.request) return value;
|
|
1468
1481
|
const data = req.data;
|
|
1469
1482
|
if (typeof value === "string") {
|
|
1470
|
-
(
|
|
1483
|
+
(_a2 = value.match(/\$[a-zA-Z][a-zA-Z0-9_]+/g)) == null ? void 0 : _a2.forEach((param) => {
|
|
1471
1484
|
const requestParam = routeData.request.find((item) => {
|
|
1472
1485
|
return item.name === param.replace("$", "");
|
|
1473
1486
|
});
|
|
@@ -1480,9 +1493,9 @@ var SqlEngine = class {
|
|
|
1480
1493
|
return value;
|
|
1481
1494
|
}
|
|
1482
1495
|
replaceGlobalParamKeywords(value, routeData, req, sqlParams) {
|
|
1483
|
-
var
|
|
1496
|
+
var _a2;
|
|
1484
1497
|
if (typeof value === "string") {
|
|
1485
|
-
(
|
|
1498
|
+
(_a2 = value.match(/#[a-zA-Z][a-zA-Z0-9_]+/g)) == null ? void 0 : _a2.forEach((param) => {
|
|
1486
1499
|
param = param.replace("#", "");
|
|
1487
1500
|
const globalParamValue = req.requesterDetails[param];
|
|
1488
1501
|
if (!globalParamValue)
|
|
@@ -1598,7 +1611,7 @@ var filterPsqlParser = import_pegjs.default.generate(filterSqlGrammar, {
|
|
|
1598
1611
|
var filterPsqlParser_default = filterPsqlParser;
|
|
1599
1612
|
|
|
1600
1613
|
// src/restura/eventManager.ts
|
|
1601
|
-
var
|
|
1614
|
+
var import_bluebird2 = __toESM(require("bluebird"));
|
|
1602
1615
|
var EventManager = class {
|
|
1603
1616
|
constructor() {
|
|
1604
1617
|
this.actionHandlers = {
|
|
@@ -1635,7 +1648,7 @@ var EventManager = class {
|
|
|
1635
1648
|
}
|
|
1636
1649
|
}
|
|
1637
1650
|
async fireInsertActions(data, triggerResult) {
|
|
1638
|
-
await
|
|
1651
|
+
await import_bluebird2.default.map(
|
|
1639
1652
|
this.actionHandlers.DATABASE_ROW_INSERT,
|
|
1640
1653
|
({ callback, filter }) => {
|
|
1641
1654
|
if (!this.hasHandlersForEventType("DATABASE_ROW_INSERT", filter, triggerResult)) return;
|
|
@@ -1651,7 +1664,7 @@ var EventManager = class {
|
|
|
1651
1664
|
);
|
|
1652
1665
|
}
|
|
1653
1666
|
async fireDeleteActions(data, triggerResult) {
|
|
1654
|
-
await
|
|
1667
|
+
await import_bluebird2.default.map(
|
|
1655
1668
|
this.actionHandlers.DATABASE_ROW_DELETE,
|
|
1656
1669
|
({ callback, filter }) => {
|
|
1657
1670
|
if (!this.hasHandlersForEventType("DATABASE_ROW_DELETE", filter, triggerResult)) return;
|
|
@@ -1666,7 +1679,7 @@ var EventManager = class {
|
|
|
1666
1679
|
);
|
|
1667
1680
|
}
|
|
1668
1681
|
async fireUpdateActions(data, triggerResult) {
|
|
1669
|
-
await
|
|
1682
|
+
await import_bluebird2.default.map(
|
|
1670
1683
|
this.actionHandlers.DATABASE_COLUMN_UPDATE,
|
|
1671
1684
|
({ callback, filter }) => {
|
|
1672
1685
|
if (!this.hasHandlersForEventType("DATABASE_COLUMN_UPDATE", filter, triggerResult)) return;
|
|
@@ -1840,16 +1853,19 @@ var PsqlEngine = class extends SqlEngine {
|
|
|
1840
1853
|
return enums.join("\n") + "\n" + sqlStatements.join("\n\n");
|
|
1841
1854
|
}
|
|
1842
1855
|
async getScratchPool() {
|
|
1843
|
-
await this.psqlConnectionPool.runQuery(
|
|
1844
|
-
`
|
|
1845
|
-
|
|
1846
|
-
systemUser
|
|
1847
|
-
);
|
|
1848
|
-
await this.psqlConnectionPool.runQuery(
|
|
1849
|
-
`CREATE DATABASE ${this.psqlConnectionPool.poolConfig.database}_scratch;`,
|
|
1856
|
+
const response = await this.psqlConnectionPool.runQuery(
|
|
1857
|
+
`SELECT * FROM pg_database
|
|
1858
|
+
WHERE datname = '${this.psqlConnectionPool.poolConfig.database}_scratch'`,
|
|
1850
1859
|
[],
|
|
1851
1860
|
systemUser
|
|
1852
1861
|
);
|
|
1862
|
+
if (response.length === 0) {
|
|
1863
|
+
await this.psqlConnectionPool.runQuery(
|
|
1864
|
+
`CREATE DATABASE ${this.psqlConnectionPool.poolConfig.database}_scratch;`,
|
|
1865
|
+
[],
|
|
1866
|
+
systemUser
|
|
1867
|
+
);
|
|
1868
|
+
}
|
|
1853
1869
|
const scratchPool = new PsqlPool({
|
|
1854
1870
|
host: this.psqlConnectionPool.poolConfig.host,
|
|
1855
1871
|
port: this.psqlConnectionPool.poolConfig.port,
|
|
@@ -1860,6 +1876,12 @@ var PsqlEngine = class extends SqlEngine {
|
|
|
1860
1876
|
idleTimeoutMillis: this.psqlConnectionPool.poolConfig.idleTimeoutMillis,
|
|
1861
1877
|
connectionTimeoutMillis: this.psqlConnectionPool.poolConfig.connectionTimeoutMillis
|
|
1862
1878
|
});
|
|
1879
|
+
await scratchPool.runQuery(`drop schema public cascade;`, [], systemUser);
|
|
1880
|
+
await scratchPool.runQuery(
|
|
1881
|
+
`create schema public authorization ${this.psqlConnectionPool.poolConfig.user};`,
|
|
1882
|
+
[],
|
|
1883
|
+
systemUser
|
|
1884
|
+
);
|
|
1863
1885
|
return scratchPool;
|
|
1864
1886
|
}
|
|
1865
1887
|
async diffDatabaseToSchema(schema) {
|
|
@@ -1879,17 +1901,13 @@ var PsqlEngine = class extends SqlEngine {
|
|
|
1879
1901
|
host: this.psqlConnectionPool.poolConfig.host,
|
|
1880
1902
|
port: this.psqlConnectionPool.poolConfig.port
|
|
1881
1903
|
});
|
|
1882
|
-
|
|
1883
|
-
await
|
|
1884
|
-
const
|
|
1885
|
-
|
|
1886
|
-
});
|
|
1887
|
-
const info2 = await (0, import_pg_info.default)({
|
|
1888
|
-
client: scratchClient
|
|
1889
|
-
});
|
|
1904
|
+
const promises = [originalClient.connect(), scratchClient.connect()];
|
|
1905
|
+
await Promise.all(promises);
|
|
1906
|
+
const infoPromises = [(0, import_pg_info.default)({ client: originalClient }), (0, import_pg_info.default)({ client: scratchClient })];
|
|
1907
|
+
const [info1, info2] = await Promise.all(infoPromises);
|
|
1890
1908
|
const diff = (0, import_pg_diff_sync.default)(info1, info2);
|
|
1891
|
-
|
|
1892
|
-
await
|
|
1909
|
+
const endPromises = [originalClient.end(), scratchClient.end()];
|
|
1910
|
+
await Promise.all(endPromises);
|
|
1893
1911
|
return diff.join("\n");
|
|
1894
1912
|
}
|
|
1895
1913
|
createNestedSelect(req, schema, item, routeData, userRole, sqlParams) {
|
|
@@ -2012,7 +2030,7 @@ var PsqlEngine = class extends SqlEngine {
|
|
|
2012
2030
|
);
|
|
2013
2031
|
const totalQuery = `SELECT COUNT(${routeData.groupBy ? `DISTINCT ${routeData.groupBy.tableName}.${routeData.groupBy.columnName}` : "*"}) AS total
|
|
2014
2032
|
${sqlStatement};`;
|
|
2015
|
-
const totalPromise =
|
|
2033
|
+
const totalPromise = this.psqlConnectionPool.runQuery(
|
|
2016
2034
|
totalQuery,
|
|
2017
2035
|
sqlParams,
|
|
2018
2036
|
req.requesterDetails
|
|
@@ -2029,7 +2047,7 @@ var PsqlEngine = class extends SqlEngine {
|
|
|
2029
2047
|
}
|
|
2030
2048
|
async executeUpdateRequest(req, routeData, schema) {
|
|
2031
2049
|
const sqlParams = [];
|
|
2032
|
-
const
|
|
2050
|
+
const _a2 = req.body, { id } = _a2, bodyNoId = __objRest(_a2, ["id"]);
|
|
2033
2051
|
const table = schema.database.find((item) => {
|
|
2034
2052
|
return item.name === routeData.table;
|
|
2035
2053
|
});
|
|
@@ -2144,22 +2162,22 @@ DELETE FROM "${routeData.table}" ${joinStatement} ${whereClause}`;
|
|
|
2144
2162
|
const data = req.data;
|
|
2145
2163
|
if (routeData.type === "PAGED" && !!(data == null ? void 0 : data.filter)) {
|
|
2146
2164
|
let statement = data.filter.replace(/\$[a-zA-Z][a-zA-Z0-9_]+/g, (value) => {
|
|
2147
|
-
var
|
|
2165
|
+
var _a2;
|
|
2148
2166
|
const requestParam = routeData.request.find((item) => {
|
|
2149
2167
|
return item.name === value.replace("$", "");
|
|
2150
2168
|
});
|
|
2151
2169
|
if (!requestParam)
|
|
2152
2170
|
throw new RsError("SCHEMA_ERROR", `Invalid route keyword in route ${routeData.name}`);
|
|
2153
|
-
return ((
|
|
2171
|
+
return ((_a2 = data[requestParam.name]) == null ? void 0 : _a2.toString()) || "";
|
|
2154
2172
|
});
|
|
2155
2173
|
statement = statement.replace(/#[a-zA-Z][a-zA-Z0-9_]+/g, (value) => {
|
|
2156
|
-
var
|
|
2174
|
+
var _a2;
|
|
2157
2175
|
const requestParam = routeData.request.find((item) => {
|
|
2158
2176
|
return item.name === value.replace("#", "");
|
|
2159
2177
|
});
|
|
2160
2178
|
if (!requestParam)
|
|
2161
2179
|
throw new RsError("SCHEMA_ERROR", `Invalid route keyword in route ${routeData.name}`);
|
|
2162
|
-
return ((
|
|
2180
|
+
return ((_a2 = data[requestParam.name]) == null ? void 0 : _a2.toString()) || "";
|
|
2163
2181
|
});
|
|
2164
2182
|
statement = filterPsqlParser_default.parse(statement);
|
|
2165
2183
|
if (whereClause.startsWith("WHERE")) {
|
|
@@ -2281,13 +2299,13 @@ var CompareSchema = class {
|
|
|
2281
2299
|
const originalClone = (0, import_lodash.default)(originalEndpoints);
|
|
2282
2300
|
const diffObj = [];
|
|
2283
2301
|
newEndPoints.forEach((endPoint) => {
|
|
2284
|
-
const { path:
|
|
2302
|
+
const { path: path5, method } = endPoint;
|
|
2285
2303
|
const endPointIndex = originalClone.findIndex((original) => {
|
|
2286
2304
|
return original.path === endPoint.path && original.method === endPoint.method;
|
|
2287
2305
|
});
|
|
2288
2306
|
if (endPointIndex === -1) {
|
|
2289
2307
|
diffObj.push({
|
|
2290
|
-
name: `${method} ${
|
|
2308
|
+
name: `${method} ${path5}`,
|
|
2291
2309
|
changeType: "NEW"
|
|
2292
2310
|
});
|
|
2293
2311
|
} else {
|
|
@@ -2296,7 +2314,7 @@ var CompareSchema = class {
|
|
|
2296
2314
|
});
|
|
2297
2315
|
if (original === -1) {
|
|
2298
2316
|
diffObj.push({
|
|
2299
|
-
name: `${method} ${
|
|
2317
|
+
name: `${method} ${path5}`,
|
|
2300
2318
|
changeType: "MODIFIED"
|
|
2301
2319
|
});
|
|
2302
2320
|
}
|
|
@@ -2304,9 +2322,9 @@ var CompareSchema = class {
|
|
|
2304
2322
|
}
|
|
2305
2323
|
});
|
|
2306
2324
|
originalClone.forEach((original) => {
|
|
2307
|
-
const { path:
|
|
2325
|
+
const { path: path5, method } = original;
|
|
2308
2326
|
diffObj.push({
|
|
2309
|
-
name: `${method} ${
|
|
2327
|
+
name: `${method} ${path5}`,
|
|
2310
2328
|
changeType: "DELETED"
|
|
2311
2329
|
});
|
|
2312
2330
|
});
|
|
@@ -2331,6 +2349,63 @@ __decorateClass([
|
|
|
2331
2349
|
var compareSchema = new CompareSchema();
|
|
2332
2350
|
var compareSchema_default = compareSchema;
|
|
2333
2351
|
|
|
2352
|
+
// src/restura/middleware/getMulterUploadSingleton.ts
|
|
2353
|
+
var import_multer = __toESM(require("multer"));
|
|
2354
|
+
var import_path3 = require("path");
|
|
2355
|
+
var os = __toESM(require("os"));
|
|
2356
|
+
var OneHundredMB = 100 * 1024 * 1024;
|
|
2357
|
+
var commonUpload = null;
|
|
2358
|
+
var getMulterUploadSingleton = (directory) => {
|
|
2359
|
+
if (commonUpload) return commonUpload;
|
|
2360
|
+
const storage = import_multer.default.diskStorage({
|
|
2361
|
+
destination: directory || os.tmpdir(),
|
|
2362
|
+
filename: function(request, file, cb) {
|
|
2363
|
+
const extension = (0, import_path3.extname)(file.originalname);
|
|
2364
|
+
const uniqueName = Date.now() + "-" + Math.round(Math.random() * 1e3);
|
|
2365
|
+
cb(null, `${uniqueName}${extension}`);
|
|
2366
|
+
}
|
|
2367
|
+
});
|
|
2368
|
+
commonUpload = (0, import_multer.default)({
|
|
2369
|
+
storage,
|
|
2370
|
+
limits: {
|
|
2371
|
+
fileSize: OneHundredMB
|
|
2372
|
+
}
|
|
2373
|
+
});
|
|
2374
|
+
return commonUpload;
|
|
2375
|
+
};
|
|
2376
|
+
|
|
2377
|
+
// src/restura/utils/TempCache.ts
|
|
2378
|
+
var import_fs3 = __toESM(require("fs"));
|
|
2379
|
+
var import_path4 = __toESM(require("path"));
|
|
2380
|
+
var import_core_utils6 = require("@redskytech/core-utils");
|
|
2381
|
+
var import_bluebird3 = __toESM(require("bluebird"));
|
|
2382
|
+
var os2 = __toESM(require("os"));
|
|
2383
|
+
var import_internal3 = require("@restura/internal");
|
|
2384
|
+
var TempCache = class {
|
|
2385
|
+
constructor(location) {
|
|
2386
|
+
this.maxDurationDays = 7;
|
|
2387
|
+
this.location = location || os2.tmpdir();
|
|
2388
|
+
import_internal3.fileUtils.ensureDir(this.location).catch((e) => {
|
|
2389
|
+
throw e;
|
|
2390
|
+
});
|
|
2391
|
+
}
|
|
2392
|
+
async cleanup() {
|
|
2393
|
+
const fileList = await import_fs3.default.promises.readdir(this.location);
|
|
2394
|
+
await import_bluebird3.default.map(
|
|
2395
|
+
fileList,
|
|
2396
|
+
async (file) => {
|
|
2397
|
+
const fullFilePath = import_path4.default.join(this.location, file);
|
|
2398
|
+
const fileStats = await import_fs3.default.promises.stat(fullFilePath);
|
|
2399
|
+
if (import_core_utils6.DateUtils.daysBetweenStartAndEndDates(new Date(fileStats.mtimeMs), /* @__PURE__ */ new Date()) > this.maxDurationDays) {
|
|
2400
|
+
logger.info(`Deleting old temp file: ${file}`);
|
|
2401
|
+
await import_fs3.default.promises.unlink(fullFilePath);
|
|
2402
|
+
}
|
|
2403
|
+
},
|
|
2404
|
+
{ concurrency: 10 }
|
|
2405
|
+
);
|
|
2406
|
+
}
|
|
2407
|
+
};
|
|
2408
|
+
|
|
2334
2409
|
// src/restura/restura.ts
|
|
2335
2410
|
var { types } = import_pg3.default;
|
|
2336
2411
|
var ResturaEngine = class {
|
|
@@ -2350,7 +2425,9 @@ var ResturaEngine = class {
|
|
|
2350
2425
|
* @returns A promise that resolves when the initialization is complete.
|
|
2351
2426
|
*/
|
|
2352
2427
|
async init(app, authenticationHandler, psqlConnectionPool) {
|
|
2353
|
-
this.resturaConfig =
|
|
2428
|
+
this.resturaConfig = import_internal4.config.validate("restura", resturaConfigSchema);
|
|
2429
|
+
this.multerCommonUpload = getMulterUploadSingleton(this.resturaConfig.fileTempCachePath);
|
|
2430
|
+
new TempCache(this.resturaConfig.fileTempCachePath);
|
|
2354
2431
|
this.psqlConnectionPool = psqlConnectionPool;
|
|
2355
2432
|
this.psqlEngine = new PsqlEngine(this.psqlConnectionPool, true);
|
|
2356
2433
|
setupPgReturnTypes();
|
|
@@ -2417,7 +2494,7 @@ var ResturaEngine = class {
|
|
|
2417
2494
|
* @returns A promise that resolves when the API has been successfully generated and written to the output file.
|
|
2418
2495
|
*/
|
|
2419
2496
|
async generateApiFromSchema(outputFile, providedSchema) {
|
|
2420
|
-
|
|
2497
|
+
import_fs4.default.writeFileSync(
|
|
2421
2498
|
outputFile,
|
|
2422
2499
|
await apiGenerator(providedSchema, await this.generateHashForSchema(providedSchema))
|
|
2423
2500
|
);
|
|
@@ -2430,7 +2507,7 @@ var ResturaEngine = class {
|
|
|
2430
2507
|
* @returns A promise that resolves when the model has been successfully written to the output file.
|
|
2431
2508
|
*/
|
|
2432
2509
|
async generateModelFromSchema(outputFile, providedSchema) {
|
|
2433
|
-
|
|
2510
|
+
import_fs4.default.writeFileSync(
|
|
2434
2511
|
outputFile,
|
|
2435
2512
|
await modelGenerator(providedSchema, await this.generateHashForSchema(providedSchema))
|
|
2436
2513
|
);
|
|
@@ -2442,12 +2519,12 @@ var ResturaEngine = class {
|
|
|
2442
2519
|
* @throws {Error} If the schema file is missing or the schema is not valid.
|
|
2443
2520
|
*/
|
|
2444
2521
|
async getLatestFileSystemSchema() {
|
|
2445
|
-
if (!
|
|
2522
|
+
if (!import_fs4.default.existsSync(this.resturaConfig.schemaFilePath)) {
|
|
2446
2523
|
logger.error(`Missing restura schema file, expected path: ${this.resturaConfig.schemaFilePath}`);
|
|
2447
2524
|
throw new Error("Missing restura schema file");
|
|
2448
2525
|
}
|
|
2449
|
-
const schemaFileData =
|
|
2450
|
-
const schema =
|
|
2526
|
+
const schemaFileData = import_fs4.default.readFileSync(this.resturaConfig.schemaFilePath, { encoding: "utf8" });
|
|
2527
|
+
const schema = import_core_utils7.ObjectUtils.safeParse(schemaFileData);
|
|
2451
2528
|
const isValid = await isSchemaValid(schema);
|
|
2452
2529
|
if (!isValid) {
|
|
2453
2530
|
logger.error("Schema is not valid");
|
|
@@ -2465,11 +2542,11 @@ var ResturaEngine = class {
|
|
|
2465
2542
|
* - `modelCreatedSchemaHash`: The hash extracted from the generated `models.d.ts` file.
|
|
2466
2543
|
*/
|
|
2467
2544
|
async getHashes(providedSchema) {
|
|
2468
|
-
var
|
|
2545
|
+
var _a2, _b, _c, _d;
|
|
2469
2546
|
const schemaHash = await this.generateHashForSchema(providedSchema);
|
|
2470
|
-
const apiFile =
|
|
2471
|
-
const apiCreatedSchemaHash = (_b = (
|
|
2472
|
-
const modelFile =
|
|
2547
|
+
const apiFile = import_fs4.default.readFileSync(import_path5.default.join(this.resturaConfig.generatedTypesPath, "api.d.ts"));
|
|
2548
|
+
const apiCreatedSchemaHash = (_b = (_a2 = apiFile.toString().match(/\((.*)\)/)) == null ? void 0 : _a2[1]) != null ? _b : "";
|
|
2549
|
+
const modelFile = import_fs4.default.readFileSync(import_path5.default.join(this.resturaConfig.generatedTypesPath, "models.d.ts"));
|
|
2473
2550
|
const modelCreatedSchemaHash = (_d = (_c = modelFile.toString().match(/\((.*)\)/)) == null ? void 0 : _c[1]) != null ? _d : "";
|
|
2474
2551
|
return {
|
|
2475
2552
|
schemaHash,
|
|
@@ -2505,27 +2582,27 @@ var ResturaEngine = class {
|
|
|
2505
2582
|
logger.info(`Restura loaded (${routeCount}) endpoint${routeCount > 1 ? "s" : ""}`);
|
|
2506
2583
|
}
|
|
2507
2584
|
async validateGeneratedTypesFolder() {
|
|
2508
|
-
if (!
|
|
2509
|
-
|
|
2585
|
+
if (!import_fs4.default.existsSync(this.resturaConfig.generatedTypesPath)) {
|
|
2586
|
+
import_fs4.default.mkdirSync(this.resturaConfig.generatedTypesPath, { recursive: true });
|
|
2510
2587
|
}
|
|
2511
|
-
const hasApiFile =
|
|
2512
|
-
const hasModelsFile =
|
|
2588
|
+
const hasApiFile = import_fs4.default.existsSync(import_path5.default.join(this.resturaConfig.generatedTypesPath, "api.d.ts"));
|
|
2589
|
+
const hasModelsFile = import_fs4.default.existsSync(import_path5.default.join(this.resturaConfig.generatedTypesPath, "models.d.ts"));
|
|
2513
2590
|
if (!hasApiFile) {
|
|
2514
|
-
await this.generateApiFromSchema(
|
|
2591
|
+
await this.generateApiFromSchema(import_path5.default.join(this.resturaConfig.generatedTypesPath, "api.d.ts"), this.schema);
|
|
2515
2592
|
}
|
|
2516
2593
|
if (!hasModelsFile) {
|
|
2517
2594
|
await this.generateModelFromSchema(
|
|
2518
|
-
|
|
2595
|
+
import_path5.default.join(this.resturaConfig.generatedTypesPath, "models.d.ts"),
|
|
2519
2596
|
this.schema
|
|
2520
2597
|
);
|
|
2521
2598
|
}
|
|
2522
2599
|
const hashes = await this.getHashes(this.schema);
|
|
2523
2600
|
if (hashes.schemaHash !== hashes.apiCreatedSchemaHash) {
|
|
2524
|
-
await this.generateApiFromSchema(
|
|
2601
|
+
await this.generateApiFromSchema(import_path5.default.join(this.resturaConfig.generatedTypesPath, "api.d.ts"), this.schema);
|
|
2525
2602
|
}
|
|
2526
2603
|
if (hashes.schemaHash !== hashes.modelCreatedSchemaHash) {
|
|
2527
2604
|
await this.generateModelFromSchema(
|
|
2528
|
-
|
|
2605
|
+
import_path5.default.join(this.resturaConfig.generatedTypesPath, "models.d.ts"),
|
|
2529
2606
|
this.schema
|
|
2530
2607
|
);
|
|
2531
2608
|
}
|
|
@@ -2555,9 +2632,9 @@ var ResturaEngine = class {
|
|
|
2555
2632
|
}
|
|
2556
2633
|
}
|
|
2557
2634
|
async updateTypes() {
|
|
2558
|
-
await this.generateApiFromSchema(
|
|
2635
|
+
await this.generateApiFromSchema(import_path5.default.join(this.resturaConfig.generatedTypesPath, "api.d.ts"), this.schema);
|
|
2559
2636
|
await this.generateModelFromSchema(
|
|
2560
|
-
|
|
2637
|
+
import_path5.default.join(this.resturaConfig.generatedTypesPath, "models.d.ts"),
|
|
2561
2638
|
this.schema
|
|
2562
2639
|
);
|
|
2563
2640
|
}
|
|
@@ -2575,10 +2652,30 @@ var ResturaEngine = class {
|
|
|
2575
2652
|
res.status(400).send({ error: err });
|
|
2576
2653
|
}
|
|
2577
2654
|
}
|
|
2655
|
+
async getMulterFilesIfAny(req, res, routeData) {
|
|
2656
|
+
var _a2;
|
|
2657
|
+
if (!((_a2 = req.header("content-type")) == null ? void 0 : _a2.includes("multipart/form-data"))) return;
|
|
2658
|
+
if (!this.isCustomRoute(routeData)) return;
|
|
2659
|
+
if (!routeData.fileUploadType) {
|
|
2660
|
+
throw new RsError("BAD_REQUEST", "File upload type not defined for route");
|
|
2661
|
+
}
|
|
2662
|
+
const multerFileUploadFunction = routeData.fileUploadType === "MULTIPLE" ? this.multerCommonUpload.array("files") : this.multerCommonUpload.single("file");
|
|
2663
|
+
return new Promise((resolve2, reject) => {
|
|
2664
|
+
multerFileUploadFunction(req, res, (err) => {
|
|
2665
|
+
if (err) {
|
|
2666
|
+
logger.warn("Multer error: " + err);
|
|
2667
|
+
reject(err);
|
|
2668
|
+
}
|
|
2669
|
+
if (req.body["data"]) req.body = JSON.parse(req.body["data"]);
|
|
2670
|
+
resolve2();
|
|
2671
|
+
});
|
|
2672
|
+
});
|
|
2673
|
+
}
|
|
2578
2674
|
async executeRouteLogic(req, res, next) {
|
|
2579
2675
|
try {
|
|
2580
2676
|
const routeData = this.getRouteData(req.method, req.baseUrl, req.path);
|
|
2581
2677
|
this.validateAuthorization(req, routeData);
|
|
2678
|
+
await this.getMulterFilesIfAny(req, res, routeData);
|
|
2582
2679
|
validateRequestParams(req, routeData, this.customTypeValidation);
|
|
2583
2680
|
if (this.isCustomRoute(routeData)) {
|
|
2584
2681
|
await this.runCustomRouteLogic(req, res, routeData);
|
|
@@ -2604,18 +2701,19 @@ var ResturaEngine = class {
|
|
|
2604
2701
|
let domain = routeData.path.split("/")[1];
|
|
2605
2702
|
domain = domain.split("-").reduce((acc, value, index) => {
|
|
2606
2703
|
if (index === 0) acc = value;
|
|
2607
|
-
else acc +=
|
|
2704
|
+
else acc += import_core_utils7.StringUtils.capitalizeFirst(value);
|
|
2608
2705
|
return acc;
|
|
2609
2706
|
}, "");
|
|
2610
|
-
const customApiName = `${
|
|
2707
|
+
const customApiName = `${import_core_utils7.StringUtils.capitalizeFirst(domain)}Api${import_core_utils7.StringUtils.capitalizeFirst(version)}`;
|
|
2611
2708
|
const customApi = customApiFactory_default.getCustomApi(customApiName);
|
|
2612
2709
|
if (!customApi) throw new RsError("NOT_FOUND", `API domain ${domain}-${version} not found`);
|
|
2613
2710
|
const functionName = `${routeData.method.toLowerCase()}${routeData.path.replace(new RegExp("-", "g"), "/").split("/").reduce((acc, cur) => {
|
|
2614
2711
|
if (cur === "") return acc;
|
|
2615
|
-
return acc +
|
|
2712
|
+
return acc + import_core_utils7.StringUtils.capitalizeFirst(cur);
|
|
2616
2713
|
}, "")}`;
|
|
2617
2714
|
const customFunction = customApi[functionName];
|
|
2618
|
-
if (!customFunction)
|
|
2715
|
+
if (!customFunction)
|
|
2716
|
+
throw new RsError("NOT_FOUND", `API path ${routeData.path} not implemented ${functionName}`);
|
|
2619
2717
|
await customFunction(req, res, routeData);
|
|
2620
2718
|
}
|
|
2621
2719
|
async generateHashForSchema(providedSchema) {
|
|
@@ -2642,7 +2740,7 @@ var ResturaEngine = class {
|
|
|
2642
2740
|
printWidth: 120,
|
|
2643
2741
|
singleQuote: true
|
|
2644
2742
|
}));
|
|
2645
|
-
|
|
2743
|
+
import_fs4.default.writeFileSync(this.resturaConfig.schemaFilePath, schemaPrettyStr);
|
|
2646
2744
|
}
|
|
2647
2745
|
resetPublicEndpoints() {
|
|
2648
2746
|
this.publicEndpoints = {
|
|
@@ -2659,13 +2757,13 @@ var ResturaEngine = class {
|
|
|
2659
2757
|
if (!routeData.roles.includes(role))
|
|
2660
2758
|
throw new RsError("UNAUTHORIZED", "Not authorized to access this endpoint");
|
|
2661
2759
|
}
|
|
2662
|
-
getRouteData(method, baseUrl,
|
|
2760
|
+
getRouteData(method, baseUrl, path5) {
|
|
2663
2761
|
const endpoint = this.schema.endpoints.find((item) => {
|
|
2664
2762
|
return item.baseUrl === baseUrl;
|
|
2665
2763
|
});
|
|
2666
2764
|
if (!endpoint) throw new RsError("NOT_FOUND", "Route not found");
|
|
2667
2765
|
const route = endpoint.routes.find((item) => {
|
|
2668
|
-
return item.method === method && item.path ===
|
|
2766
|
+
return item.method === method && item.path === path5;
|
|
2669
2767
|
});
|
|
2670
2768
|
if (!route) throw new RsError("NOT_FOUND", "Route not found");
|
|
2671
2769
|
return route;
|
|
@@ -2686,6 +2784,9 @@ __decorateClass([
|
|
|
2686
2784
|
__decorateClass([
|
|
2687
2785
|
boundMethod
|
|
2688
2786
|
], ResturaEngine.prototype, "getSchemaAndTypes", 1);
|
|
2787
|
+
__decorateClass([
|
|
2788
|
+
boundMethod
|
|
2789
|
+
], ResturaEngine.prototype, "getMulterFilesIfAny", 1);
|
|
2689
2790
|
__decorateClass([
|
|
2690
2791
|
boundMethod
|
|
2691
2792
|
], ResturaEngine.prototype, "executeRouteLogic", 1);
|