@appweaver/core 1.0.0

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 (271) hide show
  1. package/LICENSE +1 -0
  2. package/README.md +7 -0
  3. package/app/application.d.ts +43 -0
  4. package/app/application.js +112 -0
  5. package/app/create-app.d.ts +32 -0
  6. package/app/create-app.js +38 -0
  7. package/app/index.d.ts +2 -0
  8. package/app/index.js +18 -0
  9. package/app/lifecycle-manager.d.ts +20 -0
  10. package/app/lifecycle-manager.js +42 -0
  11. package/app/load-modules.d.ts +10 -0
  12. package/app/load-modules.js +50 -0
  13. package/app/load-providers.d.ts +8 -0
  14. package/app/load-providers.js +33 -0
  15. package/cache/cache-service.d.ts +72 -0
  16. package/cache/cache-service.js +202 -0
  17. package/cache/cache.d.ts +12 -0
  18. package/cache/cache.js +184 -0
  19. package/cache/caching.d.ts +8 -0
  20. package/cache/caching.js +72 -0
  21. package/cache/eviction/eviction-index.d.ts +35 -0
  22. package/cache/eviction/eviction-index.js +2 -0
  23. package/cache/eviction/fifo-eviction-index.d.ts +7 -0
  24. package/cache/eviction/fifo-eviction-index.js +28 -0
  25. package/cache/eviction/index.d.ts +4 -0
  26. package/cache/eviction/index.js +20 -0
  27. package/cache/eviction/lfu-eviction-index.d.ts +8 -0
  28. package/cache/eviction/lfu-eviction-index.js +82 -0
  29. package/cache/eviction/lru-eviction-index.d.ts +8 -0
  30. package/cache/eviction/lru-eviction-index.js +81 -0
  31. package/cache/index.d.ts +2 -0
  32. package/cache/index.js +18 -0
  33. package/cache/memory-cache.d.ts +4 -0
  34. package/cache/memory-cache.js +12 -0
  35. package/cache/redis-cache.d.ts +4 -0
  36. package/cache/redis-cache.js +12 -0
  37. package/context/context.d.ts +2 -0
  38. package/context/context.js +13 -0
  39. package/context/dependency-injection.d.ts +98 -0
  40. package/context/dependency-injection.js +276 -0
  41. package/context/index.d.ts +2 -0
  42. package/context/index.js +18 -0
  43. package/database/create-client.d.ts +11 -0
  44. package/database/create-client.js +142 -0
  45. package/database/index.d.ts +1 -0
  46. package/database/index.js +17 -0
  47. package/database/prisma-database.d.ts +15 -0
  48. package/database/prisma-database.js +53 -0
  49. package/errors/error-handler.d.ts +3 -0
  50. package/errors/error-handler.js +24 -0
  51. package/errors/error-schema.d.ts +32 -0
  52. package/errors/error-schema.js +31 -0
  53. package/errors/http-error.d.ts +21 -0
  54. package/errors/http-error.js +33 -0
  55. package/errors/index.d.ts +3 -0
  56. package/errors/index.js +19 -0
  57. package/events/node-events.d.ts +7 -0
  58. package/events/node-events.js +39 -0
  59. package/export/export-service.d.ts +19 -0
  60. package/export/export-service.js +154 -0
  61. package/export/index.d.ts +1 -0
  62. package/export/index.js +17 -0
  63. package/factory/create-model.d.ts +2 -0
  64. package/factory/create-model.js +366 -0
  65. package/factory/create-policy.d.ts +2 -0
  66. package/factory/create-policy.js +16 -0
  67. package/factory/create-routes.d.ts +2 -0
  68. package/factory/create-routes.js +21 -0
  69. package/factory/create-service.d.ts +3 -0
  70. package/factory/create-service.js +97 -0
  71. package/factory/index.d.ts +4 -0
  72. package/factory/index.js +20 -0
  73. package/health/health-routes.d.ts +2 -0
  74. package/health/health-routes.js +36 -0
  75. package/health/health-schema.d.ts +45 -0
  76. package/health/health-schema.js +52 -0
  77. package/health/health-service.d.ts +38 -0
  78. package/health/health-service.js +82 -0
  79. package/health/index.d.ts +2 -0
  80. package/health/index.js +18 -0
  81. package/index.d.ts +15 -0
  82. package/index.js +31 -0
  83. package/mailer/email-service.d.ts +36 -0
  84. package/mailer/email-service.js +89 -0
  85. package/mailer/index.d.ts +1 -0
  86. package/mailer/index.js +17 -0
  87. package/mailer/json-mailer.d.ts +7 -0
  88. package/mailer/json-mailer.js +32 -0
  89. package/mailer/smtp-mailer.d.ts +7 -0
  90. package/mailer/smtp-mailer.js +43 -0
  91. package/memory/in-memory.d.ts +24 -0
  92. package/memory/in-memory.js +164 -0
  93. package/memory/redis.d.ts +26 -0
  94. package/memory/redis.js +158 -0
  95. package/package.json +68 -0
  96. package/prisma/client/browser.d.ts +34 -0
  97. package/prisma/client/browser.js +56 -0
  98. package/prisma/client/client.d.ts +53 -0
  99. package/prisma/client/client.js +70 -0
  100. package/prisma/client/commonInputTypes.d.ts +395 -0
  101. package/prisma/client/commonInputTypes.js +11 -0
  102. package/prisma/client/enums.d.ts +1 -0
  103. package/prisma/client/enums.js +11 -0
  104. package/prisma/client/internal/class.d.ts +187 -0
  105. package/prisma/client/internal/class.js +85 -0
  106. package/prisma/client/internal/prismaNamespace.d.ts +987 -0
  107. package/prisma/client/internal/prismaNamespace.js +193 -0
  108. package/prisma/client/internal/prismaNamespaceBrowser.d.ts +125 -0
  109. package/prisma/client/internal/prismaNamespaceBrowser.js +164 -0
  110. package/prisma/client/models/ApiKey.d.ts +1167 -0
  111. package/prisma/client/models/ApiKey.js +2 -0
  112. package/prisma/client/models/File.d.ts +1248 -0
  113. package/prisma/client/models/File.js +2 -0
  114. package/prisma/client/models/OneTimeToken.d.ts +1083 -0
  115. package/prisma/client/models/OneTimeToken.js +2 -0
  116. package/prisma/client/models/Permission.d.ts +1209 -0
  117. package/prisma/client/models/Permission.js +2 -0
  118. package/prisma/client/models/Role.d.ts +1209 -0
  119. package/prisma/client/models/Role.js +2 -0
  120. package/prisma/client/models/Seeder.d.ts +1023 -0
  121. package/prisma/client/models/Seeder.js +2 -0
  122. package/prisma/client/models.d.ts +7 -0
  123. package/prisma/client/models.js +2 -0
  124. package/queue/bull-queue.d.ts +37 -0
  125. package/queue/bull-queue.js +207 -0
  126. package/queue/memory-queue.d.ts +54 -0
  127. package/queue/memory-queue.js +283 -0
  128. package/resource/index.d.ts +4 -0
  129. package/resource/index.js +20 -0
  130. package/resource/resource-loader.d.ts +26 -0
  131. package/resource/resource-loader.js +161 -0
  132. package/resource/resource-routes.d.ts +3 -0
  133. package/resource/resource-routes.js +174 -0
  134. package/resource/resource-schema.d.ts +33 -0
  135. package/resource/resource-schema.js +186 -0
  136. package/resource/resource-service.d.ts +89 -0
  137. package/resource/resource-service.js +772 -0
  138. package/resources.d.ts +9 -0
  139. package/resources.js +24 -0
  140. package/scheduler/cron-scheduler.d.ts +12 -0
  141. package/scheduler/cron-scheduler.js +73 -0
  142. package/security/account/account-routes.d.ts +2 -0
  143. package/security/account/account-routes.js +104 -0
  144. package/security/account/account-schema.d.ts +290 -0
  145. package/security/account/account-schema.js +166 -0
  146. package/security/account/account-service.d.ts +88 -0
  147. package/security/account/account-service.js +218 -0
  148. package/security/account/index.d.ts +3 -0
  149. package/security/account/index.js +19 -0
  150. package/security/api-key/api-key-auth.d.ts +4 -0
  151. package/security/api-key/api-key-auth.js +66 -0
  152. package/security/api-key/index.d.ts +1 -0
  153. package/security/api-key/index.js +17 -0
  154. package/security/auth-routes.d.ts +2 -0
  155. package/security/auth-routes.js +80 -0
  156. package/security/auth-schema.d.ts +215 -0
  157. package/security/auth-schema.js +129 -0
  158. package/security/auth-service.d.ts +117 -0
  159. package/security/auth-service.js +272 -0
  160. package/security/auth.d.ts +3 -0
  161. package/security/auth.js +127 -0
  162. package/security/basic/basic-auth.d.ts +4 -0
  163. package/security/basic/basic-auth.js +32 -0
  164. package/security/basic/index.d.ts +1 -0
  165. package/security/basic/index.js +17 -0
  166. package/security/create-auth-resources.d.ts +6 -0
  167. package/security/create-auth-resources.js +129 -0
  168. package/security/helper.d.ts +127 -0
  169. package/security/helper.js +329 -0
  170. package/security/index.d.ts +4 -0
  171. package/security/index.js +20 -0
  172. package/security/jwt/index.d.ts +2 -0
  173. package/security/jwt/index.js +18 -0
  174. package/security/jwt/jwt-auth.d.ts +4 -0
  175. package/security/jwt/jwt-auth.js +57 -0
  176. package/security/jwt/jwt-keys.d.ts +7 -0
  177. package/security/jwt/jwt-keys.js +43 -0
  178. package/security/oauth2/create-oauth2-plugin.d.ts +17 -0
  179. package/security/oauth2/create-oauth2-plugin.js +85 -0
  180. package/security/oauth2/index.d.ts +3 -0
  181. package/security/oauth2/index.js +19 -0
  182. package/security/oauth2/oauth2-custom.d.ts +7 -0
  183. package/security/oauth2/oauth2-custom.js +40 -0
  184. package/security/oauth2/oauth2-facebook.d.ts +1 -0
  185. package/security/oauth2/oauth2-facebook.js +30 -0
  186. package/security/oauth2/oauth2-google.d.ts +1 -0
  187. package/security/oauth2/oauth2-google.js +28 -0
  188. package/security/oauth2/oauth2-schema.d.ts +10 -0
  189. package/security/oauth2/oauth2-schema.js +53 -0
  190. package/security/recaptcha/index.d.ts +2 -0
  191. package/security/recaptcha/index.js +18 -0
  192. package/security/recaptcha/recaptcha-verify.d.ts +1 -0
  193. package/security/recaptcha/recaptcha-verify.js +33 -0
  194. package/security/recaptcha/recaptcha.d.ts +2 -0
  195. package/security/recaptcha/recaptcha.js +22 -0
  196. package/security/resources/api-key/model.d.ts +2 -0
  197. package/security/resources/api-key/model.js +63 -0
  198. package/security/resources/api-key/policy.d.ts +2 -0
  199. package/security/resources/api-key/policy.js +26 -0
  200. package/security/resources/api-key/routes.d.ts +2 -0
  201. package/security/resources/api-key/routes.js +15 -0
  202. package/security/resources/api-key/service.d.ts +3 -0
  203. package/security/resources/api-key/service.js +33 -0
  204. package/security/resources/one-time-token/model.d.ts +2 -0
  205. package/security/resources/one-time-token/model.js +32 -0
  206. package/security/resources/permission/model.d.ts +2 -0
  207. package/security/resources/permission/model.js +16 -0
  208. package/security/resources/role/model.d.ts +2 -0
  209. package/security/resources/role/model.js +22 -0
  210. package/security/store/database-security-store.d.ts +5 -0
  211. package/security/store/database-security-store.js +51 -0
  212. package/security/store/redis-security-store.d.ts +5 -0
  213. package/security/store/redis-security-store.js +32 -0
  214. package/seeder/create-seeder.d.ts +21 -0
  215. package/seeder/create-seeder.js +17 -0
  216. package/seeder/index.d.ts +2 -0
  217. package/seeder/index.js +18 -0
  218. package/seeder/resources/seeder/model.d.ts +2 -0
  219. package/seeder/resources/seeder/model.js +38 -0
  220. package/seeder/seeder.d.ts +20 -0
  221. package/seeder/seeder.js +175 -0
  222. package/server/create-server.d.ts +20 -0
  223. package/server/create-server.js +160 -0
  224. package/server/index.d.ts +4 -0
  225. package/server/index.js +20 -0
  226. package/server/info-route.d.ts +2 -0
  227. package/server/info-route.js +18 -0
  228. package/server/info-schema.d.ts +37 -0
  229. package/server/info-schema.js +19 -0
  230. package/server/register-model.d.ts +2 -0
  231. package/server/register-model.js +12 -0
  232. package/server/register-plugin.d.ts +2 -0
  233. package/server/register-plugin.js +13 -0
  234. package/server/register-route.d.ts +3 -0
  235. package/server/register-route.js +74 -0
  236. package/server/schemas.d.ts +3 -0
  237. package/server/schemas.js +30 -0
  238. package/server/swagger.d.ts +3 -0
  239. package/server/swagger.js +122 -0
  240. package/storage/file-route.d.ts +2 -0
  241. package/storage/file-route.js +39 -0
  242. package/storage/file-schema.d.ts +9 -0
  243. package/storage/file-schema.js +42 -0
  244. package/storage/file-service.d.ts +81 -0
  245. package/storage/file-service.js +384 -0
  246. package/storage/filesystem-storage.d.ts +10 -0
  247. package/storage/filesystem-storage.js +128 -0
  248. package/storage/index.d.ts +2 -0
  249. package/storage/index.js +18 -0
  250. package/storage/resources/file/model.d.ts +2 -0
  251. package/storage/resources/file/model.js +75 -0
  252. package/types/application-context.d.ts +20 -0
  253. package/types/application-context.js +2 -0
  254. package/types/auth.d.ts +31 -0
  255. package/types/auth.js +2 -0
  256. package/types/fastify-extensions.d.ts +24 -0
  257. package/types/fastify-extensions.js +4 -0
  258. package/types/generated.d.ts +193 -0
  259. package/types/generated.js +3 -0
  260. package/types/index.d.ts +4 -0
  261. package/types/index.js +20 -0
  262. package/types/server.d.ts +4 -0
  263. package/types/server.js +2 -0
  264. package/utils/export-util.d.ts +8 -0
  265. package/utils/export-util.js +25 -0
  266. package/utils/file-util.d.ts +64 -0
  267. package/utils/file-util.js +141 -0
  268. package/utils/index.d.ts +3 -0
  269. package/utils/index.js +19 -0
  270. package/utils/schema-util.d.ts +20 -0
  271. package/utils/schema-util.js +37 -0
