unconventional 0.0.3 → 0.0.4
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/core/abstractbase.controller.d.ts +34 -0
- package/dist/core/abstractbase.controller.js +101 -10
- package/dist/core/api-error.js +5 -1
- package/dist/core/base.cache.d.ts +6 -0
- package/dist/core/base.cache.js +31 -14
- package/dist/core/base.model.js +51 -46
- package/dist/core/base.options.d.ts +12 -0
- package/dist/core/base.options.js +2 -1
- package/dist/core/base.service.d.ts +46 -0
- package/dist/core/base.service.js +82 -30
- package/dist/core/index.js +22 -6
- package/dist/core/pg.driver.d.ts +1 -0
- package/dist/core/pg.driver.js +6 -1
- package/dist/decorators/index.decorator.d.ts +10 -0
- package/dist/decorators/index.decorator.js +16 -2
- package/dist/decorators/index.js +20 -4
- package/dist/decorators/prop.decorator.d.ts +14 -0
- package/dist/decorators/prop.decorator.js +19 -1
- package/dist/decorators/timestamp.decorator.d.ts +8 -0
- package/dist/decorators/timestamp.decorator.js +14 -2
- package/dist/decorators/utils.d.ts +5 -0
- package/dist/decorators/utils.js +10 -1
- package/dist/index.js +21 -5
- package/dist/server.d.ts +11 -0
- package/dist/server.js +30 -10
- package/dist/types/api.types.js +11 -8
- package/dist/types/db.types.js +10 -7
- package/dist/types/decorator.types.d.ts +31 -0
- package/dist/types/decorator.types.js +9 -2
- package/dist/types/index.js +20 -4
- package/dist/types/server.types.js +2 -1
- package/dist/utils/api.utils.d.ts +15 -0
- package/dist/utils/api.utils.js +34 -8
- package/dist/utils/array.utils.d.ts +2 -0
- package/dist/utils/array.utils.js +9 -2
- package/dist/utils/cache.utils.js +9 -2
- package/dist/utils/crypto.utils.d.ts +1 -0
- package/dist/utils/crypto.utils.js +7 -1
- package/dist/utils/db.utils.d.ts +5 -0
- package/dist/utils/db.utils.js +55 -36
- package/dist/utils/function.utils.d.ts +1 -0
- package/dist/utils/function.utils.js +6 -3
- package/dist/utils/index.js +24 -8
- package/dist/utils/middleware.utils.d.ts +4 -0
- package/dist/utils/middleware.utils.js +9 -1
- package/dist/utils/server.utils.d.ts +3 -0
- package/dist/utils/server.utils.js +20 -9
- package/package.json +1 -1
package/dist/utils/db.utils.js
CHANGED
|
@@ -1,22 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildFilter = exports.getConflict = exports.getReturn = exports.getPage = exports.getOrder = exports.getWhere = exports.getExpand = void 0;
|
|
4
|
+
const unconventional_pg_queries_1 = require("unconventional-pg-queries");
|
|
5
|
+
const db_types_1 = require("../types/db.types");
|
|
6
|
+
const decorator_types_1 = require("../types/decorator.types");
|
|
7
|
+
const api_utils_1 = require("./api.utils");
|
|
8
|
+
const array_utils_1 = require("./array.utils");
|
|
9
|
+
const api_error_1 = require("../core/api-error");
|
|
10
|
+
/** Converts a stringified list of relational fields to an array of data needed to expand those fields in a SQL environment */
|
|
11
|
+
function getExpand(model, expand) {
|
|
8
12
|
if (!expand)
|
|
9
13
|
return {};
|
|
10
14
|
const propSummary = model.schema.props;
|
|
11
15
|
const expansions = {};
|
|
12
|
-
const parts = parseExpandString(expand);
|
|
16
|
+
const parts = (0, api_utils_1.parseExpandString)(expand);
|
|
13
17
|
parts.forEach((field) => {
|
|
14
|
-
const { parent, children } = splitExpandUnit(field);
|
|
18
|
+
const { parent, children } = (0, api_utils_1.splitExpandUnit)(field);
|
|
15
19
|
const relation = propSummary[parent]?.relation;
|
|
16
20
|
if (!relation)
|
|
17
|
-
throw APIError.errInvalidQueryParameter(`Invalid expansion: ${parent}`);
|
|
21
|
+
throw api_error_1.APIError.errInvalidQueryParameter(`Invalid expansion: ${parent}`);
|
|
18
22
|
expansions[parent] = {
|
|
19
|
-
type: [RelationType.HasOne, RelationType.BelongsTo].includes(relation.type) ? OneOrMany.One : OneOrMany.Many,
|
|
23
|
+
type: [decorator_types_1.RelationType.HasOne, decorator_types_1.RelationType.BelongsTo].includes(relation.type) ? unconventional_pg_queries_1.OneOrMany.One : unconventional_pg_queries_1.OneOrMany.Many,
|
|
20
24
|
fromTable: model.collection,
|
|
21
25
|
fromField: relation.from.toString(),
|
|
22
26
|
toTable: relation.model.collection,
|
|
@@ -29,73 +33,84 @@ export function getExpand(model, expand) {
|
|
|
29
33
|
});
|
|
30
34
|
return expansions;
|
|
31
35
|
}
|
|
32
|
-
|
|
36
|
+
exports.getExpand = getExpand;
|
|
37
|
+
/** Converts a string of filters to an array of 'where' clause outlines for a SQL environment */
|
|
38
|
+
function getWhere(model, filterString) {
|
|
33
39
|
if (!filterString)
|
|
34
40
|
return [];
|
|
35
41
|
const propSummary = model.schema.props;
|
|
36
42
|
const wheres = [];
|
|
37
43
|
if (filterString) {
|
|
38
|
-
filterString.split(andOrPattern).forEach((filter) => {
|
|
44
|
+
filterString.split(db_types_1.andOrPattern).forEach((filter) => {
|
|
45
|
+
// Handle logically combined clauses
|
|
39
46
|
let andOr = undefined;
|
|
40
|
-
if (filter.startsWith(AndOr.And)) {
|
|
41
|
-
filter = filter.substring(AndOr.And.length + 1);
|
|
42
|
-
andOr = AndOr.And;
|
|
47
|
+
if (filter.startsWith(unconventional_pg_queries_1.AndOr.And)) {
|
|
48
|
+
filter = filter.substring(unconventional_pg_queries_1.AndOr.And.length + 1);
|
|
49
|
+
andOr = unconventional_pg_queries_1.AndOr.And;
|
|
43
50
|
}
|
|
44
|
-
else if (filter.startsWith(AndOr.Or)) {
|
|
45
|
-
filter = filter.substring(AndOr.Or.length + 1);
|
|
46
|
-
andOr = AndOr.Or;
|
|
51
|
+
else if (filter.startsWith(unconventional_pg_queries_1.AndOr.Or)) {
|
|
52
|
+
filter = filter.substring(unconventional_pg_queries_1.AndOr.Or.length + 1);
|
|
53
|
+
andOr = unconventional_pg_queries_1.AndOr.Or;
|
|
47
54
|
}
|
|
48
55
|
let field = filter.substring(0, filter.indexOf(' '));
|
|
49
56
|
let value = filter.substring(filter.lastIndexOf(' ') + 1);
|
|
50
57
|
let operator = filter.substring(filter.indexOf(' ') + 1, filter.lastIndexOf(' '));
|
|
51
58
|
let jsonPath = [];
|
|
59
|
+
// Handle IS NULL and IS NOT NULL, which don't have values
|
|
52
60
|
if (operator.startsWith('IS')) {
|
|
53
61
|
operator = `${operator} ${value}`;
|
|
54
62
|
value = null;
|
|
55
63
|
}
|
|
64
|
+
// Handle JSON path
|
|
56
65
|
if (field.includes('.')) {
|
|
57
66
|
jsonPath = field.split('.');
|
|
58
67
|
field = jsonPath.shift();
|
|
59
68
|
}
|
|
60
69
|
if (!propSummary[field])
|
|
61
|
-
throw APIError.errInvalidQueryParameter(`Invalid filter: '${field}'`);
|
|
62
|
-
if (!ValidSqlOperators.includes(operator))
|
|
63
|
-
throw APIError.errInvalidQueryParameter(`Invalid operator in filter: '${operator}'`);
|
|
64
|
-
if (!value && !NullSqlOperators.includes(operator))
|
|
65
|
-
throw APIError.errInvalidQueryParameter(`Invalid value in filter: '${value}'`);
|
|
70
|
+
throw api_error_1.APIError.errInvalidQueryParameter(`Invalid filter: '${field}'`);
|
|
71
|
+
if (!db_types_1.ValidSqlOperators.includes(operator))
|
|
72
|
+
throw api_error_1.APIError.errInvalidQueryParameter(`Invalid operator in filter: '${operator}'`);
|
|
73
|
+
if (!value && !db_types_1.NullSqlOperators.includes(operator))
|
|
74
|
+
throw api_error_1.APIError.errInvalidQueryParameter(`Invalid value in filter: '${value}'`);
|
|
66
75
|
wheres.push({ field, jsonPath, operator: operator, value, andOr });
|
|
67
76
|
});
|
|
68
77
|
}
|
|
69
78
|
return wheres;
|
|
70
79
|
}
|
|
71
|
-
|
|
80
|
+
exports.getWhere = getWhere;
|
|
81
|
+
/** Converts a stringified list of fields to order ascending or descending to an array of order data for a SQL environment */
|
|
82
|
+
function getOrder(model, sort) {
|
|
72
83
|
if (!sort)
|
|
73
|
-
return [{ field: model.idField, direction: SqlDirection.Asc }];
|
|
84
|
+
return [{ field: model.idField, direction: unconventional_pg_queries_1.SqlDirection.Asc }];
|
|
74
85
|
const propSummary = model.schema.props;
|
|
75
86
|
const orders = [];
|
|
76
87
|
sort.split(',').forEach((item) => {
|
|
77
88
|
let [field, direction] = item.split(' ');
|
|
78
89
|
let jsonPath = [];
|
|
79
|
-
direction ||= SqlDirection.Asc;
|
|
90
|
+
direction ||= unconventional_pg_queries_1.SqlDirection.Asc;
|
|
91
|
+
// Handle JSON path
|
|
80
92
|
if (field.includes('.')) {
|
|
81
93
|
jsonPath = field.split('.');
|
|
82
94
|
field = jsonPath.shift();
|
|
83
95
|
}
|
|
84
96
|
if (!propSummary[field])
|
|
85
|
-
throw APIError.errInvalidQueryParameter(`Invalid orderBy field: '${field}'`);
|
|
86
|
-
if (!ValidSortDirections.includes(direction.toUpperCase()))
|
|
87
|
-
throw APIError.errInvalidQueryParameter(`Invalid orderBy direction: '${direction}'`);
|
|
97
|
+
throw api_error_1.APIError.errInvalidQueryParameter(`Invalid orderBy field: '${field}'`);
|
|
98
|
+
if (!db_types_1.ValidSortDirections.includes(direction.toUpperCase()))
|
|
99
|
+
throw api_error_1.APIError.errInvalidQueryParameter(`Invalid orderBy direction: '${direction}'`);
|
|
88
100
|
orders.push({ field, jsonPath, direction: direction.toUpperCase() });
|
|
89
101
|
});
|
|
90
102
|
return orders;
|
|
91
103
|
}
|
|
92
|
-
|
|
104
|
+
exports.getOrder = getOrder;
|
|
105
|
+
function getPage(model, cursor) {
|
|
93
106
|
if (!cursor)
|
|
94
107
|
return undefined;
|
|
95
108
|
const pagination = { field: model.idField, cursor };
|
|
96
109
|
return pagination;
|
|
97
110
|
}
|
|
98
|
-
|
|
111
|
+
exports.getPage = getPage;
|
|
112
|
+
/** Retrieves all non-relational fields from a model for the 'returning' clause of a SQL call */
|
|
113
|
+
function getReturn(model) {
|
|
99
114
|
const propSummary = model.schema.props;
|
|
100
115
|
const fields = [];
|
|
101
116
|
Object.entries(propSummary).forEach(([field, summary]) => {
|
|
@@ -104,24 +119,28 @@ export function getReturn(model) {
|
|
|
104
119
|
});
|
|
105
120
|
return fields;
|
|
106
121
|
}
|
|
107
|
-
|
|
122
|
+
exports.getReturn = getReturn;
|
|
123
|
+
function getConflict(model, action, constraint) {
|
|
108
124
|
if (!constraint)
|
|
109
125
|
return undefined;
|
|
110
126
|
const indexes = model.schema.indexes;
|
|
111
127
|
for (const index of indexes) {
|
|
112
128
|
const keys = Object.keys(index.definition);
|
|
113
|
-
if (equalArrays(keys, constraint))
|
|
129
|
+
if ((0, array_utils_1.equalArrays)(keys, constraint))
|
|
114
130
|
return { action, constraint: keys };
|
|
115
131
|
}
|
|
116
132
|
return undefined;
|
|
117
133
|
}
|
|
118
|
-
|
|
134
|
+
exports.getConflict = getConflict;
|
|
135
|
+
/** A type-safe way to build filter strings */
|
|
136
|
+
function buildFilter(field, operator, value) {
|
|
119
137
|
let formatted = `${value}`;
|
|
120
138
|
if (typeof value === 'string')
|
|
121
139
|
formatted = `'${value}'`;
|
|
122
140
|
else if (Array.isArray(value))
|
|
123
141
|
formatted = (typeof value[0] === 'string') ? `('${value.join("','")}')` : `(${value.join()})`;
|
|
124
|
-
else if (value == null || NullSqlOperators.includes(operator))
|
|
142
|
+
else if (value == null || db_types_1.NullSqlOperators.includes(operator))
|
|
125
143
|
formatted = '';
|
|
126
144
|
return `${field} ${operator} ${formatted}`;
|
|
127
145
|
}
|
|
146
|
+
exports.buildFilter = buildFilter;
|
|
@@ -6,5 +6,6 @@ interface CFFunctionDefinition {
|
|
|
6
6
|
routeRegistrationFn: (server: BackendServer) => void;
|
|
7
7
|
}
|
|
8
8
|
export type CFFunctionHandler = (config: CFFunctionDefinition) => PagesFunction<{}>;
|
|
9
|
+
/** A Cloudflare Pages function handler configured with routes, a database connection, middleware, cors, and error handling OOTB. */
|
|
9
10
|
declare const functionHandler: CFFunctionHandler;
|
|
10
11
|
export default functionHandler;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const server_1 = require("../server");
|
|
4
|
+
/** A Cloudflare Pages function handler configured with routes, a database connection, middleware, cors, and error handling OOTB. */
|
|
2
5
|
const functionHandler = (config) => {
|
|
3
|
-
const server = new BackendServer();
|
|
6
|
+
const server = new server_1.BackendServer();
|
|
4
7
|
let handler;
|
|
5
8
|
return async (eventContext) => {
|
|
6
9
|
if (!server.configured) {
|
|
@@ -11,4 +14,4 @@ const functionHandler = (config) => {
|
|
|
11
14
|
return await handler(eventContext);
|
|
12
15
|
};
|
|
13
16
|
};
|
|
14
|
-
|
|
17
|
+
exports.default = functionHandler;
|
package/dist/utils/index.js
CHANGED
|
@@ -1,8 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./api.utils"), exports);
|
|
18
|
+
__exportStar(require("./array.utils"), exports);
|
|
19
|
+
__exportStar(require("./cache.utils"), exports);
|
|
20
|
+
__exportStar(require("./crypto.utils"), exports);
|
|
21
|
+
__exportStar(require("./db.utils"), exports);
|
|
22
|
+
__exportStar(require("./function.utils"), exports);
|
|
23
|
+
__exportStar(require("./middleware.utils"), exports);
|
|
24
|
+
__exportStar(require("./server.utils"), exports);
|
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
import { Input, MiddlewareHandler } from "hono";
|
|
2
2
|
import { BaseHandler, Env } from "../types/api.types";
|
|
3
|
+
/**
|
|
4
|
+
* Combines any number of RequestHandlers into one function that performs
|
|
5
|
+
* the logical OR of their results.
|
|
6
|
+
*/
|
|
3
7
|
export declare function Or<E extends Env = Env, P extends string = any, I extends Input = Input, T extends BaseHandler<E, P, I> | MiddlewareHandler<E, P, I> = MiddlewareHandler<E, P, I>>(...methods: Array<T>): MiddlewareHandler<E, P, I>;
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Or = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Combines any number of RequestHandlers into one function that performs
|
|
6
|
+
* the logical OR of their results.
|
|
7
|
+
*/
|
|
8
|
+
function Or(...methods) {
|
|
2
9
|
return async (ctx, next) => {
|
|
3
10
|
const halt = async () => { };
|
|
4
11
|
const promises = methods.map(x => x(ctx, halt));
|
|
@@ -8,3 +15,4 @@ export function Or(...methods) {
|
|
|
8
15
|
await next();
|
|
9
16
|
};
|
|
10
17
|
}
|
|
18
|
+
exports.Or = Or;
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { DBFactory } from "../types";
|
|
2
|
+
/** Default CORS middleware permitting all origins and methods */
|
|
2
3
|
export declare const defaultCors: import("hono").MiddlewareHandler;
|
|
4
|
+
/** Binds the database proxy to the BaseModel */
|
|
3
5
|
export declare const bindDatabase: (getDB: DBFactory) => (ctx: any, next: any) => Promise<void>;
|
|
6
|
+
/** Catches and formats errors in a standard way */
|
|
4
7
|
export declare const defaultErrorHandler: (err: any, ctx: any) => any;
|
|
@@ -1,19 +1,29 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.defaultErrorHandler = exports.bindDatabase = exports.defaultCors = void 0;
|
|
7
|
+
const cors_1 = require("hono/cors");
|
|
8
|
+
const base_model_1 = __importDefault(require("../core/base.model"));
|
|
9
|
+
const core_1 = require("../core");
|
|
10
|
+
/** Default CORS middleware permitting all origins and methods */
|
|
11
|
+
exports.defaultCors = (0, cors_1.cors)({
|
|
5
12
|
origin: "*",
|
|
6
13
|
allowMethods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"]
|
|
7
14
|
});
|
|
8
|
-
|
|
15
|
+
/** Binds the database proxy to the BaseModel */
|
|
16
|
+
const bindDatabase = (getDB) => {
|
|
9
17
|
return async (ctx, next) => {
|
|
10
|
-
if (!
|
|
11
|
-
|
|
18
|
+
if (!base_model_1.default.db)
|
|
19
|
+
base_model_1.default.db = getDB(ctx);
|
|
12
20
|
await next();
|
|
13
21
|
};
|
|
14
22
|
};
|
|
15
|
-
|
|
16
|
-
|
|
23
|
+
exports.bindDatabase = bindDatabase;
|
|
24
|
+
/** Catches and formats errors in a standard way */
|
|
25
|
+
const defaultErrorHandler = (err, ctx) => {
|
|
26
|
+
if (err instanceof core_1.APIError) {
|
|
17
27
|
ctx.status(err.statusCode || 500);
|
|
18
28
|
return ctx.json({
|
|
19
29
|
error_code: err.name,
|
|
@@ -25,3 +35,4 @@ export const defaultErrorHandler = (err, ctx) => {
|
|
|
25
35
|
ctx.status(500);
|
|
26
36
|
return ctx.json({ error: err.message });
|
|
27
37
|
};
|
|
38
|
+
exports.defaultErrorHandler = defaultErrorHandler;
|