millas 0.2.11 → 0.2.12-beta-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/package.json +6 -5
  2. package/src/auth/Auth.js +13 -8
  3. package/src/auth/AuthController.js +45 -134
  4. package/src/auth/AuthMiddleware.js +12 -23
  5. package/src/auth/AuthUser.js +98 -0
  6. package/src/auth/RoleMiddleware.js +7 -17
  7. package/src/cli.js +1 -1
  8. package/src/commands/migrate.js +46 -31
  9. package/src/commands/serve.js +238 -38
  10. package/src/container/AppInitializer.js +158 -0
  11. package/src/container/Application.js +288 -183
  12. package/src/container/HttpServer.js +156 -0
  13. package/src/container/MillasApp.js +23 -280
  14. package/src/container/MillasConfig.js +163 -0
  15. package/src/controller/Controller.js +79 -300
  16. package/src/core/auth.js +9 -0
  17. package/src/core/db.js +8 -0
  18. package/src/core/foundation.js +67 -0
  19. package/src/core/http.js +11 -0
  20. package/src/core/mail.js +6 -0
  21. package/src/core/queue.js +7 -0
  22. package/src/core/validation.js +29 -0
  23. package/src/errors/ErrorRenderer.js +640 -0
  24. package/src/facades/Admin.js +49 -0
  25. package/src/facades/Auth.js +29 -0
  26. package/src/facades/Cache.js +28 -0
  27. package/src/facades/Database.js +43 -0
  28. package/src/facades/Events.js +25 -0
  29. package/src/facades/Facade.js +197 -0
  30. package/src/facades/Http.js +51 -0
  31. package/src/facades/Log.js +32 -0
  32. package/src/facades/Mail.js +35 -0
  33. package/src/facades/Queue.js +30 -0
  34. package/src/facades/Storage.js +25 -0
  35. package/src/facades/Url.js +53 -0
  36. package/src/http/HttpClient.js +673 -0
  37. package/src/http/MillasRequest.js +253 -0
  38. package/src/http/MillasResponse.js +196 -0
  39. package/src/http/RequestContext.js +176 -0
  40. package/src/http/ResponseDispatcher.js +51 -0
  41. package/src/http/UrlGenerator.js +375 -0
  42. package/src/http/WelcomePage.js +273 -0
  43. package/src/http/adapters/ExpressAdapter.js +315 -0
  44. package/src/http/adapters/HttpAdapter.js +168 -0
  45. package/src/http/adapters/index.js +9 -0
  46. package/src/http/helpers.js +164 -0
  47. package/src/http/index.js +13 -0
  48. package/src/index.js +5 -91
  49. package/src/logger/formatters/PrettyFormatter.js +15 -5
  50. package/src/logger/internal.js +76 -0
  51. package/src/logger/patchConsole.js +145 -0
  52. package/src/middleware/CorsMiddleware.js +22 -30
  53. package/src/middleware/LogMiddleware.js +27 -59
  54. package/src/middleware/Middleware.js +24 -15
  55. package/src/middleware/MiddlewarePipeline.js +30 -67
  56. package/src/middleware/MiddlewareRegistry.js +106 -0
  57. package/src/middleware/ThrottleMiddleware.js +22 -26
  58. package/src/orm/fields/index.js +124 -56
  59. package/src/orm/migration/ModelInspector.js +339 -336
  60. package/src/orm/model/Model.js +96 -6
  61. package/src/orm/query/QueryBuilder.js +141 -3
  62. package/src/providers/AuthServiceProvider.js +9 -5
  63. package/src/providers/CacheStorageServiceProvider.js +3 -1
  64. package/src/providers/EventServiceProvider.js +2 -1
  65. package/src/providers/LogServiceProvider.js +88 -17
  66. package/src/providers/MailServiceProvider.js +3 -2
  67. package/src/providers/ProviderRegistry.js +14 -1
  68. package/src/providers/QueueServiceProvider.js +3 -2
  69. package/src/providers/ServiceProvider.js +40 -8
  70. package/src/router/Router.js +121 -222
  71. package/src/scaffold/maker.js +24 -59
  72. package/src/scaffold/templates.js +21 -19
  73. package/src/validation/BaseValidator.js +193 -0
  74. package/src/validation/Validator.js +680 -0
