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,189 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { ConflictResolution, OneOrMany, SqlWhereOperator } from "unconventional-pg-queries";
11
+ import { prop } from "../decorators/prop.decorator";
12
+ import { timestamp } from "../decorators/timestamp.decorator";
13
+ import { SqlAction } from "../types/db.types";
14
+ import { getConflict, getExpand, getOrder, getPage, getWhere } from "../utils/db.utils";
15
+ export class Document {
16
+ static schema = { indexes: [], props: {} };
17
+ }
18
+ export default class BaseModel extends Document {
19
+ static collection;
20
+ static idField = 'id';
21
+ static keyField;
22
+ static ownerField;
23
+ static db;
24
+ id;
25
+ static async create(data, upsertConfig) {
26
+ const timestamp = this.schema.timestamped ? {
27
+ updatedAt: new Date(),
28
+ createdAt: new Date()
29
+ } : {};
30
+ const response = await this.db.fetch({
31
+ action: SqlAction.Insert,
32
+ type: OneOrMany.One,
33
+ table: this.collection,
34
+ conflict: getConflict(this, upsertConfig?.action || ConflictResolution.doUpdate, upsertConfig?.constraint),
35
+ data: this.addDefaults({ ...data, ...timestamp })
36
+ });
37
+ if (!response)
38
+ return null;
39
+ const result = Array.isArray(response) ? response[0] : response;
40
+ return this.fromDatabaseJson(result);
41
+ }
42
+ static async createMany(data, upsertConfig) {
43
+ const timestamp = this.schema.timestamped ? {
44
+ updatedAt: new Date(),
45
+ createdAt: new Date()
46
+ } : {};
47
+ const response = await this.db.fetch({
48
+ action: SqlAction.Insert,
49
+ type: OneOrMany.Many,
50
+ table: this.collection,
51
+ conflict: getConflict(this, upsertConfig?.action || ConflictResolution.doUpdate, upsertConfig?.constraint),
52
+ data: data.map(item => this.addDefaults({ ...item, ...timestamp }))
53
+ });
54
+ if (!response)
55
+ return null;
56
+ return response.map(item => this.fromDatabaseJson(item));
57
+ }
58
+ static async findById(id, config) {
59
+ const response = await this.db.fetch({
60
+ action: SqlAction.Select,
61
+ type: OneOrMany.One,
62
+ table: this.collection,
63
+ expand: getExpand(this, config?.expand),
64
+ where: [{ field: this.idField, operator: SqlWhereOperator.Eq, value: id }]
65
+ });
66
+ return response ? this.fromDatabaseJson(response) : null;
67
+ }
68
+ static async findOne(config) {
69
+ const response = await this.db.fetch({
70
+ action: SqlAction.Select,
71
+ type: OneOrMany.One,
72
+ table: this.collection,
73
+ expand: getExpand(this, config?.expand),
74
+ where: getWhere(this, config?.filter)
75
+ });
76
+ return response ? this.fromDatabaseJson(response) : null;
77
+ }
78
+ static async findMany(config) {
79
+ const response = await this.db.fetch({
80
+ action: SqlAction.Select,
81
+ type: OneOrMany.Many,
82
+ table: this.collection,
83
+ expand: getExpand(this, config?.expand),
84
+ where: getWhere(this, config?.filter),
85
+ order: getOrder(this, config?.sort),
86
+ page: getPage(this, config?.cursor),
87
+ limit: config?.limit
88
+ });
89
+ return response ? response.map(item => this.fromDatabaseJson(item)) : [];
90
+ }
91
+ static async update(id, data) {
92
+ const timestamp = this.schema.timestamped ? { updatedAt: new Date() } : {};
93
+ delete data[this.idField];
94
+ const response = await this.db.fetch({
95
+ action: SqlAction.Update,
96
+ type: OneOrMany.One,
97
+ table: this.collection,
98
+ where: [{ field: this.idField, operator: SqlWhereOperator.Eq, value: id }],
99
+ data: { ...data, ...timestamp }
100
+ });
101
+ if (!response)
102
+ return null;
103
+ const result = Array.isArray(response) ? response[0] : response;
104
+ return this.fromDatabaseJson(result);
105
+ }
106
+ static async updateMany(data) {
107
+ const timestamp = this.schema.timestamped ? { updatedAt: new Date() } : {};
108
+ const response = await this.db.fetch({
109
+ action: SqlAction.Update,
110
+ type: OneOrMany.Many,
111
+ table: this.collection,
112
+ data: data.map(item => ({ ...item, ...timestamp }))
113
+ });
114
+ if (!response)
115
+ return null;
116
+ return response.map(item => this.fromDatabaseJson(item));
117
+ }
118
+ static async delete(id) {
119
+ const response = await this.db.fetch({
120
+ action: SqlAction.Delete,
121
+ type: OneOrMany.One,
122
+ table: this.collection,
123
+ where: [{ field: this.idField, operator: SqlWhereOperator.Eq, value: id }]
124
+ });
125
+ if (!response)
126
+ return null;
127
+ const result = Array.isArray(response) ? response[0] : response;
128
+ return this.fromDatabaseJson(result);
129
+ }
130
+ static async deleteMany(config) {
131
+ const response = await this.db.fetch({
132
+ action: SqlAction.Delete,
133
+ type: OneOrMany.Many,
134
+ table: this.collection,
135
+ where: getWhere(this, config?.filter)
136
+ });
137
+ if (!response)
138
+ return null;
139
+ return response.map(item => this.fromDatabaseJson(item));
140
+ }
141
+ static async count() {
142
+ const response = await this.db.fetch({
143
+ action: SqlAction.Select,
144
+ type: OneOrMany.Many,
145
+ table: this.collection,
146
+ count: true
147
+ });
148
+ if (!response)
149
+ return null;
150
+ return response.count;
151
+ }
152
+ static fromDatabaseJson(json) {
153
+ const model = new this();
154
+ Object.assign(model, json);
155
+ return model;
156
+ }
157
+ static addDefaults(data) {
158
+ Object.entries(this.schema.props).forEach(([key, options]) => {
159
+ if (data[key] === undefined && options.default != null) {
160
+ const val = options.default;
161
+ data[key] = typeof val === "function" ? val() : val;
162
+ }
163
+ });
164
+ return data;
165
+ }
166
+ $id() { return this[this.constructor['idField']]; }
167
+ $key() { return this[this.constructor['keyField']]; }
168
+ $owner() { return this[this.constructor['ownerField']]; }
169
+ }
170
+ __decorate([
171
+ prop({ required: true, unique: true }),
172
+ __metadata("design:type", Number)
173
+ ], BaseModel.prototype, "id", void 0);
174
+ let TimeStamped = class TimeStamped extends BaseModel {
175
+ createdAt;
176
+ updatedAt;
177
+ };
178
+ __decorate([
179
+ prop(),
180
+ __metadata("design:type", Date)
181
+ ], TimeStamped.prototype, "createdAt", void 0);
182
+ __decorate([
183
+ prop(),
184
+ __metadata("design:type", Date)
185
+ ], TimeStamped.prototype, "updatedAt", void 0);
186
+ TimeStamped = __decorate([
187
+ timestamp()
188
+ ], TimeStamped);
189
+ export { TimeStamped };
@@ -0,0 +1,57 @@
1
+ /// <reference types="@cloudflare/workers-types" />
2
+ import { ConflictResolution } from "unconventional-pg-queries";
3
+ import { Env } from "../types/api.types";
4
+ import BaseModel from "./base.model";
5
+ export interface PageConfig {
6
+ limit?: number;
7
+ cursor?: string;
8
+ sort?: string;
9
+ }
10
+ export interface FilterConfig {
11
+ filter?: string;
12
+ expand?: string;
13
+ }
14
+ interface DownloadResponse {
15
+ filename: string;
16
+ buffer: ArrayBufferLike;
17
+ }
18
+ export interface UpsertConfig<M extends typeof BaseModel> {
19
+ constraint?: Array<keyof InstanceType<M>>;
20
+ action?: ConflictResolution;
21
+ }
22
+ export interface ServiceConfig<M extends typeof BaseModel> {
23
+ cache?: KVNamespace;
24
+ cacheTTL?: number;
25
+ upsertConfig?: UpsertConfig<M>;
26
+ }
27
+ export interface ControllerOptions {
28
+ cache?: boolean;
29
+ cacheTTL?: number;
30
+ }
31
+ export type PI<T extends abstract new (...args: any[]) => any> = Partial<InstanceType<T>>;
32
+ export type I<T extends abstract new (...args: any[]) => any> = InstanceType<T>;
33
+ export interface ControllerMethodOptions<M extends typeof BaseModel, V extends Env, U extends PI<M> | PI<M>[] = PI<M>, W extends I<M> | I<M>[] = I<M>> {
34
+ before?: BodyProcessor<M, V, U>;
35
+ after?: ResponseProcessor<M, V, U, W>;
36
+ cache?: boolean;
37
+ cacheTTL?: number;
38
+ limitOverride?: boolean;
39
+ upsertContraint?: Array<keyof InstanceType<M>>;
40
+ }
41
+ export interface DownloadMethodOptions<M extends typeof BaseModel, V extends Env, U extends PI<M> | PI<M>[] = any, W extends I<M> | I<M>[] = any> {
42
+ download?: DownloadProcessor<M, V, U, W>;
43
+ }
44
+ export interface RequestContext<M extends typeof BaseModel, V extends Env, U extends PI<M> | PI<M>[] = PI<M>> {
45
+ headers: Headers;
46
+ waitUntil: (promise: Promise<unknown>) => void;
47
+ body: U;
48
+ params: Record<string, string>;
49
+ queries: Record<string, string | string[]>;
50
+ env: V['Bindings'];
51
+ get: <Key extends keyof V['Variables']>(key: Key) => V['Variables'][Key];
52
+ }
53
+ export type BodyProcessor<M extends typeof BaseModel, V extends Env, U extends PI<M> | PI<M>[] = PI<M>> = (requestContext: RequestContext<M, V, U>) => Promise<void>;
54
+ export type ResponseProcessor<M extends typeof BaseModel, V extends Env = Env, U extends PI<M> | PI<M>[] = PI<M>, W extends I<M> | I<M>[] = I<M>> = (requestContext: RequestContext<M, V, U>, response: W) => Promise<void>;
55
+ export type DownloadProcessor<M extends typeof BaseModel, V extends Env = Env, U extends PI<M> | PI<M>[] = any, W = any> = (requestContext: RequestContext<M, V, U>, response: W) => Promise<DownloadResponse>;
56
+ export {};
57
+ //# sourceMappingURL=base.options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.options.d.ts","sourceRoot":"","sources":["../../src/core/base.options.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ ;
2
+ ;
3
+ export {};
@@ -0,0 +1,16 @@
1
+ import BaseModel from "./base.model";
2
+ import { FilterConfig, PageConfig, ServiceConfig } from "./base.options";
3
+ export default class BaseService<M extends typeof BaseModel> {
4
+ private model;
5
+ constructor(model: M);
6
+ static for<M extends typeof BaseModel>(model: M): BaseService<M>;
7
+ create(data: Partial<InstanceType<M>>, config?: ServiceConfig<M>): Promise<InstanceType<M>>;
8
+ createMany(data: Partial<InstanceType<M>>[], config?: ServiceConfig<M>): Promise<InstanceType<M>[]>;
9
+ get(identifier: string | number, config?: FilterConfig & ServiceConfig<M>): Promise<InstanceType<M>>;
10
+ getAll(config?: PageConfig & FilterConfig & ServiceConfig<M>): Promise<Array<InstanceType<M>>>;
11
+ update(identifier: string, data: Partial<InstanceType<M>>, config?: ServiceConfig<M>): Promise<InstanceType<M>>;
12
+ updateMany(data: Partial<InstanceType<M>>[], config?: ServiceConfig<M>): Promise<InstanceType<M>[]>;
13
+ delete(identifier: string, config?: ServiceConfig<M>): Promise<InstanceType<M>>;
14
+ deleteMany(config?: FilterConfig & ServiceConfig<M>): Promise<InstanceType<M>[]>;
15
+ }
16
+ //# sourceMappingURL=base.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.service.d.ts","sourceRoot":"","sources":["../../src/core/base.service.ts"],"names":[],"mappings":"AAGA,OAAO,SAAS,MAAM,cAAc,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGzE,MAAM,CAAC,OAAO,OAAO,WAAW,CAAC,CAAC,SAAS,OAAO,SAAS;IACzD,OAAO,CAAC,KAAK,CAAI;gBAGL,KAAK,EAAE,CAAC;IAKpB,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,OAAO,SAAS,EAAE,KAAK,EAAE,CAAC;IASlC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAkB3F,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IAoBnG,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAoCpG,MAAM,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,YAAY,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;IA2B9F,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAkB/G,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IAoBnG,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAiB/E,UAAU,CAAC,MAAM,CAAC,EAAE,YAAY,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;CAgB9F"}
@@ -0,0 +1,122 @@
1
+ import { SqlWhereOperator } from "unconventional-pg-queries";
2
+ import { APIError } from "./api-error";
3
+ import BaseCache from "./base.cache";
4
+ import { buildFilter } from "../utils/db.utils";
5
+ export default class BaseService {
6
+ model;
7
+ constructor(model) {
8
+ this.model = model;
9
+ }
10
+ static for(model) {
11
+ return new this(model);
12
+ }
13
+ async create(data, config) {
14
+ const response = await this.model.create(data, config?.upsertConfig);
15
+ if (!response) {
16
+ throw APIError.errResourceCreationFailed(`Failed to create ${this.model.name}`);
17
+ }
18
+ else if (config?.cache) {
19
+ await BaseCache.clearPage(config.cache, this.model);
20
+ await BaseCache.setModel(config.cache, response, undefined, config.cacheTTL);
21
+ }
22
+ return response;
23
+ }
24
+ async createMany(data, config) {
25
+ const response = await this.model.createMany(data, config?.upsertConfig);
26
+ if (!response) {
27
+ throw APIError.errResourceCreationFailed(`Failed to create ${this.model.name}s`);
28
+ }
29
+ else if (config?.cache) {
30
+ const cache = config.cache;
31
+ await BaseCache.clearPage(cache, this.model);
32
+ await Promise.all(response.map(item => BaseCache.setModel(cache, item, undefined, config.cacheTTL)));
33
+ }
34
+ return response;
35
+ }
36
+ async get(identifier, config) {
37
+ const { cache, cacheTTL, ...modifiers } = config || {};
38
+ let entity = null;
39
+ if (cache) {
40
+ entity = await BaseCache.getModel(cache, this.model, identifier, modifiers);
41
+ }
42
+ if (!entity) {
43
+ if (!isNaN(+identifier)) {
44
+ entity = await this.model.findById(identifier, modifiers);
45
+ }
46
+ else {
47
+ const keyFilter = buildFilter(this.model.keyField, SqlWhereOperator.Eq, identifier);
48
+ const filter = modifiers.filter ? `${modifiers.filter} AND ${keyFilter}` : keyFilter;
49
+ entity = await this.model.findOne({ ...modifiers, filter });
50
+ }
51
+ if (!entity)
52
+ throw APIError.errNotFound(`No ${this.model.name} found with id ${identifier}`);
53
+ if (cache) {
54
+ await BaseCache.setModel(cache, entity, modifiers, cacheTTL);
55
+ }
56
+ }
57
+ return entity;
58
+ }
59
+ async getAll(config) {
60
+ const { cache, cacheTTL, ...modifiers } = config || {};
61
+ let page = null;
62
+ if (cache) {
63
+ page = await BaseCache.getPage(cache, this.model, modifiers);
64
+ }
65
+ if (!page) {
66
+ const limit = modifiers.limit || 12;
67
+ page = await this.model.findMany({ limit, ...modifiers });
68
+ if (cache) {
69
+ await BaseCache.setPage(cache, page, modifiers, cacheTTL);
70
+ }
71
+ }
72
+ return page;
73
+ }
74
+ async update(identifier, data, config) {
75
+ const response = await this.model.update(identifier, data);
76
+ if (!response) {
77
+ throw APIError.errNotFound(`No ${this.model.name} found with id ${identifier}`);
78
+ }
79
+ else if (config?.cache) {
80
+ await BaseCache.clearModel(config.cache, response);
81
+ await BaseCache.setModel(config.cache, response, undefined, config.cacheTTL);
82
+ }
83
+ return response;
84
+ }
85
+ async updateMany(data, config) {
86
+ const response = await this.model.updateMany(data);
87
+ if (!response) {
88
+ throw APIError.errResourceUpdateFailed(`Failed to update ${this.model.name}s`);
89
+ }
90
+ else if (config?.cache) {
91
+ const cache = config.cache;
92
+ await Promise.all(response.map(item => BaseCache.clearModel(cache, item)));
93
+ await Promise.all(response.map(item => BaseCache.setModel(cache, item, undefined, config.cacheTTL)));
94
+ }
95
+ return response;
96
+ }
97
+ async delete(identifier, config) {
98
+ const response = await this.model.delete(identifier);
99
+ if (!response) {
100
+ throw APIError.errNotFound(`No ${this.model.name} found with id ${identifier}`);
101
+ }
102
+ else if (config?.cache) {
103
+ await BaseCache.clearModel(config.cache, response);
104
+ await BaseCache.clearPage(config.cache, this.model);
105
+ }
106
+ return response;
107
+ }
108
+ async deleteMany(config) {
109
+ if (!config?.filter)
110
+ throw APIError.errBadRequest("No filter provided");
111
+ const response = await this.model.deleteMany(config);
112
+ if (!response) {
113
+ throw APIError.errResourceDeletionFailed(`Failed to delete ${this.model.name}s`);
114
+ }
115
+ else if (config?.cache) {
116
+ const cache = config.cache;
117
+ await BaseCache.clearPage(config.cache, this.model);
118
+ await Promise.all(response.map(item => BaseCache.clearModel(cache, item)));
119
+ }
120
+ return response;
121
+ }
122
+ }
@@ -0,0 +1,7 @@
1
+ export * from './abstractbase.controller';
2
+ export * from './api-error';
3
+ export * from './base.cache';
4
+ export * from './base.model';
5
+ export * from './base.options';
6
+ export * from './base.service';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,2BAA2B,CAAC;AAC1C,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export * from './abstractbase.controller';
2
+ export * from './api-error';
3
+ export * from './base.cache';
4
+ export * from './base.model';
5
+ export * from './base.options';
6
+ export * from './base.service';
@@ -0,0 +1,3 @@
1
+ import { DBFactory } from "../types";
2
+ export declare const PGFactory: DBFactory;
3
+ //# sourceMappingURL=pg.driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pg.driver.d.ts","sourceRoot":"","sources":["../../src/core/pg.driver.ts"],"names":[],"mappings":"AACA,OAAO,EAAU,SAAS,EAAE,MAAM,UAAU,CAAC;AAgB7C,eAAO,MAAM,SAAS,EAAE,SASvB,CAAC"}
@@ -0,0 +1,21 @@
1
+ async function PGFn(binding, endpoint, query) {
2
+ const response = await binding.fetch(new Request(`http://worker/${endpoint}`, {
3
+ method: 'POST',
4
+ headers: { 'Content-Type': 'application/json' },
5
+ body: JSON.stringify(query)
6
+ }));
7
+ if (!response.ok)
8
+ return null;
9
+ const body = await response.json();
10
+ return body;
11
+ }
12
+ export const PGFactory = (ctx) => {
13
+ return {
14
+ fetch: async (query) => {
15
+ return await PGFn(ctx.env.DB_PROXY, 'query', query);
16
+ },
17
+ raw: async (query) => {
18
+ return await PGFn(ctx.env.DB_PROXY, 'text', { text: query });
19
+ }
20
+ };
21
+ };
@@ -0,0 +1,5 @@
1
+ export * from './index.decorator';
2
+ export * from './prop.decorator';
3
+ export * from './timestamp.decorator';
4
+ export * from './utils';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/decorators/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,SAAS,CAAC"}
@@ -0,0 +1,5 @@
1
+ import BaseModel from '../core/base.model';
2
+ import { IndexDefinition, IndexOptions, TypedClassDecorator } from '../types/decorator.types';
3
+ export declare function index<T extends typeof BaseModel>(fields: IndexDefinition<InstanceType<T>>, options?: IndexOptions): TypedClassDecorator<T>;
4
+ export { index as Index };
5
+ //# sourceMappingURL=index.decorator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.decorator.d.ts","sourceRoot":"","sources":["../../src/decorators/index.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAY9F,wBAAgB,KAAK,CAAC,CAAC,SAAS,OAAO,SAAS,EAAE,MAAM,EAAE,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAI1I;AAED,OAAO,EAAE,KAAK,IAAI,KAAK,EAAE,CAAC"}
@@ -0,0 +1,6 @@
1
+ export function index(fields, options) {
2
+ return (target) => {
3
+ target.schema.indexes.push({ definition: fields, options });
4
+ };
5
+ }
6
+ export { index as Index };
@@ -0,0 +1,4 @@
1
+ export * from './index.decorator';
2
+ export * from './prop.decorator';
3
+ export * from './timestamp.decorator';
4
+ export * from './utils';
@@ -0,0 +1,5 @@
1
+ import BaseModel from '../core/base.model';
2
+ import type { PropOptions } from '../types/decorator.types';
3
+ declare function prop<Target = any, Source extends typeof BaseModel = any, Pivot extends typeof BaseModel = any>(options?: PropOptions<Target, Source, Pivot>): PropertyDecorator;
4
+ export { prop as Prop, prop };
5
+ //# sourceMappingURL=prop.decorator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prop.decorator.d.ts","sourceRoot":"","sources":["../../src/decorators/prop.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,oBAAoB,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAgB5D,iBAAS,IAAI,CAAC,MAAM,GAAG,GAAG,EAAE,MAAM,SAAS,OAAO,SAAS,GAAG,GAAG,EAAE,KAAK,SAAS,OAAO,SAAS,GAAG,GAAG,EAAE,OAAO,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG,iBAAiB,CAaxK;AAED,OAAO,EAAE,IAAI,IAAI,IAAI,EAAE,IAAI,EAAE,CAAC"}
@@ -0,0 +1,13 @@
1
+ function prop(options) {
2
+ return (target, key) => {
3
+ const parent = Object.getPrototypeOf(target.constructor);
4
+ const child = target.constructor;
5
+ if (child.schema === parent.schema) {
6
+ child.schema = parent.schema
7
+ ? { indexes: [...parent.schema.indexes], props: { ...parent.schema.props }, timestamped: parent.schema.timestamped }
8
+ : { indexes: [], props: {} };
9
+ }
10
+ child.schema.props[key] = options || {};
11
+ };
12
+ }
13
+ export { prop as Prop, prop };
@@ -0,0 +1,5 @@
1
+ import { TimeStamped } from '../core/base.model';
2
+ import { TypedClassDecorator } from '../types/decorator.types';
3
+ export declare function timestamp<T extends typeof TimeStamped>(): TypedClassDecorator<T>;
4
+ export { timestamp as Timestamp };
5
+ //# sourceMappingURL=timestamp.decorator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timestamp.decorator.d.ts","sourceRoot":"","sources":["../../src/decorators/timestamp.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAU/D,wBAAgB,SAAS,CAAC,CAAC,SAAS,OAAO,WAAW,KAAK,mBAAmB,CAAC,CAAC,CAAC,CAIhF;AAED,OAAO,EAAE,SAAS,IAAI,SAAS,EAAE,CAAC"}
@@ -0,0 +1,6 @@
1
+ export function timestamp() {
2
+ return (target) => {
3
+ target.schema.timestamped = true;
4
+ };
5
+ }
6
+ export { timestamp as Timestamp };
@@ -0,0 +1,2 @@
1
+ export declare function getName(target: any): any;
2
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/decorators/utils.ts"],"names":[],"mappings":"AAKA,wBAAgB,OAAO,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG,CAExC"}
@@ -0,0 +1,3 @@
1
+ export function getName(target) {
2
+ return target.constructor?.name === 'Function' ? target.name : target.constructor.name;
3
+ }
@@ -0,0 +1,6 @@
1
+ export * from './core';
2
+ export * from './decorators';
3
+ export * from './types';
4
+ export * from './utils';
5
+ export * from './server';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export * from './core';
2
+ export * from './decorators';
3
+ export * from './types';
4
+ export * from './utils';
5
+ export * from './server';
@@ -0,0 +1,13 @@
1
+ /// <reference types="@cloudflare/workers-types" />
2
+ import { Hono } from "hono";
3
+ import type { Env } from "./types/api.types";
4
+ import type { ServerConfig } from "./types/server.types";
5
+ export declare class BackendServer {
6
+ private _app;
7
+ configured: boolean;
8
+ constructor(config?: ServerConfig);
9
+ get app(): Hono<Env, any, any>;
10
+ configure(config: ServerConfig): this;
11
+ start(): (eventContext: import("hono/cloudflare-pages").EventContext<{}, any, {}>) => Response | Promise<Response>;
12
+ }
13
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAezD,qBAAa,aAAa;IACxB,OAAO,CAAC,IAAI,CAAsB;IAC3B,UAAU,EAAE,OAAO,CAAS;gBAEvB,MAAM,CAAC,EAAE,YAAY;IAOjC,IAAW,GAAG,wBAEb;IAEM,SAAS,CAAC,MAAM,EAAE,YAAY;IAsB9B,KAAK;CAGb"}
package/dist/server.js ADDED
@@ -0,0 +1,32 @@
1
+ import { Hono } from "hono";
2
+ import { handle } from "hono/cloudflare-pages";
3
+ import { bindDatabase, defaultCors, defaultErrorHandler } from "./utils";
4
+ import { cors } from "hono/cors";
5
+ export class BackendServer {
6
+ _app;
7
+ configured = false;
8
+ constructor(config) {
9
+ this._app = new Hono();
10
+ if (config)
11
+ this.configure(config);
12
+ }
13
+ get app() {
14
+ return this._app;
15
+ }
16
+ configure(config) {
17
+ if (this.configured)
18
+ throw new Error("Cannot reconfigure server");
19
+ if (config.basePath)
20
+ this._app = this._app.basePath(config.basePath);
21
+ this._app.use(bindDatabase(config.getDB));
22
+ this._app.use(config.cors ? cors(config.cors) : defaultCors);
23
+ this._app.onError(defaultErrorHandler);
24
+ if (config.middleware)
25
+ this._app.use(...config.middleware);
26
+ this.configured = true;
27
+ return this;
28
+ }
29
+ start() {
30
+ return handle(this._app);
31
+ }
32
+ }
@@ -0,0 +1,31 @@
1
+ /// <reference types="@cloudflare/workers-types" />
2
+ import { Handler, Input } from "hono";
3
+ export declare enum Query {
4
+ Expand = "expand"
5
+ }
6
+ export declare enum CachePrefix {
7
+ Record = "rec_",
8
+ Page = "page_"
9
+ }
10
+ export declare const DefaultCacheTTL = 900;
11
+ export declare const MaxCacheTTL = 2147483647;
12
+ export type Bindings = {
13
+ CACHE: KVNamespace;
14
+ STORAGE: KVNamespace;
15
+ DB_PROXY: Fetcher;
16
+ };
17
+ export declare enum BaseEnvKey {
18
+ ownerId = "ownerId",
19
+ isPrivileged = "isPrivileged"
20
+ }
21
+ export type Variables = {
22
+ [BaseEnvKey.ownerId]?: number;
23
+ [BaseEnvKey.isPrivileged]?: boolean;
24
+ };
25
+ export type Env<V extends object = {}, B extends object = {}> = {
26
+ Bindings: Bindings & B;
27
+ Variables: Variables & V;
28
+ };
29
+ export interface BaseHandler<E extends Env = Env, P extends string = any, I extends Input = Input> extends Handler<E, P, I> {
30
+ }
31
+ //# sourceMappingURL=api.types.d.ts.map