unconventional 0.0.1 → 0.0.2

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.
Files changed (89) hide show
  1. package/README.md +2 -1
  2. package/dist/core/abstractbase.controller.d.ts +36 -0
  3. package/dist/core/abstractbase.controller.d.ts.map +1 -0
  4. package/dist/core/abstractbase.controller.js +198 -0
  5. package/dist/core/api-error.d.ts +29 -0
  6. package/dist/core/api-error.d.ts.map +1 -0
  7. package/dist/core/api-error.js +78 -0
  8. package/dist/core/base.cache.d.ts +16 -0
  9. package/dist/core/base.cache.d.ts.map +1 -0
  10. package/dist/core/base.cache.js +72 -0
  11. package/dist/core/base.model.d.ts +40 -0
  12. package/dist/core/base.model.d.ts.map +1 -0
  13. package/dist/core/base.model.js +189 -0
  14. package/dist/core/base.options.d.ts +57 -0
  15. package/dist/core/base.options.d.ts.map +1 -0
  16. package/dist/core/base.options.js +3 -0
  17. package/dist/core/base.service.d.ts +16 -0
  18. package/dist/core/base.service.d.ts.map +1 -0
  19. package/dist/core/base.service.js +122 -0
  20. package/dist/core/index.d.ts +7 -0
  21. package/dist/core/index.d.ts.map +1 -0
  22. package/dist/core/index.js +6 -0
  23. package/dist/core/pg.driver.d.ts +3 -0
  24. package/dist/core/pg.driver.d.ts.map +1 -0
  25. package/dist/core/pg.driver.js +21 -0
  26. package/dist/decorators/index.d.ts +5 -0
  27. package/dist/decorators/index.d.ts.map +1 -0
  28. package/dist/decorators/index.decorator.d.ts +5 -0
  29. package/dist/decorators/index.decorator.d.ts.map +1 -0
  30. package/dist/decorators/index.decorator.js +6 -0
  31. package/dist/decorators/index.js +4 -0
  32. package/dist/decorators/prop.decorator.d.ts +5 -0
  33. package/dist/decorators/prop.decorator.d.ts.map +1 -0
  34. package/dist/decorators/prop.decorator.js +13 -0
  35. package/dist/decorators/timestamp.decorator.d.ts +5 -0
  36. package/dist/decorators/timestamp.decorator.d.ts.map +1 -0
  37. package/dist/decorators/timestamp.decorator.js +6 -0
  38. package/dist/decorators/utils.d.ts +2 -0
  39. package/dist/decorators/utils.d.ts.map +1 -0
  40. package/dist/decorators/utils.js +3 -0
  41. package/dist/index.d.ts +6 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +5 -0
  44. package/dist/server.d.ts +13 -0
  45. package/dist/server.d.ts.map +1 -0
  46. package/dist/server.js +32 -0
  47. package/dist/types/api.types.d.ts +31 -0
  48. package/dist/types/api.types.d.ts.map +1 -0
  49. package/dist/types/api.types.js +17 -0
  50. package/dist/types/db.types.d.ts +25 -0
  51. package/dist/types/db.types.d.ts.map +1 -0
  52. package/dist/types/db.types.js +12 -0
  53. package/dist/types/decorator.types.d.ts +39 -0
  54. package/dist/types/decorator.types.d.ts.map +1 -0
  55. package/dist/types/decorator.types.js +7 -0
  56. package/dist/types/index.d.ts +5 -0
  57. package/dist/types/index.d.ts.map +1 -0
  58. package/dist/types/index.js +4 -0
  59. package/dist/types/server.types.d.ts +11 -0
  60. package/dist/types/server.types.d.ts.map +1 -0
  61. package/dist/types/server.types.js +1 -0
  62. package/dist/utils/api.utils.d.ts +9 -0
  63. package/dist/utils/api.utils.d.ts.map +1 -0
  64. package/dist/utils/api.utils.js +46 -0
  65. package/dist/utils/array.utils.d.ts +3 -0
  66. package/dist/utils/array.utils.d.ts.map +1 -0
  67. package/dist/utils/array.utils.js +20 -0
  68. package/dist/utils/cache.utils.d.ts +3 -0
  69. package/dist/utils/cache.utils.d.ts.map +1 -0
  70. package/dist/utils/cache.utils.js +14 -0
  71. package/dist/utils/crypto.utils.d.ts +2 -0
  72. package/dist/utils/crypto.utils.d.ts.map +1 -0
  73. package/dist/utils/crypto.utils.js +9 -0
  74. package/dist/utils/db.utils.d.ts +10 -0
  75. package/dist/utils/db.utils.d.ts.map +1 -0
  76. package/dist/utils/db.utils.js +127 -0
  77. package/dist/utils/function.utils.d.ts +11 -0
  78. package/dist/utils/function.utils.d.ts.map +1 -0
  79. package/dist/utils/function.utils.js +14 -0
  80. package/dist/utils/index.d.ts +9 -0
  81. package/dist/utils/index.d.ts.map +1 -0
  82. package/dist/utils/index.js +8 -0
  83. package/dist/utils/middleware.utils.d.ts +4 -0
  84. package/dist/utils/middleware.utils.d.ts.map +1 -0
  85. package/dist/utils/middleware.utils.js +10 -0
  86. package/dist/utils/server.utils.d.ts +5 -0
  87. package/dist/utils/server.utils.d.ts.map +1 -0
  88. package/dist/utils/server.utils.js +27 -0
  89. package/package.json +37 -11
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.types.d.ts","sourceRoot":"","sources":["../../src/types/api.types.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,MAAM,CAAC;AAEtC,oBAAY,KAAK;IACf,MAAM,WAAW;CAClB;AAED,oBAAY,WAAW;IACrB,MAAM,SAAS;IACf,IAAI,UAAU;CACf;AAED,eAAO,MAAM,eAAe,MAAM,CAAC;AACnC,eAAO,MAAM,WAAW,aAAa,CAAC;AAEtC,MAAM,MAAM,QAAQ,GAAG;IACrB,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAA;AAED,oBAAY,UAAU;IACpB,OAAO,YAAY;IACnB,YAAY,iBAAiB;CAC9B;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,EAAE,MAAM,CAAC;IAC9B,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC;CACrC,CAAA;AAED,MAAM,MAAM,GAAG,CAAC,CAAC,SAAS,MAAM,GAAG,EAAE,EAAE,CAAC,SAAS,MAAM,GAAG,EAAE,IAAI;IAC9D,QAAQ,EAAE,QAAQ,GAAG,CAAC,CAAC;IACvB,SAAS,EAAE,SAAS,GAAG,CAAC,CAAC;CAC1B,CAAA;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,SAAS,GAAG,GAAG,GAAG,EAAE,CAAC,SAAS,MAAM,GAAG,GAAG,EAAE,CAAC,SAAS,KAAK,GAAG,KAAK,CAAE,SAAQ,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;CAAI"}
@@ -0,0 +1,17 @@
1
+ export var Query;
2
+ (function (Query) {
3
+ Query["Expand"] = "expand";
4
+ })(Query || (Query = {}));
5
+ export var CachePrefix;
6
+ (function (CachePrefix) {
7
+ CachePrefix["Record"] = "rec_";
8
+ CachePrefix["Page"] = "page_";
9
+ })(CachePrefix || (CachePrefix = {}));
10
+ export const DefaultCacheTTL = 900;
11
+ export const MaxCacheTTL = 2147483647;
12
+ export var BaseEnvKey;
13
+ (function (BaseEnvKey) {
14
+ BaseEnvKey["ownerId"] = "ownerId";
15
+ BaseEnvKey["isPrivileged"] = "isPrivileged";
16
+ })(BaseEnvKey || (BaseEnvKey = {}));
17
+ ;
@@ -0,0 +1,25 @@
1
+ /// <reference types="@cloudflare/workers-types" />
2
+ import { Context } from "hono";
3
+ import { OneOrMany, QueryDefinition } from "unconventional-pg-queries";
4
+ export declare const ValidSqlOperators: string[];
5
+ export declare const NullSqlOperators: string[];
6
+ export declare const ValidSortDirections: string[];
7
+ export declare const andOrPattern: RegExp;
8
+ export declare enum SqlAction {
9
+ Select = "SELECT",
10
+ Insert = "INSERT",
11
+ Update = "UPDATE",
12
+ Delete = "DELETE"
13
+ }
14
+ export interface DBCall extends QueryDefinition {
15
+ action: SqlAction;
16
+ type: OneOrMany;
17
+ }
18
+ export type DBProxy<I extends string | DBCall> = <R extends object>(query: I) => Promise<R | null>;
19
+ export interface DB {
20
+ fetch: DBProxy<DBCall>;
21
+ raw: DBProxy<string>;
22
+ }
23
+ export type DBBinding = Fetcher | D1Database | KVNamespace;
24
+ export type DBFactory = (ctx: Context) => DB;
25
+ //# sourceMappingURL=db.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.types.d.ts","sourceRoot":"","sources":["../../src/types/db.types.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,SAAS,EAAE,eAAe,EAAkC,MAAM,2BAA2B,CAAC;AAEvG,eAAO,MAAM,iBAAiB,UAA0C,CAAC;AACzE,eAAO,MAAM,gBAAgB,EAAE,MAAM,EAA0D,CAAC;AAChG,eAAO,MAAM,mBAAmB,UAAsC,CAAC;AAEvE,eAAO,MAAM,YAAY,QAAiB,CAAC;AAE3C,oBAAY,SAAS;IACnB,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,MAAM,WAAW;CAClB;AAED,MAAM,WAAW,MAAO,SAAQ,eAAe;IAC7C,MAAM,EAAE,SAAS,CAAC;IAClB,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AAEnG,MAAM,WAAW,EAAE;IACjB,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACvB,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;CACtB;AAED,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,UAAU,GAAG,WAAW,CAAC;AAC3D,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,EAAE,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { SqlDirection, SqlWhereOperator } from "unconventional-pg-queries";
2
+ export const ValidSqlOperators = Object.values(SqlWhereOperator);
3
+ export const NullSqlOperators = [SqlWhereOperator.IsNull, SqlWhereOperator.IsNotNull];
4
+ export const ValidSortDirections = Object.values(SqlDirection);
5
+ export const andOrPattern = /\s(?=AND|OR)/;
6
+ export var SqlAction;
7
+ (function (SqlAction) {
8
+ SqlAction["Select"] = "SELECT";
9
+ SqlAction["Insert"] = "INSERT";
10
+ SqlAction["Update"] = "UPDATE";
11
+ SqlAction["Delete"] = "DELETE";
12
+ })(SqlAction || (SqlAction = {}));
@@ -0,0 +1,39 @@
1
+ import BaseModel from "../core/base.model";
2
+ export declare type TypedClassDecorator<T> = (target: T) => T | void;
3
+ export type IndexDefinition<T> = {
4
+ [P in keyof T]?: 1 | -1;
5
+ };
6
+ export interface IndexOptions {
7
+ unique?: boolean;
8
+ }
9
+ export interface IndexSummary<T = any> {
10
+ definition: IndexDefinition<T>;
11
+ options?: IndexOptions;
12
+ }
13
+ export declare enum RelationType {
14
+ HasOne = 0,
15
+ HasMany = 1,
16
+ ManyToMany = 2,
17
+ BelongsTo = 3
18
+ }
19
+ export interface RelationPivot<T extends typeof BaseModel = any> {
20
+ model: T;
21
+ from: keyof InstanceType<T>;
22
+ to: keyof InstanceType<T>;
23
+ }
24
+ export interface Relation<Target extends typeof BaseModel = any, Source extends typeof BaseModel = any, Pivot extends typeof BaseModel = any> {
25
+ type: RelationType;
26
+ model: Target;
27
+ from: keyof InstanceType<Source>;
28
+ to: keyof InstanceType<Target>;
29
+ through?: RelationPivot<Pivot>;
30
+ }
31
+ export interface PropOptions<T = any, S extends typeof BaseModel = any, P extends typeof BaseModel = any> {
32
+ required?: boolean;
33
+ unique?: boolean;
34
+ enum?: any;
35
+ default?: T | (() => T);
36
+ relation?: T extends typeof BaseModel ? Relation<T, S, P> : never;
37
+ }
38
+ export type PropSummary<Target = any, Source extends typeof BaseModel = any> = Record<keyof Source, PropOptions<Target, Source>>;
39
+ //# sourceMappingURL=decorator.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decorator.types.d.ts","sourceRoot":"","sources":["../../src/types/decorator.types.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,oBAAoB,CAAC;AAG3C,MAAM,CAAC,OAAO,MAAM,mBAAmB,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;AAMrE,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI;KAC9B,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;CACxB,CAAA;AAGD,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AASD,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,GAAG;IACnC,UAAU,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB;AAMD,oBAAY,YAAY;IACtB,MAAM,IAAI;IACV,OAAO,IAAI;IACX,UAAU,IAAI;IACd,SAAS,IAAI;CACd;AAGD,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,OAAO,SAAS,GAAG,GAAG;IAE7D,KAAK,EAAE,CAAC,CAAC;IAET,IAAI,EAAE,MAAM,YAAY,CAAC,CAAC,CAAC,CAAC;IAE5B,EAAE,EAAE,MAAM,YAAY,CAAC,CAAC,CAAC,CAAC;CAC3B;AAED,MAAM,WAAW,QAAQ,CAAC,MAAM,SAAS,OAAO,SAAS,GAAG,GAAG,EAAE,MAAM,SAAS,OAAO,SAAS,GAAG,GAAG,EAAE,KAAK,SAAS,OAAO,SAAS,GAAG,GAAG;IAE1I,IAAI,EAAE,YAAY,CAAC;IAEnB,KAAK,EAAE,MAAM,CAAC;IAEd,IAAI,EAAE,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;IAEjC,EAAE,EAAE,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;IAE/B,OAAO,CAAC,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;CAChC;AAOD,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,SAAS,OAAO,SAAS,GAAG,GAAG,EAAE,CAAC,SAAS,OAAO,SAAS,GAAG,GAAG;IAKtG,QAAQ,CAAC,EAAE,OAAO,CAAC;IAInB,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB,IAAI,CAAC,EAAE,GAAG,CAAC;IAEX,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAExB,QAAQ,CAAC,EAAE,CAAC,SAAS,OAAO,SAAS,GAAG,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC;CACnE;AAGD,MAAM,MAAM,WAAW,CAAC,MAAM,GAAG,GAAG,EAAE,MAAM,SAAS,OAAO,SAAS,GAAG,GAAG,IAAI,MAAM,CAAC,MAAM,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA"}
@@ -0,0 +1,7 @@
1
+ export var RelationType;
2
+ (function (RelationType) {
3
+ RelationType[RelationType["HasOne"] = 0] = "HasOne";
4
+ RelationType[RelationType["HasMany"] = 1] = "HasMany";
5
+ RelationType[RelationType["ManyToMany"] = 2] = "ManyToMany";
6
+ RelationType[RelationType["BelongsTo"] = 3] = "BelongsTo";
7
+ })(RelationType || (RelationType = {}));
@@ -0,0 +1,5 @@
1
+ export * from './api.types';
2
+ export * from './db.types';
3
+ export * from './decorator.types';
4
+ export * from './server.types';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from './api.types';
2
+ export * from './db.types';
3
+ export * from './decorator.types';
4
+ export * from './server.types';
@@ -0,0 +1,11 @@
1
+ import { MiddlewareHandler } from "hono";
2
+ import { DBFactory } from "./db.types";
3
+ import { cors } from "hono/cors";
4
+ export interface ServerConfig {
5
+ name: string;
6
+ basePath?: string;
7
+ middleware?: MiddlewareHandler[];
8
+ cors?: Parameters<typeof cors>[0];
9
+ getDB: DBFactory;
10
+ }
11
+ //# sourceMappingURL=server.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.types.d.ts","sourceRoot":"","sources":["../../src/types/server.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AACzC,OAAO,EAAE,SAAS,EAAa,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACjC,IAAI,CAAC,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAClC,KAAK,EAAE,SAAS,CAAC;CAClB"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ import { AndOr } from "unconventional-pg-queries";
2
+ export declare function parseExpandString(expand: string): string[];
3
+ export declare function splitExpandUnit(input: string): {
4
+ parent: string;
5
+ children: string;
6
+ };
7
+ export declare function replaceFilter(filter: string | string[] | undefined, target: string, replacement: string, andOr?: AndOr): string;
8
+ export declare function hasFilter(filter: string | string[] | undefined, target: string): boolean;
9
+ //# sourceMappingURL=api.utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.utils.d.ts","sourceRoot":"","sources":["../../src/utils/api.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAalD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CA4B1D;AASD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM;;;EAK5C;AAID,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,GAAE,KAAiB,UAMjI;AAGD,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,WAI9E"}
@@ -0,0 +1,46 @@
1
+ import { AndOr } from "unconventional-pg-queries";
2
+ import { andOrPattern } from "../types/db.types";
3
+ const defaultTarget = ',';
4
+ const openBracket = '[';
5
+ const closeBracket = ']';
6
+ export function parseExpandString(expand) {
7
+ const text = expand.trim();
8
+ if (!text)
9
+ return [];
10
+ const result = [];
11
+ let word = '';
12
+ let bracketCount = 0;
13
+ for (const char of text) {
14
+ if (bracketCount === 0 && char === defaultTarget) {
15
+ result.push(`${word}`);
16
+ word = '';
17
+ }
18
+ else {
19
+ word += char;
20
+ if (char === openBracket)
21
+ bracketCount++;
22
+ else if (char === closeBracket)
23
+ bracketCount--;
24
+ }
25
+ }
26
+ result.push(`${word}`);
27
+ return result;
28
+ }
29
+ export function splitExpandUnit(input) {
30
+ const index = input.indexOf(openBracket);
31
+ if (index === -1)
32
+ return { parent: input, children: '' };
33
+ return { parent: input.slice(0, index), children: input.slice(index + 1, -1) };
34
+ }
35
+ export function replaceFilter(filter, target, replacement, andOr = AndOr.And) {
36
+ if (!filter)
37
+ return replacement;
38
+ const otherFilters = filter.split(andOrPattern).flatMap(x => x.includes(target) ? [] : x);
39
+ otherFilters.push(`${otherFilters.length ? `${andOr} ` : ''}${replacement}`);
40
+ return otherFilters.join(' ');
41
+ }
42
+ export function hasFilter(filter, target) {
43
+ if (!filter)
44
+ return false;
45
+ return filter.split(andOrPattern).some(x => x.startsWith(target));
46
+ }
@@ -0,0 +1,3 @@
1
+ export declare const equalArrays: <T>(a: T[], b: T[]) => boolean;
2
+ export declare function isEmpty(obj: any): boolean;
3
+ //# sourceMappingURL=array.utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"array.utils.d.ts","sourceRoot":"","sources":["../../src/utils/array.utils.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,WAAW,gCAcvB,CAAC;AAGF,wBAAgB,OAAO,CAAC,GAAG,EAAE,GAAG,WAG/B"}
@@ -0,0 +1,20 @@
1
+ export const equalArrays = (a, b) => {
2
+ if (a.length !== b.length)
3
+ return false;
4
+ const clone = [...b];
5
+ for (const key of a) {
6
+ const idx = b.indexOf(key);
7
+ if (idx > -1)
8
+ clone.splice(idx, 1);
9
+ else {
10
+ break;
11
+ }
12
+ }
13
+ return clone.length === 0;
14
+ };
15
+ export function isEmpty(obj) {
16
+ for (const key in obj)
17
+ if (obj[key] !== undefined)
18
+ return false;
19
+ return true;
20
+ }
@@ -0,0 +1,3 @@
1
+ /// <reference types="@cloudflare/workers-types" />
2
+ export declare function getCachedOrFetch<T>(cache: KVNamespace, key: string, fetchFn: () => Promise<T>, ttl?: number): Promise<T>;
3
+ //# sourceMappingURL=cache.utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.utils.d.ts","sourceRoot":"","sources":["../../src/utils/cache.utils.ts"],"names":[],"mappings":";AAEA,wBAAsB,gBAAgB,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,GAAE,MAAwB,GAAG,OAAO,CAAC,CAAC,CAAC,CAkB/I"}
@@ -0,0 +1,14 @@
1
+ import { DefaultCacheTTL } from "../types/api.types";
2
+ export async function getCachedOrFetch(cache, key, fetchFn, ttl = DefaultCacheTTL) {
3
+ if (cache) {
4
+ const cachedResponse = await cache.get(key);
5
+ if (cachedResponse) {
6
+ return JSON.parse(cachedResponse);
7
+ }
8
+ }
9
+ const response = await fetchFn();
10
+ if (response && cache) {
11
+ await cache.put(key, JSON.stringify(response), { expirationTtl: ttl });
12
+ }
13
+ return response;
14
+ }
@@ -0,0 +1,2 @@
1
+ export declare function sha256(value: string): Promise<string>;
2
+ //# sourceMappingURL=crypto.utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.utils.d.ts","sourceRoot":"","sources":["../../src/utils/crypto.utils.ts"],"names":[],"mappings":"AAEA,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,mBAGnC"}
@@ -0,0 +1,9 @@
1
+ export function sha256(value) {
2
+ var buffer = new TextEncoder().encode(value);
3
+ return crypto.subtle.digest("SHA-256", buffer).then(hex);
4
+ }
5
+ function hex(buffer) {
6
+ return [...new Uint8Array(buffer)]
7
+ .map(b => b.toString(16).padStart(2, '0'))
8
+ .join('');
9
+ }
@@ -0,0 +1,10 @@
1
+ import { ConflictResolution, Expansion, SqlConflict, SqlOrder, SqlPaginate, SqlWhere, SqlWhereOperator } from "unconventional-pg-queries";
2
+ import BaseModel from "../core/base.model";
3
+ export declare function getExpand<T extends typeof BaseModel>(model: T, expand?: string): Record<string, Expansion>;
4
+ export declare function getWhere<T extends typeof BaseModel>(model: T, filterString?: string): SqlWhere[];
5
+ export declare function getOrder<T extends typeof BaseModel>(model: T, sort?: string): SqlOrder[];
6
+ export declare function getPage<T extends typeof BaseModel>(model: T, cursor?: string | number): SqlPaginate | undefined;
7
+ export declare function getReturn<T extends typeof BaseModel>(model: T): string[];
8
+ export declare function getConflict<T extends typeof BaseModel>(model: T, action: ConflictResolution, constraint?: Array<keyof InstanceType<T>>): SqlConflict | undefined;
9
+ export declare function buildFilter<T>(field: keyof T, operator: SqlWhereOperator, value?: any): string;
10
+ //# sourceMappingURL=db.utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.utils.d.ts","sourceRoot":"","sources":["../../src/utils/db.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,kBAAkB,EAAE,SAAS,EAAa,WAAW,EAAgB,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAM1K,OAAO,SAAS,MAAM,oBAAoB,CAAC;AAG3C,wBAAgB,SAAS,CAAC,CAAC,SAAS,OAAO,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CA4B1G;AAGD,wBAAgB,QAAQ,CAAC,CAAC,SAAS,OAAO,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,QAAQ,EAAE,CA4ChG;AAGD,wBAAgB,QAAQ,CAAC,CAAC,SAAS,OAAO,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,QAAQ,EAAE,CAwBxF;AAED,wBAAgB,OAAO,CAAC,CAAC,SAAS,OAAO,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,WAAW,GAAG,SAAS,CAK/G;AAGD,wBAAgB,SAAS,CAAC,CAAC,SAAS,OAAO,SAAS,EAAE,KAAK,EAAE,CAAC,GAAG,MAAM,EAAE,CASxE;AAED,wBAAgB,WAAW,CAAC,CAAC,SAAS,OAAO,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,kBAAkB,EAAE,UAAU,CAAC,EAAE,KAAK,CAAC,MAAM,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,WAAW,GAAG,SAAS,CAUhK;AAGD,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,gBAAgB,EAAE,KAAK,CAAC,EAAE,GAAG,UAWrF"}
@@ -0,0 +1,127 @@
1
+ import { AndOr, OneOrMany, SqlDirection } from "unconventional-pg-queries";
2
+ import { NullSqlOperators, ValidSortDirections, ValidSqlOperators, andOrPattern } from "../types/db.types";
3
+ import { RelationType } from "../types/decorator.types";
4
+ import { parseExpandString, splitExpandUnit } from "./api.utils";
5
+ import { equalArrays } from "./array.utils";
6
+ import { APIError } from "../core/api-error";
7
+ export function getExpand(model, expand) {
8
+ if (!expand)
9
+ return {};
10
+ const propSummary = model.schema.props;
11
+ const expansions = {};
12
+ const parts = parseExpandString(expand);
13
+ parts.forEach((field) => {
14
+ const { parent, children } = splitExpandUnit(field);
15
+ const relation = propSummary[parent]?.relation;
16
+ if (!relation)
17
+ throw APIError.errInvalidQueryParameter(`Invalid expansion: ${parent}`);
18
+ expansions[parent] = {
19
+ type: [RelationType.HasOne, RelationType.BelongsTo].includes(relation.type) ? OneOrMany.One : OneOrMany.Many,
20
+ fromTable: model.collection,
21
+ fromField: relation.from.toString(),
22
+ toTable: relation.model.collection,
23
+ toField: relation.to.toString(),
24
+ throughTable: relation.through?.model.collection,
25
+ throughFromField: relation.through?.from.toString(),
26
+ throughToField: relation.through?.to.toString(),
27
+ expand: children ? getExpand(relation.model, children) : undefined
28
+ };
29
+ });
30
+ return expansions;
31
+ }
32
+ export function getWhere(model, filterString) {
33
+ if (!filterString)
34
+ return [];
35
+ const propSummary = model.schema.props;
36
+ const wheres = [];
37
+ if (filterString) {
38
+ filterString.split(andOrPattern).forEach((filter) => {
39
+ let andOr = undefined;
40
+ if (filter.startsWith(AndOr.And)) {
41
+ filter = filter.substring(AndOr.And.length + 1);
42
+ andOr = AndOr.And;
43
+ }
44
+ else if (filter.startsWith(AndOr.Or)) {
45
+ filter = filter.substring(AndOr.Or.length + 1);
46
+ andOr = AndOr.Or;
47
+ }
48
+ let field = filter.substring(0, filter.indexOf(' '));
49
+ let value = filter.substring(filter.lastIndexOf(' ') + 1);
50
+ let operator = filter.substring(filter.indexOf(' ') + 1, filter.lastIndexOf(' '));
51
+ let jsonPath = [];
52
+ if (operator.startsWith('IS')) {
53
+ operator = `${operator} ${value}`;
54
+ value = null;
55
+ }
56
+ if (field.includes('.')) {
57
+ jsonPath = field.split('.');
58
+ field = jsonPath.shift();
59
+ }
60
+ 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}'`);
66
+ wheres.push({ field, jsonPath, operator: operator, value, andOr });
67
+ });
68
+ }
69
+ return wheres;
70
+ }
71
+ export function getOrder(model, sort) {
72
+ if (!sort)
73
+ return [{ field: model.idField, direction: SqlDirection.Asc }];
74
+ const propSummary = model.schema.props;
75
+ const orders = [];
76
+ sort.split(',').forEach((item) => {
77
+ let [field, direction] = item.split(' ');
78
+ let jsonPath = [];
79
+ direction ||= SqlDirection.Asc;
80
+ if (field.includes('.')) {
81
+ jsonPath = field.split('.');
82
+ field = jsonPath.shift();
83
+ }
84
+ 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}'`);
88
+ orders.push({ field, jsonPath, direction: direction.toUpperCase() });
89
+ });
90
+ return orders;
91
+ }
92
+ export function getPage(model, cursor) {
93
+ if (!cursor)
94
+ return undefined;
95
+ const pagination = { field: model.idField, cursor };
96
+ return pagination;
97
+ }
98
+ export function getReturn(model) {
99
+ const propSummary = model.schema.props;
100
+ const fields = [];
101
+ Object.entries(propSummary).forEach(([field, summary]) => {
102
+ if (!summary.relation)
103
+ fields.push(field);
104
+ });
105
+ return fields;
106
+ }
107
+ export function getConflict(model, action, constraint) {
108
+ if (!constraint)
109
+ return undefined;
110
+ const indexes = model.schema.indexes;
111
+ for (const index of indexes) {
112
+ const keys = Object.keys(index.definition);
113
+ if (equalArrays(keys, constraint))
114
+ return { action, constraint: keys };
115
+ }
116
+ return undefined;
117
+ }
118
+ export function buildFilter(field, operator, value) {
119
+ let formatted = `${value}`;
120
+ if (typeof value === 'string')
121
+ formatted = `'${value}'`;
122
+ else if (Array.isArray(value))
123
+ formatted = (typeof value[0] === 'string') ? `('${value.join("','")}')` : `(${value.join()})`;
124
+ else if (value == null || NullSqlOperators.includes(operator))
125
+ formatted = '';
126
+ return `${field} ${operator} ${formatted}`;
127
+ }
@@ -0,0 +1,11 @@
1
+ /// <reference types="@cloudflare/workers-types" />
2
+ import { BackendServer } from "../server";
3
+ import { ServerConfig } from "../types";
4
+ interface CFFunctionDefinition {
5
+ serverConfig: ServerConfig;
6
+ routeRegistrationFn: (server: BackendServer) => void;
7
+ }
8
+ export type CFFunctionHandler = (config: CFFunctionDefinition) => PagesFunction<{}>;
9
+ declare const functionHandler: CFFunctionHandler;
10
+ export default functionHandler;
11
+ //# sourceMappingURL=function.utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"function.utils.d.ts","sourceRoot":"","sources":["../../src/utils/function.utils.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,UAAU,oBAAoB;IAC5B,YAAY,EAAE,YAAY,CAAC;IAC3B,mBAAmB,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;CACtD;AAED,MAAM,MAAM,iBAAiB,GAAG,CAAC,MAAM,EAAE,oBAAoB,KAAK,aAAa,CAAC,EAAE,CAAC,CAAC;AAGpF,QAAA,MAAM,eAAe,EAAE,iBActB,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { BackendServer } from "../server";
2
+ const functionHandler = (config) => {
3
+ const server = new BackendServer();
4
+ let handler;
5
+ return async (eventContext) => {
6
+ if (!server.configured) {
7
+ server.configure(config.serverConfig);
8
+ config.routeRegistrationFn(server);
9
+ handler = server.start();
10
+ }
11
+ return await handler(eventContext);
12
+ };
13
+ };
14
+ export default functionHandler;
@@ -0,0 +1,9 @@
1
+ export * from './api.utils';
2
+ export * from './array.utils';
3
+ export * from './cache.utils';
4
+ export * from './crypto.utils';
5
+ export * from './db.utils';
6
+ export * from './function.utils';
7
+ export * from './middleware.utils';
8
+ export * from './server.utils';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,8 @@
1
+ export * from './api.utils';
2
+ export * from './array.utils';
3
+ export * from './cache.utils';
4
+ export * from './crypto.utils';
5
+ export * from './db.utils';
6
+ export * from './function.utils';
7
+ export * from './middleware.utils';
8
+ export * from './server.utils';
@@ -0,0 +1,4 @@
1
+ import { Input, MiddlewareHandler } from "hono";
2
+ import { BaseHandler, Env } from "../types/api.types";
3
+ 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>;
4
+ //# sourceMappingURL=middleware.utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.utils.d.ts","sourceRoot":"","sources":["../../src/utils/middleware.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAMtD,wBAAgB,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,GAAG,EAAE,CAAC,SAAS,MAAM,GAAG,GAAG,EAAE,CAAC,SAAS,KAAK,GAAG,KAAK,EAAE,CAAC,SAAS,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,iBAAiB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,iBAAiB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,iBAAiB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAanO"}
@@ -0,0 +1,10 @@
1
+ export function Or(...methods) {
2
+ return async (ctx, next) => {
3
+ const halt = async () => { };
4
+ const promises = methods.map(x => x(ctx, halt));
5
+ const values = await Promise.allSettled(promises);
6
+ if (!values.some(x => x.status === "fulfilled"))
7
+ throw values[0].reason;
8
+ await next();
9
+ };
10
+ }
@@ -0,0 +1,5 @@
1
+ import { DBFactory } from "../types";
2
+ export declare const defaultCors: import("hono").MiddlewareHandler;
3
+ export declare const bindDatabase: (getDB: DBFactory) => (ctx: any, next: any) => Promise<void>;
4
+ export declare const defaultErrorHandler: (err: any, ctx: any) => any;
5
+ //# sourceMappingURL=server.utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.utils.d.ts","sourceRoot":"","sources":["../../src/utils/server.utils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAGrC,eAAO,MAAM,WAAW,kCAGtB,CAAC;AAGH,eAAO,MAAM,YAAY,UAAW,SAAS,2CAO5C,CAAC;AAGF,eAAO,MAAM,mBAAmB,6BAc/B,CAAC"}
@@ -0,0 +1,27 @@
1
+ import { cors } from "hono/cors";
2
+ import BaseModel from "../core/base.model";
3
+ import { APIError } from "../core";
4
+ export const defaultCors = cors({
5
+ origin: "*",
6
+ allowMethods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"]
7
+ });
8
+ export const bindDatabase = (getDB) => {
9
+ return async (ctx, next) => {
10
+ if (!BaseModel.db)
11
+ BaseModel.db = getDB(ctx);
12
+ await next();
13
+ };
14
+ };
15
+ export const defaultErrorHandler = (err, ctx) => {
16
+ if (err instanceof APIError) {
17
+ ctx.status(err.statusCode || 500);
18
+ return ctx.json({
19
+ error_code: err.name,
20
+ error: err.message,
21
+ data: err.data
22
+ });
23
+ }
24
+ console.error(err);
25
+ ctx.status(500);
26
+ return ctx.json({ error: err.message });
27
+ };
package/package.json CHANGED
@@ -1,15 +1,7 @@
1
1
  {
2
2
  "name": "unconventional",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "A complete server built on Cloudflare Pages Functions",
5
- "main": "index.js",
6
- "scripts": {
7
- "test": "echo \"Error: no test specified\" && exit 1"
8
- },
9
- "repository": {
10
- "type": "git",
11
- "url": "git+https://github.com/cloudflare-extension/unconventional.git"
12
- },
13
5
  "keywords": [
14
6
  "cloudflare",
15
7
  "pages",
@@ -18,12 +10,46 @@
18
10
  "edge",
19
11
  "server",
20
12
  "express",
21
- "crud"
13
+ "crud",
14
+ "rest",
15
+ "api"
22
16
  ],
23
17
  "author": "Dean Mauro",
24
18
  "license": "MIT",
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/cloudflare-extension/unconventional.git"
22
+ },
25
23
  "bugs": {
26
24
  "url": "https://github.com/cloudflare-extension/unconventional/issues"
27
25
  },