@@ -0,0 +1,193 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * BaseValidator
5
+ *
6
+ * Foundation class for all field validators.
7
+ * Every validator extends this and adds its own type-specific rules.
8
+ *
9
+ * All methods return `this` for chaining, and accept an optional
10
+ * custom error message as their last argument.
11
+ */
12
+ class BaseValidator {
13
+ /**
14
+ * @param {string} [typeError] — message shown when the value fails the base type check
15
+ */
16
+ constructor(typeError) {
17
+ this._typeError = typeError || null;
18
+ this._required = false;
19
+ this._requiredMsg = null;
20
+ this._nullable = false;
21
+ this._defaultValue = undefined;
22
+ this._customFns = []; // [{ fn: async (value, data) => string|null }]
23
+ this._rules = []; // [{ check: fn, message: string }] — added by subclasses
24
+ this._label = null; // field name, set by Validator before running
25
+ }
26
+
27
+ // ─── Common modifiers ──────────────────────────────────────────────────────
28
+
29
+ /**
30
+ * Mark the field as required — fails if value is absent, null, or empty string.
31
+ * string().required()
32
+ * string().required('Name is required')
33
+ */
34
+ required(msg) {
35
+ this._required = true;
36
+ this._requiredMsg = msg || null;
37
+ return this;
38
+ }
39
+
40
+ /**
41
+ * Mark the field as optional (default). Skips all other rules if absent.
42
+ * string().optional()
43
+ */
44
+ optional() {
45
+ this._required = false;
46
+ return this;
47
+ }
48
+
49
+ /**
50
+ * Allow null as a valid value (passes even when null).
51
+ */
52
+ nullable() {
53
+ this._nullable = true;
54
+ return this;
55
+ }
56
+
57
+ /**
58
+ * Set a default value used when the field is absent.
59
+ * string().optional().default('guest')
60
+ * number().optional().default(0)
61
+ */
62
+ default(value) {
63
+ this._defaultValue = value;
64
+ return this;
65
+ }
66
+
67
+ /**
68
+ * Add a custom validation function.
69
+ * Return a string (the error message) to fail, or null/undefined to pass.
70
+ *
71
+ * string().custom(async (value, allData) => {
72
+ * const exists = await User.where('email', value).exists();
73
+ * if (exists) return 'Email is already taken';
74
+ * })
75
+ */
76
+ custom(fn) {
77
+ this._customFns.push(fn);
78
+ return this;
79
+ }
80
+
81
+ /**
82
+ * Set the human-readable label used in default error messages.
83
+ * Automatically set by Validator from the field key.
84
+ * string().label('Email address')
85
+ */
86
+ label(name) {
87
+ this._label = name;
88
+ return this;
89
+ }
90
+
91
+ // ─── Internal ──────────────────────────────────────────────────────────────
92
+
93
+ /**
94
+ * Human-readable field name for error messages.
95
+ */
96
+ _fieldLabel(key) {
97
+ return this._label || _titleCase(key);
98
+ }
99
+
100
+ /**
101
+ * Returns true if the value is considered "empty" for required checking.
102
+ */
103
+ _isEmpty(value) {
104
+ return value === undefined || value === null || value === '';
105
+ }
106
+
107
+ /**
108
+ * Add a rule to the internal rule list (used by subclasses).
109
+ * @param {Function} check — (value) => boolean (true = valid)
110
+ * @param {string} message — error message if check fails
111
+ */
112
+ _addRule(check, message) {
113
+ this._rules.push({ check, message });
114
+ return this;
115
+ }
116
+
117
+ /**
118
+ * Type check — subclasses override to validate the base type.
119
+ * Returns an error string if invalid, null if valid.
120
+ *
121
+ * @param {*} value
122
+ * @param {string} key — field name
123
+ * @returns {string|null}
124
+ */
125
+ _checkType(value, key) {
126
+ return null; // base has no type restriction
127
+ }
128
+
129
+ /**
130
+ * Run the full validation for this field.
131
+ *
132
+ * @param {*} value — the raw input value
133
+ * @param {string} key — field name (for error messages)
134
+ * @param {object} allData — entire request data (for cross-field rules)
135
+ * @returns {Promise<{ error: string|null, value: * }>}
136
+ */
137
+ async run(value, key, allData = {}) {
138
+ const label = this._fieldLabel(key);
139
+
140
+ // ── Apply default ───────────────────────────────────────────────────────
141
+ if (this._isEmpty(value) && this._defaultValue !== undefined) {
142
+ value = typeof this._defaultValue === 'function'
143
+ ? this._defaultValue()
144
+ : this._defaultValue;
145
+ }
146
+
147
+ // ── Null check ──────────────────────────────────────────────────────────
148
+ if (value === null && this._nullable) {
149
+ return { error: null, value: null };
150
+ }
151
+
152
+ // ── Required check ──────────────────────────────────────────────────────
153
+ if (this._isEmpty(value)) {
154
+ if (this._required) {
155
+ return {
156
+ error: this._requiredMsg || `${label} is required`,
157
+ value,
158
+ };
159
+ }
160
+ // Optional and empty — skip all other rules
161
+ return { error: null, value };
162
+ }
163
+
164
+ // ── Type check ──────────────────────────────────────────────────────────
165
+ const typeErr = this._checkType(value, key);
166
+ if (typeErr) {
167
+ return { error: this._typeError || typeErr, value };
168
+ }
169
+
170
+ // ── Field-specific rules ─────────────────────────────────────────────────
171
+ for (const { check, message } of this._rules) {
172
+ if (!check(value, allData)) {
173
+ return { error: message, value };
174
+ }
175
+ }
176
+
177
+ // ── Custom functions ─────────────────────────────────────────────────────
178
+ for (const fn of this._customFns) {
179
+ const result = await fn(value, allData);
180
+ if (result) return { error: result, value };
181
+ }
182
+
183
+ return { error: null, value };
184
+ }
185
+ }
186
+
187
+ function _titleCase(str) {
188
+ return String(str)
189
+ .replace(/_/g, ' ')
190
+ .replace(/\b\w/g, c => c.toUpperCase());
191
+ }
192
+
193
+ module.exports = { BaseValidator, _titleCase };