@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.
- package/LICENSE +1 -0
- package/README.md +7 -0
- package/app/application.d.ts +43 -0
- package/app/application.js +112 -0
- package/app/create-app.d.ts +32 -0
- package/app/create-app.js +38 -0
- package/app/index.d.ts +2 -0
- package/app/index.js +18 -0
- package/app/lifecycle-manager.d.ts +20 -0
- package/app/lifecycle-manager.js +42 -0
- package/app/load-modules.d.ts +10 -0
- package/app/load-modules.js +50 -0
- package/app/load-providers.d.ts +8 -0
- package/app/load-providers.js +33 -0
- package/cache/cache-service.d.ts +72 -0
- package/cache/cache-service.js +202 -0
- package/cache/cache.d.ts +12 -0
- package/cache/cache.js +184 -0
- package/cache/caching.d.ts +8 -0
- package/cache/caching.js +72 -0
- package/cache/eviction/eviction-index.d.ts +35 -0
- package/cache/eviction/eviction-index.js +2 -0
- package/cache/eviction/fifo-eviction-index.d.ts +7 -0
- package/cache/eviction/fifo-eviction-index.js +28 -0
- package/cache/eviction/index.d.ts +4 -0
- package/cache/eviction/index.js +20 -0
- package/cache/eviction/lfu-eviction-index.d.ts +8 -0
- package/cache/eviction/lfu-eviction-index.js +82 -0
- package/cache/eviction/lru-eviction-index.d.ts +8 -0
- package/cache/eviction/lru-eviction-index.js +81 -0
- package/cache/index.d.ts +2 -0
- package/cache/index.js +18 -0
- package/cache/memory-cache.d.ts +4 -0
- package/cache/memory-cache.js +12 -0
- package/cache/redis-cache.d.ts +4 -0
- package/cache/redis-cache.js +12 -0
- package/context/context.d.ts +2 -0
- package/context/context.js +13 -0
- package/context/dependency-injection.d.ts +98 -0
- package/context/dependency-injection.js +276 -0
- package/context/index.d.ts +2 -0
- package/context/index.js +18 -0
- package/database/create-client.d.ts +11 -0
- package/database/create-client.js +142 -0
- package/database/index.d.ts +1 -0
- package/database/index.js +17 -0
- package/database/prisma-database.d.ts +15 -0
- package/database/prisma-database.js +53 -0
- package/errors/error-handler.d.ts +3 -0
- package/errors/error-handler.js +24 -0
- package/errors/error-schema.d.ts +32 -0
- package/errors/error-schema.js +31 -0
- package/errors/http-error.d.ts +21 -0
- package/errors/http-error.js +33 -0
- package/errors/index.d.ts +3 -0
- package/errors/index.js +19 -0
- package/events/node-events.d.ts +7 -0
- package/events/node-events.js +39 -0
- package/export/export-service.d.ts +19 -0
- package/export/export-service.js +154 -0
- package/export/index.d.ts +1 -0
- package/export/index.js +17 -0
- package/factory/create-model.d.ts +2 -0
- package/factory/create-model.js +366 -0
- package/factory/create-policy.d.ts +2 -0
- package/factory/create-policy.js +16 -0
- package/factory/create-routes.d.ts +2 -0
- package/factory/create-routes.js +21 -0
- package/factory/create-service.d.ts +3 -0
- package/factory/create-service.js +97 -0
- package/factory/index.d.ts +4 -0
- package/factory/index.js +20 -0
- package/health/health-routes.d.ts +2 -0
- package/health/health-routes.js +36 -0
- package/health/health-schema.d.ts +45 -0
- package/health/health-schema.js +52 -0
- package/health/health-service.d.ts +38 -0
- package/health/health-service.js +82 -0
- package/health/index.d.ts +2 -0
- package/health/index.js +18 -0
- package/index.d.ts +15 -0
- package/index.js +31 -0
- package/mailer/email-service.d.ts +36 -0
- package/mailer/email-service.js +89 -0
- package/mailer/index.d.ts +1 -0
- package/mailer/index.js +17 -0
- package/mailer/json-mailer.d.ts +7 -0
- package/mailer/json-mailer.js +32 -0
- package/mailer/smtp-mailer.d.ts +7 -0
- package/mailer/smtp-mailer.js +43 -0
- package/memory/in-memory.d.ts +24 -0
- package/memory/in-memory.js +164 -0
- package/memory/redis.d.ts +26 -0
- package/memory/redis.js +158 -0
- package/package.json +68 -0
- package/prisma/client/browser.d.ts +34 -0
- package/prisma/client/browser.js +56 -0
- package/prisma/client/client.d.ts +53 -0
- package/prisma/client/client.js +70 -0
- package/prisma/client/commonInputTypes.d.ts +395 -0
- package/prisma/client/commonInputTypes.js +11 -0
- package/prisma/client/enums.d.ts +1 -0
- package/prisma/client/enums.js +11 -0
- package/prisma/client/internal/class.d.ts +187 -0
- package/prisma/client/internal/class.js +85 -0
- package/prisma/client/internal/prismaNamespace.d.ts +987 -0
- package/prisma/client/internal/prismaNamespace.js +193 -0
- package/prisma/client/internal/prismaNamespaceBrowser.d.ts +125 -0
- package/prisma/client/internal/prismaNamespaceBrowser.js +164 -0
- package/prisma/client/models/ApiKey.d.ts +1167 -0
- package/prisma/client/models/ApiKey.js +2 -0
- package/prisma/client/models/File.d.ts +1248 -0
- package/prisma/client/models/File.js +2 -0
- package/prisma/client/models/OneTimeToken.d.ts +1083 -0
- package/prisma/client/models/OneTimeToken.js +2 -0
- package/prisma/client/models/Permission.d.ts +1209 -0
- package/prisma/client/models/Permission.js +2 -0
- package/prisma/client/models/Role.d.ts +1209 -0
- package/prisma/client/models/Role.js +2 -0
- package/prisma/client/models/Seeder.d.ts +1023 -0
- package/prisma/client/models/Seeder.js +2 -0
- package/prisma/client/models.d.ts +7 -0
- package/prisma/client/models.js +2 -0
- package/queue/bull-queue.d.ts +37 -0
- package/queue/bull-queue.js +207 -0
- package/queue/memory-queue.d.ts +54 -0
- package/queue/memory-queue.js +283 -0
- package/resource/index.d.ts +4 -0
- package/resource/index.js +20 -0
- package/resource/resource-loader.d.ts +26 -0
- package/resource/resource-loader.js +161 -0
- package/resource/resource-routes.d.ts +3 -0
- package/resource/resource-routes.js +174 -0
- package/resource/resource-schema.d.ts +33 -0
- package/resource/resource-schema.js +186 -0
- package/resource/resource-service.d.ts +89 -0
- package/resource/resource-service.js +772 -0
- package/resources.d.ts +9 -0
- package/resources.js +24 -0
- package/scheduler/cron-scheduler.d.ts +12 -0
- package/scheduler/cron-scheduler.js +73 -0
- package/security/account/account-routes.d.ts +2 -0
- package/security/account/account-routes.js +104 -0
- package/security/account/account-schema.d.ts +290 -0
- package/security/account/account-schema.js +166 -0
- package/security/account/account-service.d.ts +88 -0
- package/security/account/account-service.js +218 -0
- package/security/account/index.d.ts +3 -0
- package/security/account/index.js +19 -0
- package/security/api-key/api-key-auth.d.ts +4 -0
- package/security/api-key/api-key-auth.js +66 -0
- package/security/api-key/index.d.ts +1 -0
- package/security/api-key/index.js +17 -0
- package/security/auth-routes.d.ts +2 -0
- package/security/auth-routes.js +80 -0
- package/security/auth-schema.d.ts +215 -0
- package/security/auth-schema.js +129 -0
- package/security/auth-service.d.ts +117 -0
- package/security/auth-service.js +272 -0
- package/security/auth.d.ts +3 -0
- package/security/auth.js +127 -0
- package/security/basic/basic-auth.d.ts +4 -0
- package/security/basic/basic-auth.js +32 -0
- package/security/basic/index.d.ts +1 -0
- package/security/basic/index.js +17 -0
- package/security/create-auth-resources.d.ts +6 -0
- package/security/create-auth-resources.js +129 -0
- package/security/helper.d.ts +127 -0
- package/security/helper.js +329 -0
- package/security/index.d.ts +4 -0
- package/security/index.js +20 -0
- package/security/jwt/index.d.ts +2 -0
- package/security/jwt/index.js +18 -0
- package/security/jwt/jwt-auth.d.ts +4 -0
- package/security/jwt/jwt-auth.js +57 -0
- package/security/jwt/jwt-keys.d.ts +7 -0
- package/security/jwt/jwt-keys.js +43 -0
- package/security/oauth2/create-oauth2-plugin.d.ts +17 -0
- package/security/oauth2/create-oauth2-plugin.js +85 -0
- package/security/oauth2/index.d.ts +3 -0
- package/security/oauth2/index.js +19 -0
- package/security/oauth2/oauth2-custom.d.ts +7 -0
- package/security/oauth2/oauth2-custom.js +40 -0
- package/security/oauth2/oauth2-facebook.d.ts +1 -0
- package/security/oauth2/oauth2-facebook.js +30 -0
- package/security/oauth2/oauth2-google.d.ts +1 -0
- package/security/oauth2/oauth2-google.js +28 -0
- package/security/oauth2/oauth2-schema.d.ts +10 -0
- package/security/oauth2/oauth2-schema.js +53 -0
- package/security/recaptcha/index.d.ts +2 -0
- package/security/recaptcha/index.js +18 -0
- package/security/recaptcha/recaptcha-verify.d.ts +1 -0
- package/security/recaptcha/recaptcha-verify.js +33 -0
- package/security/recaptcha/recaptcha.d.ts +2 -0
- package/security/recaptcha/recaptcha.js +22 -0
- package/security/resources/api-key/model.d.ts +2 -0
- package/security/resources/api-key/model.js +63 -0
- package/security/resources/api-key/policy.d.ts +2 -0
- package/security/resources/api-key/policy.js +26 -0
- package/security/resources/api-key/routes.d.ts +2 -0
- package/security/resources/api-key/routes.js +15 -0
- package/security/resources/api-key/service.d.ts +3 -0
- package/security/resources/api-key/service.js +33 -0
- package/security/resources/one-time-token/model.d.ts +2 -0
- package/security/resources/one-time-token/model.js +32 -0
- package/security/resources/permission/model.d.ts +2 -0
- package/security/resources/permission/model.js +16 -0
- package/security/resources/role/model.d.ts +2 -0
- package/security/resources/role/model.js +22 -0
- package/security/store/database-security-store.d.ts +5 -0
- package/security/store/database-security-store.js +51 -0
- package/security/store/redis-security-store.d.ts +5 -0
- package/security/store/redis-security-store.js +32 -0
- package/seeder/create-seeder.d.ts +21 -0
- package/seeder/create-seeder.js +17 -0
- package/seeder/index.d.ts +2 -0
- package/seeder/index.js +18 -0
- package/seeder/resources/seeder/model.d.ts +2 -0
- package/seeder/resources/seeder/model.js +38 -0
- package/seeder/seeder.d.ts +20 -0
- package/seeder/seeder.js +175 -0
- package/server/create-server.d.ts +20 -0
- package/server/create-server.js +160 -0
- package/server/index.d.ts +4 -0
- package/server/index.js +20 -0
- package/server/info-route.d.ts +2 -0
- package/server/info-route.js +18 -0
- package/server/info-schema.d.ts +37 -0
- package/server/info-schema.js +19 -0
- package/server/register-model.d.ts +2 -0
- package/server/register-model.js +12 -0
- package/server/register-plugin.d.ts +2 -0
- package/server/register-plugin.js +13 -0
- package/server/register-route.d.ts +3 -0
- package/server/register-route.js +74 -0
- package/server/schemas.d.ts +3 -0
- package/server/schemas.js +30 -0
- package/server/swagger.d.ts +3 -0
- package/server/swagger.js +122 -0
- package/storage/file-route.d.ts +2 -0
- package/storage/file-route.js +39 -0
- package/storage/file-schema.d.ts +9 -0
- package/storage/file-schema.js +42 -0
- package/storage/file-service.d.ts +81 -0
- package/storage/file-service.js +384 -0
- package/storage/filesystem-storage.d.ts +10 -0
- package/storage/filesystem-storage.js +128 -0
- package/storage/index.d.ts +2 -0
- package/storage/index.js +18 -0
- package/storage/resources/file/model.d.ts +2 -0
- package/storage/resources/file/model.js +75 -0
- package/types/application-context.d.ts +20 -0
- package/types/application-context.js +2 -0
- package/types/auth.d.ts +31 -0
- package/types/auth.js +2 -0
- package/types/fastify-extensions.d.ts +24 -0
- package/types/fastify-extensions.js +4 -0
- package/types/generated.d.ts +193 -0
- package/types/generated.js +3 -0
- package/types/index.d.ts +4 -0
- package/types/index.js +20 -0
- package/types/server.d.ts +4 -0
- package/types/server.js +2 -0
- package/utils/export-util.d.ts +8 -0
- package/utils/export-util.js +25 -0
- package/utils/file-util.d.ts +64 -0
- package/utils/file-util.js +141 -0
- package/utils/index.d.ts +3 -0
- package/utils/index.js +19 -0
- package/utils/schema-util.d.ts +20 -0
- package/utils/schema-util.js +37 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loadResources = loadResources;
|
|
4
|
+
const typebox_1 = require("@sinclair/typebox");
|
|
5
|
+
const common_1 = require("@appweaver/common");
|
|
6
|
+
/**
|
|
7
|
+
* Loads application resources including models, services, policies, and routes.
|
|
8
|
+
*
|
|
9
|
+
* @param {string} [baseDir] - Optional base directory path from which to load the resources.
|
|
10
|
+
* If not provided, defaults to the application's root directory.
|
|
11
|
+
* @param {LoadResourcePaths} [paths={}] Path patterns for loading resources: models, services, policies, and routes.
|
|
12
|
+
* @return {Promise<ResourceContext>} A promise that resolves to an object containing
|
|
13
|
+
* the loaded resources:
|
|
14
|
+
*
|
|
15
|
+
* - `models`: The application models.
|
|
16
|
+
* - `services`: The application services.
|
|
17
|
+
* - `policies`: The access policies.
|
|
18
|
+
* - `routes`: The application routes.
|
|
19
|
+
*/
|
|
20
|
+
async function loadResources(baseDir, paths = {}) {
|
|
21
|
+
const models = await loadModels(baseDir, paths.modelPattern);
|
|
22
|
+
const services = await loadServices(baseDir, paths.servicePattern);
|
|
23
|
+
const policies = await loadPolicies(baseDir, paths.policyPattern);
|
|
24
|
+
const routes = await loadRoutes(baseDir, paths.routePattern);
|
|
25
|
+
return {
|
|
26
|
+
models: new Map(Object.entries(models)),
|
|
27
|
+
services: new Map(Object.entries(services)),
|
|
28
|
+
policies: new Map(Object.entries(policies)),
|
|
29
|
+
routes: new Map(Object.entries(routes))
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
async function loadModels(baseDir, modelPattern) {
|
|
33
|
+
const cwd = baseDir ?? process.cwd();
|
|
34
|
+
const pathPattern = modelPattern || common_1.config.RESOURCE_MODEL_PATTERN;
|
|
35
|
+
const models = {};
|
|
36
|
+
const modelPaths = await findAllFiles(pathPattern, cwd);
|
|
37
|
+
for (const path of modelPaths) {
|
|
38
|
+
const modelSchema = await importPath(path);
|
|
39
|
+
if (!modelSchema) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if ((0, common_1.isResourceModel)(modelSchema)) {
|
|
43
|
+
models[modelSchema.name] = modelSchema;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
for (const maybeSchema of Object.values(modelSchema)) {
|
|
47
|
+
if ((0, common_1.isResourceModel)(maybeSchema)) {
|
|
48
|
+
models[maybeSchema.name] = maybeSchema;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Map model variants to schemas using their corresponding suffixes
|
|
54
|
+
const resourceModels = {};
|
|
55
|
+
for (const model of Object.values(models)) {
|
|
56
|
+
for (const [suffix, property] of Object.entries(common_1.resourceModelProps)) {
|
|
57
|
+
resourceModels[`${model.name}${suffix}`] = model[property];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Resolve all model references through the TypeBox module system
|
|
61
|
+
const module = typebox_1.Type.Module(resourceModels);
|
|
62
|
+
// Apply resolved models back to the resource schema definitions
|
|
63
|
+
for (const model of Object.values(models)) {
|
|
64
|
+
for (const [suffix, property] of Object.entries(common_1.resourceModelProps)) {
|
|
65
|
+
const schemaKey = `${model.name}${suffix}`;
|
|
66
|
+
const importedModel = module.Import(schemaKey);
|
|
67
|
+
model[property] = importedModel;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return models;
|
|
71
|
+
}
|
|
72
|
+
async function loadServices(baseDir, servicePattern) {
|
|
73
|
+
const cwd = baseDir ?? process.cwd();
|
|
74
|
+
const pathPattern = servicePattern || common_1.config.RESOURCE_SERVICE_PATTERN;
|
|
75
|
+
const services = {};
|
|
76
|
+
const servicePaths = await findAllFiles(pathPattern, cwd);
|
|
77
|
+
for (const path of servicePaths) {
|
|
78
|
+
const resourceService = await importPath(path);
|
|
79
|
+
if (!resourceService) {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if ((0, common_1.isResourceService)(resourceService)) {
|
|
83
|
+
services[resourceService.modelName] = resourceService;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
for (const maybeService of Object.values(resourceService)) {
|
|
87
|
+
if ((0, common_1.isResourceService)(maybeService)) {
|
|
88
|
+
services[maybeService.modelName] = maybeService;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return services;
|
|
94
|
+
}
|
|
95
|
+
async function loadPolicies(baseDir, policyPattern) {
|
|
96
|
+
const cwd = baseDir ?? process.cwd();
|
|
97
|
+
const pathPattern = policyPattern || common_1.config.RESOURCE_POLICY_PATTERN;
|
|
98
|
+
const policies = {};
|
|
99
|
+
const policyPaths = await findAllFiles(pathPattern, cwd);
|
|
100
|
+
for (const path of policyPaths) {
|
|
101
|
+
const resourcePolicy = await importPath(path);
|
|
102
|
+
if (!resourcePolicy) {
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if ((0, common_1.isResourcePolicy)(resourcePolicy)) {
|
|
106
|
+
policies[resourcePolicy.modelName] = resourcePolicy;
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
for (const maybePolicy of Object.values(resourcePolicy)) {
|
|
110
|
+
if ((0, common_1.isResourcePolicy)(maybePolicy)) {
|
|
111
|
+
policies[maybePolicy.modelName] = maybePolicy;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return policies;
|
|
117
|
+
}
|
|
118
|
+
async function loadRoutes(baseDir, routePattern) {
|
|
119
|
+
const cwd = baseDir ?? process.cwd();
|
|
120
|
+
const pathPattern = routePattern || common_1.config.RESOURCE_ROUTES_PATTERN;
|
|
121
|
+
const routes = {};
|
|
122
|
+
const routePaths = await findAllFiles(pathPattern, cwd);
|
|
123
|
+
for (const path of routePaths) {
|
|
124
|
+
const resourceRoute = await importPath(path);
|
|
125
|
+
if (!resourceRoute) {
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if ((0, common_1.isResourceRoutes)(resourceRoute)) {
|
|
129
|
+
routes[resourceRoute.config.modelName] = resourceRoute;
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
for (const maybeRoute of Object.values(resourceRoute)) {
|
|
133
|
+
if ((0, common_1.isResourceRoutes)(maybeRoute)) {
|
|
134
|
+
routes[maybeRoute.config.modelName] = maybeRoute;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return routes;
|
|
140
|
+
}
|
|
141
|
+
async function findAllFiles(pattern, cwd) {
|
|
142
|
+
const files = [];
|
|
143
|
+
// Find all project files matching provided glob pattern
|
|
144
|
+
const projectFiles = await (0, common_1.findFilesByPattern)(pattern, cwd);
|
|
145
|
+
files.push(...projectFiles);
|
|
146
|
+
// Add exported core module resources
|
|
147
|
+
files.push('@appweaver/core/resources');
|
|
148
|
+
// Add additional modules from config
|
|
149
|
+
for (const module of common_1.config.APP_AUTOLOAD_MODULES) {
|
|
150
|
+
files.push(module);
|
|
151
|
+
}
|
|
152
|
+
return files;
|
|
153
|
+
}
|
|
154
|
+
async function importPath(filePath) {
|
|
155
|
+
const { value, error } = await (0, common_1.importModule)(filePath);
|
|
156
|
+
if (error) {
|
|
157
|
+
common_1.logger.error(error, 'Resource path import error');
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
return value;
|
|
161
|
+
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resourceRoutes = resourceRoutes;
|
|
4
|
+
const resource_schema_1 = require("./resource-schema");
|
|
5
|
+
const context_1 = require("../context");
|
|
6
|
+
const storage_1 = require("../storage");
|
|
7
|
+
const export_1 = require("../export");
|
|
8
|
+
const utils_1 = require("../utils");
|
|
9
|
+
function resourceRoutes(name, routesConfig = {}) {
|
|
10
|
+
const routeConfig = (configName) => {
|
|
11
|
+
return {
|
|
12
|
+
...(routesConfig[configName] ?? {}),
|
|
13
|
+
resourceRouteName: configName,
|
|
14
|
+
cacheModelName: ['find', 'query', 'aggregate'].includes(configName)
|
|
15
|
+
? name
|
|
16
|
+
: undefined
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
const routeNames = [
|
|
20
|
+
'find',
|
|
21
|
+
'query',
|
|
22
|
+
'aggregate',
|
|
23
|
+
'create',
|
|
24
|
+
'update',
|
|
25
|
+
'delete',
|
|
26
|
+
'export',
|
|
27
|
+
'fileUpload',
|
|
28
|
+
'fileDelete'
|
|
29
|
+
];
|
|
30
|
+
const routeAuthTypes = routeNames.reduce((acc, routeName) => {
|
|
31
|
+
const config = routeConfig(routeName);
|
|
32
|
+
if (config?.public || config?.auth?.length === 0) {
|
|
33
|
+
acc[routeName] = [];
|
|
34
|
+
}
|
|
35
|
+
else if (config?.auth && config.auth.length > 0) {
|
|
36
|
+
acc[routeName] = config.auth;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
acc[routeName] = undefined;
|
|
40
|
+
}
|
|
41
|
+
return acc;
|
|
42
|
+
}, {});
|
|
43
|
+
const routeRecaptcha = routeNames.reduce((acc, routeName) => {
|
|
44
|
+
const config = routeConfig(routeName);
|
|
45
|
+
acc[routeName] = {
|
|
46
|
+
recaptcha: config?.recaptcha,
|
|
47
|
+
recaptchaAction: config?.recaptchaAction
|
|
48
|
+
};
|
|
49
|
+
return acc;
|
|
50
|
+
}, {});
|
|
51
|
+
return (server) => {
|
|
52
|
+
const { authenticate, recaptcha } = server;
|
|
53
|
+
const schema = (0, resource_schema_1.createSchema)(name, routeAuthTypes, routeRecaptcha);
|
|
54
|
+
const service = (0, context_1.injectService)(name);
|
|
55
|
+
const resourceModel = (0, context_1.injectModel)(name);
|
|
56
|
+
const routeAuth = (config) => [
|
|
57
|
+
config?.public ? undefined : authenticate(config?.auth),
|
|
58
|
+
config?.recaptcha || config?.recaptchaAction ? recaptcha : undefined
|
|
59
|
+
].filter((v) => v !== undefined);
|
|
60
|
+
const hasFiles = Object.keys(resourceModel.config.files ?? {}).length > 0;
|
|
61
|
+
const findConfig = routeConfig('find');
|
|
62
|
+
if (!findConfig?.exclude) {
|
|
63
|
+
server.get('/:id', {
|
|
64
|
+
schema: schema.findSchema,
|
|
65
|
+
onRequest: routeAuth(findConfig),
|
|
66
|
+
config: findConfig
|
|
67
|
+
}, async (request, reply) => {
|
|
68
|
+
const response = await service.find(request.params.id);
|
|
69
|
+
return reply.send(response);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
const queryConfig = routeConfig('query');
|
|
73
|
+
if (!queryConfig?.exclude) {
|
|
74
|
+
server.post('/query', {
|
|
75
|
+
schema: schema.querySchema,
|
|
76
|
+
onRequest: routeAuth(queryConfig),
|
|
77
|
+
config: queryConfig
|
|
78
|
+
}, async (request, reply) => {
|
|
79
|
+
const { page, size, sort, ...body } = request.body;
|
|
80
|
+
const response = await service.query(body.filter, page, size, sort);
|
|
81
|
+
return reply.send(response);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
const aggregateConfig = routeConfig('aggregate');
|
|
85
|
+
if (!aggregateConfig?.exclude) {
|
|
86
|
+
server.post('/aggregate', {
|
|
87
|
+
schema: schema.aggregateSchema,
|
|
88
|
+
onRequest: routeAuth(aggregateConfig),
|
|
89
|
+
config: aggregateConfig
|
|
90
|
+
}, async (request, reply) => {
|
|
91
|
+
const { dateField, from, to, step, safeIncrement, ...body } = request.body;
|
|
92
|
+
const response = await service.aggregate(body.filter, body.select, dateField, from, to, step, safeIncrement);
|
|
93
|
+
return reply.send(response);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
const createConfig = routeConfig('create');
|
|
97
|
+
if (!createConfig?.exclude) {
|
|
98
|
+
server.post('', {
|
|
99
|
+
schema: schema.createSchema,
|
|
100
|
+
onRequest: routeAuth(createConfig),
|
|
101
|
+
config: createConfig
|
|
102
|
+
}, async (request, reply) => {
|
|
103
|
+
const response = await service.create(request.body);
|
|
104
|
+
return reply.status(201).send(response);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
const updateConfig = routeConfig('update');
|
|
108
|
+
if (!updateConfig?.exclude) {
|
|
109
|
+
server.put('/:id', {
|
|
110
|
+
schema: schema.updateSchema,
|
|
111
|
+
onRequest: routeAuth(updateConfig),
|
|
112
|
+
config: updateConfig
|
|
113
|
+
}, async (request, reply) => {
|
|
114
|
+
const response = await service.update(request.params.id, request.body);
|
|
115
|
+
return reply.send(response);
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
const deleteConfig = routeConfig('delete');
|
|
119
|
+
if (!deleteConfig?.exclude) {
|
|
120
|
+
server.delete('/:id', {
|
|
121
|
+
schema: schema.deleteSchema,
|
|
122
|
+
onRequest: routeAuth(deleteConfig),
|
|
123
|
+
config: deleteConfig
|
|
124
|
+
}, async (request, reply) => {
|
|
125
|
+
const response = await service.delete(request.params.id);
|
|
126
|
+
return reply.send(response);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
const exportConfig = routeConfig('export');
|
|
130
|
+
if (!exportConfig?.exclude) {
|
|
131
|
+
server.post('/export', {
|
|
132
|
+
schema: schema.exportSchema,
|
|
133
|
+
onRequest: routeAuth(exportConfig),
|
|
134
|
+
config: exportConfig
|
|
135
|
+
}, async (request, reply) => {
|
|
136
|
+
const { sort, ...body } = request.body;
|
|
137
|
+
const response = await (0, context_1.inject)(export_1.ExportService).exportCsv(name, body.filter, sort);
|
|
138
|
+
return reply
|
|
139
|
+
.type(response.mimeType)
|
|
140
|
+
.header('Content-Disposition', `attachment; filename="${response.fileName}"`)
|
|
141
|
+
.send(response.stream);
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
const fileUploadConfig = routeConfig('fileUpload');
|
|
145
|
+
if (hasFiles && !fileUploadConfig?.exclude && resourceModel.config.files) {
|
|
146
|
+
const config = resourceModel.config.files;
|
|
147
|
+
const maxSize = (0, utils_1.maxFileSize)(config);
|
|
148
|
+
server.post('/:id/files', {
|
|
149
|
+
schema: schema.fileUploadSchema,
|
|
150
|
+
onRequest: routeAuth(fileUploadConfig),
|
|
151
|
+
config: fileUploadConfig,
|
|
152
|
+
attachValidation: true // Disable validation because of a multipart body.
|
|
153
|
+
}, async (request, reply) => {
|
|
154
|
+
const resource = await service.find(request.params.id);
|
|
155
|
+
const parts = request.parts({ limits: { fileSize: maxSize } });
|
|
156
|
+
const files = await (0, context_1.inject)(storage_1.FileService).saveFiles(parts, resource, service.client);
|
|
157
|
+
return reply.send((0, utils_1.aggregateFiles)(files, config));
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
const fileDeleteConfig = routeConfig('fileDelete');
|
|
161
|
+
if (hasFiles && !fileDeleteConfig?.exclude && resourceModel.config.files) {
|
|
162
|
+
const config = resourceModel.config.files;
|
|
163
|
+
server.post('/:id/delete-files', {
|
|
164
|
+
schema: schema.fileDeleteSchema,
|
|
165
|
+
onRequest: routeAuth(fileDeleteConfig),
|
|
166
|
+
config: fileDeleteConfig
|
|
167
|
+
}, async (request, reply) => {
|
|
168
|
+
const resource = await service.find(request.params.id);
|
|
169
|
+
const files = await (0, context_1.inject)(storage_1.FileService).deleteFiles(request.body, resource, service.client);
|
|
170
|
+
return reply.send((0, utils_1.aggregateFiles)(files, config));
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { AuthType, RecaptchaConfig, ResourceRoutesConfig, ResourceSchemaConfig } from '@appweaver/common';
|
|
2
|
+
export declare const Id: import("@sinclair/typebox").TObject<{
|
|
3
|
+
id: import("@sinclair/typebox").TInteger;
|
|
4
|
+
}>;
|
|
5
|
+
export declare const IdString: import("@sinclair/typebox").TObject<{
|
|
6
|
+
id: import("@sinclair/typebox").TString;
|
|
7
|
+
}>;
|
|
8
|
+
export declare const AuditData: import("@sinclair/typebox").TObject<{
|
|
9
|
+
updatedAt: import("@sinclair/typebox").TUnsafe<Date>;
|
|
10
|
+
createdAt: import("@sinclair/typebox").TUnsafe<Date>;
|
|
11
|
+
createdById: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnsafe<number | null>>;
|
|
12
|
+
}>;
|
|
13
|
+
export declare const QueryRequestData: import("@sinclair/typebox").TObject<{
|
|
14
|
+
filter: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TAny>;
|
|
15
|
+
page: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
16
|
+
size: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
17
|
+
sort: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
18
|
+
}>;
|
|
19
|
+
export declare const QueryResponseData: import("@sinclair/typebox").TObject<{
|
|
20
|
+
resultCount: import("@sinclair/typebox").TNumber;
|
|
21
|
+
totalCount: import("@sinclair/typebox").TNumber;
|
|
22
|
+
}>;
|
|
23
|
+
export declare const AggregateRequestData: import("@sinclair/typebox").TObject<{
|
|
24
|
+
filter: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TAny>;
|
|
25
|
+
select: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TAny>;
|
|
26
|
+
dateField: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
27
|
+
from: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnsafe<Date>>;
|
|
28
|
+
to: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnsafe<Date>>;
|
|
29
|
+
step: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
|
|
30
|
+
safeIncrement: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
31
|
+
}>;
|
|
32
|
+
export declare const AggregateResponseData: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TAny>;
|
|
33
|
+
export declare function createSchema(name: string, routeAuthTypes: Record<keyof ResourceRoutesConfig, AuthType[] | undefined>, routeRecaptcha: Record<keyof ResourceRoutesConfig, RecaptchaConfig>): ResourceSchemaConfig;
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AggregateResponseData = exports.AggregateRequestData = exports.QueryResponseData = exports.QueryRequestData = exports.AuditData = exports.IdString = exports.Id = void 0;
|
|
4
|
+
exports.createSchema = createSchema;
|
|
5
|
+
const typebox_1 = require("@sinclair/typebox");
|
|
6
|
+
const common_1 = require("@appweaver/common");
|
|
7
|
+
const context_1 = require("../context");
|
|
8
|
+
const security_1 = require("../security");
|
|
9
|
+
const errors_1 = require("../errors");
|
|
10
|
+
const utils_1 = require("../utils");
|
|
11
|
+
exports.Id = typebox_1.Type.Object({
|
|
12
|
+
id: typebox_1.Type.Integer({ minimum: 1 })
|
|
13
|
+
});
|
|
14
|
+
exports.IdString = typebox_1.Type.Object({
|
|
15
|
+
id: typebox_1.Type.String({ maxLength: 36 })
|
|
16
|
+
});
|
|
17
|
+
exports.AuditData = typebox_1.Type.Object({
|
|
18
|
+
updatedAt: (0, common_1.StringDate)(),
|
|
19
|
+
createdAt: (0, common_1.StringDate)(),
|
|
20
|
+
createdById: (0, common_1.Nullable)(typebox_1.Type.Integer({ minimum: 1, example: 1 }))
|
|
21
|
+
});
|
|
22
|
+
exports.QueryRequestData = typebox_1.Type.Object({
|
|
23
|
+
filter: typebox_1.Type.Optional((0, common_1.AnyJson)({ example: { field: 'value' } })),
|
|
24
|
+
page: typebox_1.Type.Optional(typebox_1.Type.Number({ minimum: 1, example: 1 })),
|
|
25
|
+
size: typebox_1.Type.Optional(typebox_1.Type.Number({ minimum: 0, maximum: 1000, example: 50 })),
|
|
26
|
+
sort: typebox_1.Type.Optional(typebox_1.Type.String({ example: '-createdAt,id' }))
|
|
27
|
+
});
|
|
28
|
+
exports.QueryResponseData = typebox_1.Type.Object({
|
|
29
|
+
resultCount: typebox_1.Type.Number({ example: 10 }),
|
|
30
|
+
totalCount: typebox_1.Type.Number({ example: 100 })
|
|
31
|
+
});
|
|
32
|
+
exports.AggregateRequestData = typebox_1.Type.Object({
|
|
33
|
+
filter: typebox_1.Type.Optional((0, common_1.AnyJson)({ example: { field: 'value' } })),
|
|
34
|
+
select: typebox_1.Type.Optional((0, common_1.AnyJson)({ example: { field: 'value' } })),
|
|
35
|
+
dateField: typebox_1.Type.Optional(typebox_1.Type.String({ example: 'createdAt' })),
|
|
36
|
+
from: typebox_1.Type.Optional((0, common_1.StringDate)()),
|
|
37
|
+
to: typebox_1.Type.Optional((0, common_1.StringDate)()),
|
|
38
|
+
step: typebox_1.Type.Optional(typebox_1.Type.Integer({ minimum: 1, example: 3600 })),
|
|
39
|
+
safeIncrement: typebox_1.Type.Optional(typebox_1.Type.Boolean({ example: true }))
|
|
40
|
+
});
|
|
41
|
+
exports.AggregateResponseData = typebox_1.Type.Optional((0, common_1.AnyJson)({ example: { field: 'value' } }));
|
|
42
|
+
function createSchema(name, routeAuthTypes, routeRecaptcha) {
|
|
43
|
+
const resourceModel = (0, context_1.injectModel)(name);
|
|
44
|
+
const resourceName = (0, common_1.camelToSnakeCase)(name, ' ');
|
|
45
|
+
const tag = (0, common_1.plural)(name);
|
|
46
|
+
const queryRequest = typebox_1.Type.Composite([exports.QueryRequestData], {
|
|
47
|
+
$id: `${name}QueryRequest`
|
|
48
|
+
});
|
|
49
|
+
const queryResponse = typebox_1.Type.Composite([
|
|
50
|
+
exports.QueryResponseData,
|
|
51
|
+
typebox_1.Type.Object({
|
|
52
|
+
items: typebox_1.Type.Array(resourceModel.readManyModel)
|
|
53
|
+
})
|
|
54
|
+
], { $id: `${name}QueryResponse` });
|
|
55
|
+
const aggregateRequest = typebox_1.Type.Composite([exports.AggregateRequestData], {
|
|
56
|
+
$id: `${name}AggregateRequest`
|
|
57
|
+
});
|
|
58
|
+
const aggregateResponse = typebox_1.Type.Composite([exports.AggregateResponseData], {
|
|
59
|
+
$id: `${name}AggregateResponse`
|
|
60
|
+
});
|
|
61
|
+
const exportRequest = typebox_1.Type.Composite([typebox_1.Type.Pick(exports.QueryRequestData, ['filter', 'sort'])], { $id: `${name}ExportRequest` });
|
|
62
|
+
const resourceSchemaConfig = {
|
|
63
|
+
findSchema: {
|
|
64
|
+
tags: [tag],
|
|
65
|
+
security: (0, security_1.authSchema)(routeAuthTypes['find']),
|
|
66
|
+
headers: (0, security_1.recaptchaHeaderSchema)(routeRecaptcha['find']),
|
|
67
|
+
summary: `Find ${resourceName} data`,
|
|
68
|
+
description: `Find ${resourceName} data`,
|
|
69
|
+
response: {
|
|
70
|
+
200: resourceModel.readOneModel,
|
|
71
|
+
...errors_1.AllErrorResponses
|
|
72
|
+
},
|
|
73
|
+
params: exports.Id
|
|
74
|
+
},
|
|
75
|
+
querySchema: {
|
|
76
|
+
tags: [tag],
|
|
77
|
+
security: (0, security_1.authSchema)(routeAuthTypes['query']),
|
|
78
|
+
headers: (0, security_1.recaptchaHeaderSchema)(routeRecaptcha['query']),
|
|
79
|
+
summary: `Query ${resourceName} data`,
|
|
80
|
+
description: `Query ${resourceName} data`,
|
|
81
|
+
response: {
|
|
82
|
+
200: (0, utils_1.createSchemaModel)(queryResponse),
|
|
83
|
+
...errors_1.AllErrorResponses
|
|
84
|
+
},
|
|
85
|
+
body: (0, utils_1.createSchemaModel)(queryRequest)
|
|
86
|
+
},
|
|
87
|
+
aggregateSchema: {
|
|
88
|
+
tags: [tag],
|
|
89
|
+
security: (0, security_1.authSchema)(routeAuthTypes['aggregate']),
|
|
90
|
+
headers: (0, security_1.recaptchaHeaderSchema)(routeRecaptcha['aggregate']),
|
|
91
|
+
summary: `Aggregate ${resourceName} data`,
|
|
92
|
+
description: `Aggregate ${resourceName} data`,
|
|
93
|
+
response: {
|
|
94
|
+
200: (0, utils_1.createSchemaModel)(aggregateResponse),
|
|
95
|
+
...errors_1.AllErrorResponses
|
|
96
|
+
},
|
|
97
|
+
body: (0, utils_1.createSchemaModel)(aggregateRequest)
|
|
98
|
+
},
|
|
99
|
+
createSchema: {
|
|
100
|
+
tags: [tag],
|
|
101
|
+
security: (0, security_1.authSchema)(routeAuthTypes['create']),
|
|
102
|
+
headers: (0, security_1.recaptchaHeaderSchema)(routeRecaptcha['create']),
|
|
103
|
+
summary: `Create ${resourceName} data`,
|
|
104
|
+
description: `Create ${resourceName} data`,
|
|
105
|
+
response: {
|
|
106
|
+
201: resourceModel.readOneModel,
|
|
107
|
+
...errors_1.AllErrorResponses
|
|
108
|
+
},
|
|
109
|
+
body: resourceModel.createOneModel
|
|
110
|
+
},
|
|
111
|
+
updateSchema: {
|
|
112
|
+
tags: [tag],
|
|
113
|
+
security: (0, security_1.authSchema)(routeAuthTypes['update']),
|
|
114
|
+
headers: (0, security_1.recaptchaHeaderSchema)(routeRecaptcha['update']),
|
|
115
|
+
summary: `Update ${resourceName} data`,
|
|
116
|
+
description: `Update ${resourceName} data`,
|
|
117
|
+
response: {
|
|
118
|
+
200: resourceModel.readOneModel,
|
|
119
|
+
...errors_1.AllErrorResponses
|
|
120
|
+
},
|
|
121
|
+
body: resourceModel.updateOneModel,
|
|
122
|
+
params: exports.Id
|
|
123
|
+
},
|
|
124
|
+
deleteSchema: {
|
|
125
|
+
tags: [tag],
|
|
126
|
+
security: (0, security_1.authSchema)(routeAuthTypes['delete']),
|
|
127
|
+
headers: (0, security_1.recaptchaHeaderSchema)(routeRecaptcha['delete']),
|
|
128
|
+
summary: `Delete ${resourceName} data`,
|
|
129
|
+
description: `Delete ${resourceName} data`,
|
|
130
|
+
response: {
|
|
131
|
+
200: resourceModel.readOneModel,
|
|
132
|
+
...errors_1.AllErrorResponses
|
|
133
|
+
},
|
|
134
|
+
params: exports.Id
|
|
135
|
+
},
|
|
136
|
+
exportSchema: {
|
|
137
|
+
tags: [tag],
|
|
138
|
+
security: (0, security_1.authSchema)(routeAuthTypes['export']),
|
|
139
|
+
headers: (0, security_1.recaptchaHeaderSchema)(routeRecaptcha['export']),
|
|
140
|
+
summary: `Export ${resourceName} data`,
|
|
141
|
+
description: `Export ${resourceName} data`,
|
|
142
|
+
response: {
|
|
143
|
+
200: {
|
|
144
|
+
content: {
|
|
145
|
+
'text/csv': {
|
|
146
|
+
schema: typebox_1.Type.String({ format: 'binary' })
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
...errors_1.AllErrorResponses
|
|
151
|
+
},
|
|
152
|
+
body: (0, utils_1.createSchemaModel)(exportRequest)
|
|
153
|
+
},
|
|
154
|
+
fileUploadSchema: {
|
|
155
|
+
tags: [tag],
|
|
156
|
+
security: (0, security_1.authSchema)(routeAuthTypes['fileUpload']),
|
|
157
|
+
headers: (0, security_1.recaptchaHeaderSchema)(routeRecaptcha['fileUpload']),
|
|
158
|
+
summary: `Upload ${resourceName} files`,
|
|
159
|
+
description: `Upload ${resourceName} files`,
|
|
160
|
+
consumes: ['multipart/form-data'],
|
|
161
|
+
response: {
|
|
162
|
+
200: resourceModel.filesModel,
|
|
163
|
+
...errors_1.AllErrorResponses
|
|
164
|
+
},
|
|
165
|
+
body: resourceModel.fileUploadModel,
|
|
166
|
+
params: exports.Id
|
|
167
|
+
},
|
|
168
|
+
fileDeleteSchema: {
|
|
169
|
+
tags: [tag],
|
|
170
|
+
security: (0, security_1.authSchema)(routeAuthTypes['fileDelete']),
|
|
171
|
+
headers: (0, security_1.recaptchaHeaderSchema)(routeRecaptcha['fileDelete']),
|
|
172
|
+
summary: `Delete ${resourceName} files`,
|
|
173
|
+
description: `Delete ${resourceName} files`,
|
|
174
|
+
response: {
|
|
175
|
+
200: resourceModel.filesModel,
|
|
176
|
+
...errors_1.AllErrorResponses
|
|
177
|
+
},
|
|
178
|
+
body: resourceModel.fileDeleteModel,
|
|
179
|
+
params: exports.Id
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
for (const resourceConfig of Object.values(resourceSchemaConfig)) {
|
|
183
|
+
resourceConfig[`x-${common_1.CONFIG_NAME}-resource`] = name;
|
|
184
|
+
}
|
|
185
|
+
return resourceSchemaConfig;
|
|
186
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { ActionType, AggregateResponse, AggregateSelect, IResourceService, QueryResponse, Resource, ResourceClient, ResourceData } from '@appweaver/common';
|
|
2
|
+
export declare abstract class ResourceService<ReadOne = Resource, ReadMany = Resource, Create = ResourceData<Resource>, Update = Partial<ResourceData<Resource>>, Query = any> implements IResourceService<ReadOne, ReadMany, Create, Update, Query> {
|
|
3
|
+
readonly modelName: string;
|
|
4
|
+
constructor(modelName: string);
|
|
5
|
+
get client(): ResourceClient;
|
|
6
|
+
find(id: number): Promise<ReadOne>;
|
|
7
|
+
query(filter?: Query, page?: number, size?: number, sort?: string): Promise<QueryResponse<ReadMany>>;
|
|
8
|
+
aggregate(filter: Query | undefined, select: AggregateSelect<ReadOne>, dateField?: string, from?: string, to?: string, step?: number, safeIncrement?: boolean): Promise<AggregateResponse<ReadOne>>;
|
|
9
|
+
create(data: Create): Promise<ReadOne>;
|
|
10
|
+
update(id: number, data: Update): Promise<ReadOne>;
|
|
11
|
+
delete(id: number): Promise<ReadOne>;
|
|
12
|
+
/**
|
|
13
|
+
* This method should be overridden with custom logic for restricting read
|
|
14
|
+
* operations on specific data for currently logged-in user and other
|
|
15
|
+
* authorization rules. The returned object will be applied as a filter on
|
|
16
|
+
* all actions (except create action) which will prevent unwanted data access
|
|
17
|
+
* and modifications. This method can also cancel current action by throwing
|
|
18
|
+
* an error, recommended is {@link HttpError } with appropriate HTTP error
|
|
19
|
+
* code.
|
|
20
|
+
*
|
|
21
|
+
* @param action The called action method on this service (find, query,
|
|
22
|
+
* aggregate, update, or delete)
|
|
23
|
+
* @param data The passed data to the called function, can be number or
|
|
24
|
+
* object. If the data is a type of number, then it represents the resource
|
|
25
|
+
* id, otherwise it depends on the action and can be one of the following:
|
|
26
|
+
*
|
|
27
|
+
* - query and aggregate -> filter object
|
|
28
|
+
* - update -> combined id and the data object (i.e. { id, ...data })
|
|
29
|
+
*
|
|
30
|
+
* For other actions (find and delete) it represents the resource id.
|
|
31
|
+
* @return The filter containing additional query restrictions.
|
|
32
|
+
*/
|
|
33
|
+
protected readRestrictions(action: Exclude<ActionType, 'create'>, data: any): Promise<Query>;
|
|
34
|
+
/**
|
|
35
|
+
* This method should be overridden with custom logic for restricting write
|
|
36
|
+
* operations on specific data for currently logged-in users and other
|
|
37
|
+
* authorization rules. The returned object will be applied as a filter on
|
|
38
|
+
* all actions (create and update) to ensure that users can only modify
|
|
39
|
+
* data they are authorized to access. This method can also cancel the
|
|
40
|
+
* current action by throwing an error, with the recommended type being
|
|
41
|
+
* {@link HttpError} with the appropriate HTTP error code.
|
|
42
|
+
*
|
|
43
|
+
* @param action The called action method on this service (create or update)
|
|
44
|
+
* @param data The passed data to the called function, which should be an
|
|
45
|
+
* object representing the resource data to be created or updated. For
|
|
46
|
+
* update operations, this object will also include the resource ID.
|
|
47
|
+
*
|
|
48
|
+
* @return A partial object containing additional data restrictions to be
|
|
49
|
+
* applied, or an empty object if no restrictions are necessary.
|
|
50
|
+
*/
|
|
51
|
+
protected writeRestrictions(action: 'create' | 'update', data: any): Promise<Partial<Create & Update>>;
|
|
52
|
+
/**
|
|
53
|
+
* This method should provide logic for checking the access permissions for
|
|
54
|
+
* the provided resource object. If the resource should not be accessible by
|
|
55
|
+
* a currently authenticated user or other logic, this method should return
|
|
56
|
+
* false. Otherwise, it returns true and continues with the request execution.
|
|
57
|
+
*
|
|
58
|
+
* @param action The called action method on this service (find, query,
|
|
59
|
+
* aggregate, create, update, or delete)
|
|
60
|
+
* @param resource The resource object that is being check for access.
|
|
61
|
+
* @returns True if the access for resource is granted, false otherwise.
|
|
62
|
+
*/
|
|
63
|
+
protected checkAccess(action: ActionType, resource: ReadOne): Promise<boolean>;
|
|
64
|
+
/**
|
|
65
|
+
* Constructs a query object for performing a text search on resources in the
|
|
66
|
+
* database based on the provided search text. This method will transform the
|
|
67
|
+
* search text into a format suitable for text search functionality, returning
|
|
68
|
+
* a query object that can be used to filter results.
|
|
69
|
+
*
|
|
70
|
+
* @param searchText The text string used for searching resources.
|
|
71
|
+
* @returns A query object that represents the conditions for the text
|
|
72
|
+
* search operation. This will be used by the database query methods to
|
|
73
|
+
* retrieve matching resources.
|
|
74
|
+
*/
|
|
75
|
+
protected textSearchQuery(searchText: string): Query;
|
|
76
|
+
private extractTextSearchQuery;
|
|
77
|
+
private mapSortValues;
|
|
78
|
+
private mapAggregationValues;
|
|
79
|
+
private makeAggregationIterator;
|
|
80
|
+
private projectResource;
|
|
81
|
+
private projectVirtualFields;
|
|
82
|
+
private sanitizeData;
|
|
83
|
+
private mapQueryFilter;
|
|
84
|
+
private mapRelationInclusions;
|
|
85
|
+
private buildNestedInclusion;
|
|
86
|
+
private shouldIncludeRelation;
|
|
87
|
+
private mapRelationActions;
|
|
88
|
+
private createdByConnect;
|
|
89
|
+
}
|