@veloxts/velox 0.7.0 → 0.7.2

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/CHANGELOG.md CHANGED
@@ -1,6 +1,42 @@
1
1
  # @veloxts/velox
2
2
 
3
- ## 1.0.0
3
+ ## 0.7.2
4
+
5
+ ### Patch Changes
6
+
7
+ - chore(auth,core,create,cli,client,orm,mcp,router,validation,web): simplify code for clarity and maintainability
8
+ - Updated dependencies
9
+ - @veloxts/auth@0.7.2
10
+ - @veloxts/cache@0.7.2
11
+ - @veloxts/core@0.7.2
12
+ - @veloxts/events@0.7.2
13
+ - @veloxts/mail@0.7.2
14
+ - @veloxts/orm@0.7.2
15
+ - @veloxts/queue@0.7.2
16
+ - @veloxts/router@0.7.2
17
+ - @veloxts/scheduler@0.7.2
18
+ - @veloxts/storage@0.7.2
19
+ - @veloxts/validation@0.7.2
20
+
21
+ ## 0.7.1
22
+
23
+ ### Patch Changes
24
+
25
+ - security audit, bumps dependency packages
26
+ - Updated dependencies
27
+ - @veloxts/auth@0.7.1
28
+ - @veloxts/cache@0.7.1
29
+ - @veloxts/core@0.7.1
30
+ - @veloxts/events@0.7.1
31
+ - @veloxts/mail@0.7.1
32
+ - @veloxts/orm@0.7.1
33
+ - @veloxts/queue@0.7.1
34
+ - @veloxts/router@0.7.1
35
+ - @veloxts/scheduler@0.7.1
36
+ - @veloxts/storage@0.7.1
37
+ - @veloxts/validation@0.7.1
38
+
39
+ ## 0.7.0
4
40
 
5
41
  ### Minor Changes
6
42
 
@@ -160,77 +160,32 @@ const productionAuthPreset = {
160
160
  },
161
161
  };
162
162
  /**
163
- * Create production preset with validated environment variables.
163
+ * Build a production preset from environment variable values.
164
+ * Accepts either validated or raw values.
164
165
  */
