@azure-net/cli 2.3.62 → 4.0.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 (91) hide show
  1. package/.prettierrc +7 -0
  2. package/bin/azure-net.js +247 -157
  3. package/bin/azure-net.ts +253 -0
  4. package/eslint.config.js +19 -0
  5. package/package.json +12 -5
  6. package/src/commands/generate/generateCrudBase.js +95 -114
  7. package/src/commands/generate/generateCrudPresenter.js +135 -142
  8. package/src/commands/generate/generateModule.js +21 -21
  9. package/src/commands/generate/generateModuleBase.js +92 -114
  10. package/src/commands/generate/generateModulePresenter.js +73 -80
  11. package/src/commands/generate/generatePresenter.js +38 -44
  12. package/src/commands/generate/generateRepository.js +41 -47
  13. package/src/commands/generate/generateSchema.js +74 -70
  14. package/src/commands/generate/generateService.js +32 -37
  15. package/src/commands/generate/index.js +0 -5
  16. package/src/generate/layers/generateRepository.js +124 -0
  17. package/src/generate/layers/generateRepositoryMethod.js +102 -0
  18. package/src/generate/layers/generateUseCases.js +50 -0
  19. package/src/generate/layers/repositoryShared.js +569 -0
  20. package/src/generate/module/generateDomain.js +146 -0
  21. package/src/generate/module/generateDomain.ts +147 -0
  22. package/src/generate/module/generateModule.js +84 -0
  23. package/src/generate/module/generateModule.ts +84 -0
  24. package/src/generate/module/generatePresenter.js +419 -0
  25. package/src/generate/module/generatePresenter.ts +442 -0
  26. package/src/generate/module/generateRepository.js +144 -0
  27. package/src/generate/module/generateRepository.ts +158 -0
  28. package/src/generate/module/generateSchemaFromType.js +320 -0
  29. package/src/generate/module/generateSchemaFromType.ts +325 -0
  30. package/src/generate/module/generateTypesJson.js +252 -0
  31. package/src/generate/module/generateTypesJson.ts +259 -0
  32. package/src/generate/module/generateUseCases.js +67 -0
  33. package/src/generate/module/generateUseCases.ts +67 -0
  34. package/src/generate/module/repositoryModuleShared.js +598 -0
  35. package/src/generate/ui/generateComponent.js +98 -0
  36. package/src/generate/ui/generateComponent.ts +100 -0
  37. package/src/generate/ui/generateDesignComponent.js +71 -0
  38. package/src/generate/ui/generateDesignComponent.ts +71 -0
  39. package/src/generate/ui/generateWidget.js +71 -0
  40. package/src/generate/ui/generateWidget.ts +71 -0
  41. package/src/init/initAliases.js +159 -0
  42. package/src/init/initAliases.ts +167 -0
  43. package/src/init/initEdges.js +74 -0
  44. package/src/init/initEdges.ts +74 -0
  45. package/src/init/initStructure.js +122 -0
  46. package/src/init/initStructure.ts +124 -0
  47. package/src/install/installFresh.js +101 -0
  48. package/src/install/installFresh.ts +101 -0
  49. package/src/plugins/addLint.js +257 -0
  50. package/src/plugins/addLint.ts +274 -0
  51. package/src/plugins/index.js +1 -0
  52. package/src/plugins/index.ts +1 -0
  53. package/src/scaffolds/createCoreMiddleware.js +27 -0
  54. package/src/scaffolds/createCoreMiddleware.ts +27 -0
  55. package/src/scaffolds/createCoreSchema.js +141 -0
  56. package/src/scaffolds/createCoreSchema.ts +142 -0
  57. package/src/scaffolds/createDatasource.js +173 -0
  58. package/src/scaffolds/createDatasource.ts +175 -0
  59. package/src/scaffolds/createDatasourceProvider.js +164 -0
  60. package/src/scaffolds/createDatasourceProvider.ts +175 -0
  61. package/src/scaffolds/createMiddleware.js +105 -0
  62. package/src/scaffolds/createMiddleware.ts +105 -0
  63. package/src/scaffolds/createPresenterFactory.js +112 -0
  64. package/src/scaffolds/createPresenterFactory.ts +114 -0
  65. package/src/scaffolds/createResponse.js +64 -0
  66. package/src/scaffolds/createResponse.ts +64 -0
  67. package/src/scaffolds/createSchemaRule.js +40 -0
  68. package/src/scaffolds/createSchemaRule.ts +42 -0
  69. package/src/scaffolds/createTranslationManager.js +78 -0
  70. package/src/scaffolds/createTranslationManager.ts +78 -0
  71. package/src/scaffolds/index.js +9 -0
  72. package/src/scaffolds/index.ts +9 -0
  73. package/src/utils/contextUtils.js +56 -49
  74. package/src/utils/fileUtils.js +72 -84
  75. package/src/utils/loadConfig.js +57 -13
  76. package/tsconfig.json +19 -0
  77. package/src/commands/generate/generateComponent.js +0 -53
  78. package/src/commands/generate/generateDatasource.js +0 -84
  79. package/src/commands/generate/generateDesignComponent.js +0 -53
  80. package/src/commands/generate/generateResponse.js +0 -41
  81. package/src/commands/generate/generateWidget.js +0 -53
  82. package/src/commands/init/index.js +0 -9
  83. package/src/commands/init/initAliases.js +0 -52
  84. package/src/commands/init/initEdges.js +0 -42
  85. package/src/commands/init/initLint.js +0 -138
  86. package/src/commands/init/initMiddleware.js +0 -21
  87. package/src/commands/init/initPresenter.js +0 -25
  88. package/src/commands/init/initSchema.js +0 -22
  89. package/src/commands/init/initStructure.js +0 -140
  90. package/src/commands/init/initTranslations.js +0 -59
  91. package/src/commands/init/migrateStructure.js +0 -144
