@digicroz/node-backend-kit 1.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.
Files changed (59) hide show
  1. package/README.md +255 -0
  2. package/dist/b2fPortalV3/b2fPortal.d.ts +2 -0
  3. package/dist/b2fPortalV3/b2fPortal.js +199 -0
  4. package/dist/b2fPortalV3/checkModuleRecords.d.ts +1 -0
  5. package/dist/b2fPortalV3/checkModuleRecords.js +60 -0
  6. package/dist/b2fPortalV3/checkModuleZodRecords.d.ts +1 -0
  7. package/dist/b2fPortalV3/checkModuleZodRecords.js +60 -0
  8. package/dist/b2fPortalV3/moduleFileCreator.d.ts +1 -0
  9. package/dist/b2fPortalV3/moduleFileCreator.js +42 -0
  10. package/dist/b2fPortalV3/moduleZodCreator.d.ts +1 -0
  11. package/dist/b2fPortalV3/moduleZodCreator.js +41 -0
  12. package/dist/b2fPortalV3/stripExtensions.d.ts +12 -0
  13. package/dist/b2fPortalV3/stripExtensions.js +51 -0
  14. package/dist/b2fPortalV3/syncProjectCommons.d.ts +8 -0
  15. package/dist/b2fPortalV3/syncProjectCommons.js +180 -0
  16. package/dist/bin/nbk.d.ts +2 -0
  17. package/dist/bin/nbk.js +83 -0
  18. package/dist/cli/addDevVersion.d.ts +1 -0
  19. package/dist/cli/addDevVersion.js +51 -0
  20. package/dist/cli/addProdVersion.d.ts +1 -0
  21. package/dist/cli/addProdVersion.js +71 -0
  22. package/dist/cli/createInitWorkspaceShellFile.d.ts +1 -0
  23. package/dist/cli/createInitWorkspaceShellFile.js +129 -0
  24. package/dist/cli/deleteAllRepos.d.ts +1 -0
  25. package/dist/cli/deleteAllRepos.js +62 -0
  26. package/dist/cli/deleteAndCopy.d.ts +6 -0
  27. package/dist/cli/deleteAndCopy.js +88 -0
  28. package/dist/cli/deployAllRepos.d.ts +1 -0
  29. package/dist/cli/deployAllRepos.js +202 -0
  30. package/dist/cli/fixConfigFile.d.ts +5 -0
  31. package/dist/cli/fixConfigFile.js +76 -0
  32. package/dist/cli/gitAcpAllRepos.d.ts +1 -0
  33. package/dist/cli/gitAcpAllRepos.js +156 -0
  34. package/dist/cli/gitPushAllRepos.d.ts +1 -0
  35. package/dist/cli/gitPushAllRepos.js +70 -0
  36. package/dist/cli/initConfig.d.ts +1 -0
  37. package/dist/cli/initConfig.js +23 -0
  38. package/dist/cli/transfer2Shared.d.ts +1 -0
  39. package/dist/cli/transfer2Shared.js +180 -0
  40. package/dist/configs/environment.d.ts +4 -0
  41. package/dist/configs/environment.js +7 -0
  42. package/dist/helpers/checkCrossProjectImports.d.ts +2 -0
  43. package/dist/helpers/checkCrossProjectImports.js +73 -0
  44. package/dist/index.d.ts +18 -0
  45. package/dist/index.js +47 -0
  46. package/dist/types.d.ts +34 -0
  47. package/dist/types.js +4 -0
  48. package/dist/utils/jsonFile.d.ts +7 -0
  49. package/dist/utils/jsonFile.js +24 -0
  50. package/dist/utils/loadConfig.d.ts +8 -0
  51. package/dist/utils/loadConfig.js +203 -0
  52. package/dist/utils/path.d.ts +6 -0
  53. package/dist/utils/path.js +16 -0
  54. package/dist/utils/progress.d.ts +65 -0
  55. package/dist/utils/progress.js +108 -0
  56. package/dist/utils/vscodeSettings.d.ts +1 -0
  57. package/dist/utils/vscodeSettings.js +67 -0
  58. package/nbk.schema.json +95 -0
  59. package/package.json +80 -0
