@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,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InMemory = void 0;
|
|
4
|
+
const promises_1 = require("node:timers/promises");
|
|
5
|
+
const flatted_1 = require("flatted");
|
|
6
|
+
const common_1 = require("@appweaver/common");
|
|
7
|
+
class InMemory extends common_1.Memory {
|
|
8
|
+
/** @internal */
|
|
9
|
+
_storage = new Map();
|
|
10
|
+
/** @internal */
|
|
11
|
+
_locks = new Map();
|
|
12
|
+
/** @internal */
|
|
13
|
+
_maxSizeBytes = (0, common_1.textToBytes)(common_1.config.MEMORY_MAX_SIZE);
|
|
14
|
+
/** @internal */
|
|
15
|
+
_approximatedSize = 0;
|
|
16
|
+
async onInit() {
|
|
17
|
+
await this.connect();
|
|
18
|
+
}
|
|
19
|
+
async onDestroy() {
|
|
20
|
+
await this.disconnect();
|
|
21
|
+
}
|
|
22
|
+
async connect() {
|
|
23
|
+
// no-op
|
|
24
|
+
}
|
|
25
|
+
async disconnect() {
|
|
26
|
+
// no-op
|
|
27
|
+
}
|
|
28
|
+
createClient() {
|
|
29
|
+
// no-op
|
|
30
|
+
}
|
|
31
|
+
async getValue(key) {
|
|
32
|
+
const entry = this._storage.get(key);
|
|
33
|
+
if (!entry) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
// Check if expired
|
|
37
|
+
if (entry.expiresAt && entry.expiresAt < Date.now()) {
|
|
38
|
+
await this.cleanupExpired();
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
return (0, flatted_1.parse)(entry.value);
|
|
42
|
+
}
|
|
43
|
+
async putValue(key, value, expireMs) {
|
|
44
|
+
await this.cleanupExpired();
|
|
45
|
+
const jsonValue = (0, flatted_1.stringify)(value);
|
|
46
|
+
const expiresAt = expireMs ? Date.now() + expireMs : undefined;
|
|
47
|
+
this._storage.set(key, {
|
|
48
|
+
value: jsonValue,
|
|
49
|
+
expiresAt
|
|
50
|
+
});
|
|
51
|
+
this._approximatedSize += Buffer.byteLength(jsonValue, 'utf8');
|
|
52
|
+
// If memory max size is reached, remove entries from start until the size
|
|
53
|
+
// is below the configured value
|
|
54
|
+
if (this._maxSizeBytes) {
|
|
55
|
+
while (this._approximatedSize > this._maxSizeBytes) {
|
|
56
|
+
await this.removeValue(this._storage.keys()[0]);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
async hasKey(key) {
|
|
62
|
+
return this._storage.has(key);
|
|
63
|
+
}
|
|
64
|
+
async removeValue(key) {
|
|
65
|
+
const jsonValue = await this.getValue(key);
|
|
66
|
+
if (!jsonValue) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
const deleted = this._storage.delete(key);
|
|
70
|
+
this._approximatedSize -= Buffer.byteLength(jsonValue, 'utf8');
|
|
71
|
+
if (this._approximatedSize < 0) {
|
|
72
|
+
this._approximatedSize = 0;
|
|
73
|
+
}
|
|
74
|
+
return deleted;
|
|
75
|
+
}
|
|
76
|
+
async removeEntries(query) {
|
|
77
|
+
const keys = await this.findKeys(query);
|
|
78
|
+
const removeActions = Array.from(keys).map((key) => this.removeValue(key));
|
|
79
|
+
const results = await Promise.allSettled(removeActions);
|
|
80
|
+
return results.filter((r) => r.status === 'fulfilled' && r.value).length;
|
|
81
|
+
}
|
|
82
|
+
async findKeys(pattern = '*') {
|
|
83
|
+
const matchingKeys = new Set();
|
|
84
|
+
// Convert glob pattern to regex
|
|
85
|
+
const regexPattern = pattern
|
|
86
|
+
.replace(/[.+^${}()|[\]\\]/g, '\\$&')
|
|
87
|
+
.replace(/\*/g, '.*')
|
|
88
|
+
.replace(/\?/g, '.');
|
|
89
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
90
|
+
for (const key of this._storage.keys()) {
|
|
91
|
+
const entry = this._storage.get(key);
|
|
92
|
+
if (entry && entry.expiresAt && entry.expiresAt < Date.now()) {
|
|
93
|
+
this._storage.delete(key);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (regex.test(key)) {
|
|
97
|
+
matchingKeys.add(key);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return matchingKeys;
|
|
101
|
+
}
|
|
102
|
+
async valueSizeBytes(key) {
|
|
103
|
+
const entry = this._storage.get(key);
|
|
104
|
+
return entry ? Buffer.byteLength(entry.value, 'utf8') : null;
|
|
105
|
+
}
|
|
106
|
+
async lock(resource, lockConfig = {}) {
|
|
107
|
+
const expireMs = lockConfig.expireMs ?? 5000;
|
|
108
|
+
const retryCount = lockConfig.retryCount ?? 10;
|
|
109
|
+
const retryDelay = lockConfig.retryDelay ?? 200;
|
|
110
|
+
const resourceKey = `lock:${resource}`;
|
|
111
|
+
const lockValue = (0, common_1.uuid)();
|
|
112
|
+
let retries = 0;
|
|
113
|
+
do {
|
|
114
|
+
// Try to acquire lock (NX semantics - only set if not exists)
|
|
115
|
+
const existingLock = this._locks.get(resourceKey);
|
|
116
|
+
// Check if the existing lock is expired
|
|
117
|
+
if (existingLock && existingLock.expiresAt < Date.now()) {
|
|
118
|
+
this._locks.delete(resourceKey);
|
|
119
|
+
}
|
|
120
|
+
// Try to acquire
|
|
121
|
+
if (!this._locks.has(resourceKey)) {
|
|
122
|
+
this._locks.set(resourceKey, {
|
|
123
|
+
value: lockValue,
|
|
124
|
+
expiresAt: Date.now() + expireMs
|
|
125
|
+
});
|
|
126
|
+
return {
|
|
127
|
+
release: async () => {
|
|
128
|
+
// Only release if the lock value matches
|
|
129
|
+
const currentLock = this._locks.get(resourceKey);
|
|
130
|
+
if (currentLock && currentLock.value === lockValue) {
|
|
131
|
+
this._locks.delete(resourceKey);
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
await (0, promises_1.setTimeout)(retryDelay);
|
|
139
|
+
retries++;
|
|
140
|
+
} while (retries < retryCount);
|
|
141
|
+
throw new Error('Unable to acquire lock on requested resource');
|
|
142
|
+
}
|
|
143
|
+
async checkHealth() {
|
|
144
|
+
return { success: true };
|
|
145
|
+
}
|
|
146
|
+
async cleanupExpired() {
|
|
147
|
+
const now = Date.now();
|
|
148
|
+
// Clean up expired storage entries
|
|
149
|
+
for (const key in this._storage.keys()) {
|
|
150
|
+
const entry = this._storage.get(key);
|
|
151
|
+
if (entry && entry.expiresAt && entry.expiresAt < now) {
|
|
152
|
+
await this.removeValue(key);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// Clean up expired locks
|
|
156
|
+
for (const key in this._locks.keys()) {
|
|
157
|
+
const lock = this._locks.get(key);
|
|
158
|
+
if (lock && lock.expiresAt < now) {
|
|
159
|
+
this._locks.delete(key);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
exports.InMemory = InMemory;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Redis as RedisClient, RedisOptions } from 'ioredis';
|
|
2
|
+
import { HealthCheckResult, Redis as CommonRedis } from '@appweaver/common';
|
|
3
|
+
export declare class Redis extends CommonRedis<RedisOptions, RedisClient> {
|
|
4
|
+
constructor();
|
|
5
|
+
onInit(): Promise<void>;
|
|
6
|
+
onDestroy(): Promise<void>;
|
|
7
|
+
createClient(options?: RedisOptions): RedisClient;
|
|
8
|
+
connect(): Promise<void>;
|
|
9
|
+
disconnect(): Promise<void>;
|
|
10
|
+
getValue<T = any>(key: string): Promise<T | null>;
|
|
11
|
+
putValue(key: string, value: any, expireMs?: number): Promise<boolean>;
|
|
12
|
+
hasKey(key: string): Promise<boolean>;
|
|
13
|
+
removeValue(key: string): Promise<boolean>;
|
|
14
|
+
removeEntries(query: string): Promise<number>;
|
|
15
|
+
findKeys(pattern?: string): Promise<Set<string>>;
|
|
16
|
+
valueSizeBytes(key: string): Promise<number | null>;
|
|
17
|
+
lock(resource: string, lockConfig?: {
|
|
18
|
+
expireMs?: number;
|
|
19
|
+
retryCount?: number;
|
|
20
|
+
retryDelay?: number;
|
|
21
|
+
}): Promise<{
|
|
22
|
+
release: () => Promise<boolean>;
|
|
23
|
+
}>;
|
|
24
|
+
checkHealth(): Promise<HealthCheckResult>;
|
|
25
|
+
private parseConnectionUrl;
|
|
26
|
+
}
|
package/memory/redis.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Redis = void 0;
|
|
4
|
+
const promises_1 = require("node:timers/promises");
|
|
5
|
+
const ioredis_1 = require("ioredis");
|
|
6
|
+
const flatted_1 = require("flatted");
|
|
7
|
+
const common_1 = require("@appweaver/common");
|
|
8
|
+
class Redis extends common_1.Redis {
|
|
9
|
+
/** @internal */
|
|
10
|
+
_options;
|
|
11
|
+
/** @internal */
|
|
12
|
+
_client;
|
|
13
|
+
constructor() {
|
|
14
|
+
super();
|
|
15
|
+
this._options = this.parseConnectionUrl(common_1.config.REDIS_URL);
|
|
16
|
+
this._client = this.createClient({ lazyConnect: true });
|
|
17
|
+
}
|
|
18
|
+
async onInit() {
|
|
19
|
+
await this.connect();
|
|
20
|
+
}
|
|
21
|
+
async onDestroy() {
|
|
22
|
+
await this.disconnect();
|
|
23
|
+
}
|
|
24
|
+
createClient(options = {}) {
|
|
25
|
+
return new ioredis_1.Redis({
|
|
26
|
+
...this._options,
|
|
27
|
+
...options
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
async connect() {
|
|
31
|
+
await this._client.connect();
|
|
32
|
+
}
|
|
33
|
+
async disconnect() {
|
|
34
|
+
try {
|
|
35
|
+
await this._client.quit();
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// Ignore already closed connection error
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async getValue(key) {
|
|
42
|
+
const value = await this._client.get(key);
|
|
43
|
+
return value ? (0, flatted_1.parse)(value) : null;
|
|
44
|
+
}
|
|
45
|
+
async putValue(key, value, expireMs) {
|
|
46
|
+
const jsonValue = (0, flatted_1.stringify)(value);
|
|
47
|
+
const result = expireMs
|
|
48
|
+
? await this._client.set(key, jsonValue, 'PX', expireMs)
|
|
49
|
+
: await this._client.set(key, jsonValue);
|
|
50
|
+
return result === 'OK';
|
|
51
|
+
}
|
|
52
|
+
async hasKey(key) {
|
|
53
|
+
const result = await this._client.exists(key);
|
|
54
|
+
return result === 1;
|
|
55
|
+
}
|
|
56
|
+
async removeValue(key) {
|
|
57
|
+
const result = await this._client.del(key);
|
|
58
|
+
return result > 0;
|
|
59
|
+
}
|
|
60
|
+
async removeEntries(query) {
|
|
61
|
+
const keys = await this.findKeys(query);
|
|
62
|
+
if (keys.size === 0) {
|
|
63
|
+
return 0;
|
|
64
|
+
}
|
|
65
|
+
return this._client.del(...keys);
|
|
66
|
+
}
|
|
67
|
+
async findKeys(pattern = '*') {
|
|
68
|
+
return new Promise((resolve) => {
|
|
69
|
+
const stream = this._client.scanStream({
|
|
70
|
+
match: pattern,
|
|
71
|
+
count: 10000
|
|
72
|
+
});
|
|
73
|
+
const keysSet = new Set();
|
|
74
|
+
stream.on('data', (keys) => {
|
|
75
|
+
stream.pause();
|
|
76
|
+
keys.forEach((key) => keysSet.add(key));
|
|
77
|
+
stream.resume();
|
|
78
|
+
});
|
|
79
|
+
stream.on('end', () => {
|
|
80
|
+
resolve(keysSet);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
async valueSizeBytes(key) {
|
|
85
|
+
return this._client.memory('USAGE', key);
|
|
86
|
+
}
|
|
87
|
+
async lock(resource, lockConfig = {}) {
|
|
88
|
+
const redisLock = new RedisLock(this._client, resource, lockConfig.expireMs, lockConfig.retryCount, lockConfig.retryDelay);
|
|
89
|
+
return await redisLock.lock();
|
|
90
|
+
}
|
|
91
|
+
async checkHealth() {
|
|
92
|
+
try {
|
|
93
|
+
const result = await this._client.ping();
|
|
94
|
+
return { success: result === 'PONG' };
|
|
95
|
+
}
|
|
96
|
+
catch (e) {
|
|
97
|
+
return { success: false, message: e.message };
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
parseConnectionUrl(url) {
|
|
101
|
+
const urlPattern = /redis:\/\/(?:(.*?)(?::(.*?))?@)?(.*?):(\d+)(?:\/(\d+))?/;
|
|
102
|
+
const match = url.match(urlPattern);
|
|
103
|
+
if (!match) {
|
|
104
|
+
return { host: 'localhost', port: 6379 };
|
|
105
|
+
}
|
|
106
|
+
const username = match[2] ? match[1] : undefined;
|
|
107
|
+
const password = match[2] || match[1];
|
|
108
|
+
const host = match[3] || 'localhost';
|
|
109
|
+
const port = parseInt(match[4], 10) || 6379;
|
|
110
|
+
const db = match[5] ? parseInt(match[5], 10) : undefined;
|
|
111
|
+
return { username, password, host, port, db };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
exports.Redis = Redis;
|
|
115
|
+
class RedisLock {
|
|
116
|
+
client;
|
|
117
|
+
resource;
|
|
118
|
+
expireMs;
|
|
119
|
+
retryCount;
|
|
120
|
+
retryDelay;
|
|
121
|
+
/** @internal */
|
|
122
|
+
_releaseLockCommand = 'releaseLock';
|
|
123
|
+
constructor(client, resource, expireMs = 5000, retryCount = 10, retryDelay = 200) {
|
|
124
|
+
this.client = client;
|
|
125
|
+
this.resource = resource;
|
|
126
|
+
this.expireMs = expireMs;
|
|
127
|
+
this.retryCount = retryCount;
|
|
128
|
+
this.retryDelay = retryDelay;
|
|
129
|
+
this.initReleaseLockScript();
|
|
130
|
+
}
|
|
131
|
+
async lock() {
|
|
132
|
+
const resourceKey = `lock:${this.resource}`;
|
|
133
|
+
const lockValue = (0, common_1.uuid)();
|
|
134
|
+
let retries = 0;
|
|
135
|
+
do {
|
|
136
|
+
const result = await this.client.set(resourceKey, lockValue, 'PX', this.expireMs, 'NX');
|
|
137
|
+
if (result === 'OK') {
|
|
138
|
+
return {
|
|
139
|
+
release: async () => (await this.client[this._releaseLockCommand](resourceKey, lockValue)) > 0
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
await (0, promises_1.setTimeout)(this.retryDelay);
|
|
144
|
+
retries++;
|
|
145
|
+
}
|
|
146
|
+
} while (retries < this.retryCount);
|
|
147
|
+
throw new Error('Unable to acquire lock on requested resource');
|
|
148
|
+
}
|
|
149
|
+
initReleaseLockScript() {
|
|
150
|
+
if (this._releaseLockCommand in this.client) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
this.client.defineCommand(this._releaseLockCommand, {
|
|
154
|
+
numberOfKeys: 1,
|
|
155
|
+
lua: 'if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1]) else return 0 end'
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@appweaver/core",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Appweaver - simple, fast, and reliable web application builder tool (@core)",
|
|
5
|
+
"author": "Luka Matosevic",
|
|
6
|
+
"license": "UNLICENSED",
|
|
7
|
+
"main": "./index.js",
|
|
8
|
+
"types": "./index.d.ts",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/lmatosevic/appweaver.git",
|
|
12
|
+
"directory": "packages/core"
|
|
13
|
+
},
|
|
14
|
+
"maintainers": [
|
|
15
|
+
{
|
|
16
|
+
"name": "Luka Matosevic",
|
|
17
|
+
"email": "lukamatosevic5@gmail.com",
|
|
18
|
+
"web": "https://lukamatosevic.com"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">= 20"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"generate": "weaver generate --modelPattern ./**/model.ts --typesPath ./types/generated.ts --schemaPath ./prisma/schema.prisma --clientPath ./prisma/client",
|
|
29
|
+
"db:recreate": "rimraf dev.db && rimraf prisma/migrations --glob \"*_init\" && weaver migration new init"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@fastify/auth": "5.0.4",
|
|
33
|
+
"@fastify/basic-auth": "6.2.0",
|
|
34
|
+
"@fastify/cors": "11.2.0",
|
|
35
|
+
"@fastify/helmet": "13.0.2",
|
|
36
|
+
"@fastify/jwt": "10.0.0",
|
|
37
|
+
"@fastify/multipart": "9.4.0",
|
|
38
|
+
"@fastify/oauth2": "8.2.0",
|
|
39
|
+
"@fastify/rate-limit": "10.3.0",
|
|
40
|
+
"@fastify/request-context": "6.2.1",
|
|
41
|
+
"@fastify/static": "9.1.3",
|
|
42
|
+
"@fastify/swagger": "9.6.1",
|
|
43
|
+
"@fastify/swagger-ui": "5.2.4",
|
|
44
|
+
"@fastify/type-provider-typebox": "6.1.0",
|
|
45
|
+
"@sinclair/typebox": "0.34.47",
|
|
46
|
+
"bcrypt": "6.0.0",
|
|
47
|
+
"csv-stringify": "6.6.0",
|
|
48
|
+
"date-fns": "4.1.0",
|
|
49
|
+
"fastify": "5.8.5",
|
|
50
|
+
"fastify-plugin": "5.1.0",
|
|
51
|
+
"flatted": "3.4.2"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@appweaver/common": "^1.0.0",
|
|
55
|
+
"@prisma/adapter-better-sqlite3": "^7.3.0",
|
|
56
|
+
"@prisma/client": "^7.3.0",
|
|
57
|
+
"bullmq": "^5.70.0",
|
|
58
|
+
"cron": "^4.4.0",
|
|
59
|
+
"ioredis": "^5.9.0",
|
|
60
|
+
"nodemailer": "^8.0.0",
|
|
61
|
+
"prisma": "^7.3.0",
|
|
62
|
+
"rimraf": "6.1.2"
|
|
63
|
+
},
|
|
64
|
+
"peerDependencies": {
|
|
65
|
+
"@appweaver/common": "^1.0.0",
|
|
66
|
+
"@prisma/client": "^7.3.0"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as Prisma from './internal/prismaNamespaceBrowser';
|
|
2
|
+
export { Prisma };
|
|
3
|
+
export * as $Enums from './enums';
|
|
4
|
+
export * from './enums';
|
|
5
|
+
/**
|
|
6
|
+
* Model ApiKey
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
9
|
+
export type ApiKey = Prisma.ApiKeyModel;
|
|
10
|
+
/**
|
|
11
|
+
* Model OneTimeToken
|
|
12
|
+
*
|
|
13
|
+
*/
|
|
14
|
+
export type OneTimeToken = Prisma.OneTimeTokenModel;
|
|
15
|
+
/**
|
|
16
|
+
* Model Permission
|
|
17
|
+
*
|
|
18
|
+
*/
|
|
19
|
+
export type Permission = Prisma.PermissionModel;
|
|
20
|
+
/**
|
|
21
|
+
* Model Role
|
|
22
|
+
*
|
|
23
|
+
*/
|
|
24
|
+
export type Role = Prisma.RoleModel;
|
|
25
|
+
/**
|
|
26
|
+
* Model Seeder
|
|
27
|
+
*
|
|
28
|
+
*/
|
|
29
|
+
export type Seeder = Prisma.SeederModel;
|
|
30
|
+
/**
|
|
31
|
+
* Model File
|
|
32
|
+
*
|
|
33
|
+
*/
|
|
34
|
+
export type File = Prisma.FileModel;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* !!! This is code generated by Prisma. Do not edit directly. !!! */
|
|
3
|
+
/* eslint-disable */
|
|
4
|
+
// biome-ignore-all lint: generated file
|
|
5
|
+
// @ts-nocheck
|
|
6
|
+
/*
|
|
7
|
+
* This file should be your main import to use Prisma-related types and utilities in a browser.
|
|
8
|
+
* Use it to get access to models, enums, and input types.
|
|
9
|
+
*
|
|
10
|
+
* This file does not contain a `PrismaClient` class, nor several other helpers that are intended as server-side only.
|
|
11
|
+
* See `client.ts` for the standard, server-side entry point.
|
|
12
|
+
*
|
|
13
|
+
* 🟢 You can import this file directly.
|
|
14
|
+
*/
|
|
15
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
18
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
19
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
20
|
+
}
|
|
21
|
+
Object.defineProperty(o, k2, desc);
|
|
22
|
+
}) : (function(o, m, k, k2) {
|
|
23
|
+
if (k2 === undefined) k2 = k;
|
|
24
|
+
o[k2] = m[k];
|
|
25
|
+
}));
|
|
26
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
27
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
28
|
+
}) : function(o, v) {
|
|
29
|
+
o["default"] = v;
|
|
30
|
+
});
|
|
31
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
32
|
+
var ownKeys = function(o) {
|
|
33
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
34
|
+
var ar = [];
|
|
35
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
36
|
+
return ar;
|
|
37
|
+
};
|
|
38
|
+
return ownKeys(o);
|
|
39
|
+
};
|
|
40
|
+
return function (mod) {
|
|
41
|
+
if (mod && mod.__esModule) return mod;
|
|
42
|
+
var result = {};
|
|
43
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
44
|
+
__setModuleDefault(result, mod);
|
|
45
|
+
return result;
|
|
46
|
+
};
|
|
47
|
+
})();
|
|
48
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
49
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
50
|
+
};
|
|
51
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
52
|
+
exports.$Enums = exports.Prisma = void 0;
|
|
53
|
+
const Prisma = __importStar(require("./internal/prismaNamespaceBrowser"));
|
|
54
|
+
exports.Prisma = Prisma;
|
|
55
|
+
exports.$Enums = __importStar(require("./enums"));
|
|
56
|
+
__exportStar(require("./enums"), exports);
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import * as runtime from "@prisma/client/runtime/client";
|
|
2
|
+
import * as $Class from "./internal/class";
|
|
3
|
+
import * as Prisma from "./internal/prismaNamespace";
|
|
4
|
+
export * as $Enums from './enums';
|
|
5
|
+
export * from "./enums";
|
|
6
|
+
/**
|
|
7
|
+
* ## Prisma Client
|
|
8
|
+
*
|
|
9
|
+
* Type-safe database client for TypeScript
|
|
10
|
+
* @example
|
|
11
|
+
* ```
|
|
12
|
+
* const prisma = new PrismaClient({
|
|
13
|
+
* adapter: new PrismaPg({ connectionString: process.env.DATABASE_URL })
|
|
14
|
+
* })
|
|
15
|
+
* // Fetch zero or more ApiKeys
|
|
16
|
+
* const apiKeys = await prisma.apiKey.findMany()
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* Read more in our [docs](https://pris.ly/d/client).
|
|
20
|
+
*/
|
|
21
|
+
export declare const PrismaClient: $Class.PrismaClientConstructor;
|
|
22
|
+
export type PrismaClient<LogOpts extends Prisma.LogLevel = never, OmitOpts extends Prisma.PrismaClientOptions["omit"] = Prisma.PrismaClientOptions["omit"], ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = $Class.PrismaClient<LogOpts, OmitOpts, ExtArgs>;
|
|
23
|
+
export { Prisma };
|
|
24
|
+
/**
|
|
25
|
+
* Model ApiKey
|
|
26
|
+
*
|
|
27
|
+
*/
|
|
28
|
+
export type ApiKey = Prisma.ApiKeyModel;
|
|
29
|
+
/**
|
|
30
|
+
* Model OneTimeToken
|
|
31
|
+
*
|
|
32
|
+
*/
|
|
33
|
+
export type OneTimeToken = Prisma.OneTimeTokenModel;
|
|
34
|
+
/**
|
|
35
|
+
* Model Permission
|
|
36
|
+
*
|
|
37
|
+
*/
|
|
38
|
+
export type Permission = Prisma.PermissionModel;
|
|
39
|
+
/**
|
|
40
|
+
* Model Role
|
|
41
|
+
*
|
|
42
|
+
*/
|
|
43
|
+
export type Role = Prisma.RoleModel;
|
|
44
|
+
/**
|
|
45
|
+
* Model Seeder
|
|
46
|
+
*
|
|
47
|
+
*/
|
|
48
|
+
export type Seeder = Prisma.SeederModel;
|
|
49
|
+
/**
|
|
50
|
+
* Model File
|
|
51
|
+
*
|
|
52
|
+
*/
|
|
53
|
+
export type File = Prisma.FileModel;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* !!! This is code generated by Prisma. Do not edit directly. !!! */
|
|
3
|
+
/* eslint-disable */
|
|
4
|
+
// biome-ignore-all lint: generated file
|
|
5
|
+
// @ts-nocheck
|
|
6
|
+
/*
|
|
7
|
+
* This file should be your main import to use Prisma. Through it you get access to all the models, enums, and input types.
|
|
8
|
+
* If you're looking for something you can import in the client-side of your application, please refer to the `browser.ts` file instead.
|
|
9
|
+
*
|
|
10
|
+
* 🟢 You can import this file directly.
|
|
11
|
+
*/
|
|
12
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
15
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
16
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
17
|
+
}
|
|
18
|
+
Object.defineProperty(o, k2, desc);
|
|
19
|
+
}) : (function(o, m, k, k2) {
|
|
20
|
+
if (k2 === undefined) k2 = k;
|
|
21
|
+
o[k2] = m[k];
|
|
22
|
+
}));
|
|
23
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
24
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
25
|
+
}) : function(o, v) {
|
|
26
|
+
o["default"] = v;
|
|
27
|
+
});
|
|
28
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
29
|
+
var ownKeys = function(o) {
|
|
30
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
31
|
+
var ar = [];
|
|
32
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
33
|
+
return ar;
|
|
34
|
+
};
|
|
35
|
+
return ownKeys(o);
|
|
36
|
+
};
|
|
37
|
+
return function (mod) {
|
|
38
|
+
if (mod && mod.__esModule) return mod;
|
|
39
|
+
var result = {};
|
|
40
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
41
|
+
__setModuleDefault(result, mod);
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
|
+
})();
|
|
45
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
46
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
47
|
+
};
|
|
48
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
+
exports.Prisma = exports.PrismaClient = exports.$Enums = void 0;
|
|
50
|
+
const $Class = __importStar(require("./internal/class"));
|
|
51
|
+
const Prisma = __importStar(require("./internal/prismaNamespace"));
|
|
52
|
+
exports.Prisma = Prisma;
|
|
53
|
+
exports.$Enums = __importStar(require("./enums"));
|
|
54
|
+
__exportStar(require("./enums"), exports);
|
|
55
|
+
/**
|
|
56
|
+
* ## Prisma Client
|
|
57
|
+
*
|
|
58
|
+
* Type-safe database client for TypeScript
|
|
59
|
+
* @example
|
|
60
|
+
* ```
|
|
61
|
+
* const prisma = new PrismaClient({
|
|
62
|
+
* adapter: new PrismaPg({ connectionString: process.env.DATABASE_URL })
|
|
63
|
+
* })
|
|
64
|
+
* // Fetch zero or more ApiKeys
|
|
65
|
+
* const apiKeys = await prisma.apiKey.findMany()
|
|
66
|
+
* ```
|
|
67
|
+
*
|
|
68
|
+
* Read more in our [docs](https://pris.ly/d/client).
|
|
69
|
+
*/
|
|
70
|
+
exports.PrismaClient = $Class.getPrismaClientClass();
|