@flusys/nestjs-core 4.1.1 → 5.0.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.
@@ -90,19 +90,20 @@ let EnvConfigService = class EnvConfigService {
90
90
  isProduction() {
91
91
  return this.getValue('MODE', false).toUpperCase() !== 'DEV';
92
92
  }
93
- getFrontendUrl() {
94
- return this.getValue('FRONTEND_URL');
95
- }
96
93
  getOrigins() {
97
94
  const origins = this.getValue('ALLOW_ORIGINS');
98
95
  return origins ? origins.split(',').map((o)=>o.trim()) : [];
99
96
  }
100
97
  getTypeOrmConfig() {
98
+ const type = this.getValue('DB_TYPE', false) || 'mysql';
99
+ const defaultPort = type === 'postgres' ? 5432 : 3306;
101
100
  return {
102
- host: this.getValue('DB_HOST'),
103
- port: this.getNumber('DB_PORT'),
104
- username: this.getValue('DB_USER'),
105
- password: this.getValue('DB_PASSWORD')
101
+ type,
102
+ host: this.getValue('DB_HOST', false) || 'localhost',
103
+ port: this.getNumber('DB_PORT', false) || defaultPort,
104
+ username: this.getValue('DB_USER', false) || 'root',
105
+ password: this.getValue('DB_PASSWORD', false) || '',
106
+ database: this.getValue('DB_NAME', false) || 'flusys_main'
106
107
  };
107
108
  }
108
109
  getJwtConfig() {
@@ -149,10 +150,12 @@ let EnvConfigService = class EnvConfigService {
149
150
  ALLOW_ORIGINS: 'getOrigins',
150
151
  PORT: 'getPort',
151
152
  MODE: 'isProduction',
153
+ DB_TYPE: 'getTypeOrmConfig',
152
154
  DB_HOST: 'getTypeOrmConfig',
153
155
  DB_PORT: 'getTypeOrmConfig',
154
156
  DB_USER: 'getTypeOrmConfig',
155
- DB_PASSWORD: 'getTypeOrmConfig'
157
+ DB_PASSWORD: 'getTypeOrmConfig',
158
+ DB_NAME: 'getTypeOrmConfig'
156
159
  };
157
160
  }
158
161
  };
@@ -162,6 +162,22 @@ function pathMatchesPattern(path, pattern) {
162
162
  const regex = new RegExp(`^${regexPattern}$`);
163
163
  return regex.test(path);
164
164
  }
