@yunsoft/yuncms-core 0.1.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 +21 -0
- package/README.md +5 -0
- package/package.json +36 -0
- package/src/accountability.js +39 -0
- package/src/advisory-lock.js +30 -0
- package/src/auth/password.js +100 -0
- package/src/auth/tokens.js +38 -0
- package/src/auth/users-repository.js +25 -0
- package/src/bootstrap.js +41 -0
- package/src/config.js +106 -0
- package/src/context.js +33 -0
- package/src/database.js +31 -0
- package/src/errors.js +35 -0
- package/src/field-types.js +110 -0
- package/src/hooks.js +121 -0
- package/src/identifier.js +13 -0
- package/src/index.js +67 -0
- package/src/logger.js +56 -0
- package/src/m2m-lifecycle.js +139 -0
- package/src/mail/smtp-mailer.js +65 -0
- package/src/migrations/0001-system-schema.js +164 -0
- package/src/migrations/0002-session-access-tokens.js +10 -0
- package/src/migrations/0003-public-role-constraints.js +10 -0
- package/src/migrations/0004-auth-action-tokens.js +19 -0
- package/src/migrations.js +81 -0
- package/src/permission-validation.js +63 -0
- package/src/query.js +193 -0
- package/src/relation-expansion.js +216 -0
- package/src/retry.js +29 -0
- package/src/schema-metadata-repository.js +284 -0
- package/src/schema-version.js +21 -0
- package/src/schema.js +82 -0
- package/src/services/api-tokens-service.js +117 -0
- package/src/services/audit-service.js +182 -0
- package/src/services/auth-service.js +164 -0
- package/src/services/auth-tokens-service.js +215 -0
- package/src/services/base-service.js +26 -0
- package/src/services/collections-service.js +249 -0
- package/src/services/core-services.js +32 -0
- package/src/services/fields-service.js +471 -0
- package/src/services/file-reconciliation-service.js +127 -0
- package/src/services/files-service.js +227 -0
- package/src/services/items-service.js +445 -0
- package/src/services/permissions-service.js +282 -0
- package/src/services/relations-service.js +455 -0
- package/src/services/roles-service.js +160 -0
- package/src/services/schema-access.js +7 -0
- package/src/services/service-registry.js +32 -0
- package/src/services/sessions-service.js +179 -0
- package/src/services/users-service.js +215 -0
- package/src/setup.js +66 -0
- package/src/storage/local-storage-driver.js +105 -0
- package/src/storage/s3-storage-driver.js +150 -0
- package/src/storage/storage-registry.js +39 -0
- package/src/transaction.js +46 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
function assertDriver(name, driver) {
|
|
2
|
+
for (const method of ['put', 'get', 'delete', 'stat', 'getSignedUrl']) {
|
|
3
|
+
if (typeof driver?.[method] !== 'function') {
|
|
4
|
+
throw new Error(`Storage driver ${name} must implement ${method}()`);
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
return driver;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function createStorageRegistry(drivers = {}) {
|
|
11
|
+
const entries = Object.entries(drivers);
|
|
12
|
+
if (entries.length === 0) throw new Error('At least one storage driver is required');
|
|
13
|
+
|
|
14
|
+
const registry = new Map();
|
|
15
|
+
for (const [name, driver] of entries) {
|
|
16
|
+
if (!/^[a-z][a-z0-9_-]{0,63}$/.test(name)) {
|
|
17
|
+
throw new Error(`Invalid storage driver name: ${name}`);
|
|
18
|
+
}
|
|
19
|
+
registry.set(name, assertDriver(name, driver));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return Object.freeze({
|
|
23
|
+
has(name) {
|
|
24
|
+
return registry.has(name);
|
|
25
|
+
},
|
|
26
|
+
get(name) {
|
|
27
|
+
const driver = registry.get(name);
|
|
28
|
+
if (!driver) {
|
|
29
|
+
const error = new Error(`Unknown storage driver: ${name}`);
|
|
30
|
+
error.code = 'STORAGE_NOT_FOUND';
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
return driver;
|
|
34
|
+
},
|
|
35
|
+
names() {
|
|
36
|
+
return Object.freeze([...registry.keys()]);
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const ISOLATION_LEVELS = new Set([
|
|
2
|
+
'READ UNCOMMITTED',
|
|
3
|
+
'READ COMMITTED',
|
|
4
|
+
'REPEATABLE READ',
|
|
5
|
+
'SERIALIZABLE',
|
|
6
|
+
]);
|
|
7
|
+
|
|
8
|
+
async function setIsolationLevel(connection, isolationLevel) {
|
|
9
|
+
if (!isolationLevel) return;
|
|
10
|
+
const level = String(isolationLevel).toUpperCase();
|
|
11
|
+
if (!ISOLATION_LEVELS.has(level)) {
|
|
12
|
+
throw new Error(`Unsupported transaction isolation level: ${isolationLevel}`);
|
|
13
|
+
}
|
|
14
|
+
await connection.query(`SET TRANSACTION ISOLATION LEVEL ${level}`);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export async function withConnectionTransaction(connection, operation, options = {}) {
|
|
18
|
+
if (!connection) throw new Error('Database connection is required');
|
|
19
|
+
if (typeof operation !== 'function') throw new Error('Transaction operation is required');
|
|
20
|
+
|
|
21
|
+
await setIsolationLevel(connection, options.isolationLevel);
|
|
22
|
+
await connection.beginTransaction();
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
const result = await operation(connection);
|
|
26
|
+
await connection.commit();
|
|
27
|
+
return result;
|
|
28
|
+
} catch (error) {
|
|
29
|
+
try {
|
|
30
|
+
await connection.rollback();
|
|
31
|
+
} catch (rollbackError) {
|
|
32
|
+
error.rollbackError = rollbackError;
|
|
33
|
+
}
|
|
34
|
+
throw error;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function withTransaction(pool, operation, options = {}) {
|
|
39
|
+
const connection = await pool.getConnection();
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
return await withConnectionTransaction(connection, operation, options);
|
|
43
|
+
} finally {
|
|
44
|
+
connection.release();
|
|
45
|
+
}
|
|
46
|
+
}
|