@@ -0,0 +1,366 @@
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.createModel = createModel;
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ const typebox_1 = require("@sinclair/typebox");
9
+ const common_1 = require("@appweaver/common");
10
+ const context_1 = require("../context");
11
+ const resource_1 = require("../resource");
12
+ function createModel(config, override = false) {
13
+ const name = (0, common_1.capitalize)(config.name || node_path_1.default.basename(node_path_1.default.dirname(__dirname)));
14
+ const idSchema = buildIdSchema(config?.id);
15
+ const auditSchema = buildAuditSchema(config?.audit);
16
+ const scalarsSchema = buildScalarsSchema(config?.scalars);
17
+ const virtualSchema = buildScalarsSchema(config?.virtual);
18
+ const filesSchema = buildFilesSchema(config?.files);
19
+ const relationsSchema = buildRelationsSchema(config?.relations);
20
+ const readModel = typebox_1.Type.Composite([
21
+ idSchema,
22
+ scalarsSchema,
23
+ virtualSchema,
24
+ relationsSchema,
25
+ filesSchema,
26
+ auditSchema
27
+ ], {
28
+ $id: name
29
+ });
30
+ const virtualModel = typebox_1.Type.Composite([virtualSchema], {
31
+ $id: `${name}Virtual`
32
+ });
33
+ const relationsModel = typebox_1.Type.Composite([relationsSchema], {
34
+ $id: `${name}Relations`
35
+ });
36
+ const filesModel = typebox_1.Type.Composite([filesSchema], { $id: `${name}Files` });
37
+ const baseReadModel = omitOrPickScalars(typebox_1.Type.Composite([idSchema, scalarsSchema, virtualSchema, auditSchema]), config.read);
38
+ const createModel = omitOrPickScalars(resolveDefaultScalars(typebox_1.Type.Composite([scalarsSchema, virtualSchema]), config), config.create);
39
+ const updateModel = omitOrPickScalars(resolveDefaultScalars(typebox_1.Type.Partial(typebox_1.Type.Composite([scalarsSchema, virtualSchema])), config), config.update);
40
+ const { readOneModel, readManyModel } = buildOutputModels(baseReadModel, relationsModel, filesModel, config);
41
+ const { createOneModel, updateOneModel } = buildInputModels(createModel, updateModel, relationsModel, config);
42
+ const { fileUploadModel, fileDeleteModel } = buildFileInputModels(config);
43
+ const resourceModel = {
44
+ name,
45
+ config: config,
46
+ readModel,
47
+ createModel,
48
+ updateModel,
49
+ relationsModel,
50
+ filesModel,
51
+ virtualModel,
52
+ readOneModel,
53
+ readManyModel,
54
+ createOneModel,
55
+ updateOneModel,
56
+ fileUploadModel,
57
+ fileDeleteModel
58
+ };
59
+ for (const value of Object.values(resourceModel)) {
60
+ if ((0, common_1.isObject)(value)) {
61
+ value[common_1.RESOURCE_NAME] = name;
62
+ }
63
+ }
64
+ resourceModel[common_1.RESOURCE_NAME] = name;
65
+ resourceModel[common_1.RESOURCE_TYPE] = common_1.RESOURCE_MODEL_TYPE;
66
+ common_1.logger.debug({ modelName: name }, 'Created resource model');
67
+ (0, context_1.define)(resourceModel, undefined, override ? 'override' : undefined);
68
+ return resourceModel;
69
+ }
70
+ function buildIdSchema(idField = { type: 'int' }) {
71
+ let idType;
72
+ switch (idField.type) {
73
+ case 'string':
74
+ idType = resource_1.IdString;
75
+ break;
76
+ case 'int':
77
+ case 'bigInt':
78
+ default:
79
+ idType = resource_1.Id;
80
+ }
81
+ return idType;
82
+ }
83
+ function buildAuditSchema(audit = {}) {
84
+ const defaultAudit = {
85
+ updatedAt: true,
86
+ createdAt: true,
87
+ createdById: true
88
+ };
89
+ const mergedAudit = { ...defaultAudit, ...audit };
90
+ const fields = [];
91
+ for (const [name, included] of Object.entries(mergedAudit)) {
92
+ if (included) {
93
+ fields.push(name);
94
+ }
95
+ }
96
+ return typebox_1.Type.Pick(resource_1.AuditData, fields);
97
+ }
98
+ function buildScalarsSchema(fields = {}) {
99
+ const properties = {};
100
+ for (const [name, field] of Object.entries(fields)) {
101
+ properties[name] = buildScalarSchema(field);
102
+ }
103
+ return typebox_1.Type.Object(properties);
104
+ }
105
+ function buildScalarSchema(field) {
106
+ let fieldType;
107
+ switch (field.type) {
108
+ case 'string':
109
+ fieldType = typebox_1.Type.String((0, common_1.pickProperties)(field, [
110
+ 'minLength',
111
+ 'maxLength',
112
+ 'format',
113
+ 'pattern',
114
+ 'hidden',
115
+ 'example'
116
+ ]));
117
+ break;
118
+ case 'int':
119
+ case 'bigInt':
120
+ fieldType = typebox_1.Type.Integer((0, common_1.pickProperties)(field, ['minimum', 'maximum', 'hidden', 'example']));
121
+ break;
122
+ case 'float':
123
+ fieldType = typebox_1.Type.Number((0, common_1.pickProperties)(field, ['minimum', 'maximum', 'hidden', 'example']));
124
+ break;
125
+ case 'boolean':
126
+ fieldType = typebox_1.Type.Boolean((0, common_1.pickProperties)(field, ['hidden', 'example']));
127
+ break;
128
+ case 'dateTime':
129
+ fieldType = (0, common_1.StringDate)((0, common_1.pickProperties)(field, ['format', 'hidden', 'example']));
130
+ break;
131
+ case 'json':
132
+ fieldType = (0, common_1.AnyJson)((0, common_1.pickProperties)(field, ['hidden', 'example']));
133
+ break;
134
+ case 'enum':
135
+ fieldType = (0, common_1.StringEnum)(field.values ?? [], (0, common_1.pickProperties)(field, ['hidden', 'example']));
136
+ break;
137
+ }
138
+ if (field.array === true) {
139
+ fieldType = typebox_1.Type.Array(fieldType);
140
+ }
141
+ if (field.required === false) {
142
+ fieldType = (0, common_1.Nullable)(fieldType);
143
+ }
144
+ return fieldType;
145
+ }
146
+ function omitOrPickScalars(type, operationConfig) {
147
+ let restrictedType = type;
148
+ if (operationConfig?.pick) {
149
+ restrictedType = typebox_1.Type.Pick(type, operationConfig.pick);
150
+ }
151
+ else if (operationConfig?.omit) {
152
+ restrictedType = typebox_1.Type.Omit(type, operationConfig.omit);
153
+ }
154
+ return typebox_1.Type.Composite([restrictedType]);
155
+ }
156
+ function resolveDefaultScalars(type, config) {
157
+ for (const name of Object.keys(type.properties)) {
158
+ const field = type.properties[name];
159
+ if (config?.scalars?.[name]?.default !== undefined ||
160
+ config?.virtual?.[name]?.default !== undefined) {
161
+ type.properties[name] = typebox_1.Type.Optional(field);
162
+ }
163
+ }
164
+ return type;
165
+ }
166
+ function buildFilesSchema(files = {}) {
167
+ const properties = {};
168
+ for (const [name, file] of Object.entries(files)) {
169
+ properties[name] = buildFileSchema(file);
170
+ }
171
+ return typebox_1.Type.Object(properties);
172
+ }
173
+ function buildFileSchema(file) {
174
+ const fileSchema = typebox_1.Type.Ref('FileSingle');
175
+ return file.array ? typebox_1.Type.Array(fileSchema) : (0, common_1.Nullable)(fileSchema);
176
+ }
177
+ function buildRelationsSchema(relations = {}) {
178
+ const properties = {};
179
+ for (const [name, relation] of Object.entries(relations)) {
180
+ properties[name] = buildRelationSchema(relation);
181
+ }
182
+ return typebox_1.Type.Object(properties);
183
+ }
184
+ function buildRelationSchema(relation) {
185
+ const modelName = (0, common_1.capitalize)(relation.model);
186
+ const modelRefName = `${modelName}Single`;
187
+ let relationType = typebox_1.Type.Ref(modelRefName);
188
+ relationType = relation.array
189
+ ? typebox_1.Type.Array(relationType, (0, common_1.pickProperties)(relation, ['minItems']))
190
+ : relationType;
191
+ return relation.required === false
192
+ ? typebox_1.Type.Optional(relationType)
193
+ : relationType;
194
+ }
195
+ function buildOutputModels(readModel, relationsModel, filesModel, config) {
196
+ const virtualConfig = config.virtual;
197
+ const relationsConfig = config.relations;
198
+ const filesConfig = config.files;
199
+ const adjustedReadModel = removeHiddenFields(readModel);
200
+ const readOneModel = typebox_1.Type.Composite([
201
+ resolveOutputVirtualFields(adjustedReadModel, virtualConfig, 'single'),
202
+ relationOutputProperties(relationsModel, relationsConfig, 'single'),
203
+ relationOutputProperties(filesModel, filesConfig, 'single')
204
+ ], { $id: `${config.name}Single` });
205
+ const readManyModel = typebox_1.Type.Composite([
206
+ resolveOutputVirtualFields(adjustedReadModel, virtualConfig, 'multiple'),
207
+ relationOutputProperties(relationsModel, relationsConfig, 'multiple'),
208
+ relationOutputProperties(filesModel, filesConfig, 'multiple')
209
+ ], { $id: `${config.name}Multiple` });
210
+ return { readOneModel, readManyModel };
211
+ }
212
+ function buildInputModels(createModel, updateModel, relationsModel, config) {
213
+ const virtualConfig = config.virtual;
214
+ const relationsConfig = config.relations;
215
+ const adjustedCreateModel = resolveInputVirtualFields(removeHiddenFields(createModel), virtualConfig, 'create');
216
+ const adjustedUpdateModel = resolveInputVirtualFields(removeHiddenFields(updateModel), virtualConfig, 'update');
217
+ if (Object.keys(relationsConfig ?? {}).length === 0) {
218
+ return {
219
+ createOneModel: adjustedCreateModel,
220
+ updateOneModel: adjustedUpdateModel
221
+ };
222
+ }
223
+ const relationCreateInputs = relationInputProperties(relationsModel, relationsConfig, 'create');
224
+ const createOneModel = typebox_1.Type.Composite([adjustedCreateModel, relationCreateInputs], {
225
+ $id: `${config.name}Create`
226
+ });
227
+ const relationUpdateInputs = relationInputProperties(relationsModel, relationsConfig, 'update');
228
+ const updateOneModel = typebox_1.Type.Composite([adjustedUpdateModel, typebox_1.Type.Partial(relationUpdateInputs)], { $id: `${config.name}Update` });
229
+ return { createOneModel, updateOneModel };
230
+ }
231
+ function buildFileInputModels(config) {
232
+ const fileConfig = config.files ?? {};
233
+ const FileUpload = typebox_1.Type.Unsafe({
234
+ type: 'string',
235
+ format: 'binary',
236
+ [typebox_1.Kind]: 'String'
237
+ });
238
+ const FileDelete = typebox_1.Type.String({ example: 'image_123.png' });
239
+ const fileUploadModel = typebox_1.Type.Object(Object.fromEntries(Object.entries(fileConfig).map(([key, conf]) => [
240
+ key,
241
+ typebox_1.Type.Optional(conf.array ? typebox_1.Type.Array(FileUpload) : FileUpload)
242
+ ])), { $id: `${config.name}FileUpload` });
243
+ const fileDeleteModel = typebox_1.Type.Object(Object.fromEntries(Object.entries(fileConfig).map(([key, conf]) => [
244
+ key,
245
+ typebox_1.Type.Optional(conf.array ? typebox_1.Type.Array(FileDelete) : FileDelete)
246
+ ])), { $id: `${config.name}FileDelete` });
247
+ return { fileUploadModel, fileDeleteModel };
248
+ }
249
+ function relationInputProperties(object, relationConfig, inputType) {
250
+ const relationInputType = (key) => {
251
+ const { type, ...options } = object.properties[key];
252
+ const uniqueIdObject = resource_1.Id;
253
+ const uniqueIdType = resource_1.Id.properties.id;
254
+ let fullInputType = undefined;
255
+ const config = relationConfig?.[key];
256
+ if (config) {
257
+ if (shouldSkipInputField(config.input?.type, inputType)) {
258
+ return undefined;
259
+ }
260
+ if (config.input?.fullModel) {
261
+ fullInputType = typebox_1.Type.Ref(`${config.model}Create`);
262
+ }
263
+ }
264
+ const isArray = type === 'array';
265
+ const isOptional = config?.required === false;
266
+ const idObjectSchema = isArray
267
+ ? typebox_1.Type.Array(uniqueIdObject, options)
268
+ : uniqueIdObject;
269
+ const idTypeSchema = isArray
270
+ ? typebox_1.Type.Array(uniqueIdType, options)
271
+ : uniqueIdType;
272
+ const inputTypeSchemas = [
273
+ isOptional ? (0, common_1.Nullable)(idObjectSchema) : idObjectSchema,
274
+ isOptional ? (0, common_1.Nullable)(idTypeSchema) : idTypeSchema
275
+ ];
276
+ if (fullInputType) {
277
+ const fullInputTypeSchema = isArray
278
+ ? typebox_1.Type.Array(fullInputType, options)
279
+ : fullInputType;
280
+ inputTypeSchemas.push(isOptional ? (0, common_1.Nullable)(fullInputTypeSchema) : fullInputTypeSchema);
281
+ }
282
+ const unionSchema = typebox_1.Type.Union(inputTypeSchemas);
283
+ return isOptional ? typebox_1.Type.Optional(unionSchema) : unionSchema;
284
+ };
285
+ return typebox_1.Type.Object({
286
+ ...Object.keys(object.properties).reduce((acc, key) => {
287
+ const type = relationInputType(key);
288
+ if (type) {
289
+ acc[key] = type;
290
+ }
291
+ return acc;
292
+ }, {})
293
+ });
294
+ }
295
+ function relationOutputProperties(object, relationConfig, outputType) {
296
+ const relationOutputType = (key) => {
297
+ let schema = object.properties[key];
298
+ const config = relationConfig?.[key];
299
+ if (config) {
300
+ if (shouldSkipOutputField(config.output?.type, outputType)) {
301
+ return undefined;
302
+ }
303
+ if (config.required === false && schema.type !== 'array') {
304
+ schema = (0, common_1.Nullable)(schema);
305
+ }
306
+ }
307
+ return schema;
308
+ };
309
+ const relationCountType = (key) => {
310
+ const config = relationConfig?.[key];
311
+ if (!config?.output?.count) {
312
+ return undefined;
313
+ }
314
+ return typebox_1.Type.Integer({ minimum: 0 });
315
+ };
316
+ return typebox_1.Type.Object({
317
+ ...Object.keys(object.properties).reduce((acc, key) => {
318
+ const type = relationOutputType(key);
319
+ if (type) {
320
+ acc[key] = type;
321
+ }
322
+ const countType = relationCountType(key);
323
+ if (countType) {
324
+ acc[(0, common_1.countFieldName)(key)] = countType;
325
+ }
326
+ return acc;
327
+ }, {})
328
+ });
329
+ }
330
+ function removeHiddenFields(schema) {
331
+ const properties = {};
332
+ for (const [name, field] of Object.entries(schema.properties)) {
333
+ if (!field.hidden) {
334
+ properties[name] = field;
335
+ }
336
+ }
337
+ return typebox_1.Type.Object(properties);
338
+ }
339
+ function resolveInputVirtualFields(schema, virtualConfig, inputType) {
340
+ const excludeFields = [];
341
+ for (const [name, virtual] of Object.entries(virtualConfig ?? {})) {
342
+ if (shouldSkipInputField(virtual.input?.type, inputType)) {
343
+ excludeFields.push(name);
344
+ }
345
+ }
346
+ return typebox_1.Type.Omit(schema, excludeFields);
347
+ }
348
+ function resolveOutputVirtualFields(schema, virtualConfig, outputType) {
349
+ const excludeFields = [];
350
+ for (const [name, virtual] of Object.entries(virtualConfig ?? {})) {
351
+ if (shouldSkipOutputField(virtual.output?.type, outputType)) {
352
+ excludeFields.push(name);
353
+ }
354
+ }
355
+ return typebox_1.Type.Omit(schema, excludeFields);
356
+ }
357
+ function shouldSkipInputField(fieldInputType, methodInputType) {
358
+ return (fieldInputType === 'none' ||
359
+ (methodInputType === 'create' && fieldInputType === 'update') ||
360
+ (methodInputType === 'update' && fieldInputType === 'create'));
361
+ }
362
+ function shouldSkipOutputField(fieldOutputType, methodOutputType) {
363
+ return (fieldOutputType === 'none' ||
364
+ (methodOutputType === 'single' && fieldOutputType === 'multiple') ||
365
+ (methodOutputType === 'multiple' && fieldOutputType === 'single'));
366
+ }
@@ -0,0 +1,2 @@
1
+ import { ResourcePolicyConfig } from '@appweaver/common';
2
+ export declare function createPolicy<T = any>(config: ResourcePolicyConfig<T>, override?: boolean): ResourcePolicyConfig<T>;
@@ -0,0 +1,16 @@
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.createPolicy = createPolicy;
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ const common_1 = require("@appweaver/common");
9
+ const context_1 = require("../context");
10
+ function createPolicy(config, override = false) {
11
+ config[common_1.RESOURCE_NAME] = (0, common_1.capitalize)(config.modelName || node_path_1.default.basename(node_path_1.default.dirname(__dirname)));
12
+ config[common_1.RESOURCE_TYPE] = common_1.RESOURCE_POLICY_TYPE;
13
+ common_1.logger.debug({ modelName: config.modelName }, 'Created resource policy');
14
+ (0, context_1.define)(config, undefined, override ? 'override' : undefined);
15
+ return config;
16
+ }
@@ -0,0 +1,2 @@
1
+ import { ResourceRoutes, ResourceRoutesConfig } from '@appweaver/common';
2
+ export declare function createRoutes(config: ResourceRoutesConfig, override?: boolean): ResourceRoutes;
@@ -0,0 +1,21 @@
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.createRoutes = createRoutes;
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ const common_1 = require("@appweaver/common");
9
+ const context_1 = require("../context");
10
+ const resource_1 = require("../resource");
11
+ function createRoutes(config, override = false) {
12
+ const name = (0, common_1.capitalize)(config.modelName || node_path_1.default.basename(node_path_1.default.dirname(__dirname)));
13
+ const basePath = config.path || (0, common_1.camelToSnakeCase)((0, common_1.plural)(name), '-').toLowerCase();
14
+ const handler = (0, resource_1.resourceRoutes)(name, config);
15
+ const routeData = { config, basePath, handler };
16
+ routeData[common_1.RESOURCE_NAME] = name;
17
+ routeData[common_1.RESOURCE_TYPE] = common_1.RESOURCE_ROUTES_TYPE;
18
+ common_1.logger.debug({ modelName: config.modelName }, 'Created resource routes');
19
+ (0, context_1.define)(routeData, undefined, override ? 'override' : undefined);
20
+ return routeData;
21
+ }
@@ -0,0 +1,3 @@
1
+ import { Ctor, ResourceServiceConfig } from '@appweaver/common';
2
+ import { ResourceService } from '../resource';
3
+ export declare function createService<T = any, C = any, U = any>(config: ResourceServiceConfig<T, C, U>, override?: boolean): Ctor<ResourceService<T, T, C, U>>;
@@ -0,0 +1,97 @@
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.createService = createService;
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ const common_1 = require("@appweaver/common");
9
+ const context_1 = require("../context");
10
+ const resource_1 = require("../resource");
11
+ function createService(config, override = false) {
12
+ const name = (0, common_1.capitalize)(config.modelName || node_path_1.default.basename(node_path_1.default.dirname(__dirname)));
13
+ class Service extends resource_1.ResourceService {
14
+ [common_1.CONFIG] = config;
15
+ [common_1.RESOURCE_NAME] = name;
16
+ [common_1.RESOURCE_TYPE] = common_1.RESOURCE_SERVICE_TYPE;
17
+ constructor() {
18
+ super(name);
19
+ }
20
+ async find(id) {
21
+ await config.beforeFind?.(id);
22
+ const result = await super.find(id);
23
+ await config.afterFind?.(result);
24
+ return result;
25
+ }
26
+ async query(filter = {}, page = 1, size = 50, sort = '-createdAt,id') {
27
+ await config.beforeQuery?.(filter, page, size, sort);
28
+ const result = await super.query(filter, page, size, sort);
29
+ await config.afterQuery?.(result);
30
+ return result;
31
+ }
32
+ async aggregate(filter = {}, select, dateField = 'createdAt', from, to, step, safeIncrement = true) {
33
+ await config.beforeAggregate?.(filter, select, dateField, from, to, step, safeIncrement);
34
+ const result = await super.aggregate(filter, select, dateField, from, to, step, safeIncrement);
35
+ await config.afterAggregate?.(result);
36
+ return result;
37
+ }
38
+ async create(data) {
39
+ await config.beforeCreate?.(data);
40
+ const result = await super.create(data);
41
+ await config.afterCreate?.(result);
42
+ return result;
43
+ }
44
+ async update(id, data) {
45
+ await config.beforeUpdate?.(id, data);
46
+ const result = await super.update(id, data);
47
+ await config.afterUpdate?.(result);
48
+ return result;
49
+ }
50
+ async delete(id) {
51
+ await config.beforeDelete?.(id);
52
+ const result = await super.delete(id);
53
+ await config.afterDelete?.(result);
54
+ return result;
55
+ }
56
+ textSearchQuery(searchText) {
57
+ if ((0, common_1.isFunction)(config.textSearch)) {
58
+ return config.textSearch(searchText);
59
+ }
60
+ if ((0, common_1.isObject)(config.textSearch)) {
61
+ return config.textSearch;
62
+ }
63
+ return super.textSearchQuery(searchText);
64
+ }
65
+ async readRestrictions(action, data) {
66
+ const policy = (0, context_1.injectPolicy)(name);
67
+ if (policy.readRestrictions) {
68
+ return policy.readRestrictions(action, data) ?? {};
69
+ }
70
+ return super.readRestrictions(action, data);
71
+ }
72
+ async writeRestrictions(action, data) {
73
+ const policy = (0, context_1.injectPolicy)(name);
74
+ if (policy.writeRestrictions) {
75
+ return policy.writeRestrictions(action, data) ?? {};
76
+ }
77
+ return super.writeRestrictions(action, data);
78
+ }
79
+ async checkAccess(action, resource) {
80
+ const policy = (0, context_1.injectPolicy)(name);
81
+ if (policy?.checkAccess) {
82
+ return policy.checkAccess(action, resource);
83
+ }
84
+ return super.checkAccess(action, resource);
85
+ }
86
+ }
87
+ Object.defineProperty(Service, 'name', {
88
+ value: `${name}Service`,
89
+ configurable: true
90
+ });
91
+ Service[common_1.CONFIG] = config;
92
+ Service[common_1.RESOURCE_NAME] = name;
93
+ Service[common_1.RESOURCE_TYPE] = common_1.RESOURCE_SERVICE_TYPE;
94
+ common_1.logger.debug({ modelName: config.modelName }, 'Created resource service');
95
+ (0, context_1.define)(Service, undefined, override ? 'override' : undefined);
96
+ return Service;
97
+ }
@@ -0,0 +1,4 @@
1
+ export * from './create-model';
2
+ export * from './create-policy';
3
+ export * from './create-routes';
4
+ export * from './create-service';
@@ -0,0 +1,20 @@
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("./create-model"), exports);
18
+ __exportStar(require("./create-policy"), exports);
19
+ __exportStar(require("./create-routes"), exports);
20
+ __exportStar(require("./create-service"), exports);
@@ -0,0 +1,2 @@
1
+ import { Server } from '../types';
2
+ export declare function health(server: Server): void;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.health = health;
4
+ const common_1 = require("@appweaver/common");
5
+ const health_schema_1 = require("./health-schema");
6
+ const health_service_1 = require("./health-service");
7
+ const context_1 = require("../context");
8
+ function health(server) {
9
+ const { authenticate } = server;
10
+ const healthService = (0, context_1.inject)(health_service_1.HealthService);
11
+ const healthCheckSchema = (0, health_schema_1.createHealthCheckSchema)(healthService.healthCheckInstances().map((s) => s.name));
12
+ server.get('/check', {
13
+ schema: healthCheckSchema,
14
+ onRequest: common_1.config.HEALTH_CHECK_AUTH ? authenticate() : undefined,
15
+ config: {
16
+ cacheTTL: common_1.config.HEALTH_CHECK_CACHE_TTL,
17
+ rateLimit: {
18
+ max: 12
19
+ }
20
+ }
21
+ }, async (_, reply) => {
22
+ const healthCheck = await healthService.checkHealth();
23
+ const allUp = Object.values(healthCheck).every((check) => check.status === common_1.HealthCheckStatus.Up);
24
+ return reply.status(allUp ? 200 : 503).send({
25
+ status: allUp ? common_1.HealthCheckStatus.Up : common_1.HealthCheckStatus.Down,
26
+ timestamp: new Date(),
27
+ checks: healthCheck
28
+ });
29
+ });
30
+ server.get('/ready', {
31
+ schema: health_schema_1.healthReadySchema
32
+ }, async (_, reply) => {
33
+ const ready = await healthService.checkReadiness();
34
+ return reply.send({ ready });
35
+ });
36
+ }
@@ -0,0 +1,45 @@
1
+ import { HealthCheckStatus, RouteSchema } from '@appweaver/common';
2
+ export declare const HealthCheckResult: import("@sinclair/typebox").TObject<{
3
+ status: import("@sinclair/typebox").TUnsafe<HealthCheckStatus>;
4
+ message: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
5
+ }>;
6
+ export declare const HealthCheckCommonData: import("@sinclair/typebox").TObject<{
7
+ status: import("@sinclair/typebox").TUnsafe<HealthCheckStatus>;
8
+ timestamp: import("@sinclair/typebox").TUnsafe<Date>;
9
+ }>;
10
+ export declare const ReadyResponse: import("@sinclair/typebox").TObject<{
11
+ ready: import("@sinclair/typebox").TBoolean;
12
+ }>;
13
+ export declare const healthReadySchema: {
14
+ tags: string[];
15
+ summary: string;
16
+ description: string;
17
+ response: {
18
+ '4xx': {
19
+ description: string;
20
+ content: {
21
+ 'application/json': {
22
+ schema: import("@sinclair/typebox").TObject<{
23
+ errorCode: import("@sinclair/typebox").TInteger;
24
+ message: import("@sinclair/typebox").TString;
25
+ }>;
26
+ };
27
+ };
28
+ };
29
+ '5xx': {
30
+ description: string;
31
+ content: {
32
+ 'application/json': {
33
+ schema: import("@sinclair/typebox").TObject<{
34
+ errorCode: import("@sinclair/typebox").TInteger;
35
+ message: import("@sinclair/typebox").TString;
36
+ }>;
37
+ };
38
+ };
39
+ };
40
+ 200: import("@sinclair/typebox").TObject<{
41
+ ready: import("@sinclair/typebox").TBoolean;
42
+ }>;
43
+ };
44
+ };
45
+ export declare function createHealthCheckSchema(serviceNames: string[]): RouteSchema;