165
+ function filterPaths(document, excludePaths) {
166
+ if (!excludePaths?.length || !document.paths) {
167
+ return document;
168
+ }
169
+ const filteredPaths = {};
170
+ for (const [path, pathItem] of Object.entries(document.paths)){
171
+ const isExcluded = excludePaths.some((pattern)=>pathMatchesPattern(path, pattern));
172
+ if (!isExcluded) {
173
+ filteredPaths[path] = pathItem;
174
+ }
175
+ }
176
+ return {
177
+ ...document,
178
+ paths: filteredPaths
179
+ };
180
+ }
165
181
  function filterDocumentByTags(document, excludeTags) {
166
182
  if (!excludeTags?.length) {
167
183
  return document;
@@ -232,6 +248,10 @@ function setupModuleSwaggerDocs(app, configs) {
232
248
  include: config.modules
233
249
  } : {};
234
250
  let document = _swagger.SwaggerModule.createDocument(app, builder.build(), createDocOptions);
251
+ // Filter out excluded paths
252
+ if (config.excludePaths?.length) {
253
+ document = filterPaths(document, config.excludePaths);
254
+ }
235
255
  // Filter out excluded tags
236
256
  if (config.excludeTags?.length) {
237
257
  document = filterDocumentByTags(document, config.excludeTags);
package/cjs/index.js CHANGED
@@ -7,7 +7,6 @@ _export_star(require("./interfaces"), exports);
7
7
  _export_star(require("./constants"), exports);
8
8
  _export_star(require("./utils"), exports);
9
9
  _export_star(require("./migration"), exports);
10
- _export_star(require("./seeders"), exports);
11
10
  _export_star(require("./config"), exports);
12
11
  function _export_star(from, to) {
13
12
  Object.keys(from).forEach(function(k) {
@@ -10,13 +10,14 @@ declare class EnvConfigService {
10
10
  getBoolean(key: string, throwOnMissing?: boolean): boolean;
11
11
  getPort(): number;
12
12
  isProduction(): boolean;
13
- getFrontendUrl(): string;
14
13
  getOrigins(): string[];
15
14
  getTypeOrmConfig(): {
15
+ type: "mysql" | "postgres" | "mariadb" | "sqlite" | "mssql";
16
16
  host: string;
17
17
  port: number;
18
18
  username: string;
19
19
  password: string;
20
+ database: string;
20
21
  };
21
22
  getJwtConfig(): {
22
23
  secret: string;
@@ -31,6 +31,7 @@ export interface IModuleSwaggerOptions {
31
31
  excludeSchemaProperties?: ISchemaPropertyExclusion[];
32
32
  excludeQueryParameters?: IQueryParameterExclusion[];
33
33
  excludeExamples?: IExampleExclusion[];
34
+ excludePaths?: string[];
34
35
  }
35
36
  export declare function setupModuleSwaggerDocs(app: INestApplication, configs: IModuleSwaggerOptions[]): void;
36
37
  export declare function setupSwaggerDocs(app: INestApplication, ...modules: IModuleSwaggerOptions[]): void;
@@ -39,19 +39,20 @@ let EnvConfigService = class EnvConfigService {
39
39
  isProduction() {
40
40
  return this.getValue('MODE', false).toUpperCase() !== 'DEV';
41
41
  }
42
- getFrontendUrl() {
43
- return this.getValue('FRONTEND_URL');
44
- }
45
42
  getOrigins() {
46
43
  const origins = this.getValue('ALLOW_ORIGINS');
47
44
  return origins ? origins.split(',').map((o)=>o.trim()) : [];
48
45
  }
49
46
  getTypeOrmConfig() {
47
+ const type = this.getValue('DB_TYPE', false) || 'mysql';
48
+ const defaultPort = type === 'postgres' ? 5432 : 3306;
50
49
  return {
51
- host: this.getValue('DB_HOST'),
52
- port: this.getNumber('DB_PORT'),
53
- username: this.getValue('DB_USER'),
54
- password: this.getValue('DB_PASSWORD')
50
+ type,
51
+ host: this.getValue('DB_HOST', false) || 'localhost',
52
+ port: this.getNumber('DB_PORT', false) || defaultPort,
53
+ username: this.getValue('DB_USER', false) || 'root',
54
+ password: this.getValue('DB_PASSWORD', false) || '',
55
+ database: this.getValue('DB_NAME', false) || 'flusys_main'
55
56
  };
56
57
  }
57
58
  getJwtConfig() {
@@ -98,10 +99,12 @@ let EnvConfigService = class EnvConfigService {
98
99
  ALLOW_ORIGINS: 'getOrigins',
99
100
  PORT: 'getPort',
100
101
  MODE: 'isProduction',
102
+ DB_TYPE: 'getTypeOrmConfig',
101
103
  DB_HOST: 'getTypeOrmConfig',
102
104
  DB_PORT: 'getTypeOrmConfig',
103
105
  DB_USER: 'getTypeOrmConfig',
104
- DB_PASSWORD: 'getTypeOrmConfig'
106
+ DB_PASSWORD: 'getTypeOrmConfig',
107
+ DB_NAME: 'getTypeOrmConfig'
105
108
  };
106
109
  }
107
110
  };
@@ -144,6 +144,22 @@ function pathMatchesPattern(path, pattern) {
144
144
  const regex = new RegExp(`^${regexPattern}$`);
145
145
  return regex.test(path);
146
146
  }
147
+ function filterPaths(document, excludePaths) {
148
+ if (!excludePaths?.length || !document.paths) {
149
+ return document;
150
+ }
151
+ const filteredPaths = {};
152
+ for (const [path, pathItem] of Object.entries(document.paths)){
153
+ const isExcluded = excludePaths.some((pattern)=>pathMatchesPattern(path, pattern));
154
+ if (!isExcluded) {
155
+ filteredPaths[path] = pathItem;
156
+ }
157
+ }
158
+ return {
159
+ ...document,
160
+ paths: filteredPaths
161
+ };
162
+ }
147
163
  function filterDocumentByTags(document, excludeTags) {
148
164
  if (!excludeTags?.length) {
149
165
  return document;
@@ -214,6 +230,10 @@ export function setupModuleSwaggerDocs(app, configs) {
214
230
  include: config.modules
215
231
  } : {};
216
232
  let document = SwaggerModule.createDocument(app, builder.build(), createDocOptions);
233
+ // Filter out excluded paths
234
+ if (config.excludePaths?.length) {
235
+ document = filterPaths(document, config.excludePaths);
236
+ }
217
237
  // Filter out excluded tags
218
238
  if (config.excludeTags?.length) {
219
239
  document = filterDocumentByTags(document, config.excludeTags);
package/fesm/index.js CHANGED
@@ -6,7 +6,5 @@ export * from './constants';
6
6
  export * from './utils';
7
7
  // Migration
8
8
  export * from './migration';
9
- // Seeders
10
- export * from './seeders';
11
9
  // Config
12
10
  export * from './config';
package/index.d.ts CHANGED
@@ -2,5 +2,4 @@ export * from './interfaces';
2
2
  export * from './constants';
3
3
  export * from './utils';
4
4
  export * from './migration';
5
- export * from './seeders';
6
5
  export * from './config';
@@ -14,9 +14,6 @@ export interface ITimestampable {
14
14
  export interface IOrderable {
15
15
  serial?: number | null;
16
16
  }
17
- export interface IMetadata {
18
- metadata?: Record<string, any> | null;
19
- }
20
17
  export interface ICompanyOwned {
21
18
  companyId?: string | null;
22
19
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flusys/nestjs-core",
3
- "version": "4.1.1",
3
+ "version": "5.0.0",
4
4
  "description": "Core types, interfaces, and constants for Flusys NestJS packages",
5
5
  "main": "cjs/index.js",
6
6
  "module": "fesm/index.js",
@@ -1,76 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "BaseSeeder", {
6
- enumerable: true,
7
- get: function() {
8
- return BaseSeeder;
9
- }
10
- });
11
- function _define_property(obj, key, value) {
12
- if (key in obj) {
13
- Object.defineProperty(obj, key, {
14
- value: value,
15
- enumerable: true,
16
- configurable: true,
17
- writable: true
18
- });
19
- } else {
20
- obj[key] = value;
21
- }
22
- return obj;
23
- }
24
- let BaseSeeder = class BaseSeeder {
25
- async clear(hard = false) {
26
- const hasSoftDelete = this.metadata.deleteDateColumn !== undefined;
27
- if (hard || !hasSoftDelete) {
28
- await this.repository.clear();
29
- } else {
30
- await this.repository.createQueryBuilder().softDelete().where('id IS NOT NULL').execute();
31
- }
32
- }
33
- async count(includeDeleted = false) {
34
- const hasSoftDelete = this.metadata.deleteDateColumn !== undefined;
35
- if (hasSoftDelete && !includeDeleted) {
36
- return this.repository.count({
37
- where: {
38
- deletedAt: null
39
- }
40
- });
41
- }
42
- return this.repository.count();
43
- }
44
- async isEmpty() {
45
- return await this.count() === 0;
46
- }
47
- getEntityName() {
48
- return this.metadata.tableName;
49
- }
50
- async withTransaction(operation) {
51
- const queryRunner = this.dataSource.createQueryRunner();
52
- await queryRunner.connect();
53
- await queryRunner.startTransaction();
54
- try {
55
- const transactionalRepo = queryRunner.manager.getRepository(this.entity);
56
- const result = await operation(transactionalRepo);
57
- await queryRunner.commitTransaction();
58
- return result;
59
- } catch (error) {
60
- await queryRunner.rollbackTransaction();
61
- throw error;
62
- } finally{
63
- await queryRunner.release();
64
- }
65
- }
66
- constructor(dataSource, entity){
67
- _define_property(this, "dataSource", void 0);
68
- _define_property(this, "entity", void 0);
69
- _define_property(this, "repository", void 0);
70
- _define_property(this, "metadata", void 0);
71
- this.dataSource = dataSource;
72
- this.entity = entity;
73
- this.repository = dataSource.getRepository(entity);
74
- this.metadata = this.repository.metadata;
75
- }
76
- };
@@ -1,291 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- Object.defineProperty(exports, "runSeedCli", {
7
- enumerable: true,
8
- get: function() {
9
- return main;
10
- }
11
- });
12
- const _path = /*#__PURE__*/ _interop_require_wildcard(require("path"));
13
- const _typeorm = require("typeorm");
14
- const _config = require("../config");
15
- const _seedrunner = require("./seed-runner");
16
- function _getRequireWildcardCache(nodeInterop) {
17
- if (typeof WeakMap !== "function") return null;
18
- var cacheBabelInterop = new WeakMap();
19
- var cacheNodeInterop = new WeakMap();
20
- return (_getRequireWildcardCache = function(nodeInterop) {
21
- return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
22
- })(nodeInterop);
23
- }
24
- function _interop_require_wildcard(obj, nodeInterop) {
25
- if (!nodeInterop && obj && obj.__esModule) {
26
- return obj;
27
- }
28
- if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
29
- return {
30
- default: obj
31
- };
32
- }
33
- var cache = _getRequireWildcardCache(nodeInterop);
34
- if (cache && cache.has(obj)) {
35
- return cache.get(obj);
36
- }
37
- var newObj = {
38
- __proto__: null
39
- };
40
- var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
41
- for(var key in obj){
42
- if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
43
- var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
44
- if (desc && (desc.get || desc.set)) {
45
- Object.defineProperty(newObj, key, desc);
46
- } else {
47
- newObj[key] = obj[key];
48
- }
49
- }
50
- }
51
- newObj.default = obj;
52
- if (cache) {
53
- cache.set(obj, newObj);
54
- }
55
- return newObj;
56
- }
57
- function showHelp() {
58
- console.log(`
59
- Seed Data CLI
60
-
61
- Usage:
62
- npm run seed:<command> [options]
63
-
64
- Commands:
65
- run Execute seeders for all entities
66
- run:all Execute seeders for all tenants (multi-tenant mode)
67
- clear Clear all seeded data
68
- status Show seeding status
69
-
70
- Options:
71
- --config=<path> Migration config file (default: src/persistence/migration.config.ts)
72
- --count=<number> Number of records per entity (default: from seed-config)
73
- --clear Clear existing data before seeding
74
- --entity=<name> Seed only specific entity
75
- --hard Hard delete when clearing (ignore soft delete)
76
- --tenant=<id> Target specific tenant (multi-tenant mode)
77
-
78
- Examples:
79
- npm run seed:run
80
- npm run seed:run -- --count=50 --clear
81
- npm run seed:run -- --entity=User --count=100
82
- npm run seed:clear
83
- npm run seed:clear -- --hard
84
- npm run seed:status
85
- npm run seed:run:all
86
- `);
87
- }
88
- function parseArgs() {
89
- const args = process.argv.slice(2);
90
- let command;
91
- let count;
92
- let clear = false;
93
- let entity;
94
- let hard = false;
95
- let tenant;
96
- let configPath;
97
- for (const arg of args){
98
- if (arg.startsWith('--count=')) {
99
- count = parseInt(arg.split('=')[1], 10);
100
- } else if (arg === '--clear') {
101
- clear = true;
102
- } else if (arg.startsWith('--entity=')) {
103
- entity = arg.split('=')[1];
104
- } else if (arg === '--hard') {
105
- hard = true;
106
- } else if (arg.startsWith('--tenant=')) {
107
- tenant = arg.split('=')[1];
108
- } else if (arg.startsWith('--config=')) {
109
- configPath = arg.split('=')[1];
110
- } else if (!arg.startsWith('-') && !command) {
111
- command = arg;
112
- }
113
- }
114
- return {
115
- command,
116
- count,
117
- clear,
118
- entity,
119
- hard,
120
- tenant,
121
- configPath
122
- };
123
- }
124
- let resolvedConfigPath;
125
- async function resolveConfigPath(explicitPath) {
126
- if (resolvedConfigPath) return resolvedConfigPath;
127
- const envConfigPath = _config.envConfig.tryGetValue('MIGRATION_CONFIG');
128
- const defaultPaths = [
129
- explicitPath,
130
- envConfigPath,
131
- 'src/persistence/migration.config.ts',
132
- 'src/persistence/migration.config.js'
133
- ].filter(Boolean);
134
- for (const tryPath of defaultPaths){
135
- const absolutePath = _path.isAbsolute(tryPath) ? tryPath : _path.resolve(process.cwd(), tryPath);
136
- try {
137
- await Promise.resolve(absolutePath).then((p)=>/*#__PURE__*/ _interop_require_wildcard(require(p)));
138
- resolvedConfigPath = absolutePath;
139
- return absolutePath;
140
- } catch {
141
- // Try next path
142
- }
143
- }
144
- console.error('āŒ Config not found. Use --config=<path> or set MIGRATION_CONFIG env var');
145
- process.exit(1);
146
- }
147
- async function loadDataSource(tenantId, configPath) {
148
- const resolvedPath = await resolveConfigPath(configPath);
149
- const module1 = await Promise.resolve(resolvedPath).then((p)=>/*#__PURE__*/ _interop_require_wildcard(require(p)));
150
- const migrationConfig = module1.migrationConfig || module1.default?.migrationConfig || module1;
151
- const dbConfig = tenantId ? migrationConfig.tenants?.find((t)=>t.tenantId === tenantId || t.id === tenantId) : migrationConfig.defaultDatabaseConfig || migrationConfig.database;
152
- if (!dbConfig) {
153
- throw new Error(`Database configuration not found${tenantId ? ` for tenant: ${tenantId}` : ''}`);
154
- }
155
- const entities = typeof migrationConfig.entities === 'function' ? migrationConfig.entities() : migrationConfig.entities || [];
156
- const dataSource = new _typeorm.DataSource({
157
- type: dbConfig.type || 'mysql',
158
- host: dbConfig.host,
159
- port: dbConfig.port,
160
- username: dbConfig.username,
161
- password: dbConfig.password,
162
- database: dbConfig.database,
163
- entities,
164
- synchronize: false,
165
- logging: false
166
- });
167
- await dataSource.initialize();
168
- return dataSource;
169
- }
170
- async function getAllTenantIds(configPath) {
171
- const resolvedPath = await resolveConfigPath(configPath);
172
- const module1 = await Promise.resolve(resolvedPath).then((p)=>/*#__PURE__*/ _interop_require_wildcard(require(p)));
173
- const migrationConfig = module1.migrationConfig || module1.default?.migrationConfig || module1;
174
- if (migrationConfig.bootstrapAppConfig?.databaseMode !== 'multi-tenant' || !migrationConfig.tenants) {
175
- throw new Error('Multi-tenant mode is not configured');
176
- }
177
- return migrationConfig.tenants.map((t)=>t.tenantId || t.id);
178
- }
179
- async function runCommand(options, configPath) {
180
- const dataSource = await loadDataSource(undefined, configPath);
181
- try {
182
- const runner = new _seedrunner.SeedRunner(dataSource);
183
- if (options.entity) {
184
- console.log(`🌱 Seeding entity: ${options.entity}\n`);
185
- const result = await runner.runSingle(options.entity, options);
186
- if (result.success) {
187
- console.log(`\nāœ“ ${result.entity}: ${result.count} records created\n`);
188
- } else {
189
- console.error(`\nāœ— ${result.entity}: ${result.error}\n`);
190
- process.exit(1);
191
- }
192
- } else {
193
- const results = await runner.runAll(options);
194
- if (results.some((r)=>!r.success)) process.exit(1);
195
- }
196
- } finally{
197
- await dataSource.destroy();
198
- }
199
- }
200
- async function runAllTenantsCommand(options, configPath) {
201
- console.log('šŸ¢ Running seeds for all tenants...\n');
202
- const tenantIds = await getAllTenantIds(configPath);
203
- let successCount = 0;
204
- let failCount = 0;
205
- for (const tenantId of tenantIds){
206
- console.log(`\nšŸ“¦ Tenant: ${tenantId}`);
207
- console.log('─'.repeat(50));
208
- const dataSource = await loadDataSource(tenantId, configPath);
209
- try {
210
- const runner = new _seedrunner.SeedRunner(dataSource);
211
- const results = await runner.runAll(options);
212
- results.some((r)=>!r.success) ? failCount++ : successCount++;
213
- } catch (error) {
214
- console.error(`āœ— Failed to seed tenant ${tenantId}:`, error);
215
- failCount++;
216
- } finally{
217
- await dataSource.destroy();
218
- }
219
- }
220
- console.log('\n' + '='.repeat(50));
221
- console.log(`\nāœ“ Completed: ${successCount} tenants seeded`);
222
- if (failCount > 0) {
223
- console.log(`āœ— Failed: ${failCount} tenants\n`);
224
- process.exit(1);
225
- }
226
- }
227
- async function clearCommand(hard = false, configPath) {
228
- const dataSource = await loadDataSource(undefined, configPath);
229
- try {
230
- await new _seedrunner.SeedRunner(dataSource).clearAll(hard);
231
- } finally{
232
- await dataSource.destroy();
233
- }
234
- }
235
- async function statusCommand(configPath) {
236
- const dataSource = await loadDataSource(undefined, configPath);
237
- try {
238
- const status = await new _seedrunner.SeedRunner(dataSource).getStatus();
239
- console.log('\nSeed Status:');
240
- console.log('ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”');
241
- console.log('│ Entity │ Records │ Status │');
242
- console.log('ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤');
243
- for (const item of status){
244
- console.log(`│ ${item.entity.padEnd(26)} │ ${item.count.toString().padEnd(9)} │ ${item.isEmpty ? '⚠ Empty' : 'āœ“ Ready '} │`);
245
- }
246
- console.log('ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜\n');
247
- } finally{
248
- await dataSource.destroy();
249
- }
250
- }
251
- async function main() {
252
- const args = parseArgs();
253
- if (!args.command) {
254
- showHelp();
255
- return;
256
- }
257
- if (args.configPath) {
258
- await resolveConfigPath(args.configPath);
259
- }
260
- switch(args.command){
261
- case 'run':
262
- await runCommand({
263
- count: args.count,
264
- clear: args.clear,
265
- entity: args.entity
266
- }, args.configPath);
267
- break;
268
- case 'run:all':
269
- await runAllTenantsCommand({
270
- count: args.count,
271
- clear: args.clear
272
- }, args.configPath);
273
- break;
274
- case 'clear':
275
- await clearCommand(args.hard, args.configPath);
276
- break;
277
- case 'status':
278
- await statusCommand(args.configPath);
279
- break;
280
- default:
281
- console.error(`āŒ Unknown command: ${args.command}`);
282
- showHelp();
283
- process.exit(1);
284
- }
285
- }
286
- if (require.main === module) {
287
- main().catch((error)=>{
288
- console.error('Fatal error:', error);
289
- process.exit(1);
290
- });
291
- }