package/README.md ADDED
@@ -0,0 +1,255 @@
1
+ # Primexop Backend Kit (NBK) 🚀
2
+
3
+ [![npm version](https://badge.fury.io/js/%40primexop%2Fnbk.svg)](https://badge.fury.io/js/%40primexop%2Fnbk)
4
+ [![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](https://opensource.org/licenses/ISC)
5
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.8.3-blue.svg)](https://www.typescriptlang.org/)
6
+ [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D16.0.0-green.svg)](https://nodejs.org/)
7
+
8
+ > A powerful TypeScript utility for managing backend projects with features like B2F Portal integration, cross-project validation, and Next.js support.
9
+
10
+ ## 📦 Features
11
+
12
+ - 🔧 Project configuration management with TypeScript support
13
+ - 🌐 B2F Portal integration support
14
+ - 🔍 Cross-project import validation
15
+ - 💻 VSCode integration with JSON schema validation
16
+ - 🛠️ CLI tools for project management
17
+ - ⚡ Next.js patch support for specific sections
18
+ - 🔄 Shared backend path configuration
19
+
20
+ ## 🚀 Quick Start
21
+
22
+ ### Installation
23
+
24
+ ```bash
25
+ npm install @digicroz/node-backend-kit --save-dev
26
+ ```
27
+
28
+ ### Basic Usage
29
+
30
+ ```typescript
31
+ import { nbkInit } from "@digicroz/node-backend-kit"
32
+
33
+ // Initialize with default config path (nbk.config.json in current directory)
34
+ const config = nbkInit()
35
+
36
+ // Or specify a custom config path
37
+ const config = nbkInit({ configPath: "./custom/path/config.json" })
38
+ ```
39
+
40
+ ## 📋 Requirements
41
+
42
+ - Node.js >= 16.0.0
43
+ - TypeScript >= 5.8.3
44
+
45
+ ## ⚙️ Configuration
46
+
47
+ Create a `nbk.config.json` file in your project root:
48
+
49
+ ```json
50
+ {
51
+ "projects": [
52
+ {
53
+ "projectName": "My Project",
54
+ "projectBaseDirPath": "/path/to/project",
55
+ "sharedBackendPath": "/path/to/shared-backend",
56
+ "sections": [
57
+ {
58
+ "sectionName": "API",
59
+ "repository": {
60
+ "name": "my-api",
61
+ "path": "https://github.com/organization/my-api"
62
+ },
63
+ "localPath": "/path/to/api",
64
+ "isZodCreator": true,
65
+ "needNextJsPatch": false
66
+ }
67
+ ]
68
+ }
69
+ ],
70
+ "b2fPortal": false,
71
+ "checkCrossProjectImports": true
72
+ }
73
+ ```
74
+
75
+ ### 📝 Configuration Options
76
+
77
+ #### Project Configuration
78
+
79
+ - `projectName`: Name of your project
80
+ - `projectBaseDirPath`: Base directory path for the project
81
+ - `sharedBackendPath`: (Optional) Path to shared backend code
82
+ - `sections`: Array of project sections
83
+
84
+ #### Section Configuration
85
+
86
+ - `sectionName`: Name of the section
87
+ - `repository`: Repository information
88
+ - `name`: Repository name
89
+ - `path`: Repository URL
90
+ - `localPath`: Local path where the section code resides
91
+ - `isZodCreator`: Whether the section uses Zod for validation
92
+ - `needNextJsPatch`: (Optional) Whether the section needs Next.js patch
93
+
94
+ #### Global Configuration
95
+
96
+ - `b2fPortal`: Enable/disable B2F Portal integration
97
+ - `checkCrossProjectImports`: Enable/disable cross-project import validation
98
+
99
+ ## 🔧 VSCode Integration
100
+
101
+ This package includes JSON schema validation for your configuration file. To enable auto-completion and validation in VSCode:
102
+
103
+ 1. Install the "JSON Language Support" extension in VSCode
104
+ 2. Add this to your VSCode settings.json:
105
+
106
+ ```json
107
+ {
108
+ "json.schemas": [
109
+ {
110
+ "fileMatch": ["nbk.config.json"],
111
+ "url": "./node_modules/@digicroz/node-backend-kit/nbk.schema.json"
112
+ }
113
+ ],
114
+ "files.associations": {
115
+ "nbk.config.json": "jsonc"
116
+ }
117
+ }
118
+ ```
119
+
120
+ ### 💡 Benefits
121
+
122
+ - ✨ Auto-completion for all available options
123
+ - ✅ Validation to ensure your configuration is correct
124
+ - 📚 Hover documentation for each field
125
+ - ⚠️ Error highlighting for invalid configurations
126
+
127
+ ## 🚀 Features in Detail
128
+
129
+ ### B2F Portal Integration
130
+
131
+ When `b2fPortal` is set to `true` in the configuration, the kit will initialize B2F Portal specific features.
132
+
133
+ ### Cross-Project Import Validation
134
+
135
+ When `checkCrossProjectImports` is enabled, the kit will validate imports between different projects to ensure proper dependency management.
136
+
137
+ ### Next.js Patch Support
138
+
139
+ Sections can be configured with `needNextJsPatch: true` to apply Next.js specific patches.
140
+
141
+ ## 🛠️ CLI Commands
142
+
143
+ NBK comes with several CLI commands to help you manage your projects:
144
+
145
+ ```bash
146
+ # Initialize a nbk.config.json file
147
+ npx @digicroz/node-backend-kit init
148
+
149
+ # Fix JSON file formatting
150
+ npx @digicroz/node-backend-kit fix-config-file
151
+
152
+ # Delete b2fPortal directory in all repositories
153
+ npx @digicroz/node-backend-kit delete-all-repos
154
+
155
+ # Deploy all repositories
156
+ npx @digicroz/node-backend-kit deploy-all-repos
157
+
158
+ # Add, commit, and push changes in all repositories
159
+ npx @digicroz/node-backend-kit git-acp-all-repos
160
+
161
+ # Push b2fPortal changes in all repositories
162
+ npx @digicroz/node-backend-kit git-push-all-repos
163
+
164
+ # Transfer project files to shared backend repositories
165
+ npx @digicroz/node-backend-kit transfer-2-shared
166
+
167
+ # Create a shell script to initialize workspaces
168
+ npx @digicroz/node-backend-kit create-init-workspace-shell-file
169
+
170
+ # Update package.json to use local development version
171
+ npx @digicroz/node-backend-kit add-dev-version
172
+
173
+ # Update package.json to use published production version
174
+ npx @digicroz/node-backend-kit add-prod-version
175
+ ```
176
+
177
+ ### Development and Production Versioning
178
+
179
+ NBK provides commands to easily switch between development and production versions:
180
+
181
+ - `add-dev-version` updates your project to use the local development version from `C:/primexopRepos/nbk`
182
+ - `add-prod-version` reverts back to using the published npm version (latest by default)
183
+
184
+ Examples:
185
+
186
+ ```bash
187
+ # Switch to local development version
188
+ npx @digicroz/node-backend-kit add-dev-version
189
+
190
+ # Switch back to latest published version
191
+ npx @digicroz/node-backend-kit add-prod-version
192
+
193
+ # Switch to a specific published version
194
+ npx @digicroz/node-backend-kit add-prod-version --version "1.0.7"
195
+
196
+ # Apply to a different directory
197
+ npx @digicroz/node-backend-kit add-prod-version --dir ../other-project
198
+ ```
199
+
200
+ ### Workspace Initialization Script
201
+
202
+ The `create-init-workspace-shell-file` command generates a shell script (`initWorkspace.sh`) that helps you:
203
+
204
+ - Select your preferred editor (VSCode, Cursor, or Trae)
205
+ - Open all your project directories in the selected editor
206
+ - Navigate between project sections easily
207
+
208
+ After generating the script, make it executable:
209
+
210
+ ```bash
211
+ chmod +x initWorkspace.sh
212
+ ```
213
+
214
+ Then run it:
215
+
216
+ ```bash
217
+ ./initWorkspace.sh
218
+ ```
219
+
220
+ ## 👩‍💻 Development
221
+
222
+ ### Available Scripts
223
+
224
+ - `npm run dev` - Start development mode with watch
225
+ - `npm run build` - Build the project
226
+ - `npm test` - Run tests
227
+ - `npm run test:watch` - Run tests in watch mode
228
+ - `npm run lint` - Run TypeScript type checking
229
+ - `npm run clean` - Clean build artifacts
230
+ - `npm run release:patch` - Release a patch version
231
+
232
+ ### Project Structure
233
+
234
+ ```
235
+ src/
236
+ ├── bin/ # CLI entry points
237
+ ├── cli/ # CLI command implementations
238
+ ├── configs/ # Configuration related code
239
+ ├── helpers/ # Helper functions
240
+ ├── utils/ # Utility functions
241
+ ├── b2fPortalV3/ # B2F Portal specific implementations
242
+ └── types.ts # TypeScript type definitions
243
+ ```
244
+
245
+ ## 📄 License
246
+
247
+ ISC
248
+
249
+ ## 🤝 Contributing
250
+
251
+ Contributions are welcome! Please feel free to submit a Pull Request.
252
+
253
+ ## 📞 Support
254
+
255
+ For support, please open an issue in the [GitHub repository](https://github.com/AdarshHatkar/nbk/issues).
@@ -0,0 +1,2 @@
1
+ import { TNbkProject } from "../types.js";
2
+ export declare const b2fPortalInit: (b2fPortalProjects: TNbkProject[]) => Promise<void>;
@@ -0,0 +1,199 @@
1
+ import fs from "fs";
2
+ import { join } from "path";
3
+ import { createZodFiles } from "./moduleZodCreator.js";
4
+ import { syncFilesAndFolders } from "./syncProjectCommons.js";
5
+ import { createModuleFiles } from "./moduleFileCreator.js";
6
+ import { checkModuleRecords } from "./checkModuleRecords.js";
7
+ import { checkModuleZodRecords } from "./checkModuleZodRecords.js";
8
+ import { getTsFiles, updateImports } from "./stripExtensions.js";
9
+ export const b2fPortalInit = async (b2fPortalProjects) => {
10
+ console.log("------------nbk Started-------------");
11
+ let clientRootDirPath = process.cwd();
12
+ // console.log({clientRootDirPath});
13
+ const srcDirPath = join(clientRootDirPath, "src");
14
+ const distDirPath = join(clientRootDirPath, "dist");
15
+ for (const project of b2fPortalProjects) {
16
+ const serverB2fPath = join(srcDirPath, "serverB2f");
17
+ // console.log('serverB2fPath', serverB2fPath);
18
+ if (!fs.existsSync(serverB2fPath)) {
19
+ console.log("serverB2fPath does not exist");
20
+ console.log({ serverB2fPath });
21
+ return;
22
+ }
23
+ const projectSrcPath = join(srcDirPath, project.projectBaseDirPath);
24
+ // console.log('projectSrcpath', projectSrcPath);
25
+ if (!fs.existsSync(projectSrcPath)) {
26
+ console.log("projectSrcPath does not exist");
27
+ console.log({ projectSrcPath });
28
+ return;
29
+ }
30
+ const projectDistPath = join(distDirPath, project.projectBaseDirPath);
31
+ // console.log('projectDistPath', projectDistPath);
32
+ if (!fs.existsSync(projectDistPath)) {
33
+ console.log("projectDistPath does not exist");
34
+ console.log({ projectDistPath });
35
+ return;
36
+ }
37
+ const projectPrismaClientPath = join(clientRootDirPath, "prisma", project.projectName, "generatedClient");
38
+ if (!fs.existsSync(projectPrismaClientPath)) {
39
+ console.log("projectPrismaClientPath does not exist");
40
+ console.log({ projectPrismaClientPath });
41
+ return;
42
+ }
43
+ const projectB2fPath = join(projectSrcPath, "projectB2f");
44
+ if (!fs.existsSync(projectB2fPath)) {
45
+ console.log("projectB2fPath does not exist");
46
+ console.log({ projectB2fPath });
47
+ return;
48
+ }
49
+ if (project.sections.length === 0) {
50
+ console.log("no sections in " + project.projectName);
51
+ return;
52
+ }
53
+ for (const section of project.sections) {
54
+ const sectionSrcPath = join(projectSrcPath, section.localPath);
55
+ const sectionDistPath = join(projectDistPath, section.localPath);
56
+ if (!fs.existsSync(sectionSrcPath)) {
57
+ console.log("sectionSrcPath does not exist");
58
+ console.log({ sectionSrcPath });
59
+ return;
60
+ }
61
+ if (!fs.existsSync(sectionDistPath)) {
62
+ console.log("sectionDistPath does not exist");
63
+ console.log({ sectionDistPath });
64
+ return;
65
+ }
66
+ const sectionB2fPath = join(sectionSrcPath, "sectionB2f");
67
+ if (!fs.existsSync(sectionB2fPath)) {
68
+ console.log("sectionB2fPath does not exist");
69
+ console.log({ sectionB2fPath });
70
+ return;
71
+ }
72
+ const sectionSrcTrpcApiPath = join(sectionSrcPath, "trpcApi");
73
+ if (!fs.existsSync(sectionSrcTrpcApiPath)) {
74
+ console.log("sectionSrcTrpcApiPath does not exist");
75
+ console.log({ sectionSrcTrpcApiPath });
76
+ return;
77
+ }
78
+ const sectionSrcTrpcApiModulePath = join(sectionSrcTrpcApiPath, "modules");
79
+ if (!fs.existsSync(sectionSrcTrpcApiModulePath)) {
80
+ console.log("sectionSrcTrpcApiModulePath does not exist");
81
+ console.log({ sectionSrcTrpcApiModulePath });
82
+ return;
83
+ }
84
+ const sectionDistTrpcApiPath = join(sectionDistPath, "trpcApi");
85
+ // console.log('sectionDistTrpcApiPath', sectionDistTrpcApiPath);
86
+ if (!fs.existsSync(sectionDistTrpcApiPath)) {
87
+ console.log("sectionDistTrpcApiPath does not exist");
88
+ console.log({ sectionDistTrpcApiPath });
89
+ return;
90
+ }
91
+ const sectionTrpcRouterTypesDeclarationPath = join(sectionDistPath, "trpcApi", "trpcRouter.d.ts");
92
+ if (!fs.existsSync(sectionTrpcRouterTypesDeclarationPath)) {
93
+ console.log("sectionTrpcRouterTypesDeclarationPath does not exist");
94
+ console.log({ sectionTrpcRouterTypesDeclarationPath });
95
+ return;
96
+ }
97
+ const repositoryPath = join(clientRootDirPath, section.repository.path);
98
+ if (!fs.existsSync(repositoryPath)) {
99
+ console.log("repositoryPath does not exist");
100
+ console.log({ repositoryPath });
101
+ return;
102
+ }
103
+ if (!fs.existsSync(join(repositoryPath, ".git"))) {
104
+ console.log("repositoryPath does not have .git");
105
+ console.log({ repositoryPath });
106
+ return;
107
+ }
108
+ const repositoryPackageJsonPath = join(repositoryPath, "package.json");
109
+ if (!fs.existsSync(repositoryPackageJsonPath)) {
110
+ console.log("repositoryPackageJsonPath does not exist");
111
+ console.log({ repositoryPackageJsonPath });
112
+ return;
113
+ }
114
+ const repositoryPackageJson = JSON.parse(fs.readFileSync(repositoryPackageJsonPath, "utf8"));
115
+ if (!repositoryPackageJson.name) {
116
+ console.log("repositoryPackageJson.name does not exist");
117
+ console.log({ repositoryPackageJson });
118
+ return;
119
+ }
120
+ if (repositoryPackageJson.name !== section.repository.name) {
121
+ console.log("repositoryPackageJson.name does not match ");
122
+ console.log({
123
+ requiredName: section.repository.name,
124
+ repositoryName: repositoryPackageJson.name,
125
+ });
126
+ return;
127
+ }
128
+ const repositoryBackedPortalPath = join(repositoryPath, "b2fPortal");
129
+ if (!fs.existsSync(repositoryBackedPortalPath)) {
130
+ console.log("repositoryBackedPortalPath does not exist");
131
+ console.log({ repositoryBackedPortalPath });
132
+ return;
133
+ }
134
+ const repositoryDistTrpcApiPath = join(repositoryBackedPortalPath, sectionDistTrpcApiPath.replace(clientRootDirPath, ""));
135
+ const repositoryPrismaClientPath = join(repositoryBackedPortalPath, projectPrismaClientPath.replace(clientRootDirPath, ""));
136
+ createModuleFiles(sectionSrcTrpcApiModulePath);
137
+ // create zod files
138
+ createZodFiles(sectionSrcTrpcApiModulePath);
139
+ // check trpcRouterRecords and zodSchemas
140
+ try {
141
+ checkModuleRecords(sectionSrcTrpcApiPath);
142
+ checkModuleZodRecords(sectionSrcTrpcApiPath);
143
+ }
144
+ catch (error) {
145
+ console.warn(error);
146
+ }
147
+ // sync serverB2f
148
+ const repositoryServerB2fPath = join(repositoryBackedPortalPath, "serverB2f");
149
+ await syncFilesAndFolders({
150
+ sourceDirPath: serverB2fPath,
151
+ targetDirPath: repositoryServerB2fPath,
152
+ });
153
+ // sync projectB2f
154
+ const repositoryProjectB2fPath = join(repositoryBackedPortalPath, "projectB2f");
155
+ await syncFilesAndFolders({
156
+ sourceDirPath: projectB2fPath,
157
+ targetDirPath: repositoryProjectB2fPath,
158
+ });
159
+ // sync section common
160
+ const repositorySectionB2fPath = join(repositoryBackedPortalPath, section.sectionName, "sectionB2f");
161
+ await syncFilesAndFolders({
162
+ sourceDirPath: sectionB2fPath,
163
+ targetDirPath: repositorySectionB2fPath,
164
+ });
165
+ // sync zod schemas
166
+ const repositoryTrpcApiPath = join(repositoryBackedPortalPath, section.sectionName, "trpcApi");
167
+ await syncFilesAndFolders({
168
+ sourceDirPath: sectionSrcTrpcApiPath,
169
+ targetDirPath: repositoryTrpcApiPath,
170
+ fileNamePatterns: ["Zod", "zodSchemas"],
171
+ });
172
+ await syncFilesAndFolders({
173
+ sourceDirPath: sectionDistTrpcApiPath,
174
+ targetDirPath: repositoryDistTrpcApiPath,
175
+ fileNamePatterns: ["trpcRouter.d.ts"],
176
+ });
177
+ await syncFilesAndFolders({
178
+ sourceDirPath: projectPrismaClientPath,
179
+ targetDirPath: repositoryPrismaClientPath,
180
+ fileNamePatterns: [
181
+ // "index.js",
182
+ // "index.d.ts",
183
+ // "library.js",
184
+ // "library.d.ts",
185
+ ".d.ts",
186
+ ],
187
+ });
188
+ if (section.needNextJsPatch) {
189
+ // console.log("Next Js Patch started");
190
+ const tsFiles = getTsFiles(repositoryBackedPortalPath);
191
+ tsFiles.forEach((filePath) => {
192
+ updateImports(filePath);
193
+ });
194
+ // console.log("Next Js Patch completed");
195
+ }
196
+ }
197
+ }
198
+ console.log("------------nbk finished-------------");
199
+ };
@@ -0,0 +1 @@
1
+ export declare const checkModuleRecords: (baseDir: string) => void;
@@ -0,0 +1,60 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ // Recursively checks if all internal modules have correct entries in their parent router file
4
+ const checkSubModules = (parentModuleDir, parentRouterFile) => {
5
+ const subItems = fs.readdirSync(parentModuleDir);
6
+ subItems.forEach((item) => {
7
+ const itemPath = path.join(parentModuleDir, item);
8
+ if (fs.lstatSync(itemPath).isDirectory()) {
9
+ // If it's a directory, expect that it has a corresponding .ts file
10
+ const subModuleRouter = path.join(itemPath, `${item}.ts`);
11
+ if (fs.existsSync(subModuleRouter)) {
12
+ // Check that the submodule is included in the parent router file
13
+ const parentRouterContent = fs.readFileSync(parentRouterFile, "utf-8");
14
+ const expectedRouteEntry = `${item}: ${item}Routes`;
15
+ if (!parentRouterContent.includes(expectedRouteEntry)) {
16
+ throw new Error(`\n\n ${expectedRouteEntry}, \n\nis missing in ${path.basename(parentRouterFile)}, \n\nPath:${parentRouterFile}\n\n`);
17
+ }
18
+ // Recursively check subdirectories
19
+ checkSubModules(itemPath, subModuleRouter);
20
+ }
21
+ else {
22
+ console.log(`Warning: Expected ${subModuleRouter} not found in ${itemPath}`);
23
+ }
24
+ }
25
+ });
26
+ };
27
+ // Main function to check the first level in trpcRouter.ts and recurse for internal levels
28
+ export const checkModuleRecords = (baseDir) => {
29
+ const trpcRouterPath = path.join(baseDir, "trpcRouter.ts");
30
+ // Check if trpcRouter.ts file exists
31
+ if (!fs.existsSync(trpcRouterPath)) {
32
+ throw new Error(`Error: trpcRouter.ts file not found in ${baseDir}`);
33
+ }
34
+ // Read trpcRouter.ts content
35
+ const trpcRouterContent = fs.readFileSync(trpcRouterPath, "utf-8");
36
+ // List of first-level directories inside /modules
37
+ const modulesPath = path.join(baseDir, "modules");
38
+ const modules = fs.readdirSync(modulesPath).filter((file) => {
39
+ const moduleDir = path.join(modulesPath, file);
40
+ return fs.lstatSync(moduleDir).isDirectory();
41
+ });
42
+ // Iterate over first-level modules to check for corresponding entries in trpcRouter.ts
43
+ for (const moduleName of modules) {
44
+ const moduleDir = path.join(modulesPath, moduleName);
45
+ const moduleRouterFile = path.join(moduleDir, `${moduleName}.ts`);
46
+ // Ensure the first-level module .ts file exists and is in trpcRouter.ts
47
+ if (fs.existsSync(moduleRouterFile)) {
48
+ const routeName = `${moduleName}: ${moduleName}Routes`;
49
+ if (!trpcRouterContent.includes(routeName)) {
50
+ throw new Error(`\n\n ${routeName}, \n\n is missing in trpcRouter.ts \n\nPath:${trpcRouterPath}\n\n`);
51
+ }
52
+ // Recursively check submodules for this first-level module
53
+ checkSubModules(moduleDir, moduleRouterFile);
54
+ }
55
+ else {
56
+ console.log(`Warning: ${moduleRouterFile} does not exist, skipping check for ${moduleName}`);
57
+ }
58
+ }
59
+ // console.log("All module and sub-module routes are correctly defined.");
60
+ };
@@ -0,0 +1 @@
1
+ export declare const checkModuleZodRecords: (baseDir: string) => void;
@@ -0,0 +1,60 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ // Recursively checks if all internal Zod schemas have correct entries in their parent Zod schema file
4
+ const checkSubZodSchemas = (parentModuleDir, parentZodFile) => {
5
+ const subItems = fs.readdirSync(parentModuleDir);
6
+ subItems.forEach((item) => {
7
+ const itemPath = path.join(parentModuleDir, item);
8
+ if (fs.lstatSync(itemPath).isDirectory()) {
9
+ // If it's a directory, expect that it has a corresponding Zod schema file
10
+ const subZodFile = path.join(itemPath, `${item}Zod.ts`);
11
+ if (fs.existsSync(subZodFile)) {
12
+ // Check that the submodule's Zod schema is included in the parent Zod file
13
+ const parentZodContent = fs.readFileSync(parentZodFile, "utf-8");
14
+ const expectedSchemaEntry = `${item}: ${item}ZodSchema`;
15
+ if (!parentZodContent.includes(expectedSchemaEntry)) {
16
+ throw new Error(`\n\n ${expectedSchemaEntry},\n\nis missing in ${path.basename(parentZodFile)},\n\nPath:${parentZodFile}\n\n`);
17
+ }
18
+ // Recursively check subdirectories for further internal schemas
19
+ checkSubZodSchemas(itemPath, subZodFile);
20
+ }
21
+ else {
22
+ console.log(`Warning: Expected ${subZodFile} not found in ${itemPath}`);
23
+ }
24
+ }
25
+ });
26
+ };
27
+ // Main function to check first-level Zod schemas in zodSchemas.ts and recurse for internal levels
28
+ export const checkModuleZodRecords = (baseDir) => {
29
+ const zodSchemasPath = path.join(baseDir, "zodSchemas.ts");
30
+ // Check if zodSchemas.ts file exists
31
+ if (!fs.existsSync(zodSchemasPath)) {
32
+ throw new Error(`Error: zodSchemas.ts file not found in ${baseDir}`);
33
+ }
34
+ // Read zodSchemas.ts content
35
+ const zodSchemasContent = fs.readFileSync(zodSchemasPath, "utf-8");
36
+ // List of first-level directories inside /modules
37
+ const modulesPath = path.join(baseDir, "modules");
38
+ const modules = fs.readdirSync(modulesPath).filter((file) => {
39
+ const moduleDir = path.join(modulesPath, file);
40
+ return fs.lstatSync(moduleDir).isDirectory();
41
+ });
42
+ // Iterate over first-level modules to check for corresponding Zod schemas in zodSchemas.ts
43
+ for (const moduleName of modules) {
44
+ const moduleDir = path.join(modulesPath, moduleName);
45
+ const moduleZodFile = path.join(moduleDir, `${moduleName}Zod.ts`);
46
+ // Ensure the first-level Zod schema file exists and is in zodSchemas.ts
47
+ if (fs.existsSync(moduleZodFile)) {
48
+ const schemaName = `${moduleName}: ${moduleName}ZodSchema`;
49
+ if (!zodSchemasContent.includes(schemaName)) {
50
+ throw new Error(`\n\n ${schemaName},\n\n is missing in zodSchemas.ts,\n\nPath:${zodSchemasPath}\n\n`);
51
+ }
52
+ // Recursively check submodules for this first-level module
53
+ checkSubZodSchemas(moduleDir, moduleZodFile);
54
+ }
55
+ else {
56
+ console.log(`Warning: ${moduleZodFile} does not exist, skipping check for ${moduleName}`);
57
+ }
58
+ }
59
+ // console.log("All Zod schema entries are correctly defined.");
60
+ };
@@ -0,0 +1 @@
1
+ export declare function createModuleFiles(baseDir: string): void;
@@ -0,0 +1,42 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ // Function to check if a directory contains a .ts file and create it if necessary
4
+ export function createModuleFiles(baseDir) {
5
+ // Read the contents of the base directory
6
+ const items = fs.readdirSync(baseDir);
7
+ // Iterate through each item in the base directory
8
+ items.forEach((item) => {
9
+ const itemPath = path.join(baseDir, item);
10
+ // Check if the item is a directory
11
+ if (fs.statSync(itemPath).isDirectory()) {
12
+ const tsFilePath = path.join(itemPath, `${item}.ts`);
13
+ // Prepare the content
14
+ const importStatement = ` import { trpcRouter } from` + ` "@global/trpc/trpc.js";`;
15
+ const fileContent = `\n\n export const ${item}Routes = trpcRouter({});\n`;
16
+ // Ensure that the directory contains a .ts file with the same name as the directory
17
+ if (!fs.existsSync(tsFilePath)) {
18
+ // If the file does not exist, create it with the import and content
19
+ fs.writeFileSync(tsFilePath, importStatement + fileContent);
20
+ console.log(`File ${tsFilePath} created with import and default content.`);
21
+ }
22
+ else {
23
+ // Check if the .ts file is empty
24
+ const fileStats = fs.statSync(tsFilePath);
25
+ if (fileStats.size === 0) {
26
+ // Add the import statement and export function only if the file is empty
27
+ fs.writeFileSync(tsFilePath, importStatement + fileContent);
28
+ // console.log(
29
+ // `File ${tsFilePath} was empty and import and default content were added.`
30
+ // );
31
+ }
32
+ else {
33
+ // console.log(
34
+ // `File ${tsFilePath} already exists and is not empty. No changes made.`
35
+ // );
36
+ }
37
+ }
38
+ // Recursively call the function to check subdirectories
39
+ createModuleFiles(itemPath);
40
+ }
41
+ });
42
+ }
@@ -0,0 +1 @@
1
+ export declare function createZodFiles(directoryPath: string): void;
@@ -0,0 +1,41 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ export function createZodFiles(directoryPath) {
4
+ fs.readdir(directoryPath, (err, files) => {
5
+ if (err) {
6
+ console.error("Error reading directory:", err);
7
+ return;
8
+ }
9
+ files.forEach((file) => {
10
+ const filePath = path.join(directoryPath, file);
11
+ fs.stat(filePath, (err, stats) => {
12
+ if (err) {
13
+ console.error("Error accessing file:", err);
14
+ return;
15
+ }
16
+ if (stats.isDirectory()) {
17
+ // Recursively call for subdirectories
18
+ createZodFiles(filePath);
19
+ }
20
+ else if (file.endsWith(".ts") && !file.endsWith("Zod.ts")) {
21
+ const newFileName = `${path.parse(file).name}Zod.ts`;
22
+ const newFilePath = path.join(directoryPath, newFileName);
23
+ if (!fs.existsSync(newFilePath)) {
24
+ const newData = `export const ${path.parse(file).name}ZodSchema = {\n\t\n};\n`;
25
+ fs.writeFile(newFilePath, newData, (err) => {
26
+ if (err) {
27
+ console.error("Error creating new file:", err);
28
+ }
29
+ else {
30
+ console.log(`Created ${newFileName}`);
31
+ }
32
+ });
33
+ }
34
+ else {
35
+ // console.log(`${newFileName} already exists, skipping...`);
36
+ }
37
+ }
38
+ });
39
+ });
40
+ });
41
+ }