165
- function createProductionPreset(env) {
166
+ function buildProductionPreset(vars) {
166
167
  return {
167
168
  cache: {
168
169
  driver: 'redis',
169
- config: {
170
- url: env.REDIS_URL,
171
- },
170
+ config: { url: vars.REDIS_URL },
172
171
  },
173
172
  queue: {
174
173
  driver: 'bullmq',
175
- config: {
176
- url: env.REDIS_URL,
177
- },
174
+ config: { url: vars.REDIS_URL },
178
175
  },
179
176
  mail: {
180
177
  driver: 'resend',
181
- config: {
182
- apiKey: env.RESEND_API_KEY,
183
- },
178
+ config: { apiKey: vars.RESEND_API_KEY },
184
179
  },
185
180
  storage: {
186
181
  driver: 's3',
187
- bucket: env.S3_BUCKET,
188
- region: env.AWS_REGION,
182
+ bucket: vars.S3_BUCKET,
183
+ region: vars.AWS_REGION,
189
184
  },
190
185
  events: {
191
186
  driver: 'ws',
192
187
  path: '/ws',
193
- redis: env.REDIS_URL,
194
- },
195
- scheduler: {
196
- tasks: [],
197
- },
198
- auth: productionAuthPreset,
199
- };
200
- }
201
- /**
202
- * Create production preset with current environment variables (unvalidated).
203
- * Used for the module-level export. Prefer getPreset('production') which validates.
204
- */
205
- function createProductionPresetFromEnv() {
206
- return {
207
- cache: {
208
- driver: 'redis',
209
- config: {
210
- url: process.env.REDIS_URL,
211
- },
212
- },
213
- queue: {
214
- driver: 'bullmq',
215
- config: {
216
- url: process.env.REDIS_URL,
217
- },
218
- },
219
- mail: {
220
- driver: 'resend',
221
- config: {
222
- apiKey: process.env.RESEND_API_KEY ?? '',
223
- },
224
- },
225
- storage: {
226
- driver: 's3',
227
- bucket: process.env.S3_BUCKET ?? '',
228
- region: process.env.AWS_REGION ?? 'us-east-1',
229
- },
230
- events: {
231
- driver: 'ws',
232
- path: '/ws',
233
- redis: process.env.REDIS_URL,
188
+ redis: vars.REDIS_URL,
234
189
  },
235
190
  scheduler: {
236
191
  tasks: [],
@@ -254,7 +209,12 @@ function createProductionPresetFromEnv() {
254
209
  *
255
210
  * @see validateProductionEnv() to check if all required vars are set
256
211
  */
257
- export const productionPreset = createProductionPresetFromEnv();
212
+ export const productionPreset = buildProductionPreset({
213
+ REDIS_URL: process.env.REDIS_URL,
214
+ RESEND_API_KEY: process.env.RESEND_API_KEY ?? '',
215
+ S3_BUCKET: process.env.S3_BUCKET ?? '',
216
+ AWS_REGION: process.env.AWS_REGION ?? 'us-east-1',
217
+ });
258
218
  /**
259
219
  * Get preset configuration for an environment.
260
220
  * For production, validates required environment variables first.
@@ -267,11 +227,8 @@ export function getPreset(env) {
267
227
  return developmentPreset;
268
228
  case 'test':
269
229
  return testPreset;
270
- case 'production': {
271
- const env = validateProductionEnv();
272
- // Return fresh preset to pick up env vars set after module load
273
- return createProductionPreset(env);
274
- }
230
+ case 'production':
231
+ return buildProductionPreset(validateProductionEnv());
275
232
  }
276
233
  }
277
234
  /**
@@ -2,23 +2,32 @@
2
2
  * Environment detection utilities.
3
3
  */
4
4
  /**
5
- * Detect current environment from NODE_ENV.
6
- * Defaults to 'development' if not set or unrecognized.
5
+ * Normalize a raw environment string to a recognized Environment value.
6
+ * Returns undefined if the value is not recognized.
7
7
  */
8
- export function detectEnvironment() {
9
- const env = process.env.NODE_ENV?.toLowerCase().trim();
10
- switch (env) {
8
+ function normalizeEnvironment(value) {
9
+ const normalized = value?.toLowerCase().trim();
10
+ switch (normalized) {
11
11
  case 'production':
12
12
  case 'prod':
13
13
  return 'production';
14
14
  case 'test':
15
15
  case 'testing':
16
16
  return 'test';
17
- default:
18
- // 'development', 'dev', undefined, or any unrecognized value
17
+ case 'development':
18
+ case 'dev':
19
19
  return 'development';
20
+ default:
21
+ return undefined;
20
22
  }
21
23
  }
24
+ /**
25
+ * Detect current environment from NODE_ENV.
26
+ * Defaults to 'development' if not set or unrecognized.
27
+ */
28
+ export function detectEnvironment() {
29
+ return normalizeEnvironment(process.env.NODE_ENV) ?? 'development';
30
+ }
22
31
  /**
23
32
  * Check if current environment is development.
24
33
  */
@@ -42,15 +51,9 @@ export function isTest() {
42
51
  * @throws Error if environment is not recognized.
43
52
  */
44
53
  export function validateEnvironment(env) {
45
- const normalized = env.toLowerCase().trim();
46
- if (normalized === 'production' || normalized === 'prod') {
47
- return 'production';
48
- }
49
- if (normalized === 'test' || normalized === 'testing') {
50
- return 'test';
51
- }
52
- if (normalized === 'development' || normalized === 'dev') {
53
- return 'development';
54
+ const result = normalizeEnvironment(env);
55
+ if (!result) {
56
+ throw new Error(`Invalid environment: "${env}". Must be one of: development, test, production`);
54
57
  }
55
- throw new Error(`Invalid environment: "${env}". Must be one of: development, test, production`);
58
+ return result;
56
59
  }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Preset plugin for automatic ecosystem package registration.
3
3
  */
4
- import type { VeloxApp } from '@veloxts/core';
4
+ import { type VeloxApp } from '@veloxts/core';
5
5
  import type { AuthPreset, EcosystemPreset, Environment, PresetOptions } from './types.js';
6
6
  /**
7
7
  * Register ecosystem plugins based on preset configuration.
@@ -1,55 +1,33 @@
1
1
  /**
2
2
  * Preset plugin for automatic ecosystem package registration.
3
3
  */
4
+ import { createLogger } from '@veloxts/core';
4
5
  import { getPreset } from './defaults.js';
5
6
  import { detectEnvironment } from './env.js';
6
7
  import { mergeDeep } from './merge.js';
8
+ const log = createLogger('velox');
9
+ /**
10
+ * Extract the driver name from a package config object.
11
+ */
12
+ function getDriver(config, defaultDriver) {
13
+ if (config !== null && typeof config === 'object' && 'driver' in config) {
14
+ const driver = config.driver;
15
+ if (typeof driver === 'string')
16
+ return driver;
17
+ }
18
+ return defaultDriver;
19
+ }
7
20
  /**
8
21
  * All ecosystem packages that can be registered.
9
22
  */
10
23
  const PACKAGES = {
11
- cache: {
12
- name: '@veloxts/cache',
13
- importPath: '@veloxts/cache',
14
- pluginExport: 'cachePlugin',
15
- getDriver: (c) => c?.driver ?? 'memory',
16
- },
17
- queue: {
18
- name: '@veloxts/queue',
19
- importPath: '@veloxts/queue',
20
- pluginExport: 'queuePlugin',
21
- getDriver: (c) => c?.driver ?? 'sync',
22
- },
23
- mail: {
24
- name: '@veloxts/mail',
25
- importPath: '@veloxts/mail',
26
- pluginExport: 'mailPlugin',
27
- getDriver: (c) => c?.driver ?? 'log',
28
- },
29
- storage: {
30
- name: '@veloxts/storage',
31
- importPath: '@veloxts/storage',
32
- pluginExport: 'storagePlugin',
33
- getDriver: (c) => c?.driver ?? 'local',
34
- },
35
- events: {
36
- name: '@veloxts/events',
37
- importPath: '@veloxts/events',
38
- pluginExport: 'eventsPlugin',
39
- getDriver: (c) => c?.driver ?? 'ws',
40
- },
41
- scheduler: {
42
- name: '@veloxts/scheduler',
43
- importPath: '@veloxts/scheduler',
44
- pluginExport: 'schedulerPlugin',
45
- getDriver: () => 'cron',
46
- },
47
- auth: {
48
- name: '@veloxts/auth',
49
- importPath: '@veloxts/auth',
50
- pluginExport: 'authPlugin',
51
- getDriver: () => 'jwt',
52
- },
24
+ cache: { name: '@veloxts/cache', pluginExport: 'cachePlugin', defaultDriver: 'memory' },
25
+ queue: { name: '@veloxts/queue', pluginExport: 'queuePlugin', defaultDriver: 'sync' },
26
+ mail: { name: '@veloxts/mail', pluginExport: 'mailPlugin', defaultDriver: 'log' },
27
+ storage: { name: '@veloxts/storage', pluginExport: 'storagePlugin', defaultDriver: 'local' },
28
+ events: { name: '@veloxts/events', pluginExport: 'eventsPlugin', defaultDriver: 'ws' },
29
+ scheduler: { name: '@veloxts/scheduler', pluginExport: 'schedulerPlugin', defaultDriver: 'cron' },
30
+ auth: { name: '@veloxts/auth', pluginExport: 'authPlugin', defaultDriver: 'jwt' },
53
31
  };
54
32
  /**
55
33
  * Packages that require special handling and are NOT auto-registered.
@@ -89,20 +67,18 @@ export async function registerEcosystemPlugins(app, preset, options) {
89
67
  const info = PACKAGES[pkg];
90
68
  try {
91
69
  // Dynamic import to avoid hard dependency
92
- const module = await import(info.importPath);
70
+ const module = await import(info.name);
93
71
  const plugin = module[info.pluginExport];
94
72
  if (!plugin) {
95
73
  throw new Error(`Plugin export '${info.pluginExport}' not found`);
96
74
  }
97
75
  await app.register(plugin(config));
98
76
  if (!options?.silent) {
99
- const driver = info.getDriver(config);
100
- console.log(` ✓ ${info.name} [${driver}]`);
77
+ log.info(` ✓ ${info.name} [${getDriver(config, info.defaultDriver)}]`);
101
78
  }
102
79
  }
103
80
  catch (error) {
104
81
  const err = error;
105
- // Check if it's a module not found error
106
82
  if (err.message?.includes('Cannot find module') || err.code === 'ERR_MODULE_NOT_FOUND') {
107
83
  throw new Error(`Package ${info.name} is not installed. Install it with: pnpm add ${info.name}`);
108
84
  }
@@ -143,31 +119,24 @@ export async function registerEcosystemPlugins(app, preset, options) {
143
119
  export async function usePresets(app, options = {}) {
144
120
  const env = options.env ?? detectEnvironment();
145
121
  const basePreset = getPreset(env);
146
- // Merge overrides with base preset using type-safe helper
147
- // Partial<T> is assignable to DeepPartial<T> for single-level overrides
148
- const merge = (base, override) => {
149
- if (!base)
150
- return undefined;
151
- if (!override)
152
- return base;
153
- // Partial<T> is compatible with DeepPartial<T> at the first level
154
- return mergeDeep(base, override);
155
- };
156
- const finalPreset = {
157
- cache: merge(basePreset.cache, options.overrides?.cache),
158
- queue: merge(basePreset.queue, options.overrides?.queue),
159
- mail: merge(basePreset.mail, options.overrides?.mail),
160
- storage: merge(basePreset.storage, options.overrides?.storage),
161
- events: merge(basePreset.events, options.overrides?.events),
162
- scheduler: merge(basePreset.scheduler, options.overrides?.scheduler),
163
- auth: merge(basePreset.auth, options.overrides?.auth),
164
- };
122
+ // Merge each package's overrides with its base preset
123
+ const finalPreset = { ...basePreset };
124
+ if (options.overrides) {
125
+ for (const key of Object.keys(options.overrides)) {
126
+ const base = basePreset[key];
127
+ const override = options.overrides[key];
128
+ if (base && override) {
129
+ // Partial<T> is compatible with DeepPartial<T> at the first level
130
+ finalPreset[key] = mergeDeep(base, override);
131
+ }
132
+ }
133
+ }
165
134
  if (!options.silent) {
166
- console.log(`\n📦 VeloxTS Ecosystem Presets [${env}]`);
135
+ log.info(`\nVeloxTS Ecosystem Presets [${env}]`);
167
136
  }
168
137
  await registerEcosystemPlugins(app, finalPreset, options);
169
138
  if (!options.silent) {
170
- console.log('');
139
+ log.info('');
171
140
  }
172
141
  }
173
142
  /**
@@ -24,13 +24,9 @@ function isValidLogLevel(value) {
24
24
  * @param defaultLevel - Fallback level if value is invalid
25
25
  */
26
26
  function parseLogLevel(value, defaultLevel) {
27
- if (value === undefined) {
28
- return defaultLevel;
29
- }
30
27
  if (isValidLogLevel(value)) {
31
28
  return value;
32
29
  }
33
- // Invalid log level - return default
34
30
  return defaultLevel;
35
31
  }
36
32
  /**
@@ -41,14 +37,11 @@ function parseLogLevel(value, defaultLevel) {
41
37
  * @param defaultPort - Fallback port if value is invalid
42
38
  */
43
39
  function parsePort(value, defaultPort) {
44
- if (value === undefined) {
40
+ if (value === undefined)
45
41
  return defaultPort;
46
- }
47
42
  const parsed = parseInt(value, 10);
48
- // Check for NaN and ensure port is in valid range (1-65535)
49
- if (Number.isNaN(parsed) || parsed < 1 || parsed > 65535) {
43
+ if (Number.isNaN(parsed) || parsed < 1 || parsed > 65535)
50
44
  return defaultPort;
51
- }
52
45
  return parsed;
53
46
  }
54
47
  /**
@@ -4,7 +4,9 @@
4
4
  * Validates that required environment variables, secrets, and security
5
5
  * settings are properly configured before the application starts.
6
6
  */
7
+ import { createLogger } from '@veloxts/core';
7
8
  import { detectEnvironment } from './env.js';
9
+ const log = createLogger('velox');
8
10
  /**
9
11
  * Default security requirements for production.
10
12
  */
@@ -130,36 +132,29 @@ export function validateSecurityOrThrow(requirements) {
130
132
  }
131
133
  const result = validateSecurity(requirements);
132
134
  if (!result.valid) {
133
- const errorLines = result.errors.map((e) => {
134
- let line = ` [${e.category}] ${e.key}: ${e.message}`;
135
- if (e.suggestion) {
136
- line += `\n Suggestion: ${e.suggestion}`;
135
+ const formatIssue = (issue) => {
136
+ let line = ` [${issue.category}] ${issue.key}: ${issue.message}`;
137
+ if (issue.suggestion) {
138
+ line += `\n Suggestion: ${issue.suggestion}`;
137
139
  }
138
140
  return line;
139
- });
140
- const warningLines = result.warnings.map((w) => {
141
- let line = ` [${w.category}] ${w.key}: ${w.message}`;
142
- if (w.suggestion) {
143
- line += `\n Suggestion: ${w.suggestion}`;
144
- }
145
- return line;
146
- });
147
- let message = `Production security validation failed:\n\n${errorLines.join('\n\n')}`;
148
- if (warningLines.length > 0) {
149
- message += `\n\nWarnings:\n${warningLines.join('\n\n')}`;
141
+ };
142
+ let message = `Production security validation failed:\n\n${result.errors.map(formatIssue).join('\n\n')}`;
143
+ if (result.warnings.length > 0) {
144
+ message += `\n\nWarnings:\n${result.warnings.map(formatIssue).join('\n\n')}`;
150
145
  }
151
146
  throw new Error(message);
152
147
  }
153
148
  // Log warnings even if validation passes
154
149
  if (result.warnings.length > 0) {
155
- console.warn('\nSecurity warnings:');
150
+ log.warn('\nSecurity warnings:');
156
151
  for (const warning of result.warnings) {
157
- console.warn(` [${warning.category}] ${warning.key}: ${warning.message}`);
152
+ log.warn(` [${warning.category}] ${warning.key}: ${warning.message}`);
158
153
  if (warning.suggestion) {
159
- console.warn(` Suggestion: ${warning.suggestion}`);
154
+ log.warn(` Suggestion: ${warning.suggestion}`);
160
155
  }
161
156
  }
162
- console.warn('');
157
+ log.warn('');
163
158
  }
164
159
  }
165
160
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veloxts/velox",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
4
4
  "description": "Complete VeloxTS framework - batteries included",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -39,30 +39,30 @@
39
39
  "CHANGELOG.md"
40
40
  ],
41
41
  "dependencies": {
42
- "@veloxts/router": "0.7.0",
43
- "@veloxts/core": "0.7.0",
44
- "@veloxts/orm": "0.7.0",
45
- "@veloxts/validation": "0.7.0",
46
- "@veloxts/auth": "0.7.0"
42
+ "@veloxts/core": "0.7.2",
43
+ "@veloxts/validation": "0.7.2",
44
+ "@veloxts/router": "0.7.2",
45
+ "@veloxts/orm": "0.7.2",
46
+ "@veloxts/auth": "0.7.2"
47
47
  },
48
48
  "devDependencies": {
49
49
  "typescript": "5.9.3",
50
50
  "vitest": "4.0.18",
51
- "@veloxts/cache": "0.7.0",
52
- "@veloxts/events": "0.7.0",
53
- "@veloxts/mail": "0.7.0",
54
- "@veloxts/queue": "0.7.0",
55
- "@veloxts/scheduler": "0.7.0",
56
- "@veloxts/storage": "0.7.0"
51
+ "@veloxts/events": "0.7.2",
52
+ "@veloxts/queue": "0.7.2",
53
+ "@veloxts/scheduler": "0.7.2",
54
+ "@veloxts/storage": "0.7.2",
55
+ "@veloxts/cache": "0.7.2",
56
+ "@veloxts/mail": "0.7.2"
57
57
  },
58
58
  "peerDependencies": {
59
59
  "zod": "^4.3.0",
60
- "@veloxts/queue": "0.7.0",
61
- "@veloxts/mail": "0.7.0",
62
- "@veloxts/cache": "0.7.0",
63
- "@veloxts/storage": "0.7.0",
64
- "@veloxts/scheduler": "0.7.0",
65
- "@veloxts/events": "0.7.0"
60
+ "@veloxts/cache": "0.7.2",
61
+ "@veloxts/queue": "0.7.2",
62
+ "@veloxts/storage": "0.7.2",
63
+ "@veloxts/mail": "0.7.2",
64
+ "@veloxts/events": "0.7.2",
65
+ "@veloxts/scheduler": "0.7.2"
66
66
  },
67
67
  "peerDependenciesMeta": {
68
68
  "@veloxts/cache": {