@@ -0,0 +1,101 @@
1
+ import prompts from 'prompts';
2
+ import { addLint } from '../plugins/index.js';
3
+ import initEdges from '../init/initEdges.js';
4
+ import initStructure from '../init/initStructure.js';
5
+ import { normalizeContexts } from '../init/initAliases.js';
6
+ import { loadUserConfig } from '../utils/loadConfig.js';
7
+ import {
8
+ createCoreMiddleware,
9
+ createCoreSchema,
10
+ createDatasource,
11
+ createDatasourceProvider,
12
+ createMiddleware,
13
+ createPresenterFactory,
14
+ createResponse,
15
+ createTranslationManager
16
+ } from '../scaffolds/index.js';
17
+
18
+ const printContextsError = (): void => {
19
+ console.error('❌ Cannot run "install fresh": `contexts` is missing or empty in azure-net.config.ts/js');
20
+ console.error('Add contexts first, for example:');
21
+ console.error('export default {');
22
+ console.error("\tcontexts: ['web', 'admin']");
23
+ console.error('\t// or');
24
+ console.error("\t// contexts: [{ name: 'web', alias: '$web' }, { name: 'admin', alias: '$admin' }]");
25
+ console.error('};');
26
+ };
27
+
28
+ const askConfirm = async (message: string): Promise<boolean> => {
29
+ const result = await prompts({
30
+ type: 'confirm',
31
+ name: 'confirmed',
32
+ message,
33
+ initial: true
34
+ });
35
+
36
+ return Boolean(result.confirmed);
37
+ };
38
+
39
+ const runOptionalStep = async (question: string, action: () => Promise<void>): Promise<void> => {
40
+ const shouldRun = await askConfirm(question);
41
+ if (!shouldRun) return;
42
+
43
+ try {
44
+ await action();
45
+ } catch (error) {
46
+ console.warn(`⚠️ Step failed: ${question}`);
47
+ console.warn(error);
48
+ }
49
+ };
50
+
51
+ export default async function installFresh(): Promise<void> {
52
+ const config = await loadUserConfig();
53
+ const contexts = normalizeContexts(config.contexts);
54
+
55
+ if (!contexts.length) {
56
+ printContextsError();
57
+ process.exitCode = 1;
58
+ return;
59
+ }
60
+
61
+ await initStructure();
62
+ await initEdges();
63
+
64
+ await runOptionalStep('Add commit tools (lint/commit conventions)?', async () => {
65
+ await addLint();
66
+ });
67
+
68
+ await runOptionalStep('Create middleware manager?', async () => {
69
+ await createCoreMiddleware();
70
+ });
71
+
72
+ await runOptionalStep('Create starter middleware?', async () => {
73
+ await createMiddleware();
74
+ });
75
+
76
+ await runOptionalStep('Create schema factory?', async () => {
77
+ await createCoreSchema();
78
+ });
79
+
80
+ await runOptionalStep('Create presenter factory?', async () => {
81
+ await createPresenterFactory();
82
+ });
83
+
84
+ await runOptionalStep('Create API response?', async () => {
85
+ await createResponse();
86
+ });
87
+
88
+ await runOptionalStep('Create datasource?', async () => {
89
+ await createDatasource();
90
+ });
91
+
92
+ await runOptionalStep('Create datasource provider?', async () => {
93
+ await createDatasourceProvider();
94
+ });
95
+
96
+ await runOptionalStep('Create translation manager (i18n)?', async () => {
97
+ await createTranslationManager();
98
+ });
99
+
100
+ console.log('✅ install fresh completed');
101
+ }
@@ -0,0 +1,257 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { execSync } from 'node:child_process';
4
+
5
+ const dependencies = ['@commitlint/cli', 'semantic-release', '@semantic-release/git', 'git-cz', 'husky', 'commitizen', 'env-cmd'];
6
+
7
+ const commitlintConfig = `export default {
8
+ rules: {
9
+ 'body-leading-blank': [2, 'always'],
10
+ 'footer-leading-blank': [2, 'always'],
11
+ 'header-max-length': [2, 'always', 72],
12
+ 'subject-empty': [2, 'never'],
13
+ 'subject-full-stop': [2, 'never', '.'],
14
+ 'type-case': [2, 'always', 'lower-case'],
15
+ 'type-empty': [2, 'never'],
16
+ 'type-enum': [2, 'always', ['feat', 'fix', 'refactor', 'perf', 'chore', 'docs', 'style', 'test', 'ci']]
17
+ }
18
+ };
19
+ `;
20
+
21
+ const releaseConfig = `export default {
22
+ branches: ['main', 'dev'],
23
+ dryRun: false,
24
+ ci: false,
25
+ plugins: [
26
+ [
27
+ '@semantic-release/commit-analyzer',
28
+ {
29
+ releaseRules: [
30
+ { type: 'release', release: 'major' },
31
+ { type: 'feature', release: 'minor' },
32
+ { type: 'perf', release: false },
33
+ { type: 'refactor', release: false },
34
+ { type: 'fix', release: 'patch' },
35
+ { type: 'chore', release: false },
36
+ { type: 'ci', release: false },
37
+ { type: 'docs', scope: 'README', release: false },
38
+ { type: 'test', release: false },
39
+ { type: 'style', release: false }
40
+ ]
41
+ }
42
+ ],
43
+ '@semantic-release/release-notes-generator'
44
+ ]
45
+ };
46
+ `;
47
+
48
+ const prettierConfig = `{
49
+ "useTabs": true,
50
+ "singleQuote": true,
51
+ "trailingComma": "none",
52
+ "tabWidth": 2,
53
+ "semi": true,
54
+ "printWidth": 150,
55
+ "plugins": ["prettier-plugin-svelte"],
56
+ "overrides": [
57
+ {
58
+ "files": "*.svelte",
59
+ "options": {
60
+ "parser": "svelte"
61
+ }
62
+ }
63
+ ]
64
+ }
65
+ `;
66
+
67
+ const resolveInstallCommand = (manager) => {
68
+ const deps = dependencies.join(' ');
69
+ switch (manager) {
70
+ case 'pnpm':
71
+ return `pnpm add -D ${deps}`;
72
+ case 'npm':
73
+ return `npm install -D ${deps}`;
74
+ case 'yarn':
75
+ return `yarn add -D ${deps}`;
76
+ case 'bun':
77
+ return `bun add -d ${deps}`;
78
+ default:
79
+ return `pnpm add -D ${deps}`;
80
+ }
81
+ };
82
+
83
+ const resolveRunScriptCommand = (manager, script) => {
84
+ switch (manager) {
85
+ case 'pnpm':
86
+ return `pnpm ${script}`;
87
+ case 'npm':
88
+ return `npm run ${script}`;
89
+ case 'yarn':
90
+ return `yarn ${script}`;
91
+ case 'bun':
92
+ return `bun run ${script}`;
93
+ default:
94
+ return `pnpm ${script}`;
95
+ }
96
+ };
97
+
98
+ const resolveHuskyCommand = (manager) => {
99
+ switch (manager) {
100
+ case 'pnpm':
101
+ return 'pnpm exec husky';
102
+ case 'npm':
103
+ return 'npx husky';
104
+ case 'yarn':
105
+ return 'yarn husky';
106
+ case 'bun':
107
+ return 'bunx husky';
108
+ default:
109
+ return 'pnpm exec husky';
110
+ }
111
+ };
112
+
113
+ const detectPackageManager = (cwd) => {
114
+ if (fs.existsSync(path.join(cwd, 'bun.lock')) || fs.existsSync(path.join(cwd, 'bun.lockb'))) return 'bun';
115
+ if (fs.existsSync(path.join(cwd, 'pnpm-lock.yaml'))) return 'pnpm';
116
+ if (fs.existsSync(path.join(cwd, 'yarn.lock'))) return 'yarn';
117
+ if (fs.existsSync(path.join(cwd, 'package-lock.json'))) return 'npm';
118
+ return undefined;
119
+ };
120
+
121
+ const parseConfigState = (cwd) => {
122
+ const tsPath = path.join(cwd, 'azure-net.config.ts');
123
+ const jsPath = path.join(cwd, 'azure-net.config.js');
124
+ const configPath = fs.existsSync(tsPath) ? tsPath : fs.existsSync(jsPath) ? jsPath : null;
125
+
126
+ if (!configPath) {
127
+ return {
128
+ configPath: null,
129
+ content: null,
130
+ hasPackageManagerKey: false,
131
+ validPackageManager: null
132
+ };
133
+ }
134
+
135
+ const content = fs.readFileSync(configPath, 'utf-8');
136
+ const hasPackageManagerKey = /packageManager\s*:/.test(content);
137
+ const managerMatch = content.match(/packageManager\s*:\s*['"`](bun|pnpm|npm|yarn)['"`]/);
138
+ const validPackageManager = managerMatch?.[1] ?? null;
139
+
140
+ return {
141
+ configPath,
142
+ content,
143
+ hasPackageManagerKey,
144
+ validPackageManager
145
+ };
146
+ };
147
+
148
+ const upsertPackageManagerInConfig = (content, manager) => {
149
+ const packageManagerEntry = `packageManager: '${manager}'`;
150
+ const hasExportDefaultObject = /export\s+default\s*\{[\s\S]*\}\s*;?/.test(content);
151
+
152
+ if (!hasExportDefaultObject) {
153
+ return `export default {\n\t${packageManagerEntry}\n};\n`;
154
+ }
155
+
156
+ if (/packageManager\s*:/.test(content)) {
157
+ return content.replace(/packageManager\s*:\s*['"`][^'"`]+['"`]/, packageManagerEntry);
158
+ }
159
+
160
+ return content.replace(/export\s+default\s*\{([\s\S]*?)\}\s*;?/, (_full, body) => {
161
+ const trimmedRight = body.replace(/\s*$/, '');
162
+ if (!trimmedRight.length) {
163
+ return `export default {\n\t${packageManagerEntry}\n};`;
164
+ }
165
+
166
+ const withComma = trimmedRight.endsWith(',') ? trimmedRight : `${trimmedRight},`;
167
+ return `export default {${withComma}\n\t${packageManagerEntry}\n};`;
168
+ });
169
+ };
170
+
171
+ const localOnlyPrepareScript = `node -e "const local = !process.env.CI && process.env.NODE_ENV !== 'production' && !process.env.DOCKER && !process.env.CONTAINER; process.exit(local ? 1 : 0)" || (husky && svelte-kit sync)`;
172
+
173
+ const selectPackageManager = async (cwd, preset) => {
174
+ if (preset) return preset;
175
+ const { default: prompts } = await import('prompts');
176
+
177
+ const order = ['bun', 'pnpm', 'npm', 'yarn'];
178
+ const detected = detectPackageManager(cwd);
179
+ const response = await prompts({
180
+ type: 'select',
181
+ name: 'manager',
182
+ message: 'Choose your package manager:',
183
+ choices: order.map((item) => ({ title: item, value: item })),
184
+ initial: detected ? order.indexOf(detected) : 0
185
+ });
186
+
187
+ if (!response.manager) {
188
+ throw new Error('Package manager is required');
189
+ }
190
+ return response.manager;
191
+ };
192
+
193
+ export default async function addLint(options = {}) {
194
+ const cwd = process.cwd();
195
+ const pkgPath = path.join(cwd, 'package.json');
196
+
197
+ if (!fs.existsSync(pkgPath)) {
198
+ console.error('❌ package.json not found in this directory');
199
+ process.exit(1);
200
+ }
201
+
202
+ const configState = parseConfigState(cwd);
203
+ const manager = configState.validPackageManager ?? (await selectPackageManager(cwd, options.manager));
204
+
205
+ if (!configState.configPath) {
206
+ const newConfigPath = path.join(cwd, 'azure-net.config.ts');
207
+ fs.writeFileSync(newConfigPath, `export default {\n\tpackageManager: '${manager}'\n};\n`);
208
+ } else if (!configState.validPackageManager || !configState.hasPackageManagerKey) {
209
+ const nextConfig = upsertPackageManagerInConfig(configState.content ?? '', manager);
210
+ fs.writeFileSync(configState.configPath, nextConfig);
211
+ }
212
+
213
+ const installCommand = resolveInstallCommand(manager);
214
+ const runFormatCommand = resolveRunScriptCommand(manager, 'format');
215
+ const preCommitScript = `${resolveRunScriptCommand(manager, 'lint')} && ${resolveRunScriptCommand(manager, 'check')}`;
216
+ const commitScript = `${resolveRunScriptCommand(manager, 'format')} && git add . && git-cz && git push`;
217
+ const releaseScript = `${resolveRunScriptCommand(manager, 'commit')} && ${resolveRunScriptCommand(manager, 'semantic-release')}`;
218
+
219
+ console.log(`📦 Installing packages with ${manager}...`);
220
+ execSync(installCommand, { stdio: 'inherit' });
221
+
222
+ console.log('📁 Updating package.json...');
223
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
224
+ pkg.scripts = {
225
+ ...(pkg.scripts || {}),
226
+ precommit: preCommitScript,
227
+ prepare: localOnlyPrepareScript,
228
+ 'semantic-release': 'env-cmd semantic-release',
229
+ commit: commitScript,
230
+ release: releaseScript
231
+ };
232
+
233
+ pkg.config = pkg.config || {};
234
+ pkg.config.commitizen = {
235
+ path: 'git-cz'
236
+ };
237
+
238
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 4));
239
+ fs.writeFileSync(path.join(cwd, 'commitlint.config.ts'), commitlintConfig);
240
+ fs.writeFileSync(path.join(cwd, 'release.config.ts'), releaseConfig);
241
+ fs.writeFileSync(path.join(cwd, '.prettierrc'), prettierConfig);
242
+
243
+ console.log('🔧 Initializing Husky...');
244
+ try {
245
+ execSync(resolveHuskyCommand(manager), { stdio: 'inherit' });
246
+ } catch {
247
+ console.warn('⚠️ Husky initialization skipped (command failed in current environment).');
248
+ }
249
+
250
+ try {
251
+ execSync(runFormatCommand, { stdio: 'inherit' });
252
+ } catch {
253
+ console.warn('⚠️ Format script execution skipped (script may be missing).');
254
+ }
255
+
256
+ console.log(`✅ Linting and release setup completed! Added prepare script: ${localOnlyPrepareScript}`);
257
+ }
@@ -0,0 +1,274 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { execSync } from 'node:child_process';
4
+
5
+ type PackageManager = 'pnpm' | 'npm' | 'yarn' | 'bun';
6
+
7
+ interface AddLintOptions {
8
+ manager?: PackageManager;
9
+ }
10
+
11
+ interface ConfigState {
12
+ configPath: string | null;
13
+ content: string | null;
14
+ hasPackageManagerKey: boolean;
15
+ validPackageManager: PackageManager | null;
16
+ }
17
+
18
+ const dependencies = ['@commitlint/cli', 'semantic-release', '@semantic-release/git', 'git-cz', 'husky', 'commitizen', 'env-cmd'];
19
+
20
+ const commitlintConfig = `export default {
21
+ rules: {
22
+ 'body-leading-blank': [2, 'always'],
23
+ 'footer-leading-blank': [2, 'always'],
24
+ 'header-max-length': [2, 'always', 72],
25
+ 'subject-empty': [2, 'never'],
26
+ 'subject-full-stop': [2, 'never', '.'],
27
+ 'type-case': [2, 'always', 'lower-case'],
28
+ 'type-empty': [2, 'never'],
29
+ 'type-enum': [2, 'always', ['feat', 'fix', 'refactor', 'perf', 'chore', 'docs', 'style', 'test', 'ci']]
30
+ }
31
+ };
32
+ `;
33
+
34
+ const releaseConfig = `export default {
35
+ branches: ['main', 'dev'],
36
+ dryRun: false,
37
+ ci: false,
38
+ plugins: [
39
+ [
40
+ '@semantic-release/commit-analyzer',
41
+ {
42
+ releaseRules: [
43
+ { type: 'release', release: 'major' },
44
+ { type: 'feature', release: 'minor' },
45
+ { type: 'perf', release: false },
46
+ { type: 'refactor', release: false },
47
+ { type: 'fix', release: 'patch' },
48
+ { type: 'chore', release: false },
49
+ { type: 'ci', release: false },
50
+ { type: 'docs', scope: 'README', release: false },
51
+ { type: 'test', release: false },
52
+ { type: 'style', release: false }
53
+ ]
54
+ }
55
+ ],
56
+ '@semantic-release/release-notes-generator'
57
+ ]
58
+ };
59
+ `;
60
+
61
+ const prettierConfig = `{
62
+ "useTabs": true,
63
+ "singleQuote": true,
64
+ "trailingComma": "none",
65
+ "tabWidth": 2,
66
+ "semi": true,
67
+ "printWidth": 150,
68
+ "plugins": ["prettier-plugin-svelte"],
69
+ "overrides": [
70
+ {
71
+ "files": "*.svelte",
72
+ "options": {
73
+ "parser": "svelte"
74
+ }
75
+ }
76
+ ]
77
+ }
78
+ `;
79
+
80
+ const resolveInstallCommand = (manager: PackageManager): string => {
81
+ const deps = dependencies.join(' ');
82
+ switch (manager) {
83
+ case 'pnpm':
84
+ return `pnpm add -D ${deps}`;
85
+ case 'npm':
86
+ return `npm install -D ${deps}`;
87
+ case 'yarn':
88
+ return `yarn add -D ${deps}`;
89
+ case 'bun':
90
+ return `bun add -d ${deps}`;
91
+ }
92
+ };
93
+
94
+ const resolveRunScriptCommand = (manager: PackageManager, script: string): string => {
95
+ switch (manager) {
96
+ case 'pnpm':
97
+ return `pnpm ${script}`;
98
+ case 'npm':
99
+ return `npm run ${script}`;
100
+ case 'yarn':
101
+ return `yarn ${script}`;
102
+ case 'bun':
103
+ return `bun run ${script}`;
104
+ }
105
+ };
106
+
107
+ const resolveHuskyCommand = (manager: PackageManager): string => {
108
+ switch (manager) {
109
+ case 'pnpm':
110
+ return 'pnpm exec husky';
111
+ case 'npm':
112
+ return 'npx husky';
113
+ case 'yarn':
114
+ return 'yarn husky';
115
+ case 'bun':
116
+ return 'bunx husky';
117
+ }
118
+ };
119
+
120
+ const detectPackageManager = (cwd: string): PackageManager | undefined => {
121
+ if (fs.existsSync(path.join(cwd, 'bun.lock')) || fs.existsSync(path.join(cwd, 'bun.lockb'))) return 'bun';
122
+ if (fs.existsSync(path.join(cwd, 'pnpm-lock.yaml'))) return 'pnpm';
123
+ if (fs.existsSync(path.join(cwd, 'yarn.lock'))) return 'yarn';
124
+ if (fs.existsSync(path.join(cwd, 'package-lock.json'))) return 'npm';
125
+ return undefined;
126
+ };
127
+
128
+ const parseConfigState = (cwd: string): ConfigState => {
129
+ const tsPath = path.join(cwd, 'azure-net.config.ts');
130
+ const jsPath = path.join(cwd, 'azure-net.config.js');
131
+ const configPath = fs.existsSync(tsPath) ? tsPath : fs.existsSync(jsPath) ? jsPath : null;
132
+
133
+ if (!configPath) {
134
+ return {
135
+ configPath: null,
136
+ content: null,
137
+ hasPackageManagerKey: false,
138
+ validPackageManager: null
139
+ };
140
+ }
141
+
142
+ const content = fs.readFileSync(configPath, 'utf-8');
143
+ const hasPackageManagerKey = /packageManager\s*:/.test(content);
144
+ const managerMatch = content.match(/packageManager\s*:\s*['"`](bun|pnpm|npm|yarn)['"`]/);
145
+ const validPackageManager = managerMatch?.[1] as PackageManager | undefined;
146
+
147
+ return {
148
+ configPath,
149
+ content,
150
+ hasPackageManagerKey,
151
+ validPackageManager: validPackageManager ?? null
152
+ };
153
+ };
154
+
155
+ const upsertPackageManagerInConfig = (content: string, manager: PackageManager): string => {
156
+ const packageManagerEntry = `packageManager: '${manager}'`;
157
+ const hasExportDefaultObject = /export\s+default\s*\{[\s\S]*\}\s*;?/.test(content);
158
+
159
+ if (!hasExportDefaultObject) {
160
+ return `export default {\n\t${packageManagerEntry}\n};\n`;
161
+ }
162
+
163
+ if (/packageManager\s*:/.test(content)) {
164
+ return content.replace(/packageManager\s*:\s*['"`][^'"`]+['"`]/, packageManagerEntry);
165
+ }
166
+
167
+ return content.replace(/export\s+default\s*\{([\s\S]*?)\}\s*;?/, (_full, body: string) => {
168
+ const trimmedRight = body.replace(/\s*$/, '');
169
+ if (!trimmedRight.length) {
170
+ return `export default {\n\t${packageManagerEntry}\n};`;
171
+ }
172
+
173
+ const withComma = trimmedRight.endsWith(',') ? trimmedRight : `${trimmedRight},`;
174
+ return `export default {${withComma}\n\t${packageManagerEntry}\n};`;
175
+ });
176
+ };
177
+
178
+ const localOnlyPrepareScript = `node -e "const local = !process.env.CI && process.env.NODE_ENV !== 'production' && !process.env.DOCKER && !process.env.CONTAINER; process.exit(local ? 1 : 0)" || (husky && svelte-kit sync)`;
179
+
180
+ const selectPackageManager = async (cwd: string, preset?: PackageManager): Promise<PackageManager> => {
181
+ if (preset) return preset;
182
+ const { default: prompts } = await import('prompts');
183
+
184
+ const detected = detectPackageManager(cwd);
185
+ const response = await prompts({
186
+ type: 'select',
187
+ name: 'manager',
188
+ message: 'Choose your package manager:',
189
+ choices: [
190
+ { title: 'bun', value: 'bun' },
191
+ { title: 'pnpm', value: 'pnpm' },
192
+ { title: 'npm', value: 'npm' },
193
+ { title: 'yarn', value: 'yarn' }
194
+ ],
195
+ initial: detected ? ['bun', 'pnpm', 'npm', 'yarn'].indexOf(detected) : 0
196
+ });
197
+
198
+ if (!response.manager) {
199
+ throw new Error('Package manager is required');
200
+ }
201
+
202
+ return response.manager as PackageManager;
203
+ };
204
+
205
+ export default async function addLint(options: AddLintOptions = {}): Promise<void> {
206
+ const cwd = process.cwd();
207
+ const pkgPath = path.join(cwd, 'package.json');
208
+
209
+ if (!fs.existsSync(pkgPath)) {
210
+ console.error('❌ package.json not found in this directory');
211
+ process.exit(1);
212
+ }
213
+
214
+ const configState = parseConfigState(cwd);
215
+ const manager = configState.validPackageManager ?? (await selectPackageManager(cwd, options.manager));
216
+
217
+ if (!configState.configPath) {
218
+ const newConfigPath = path.join(cwd, 'azure-net.config.ts');
219
+ fs.writeFileSync(newConfigPath, `export default {\n\tpackageManager: '${manager}'\n};\n`);
220
+ } else if (!configState.validPackageManager || !configState.hasPackageManagerKey) {
221
+ const nextConfig = upsertPackageManagerInConfig(configState.content ?? '', manager);
222
+ fs.writeFileSync(configState.configPath, nextConfig);
223
+ }
224
+
225
+ const installCommand = resolveInstallCommand(manager);
226
+ const runFormatCommand = resolveRunScriptCommand(manager, 'format');
227
+ const preCommitScript = `${resolveRunScriptCommand(manager, 'lint')} && ${resolveRunScriptCommand(manager, 'check')}`;
228
+ const commitScript = `${resolveRunScriptCommand(manager, 'format')} && git add . && git-cz && git push`;
229
+ const releaseScript = `${resolveRunScriptCommand(manager, 'commit')} && ${resolveRunScriptCommand(manager, 'semantic-release')}`;
230
+
231
+ console.log(`📦 Installing packages with ${manager}...`);
232
+ execSync(installCommand, { stdio: 'inherit' });
233
+
234
+ console.log('📁 Updating package.json...');
235
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) as {
236
+ scripts?: Record<string, string>;
237
+ config?: Record<string, unknown>;
238
+ };
239
+
240
+ pkg.scripts = {
241
+ ...(pkg.scripts ?? {}),
242
+ precommit: preCommitScript,
243
+ prepare: localOnlyPrepareScript,
244
+ 'semantic-release': 'env-cmd semantic-release',
245
+ commit: commitScript,
246
+ release: releaseScript
247
+ };
248
+
249
+ pkg.config = pkg.config ?? {};
250
+ pkg.config.commitizen = {
251
+ path: 'git-cz'
252
+ };
253
+
254
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 4));
255
+
256
+ fs.writeFileSync(path.join(cwd, 'commitlint.config.ts'), commitlintConfig);
257
+ fs.writeFileSync(path.join(cwd, 'release.config.ts'), releaseConfig);
258
+ fs.writeFileSync(path.join(cwd, '.prettierrc'), prettierConfig);
259
+
260
+ console.log('🔧 Initializing Husky...');
261
+ try {
262
+ execSync(resolveHuskyCommand(manager), { stdio: 'inherit' });
263
+ } catch {
264
+ console.warn('⚠️ Husky initialization skipped (command failed in current environment).');
265
+ }
266
+
267
+ try {
268
+ execSync(runFormatCommand, { stdio: 'inherit' });
269
+ } catch {
270
+ console.warn('⚠️ Format script execution skipped (script may be missing).');
271
+ }
272
+
273
+ console.log(`✅ Linting and release setup completed! Added prepare script: ${localOnlyPrepareScript}`);
274
+ }
@@ -0,0 +1 @@
1
+ export { default as addLint } from './addLint.js';
@@ -0,0 +1 @@
1
+ export { default as addLint } from './addLint.js';
@@ -0,0 +1,27 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { writeIfNotExists } from '../utils/fileUtils.js';
4
+
5
+ const createMiddlewareManagerTemplate = () => `import { createMiddlewareManager } from '@azure-net/kit';
6
+
7
+ export const { clientMiddleware, serverMiddleware, executeMiddlewares } = createMiddlewareManager([]);
8
+ `;
9
+
10
+ export default async function createCoreMiddleware() {
11
+ const middlewareManagerPath = path.join(process.cwd(), 'src', 'core', 'middleware-manager');
12
+ const middlewaresPath = path.join(middlewareManagerPath, 'middlewares');
13
+ const middlewareManagerFile = path.join(middlewareManagerPath, 'MiddlewareManager.ts');
14
+ const indexFile = path.join(middlewareManagerPath, 'index.ts');
15
+
16
+ await fs.mkdir(middlewaresPath, { recursive: true });
17
+
18
+ const createdManager = await writeIfNotExists(middlewareManagerFile, createMiddlewareManagerTemplate());
19
+ const createdIndex = await writeIfNotExists(indexFile, `export * from './MiddlewareManager';\n`);
20
+
21
+ if (!createdManager && !createdIndex) {
22
+ console.log('⚠️ Core middleware manager already exists. Nothing was overwritten.');
23
+ return;
24
+ }
25
+
26
+ console.log(`✅ Core middleware manager created: ${middlewareManagerPath}`);
27
+ }
@@ -0,0 +1,27 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { writeIfNotExists } from '../utils/fileUtils.js';
4
+
5
+ const createMiddlewareManagerTemplate = (): string => `import { createMiddlewareManager } from '@azure-net/kit';
6
+
7
+ export const { clientMiddleware, serverMiddleware, executeMiddlewares } = createMiddlewareManager([]);
8
+ `;
9
+
10
+ export default async function createCoreMiddleware(): Promise<void> {
11
+ const middlewareManagerPath = path.join(process.cwd(), 'src', 'core', 'middleware-manager');
12
+ const middlewaresPath = path.join(middlewareManagerPath, 'middlewares');
13
+ const middlewareManagerFile = path.join(middlewareManagerPath, 'MiddlewareManager.ts');
14
+ const indexFile = path.join(middlewareManagerPath, 'index.ts');
15
+
16
+ await fs.mkdir(middlewaresPath, { recursive: true });
17
+
18
+ const createdManager = await writeIfNotExists(middlewareManagerFile, createMiddlewareManagerTemplate());
19
+ const createdIndex = await writeIfNotExists(indexFile, `export * from './MiddlewareManager';\n`);
20
+
21
+ if (!createdManager && !createdIndex) {
22
+ console.log('⚠️ Core middleware manager already exists. Nothing was overwritten.');
23
+ return;
24
+ }
25
+
26
+ console.log(`✅ Core middleware manager created: ${middlewareManagerPath}`);
27
+ }