fragment-ts 1.0.43 โ†’ 1.0.45

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 (55) hide show
  1. package/dist/cli/commands/diagnostics.command.d.ts.map +1 -1
  2. package/dist/cli/commands/diagnostics.command.js +17 -73
  3. package/dist/cli/commands/diagnostics.command.js.map +1 -1
  4. package/dist/cli/commands/env.command.d.ts +10 -0
  5. package/dist/cli/commands/env.command.d.ts.map +1 -0
  6. package/dist/cli/commands/env.command.js +222 -0
  7. package/dist/cli/commands/env.command.js.map +1 -0
  8. package/dist/cli/commands/generate.command.js +9 -9
  9. package/dist/cli/commands/init.command.d.ts.map +1 -1
  10. package/dist/cli/commands/init.command.js +65 -35
  11. package/dist/cli/commands/init.command.js.map +1 -1
  12. package/dist/cli/commands/migrate.command.d.ts +14 -41
  13. package/dist/cli/commands/migrate.command.d.ts.map +1 -1
  14. package/dist/cli/commands/migrate.command.js +182 -424
  15. package/dist/cli/commands/migrate.command.js.map +1 -1
  16. package/dist/cli/commands/test.command.d.ts.map +1 -1
  17. package/dist/cli/commands/test.command.js +5 -51
  18. package/dist/cli/commands/test.command.js.map +1 -1
  19. package/dist/cli/index.js +50 -0
  20. package/dist/cli/index.js.map +1 -1
  21. package/dist/core/scanner/component-scanner.d.ts +0 -4
  22. package/dist/core/scanner/component-scanner.d.ts.map +1 -1
  23. package/dist/core/scanner/component-scanner.js +0 -15
  24. package/dist/core/scanner/component-scanner.js.map +1 -1
  25. package/dist/shared/config.utils.d.ts +0 -27
  26. package/dist/shared/config.utils.d.ts.map +1 -1
  27. package/dist/shared/config.utils.js +7 -38
  28. package/dist/shared/config.utils.js.map +1 -1
  29. package/dist/shared/env.utils.d.ts +6 -18
  30. package/dist/shared/env.utils.d.ts.map +1 -1
  31. package/dist/shared/env.utils.js +84 -39
  32. package/dist/shared/env.utils.js.map +1 -1
  33. package/dist/testing/runner.d.ts.map +1 -1
  34. package/dist/testing/runner.js +2 -12
  35. package/dist/testing/runner.js.map +1 -1
  36. package/dist/typeorm/typeorm-module.d.ts.map +1 -1
  37. package/dist/typeorm/typeorm-module.js +4 -16
  38. package/dist/typeorm/typeorm-module.js.map +1 -1
  39. package/dist/web/application.d.ts.map +1 -1
  40. package/dist/web/application.js +1 -20
  41. package/dist/web/application.js.map +1 -1
  42. package/package.json +2 -1
  43. package/src/cli/commands/diagnostics.command.ts +16 -87
  44. package/src/cli/commands/env.command.ts +224 -0
  45. package/src/cli/commands/generate.command.ts +9 -9
  46. package/src/cli/commands/init.command.ts +68 -37
  47. package/src/cli/commands/migrate.command.ts +244 -528
  48. package/src/cli/commands/test.command.ts +5 -61
  49. package/src/cli/index.ts +21 -0
  50. package/src/core/scanner/component-scanner.ts +0 -15
  51. package/src/shared/config.utils.ts +10 -54
  52. package/src/shared/env.utils.ts +50 -44
  53. package/src/testing/runner.ts +2 -11
  54. package/src/typeorm/typeorm-module.ts +5 -14
  55. package/src/web/application.ts +1 -21