28
- "homepage": "https://github.com/cloudflare-extension/unconventional#readme"
26
+ "homepage": "https://github.com/cloudflare-extension/unconventional#readme",
27
+ "files": [
28
+ "dist"
29
+ ],
30
+ "main": "dist/index.js",
31
+ "types": "dist/index.d.ts",
32
+ "scripts": {
33
+ "clean": "tsc --build --clean",
34
+ "build": "rm -rf dist && tsc --build",
35
+ "watch": "tsc --watch",
36
+ "lint": "eslint . --ext js,jsx,ts,tsx",
37
+ "format": "eslint . --ext js,jsx,ts,tsx --fix",
38
+ "docs:dev": "vitepress dev docs",
39
+ "docs:build": "vitepress build docs",
40
+ "docs:preview": "vitepress preview docs",
41
+ "docs:serve": "vitepress serve docs"
42
+ },
43
+ "peerDependencies": {
44
+ "hono": "^3.11.4",
45
+ "unconventional-pg-queries": "^0.0.5"
46
+ },
47
+ "devDependencies": {
48
+ "@cloudflare/workers-types": "^4.20231121.0",
49
+ "@typescript-eslint/eslint-plugin": "^5.62.0",
50
+ "@typescript-eslint/parser": "^5.62.0",
51
+ "hono": "^3.11.4",
52
+ "typescript": "^5.3.3",
53
+ "unconventional-pg-queries": "^0.0.5"
54
+ }
29
55
  }