@slingr/cli 0.0.2 → 0.0.4
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/LICENSE.txt +202 -0
- package/README.md +490 -319
- package/bin/dev.cmd +2 -2
- package/bin/dev.js +5 -5
- package/bin/run.cmd +2 -2
- package/bin/run.js +4 -4
- package/bin/slingr +1 -0
- package/dist/commands/build.d.ts +20 -0
- package/dist/commands/build.d.ts.map +1 -0
- package/dist/commands/build.js +206 -0
- package/dist/commands/build.js.map +1 -0
- package/dist/commands/create-app.d.ts +0 -1
- package/dist/commands/create-app.d.ts.map +1 -1
- package/dist/commands/create-app.js +38 -57
- package/dist/commands/create-app.js.map +1 -1
- package/dist/commands/debug.d.ts +28 -0
- package/dist/commands/debug.d.ts.map +1 -0
- package/dist/commands/debug.js +474 -0
- package/dist/commands/debug.js.map +1 -0
- package/dist/commands/ds.d.ts +14 -1
- package/dist/commands/ds.d.ts.map +1 -1
- package/dist/commands/ds.js +450 -121
- package/dist/commands/ds.js.map +1 -1
- package/dist/commands/gql.d.ts +1 -1
- package/dist/commands/gql.d.ts.map +1 -1
- package/dist/commands/gql.js +190 -184
- package/dist/commands/gql.js.map +1 -1
- package/dist/commands/infra/down.d.ts.map +1 -1
- package/dist/commands/infra/down.js +8 -7
- package/dist/commands/infra/down.js.map +1 -1
- package/dist/commands/infra/up.d.ts.map +1 -1
- package/dist/commands/infra/up.js +8 -7
- package/dist/commands/infra/up.js.map +1 -1
- package/dist/commands/infra/update.d.ts +1 -0
- package/dist/commands/infra/update.d.ts.map +1 -1
- package/dist/commands/infra/update.js +33 -69
- package/dist/commands/infra/update.js.map +1 -1
- package/dist/commands/run.d.ts +29 -2
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +628 -130
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/setup.d.ts +1 -1
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +34 -71
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/sync-metadata.d.ts +15 -0
- package/dist/commands/sync-metadata.d.ts.map +1 -0
- package/dist/commands/sync-metadata.js +225 -0
- package/dist/commands/sync-metadata.js.map +1 -0
- package/dist/commands/users.d.ts +30 -0
- package/dist/commands/users.d.ts.map +1 -0
- package/dist/commands/users.js +472 -0
- package/dist/commands/users.js.map +1 -0
- package/dist/commands/views.d.ts +11 -0
- package/dist/commands/views.d.ts.map +1 -0
- package/dist/commands/views.js +73 -0
- package/dist/commands/views.js.map +1 -0
- package/dist/projectStructure.d.ts +2 -2
- package/dist/projectStructure.d.ts.map +1 -1
- package/dist/projectStructure.js +281 -69
- package/dist/projectStructure.js.map +1 -1
- package/dist/scripts/generate-metadata.d.ts +13 -0
- package/dist/scripts/generate-metadata.d.ts.map +1 -0
- package/dist/scripts/generate-metadata.js +412 -0
- package/dist/scripts/generate-metadata.js.map +1 -0
- package/dist/scripts/generate-metadata.ts +498 -0
- package/dist/scripts/generate-schema.d.ts +1 -1
- package/dist/scripts/generate-schema.js +168 -74
- package/dist/scripts/generate-schema.js.map +1 -1
- package/dist/scripts/generate-schema.ts +258 -143
- package/dist/templates/.env.template +23 -0
- package/dist/templates/.firebaserc.template +5 -0
- package/dist/templates/.github/copilot-instructions.md.template +652 -17
- package/dist/templates/backend/Dockerfile.template +30 -0
- package/dist/templates/config/datasource.ts.template +12 -9
- package/dist/templates/config/jest.config.ts +30 -30
- package/dist/templates/config/jest.setup.ts +1 -1
- package/dist/templates/config/tsconfig.json.template +50 -29
- package/dist/templates/dataSources/mysql.ts.template +16 -13
- package/dist/templates/dataSources/postgres.ts.template +15 -13
- package/dist/templates/dataset-generator-script.ts.template +139 -139
- package/dist/templates/datasets/mysql-default/.slingr-schema.json.template +5 -0
- package/dist/templates/datasets/mysql-default/Address.jsonl.template +3 -3
- package/dist/templates/datasets/mysql-default/App.jsonl.template +4 -4
- package/dist/templates/datasets/mysql-default/Company.jsonl.template +3 -3
- package/dist/templates/datasets/mysql-default/Person.jsonl.template +2 -2
- package/dist/templates/datasets/mysql-default/User.jsonl.template +1 -0
- package/dist/templates/datasets/mysql-default/instructions.md.template +1 -0
- package/dist/templates/datasets/postgres-default/.slingr-schema.json.template +5 -0
- package/dist/templates/datasets/postgres-default/Address.jsonl.template +3 -3
- package/dist/templates/datasets/postgres-default/App.jsonl.template +4 -4
- package/dist/templates/datasets/postgres-default/Company.jsonl.template +3 -3
- package/dist/templates/datasets/postgres-default/Person.jsonl.template +2 -2
- package/dist/templates/datasets/postgres-default/User.jsonl.template +1 -0
- package/dist/templates/datasets/postgres-default/instructions.md.template +1 -0
- package/dist/templates/docker-compose.prod-test.yml.template +32 -0
- package/dist/templates/docker-compose.yml.template +24 -0
- package/dist/templates/docs/app-description.md.template +33 -33
- package/dist/templates/firebase.json.template +68 -0
- package/dist/templates/frontend/.umirc.ts.template +23 -0
- package/dist/templates/frontend/package.json.template +45 -0
- package/dist/templates/frontend/public/config.json +6 -0
- package/dist/templates/frontend/public/logo.svg +6 -0
- package/dist/templates/frontend/src/app.tsx.template +44 -0
- package/dist/templates/frontend/src/global.less.template +117 -0
- package/dist/templates/frontend/src/layouts/MainLayout.tsx.template +75 -0
- package/dist/templates/frontend/src/types/graphql-augmentation.d.ts.template +44 -0
- package/dist/templates/frontend/src/views/customViews/user/UserCreateView.tsx.template +18 -0
- package/dist/templates/frontend/src/views/customViews/user/UserEditView.tsx.template +29 -0
- package/dist/templates/frontend/src/views/customViews/user/UserReadView.tsx.template +24 -0
- package/dist/templates/frontend/src/views/customViews/user/UserTableView.tsx.template +38 -0
- package/dist/templates/frontend/src/views/customViews/welcome.tsx.template +34 -0
- package/dist/templates/frontend/tsconfig.json.template +50 -0
- package/dist/templates/gql/codegen.yml.template +25 -25
- package/dist/templates/gql/index.ts.template +17 -24
- package/dist/templates/gql/operations.graphql.template +30 -30
- package/dist/templates/ops/README.md.template +1045 -0
- package/dist/templates/ops/cloudbuild.yaml.template +161 -0
- package/dist/templates/ops/scripts/_utils.js.template +217 -0
- package/dist/templates/ops/scripts/deploy.js.template +145 -0
- package/dist/templates/ops/scripts/setup-gcp.js.template +330 -0
- package/dist/templates/ops/scripts/setup-secrets.js.template +76 -0
- package/dist/templates/ops/scripts/test-prod-local.js.template +49 -0
- package/dist/templates/package.json.template +50 -38
- package/dist/templates/pnpm-workspace.yaml.template +3 -0
- package/dist/templates/prompt-analysis.md.template +110 -110
- package/dist/templates/prompt-script-generation.md.template +258 -258
- package/dist/templates/src/Address.ts.template +28 -31
- package/dist/templates/src/App.ts.template +17 -61
- package/dist/templates/src/Company.ts.template +41 -47
- package/dist/templates/src/Models.test.ts.template +654 -654
- package/dist/templates/src/Person.test.ts.template +289 -289
- package/dist/templates/src/Person.ts.template +90 -105
- package/dist/templates/src/actions/index.ts.template +11 -11
- package/dist/templates/src/auth/permissions.ts.template +34 -0
- package/dist/templates/src/data/App.ts.template +48 -0
- package/dist/templates/src/data/User.ts.template +35 -0
- package/dist/templates/src/types/gql.d.ts.template +17 -17
- package/dist/templates/vscode/extensions.json +4 -3
- package/dist/templates/vscode/settings.json +17 -11
- package/dist/templates/workspace-package.json.template +21 -0
- package/dist/utils/buildCache.d.ts +12 -0
- package/dist/utils/buildCache.d.ts.map +1 -0
- package/dist/utils/buildCache.js +102 -0
- package/dist/utils/buildCache.js.map +1 -0
- package/dist/utils/checkFramework.d.ts +27 -0
- package/dist/utils/checkFramework.d.ts.map +1 -0
- package/dist/utils/checkFramework.js +104 -0
- package/dist/utils/checkFramework.js.map +1 -0
- package/dist/utils/datasourceParser.d.ts +11 -0
- package/dist/utils/datasourceParser.d.ts.map +1 -1
- package/dist/utils/datasourceParser.js +154 -56
- package/dist/utils/datasourceParser.js.map +1 -1
- package/dist/utils/dockerManager.d.ts +25 -0
- package/dist/utils/dockerManager.d.ts.map +1 -0
- package/dist/utils/dockerManager.js +281 -0
- package/dist/utils/dockerManager.js.map +1 -0
- package/dist/utils/infraFileParser.d.ts +26 -0
- package/dist/utils/infraFileParser.d.ts.map +1 -0
- package/dist/utils/infraFileParser.js +75 -0
- package/dist/utils/infraFileParser.js.map +1 -0
- package/dist/utils/jsonlLoader.d.ts +91 -12
- package/dist/utils/jsonlLoader.d.ts.map +1 -1
- package/dist/utils/jsonlLoader.js +674 -63
- package/dist/utils/jsonlLoader.js.map +1 -1
- package/dist/utils/model-analyzer.d.ts.map +1 -1
- package/dist/utils/model-analyzer.js +67 -13
- package/dist/utils/model-analyzer.js.map +1 -1
- package/dist/utils/userManagement.d.ts +57 -0
- package/dist/utils/userManagement.d.ts.map +1 -0
- package/dist/utils/userManagement.js +288 -0
- package/dist/utils/userManagement.js.map +1 -0
- package/dist/utils/viewsGenerator.d.ts +15 -0
- package/dist/utils/viewsGenerator.d.ts.map +1 -0
- package/dist/utils/viewsGenerator.js +311 -0
- package/dist/utils/viewsGenerator.js.map +1 -0
- package/oclif.manifest.json +445 -20
- package/package.json +29 -27
- package/src/templates/.env.template +23 -0
- package/src/templates/.firebaserc.template +5 -0
- package/src/templates/.github/copilot-instructions.md.template +652 -17
- package/src/templates/backend/Dockerfile.template +30 -0
- package/src/templates/config/datasource.ts.template +12 -9
- package/src/templates/config/jest.config.ts +30 -30
- package/src/templates/config/jest.setup.ts +1 -1
- package/src/templates/config/tsconfig.json.template +50 -29
- package/src/templates/dataSources/mysql.ts.template +16 -13
- package/src/templates/dataSources/postgres.ts.template +15 -13
- package/src/templates/dataset-generator-script.ts.template +139 -139
- package/src/templates/datasets/mysql-default/.slingr-schema.json.template +5 -0
- package/src/templates/datasets/mysql-default/Address.jsonl.template +3 -3
- package/src/templates/datasets/mysql-default/App.jsonl.template +4 -4
- package/src/templates/datasets/mysql-default/Company.jsonl.template +3 -3
- package/src/templates/datasets/mysql-default/Person.jsonl.template +2 -2
- package/src/templates/datasets/mysql-default/User.jsonl.template +1 -0
- package/src/templates/datasets/mysql-default/instructions.md.template +1 -0
- package/src/templates/datasets/postgres-default/.slingr-schema.json.template +5 -0
- package/src/templates/datasets/postgres-default/Address.jsonl.template +3 -3
- package/src/templates/datasets/postgres-default/App.jsonl.template +4 -4
- package/src/templates/datasets/postgres-default/Company.jsonl.template +3 -3
- package/src/templates/datasets/postgres-default/Person.jsonl.template +2 -2
- package/src/templates/datasets/postgres-default/User.jsonl.template +1 -0
- package/src/templates/datasets/postgres-default/instructions.md.template +1 -0
- package/src/templates/docker-compose.prod-test.yml.template +32 -0
- package/src/templates/docker-compose.yml.template +24 -0
- package/src/templates/docs/app-description.md.template +33 -33
- package/src/templates/firebase.json.template +68 -0
- package/src/templates/frontend/.umirc.ts.template +23 -0
- package/src/templates/frontend/package.json.template +45 -0
- package/src/templates/frontend/public/config.json +6 -0
- package/src/templates/frontend/public/logo.svg +6 -0
- package/src/templates/frontend/src/app.tsx.template +44 -0
- package/src/templates/frontend/src/global.less.template +117 -0
- package/src/templates/frontend/src/layouts/MainLayout.tsx.template +75 -0
- package/src/templates/frontend/src/types/graphql-augmentation.d.ts.template +44 -0
- package/src/templates/frontend/src/views/customViews/user/UserCreateView.tsx.template +18 -0
- package/src/templates/frontend/src/views/customViews/user/UserEditView.tsx.template +29 -0
- package/src/templates/frontend/src/views/customViews/user/UserReadView.tsx.template +24 -0
- package/src/templates/frontend/src/views/customViews/user/UserTableView.tsx.template +38 -0
- package/src/templates/frontend/src/views/customViews/welcome.tsx.template +34 -0
- package/src/templates/frontend/tsconfig.json.template +50 -0
- package/src/templates/gql/codegen.yml.template +25 -25
- package/src/templates/gql/index.ts.template +17 -24
- package/src/templates/gql/operations.graphql.template +30 -30
- package/src/templates/ops/README.md.template +1045 -0
- package/src/templates/ops/cloudbuild.yaml.template +161 -0
- package/src/templates/ops/scripts/_utils.js.template +217 -0
- package/src/templates/ops/scripts/deploy.js.template +145 -0
- package/src/templates/ops/scripts/setup-gcp.js.template +330 -0
- package/src/templates/ops/scripts/setup-secrets.js.template +76 -0
- package/src/templates/ops/scripts/test-prod-local.js.template +49 -0
- package/src/templates/package.json.template +50 -38
- package/src/templates/pnpm-workspace.yaml.template +3 -0
- package/src/templates/prompt-analysis.md.template +110 -110
- package/src/templates/prompt-script-generation.md.template +258 -258
- package/src/templates/src/Address.ts.template +28 -31
- package/src/templates/src/App.ts.template +17 -61
- package/src/templates/src/Company.ts.template +41 -47
- package/src/templates/src/Models.test.ts.template +654 -654
- package/src/templates/src/Person.test.ts.template +289 -289
- package/src/templates/src/Person.ts.template +90 -105
- package/src/templates/src/actions/index.ts.template +11 -11
- package/src/templates/src/auth/permissions.ts.template +34 -0
- package/src/templates/src/data/App.ts.template +48 -0
- package/src/templates/src/data/User.ts.template +35 -0
- package/src/templates/src/types/gql.d.ts.template +17 -17
- package/src/templates/vscode/extensions.json +4 -3
- package/src/templates/vscode/settings.json +17 -11
- package/src/templates/workspace-package.json.template +21 -0
- package/dist/templates/src/index.ts +0 -66
- package/src/templates/src/index.ts +0 -66
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.loadDataSource = loadDataSource;
|
|
7
|
+
exports.loadUserModel = loadUserModel;
|
|
8
|
+
exports.loadRoleEnum = loadRoleEnum;
|
|
9
|
+
exports.findUserByEmail = findUserByEmail;
|
|
10
|
+
exports.getUserRepository = getUserRepository;
|
|
11
|
+
exports.validateRoles = validateRoles;
|
|
12
|
+
exports.getAvailableRoles = getAvailableRoles;
|
|
13
|
+
exports.generateRandomPassword = generateRandomPassword;
|
|
14
|
+
exports.validateEmail = validateEmail;
|
|
15
|
+
exports.promptPassword = promptPassword;
|
|
16
|
+
exports.promptConfirmation = promptConfirmation;
|
|
17
|
+
exports.formatUser = formatUser;
|
|
18
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
19
|
+
const node_url_1 = require("node:url");
|
|
20
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
21
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
22
|
+
require("reflect-metadata");
|
|
23
|
+
const datasourceParser_js_1 = require("./datasourceParser.js");
|
|
24
|
+
const checkFramework_js_1 = require("./checkFramework.js");
|
|
25
|
+
const datasourceParser_js_2 = require("./datasourceParser.js");
|
|
26
|
+
// Metadata key used by the @DataModel decorator to store the datasource
|
|
27
|
+
// This matches the internal framework constant
|
|
28
|
+
const MODEL_DATASOURCE = 'model:dataSource';
|
|
29
|
+
/**
|
|
30
|
+
* Get the datasource used by the User model by inspecting the User model metadata
|
|
31
|
+
*/
|
|
32
|
+
async function getUserDataSource() {
|
|
33
|
+
const UserModel = await loadUserModel();
|
|
34
|
+
// Get the datasource from the model's metadata using reflect-metadata API
|
|
35
|
+
// The @DataModel decorator stores this information using Reflect.defineMetadata()
|
|
36
|
+
const dataSource = Reflect.getMetadata(MODEL_DATASOURCE, UserModel);
|
|
37
|
+
if (!dataSource) {
|
|
38
|
+
throw new Error(`User model does not have a datasource configured. ` +
|
|
39
|
+
`Make sure the User class has @DataModel({ dataSource: yourDataSource }) decorator.`);
|
|
40
|
+
}
|
|
41
|
+
// Try to get TypeORM datasource info, but it might not be initialized yet
|
|
42
|
+
let typeormDs;
|
|
43
|
+
try {
|
|
44
|
+
typeormDs = dataSource.getTypeOrmDataSource();
|
|
45
|
+
if (typeormDs) {
|
|
46
|
+
console.log(`\n📊 Using datasource: ${typeormDs.options?.type || 'unknown'} (${typeormDs.options?.database || 'unknown db'})`);
|
|
47
|
+
if (typeormDs.isInitialized) {
|
|
48
|
+
console.log('✅ TypeORM datasource already initialized\n');
|
|
49
|
+
return dataSource;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
// If getTypeOrmDataSource() throws, it means it's not initialized yet
|
|
55
|
+
console.log('\n⚙️ TypeORM datasource not initialized yet, initializing now...');
|
|
56
|
+
}
|
|
57
|
+
// Initialize the datasource
|
|
58
|
+
console.log('🔧 Initializing datasource...');
|
|
59
|
+
await dataSource.initialize();
|
|
60
|
+
// Log success with datasource info
|
|
61
|
+
const initializedDs = dataSource.getTypeOrmDataSource();
|
|
62
|
+
if (initializedDs) {
|
|
63
|
+
console.log(`✅ Datasource initialized: ${initializedDs.options?.type || 'unknown'} (${initializedDs.options?.database || 'unknown db'})\n`);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
console.log('✅ Datasource initialized\n');
|
|
67
|
+
}
|
|
68
|
+
return dataSource;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Load and initialize the datasource used by the User model
|
|
72
|
+
* This is the recommended way to get the datasource for user operations
|
|
73
|
+
*/
|
|
74
|
+
async function loadDataSource(dsName) {
|
|
75
|
+
// If no datasource name is provided, discover it from the User model
|
|
76
|
+
if (!dsName) {
|
|
77
|
+
return await getUserDataSource();
|
|
78
|
+
}
|
|
79
|
+
await (0, datasourceParser_js_1.discoverDatasourceFile)(dsName);
|
|
80
|
+
const dsConfig = await (0, datasourceParser_js_2.loadDataSourceFromFile)(dsName);
|
|
81
|
+
if (!dsConfig.getTypeOrmDataSource()?.isInitialized) {
|
|
82
|
+
await dsConfig.initialize();
|
|
83
|
+
}
|
|
84
|
+
return dsConfig;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Recursively find a file by name under a directory.
|
|
88
|
+
*/
|
|
89
|
+
async function findFileRecursive(dir, filename) {
|
|
90
|
+
if (!(await fs_extra_1.default.pathExists(dir))) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
const entries = await fs_extra_1.default.readdir(dir, { withFileTypes: true });
|
|
94
|
+
for (const entry of entries) {
|
|
95
|
+
const fullPath = node_path_1.default.join(dir, entry.name);
|
|
96
|
+
if (entry.isDirectory()) {
|
|
97
|
+
const found = await findFileRecursive(fullPath, filename);
|
|
98
|
+
if (found) {
|
|
99
|
+
return found;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
else if (entry.name === filename) {
|
|
103
|
+
return fullPath;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Load the User model from the compiled app
|
|
110
|
+
*/
|
|
111
|
+
async function loadUserModel() {
|
|
112
|
+
const backendPath = (0, checkFramework_js_1.getBackendPath)();
|
|
113
|
+
const dataDir = node_path_1.default.join(backendPath, 'dist', 'src', 'data');
|
|
114
|
+
const userModulePath = await findFileRecursive(dataDir, 'User.js');
|
|
115
|
+
if (!userModulePath) {
|
|
116
|
+
throw new Error('User model not found. Make sure the app is built (npm run build from backend directory) and User.ts exists somewhere under backend/src/data/');
|
|
117
|
+
}
|
|
118
|
+
try {
|
|
119
|
+
const userModule = await import((0, node_url_1.pathToFileURL)(userModulePath).href);
|
|
120
|
+
return userModule.User || userModule.default;
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
if (error.code === 'MODULE_NOT_FOUND' || error.code === 'ERR_MODULE_NOT_FOUND') {
|
|
124
|
+
throw new Error('User model not found. Make sure the app is built (npm run build from backend directory) and User.ts exists somewhere under backend/src/data/');
|
|
125
|
+
}
|
|
126
|
+
throw error;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Load the Role enum from the compiled app
|
|
131
|
+
*/
|
|
132
|
+
async function loadRoleEnum() {
|
|
133
|
+
const backendPath = (0, checkFramework_js_1.getBackendPath)();
|
|
134
|
+
const dataDir = node_path_1.default.join(backendPath, 'dist', 'src', 'data');
|
|
135
|
+
const userModulePath = await findFileRecursive(dataDir, 'User.js');
|
|
136
|
+
if (!userModulePath) {
|
|
137
|
+
return undefined;
|
|
138
|
+
} // Role enum is optional
|
|
139
|
+
try {
|
|
140
|
+
const userModule = await import((0, node_url_1.pathToFileURL)(userModulePath).href);
|
|
141
|
+
return userModule.Role;
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
return undefined; // Role enum is optional
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Find a user by email
|
|
149
|
+
*/
|
|
150
|
+
async function findUserByEmail(email, userRepo) {
|
|
151
|
+
return await userRepo.findOne({ where: { email } });
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Get user repository from datasource
|
|
155
|
+
*/
|
|
156
|
+
async function getUserRepository(dataSource) {
|
|
157
|
+
console.log(' 🔍 Loading User model...');
|
|
158
|
+
const UserModel = await loadUserModel();
|
|
159
|
+
console.log(' ✅ User model loaded');
|
|
160
|
+
console.log(' 🔍 Getting TypeORM datasource...');
|
|
161
|
+
const typeormDs = dataSource.getTypeOrmDataSource();
|
|
162
|
+
console.log(` ✅ TypeORM datasource: ${typeormDs ? 'found' : 'NOT FOUND'}`);
|
|
163
|
+
if (typeormDs) {
|
|
164
|
+
console.log(` 📊 Datasource initialized: ${typeormDs.isInitialized}`);
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
console.log(' ⚠️ WARNING: TypeORM datasource is null/undefined!');
|
|
168
|
+
}
|
|
169
|
+
console.log(' 🔍 Getting repository...');
|
|
170
|
+
return dataSource.native().getRepository(UserModel);
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Validate roles against the app's Role enum
|
|
174
|
+
*/
|
|
175
|
+
async function validateRoles(roles) {
|
|
176
|
+
try {
|
|
177
|
+
const RoleEnum = await loadRoleEnum();
|
|
178
|
+
const validRoles = Object.values(RoleEnum);
|
|
179
|
+
const invalidRoles = roles.filter(role => !validRoles.includes(role));
|
|
180
|
+
return {
|
|
181
|
+
valid: invalidRoles.length === 0,
|
|
182
|
+
invalidRoles,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
// If we can't load the enum, assume roles are valid
|
|
187
|
+
return { valid: true, invalidRoles: [] };
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Get available roles from the app's Role enum
|
|
192
|
+
*/
|
|
193
|
+
async function getAvailableRoles() {
|
|
194
|
+
try {
|
|
195
|
+
const RoleEnum = await loadRoleEnum();
|
|
196
|
+
return Object.values(RoleEnum);
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
return [];
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Generate a secure random password
|
|
204
|
+
*/
|
|
205
|
+
function generateRandomPassword(length = 12) {
|
|
206
|
+
const uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
207
|
+
const lowercase = 'abcdefghijklmnopqrstuvwxyz';
|
|
208
|
+
const numbers = '0123456789';
|
|
209
|
+
const symbols = '@$!%*?&';
|
|
210
|
+
const allChars = uppercase + lowercase + numbers + symbols;
|
|
211
|
+
let password = '';
|
|
212
|
+
// Ensure at least one of each type
|
|
213
|
+
password += uppercase[Math.floor(Math.random() * uppercase.length)];
|
|
214
|
+
password += lowercase[Math.floor(Math.random() * lowercase.length)];
|
|
215
|
+
password += numbers[Math.floor(Math.random() * numbers.length)];
|
|
216
|
+
password += symbols[Math.floor(Math.random() * symbols.length)];
|
|
217
|
+
// Fill the rest randomly
|
|
218
|
+
for (let i = password.length; i < length; i++) {
|
|
219
|
+
password += allChars[Math.floor(Math.random() * allChars.length)];
|
|
220
|
+
}
|
|
221
|
+
// Shuffle the password
|
|
222
|
+
return password
|
|
223
|
+
.split('')
|
|
224
|
+
.sort(() => Math.random() - 0.5)
|
|
225
|
+
.join('');
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Validate email format
|
|
229
|
+
*/
|
|
230
|
+
function validateEmail(email) {
|
|
231
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
232
|
+
return emailRegex.test(email);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Interactive password prompt with confirmation
|
|
236
|
+
*/
|
|
237
|
+
async function promptPassword(message = 'Password') {
|
|
238
|
+
const answers = await inquirer_1.default.prompt([
|
|
239
|
+
{
|
|
240
|
+
type: 'password',
|
|
241
|
+
name: 'password',
|
|
242
|
+
message: message,
|
|
243
|
+
mask: '*',
|
|
244
|
+
validate: (input) => {
|
|
245
|
+
if (input.length < 8) {
|
|
246
|
+
return 'Password must be at least 8 characters long';
|
|
247
|
+
}
|
|
248
|
+
return true;
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
type: 'password',
|
|
253
|
+
name: 'confirmPassword',
|
|
254
|
+
message: 'Confirm password',
|
|
255
|
+
mask: '*',
|
|
256
|
+
validate: (input, answers) => {
|
|
257
|
+
if (input !== answers?.password) {
|
|
258
|
+
return 'Passwords do not match';
|
|
259
|
+
}
|
|
260
|
+
return true;
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
]);
|
|
264
|
+
return answers.password;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Interactive confirmation prompt
|
|
268
|
+
*/
|
|
269
|
+
async function promptConfirmation(message, defaultValue = false) {
|
|
270
|
+
const answer = await inquirer_1.default.prompt([
|
|
271
|
+
{
|
|
272
|
+
type: 'confirm',
|
|
273
|
+
name: 'confirm',
|
|
274
|
+
message: message,
|
|
275
|
+
default: defaultValue,
|
|
276
|
+
},
|
|
277
|
+
]);
|
|
278
|
+
return answer.confirm;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Format user for display
|
|
282
|
+
*/
|
|
283
|
+
function formatUser(user) {
|
|
284
|
+
const rolesText = user.roles ? user.roles.join(', ') : 'None';
|
|
285
|
+
const statusText = user.status === 'active' ? '[ACTIVE]' : ' [INACTIVE]';
|
|
286
|
+
return `${user.email} - ${user.firstName} ${user.lastName} (${rolesText})${statusText}`;
|
|
287
|
+
}
|
|
288
|
+
//# sourceMappingURL=userManagement.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"userManagement.js","sourceRoot":"","sources":["../../src/utils/userManagement.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates the context.ts file for custom views.
|
|
3
|
+
* This file exports a polyfill for require.context that registers all views.
|
|
4
|
+
*
|
|
5
|
+
* The generated file will:
|
|
6
|
+
* 1. Import all .tsx files from the views directory (excluding tests and context.tsx itself)
|
|
7
|
+
* 2. Create a registry mapping relative paths to module exports
|
|
8
|
+
* 3. Export a polyfill function that mimics webpack's require.context interface
|
|
9
|
+
*
|
|
10
|
+
* @param cwd - The working directory (defaults to process.cwd())
|
|
11
|
+
* @param verbose - Whether to print progress messages (defaults to true)
|
|
12
|
+
* @returns true if context.ts was generated, false if no views were found
|
|
13
|
+
*/
|
|
14
|
+
export declare function generateViewsContext(cwd?: string, verbose?: boolean): Promise<boolean>;
|
|
15
|
+
//# sourceMappingURL=viewsGenerator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"viewsGenerator.d.ts","sourceRoot":"","sources":["../../src/utils/viewsGenerator.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;GAYG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,GAAE,MAAsB,EAAE,OAAO,GAAE,OAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAyQjH"}
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.generateViewsContext = generateViewsContext;
|
|
7
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const glob_1 = require("glob");
|
|
10
|
+
const buildCache_js_1 = require("./buildCache.js");
|
|
11
|
+
/**
|
|
12
|
+
* Generates the context.ts file for custom views.
|
|
13
|
+
* This file exports a polyfill for require.context that registers all views.
|
|
14
|
+
*
|
|
15
|
+
* The generated file will:
|
|
16
|
+
* 1. Import all .tsx files from the views directory (excluding tests and context.tsx itself)
|
|
17
|
+
* 2. Create a registry mapping relative paths to module exports
|
|
18
|
+
* 3. Export a polyfill function that mimics webpack's require.context interface
|
|
19
|
+
*
|
|
20
|
+
* @param cwd - The working directory (defaults to process.cwd())
|
|
21
|
+
* @param verbose - Whether to print progress messages (defaults to true)
|
|
22
|
+
* @returns true if context.ts was generated, false if no views were found
|
|
23
|
+
*/
|
|
24
|
+
async function generateViewsContext(cwd = process.cwd(), verbose = true) {
|
|
25
|
+
const viewsDir = node_path_1.default.join(cwd, 'frontend', 'src', 'views');
|
|
26
|
+
const generatedDir = node_path_1.default.join(cwd, 'frontend', 'generated');
|
|
27
|
+
const contextFilePath = node_path_1.default.join(generatedDir, 'context.ts');
|
|
28
|
+
const frontendViewsFilePath = node_path_1.default.join(generatedDir, 'views.ts');
|
|
29
|
+
const backendGeneratedDir = node_path_1.default.join(cwd, 'backend', 'generated');
|
|
30
|
+
const backendViewsFilePath = node_path_1.default.join(backendGeneratedDir, 'views.ts');
|
|
31
|
+
// Check if views directory exists
|
|
32
|
+
if (!(await fs_extra_1.default.pathExists(viewsDir))) {
|
|
33
|
+
if (verbose) {
|
|
34
|
+
console.log('⚠️ Views directory not found, skipping context.ts generation');
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
// Find all .tsx files in views directory (excluding tests and context.tsx itself)
|
|
39
|
+
const viewFiles = await (0, glob_1.glob)('**/*.tsx', {
|
|
40
|
+
cwd: viewsDir,
|
|
41
|
+
absolute: false,
|
|
42
|
+
ignore: ['**/*.test.tsx', '**/*.spec.tsx', 'context.tsx'],
|
|
43
|
+
});
|
|
44
|
+
// If no views found, skip context.ts creation
|
|
45
|
+
if (viewFiles.length === 0) {
|
|
46
|
+
if (verbose) {
|
|
47
|
+
console.log('ℹ️ No views found, skipping context.ts generation');
|
|
48
|
+
}
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
// Use a sidecar file to track the set of view files for up-to-date check
|
|
52
|
+
const upToDate = await (0, buildCache_js_1.isUpToDate)({
|
|
53
|
+
cwd,
|
|
54
|
+
sourceGlobs: ['frontend/src/views/**/*.tsx'],
|
|
55
|
+
outputFiles: ['frontend/generated/context.ts', 'frontend/generated/views.ts', 'backend/generated/views.ts'],
|
|
56
|
+
sidecarFile: 'frontend/generated/context.ts.sources.json',
|
|
57
|
+
});
|
|
58
|
+
if (upToDate) {
|
|
59
|
+
if (verbose) {
|
|
60
|
+
console.log('✅ Views context up-to-date, skipping');
|
|
61
|
+
}
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
if (verbose) {
|
|
65
|
+
console.log(`📝 Scanning ${viewFiles.length} .tsx file(s) for views...`);
|
|
66
|
+
}
|
|
67
|
+
// Generate import statements and registry entries
|
|
68
|
+
const imports = [];
|
|
69
|
+
const registryEntries = [];
|
|
70
|
+
const viewRegistryEntries = [];
|
|
71
|
+
const viewTypeImports = [];
|
|
72
|
+
const byType = {
|
|
73
|
+
table: [],
|
|
74
|
+
read: [],
|
|
75
|
+
edit: [],
|
|
76
|
+
create: [],
|
|
77
|
+
action: [],
|
|
78
|
+
custom: [],
|
|
79
|
+
};
|
|
80
|
+
for (const file of viewFiles) {
|
|
81
|
+
// Normalize path separators to forward slashes for consistent registry keys
|
|
82
|
+
const normalizedPath = file.replace(/\\/g, '/');
|
|
83
|
+
const viewType = await detectViewType(node_path_1.default.join(viewsDir, normalizedPath));
|
|
84
|
+
if (!viewType) {
|
|
85
|
+
continue;
|
|
86
|
+
} // skip helpers and non-view .tsx files
|
|
87
|
+
// Generate a unique variable name from the file path
|
|
88
|
+
// e.g., "customViews/welcome.tsx" -> "CustomViewsWelcome"
|
|
89
|
+
// e.g., "admin/users.tsx" -> "AdminUsers"
|
|
90
|
+
const varName = generateVariableName(normalizedPath);
|
|
91
|
+
// Generate import statement with relative path (from frontend/generated/ to frontend/src/views/)
|
|
92
|
+
const importPath = '../src/views/' + normalizedPath.replace(/\.tsx$/, '');
|
|
93
|
+
imports.push(`import ${varName} from '${importPath}';`);
|
|
94
|
+
// Add registry entry
|
|
95
|
+
registryEntries.push(` './${normalizedPath}': { default: ${varName} }`);
|
|
96
|
+
const baseName = node_path_1.default.basename(normalizedPath, '.tsx');
|
|
97
|
+
const viewClassName = baseName.charAt(0).toUpperCase() + baseName.slice(1);
|
|
98
|
+
byType[viewType].push(viewClassName);
|
|
99
|
+
viewRegistryEntries.push(` ${viewClassName}: typeof import('${importPath}').default;`);
|
|
100
|
+
viewTypeImports.push(` | typeof import('${importPath}').default`);
|
|
101
|
+
}
|
|
102
|
+
const viewCount = Object.values(byType).reduce((sum, names) => sum + names.length, 0);
|
|
103
|
+
// Ensure the generated directories exist
|
|
104
|
+
await fs_extra_1.default.ensureDir(generatedDir);
|
|
105
|
+
await fs_extra_1.default.ensureDir(backendGeneratedDir);
|
|
106
|
+
// Generate the complete context.ts file
|
|
107
|
+
const content = `/**
|
|
108
|
+
* Context Loader - Auto-generated
|
|
109
|
+
*
|
|
110
|
+
* This file is automatically generated by the Slingr CLI.
|
|
111
|
+
* Do not edit manually - changes will be overwritten.
|
|
112
|
+
*
|
|
113
|
+
* Generated: ${new Date().toISOString()}
|
|
114
|
+
* Views: ${viewCount}
|
|
115
|
+
*/
|
|
116
|
+
|
|
117
|
+
// Import and register field metadata before any views are loaded
|
|
118
|
+
import './gql';
|
|
119
|
+
${imports.join('\n')}
|
|
120
|
+
|
|
121
|
+
// Create a map of filename -> module
|
|
122
|
+
const views: Record<string, any> = {
|
|
123
|
+
${registryEntries.join(',\n')}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// Create a polyfill for require.context
|
|
127
|
+
// The framework expects a function that takes a key and returns the module
|
|
128
|
+
const contextPolyfill = (key: string) => {
|
|
129
|
+
return views[key];
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
// Attach the 'keys' method which returns the list of filenames
|
|
133
|
+
(contextPolyfill as any).keys = () => Object.keys(views);
|
|
134
|
+
|
|
135
|
+
export const customViewsContext = contextPolyfill as any;
|
|
136
|
+
|
|
137
|
+
export type AppViewClass =
|
|
138
|
+
${viewTypeImports.join('\n')};
|
|
139
|
+
|
|
140
|
+
declare global {
|
|
141
|
+
interface SlingrViewRegistry {
|
|
142
|
+
${viewRegistryEntries.join('\n')}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export {};`;
|
|
147
|
+
const categoryMeta = [
|
|
148
|
+
{
|
|
149
|
+
key: 'table',
|
|
150
|
+
exportName: 'tableViewNames',
|
|
151
|
+
typeName: 'TableViewName',
|
|
152
|
+
ifaceName: 'SlingrTableViewNameRegistry',
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
key: 'read',
|
|
156
|
+
exportName: 'readViewNames',
|
|
157
|
+
typeName: 'ReadViewName',
|
|
158
|
+
ifaceName: 'SlingrReadViewNameRegistry',
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
key: 'edit',
|
|
162
|
+
exportName: 'editViewNames',
|
|
163
|
+
typeName: 'EditViewName',
|
|
164
|
+
ifaceName: 'SlingrEditViewNameRegistry',
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
key: 'create',
|
|
168
|
+
exportName: 'createViewNames',
|
|
169
|
+
typeName: 'CreateViewName',
|
|
170
|
+
ifaceName: 'SlingrCreateViewNameRegistry',
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
key: 'action',
|
|
174
|
+
exportName: 'actionViewNames',
|
|
175
|
+
typeName: 'ActionViewName',
|
|
176
|
+
ifaceName: 'SlingrActionViewNameRegistry',
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
key: 'custom',
|
|
180
|
+
exportName: 'customViewNames',
|
|
181
|
+
typeName: 'CustomViewName',
|
|
182
|
+
ifaceName: 'SlingrCustomViewNameRegistry',
|
|
183
|
+
},
|
|
184
|
+
];
|
|
185
|
+
const categoryBlocks = categoryMeta.map(({ key, exportName, typeName }) => {
|
|
186
|
+
const names = byType[key];
|
|
187
|
+
return `export const ${exportName} = [\n${names.map(n => ` '${n}'`).join(',\n')}\n] as const;\nexport type ${typeName} = typeof ${exportName}[number];`;
|
|
188
|
+
});
|
|
189
|
+
const allViewNames = categoryMeta.flatMap(({ key }) => byType[key]);
|
|
190
|
+
const allViewNameRegistryEntries = allViewNames.map(n => ` ${n}: true;`);
|
|
191
|
+
const categoryRegistryBlocks = categoryMeta.map(({ ifaceName, key }) => ` interface ${ifaceName} {\n${byType[key].map(n => ` ${n}: true;`).join('\n')}\n }`);
|
|
192
|
+
const sharedViewsContent = `/**
|
|
193
|
+
* View Names - Auto-generated
|
|
194
|
+
*
|
|
195
|
+
* This file is automatically generated by the Slingr CLI.
|
|
196
|
+
* Do not edit manually - changes will be overwritten.
|
|
197
|
+
*
|
|
198
|
+
* Generated: ${new Date().toISOString()}
|
|
199
|
+
* Views: ${viewCount}
|
|
200
|
+
*/
|
|
201
|
+
|
|
202
|
+
${categoryBlocks.join('\n\n')}
|
|
203
|
+
|
|
204
|
+
export const viewNames = [
|
|
205
|
+
...tableViewNames,
|
|
206
|
+
...readViewNames,
|
|
207
|
+
...editViewNames,
|
|
208
|
+
...createViewNames,
|
|
209
|
+
...actionViewNames,
|
|
210
|
+
...customViewNames,
|
|
211
|
+
] as const;
|
|
212
|
+
|
|
213
|
+
export type ViewName = typeof viewNames[number];
|
|
214
|
+
|
|
215
|
+
declare global {
|
|
216
|
+
${categoryRegistryBlocks.join('\n')}
|
|
217
|
+
interface SlingrViewNameRegistry {
|
|
218
|
+
${allViewNameRegistryEntries.join('\n')}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export {};
|
|
223
|
+
`;
|
|
224
|
+
// Backend views file: module format (with declare global + exports) so that
|
|
225
|
+
// a static import in generate-schema.ts activates the type augmentations for
|
|
226
|
+
// schema compilation via ts-node.
|
|
227
|
+
const backendViewsContent = `/**
|
|
228
|
+
* View Name Type Registries - Auto-generated
|
|
229
|
+
*
|
|
230
|
+
* This file is automatically generated by the Slingr CLI.
|
|
231
|
+
* Do not edit manually - changes will be overwritten.
|
|
232
|
+
*
|
|
233
|
+
* Generated: ${new Date().toISOString()}
|
|
234
|
+
* Views: ${viewCount}
|
|
235
|
+
*
|
|
236
|
+
* Imported by the schema generation script so that declare global augmentations
|
|
237
|
+
* are active during TypeScript compilation of backend models.
|
|
238
|
+
*/
|
|
239
|
+
|
|
240
|
+
declare global {
|
|
241
|
+
${categoryRegistryBlocks.join('\n')}
|
|
242
|
+
interface SlingrViewNameRegistry {
|
|
243
|
+
${allViewNameRegistryEntries.join('\n')}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export {};
|
|
248
|
+
`;
|
|
249
|
+
// Write the generated files
|
|
250
|
+
await fs_extra_1.default.writeFile(contextFilePath, content, 'utf-8');
|
|
251
|
+
await fs_extra_1.default.writeFile(frontendViewsFilePath, sharedViewsContent, 'utf-8');
|
|
252
|
+
await fs_extra_1.default.writeFile(backendViewsFilePath, backendViewsContent, 'utf-8');
|
|
253
|
+
// Update the sidecar file with the current set of view files
|
|
254
|
+
await (0, buildCache_js_1.updateFileSetSidecar)({
|
|
255
|
+
cwd,
|
|
256
|
+
sourceGlobs: ['frontend/src/views/**/*.tsx'],
|
|
257
|
+
outputFiles: ['frontend/generated/context.ts', 'frontend/generated/views.ts', 'backend/generated/views.ts'],
|
|
258
|
+
sidecarFile: 'frontend/generated/context.ts.sources.json',
|
|
259
|
+
});
|
|
260
|
+
if (verbose) {
|
|
261
|
+
console.log(`✅ Generated context.ts with ${viewCount} view(s)`);
|
|
262
|
+
}
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Detects the view type of a .tsx file by scanning for a recognized view decorator.
|
|
267
|
+
* Returns null if no recognized decorator is found (e.g. layout helpers).
|
|
268
|
+
*/
|
|
269
|
+
async function detectViewType(filePath) {
|
|
270
|
+
const content = await fs_extra_1.default.readFile(filePath, 'utf-8');
|
|
271
|
+
if (/@TableView[\s<(]/.test(content)) {
|
|
272
|
+
return 'table';
|
|
273
|
+
}
|
|
274
|
+
if (/@ReadView[\s<(]/.test(content)) {
|
|
275
|
+
return 'read';
|
|
276
|
+
}
|
|
277
|
+
if (/@EditView[\s<(]/.test(content)) {
|
|
278
|
+
return 'edit';
|
|
279
|
+
}
|
|
280
|
+
if (/@CreateView[\s<(]/.test(content)) {
|
|
281
|
+
return 'create';
|
|
282
|
+
}
|
|
283
|
+
if (/@ActionView[\s<(]/.test(content)) {
|
|
284
|
+
return 'action';
|
|
285
|
+
}
|
|
286
|
+
if (/@CustomView[\s<(]/.test(content)) {
|
|
287
|
+
return 'custom';
|
|
288
|
+
}
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Generates a unique variable name from a file path.
|
|
293
|
+
*
|
|
294
|
+
* Examples:
|
|
295
|
+
* - "customViews/welcome.tsx" -> "CustomViewsWelcome"
|
|
296
|
+
* - "admin/users.tsx" -> "AdminUsers"
|
|
297
|
+
* - "user.tsx" -> "User"
|
|
298
|
+
*
|
|
299
|
+
* @param filePath - The file path relative to views directory
|
|
300
|
+
* @returns A valid TypeScript variable name in PascalCase
|
|
301
|
+
*/
|
|
302
|
+
function generateVariableName(filePath) {
|
|
303
|
+
// Remove .tsx extension
|
|
304
|
+
const withoutExt = filePath.replace(/\.tsx$/, '');
|
|
305
|
+
// Split by path separators and non-alphanumeric characters
|
|
306
|
+
const parts = withoutExt.split(/[\/\-_\.]/);
|
|
307
|
+
// Convert to PascalCase
|
|
308
|
+
const pascalCase = parts.map(part => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()).join('');
|
|
309
|
+
return pascalCase || 'View';
|
|
310
|
+
}
|
|
311
|
+
//# sourceMappingURL=viewsGenerator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"viewsGenerator.js","sourceRoot":"","sources":["../../src/utils/viewsGenerator.ts"],"names":[],"mappings":"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"}
|