@@ -13,11 +13,6 @@ export class TestCommand {
13
13
  .command("test")
14
14
  .description("Run tests")
15
15
  .option("--watch", "Run tests in watch mode")
16
- .option(
17
- "--env <environment>",
18
- "Environment mode: dev (use src/) or prod (use dist/)",
19
- "auto",
20
- )
21
16
  .option("--pattern <pattern>", "Test file pattern", "**/*.spec.ts")
22
17
  .option("--coverage", "Generate coverage report")
23
18
  .option("--no-color", "Disable colored output")
@@ -28,78 +23,27 @@ export class TestCommand {
28
23
 
29
24
  private static async runTests(options: any): Promise<void> {
30
25
  console.log(chalk.blue("\n๐Ÿงช Running Fragment Tests...\n"));
31
-
32
26
  const cwd = process.cwd();
33
-
34
- // Use EnvUtils for consistent environment detection
35
- const isDevMode = EnvUtils.isDevelopmentMode();
36
27
  const hasSource = fs.existsSync(path.join(cwd, "src"));
37
28
  const hasDist = fs.existsSync(path.join(cwd, "dist"));
38
29
 
39
30
  let useTypeScript: boolean;
40
- let mode: string;
41
31
  let basePath: string;
42
32
  let pattern: string;
43
33
 
44
- if (options.env === "dev") {
45
- if (!hasSource) {
46
- console.log(
47
- chalk.red("Development mode requested but src/ directory not found"),
48
- );
49
- return;
50
- }
34
+ if (hasSource) {
51
35
  useTypeScript = true;
52
- mode = "development (src/)";
53
36
  basePath = "src";
54
37
  pattern = options.pattern || "**/*.spec.ts";
55
- } else if (options.env === "prod") {
56
- if (!hasDist) {
57
- console.log(
58
- chalk.red(
59
- "Production mode requested but dist/ directory not found. Run: fragment build",
60
- ),
61
- );
62
- return;
63
- }
38
+ } else if (hasDist) {
64
39
  useTypeScript = false;
65
- mode = "production (dist/)";
66
40
  basePath = "dist";
67
- pattern = options.pattern.replace(/\.ts$/, ".js") || "**/*.spec.js";
41
+ pattern = (options.pattern || "**/*.spec.ts").replace(/\.ts$/, ".js");
68
42
  } else {
69
- // Auto-detect using same logic as EnvUtils
70
- if (isDevMode && hasSource) {
71
- useTypeScript = true;
72
- mode = "auto-detected development (src/)";
73
- basePath = "src";
74
- pattern = options.pattern || "**/*.spec.ts";
75
- } else if (!isDevMode && hasDist) {
76
- useTypeScript = false;
77
- mode = "auto-detected production (dist/)";
78
- basePath = "dist";
79
- pattern = options.pattern.replace(/\.ts$/, ".js") || "**/*.spec.js";
80
- } else if (hasSource) {
81
- // Fallback to source if available
82
- useTypeScript = true;
83
- mode = "auto-detected development (src/)";
84
- basePath = "src";
85
- pattern = options.pattern || "**/*.spec.ts";
86
- } else if (hasDist) {
87
- // Fallback to dist if available
88
- useTypeScript = false;
89
- mode = "auto-detected production (dist/)";
90
- basePath = "dist";
91
- pattern = options.pattern.replace(/\.ts$/, ".js") || "**/*.spec.js";
92
- } else {
93
- console.log(
94
- chalk.red("No src/ or dist/ directory found. Run: fragment init"),
95
- );
96
- return;
97
- }
43
+ console.log(chalk.red("No src/ or dist/ found. Run: fragment init"));
44
+ return;
98
45
  }
99
46
 
100
- console.log(chalk.gray(` Mode: ${mode}`));
101
- console.log(chalk.gray(` Pattern: ${basePath}/${pattern}`));
102
-
103
47
  // Check if we need to use ts-node for TypeScript files
104
48
  const hasTsConfig = TsConfigUtils.exists();
105
49
 
package/src/cli/index.ts CHANGED
@@ -1,4 +1,24 @@
1
+ import * as dotenv from "dotenv";
2
+ import * as fs from "fs";
3
+ import * as path from "path";
4
+
5
+ const cwd = process.cwd();
6
+
7
+ // Order: lowest priority โ†’ highest priority
8
+ const envFiles = [
9
+ ".env", // base
10
+ ".env.local", // gitignored local overrides
11
+ ".env.prod", // production (or use .env.staging, etc.)
12
+ ]
13
+ .map((file) => path.join(cwd, file))
14
+ .filter(fs.existsSync);
15
+
16
+ envFiles.forEach((file) => {
17
+ dotenv.config({ path: file });
18
+ });
19
+
1
20
  import { Command } from "commander";
21
+ import { EnvCommand } from "./commands/env.command";
2
22
  import { InitCommand } from "./commands/init.command";
3
23
  import { GenerateCommand } from "./commands/generate.command";
4
24
  import { ServeCommand } from "./commands/serve.command";
@@ -17,6 +37,7 @@ program
17
37
  .version("1.0.0");
18
38
 
19
39
  // Register all commands
40
+ EnvCommand.register(program);
20
41
  InitCommand.register(program);
21
42
  GenerateCommand.register(program);
22
43
  ServeCommand.register(program);
@@ -196,19 +196,4 @@ export class ComponentScanner {
196
196
  }
197
197
  }
198
198
  }
199
-
200
- /**
201
- * Auto-scan based on current environment mode
202
- */
203
- static async autoScan(): Promise<void> {
204
- // Detect environment using the same logic as other components
205
- const isDevMode = EnvUtils.isDevelopmentMode();;
206
-
207
- if (isDevMode) {
208
- await this.scanSource();
209
- } else {
210
- await this.scan();
211
- }
212
- }
213
-
214
199
  }
@@ -1,8 +1,9 @@
1
+ // shared/config.utils.ts
2
+
1
3
  import * as fs from "fs";
2
4
  import * as path from "path";
3
5
  import { EnvUtils } from "./env.utils";
4
6
 
5
- // Define the fragment.json structure
6
7
  interface FragmentDatabaseConfig {
7
8
  type?: string;
8
9
  host?: string;
@@ -17,33 +18,21 @@ interface FragmentDatabaseConfig {
17
18
  subscribers?: string[];
18
19
  pool?: any;
19
20
  maxQueryExecutionTime?: number;
20
- [key: string]: any; // Allow additional database-specific properties
21
+ [key: string]: any;
21
22
  }
22
23
 
24
+ // Only support flat structure now
23
25
  interface FragmentConfig {
24
- development?: {
25
- database?: FragmentDatabaseConfig;
26
- };
27
- production?: {
28
- database?: FragmentDatabaseConfig;
29
- };
30
- // Legacy flat structure (for backward compatibility)
31
26
  database?: FragmentDatabaseConfig;
32
27
  }
33
28
 
34
29
  export class ConfigUtils {
35
30
  private static configCache: FragmentConfig | null = null;
36
31
 
37
- /**
38
- * Load and parse fragment.json with caching
39
- */
40
32
  private static loadConfig(): FragmentConfig {
41
- if (this.configCache) {
42
- return this.configCache;
43
- }
33
+ if (this.configCache) return this.configCache;
44
34
 
45
35
  const configPath = path.join(process.cwd(), "fragment.json");
46
-
47
36
  if (!fs.existsSync(configPath)) {
48
37
  this.configCache = {};
49
38
  return this.configCache;
@@ -51,10 +40,9 @@ export class ConfigUtils {
51
40
 
52
41
  try {
53
42
  const raw = fs.readFileSync(configPath, "utf-8");
54
- this.configCache = JSON.parse(raw);
55
-
43
+ this.configCache = JSON.parse(raw) || {};
56
44
  if (!this.configCache) {
57
- this.configCache = {};
45
+ return {};
58
46
  }
59
47
  return this.configCache;
60
48
  } catch (error) {
@@ -64,9 +52,6 @@ export class ConfigUtils {
64
52
  }
65
53
  }
66
54
 
67
- /**
68
- * Interpolate environment variables in config values
69
- */
70
55
  static interpolateEnvVars(value: any): any {
71
56
  if (typeof value === "string") {
72
57
  return value.replace(
@@ -89,32 +74,15 @@ export class ConfigUtils {
89
74
  return value;
90
75
  }
91
76
 
92
- /**
93
- * Get the current database configuration based on environment
94
- */
77
+ // Always return the single database config
95
78
  static getDatabaseConfig(): FragmentDatabaseConfig {
96
79
  const config = this.loadConfig();
97
- const mode = EnvUtils.getEnvironmentMode();
98
-
99
- // Try environment-specific config first
100
- if (config[mode]?.database) {
101
- const interpolated = this.interpolateEnvVars(config[mode].database);
102
- return interpolated;
103
- }
104
-
105
- // Fallback to legacy flat structure
106
80
  if (config.database) {
107
- const interpolated = this.interpolateEnvVars(config.database);
108
- return interpolated;
81
+ return this.interpolateEnvVars(config.database);
109
82
  }
110
-
111
- // Return empty config if none found
112
83
  return {};
113
84
  }
114
85
 
115
- /**
116
- * Get a specific database configuration property
117
- */
118
86
  static getDatabaseProperty<T>(property: string, defaultValue: T): T {
119
87
  const dbConfig = this.getDatabaseConfig();
120
88
  return (
@@ -122,26 +90,14 @@ export class ConfigUtils {
122
90
  ) as T;
123
91
  }
124
92
 
125
- /**
126
- * Get the full fragment configuration
127
- */
128
93
  static getFullConfig(): FragmentConfig {
129
94
  return this.loadConfig();
130
95
  }
131
96
 
132
- /**
133
- * Check if database feature is enabled
134
- */
135
97
  static isDatabaseEnabled(): boolean {
136
- const config = this.loadConfig();
137
- const mode = EnvUtils.getEnvironmentMode();
138
-
139
- return !!(config[mode]?.database || config.database);
98
+ return !!this.getFullConfig().database;
140
99
  }
141
100
 
142
- /**
143
- * Clear the configuration cache (useful for testing)
144
- */
145
101
  static clearCache(): void {
146
102
  this.configCache = null;
147
103
  }
@@ -2,71 +2,77 @@ import * as fs from "fs";
2
2
  import * as path from "path";
3
3
 
4
4
  export class EnvUtils {
5
- /**
6
- * Get a string environment variable with optional default
7
- */
8
5
  static getString(key: string, defaultValue?: string): string {
9
- const value = process.env[key];
10
- return value !== undefined ? value : (defaultValue ?? "");
6
+ return process.env[key] ?? defaultValue ?? "";
11
7
  }
12
8
 
13
- /**
14
- * Get a boolean environment variable (supports 'true'/'false', '1'/'0')
15
- */
16
- static getBoolean(key: string, defaultValue: boolean = false): boolean {
17
- const value = process.env[key];
18
- if (value === undefined) return defaultValue;
19
-
20
- return ["true", "1", "yes", "on"].includes(value.toLowerCase());
9
+ static getBoolean(key: string, defaultValue = false): boolean {
10
+ const val = process.env[key];
11
+ if (val === undefined) return defaultValue;
12
+ return ["true", "1", "yes", "on"].includes(val.toLowerCase());
21
13
  }
22
14
 
23
- /**
24
- * Get a number environment variable
25
- */
26
- static getNumber(key: string, defaultValue: number = 0): number {
27
- const value = process.env[key];
28
- if (value === undefined) return defaultValue;
29
-
30
- const num = Number(value);
15
+ static getNumber(key: string, defaultValue = 0): number {
16
+ const val = process.env[key];
17
+ if (val === undefined) return defaultValue;
18
+ const num = Number(val);
31
19
  return isNaN(num) ? defaultValue : num;
32
20
  }
33
21
 
34
- /**
35
- * Get a parsed JSON environment variable
36
- */
37
22
  static getJson<T>(key: string, defaultValue: T): T {
38
- const value = process.env[key];
39
- if (value === undefined) return defaultValue;
40
-
23
+ const val = process.env[key];
24
+ if (val === undefined) return defaultValue;
41
25
  try {
42
- return JSON.parse(value) as T;
26
+ return JSON.parse(val) as T;
43
27
  } catch {
44
- console.warn(`โš ๏ธ Invalid JSON in env var ${key}, using default`);
28
+ console.warn(`โš ๏ธ Invalid JSON in env var ${key}`);
45
29
  return defaultValue;
46
30
  }
47
31
  }
48
32
 
49
33
  /**
50
- * Check if running in development mode
34
+ * Returns the current environment name based on the active .env file.
35
+ * - If .env matches .env.prod โ†’ returns "prod"
36
+ * - If .env matches .env.staging โ†’ returns "staging"
37
+ * - If .env is custom or unmatched โ†’ returns "local"
38
+ * - If no .env exists โ†’ returns "default"
51
39
  */
52
- static isDevelopmentMode(): boolean {
53
- // Check explicit FRAGMENT_DEV_MODE
54
- if (process.env.FRAGMENT_DEV_MODE !== undefined) {
55
- return process.env.FRAGMENT_DEV_MODE === "true";
40
+ static getEnv(): string {
41
+ const cwd = process.cwd();
42
+ const envPath = path.join(cwd, ".env");
43
+
44
+ // Fast path: check for .env.mode (written by `fragment env:use`)
45
+ const modePath = path.join(cwd, ".env.mode");
46
+ if (fs.existsSync(modePath)) {
47
+ try {
48
+ const mode = fs.readFileSync(modePath, "utf8").trim();
49
+ if (mode) return mode;
50
+ } catch {
51
+ // Ignore read errors
52
+ }
56
53
  }
57
54
 
58
- // Check NODE_ENV
59
- if (process.env.NODE_ENV) {
60
- return process.env.NODE_ENV === "development";
55
+ // Fallback: compare .env content with .env.* files
56
+ if (!fs.existsSync(envPath)) {
57
+ return "default";
61
58
  }
62
59
 
63
- return false;
64
- }
60
+ const envContent = fs.readFileSync(envPath, "utf8");
61
+ const files = fs.readdirSync(cwd).filter((f) => /^\.env\..+$/.test(f));
65
62
 
66
- /**
67
- * Get current environment mode ('development' or 'production')
68
- */
69
- static getEnvironmentMode(): "development" | "production" {
70
- return this.isDevelopmentMode() ? "development" : "production";
63
+ for (const file of files) {
64
+ const name = file.replace(/\.env\./, "");
65
+ const fullPath = path.join(cwd, file);
66
+ try {
67
+ const content = fs.readFileSync(fullPath, "utf8");
68
+ if (content === envContent) {
69
+ return name;
70
+ }
71
+ } catch {
72
+ // Skip unreadable files
73
+ }
74
+ }
75
+
76
+ return "local"; // custom or modified .env
71
77
  }
72
78
  }
@@ -191,17 +191,8 @@ export class TestRunner {
191
191
  * Auto-detect test patterns based on environment and configuration
192
192
  */
193
193
  getAutoTestPattern(): string {
194
- const isDevMode = EnvUtils.isDevelopmentMode();
195
-
196
- if (isDevMode) {
197
- // Development mode - use TypeScript
198
- const srcDir = TsConfigUtils.getRootDir();
199
- return `${path.relative(process.cwd(), srcDir)}/**/*.spec.ts`;
200
- } else {
201
- // Production mode - use JavaScript
202
- const outDir = TsConfigUtils.getOutDir();
203
- return `${path.relative(process.cwd(), outDir)}/**/*.spec.js`;
204
- }
194
+ const srcDir = TsConfigUtils.getRootDir();
195
+ return `${path.relative(process.cwd(), srcDir)}/**/*.spec.ts`;
205
196
  }
206
197
  }
207
198
 
@@ -749,21 +749,12 @@ export class TypeORMModule {
749
749
  fs.readFileSync(configPath, "utf-8"),
750
750
  ) as FragmentConfig;
751
751
 
752
- // Determine environment mode
753
- const isDevMode = EnvUtils.isDevelopmentMode();
754
- console.log(`Detected ${isDevMode ? "development" : "production"} mode`);
755
-
756
- // Get the appropriate config section
757
- let dbConfig = {};
758
- if (isDevMode && raw.development?.database) {
759
- dbConfig = raw.development.database;
760
- } else if (!isDevMode && raw.production?.database) {
761
- dbConfig = raw.production.database;
762
- } else if (raw.development?.database) {
763
- // Fallback to development if production not found
764
- dbConfig = raw.development.database;
765
- console.warn("Production config not found, using development config");
752
+ if (!raw.development) {
753
+ throw new Error("fragment config not found | Invalid");
766
754
  }
755
+ var dbConfig;
756
+
757
+ dbConfig = raw.development.database;
767
758
 
768
759
  // Interpolate environment variables
769
760
  return this.interpolateEnvVars(dbConfig);
@@ -90,27 +90,7 @@ export class FragmentWebApplication {
90
90
  const distExists = fs.existsSync(path.join(cwd, "dist"));
91
91
  const srcExists = fs.existsSync(path.join(cwd, "src"));
92
92
 
93
- console.log(`๐Ÿ“ Current working directory: ${cwd}`);
94
- console.log(`๐Ÿ“ dist/ exists: ${distExists}`);
95
- console.log(`๐Ÿ“ src/ exists: ${srcExists}`);
96
-
97
- // Use EnvUtils for consistent environment detection
98
- const isDevMode = EnvUtils.isDevelopmentMode();
99
- console.log(
100
- `๐Ÿ’ป Running in ${isDevMode ? "development" : "production"} mode`,
101
- );
102
-
103
- if (isDevMode && srcExists) {
104
- // Development mode: scan TypeScript source files
105
- console.log(" ๐Ÿ“ Development mode: scanning TypeScript files");
106
- await ComponentScanner.scanSource();
107
- } else if (distExists) {
108
- // Production mode: scan compiled JavaScript files
109
- console.log(" ๐Ÿ“ฆ Production mode: scanning compiled files");
110
- await ComponentScanner.scan();
111
- } else {
112
- console.warn(" โš ๏ธ Warning: No src/ or dist/ directory found");
113
- }
93
+ await ComponentScanner.scanSource();
114
94
  }
115
95
 
116
96
  // Remove the old isRunningTypeScript method since we're using EnvUtils