@nitronjs/framework 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/README.md +429 -0
- package/cli/create.js +260 -0
- package/cli/njs.js +164 -0
- package/lib/Auth/Manager.js +111 -0
- package/lib/Build/Manager.js +1232 -0
- package/lib/Console/Commands/BuildCommand.js +25 -0
- package/lib/Console/Commands/DevCommand.js +385 -0
- package/lib/Console/Commands/MakeCommand.js +110 -0
- package/lib/Console/Commands/MigrateCommand.js +98 -0
- package/lib/Console/Commands/MigrateFreshCommand.js +97 -0
- package/lib/Console/Commands/SeedCommand.js +92 -0
- package/lib/Console/Commands/StorageLinkCommand.js +31 -0
- package/lib/Console/Stubs/controller.js +19 -0
- package/lib/Console/Stubs/middleware.js +9 -0
- package/lib/Console/Stubs/migration.js +23 -0
- package/lib/Console/Stubs/model.js +7 -0
- package/lib/Console/Stubs/page-hydration.tsx +54 -0
- package/lib/Console/Stubs/seeder.js +9 -0
- package/lib/Console/Stubs/vendor.tsx +11 -0
- package/lib/Core/Config.js +86 -0
- package/lib/Core/Environment.js +21 -0
- package/lib/Core/Paths.js +188 -0
- package/lib/Database/Connection.js +61 -0
- package/lib/Database/DB.js +84 -0
- package/lib/Database/Drivers/MySQLDriver.js +234 -0
- package/lib/Database/Manager.js +162 -0
- package/lib/Database/Model.js +161 -0
- package/lib/Database/QueryBuilder.js +714 -0
- package/lib/Database/QueryValidation.js +62 -0
- package/lib/Database/Schema/Blueprint.js +126 -0
- package/lib/Database/Schema/Manager.js +116 -0
- package/lib/Date/DateTime.js +108 -0
- package/lib/Date/Locale.js +68 -0
- package/lib/Encryption/Manager.js +47 -0
- package/lib/Filesystem/Manager.js +49 -0
- package/lib/Hashing/Manager.js +25 -0
- package/lib/Http/Server.js +317 -0
- package/lib/Logging/Manager.js +153 -0
- package/lib/Mail/Manager.js +120 -0
- package/lib/Route/Loader.js +81 -0
- package/lib/Route/Manager.js +265 -0
- package/lib/Runtime/Entry.js +11 -0
- package/lib/Session/File.js +299 -0
- package/lib/Session/Manager.js +259 -0
- package/lib/Session/Memory.js +67 -0
- package/lib/Session/Session.js +196 -0
- package/lib/Support/Str.js +100 -0
- package/lib/Translation/Manager.js +49 -0
- package/lib/Validation/MimeTypes.js +39 -0
- package/lib/Validation/Validator.js +691 -0
- package/lib/View/Manager.js +544 -0
- package/lib/View/Templates/default/Home.tsx +262 -0
- package/lib/View/Templates/default/MainLayout.tsx +44 -0
- package/lib/View/Templates/errors/404.tsx +13 -0
- package/lib/View/Templates/errors/500.tsx +13 -0
- package/lib/View/Templates/errors/ErrorLayout.tsx +112 -0
- package/lib/View/Templates/messages/Maintenance.tsx +17 -0
- package/lib/View/Templates/messages/MessageLayout.tsx +136 -0
- package/lib/index.js +57 -0
- package/package.json +47 -0
- package/skeleton/.env.example +26 -0
- package/skeleton/app/Controllers/HomeController.js +9 -0
- package/skeleton/app/Kernel.js +11 -0
- package/skeleton/app/Middlewares/Authentication.js +9 -0
- package/skeleton/app/Middlewares/Guest.js +9 -0
- package/skeleton/app/Middlewares/VerifyCsrf.js +24 -0
- package/skeleton/app/Models/User.js +7 -0
- package/skeleton/config/app.js +4 -0
- package/skeleton/config/auth.js +16 -0
- package/skeleton/config/database.js +27 -0
- package/skeleton/config/hash.js +3 -0
- package/skeleton/config/server.js +28 -0
- package/skeleton/config/session.js +21 -0
- package/skeleton/database/migrations/2025_01_01_00_00_users.js +20 -0
- package/skeleton/database/seeders/UserSeeder.js +15 -0
- package/skeleton/globals.d.ts +1 -0
- package/skeleton/package.json +24 -0
- package/skeleton/public/.gitkeep +0 -0
- package/skeleton/resources/css/.gitkeep +0 -0
- package/skeleton/resources/langs/.gitkeep +0 -0
- package/skeleton/resources/views/Site/Home.tsx +66 -0
- package/skeleton/routes/web.js +4 -0
- package/skeleton/storage/app/private/.gitkeep +0 -0
- package/skeleton/storage/app/public/.gitkeep +0 -0
- package/skeleton/storage/framework/sessions/.gitkeep +0 -0
- package/skeleton/storage/logs/.gitkeep +0 -0
- package/skeleton/tsconfig.json +33 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export function validateIdentifier(identifier) {
|
|
2
|
+
if (typeof identifier !== 'string' || identifier.length === 0) {
|
|
3
|
+
throw new Error('Identifier must be a non-empty string');
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
if (identifier.length > 64) {
|
|
7
|
+
throw new Error(`Invalid identifier: "${identifier}". Maximum length is 64 characters.`);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (identifier === '*' || identifier === '*.*') {
|
|
11
|
+
return identifier;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (/--|#|\/\*|\*\//.test(identifier)) {
|
|
15
|
+
throw new Error(`Invalid identifier: "${identifier}". SQL comments are not allowed.`);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const patterns = [
|
|
19
|
+
/^[a-zA-Z_][a-zA-Z0-9_]*$/,
|
|
20
|
+
/^[a-zA-Z_][a-zA-Z0-9_]*\.[a-zA-Z_][a-zA-Z0-9_]*$/,
|
|
21
|
+
/^[a-zA-Z_][a-zA-Z0-9_]*\.\*$/
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
const isValid = patterns.some(pattern => pattern.test(identifier));
|
|
25
|
+
|
|
26
|
+
if (!isValid) {
|
|
27
|
+
throw new Error(`Invalid identifier: "${identifier}". Must be alphanumeric with underscores, optionally qualified with table name.`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return identifier;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function validateWhereOperator(operator) {
|
|
34
|
+
const normalized = String(operator).trim().toUpperCase();
|
|
35
|
+
const allowedOperators = new Set([
|
|
36
|
+
'=', '!=', '<>', '<', '>', '<=', '>=',
|
|
37
|
+
'LIKE', 'NOT LIKE', 'ILIKE', 'NOT ILIKE',
|
|
38
|
+
'IN', 'NOT IN',
|
|
39
|
+
'IS', 'IS NOT',
|
|
40
|
+
'BETWEEN', 'NOT BETWEEN',
|
|
41
|
+
'REGEXP', 'NOT REGEXP',
|
|
42
|
+
'RLIKE', 'NOT RLIKE'
|
|
43
|
+
]);
|
|
44
|
+
|
|
45
|
+
if (!allowedOperators.has(normalized)) {
|
|
46
|
+
throw new Error(
|
|
47
|
+
`Invalid WHERE operator: '${operator}'. ` +
|
|
48
|
+
`Allowed operators: ${[...allowedOperators].join(', ')}`
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return normalized;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function validateDirection(direction) {
|
|
56
|
+
const upper = String(direction).toUpperCase();
|
|
57
|
+
if (upper !== 'ASC' && upper !== 'DESC') {
|
|
58
|
+
throw new Error(`Invalid direction: ${direction}. Use 'ASC' or 'DESC'.`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return upper;
|
|
62
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Blueprint - Table schema builder
|
|
3
|
+
* Laravel-style fluent API for defining database tables
|
|
4
|
+
*/
|
|
5
|
+
class Blueprint {
|
|
6
|
+
#tableName;
|
|
7
|
+
#columns = [];
|
|
8
|
+
|
|
9
|
+
constructor(tableName) {
|
|
10
|
+
this.#tableName = tableName;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Get table name
|
|
15
|
+
*/
|
|
16
|
+
getTableName() {
|
|
17
|
+
return this.#tableName;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Get all columns
|
|
22
|
+
*/
|
|
23
|
+
getColumns() {
|
|
24
|
+
return this.#columns;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Add a column definition
|
|
29
|
+
*/
|
|
30
|
+
#addColumn(type, name, options = {}) {
|
|
31
|
+
const column = {
|
|
32
|
+
name,
|
|
33
|
+
type,
|
|
34
|
+
...options,
|
|
35
|
+
modifiers: {
|
|
36
|
+
nullable: false,
|
|
37
|
+
default: null,
|
|
38
|
+
unique: false
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
this.#columns.push(column);
|
|
43
|
+
|
|
44
|
+
// Return modifier object for chaining
|
|
45
|
+
return {
|
|
46
|
+
nullable: () => {
|
|
47
|
+
column.modifiers.nullable = true;
|
|
48
|
+
return this;
|
|
49
|
+
},
|
|
50
|
+
default: (value) => {
|
|
51
|
+
column.modifiers.default = value;
|
|
52
|
+
return this;
|
|
53
|
+
},
|
|
54
|
+
unique: () => {
|
|
55
|
+
column.modifiers.unique = true;
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Primary key: BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY
|
|
63
|
+
*/
|
|
64
|
+
id() {
|
|
65
|
+
const column = {
|
|
66
|
+
name: 'id',
|
|
67
|
+
type: 'id',
|
|
68
|
+
modifiers: {}
|
|
69
|
+
};
|
|
70
|
+
this.#columns.push(column);
|
|
71
|
+
|
|
72
|
+
// No chaining for id()
|
|
73
|
+
return this;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* VARCHAR column
|
|
78
|
+
*/
|
|
79
|
+
string(name, length = 255) {
|
|
80
|
+
return this.#addColumn('string', name, { length });
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* TEXT column
|
|
85
|
+
*/
|
|
86
|
+
text(name) {
|
|
87
|
+
return this.#addColumn('text', name);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* INT column
|
|
92
|
+
*/
|
|
93
|
+
integer(name) {
|
|
94
|
+
return this.#addColumn('integer', name);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* BIGINT column
|
|
99
|
+
*/
|
|
100
|
+
bigInteger(name) {
|
|
101
|
+
return this.#addColumn('bigInteger', name);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* TINYINT(1) column for boolean values
|
|
106
|
+
*/
|
|
107
|
+
boolean(name) {
|
|
108
|
+
return this.#addColumn('boolean', name);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* TIMESTAMP column
|
|
113
|
+
*/
|
|
114
|
+
timestamp(name) {
|
|
115
|
+
return this.#addColumn('timestamp', name);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* JSON column
|
|
120
|
+
*/
|
|
121
|
+
json(name) {
|
|
122
|
+
return this.#addColumn('json', name);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export default Blueprint;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import DatabaseManager from "../Manager.js";
|
|
2
|
+
import Config from "../../Core/Config.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Schema Builder
|
|
6
|
+
* Laravel-style database schema operations
|
|
7
|
+
*/
|
|
8
|
+
export default class Schema {
|
|
9
|
+
/**
|
|
10
|
+
* Create a new table
|
|
11
|
+
*/
|
|
12
|
+
static async create(tableName, callback) {
|
|
13
|
+
const blueprint = new (await import('./Blueprint.js')).default(tableName);
|
|
14
|
+
callback(blueprint);
|
|
15
|
+
|
|
16
|
+
const sql = this.#buildCreateTableSQL(blueprint);
|
|
17
|
+
|
|
18
|
+
const connection = DatabaseManager.getInstance().connection();
|
|
19
|
+
await connection.raw(sql);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Drop table if exists
|
|
24
|
+
*/
|
|
25
|
+
static async dropIfExists(tableName) {
|
|
26
|
+
const connection = DatabaseManager.getInstance().connection();
|
|
27
|
+
await connection.raw(`DROP TABLE IF EXISTS \`${tableName}\``);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Build CREATE TABLE SQL
|
|
32
|
+
*/
|
|
33
|
+
static #buildCreateTableSQL(blueprint) {
|
|
34
|
+
const columns = blueprint.getColumns();
|
|
35
|
+
const columnsSql = columns.map(col => this.#buildColumnSQL(col));
|
|
36
|
+
|
|
37
|
+
// Get connection config
|
|
38
|
+
const manager = DatabaseManager.getInstance();
|
|
39
|
+
const connection = manager.connection();
|
|
40
|
+
const connectionName = connection.getName();
|
|
41
|
+
const databaseConfig = Config.all('database');
|
|
42
|
+
const dbConfig = databaseConfig.connections[connectionName];
|
|
43
|
+
|
|
44
|
+
const charset = dbConfig.charset || 'utf8mb4';
|
|
45
|
+
const collation = dbConfig.collation || 'utf8mb4_unicode_ci';
|
|
46
|
+
|
|
47
|
+
let sql = `CREATE TABLE \`${blueprint.getTableName()}\` (\n`;
|
|
48
|
+
sql += ' ' + columnsSql.join(',\n ');
|
|
49
|
+
sql += `\n) ENGINE=InnoDB DEFAULT CHARSET=${charset} COLLATE=${collation}`;
|
|
50
|
+
|
|
51
|
+
return sql;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Build SQL for a single column
|
|
56
|
+
*/
|
|
57
|
+
static #buildColumnSQL(column) {
|
|
58
|
+
let sql = `\`${column.name}\` `;
|
|
59
|
+
|
|
60
|
+
// Type
|
|
61
|
+
switch (column.type) {
|
|
62
|
+
case 'id':
|
|
63
|
+
// id is special - no modifiers
|
|
64
|
+
sql += 'BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY';
|
|
65
|
+
return sql;
|
|
66
|
+
case 'string':
|
|
67
|
+
sql += `VARCHAR(${column.length || 255})`;
|
|
68
|
+
break;
|
|
69
|
+
case 'text':
|
|
70
|
+
sql += 'TEXT';
|
|
71
|
+
break;
|
|
72
|
+
case 'integer':
|
|
73
|
+
sql += 'INT';
|
|
74
|
+
break;
|
|
75
|
+
case 'bigInteger':
|
|
76
|
+
sql += 'BIGINT';
|
|
77
|
+
break;
|
|
78
|
+
case 'boolean':
|
|
79
|
+
sql += 'TINYINT(1)';
|
|
80
|
+
break;
|
|
81
|
+
case 'timestamp':
|
|
82
|
+
sql += 'TIMESTAMP';
|
|
83
|
+
break;
|
|
84
|
+
case 'json':
|
|
85
|
+
sql += 'JSON';
|
|
86
|
+
break;
|
|
87
|
+
default:
|
|
88
|
+
throw new Error(`Unknown column type: ${column.type}`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Modifiers (not for id)
|
|
92
|
+
if (column.modifiers) {
|
|
93
|
+
// NOT NULL / NULL
|
|
94
|
+
if (column.modifiers.nullable) {
|
|
95
|
+
sql += ' NULL';
|
|
96
|
+
} else {
|
|
97
|
+
sql += ' NOT NULL';
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// DEFAULT
|
|
101
|
+
if (column.modifiers.default !== null) {
|
|
102
|
+
const defaultValue = typeof column.modifiers.default === 'string'
|
|
103
|
+
? `'${column.modifiers.default}'`
|
|
104
|
+
: column.modifiers.default;
|
|
105
|
+
sql += ` DEFAULT ${defaultValue}`;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// UNIQUE
|
|
109
|
+
if (column.modifiers.unique) {
|
|
110
|
+
sql += ' UNIQUE';
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return sql;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import locale from './Locale.js';
|
|
2
|
+
import Config from '../Core/Config.js';
|
|
3
|
+
|
|
4
|
+
class DateTime {
|
|
5
|
+
static #getDate(date = null) {
|
|
6
|
+
const timezone = Config.get('app.timezone', 'UTC');
|
|
7
|
+
const d = date ? new Date(date) : new Date();
|
|
8
|
+
|
|
9
|
+
return new Date(d.toLocaleString('en-US', { timeZone: timezone }));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
static #format(date, formatString) {
|
|
13
|
+
const lang = locale[Config.get('app.locale', 'en')] || locale.en;
|
|
14
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
15
|
+
|
|
16
|
+
const map = {
|
|
17
|
+
'Y': date.getFullYear(),
|
|
18
|
+
'y': String(date.getFullYear()).slice(-2),
|
|
19
|
+
'm': pad(date.getMonth() + 1),
|
|
20
|
+
'n': date.getMonth() + 1,
|
|
21
|
+
'd': pad(date.getDate()),
|
|
22
|
+
'j': date.getDate(),
|
|
23
|
+
'H': pad(date.getHours()),
|
|
24
|
+
'i': pad(date.getMinutes()),
|
|
25
|
+
's': pad(date.getSeconds()),
|
|
26
|
+
'D': lang.days[date.getDay()],
|
|
27
|
+
'l': lang.daysShort[date.getDay()],
|
|
28
|
+
'M': lang.months[date.getMonth()],
|
|
29
|
+
'F': lang.monthsShort[date.getMonth()]
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
return formatString.replace(/[YynmdjHislDMF]/g, match => map[match]);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Get current date/time in SQL format
|
|
37
|
+
* @param {number|null} timestamp - Optional timestamp
|
|
38
|
+
* @returns {string} SQL formatted datetime (YYYY-MM-DD HH:mm:ss)
|
|
39
|
+
*/
|
|
40
|
+
static toSQL(timestamp = null) {
|
|
41
|
+
const d = timestamp ? new Date(timestamp) : this.#getDate();
|
|
42
|
+
return d.toISOString().slice(0, 19).replace('T', ' ');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Get timestamp in milliseconds
|
|
47
|
+
* @param {string|null} sqlDateTime - Optional SQL datetime string
|
|
48
|
+
* @returns {number} Timestamp in milliseconds
|
|
49
|
+
*/
|
|
50
|
+
static getTime(sqlDateTime = null) {
|
|
51
|
+
if (sqlDateTime === null) {
|
|
52
|
+
return this.#getDate().getTime();
|
|
53
|
+
}
|
|
54
|
+
return new Date(sqlDateTime).getTime();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Get formatted date
|
|
59
|
+
* @param {number|null} timestamp - Optional timestamp
|
|
60
|
+
* @param {string} format - Date format string
|
|
61
|
+
* @returns {string} Formatted date
|
|
62
|
+
*/
|
|
63
|
+
static getDate(timestamp = null, format = 'Y-m-d H:i:s') {
|
|
64
|
+
return this.#format(this.#getDate(timestamp), format);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Add days to current date
|
|
69
|
+
* @param {number} days - Number of days to add
|
|
70
|
+
* @returns {string} SQL formatted datetime
|
|
71
|
+
*/
|
|
72
|
+
static addDays(days) {
|
|
73
|
+
const date = this.#getDate();
|
|
74
|
+
date.setDate(date.getDate() + days);
|
|
75
|
+
return date.toISOString().slice(0, 19).replace('T', ' ');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Add hours to current date
|
|
80
|
+
* @param {number} hours - Number of hours to add
|
|
81
|
+
* @returns {string} SQL formatted datetime
|
|
82
|
+
*/
|
|
83
|
+
static addHours(hours) {
|
|
84
|
+
const date = this.#getDate();
|
|
85
|
+
date.setHours(date.getHours() + hours);
|
|
86
|
+
return date.toISOString().slice(0, 19).replace('T', ' ');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Subtract days from current date
|
|
91
|
+
* @param {number} days - Number of days to subtract
|
|
92
|
+
* @returns {string} SQL formatted datetime
|
|
93
|
+
*/
|
|
94
|
+
static subDays(days) {
|
|
95
|
+
return this.addDays(-days);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Subtract hours from current date
|
|
100
|
+
* @param {number} hours - Number of hours to subtract
|
|
101
|
+
* @returns {string} SQL formatted datetime
|
|
102
|
+
*/
|
|
103
|
+
static subHours(hours) {
|
|
104
|
+
return this.addHours(-hours);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export default DateTime;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
tr: {
|
|
3
|
+
days: ['Pazar', 'Pazartesi', 'Salı', 'Çarşamba', 'Perşembe', 'Cuma', 'Cumartesi'],
|
|
4
|
+
daysShort: ['Paz', 'Pzt', 'Sal', 'Çar', 'Per', 'Cum', 'Cmt'],
|
|
5
|
+
months: ['Ocak', 'Şubat', 'Mart', 'Nisan', 'Mayıs', 'Haziran', 'Temmuz', 'Ağustos', 'Eylül', 'Ekim', 'Kasım', 'Aralık'],
|
|
6
|
+
monthsShort: ['Oca', 'Şub', 'Mar', 'Nis', 'May', 'Haz', 'Tem', 'Ağu', 'Eyl', 'Eki', 'Kas', 'Ara']
|
|
7
|
+
},
|
|
8
|
+
en: {
|
|
9
|
+
days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
|
|
10
|
+
daysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
|
|
11
|
+
months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
|
|
12
|
+
monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
|
|
13
|
+
},
|
|
14
|
+
de: {
|
|
15
|
+
days: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'],
|
|
16
|
+
daysShort: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
|
|
17
|
+
months: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
|
|
18
|
+
monthsShort: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez']
|
|
19
|
+
},
|
|
20
|
+
fr: {
|
|
21
|
+
days: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi'],
|
|
22
|
+
daysShort: ['Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam'],
|
|
23
|
+
months: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
|
|
24
|
+
monthsShort: ['Jan', 'Fév', 'Mar', 'Avr', 'Mai', 'Jun', 'Jul', 'Aoû', 'Sep', 'Oct', 'Nov', 'Déc']
|
|
25
|
+
},
|
|
26
|
+
es: {
|
|
27
|
+
days: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'],
|
|
28
|
+
daysShort: ['Dom', 'Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb'],
|
|
29
|
+
months: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
|
|
30
|
+
monthsShort: ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic']
|
|
31
|
+
},
|
|
32
|
+
it: {
|
|
33
|
+
days: ['Domenica', 'Lunedì', 'Martedì', 'Mercoledì', 'Giovedì', 'Venerdì', 'Sabato'],
|
|
34
|
+
daysShort: ['Dom', 'Lun', 'Mar', 'Mer', 'Gio', 'Ven', 'Sab'],
|
|
35
|
+
months: ['Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio', 'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre', 'Dicembre'],
|
|
36
|
+
monthsShort: ['Gen', 'Feb', 'Mar', 'Apr', 'Mag', 'Giu', 'Lug', 'Ago', 'Set', 'Ott', 'Nov', 'Dic']
|
|
37
|
+
},
|
|
38
|
+
pt: {
|
|
39
|
+
days: ['Domingo', 'Segunda-feira', 'Terça-feira', 'Quarta-feira', 'Quinta-feira', 'Sexta-feira', 'Sábado'],
|
|
40
|
+
daysShort: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'],
|
|
41
|
+
months: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'],
|
|
42
|
+
monthsShort: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez']
|
|
43
|
+
},
|
|
44
|
+
ru: {
|
|
45
|
+
days: ['Воскресенье', 'Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота'],
|
|
46
|
+
daysShort: ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'],
|
|
47
|
+
months: ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'],
|
|
48
|
+
monthsShort: ['Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек']
|
|
49
|
+
},
|
|
50
|
+
ar: {
|
|
51
|
+
days: ['الأحد', 'الإثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
|
52
|
+
daysShort: ['أحد', 'إثن', 'ثلا', 'أرب', 'خمي', 'جمع', 'سبت'],
|
|
53
|
+
months: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
|
|
54
|
+
monthsShort: ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس']
|
|
55
|
+
},
|
|
56
|
+
ja: {
|
|
57
|
+
days: ['日曜日', '月曜日', '火曜日', '水曜日', '木曜日', '金曜日', '土曜日'],
|
|
58
|
+
daysShort: ['日', '月', '火', '水', '木', '金', '土'],
|
|
59
|
+
months: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
|
|
60
|
+
monthsShort: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
|
|
61
|
+
},
|
|
62
|
+
zh: {
|
|
63
|
+
days: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
|
|
64
|
+
daysShort: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
|
|
65
|
+
months: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
|
|
66
|
+
monthsShort: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
|
|
67
|
+
}
|
|
68
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import crypto from "crypto";
|
|
2
|
+
|
|
3
|
+
class EncryptionManager {
|
|
4
|
+
static encrypt(value) {
|
|
5
|
+
if (typeof value === "object") {
|
|
6
|
+
value = JSON.stringify(value);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const secretKey = this.#createSecretKey();
|
|
10
|
+
const iv = this.#createIV();
|
|
11
|
+
|
|
12
|
+
const cipher = crypto.createCipheriv("aes-256-cbc", secretKey, iv);
|
|
13
|
+
let encrypted = cipher.update(value, "utf8", "hex");
|
|
14
|
+
encrypted += cipher.final("hex");
|
|
15
|
+
encrypted = iv.toString("hex") + ":" + encrypted;
|
|
16
|
+
|
|
17
|
+
return encrypted;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static decrypt(encryptedValue) {
|
|
21
|
+
try {
|
|
22
|
+
const parts = encryptedValue.split(":");
|
|
23
|
+
const iv = Buffer.from(parts.shift(), "hex");
|
|
24
|
+
const encryptedText = Buffer.from(parts.join(":"), "hex");
|
|
25
|
+
|
|
26
|
+
const secretKey = this.#createSecretKey();
|
|
27
|
+
|
|
28
|
+
const decipher = crypto.createDecipheriv("aes-256-cbc", secretKey, iv);
|
|
29
|
+
let decrypted = decipher.update(encryptedText, "hex", "utf8");
|
|
30
|
+
decrypted += decipher.final("utf8");
|
|
31
|
+
|
|
32
|
+
return decrypted;
|
|
33
|
+
} catch (error) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
static #createSecretKey() {
|
|
39
|
+
return crypto.createHash("sha256").update(process.env.APP_KEY).digest();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
static #createIV() {
|
|
43
|
+
return crypto.randomBytes(16);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export default EncryptionManager;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import Paths from "../Core/Paths.js";
|
|
4
|
+
|
|
5
|
+
class FilesystemManager {
|
|
6
|
+
static #publicRoot = Paths.storagePublic;
|
|
7
|
+
static #privateRoot = Paths.storagePrivate;
|
|
8
|
+
|
|
9
|
+
static async get(filePath, isPrivate = false) {
|
|
10
|
+
const base = isPrivate ? this.#privateRoot : this.#publicRoot;
|
|
11
|
+
const fullPath = path.join(base, filePath);
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
return await fs.promises.readFile(fullPath);
|
|
15
|
+
} catch {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static async put(file, dir, fileName, isPrivate = false) {
|
|
21
|
+
const base = isPrivate ? this.#privateRoot : this.#publicRoot;
|
|
22
|
+
const folderPath = path.join(base, dir);
|
|
23
|
+
const fullPath = path.join(folderPath, fileName);
|
|
24
|
+
|
|
25
|
+
await fs.promises.mkdir(folderPath, { recursive: true });
|
|
26
|
+
await fs.promises.writeFile(fullPath, file._buf);
|
|
27
|
+
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static async delete(filePath, isPrivate = false) {
|
|
32
|
+
const base = isPrivate ? this.#privateRoot : this.#publicRoot;
|
|
33
|
+
await fs.promises.unlink(path.join(base, filePath));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
static exists(filePath, isPrivate = false) {
|
|
37
|
+
const base = isPrivate ? this.#privateRoot : this.#publicRoot;
|
|
38
|
+
return fs.existsSync(path.join(base, filePath));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static url(filePath) {
|
|
42
|
+
if (filePath.startsWith("/")) {
|
|
43
|
+
filePath = filePath.substring(1);
|
|
44
|
+
}
|
|
45
|
+
return `/storage/${filePath}`;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export default FilesystemManager;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import bcrypt from "bcrypt";
|
|
2
|
+
import Config from "../Core/Config.js";
|
|
3
|
+
|
|
4
|
+
class HashManager {
|
|
5
|
+
static async make(textField) {
|
|
6
|
+
if (!process.env.APP_KEY) {
|
|
7
|
+
throw new Error("APP_KEY is required for hashing");
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const saltRounds = Config.get("hash.salt_rounds", 10);
|
|
11
|
+
const salt = await bcrypt.genSalt(saltRounds);
|
|
12
|
+
|
|
13
|
+
return await bcrypt.hash(textField + process.env.APP_KEY, salt);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
static async check(textField, hashedText) {
|
|
17
|
+
if (!process.env.APP_KEY) {
|
|
18
|
+
throw new Error("APP_KEY is required for hashing");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return await bcrypt.compare(textField + process.env.APP_KEY, hashedText);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default HashManager;
|