@unisphere/nx 4.4.1 → 4.5.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 (29) hide show
  1. package/dist/generators/add-application/add-application.d.ts.map +1 -1
  2. package/dist/generators/add-application/add-application.js +5 -3
  3. package/dist/generators/add-documentation/add-documentation.d.ts.map +1 -1
  4. package/dist/generators/add-documentation/add-documentation.js +9 -21
  5. package/dist/generators/add-documentation/schema.d.ts +0 -2
  6. package/dist/generators/add-documentation/schema.json +1 -11
  7. package/dist/generators/add-package/add-package.d.ts.map +1 -1
  8. package/dist/generators/add-package/add-package.js +3 -1
  9. package/dist/generators/add-runtime/add-runtime.d.ts.map +1 -1
  10. package/dist/generators/add-runtime/add-runtime.js +3 -1
  11. package/dist/generators/change-application-scope/change-application-scope.d.ts +5 -0
  12. package/dist/generators/change-application-scope/change-application-scope.d.ts.map +1 -0
  13. package/dist/generators/change-application-scope/change-application-scope.js +240 -0
  14. package/dist/generators/change-application-scope/schema.d.ts +4 -0
  15. package/dist/generators/change-application-scope/schema.json +22 -0
  16. package/dist/generators/change-package-scope/change-package-scope.d.ts.map +1 -1
  17. package/dist/generators/change-package-scope/change-package-scope.js +12 -1
  18. package/dist/generators/rename-application/rename-application.d.ts +5 -0
  19. package/dist/generators/rename-application/rename-application.d.ts.map +1 -0
  20. package/dist/generators/rename-application/rename-application.js +293 -0
  21. package/dist/generators/rename-application/schema.d.ts +4 -0
  22. package/dist/generators/rename-application/schema.json +21 -0
  23. package/dist/generators/utils.d.ts +3 -0
  24. package/dist/generators/utils.d.ts.map +1 -1
  25. package/dist/generators/utils.js +47 -0
  26. package/dist/migrations/3-15-0/add-experience-documentation.d.ts.map +1 -1
  27. package/dist/migrations/3-15-0/add-experience-documentation.js +0 -1
  28. package/generators.json +10 -0
  29. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"add-application.d.ts","sourceRoot":"","sources":["../../../src/generators/add-application/add-application.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,IAAI,EAAgD,MAAM,YAAY,CAAC;AAE5G,OAAO,EAAE,6BAA6B,EAAE,MAAM,UAAU,CAAC;AAuEzD,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,6BAA6B,uBA0KvC;AAED,eAAe,uBAAuB,CAAC"}
1
+ {"version":3,"file":"add-application.d.ts","sourceRoot":"","sources":["../../../src/generators/add-application/add-application.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,IAAI,EAAgD,MAAM,YAAY,CAAC;AAE5G,OAAO,EAAE,6BAA6B,EAAE,MAAM,UAAU,CAAC;AAwEzD,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,6BAA6B,uBA6KvC;AAED,eAAe,uBAAuB,CAAC"}
@@ -77,8 +77,8 @@ async function addApplicationGenerator(tree, options) {
77
77
  // Extract environment variables
78
78
  const widgetName = unisphereConfig.name;
79
79
  let applicationName = options.name;
80
- if (isPlayground && !options.name.endsWith('-dev')) {
81
- applicationName += '-dev';
80
+ if (isPlayground && !options.name.endsWith('-playground')) {
81
+ applicationName += '-playground';
82
82
  }
83
83
  const applicationNameAsLowerDashCase = (0, devkit_1.names)(applicationName).fileName;
84
84
  const typesPackageInfo = (0, utils_1.findTypesOrCorePackageInfo)(tree);
@@ -102,7 +102,9 @@ async function addApplicationGenerator(tree, options) {
102
102
  subdirectory,
103
103
  projectRoot,
104
104
  };
105
- // Check if the application already exists
105
+ // Check if name already exists across all element types in .unisphere
106
+ (0, utils_1.validateElementNameUnique)(tree, applicationNameAsLowerDashCase, 'applications');
107
+ // Check if the application already exists on filesystem
106
108
  if (tree.exists(projectRoot)) {
107
109
  throw new Error(`Application "${applicationNameAsLowerDashCase}" already exists at ${projectRoot}.\n` +
108
110
  'Please choose a different application name or remove the existing application first.');
@@ -1 +1 @@
1
- {"version":3,"file":"add-documentation.d.ts","sourceRoot":"","sources":["../../../src/generators/add-documentation/add-documentation.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,IAAI,EAAiB,MAAM,YAAY,CAAC;AAG7E,OAAO,EAAE,+BAA+B,EAAE,MAAM,UAAU,CAAC;AA0C3D,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,+BAA+B,qCA6IzC;AAED,eAAe,yBAAyB,CAAC"}
1
+ {"version":3,"file":"add-documentation.d.ts","sourceRoot":"","sources":["../../../src/generators/add-documentation/add-documentation.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,IAAI,EAAiB,MAAM,YAAY,CAAC;AAG7E,OAAO,EAAE,+BAA+B,EAAE,MAAM,UAAU,CAAC;AAsB3D,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,+BAA+B,qCAiJzC;AAED,eAAe,yBAAyB,CAAC"}
@@ -8,15 +8,7 @@ const path = tslib_1.__importStar(require("path"));
8
8
  const utils_1 = require("../utils");
9
9
  const discover_typedoc_plugins_1 = require("./discover-typedoc-plugins");
10
10
  function validateOptions(options) {
11
- if (options.name) {
12
- const namePattern = /^[a-zA-Z][a-zA-Z0-9\-\s]*$/;
13
- if (!namePattern.test(options.name)) {
14
- throw new Error(`Invalid value '${options.name}' for option 'name'\n` +
15
- ` Pattern: ^[a-zA-Z][a-zA-Z0-9\\-\\s]*$\n` +
16
- ` Received: ${options.name}`);
17
- }
18
- }
19
- if (!options.isExperienceLevel && options.subName) {
11
+ if (options.subName) {
20
12
  const subNamePattern = /^[a-zA-Z][a-zA-Z0-9\-\s]*$/;
21
13
  if (!subNamePattern.test(options.subName)) {
22
14
  throw new Error(`Invalid value '${options.subName}' for option 'subName'\n` +
@@ -24,13 +16,6 @@ function validateOptions(options) {
24
16
  ` Received: ${options.subName}`);
25
17
  }
26
18
  }
27
- if (!options.isExperienceLevel && !options.subName) {
28
- throw new Error(`Missing required option: 'subName'\n` +
29
- ` Description: Sub-name for the documentation site (used when not experience-level)\n` +
30
- ` Type: string\n` +
31
- ` Pattern: ^[a-zA-Z][a-zA-Z0-9\\-\\s]*$\n` +
32
- ` Example: nx g @unisphere/nx:add-documentation --subName=api-docs`);
33
- }
34
19
  }
35
20
  async function addDocumentationGenerator(tree, options) {
36
21
  // Validate options
@@ -54,8 +39,8 @@ async function addDocumentationGenerator(tree, options) {
54
39
  'This will update your workspace pattern to support documentation sites.');
55
40
  }
56
41
  }
57
- // Resolve experience name: use --name flag, or auto-resolve from .unisphere config
58
- const documentationName = options.name || unisphereConfig.name;
42
+ // Resolve experience name from .unisphere config
43
+ const documentationName = unisphereConfig.name;
59
44
  const documentationNameAsLowerDashCase = (0, devkit_1.names)(documentationName).fileName;
60
45
  devkit_1.logger.info(`Using experience name: ${documentationNameAsLowerDashCase}`);
61
46
  // Build the full documentation name
@@ -64,10 +49,13 @@ async function addDocumentationGenerator(tree, options) {
64
49
  ? `${documentationNameAsLowerDashCase}-${subNameAsLowerDashCase}`
65
50
  : documentationNameAsLowerDashCase;
66
51
  const projectRoot = `unisphere/documentation/${fullDocumentationName}`;
67
- // Check if the documentation site already exists
52
+ // Check if name already exists across all element types in .unisphere
53
+ (0, utils_1.validateElementNameUnique)(tree, fullDocumentationName, 'documentation');
54
+ // Check if documentation already exists on filesystem
68
55
  if (tree.exists(projectRoot)) {
69
- throw new Error(`Documentation site "${fullDocumentationName}" already exists at ${projectRoot}.\n` +
70
- 'Please choose a different name or remove the existing documentation site first.');
56
+ const docType = subNameAsLowerDashCase ? `sub-documentation "${subNameAsLowerDashCase}"` : 'main documentation';
57
+ throw new Error(`Documentation site already exists: ${docType} at ${projectRoot}.\n` +
58
+ 'Please choose a different sub-name or remove the existing documentation site first.');
71
59
  }
72
60
  // Discover publishable packages for typedoc plugin auto-configuration
73
61
  const discoveredPlugins = (0, discover_typedoc_plugins_1.discoverTypedocPlugins)(tree, projectRoot);
@@ -1,6 +1,4 @@
1
1
  export interface AddDocumentationGeneratorSchema {
2
- name?: string;
3
- isExperienceLevel?: boolean;
4
2
  subName?: string;
5
3
  skipInstall?: boolean;
6
4
  }
@@ -4,19 +4,9 @@
4
4
  "title": "Add Documentation Generator",
5
5
  "type": "object",
6
6
  "properties": {
7
- "name": {
8
- "type": "string",
9
- "description": "Experience name. Auto-resolved from .unisphere config if not provided.",
10
- "pattern": "^[a-zA-Z][a-zA-Z0-9\\-\\s]*$"
11
- },
12
- "isExperienceLevel": {
13
- "type": "boolean",
14
- "description": "Whether this is an experience-level documentation site (no sub-name needed)",
15
- "default": false
16
- },
17
7
  "subName": {
18
8
  "type": "string",
19
- "description": "Sub-name for the documentation site (used when not experience-level)",
9
+ "description": "Sub-name for the documentation site. If not provided, creates the main experience-level documentation.",
20
10
  "pattern": "^[a-zA-Z][a-zA-Z0-9\\-\\s]*$"
21
11
  },
22
12
  "skipInstall": {
@@ -1 +1 @@
1
- {"version":3,"file":"add-package.d.ts","sourceRoot":"","sources":["../../../src/generators/add-package/add-package.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,IAAI,EAAgD,MAAM,YAAY,CAAC;AAE5G,OAAO,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AA8GrD,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,yBAAyB,uBAwHnC;AAED,eAAe,mBAAmB,CAAC"}
1
+ {"version":3,"file":"add-package.d.ts","sourceRoot":"","sources":["../../../src/generators/add-package/add-package.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,IAAI,EAAgD,MAAM,YAAY,CAAC;AAE5G,OAAO,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AA+GrD,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,yBAAyB,uBA2HnC;AAED,eAAe,mBAAmB,CAAC"}
@@ -128,7 +128,9 @@ async function addPackageGenerator(tree, options) {
128
128
  ...transformedPackageName,
129
129
  tmpl: '',
130
130
  };
131
- // Check if the project already exists
131
+ // Check if name already exists across all element types in .unisphere
132
+ (0, utils_1.validateElementNameUnique)(tree, userInputPackageName, 'packages');
133
+ // Check if the project already exists on filesystem
132
134
  if (tree.exists(projectRoot)) {
133
135
  throw new Error(`Package "${userInputPackageName}" already exists at ${projectRoot}.\n` +
134
136
  'Please choose a different package name or remove the existing package first.');
@@ -1 +1 @@
1
- {"version":3,"file":"add-runtime.d.ts","sourceRoot":"","sources":["../../../src/generators/add-runtime/add-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,IAAI,EAAsC,MAAM,YAAY,CAAC;AAElG,OAAO,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AA+DrD,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,yBAAyB,uBAyGnC;AAED,eAAe,mBAAmB,CAAC"}
1
+ {"version":3,"file":"add-runtime.d.ts","sourceRoot":"","sources":["../../../src/generators/add-runtime/add-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,IAAI,EAAsC,MAAM,YAAY,CAAC;AAElG,OAAO,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AAgErD,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,yBAAyB,uBA4GnC;AAED,eAAe,mBAAmB,CAAC"}
@@ -64,7 +64,9 @@ async function addRuntimeGenerator(tree, options) {
64
64
  tmpl: '',
65
65
  };
66
66
  const projectRoot = `unisphere/runtimes/${userInputRuntimeName}`;
67
- // Check if the runtime already exists
67
+ // Check if name already exists across all element types in .unisphere
68
+ (0, utils_1.validateElementNameUnique)(tree, userInputRuntimeName, 'runtimes');
69
+ // Check if the runtime already exists on filesystem
68
70
  if (tree.exists(projectRoot)) {
69
71
  throw new Error(`Runtime "${userInputRuntimeName}" already exists at ${projectRoot}.\n` +
70
72
  'Please choose a different runtime name or remove the existing runtime first.');
@@ -0,0 +1,5 @@
1
+ import { Tree } from '@nx/devkit';
2
+ import { ChangeApplicationScopeGeneratorSchema } from './schema';
3
+ export declare function changeApplicationScopeGenerator(tree: Tree, options: ChangeApplicationScopeGeneratorSchema): Promise<void>;
4
+ export default changeApplicationScopeGenerator;
5
+ //# sourceMappingURL=change-application-scope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"change-application-scope.d.ts","sourceRoot":"","sources":["../../../src/generators/change-application-scope/change-application-scope.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EAKL,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,qCAAqC,EAAE,MAAM,UAAU,CAAC;AAqRjE,wBAAsB,+BAA+B,CACnD,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,qCAAqC,iBA6E/C;AAED,eAAe,+BAA+B,CAAC"}
@@ -0,0 +1,240 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.changeApplicationScopeGenerator = changeApplicationScopeGenerator;
4
+ const devkit_1 = require("@nx/devkit");
5
+ const generators_1 = require("@nx/workspace/generators");
6
+ const utils_1 = require("../utils");
7
+ function validateOptions(options) {
8
+ if (!options.applicationName || options.applicationName.trim() === '') {
9
+ throw new Error(`Missing required option: 'applicationName'\n` +
10
+ ` Description: The name of the application to move\n` +
11
+ ` Type: string\n` +
12
+ ` Pattern: ^[a-zA-Z][a-zA-Z0-9\\-\\s]*$\n` +
13
+ ` Example: nx g @unisphere/nx:change-application-scope --applicationName=my-app --newScope=local`);
14
+ }
15
+ const namePattern = /^[a-zA-Z][a-zA-Z0-9\-\s]*$/;
16
+ if (!namePattern.test(options.applicationName)) {
17
+ throw new Error(`Invalid value '${options.applicationName}' for option 'applicationName'\n` +
18
+ ` Pattern: ^[a-zA-Z][a-zA-Z0-9\\-\\s]*$\n` +
19
+ ` Received: ${options.applicationName}`);
20
+ }
21
+ if (!options.newScope) {
22
+ throw new Error(`Missing required option: 'newScope'\n` +
23
+ ` Description: The target subdirectory for the application\n` +
24
+ ` Allowed values: local, server\n` +
25
+ ` Example: nx g @unisphere/nx:change-application-scope --applicationName=my-app --newScope=local`);
26
+ }
27
+ const allowedScopes = ['local', 'server'];
28
+ if (!allowedScopes.includes(options.newScope)) {
29
+ throw new Error(`Invalid value '${options.newScope}' for option 'newScope'\n` +
30
+ ` Allowed values: ${allowedScopes.join(', ')}\n` +
31
+ ` Received: ${options.newScope}`);
32
+ }
33
+ }
34
+ function findApplicationInUnisphere(tree, applicationName) {
35
+ const unisphereConfig = (0, devkit_1.readJson)(tree, '.unisphere');
36
+ const normalizedName = (0, devkit_1.names)(applicationName).fileName;
37
+ if (!unisphereConfig.elements?.applications) {
38
+ throw new Error('No applications found in .unisphere configuration.\n' +
39
+ 'Cannot find application to change scope.');
40
+ }
41
+ const appConfig = unisphereConfig.elements.applications[normalizedName];
42
+ if (!appConfig) {
43
+ const available = Object.keys(unisphereConfig.elements.applications);
44
+ throw new Error(`Application "${normalizedName}" not found in .unisphere configuration.\n` +
45
+ 'Available applications: ' + (available.length > 0 ? available.join(', ') : '(none)'));
46
+ }
47
+ const sourceRoot = appConfig.sourceRoot;
48
+ if (!sourceRoot) {
49
+ throw new Error(`Application "${normalizedName}" exists but has no sourceRoot configured in .unisphere`);
50
+ }
51
+ if (!tree.exists(sourceRoot)) {
52
+ throw new Error(`Application directory not found at ${sourceRoot}.\n` +
53
+ 'The .unisphere configuration references an application that does not exist.');
54
+ }
55
+ const packageJsonPath = `${sourceRoot}/package.json`;
56
+ if (!tree.exists(packageJsonPath)) {
57
+ throw new Error(`package.json not found at ${packageJsonPath}.\n` +
58
+ 'The application directory exists but is missing package.json.');
59
+ }
60
+ const packageJson = (0, devkit_1.readJson)(tree, packageJsonPath);
61
+ const subdirectory = (0, utils_1.extractApplicationSubdirectory)(sourceRoot);
62
+ if (!subdirectory) {
63
+ throw new Error(`Application "${normalizedName}" has an unexpected sourceRoot format: ${sourceRoot}\n` +
64
+ 'Expected format: unisphere/applications/{local|server}/{name}');
65
+ }
66
+ return {
67
+ packageJsonName: packageJson.name,
68
+ sourceRoot,
69
+ subdirectory,
70
+ };
71
+ }
72
+ function validateDifferentScope(currentSubdirectory, newScope) {
73
+ if (currentSubdirectory === newScope) {
74
+ throw new Error(`Application is already in the "${newScope}" scope.\n` +
75
+ 'No changes needed.');
76
+ }
77
+ }
78
+ function validateNoCollision(tree, applicationName, newSubdirectory) {
79
+ const normalizedName = (0, devkit_1.names)(applicationName).fileName;
80
+ const newPath = `unisphere/applications/${newSubdirectory}/${normalizedName}`;
81
+ if (tree.exists(newPath)) {
82
+ throw new Error(`Directory already exists at ${newPath}.\n` +
83
+ 'Please choose a different scope or remove the existing directory first.');
84
+ }
85
+ }
86
+ function updateUnisphereConfiguration(tree, applicationName, newSourceRoot) {
87
+ const unisphereConfig = (0, devkit_1.readJson)(tree, '.unisphere');
88
+ const normalizedName = (0, devkit_1.names)(applicationName).fileName;
89
+ const oldAppConfig = unisphereConfig.elements.applications[normalizedName];
90
+ unisphereConfig.elements.applications[normalizedName] = {
91
+ ...oldAppConfig,
92
+ sourceRoot: newSourceRoot,
93
+ };
94
+ (0, devkit_1.writeJson)(tree, '.unisphere', unisphereConfig);
95
+ devkit_1.logger.info(`✅ Updated .unisphere configuration`);
96
+ }
97
+ function updatePackageLock(tree, oldPath, newPath) {
98
+ const packageLockPath = 'package-lock.json';
99
+ if (!tree.exists(packageLockPath)) {
100
+ return;
101
+ }
102
+ const packageLock = (0, devkit_1.readJson)(tree, packageLockPath);
103
+ let updated = false;
104
+ if (packageLock.packages) {
105
+ const packagesEntries = Object.entries(packageLock.packages);
106
+ const newPackages = {};
107
+ for (const [key, value] of packagesEntries) {
108
+ if (key === oldPath) {
109
+ newPackages[newPath] = value;
110
+ updated = true;
111
+ }
112
+ else {
113
+ newPackages[key] = value;
114
+ }
115
+ }
116
+ packageLock.packages = newPackages;
117
+ }
118
+ if (packageLock.packages) {
119
+ for (const [, value] of Object.entries(packageLock.packages)) {
120
+ if (value && typeof value === 'object' && 'resolved' in value) {
121
+ const pkg = value;
122
+ if (pkg.resolved === oldPath) {
123
+ pkg.resolved = newPath;
124
+ updated = true;
125
+ }
126
+ }
127
+ }
128
+ }
129
+ if (updated) {
130
+ (0, devkit_1.writeJson)(tree, packageLockPath, packageLock);
131
+ devkit_1.logger.info(`✅ Updated package-lock.json path keys`);
132
+ }
133
+ }
134
+ function updateProjectJson(tree, newPath, oldPath) {
135
+ const projectJsonPath = `${newPath}/project.json`;
136
+ if (!tree.exists(projectJsonPath)) {
137
+ return;
138
+ }
139
+ let content = tree.read(projectJsonPath, 'utf-8');
140
+ if (!content) {
141
+ return;
142
+ }
143
+ if (content.includes(oldPath)) {
144
+ content = content.replace(new RegExp(escapeRegExp(oldPath), 'g'), newPath);
145
+ tree.write(projectJsonPath, content);
146
+ devkit_1.logger.info(`✅ Updated project.json paths`);
147
+ }
148
+ }
149
+ function updateWebpackConfig(tree, newPath, oldPath) {
150
+ const webpackConfigPath = `${newPath}/webpack.config.js`;
151
+ if (!tree.exists(webpackConfigPath)) {
152
+ return;
153
+ }
154
+ let content = tree.read(webpackConfigPath, 'utf-8');
155
+ if (!content) {
156
+ return;
157
+ }
158
+ if (content.includes(oldPath)) {
159
+ content = content.replace(new RegExp(escapeRegExp(oldPath), 'g'), newPath);
160
+ tree.write(webpackConfigPath, content);
161
+ devkit_1.logger.info(`✅ Updated webpack.config.js references`);
162
+ }
163
+ }
164
+ function updateReadme(tree, newPath, oldPath) {
165
+ const readmePath = `${newPath}/README.md`;
166
+ if (!tree.exists(readmePath)) {
167
+ return;
168
+ }
169
+ let content = tree.read(readmePath, 'utf-8');
170
+ if (!content) {
171
+ return;
172
+ }
173
+ if (content.includes(oldPath)) {
174
+ content = content.replace(new RegExp(escapeRegExp(oldPath), 'g'), newPath);
175
+ tree.write(readmePath, content);
176
+ devkit_1.logger.info(`✅ Updated README.md`);
177
+ }
178
+ }
179
+ function escapeRegExp(string) {
180
+ return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
181
+ }
182
+ async function changeApplicationScopeGenerator(tree, options) {
183
+ validateOptions(options);
184
+ devkit_1.logger.info('');
185
+ devkit_1.logger.info('🔄 Starting application scope change...');
186
+ devkit_1.logger.info('');
187
+ (0, utils_1.validateUnisphereConfig)(tree);
188
+ const normalizedName = (0, devkit_1.names)(options.applicationName).fileName;
189
+ const appInfo = findApplicationInUnisphere(tree, normalizedName);
190
+ devkit_1.logger.info(`📦 Application: ${normalizedName}`);
191
+ devkit_1.logger.info(`📁 Current location: ${appInfo.sourceRoot} (${appInfo.subdirectory}/)`);
192
+ validateDifferentScope(appInfo.subdirectory, options.newScope);
193
+ const newPath = `unisphere/applications/${options.newScope}/${normalizedName}`;
194
+ validateNoCollision(tree, normalizedName, options.newScope);
195
+ const nxProjectName = `unisphere-application-${normalizedName}`;
196
+ devkit_1.logger.info(`📁 Target location: ${newPath} (${options.newScope}/)`);
197
+ devkit_1.logger.info('');
198
+ devkit_1.logger.info('🔧 Running Nx move generator...');
199
+ try {
200
+ await (0, generators_1.moveGenerator)(tree, {
201
+ projectName: nxProjectName,
202
+ destination: newPath,
203
+ newProjectName: nxProjectName,
204
+ importPath: appInfo.packageJsonName,
205
+ updateImportPath: true,
206
+ skipFormat: false,
207
+ });
208
+ devkit_1.logger.info(`✅ Nx moved project and updated imports`);
209
+ }
210
+ catch (error) {
211
+ devkit_1.logger.error(`❌ Failed to move project with Nx: ${error}`);
212
+ throw error;
213
+ }
214
+ devkit_1.logger.info('');
215
+ devkit_1.logger.info('🧹 Performing Unisphere-specific cleanup...');
216
+ updateUnisphereConfiguration(tree, normalizedName, newPath);
217
+ updatePackageLock(tree, appInfo.sourceRoot, newPath);
218
+ updateProjectJson(tree, newPath, appInfo.sourceRoot);
219
+ updateWebpackConfig(tree, newPath, appInfo.sourceRoot);
220
+ updateReadme(tree, newPath, appInfo.sourceRoot);
221
+ devkit_1.logger.info('');
222
+ devkit_1.logger.info('✅ Application scope changed successfully!');
223
+ devkit_1.logger.info('');
224
+ devkit_1.logger.info('📋 Summary:');
225
+ devkit_1.logger.info(` • Application: ${normalizedName}`);
226
+ devkit_1.logger.info(` • Old scope: ${appInfo.subdirectory}`);
227
+ devkit_1.logger.info(` • New scope: ${options.newScope}`);
228
+ devkit_1.logger.info(` • Old location: ${appInfo.sourceRoot}`);
229
+ devkit_1.logger.info(` • New location: ${newPath}`);
230
+ devkit_1.logger.info('');
231
+ devkit_1.logger.info('📝 Next steps:');
232
+ devkit_1.logger.info(' 1. Review the changes: git status');
233
+ devkit_1.logger.info(' 2. Stage all changes: git add -A');
234
+ devkit_1.logger.info(' Git will detect the directory move as a rename (preserving history)');
235
+ devkit_1.logger.info(' 3. Run: npm install (to update package-lock.json)');
236
+ devkit_1.logger.info(' 4. Run: npm run build (to verify everything builds)');
237
+ devkit_1.logger.info(' 5. Commit the changes: git commit -m "Change application scope..."');
238
+ devkit_1.logger.info('');
239
+ }
240
+ exports.default = changeApplicationScopeGenerator;
@@ -0,0 +1,4 @@
1
+ export interface ChangeApplicationScopeGeneratorSchema {
2
+ applicationName: string;
3
+ newScope: 'local' | 'server';
4
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "$schema": "https://json-schema.org/schema",
3
+ "$id": "ChangeApplicationScope",
4
+ "title": "Change Application Scope Generator",
5
+ "type": "object",
6
+ "properties": {
7
+ "applicationName": {
8
+ "type": "string",
9
+ "description": "The name of the application to move",
10
+ "pattern": "^[a-zA-Z][a-zA-Z0-9\\-\\s]*$"
11
+ },
12
+ "newScope": {
13
+ "type": "string",
14
+ "description": "The target subdirectory for the application",
15
+ "enum": ["local", "server"]
16
+ }
17
+ },
18
+ "required": [
19
+ "applicationName",
20
+ "newScope"
21
+ ]
22
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"change-package-scope.d.ts","sourceRoot":"","sources":["../../../src/generators/change-package-scope/change-package-scope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACL,IAAI,EAIL,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,iCAAiC,EAAE,MAAM,UAAU,CAAC;AAwY7D,wBAAsB,2BAA2B,CAC/C,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,iCAAiC,iBAuH3C;AAED,eAAe,2BAA2B,CAAC"}
1
+ {"version":3,"file":"change-package-scope.d.ts","sourceRoot":"","sources":["../../../src/generators/change-package-scope/change-package-scope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACL,IAAI,EAIL,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,iCAAiC,EAAE,MAAM,UAAU,CAAC;AAwY7D,wBAAsB,2BAA2B,CAC/C,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,iCAAiC,iBAuI3C;AAED,eAAe,2BAA2B,CAAC"}
@@ -310,7 +310,18 @@ async function changePackageScopeGenerator(tree, options) {
310
310
  const newPackageJsonName = (0, utils_2.calculateNewPackageJsonName)(packageInfo.packageIdentifier, experienceName, newScope);
311
311
  // Calculate new paths
312
312
  const newPath = `unisphere/packages/${newSubdirectory}/${packageInfo.packageIdentifier}`;
313
- const nxProjectName = `unisphere-package-${packageInfo.packageIdentifier}`;
313
+ // Read the actual Nx project name from project.json
314
+ const projectJsonPath = `${packageInfo.sourceRoot}/project.json`;
315
+ if (!tree.exists(projectJsonPath)) {
316
+ throw new Error(`project.json not found at ${projectJsonPath}.\n` +
317
+ 'Cannot determine the Nx project name for the move operation.');
318
+ }
319
+ const projectJson = (0, devkit_1.readJson)(tree, projectJsonPath);
320
+ const nxProjectName = projectJson.name;
321
+ if (!nxProjectName) {
322
+ throw new Error(`project.json at ${projectJsonPath} does not have a "name" field.\n` +
323
+ 'Cannot determine the Nx project name for the move operation.');
324
+ }
314
325
  devkit_1.logger.info(`🏷️ Target: ${newPackageJsonName} (${newSubdirectory}/)`);
315
326
  devkit_1.logger.info(`📁 Moving: ${packageInfo.sourceRoot} → ${newPath}`);
316
327
  devkit_1.logger.info('');
@@ -0,0 +1,5 @@
1
+ import { Tree } from '@nx/devkit';
2
+ import { RenameApplicationGeneratorSchema } from './schema';
3
+ export declare function renameApplicationGenerator(tree: Tree, options: RenameApplicationGeneratorSchema): Promise<void>;
4
+ export default renameApplicationGenerator;
5
+ //# sourceMappingURL=rename-application.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rename-application.d.ts","sourceRoot":"","sources":["../../../src/generators/rename-application/rename-application.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EAKL,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,gCAAgC,EAAE,MAAM,UAAU,CAAC;AAuW5D,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,gCAAgC,iBA+E1C;AAED,eAAe,0BAA0B,CAAC"}
@@ -0,0 +1,293 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renameApplicationGenerator = renameApplicationGenerator;
4
+ const devkit_1 = require("@nx/devkit");
5
+ const generators_1 = require("@nx/workspace/generators");
6
+ const utils_1 = require("../utils");
7
+ function validateOptions(options) {
8
+ if (!options.oldApplicationName || options.oldApplicationName.trim() === '') {
9
+ throw new Error(`Missing required option: 'oldApplicationName'\n` +
10
+ ` Description: The current name of the application to rename\n` +
11
+ ` Type: string\n` +
12
+ ` Example: nx g @unisphere/nx:rename-application --oldApplicationName=old-name --newApplicationName=new-name`);
13
+ }
14
+ if (!options.newApplicationName || options.newApplicationName.trim() === '') {
15
+ throw new Error(`Missing required option: 'newApplicationName'\n` +
16
+ ` Description: The new name for the application\n` +
17
+ ` Type: string\n` +
18
+ ` Pattern: ^[a-zA-Z][a-zA-Z0-9\\-\\s]*$\n` +
19
+ ` Example: nx g @unisphere/nx:rename-application --oldApplicationName=old-name --newApplicationName=new-name`);
20
+ }
21
+ const namePattern = /^[a-zA-Z][a-zA-Z0-9\-\s]*$/;
22
+ if (!namePattern.test(options.newApplicationName)) {
23
+ throw new Error(`Invalid value '${options.newApplicationName}' for option 'newApplicationName'\n` +
24
+ ` Pattern: ^[a-zA-Z][a-zA-Z0-9\\-\\s]*$\n` +
25
+ ` Received: ${options.newApplicationName}`);
26
+ }
27
+ }
28
+ function validateOldApplicationExists(tree, oldApplicationName) {
29
+ const unisphereConfig = (0, devkit_1.readJson)(tree, '.unisphere');
30
+ const normalizedOldName = (0, devkit_1.names)(oldApplicationName).fileName;
31
+ if (!unisphereConfig.elements?.applications?.[normalizedOldName]) {
32
+ const available = Object.keys(unisphereConfig.elements?.applications || {});
33
+ throw new Error(`Application "${normalizedOldName}" not found in .unisphere configuration.\n` +
34
+ 'Available applications: ' + (available.length > 0 ? available.join(', ') : '(none)'));
35
+ }
36
+ const appConfig = unisphereConfig.elements.applications[normalizedOldName];
37
+ const sourceRoot = appConfig.sourceRoot;
38
+ if (!sourceRoot) {
39
+ throw new Error(`Application "${normalizedOldName}" exists but has no sourceRoot configured in .unisphere`);
40
+ }
41
+ const subdirectory = (0, utils_1.extractApplicationSubdirectory)(sourceRoot);
42
+ if (!subdirectory) {
43
+ throw new Error(`Application "${normalizedOldName}" has an unexpected sourceRoot format: ${sourceRoot}\n` +
44
+ 'Expected format: unisphere/applications/{local|server}/{name}');
45
+ }
46
+ if (!tree.exists(sourceRoot)) {
47
+ throw new Error(`Application directory not found at ${sourceRoot}.\n` +
48
+ 'The .unisphere configuration references an application that does not exist.');
49
+ }
50
+ const packageJsonPath = `${sourceRoot}/package.json`;
51
+ if (!tree.exists(packageJsonPath)) {
52
+ throw new Error(`package.json not found at ${packageJsonPath}.\n` +
53
+ 'The application directory exists but is missing package.json.');
54
+ }
55
+ const packageJson = (0, devkit_1.readJson)(tree, packageJsonPath);
56
+ return {
57
+ packageJsonName: packageJson.name,
58
+ sourceRoot,
59
+ subdirectory,
60
+ oldPath: sourceRoot,
61
+ };
62
+ }
63
+ function validateNewApplicationDoesNotExist(tree, newApplicationName, subdirectory) {
64
+ const unisphereConfig = (0, devkit_1.readJson)(tree, '.unisphere');
65
+ const normalizedNewName = (0, devkit_1.names)(newApplicationName).fileName;
66
+ if (unisphereConfig.elements?.applications?.[normalizedNewName]) {
67
+ throw new Error(`Application "${normalizedNewName}" already exists in .unisphere configuration.\n` +
68
+ 'Please choose a different application name.');
69
+ }
70
+ const newPath = `unisphere/applications/${subdirectory}/${normalizedNewName}`;
71
+ if (tree.exists(newPath)) {
72
+ throw new Error(`Application directory already exists at ${newPath}.\n` +
73
+ 'Please choose a different application name or remove the existing directory.');
74
+ }
75
+ }
76
+ function updateUnisphereConfiguration(tree, oldApplicationName, newApplicationName, appInfo) {
77
+ const unisphereConfig = (0, devkit_1.readJson)(tree, '.unisphere');
78
+ const normalizedNewName = (0, devkit_1.names)(newApplicationName).fileName;
79
+ const normalizedOldName = (0, devkit_1.names)(oldApplicationName).fileName;
80
+ const newSourceRoot = `unisphere/applications/${appInfo.subdirectory}/${normalizedNewName}`;
81
+ const newApplications = {};
82
+ Object.keys(unisphereConfig.elements.applications).forEach((key) => {
83
+ if (key === normalizedOldName) {
84
+ newApplications[normalizedNewName] = {
85
+ ...unisphereConfig.elements.applications[normalizedOldName],
86
+ sourceRoot: newSourceRoot,
87
+ };
88
+ }
89
+ else {
90
+ newApplications[key] = unisphereConfig.elements.applications[key];
91
+ }
92
+ });
93
+ unisphereConfig.elements.applications = newApplications;
94
+ (0, devkit_1.writeJson)(tree, '.unisphere', unisphereConfig);
95
+ devkit_1.logger.info(`✅ Updated .unisphere configuration`);
96
+ }
97
+ function updatePackageJson(tree, packagePath, newPackageJsonName) {
98
+ const packageJsonPath = `${packagePath}/package.json`;
99
+ if (!tree.exists(packageJsonPath)) {
100
+ devkit_1.logger.warn(`⚠️ package.json not found at ${packageJsonPath}`);
101
+ return;
102
+ }
103
+ const packageJson = (0, devkit_1.readJson)(tree, packageJsonPath);
104
+ if (packageJson.name !== newPackageJsonName) {
105
+ packageJson.name = newPackageJsonName;
106
+ (0, devkit_1.writeJson)(tree, packageJsonPath, packageJson);
107
+ devkit_1.logger.info(`✅ Updated package.json name to "${newPackageJsonName}"`);
108
+ }
109
+ }
110
+ function updatePackageLock(tree, oldPath, newPath) {
111
+ const packageLockPath = 'package-lock.json';
112
+ if (!tree.exists(packageLockPath)) {
113
+ return;
114
+ }
115
+ const packageLock = (0, devkit_1.readJson)(tree, packageLockPath);
116
+ let updated = false;
117
+ if (packageLock.packages) {
118
+ const packagesEntries = Object.entries(packageLock.packages);
119
+ const newPackages = {};
120
+ for (const [key, value] of packagesEntries) {
121
+ if (key === oldPath) {
122
+ newPackages[newPath] = value;
123
+ updated = true;
124
+ }
125
+ else {
126
+ newPackages[key] = value;
127
+ }
128
+ }
129
+ packageLock.packages = newPackages;
130
+ }
131
+ if (packageLock.packages) {
132
+ for (const [, value] of Object.entries(packageLock.packages)) {
133
+ if (value && typeof value === 'object' && 'resolved' in value) {
134
+ const pkg = value;
135
+ if (pkg.resolved === oldPath) {
136
+ pkg.resolved = newPath;
137
+ updated = true;
138
+ }
139
+ }
140
+ }
141
+ }
142
+ if (updated) {
143
+ (0, devkit_1.writeJson)(tree, packageLockPath, packageLock);
144
+ devkit_1.logger.info(`✅ Updated package-lock.json path keys`);
145
+ }
146
+ }
147
+ function updateWebpackConfig(tree, newPath, oldNormalizedName, newNormalizedName) {
148
+ const webpackConfigPath = `${newPath}/webpack.config.js`;
149
+ if (!tree.exists(webpackConfigPath)) {
150
+ return;
151
+ }
152
+ let content = tree.read(webpackConfigPath, 'utf-8');
153
+ if (!content) {
154
+ return;
155
+ }
156
+ const oldPattern = `application-${oldNormalizedName}`;
157
+ const newPattern = `application-${newNormalizedName}`;
158
+ if (content.includes(oldPattern)) {
159
+ content = content.replace(new RegExp(escapeRegExp(oldPattern), 'g'), newPattern);
160
+ tree.write(webpackConfigPath, content);
161
+ devkit_1.logger.info(`✅ Updated webpack.config.js references`);
162
+ }
163
+ }
164
+ function updateProjectJson(tree, newPath, oldPath, oldNxProjectName, newNxProjectName) {
165
+ const projectJsonPath = `${newPath}/project.json`;
166
+ if (!tree.exists(projectJsonPath)) {
167
+ return;
168
+ }
169
+ let content = tree.read(projectJsonPath, 'utf-8');
170
+ if (!content) {
171
+ return;
172
+ }
173
+ let updated = false;
174
+ if (content.includes(oldPath)) {
175
+ content = content.replace(new RegExp(escapeRegExp(oldPath), 'g'), newPath);
176
+ updated = true;
177
+ }
178
+ if (content.includes(oldNxProjectName)) {
179
+ content = content.replace(new RegExp(escapeRegExp(oldNxProjectName), 'g'), newNxProjectName);
180
+ updated = true;
181
+ }
182
+ if (updated) {
183
+ tree.write(projectJsonPath, content);
184
+ devkit_1.logger.info(`✅ Updated project.json paths and comments`);
185
+ }
186
+ }
187
+ function updateReadme(tree, newPath, oldNormalizedName, newNormalizedName) {
188
+ const readmePath = `${newPath}/README.md`;
189
+ if (!tree.exists(readmePath)) {
190
+ return;
191
+ }
192
+ let content = tree.read(readmePath, 'utf-8');
193
+ if (!content) {
194
+ return;
195
+ }
196
+ let updated = false;
197
+ const toHumanReadable = (name) => name
198
+ .replace(/[-_]/g, ' ')
199
+ .replace(/\b\w/g, (l) => l.toUpperCase());
200
+ const oldHumanReadable = toHumanReadable(oldNormalizedName);
201
+ const newHumanReadable = toHumanReadable(newNormalizedName);
202
+ if (content.includes(oldHumanReadable)) {
203
+ content = content.replace(new RegExp(escapeRegExp(oldHumanReadable), 'g'), newHumanReadable);
204
+ updated = true;
205
+ }
206
+ if (content.includes(oldNormalizedName)) {
207
+ content = content.replace(new RegExp(escapeRegExp(oldNormalizedName), 'g'), newNormalizedName);
208
+ updated = true;
209
+ }
210
+ if (updated) {
211
+ tree.write(readmePath, content);
212
+ devkit_1.logger.info(`✅ Updated README.md`);
213
+ }
214
+ }
215
+ function updateRootServeScript(tree, oldNormalizedName, newNormalizedName) {
216
+ if (!tree.exists('package.json')) {
217
+ return;
218
+ }
219
+ const packageJson = (0, devkit_1.readJson)(tree, 'package.json');
220
+ const oldScriptName = `serve:${oldNormalizedName}`;
221
+ if (!packageJson.scripts?.[oldScriptName]) {
222
+ return;
223
+ }
224
+ const oldCommand = packageJson.scripts[oldScriptName];
225
+ const newCommand = oldCommand.replace(new RegExp(escapeRegExp(oldNormalizedName), 'g'), newNormalizedName);
226
+ const newScriptName = `serve:${newNormalizedName}`;
227
+ (0, utils_1.renameScriptInRootPackageJson)(tree, oldScriptName, newScriptName, newCommand);
228
+ }
229
+ function escapeRegExp(string) {
230
+ return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
231
+ }
232
+ async function renameApplicationGenerator(tree, options) {
233
+ validateOptions(options);
234
+ devkit_1.logger.info('');
235
+ devkit_1.logger.info('🔄 Starting application rename...');
236
+ devkit_1.logger.info('');
237
+ (0, utils_1.validateUnisphereConfig)(tree);
238
+ const normalizedOldName = (0, devkit_1.names)(options.oldApplicationName).fileName;
239
+ const normalizedNewName = (0, devkit_1.names)(options.newApplicationName).fileName;
240
+ const appInfo = validateOldApplicationExists(tree, normalizedOldName);
241
+ validateNewApplicationDoesNotExist(tree, normalizedNewName, appInfo.subdirectory);
242
+ const oldNxProjectName = `unisphere-application-${normalizedOldName}`;
243
+ const newNxProjectName = `unisphere-application-${normalizedNewName}`;
244
+ const newPackageJsonName = `unisphere-application-${normalizedNewName}`;
245
+ const newPath = `unisphere/applications/${appInfo.subdirectory}/${normalizedNewName}`;
246
+ devkit_1.logger.info(`📦 Old application name: ${normalizedOldName}`);
247
+ devkit_1.logger.info(`📦 New application name: ${normalizedNewName}`);
248
+ devkit_1.logger.info(`🏷️ Nx project name: ${oldNxProjectName} → ${newNxProjectName}`);
249
+ devkit_1.logger.info('');
250
+ devkit_1.logger.info('🔧 Running Nx move generator...');
251
+ try {
252
+ await (0, generators_1.moveGenerator)(tree, {
253
+ projectName: oldNxProjectName,
254
+ destination: newPath,
255
+ newProjectName: newNxProjectName,
256
+ importPath: newPackageJsonName,
257
+ updateImportPath: true,
258
+ skipFormat: false,
259
+ });
260
+ devkit_1.logger.info(`✅ Nx moved project from ${appInfo.oldPath} to ${newPath}`);
261
+ }
262
+ catch (error) {
263
+ devkit_1.logger.error(`❌ Failed to move project with Nx: ${error}`);
264
+ throw error;
265
+ }
266
+ devkit_1.logger.info('');
267
+ devkit_1.logger.info('🧹 Performing Unisphere-specific cleanup...');
268
+ updateUnisphereConfiguration(tree, normalizedOldName, normalizedNewName, appInfo);
269
+ updatePackageJson(tree, newPath, newPackageJsonName);
270
+ updatePackageLock(tree, appInfo.oldPath, newPath);
271
+ updateWebpackConfig(tree, newPath, normalizedOldName, normalizedNewName);
272
+ updateProjectJson(tree, newPath, appInfo.oldPath, oldNxProjectName, newNxProjectName);
273
+ updateReadme(tree, newPath, normalizedOldName, normalizedNewName);
274
+ updateRootServeScript(tree, normalizedOldName, normalizedNewName);
275
+ devkit_1.logger.info('');
276
+ devkit_1.logger.info('✅ Application renamed successfully!');
277
+ devkit_1.logger.info('');
278
+ devkit_1.logger.info('📋 Summary:');
279
+ devkit_1.logger.info(` • Old name: ${normalizedOldName}`);
280
+ devkit_1.logger.info(` • New name: ${normalizedNewName}`);
281
+ devkit_1.logger.info(` • Old location: ${appInfo.sourceRoot}`);
282
+ devkit_1.logger.info(` • New location: ${newPath}`);
283
+ devkit_1.logger.info('');
284
+ devkit_1.logger.info('📝 Next steps:');
285
+ devkit_1.logger.info(' 1. Review the changes: git status');
286
+ devkit_1.logger.info(' 2. Stage all changes: git add -A');
287
+ devkit_1.logger.info(' Git will detect the directory move as a rename (preserving history)');
288
+ devkit_1.logger.info(' 3. Run: npm install (to update package-lock.json)');
289
+ devkit_1.logger.info(' 4. Run: npm run build (to verify everything builds)');
290
+ devkit_1.logger.info(' 5. Commit the changes: git commit -m "Rename application..."');
291
+ devkit_1.logger.info('');
292
+ }
293
+ exports.default = renameApplicationGenerator;
@@ -0,0 +1,4 @@
1
+ export interface RenameApplicationGeneratorSchema {
2
+ oldApplicationName: string;
3
+ newApplicationName: string;
4
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "$schema": "https://json-schema.org/schema",
3
+ "$id": "RenameApplication",
4
+ "title": "Rename Application Generator",
5
+ "type": "object",
6
+ "properties": {
7
+ "oldApplicationName": {
8
+ "type": "string",
9
+ "description": "The current name of the application to rename"
10
+ },
11
+ "newApplicationName": {
12
+ "type": "string",
13
+ "description": "The new name for the application",
14
+ "pattern": "^[a-zA-Z][a-zA-Z0-9\\-\\s]*$"
15
+ }
16
+ },
17
+ "required": [
18
+ "oldApplicationName",
19
+ "newApplicationName"
20
+ ]
21
+ }
@@ -9,6 +9,7 @@ export interface UnisphereConfig {
9
9
  }
10
10
  export declare function validateUnisphereConfig(tree: Tree): UnisphereConfig;
11
11
  export declare function updateTsConfigPaths(tree: Tree, pathKey: string, pathValue: string): void;
12
+ export declare function validateElementNameUnique(tree: Tree, elementName: string, targetType: 'packages' | 'runtimes' | 'applications' | 'documentation'): void;
12
13
  export declare function updateUnisphereConfig(tree: Tree, elementType: 'packages' | 'runtimes' | 'applications' | 'documentation', elementName: string, elementConfig: Record<string, any>): void;
13
14
  export declare function validateRuntimeExists(tree: Tree, runtimeName: string): string;
14
15
  export declare function findCorePackageAlias(tree: Tree): string;
@@ -61,5 +62,7 @@ export declare function extractPackageNameFromSourceRoot(sourceRoot: string): st
61
62
  * @param scriptCommand - The command to run (e.g., "npx unisphere application serve my-app --port 4002")
62
63
  */
63
64
  export declare function addScriptToRootPackageJson(tree: Tree, scriptName: string, scriptCommand: string): void;
65
+ export declare function extractApplicationSubdirectory(sourceRoot: string): string | null;
66
+ export declare function renameScriptInRootPackageJson(tree: Tree, oldScriptName: string, newScriptName: string, newScriptCommand: string): void;
64
67
  export {};
65
68
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/generators/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EAKL,MAAM,YAAY,CAAC;AAGpB,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE;QACvB,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC,CAAC;CACJ;AA+FD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,IAAI,GAAG,eAAe,CAkEnE;AAGD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,QA2BjF;AAED,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,UAAU,GAAG,UAAU,GAAG,cAAc,GAAG,eAAe,EACvE,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QA0BnC;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CA4C7E;AA6BD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CA6BvD;AAwBD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAuB/D;AAED,MAAM,WAAW,gBAAgB;IAC/B,yFAAyF;IACzF,KAAK,EAAE,MAAM,CAAC;IACd,0GAA0G;IAC1G,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,eAAe,EAAE,OAAO,CAAC;CAC1B;AAgCD;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,IAAI,GAAG,gBAAgB,CA8BvE;AAGD,KAAK,mBAAmB,CAAC,MAAM,SAAS,MAAM,IAAI;KAC/C,CAAC,IACA,GAAG,MAAM,EAAE,GACX,GAAG,MAAM,iBAAiB,GAC1B,GAAG,MAAM,aAAa,GACtB,GAAG,MAAM,cAAc,GACvB,GAAG,MAAM,gBAAgB,GACzB,GAAG,MAAM,iBAAiB,GAAG,MAAM;CACtC,CAAC;AAKF,wBAAgB,oBAAoB,CAAC,MAAM,SAAS,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAwBzH;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,KAAK,CAwBlF;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAgB7E;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,WAAW,GAAG,cAAc,GAAG,OAAO,GAAG,YAAY,GAAG,cAAc,GAAG,aAAa,GAAG,MAAM,CAE9I;AAED;;;;GAIG;AACH,wBAAgB,iCAAiC,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAWnF;AAED;;;;GAIG;AACH,wBAAgB,gCAAgC,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAI3E;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,GACpB,IAAI,CAyBN"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/generators/utils.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.validateUnisphereConfig = validateUnisphereConfig;
4
4
  exports.updateTsConfigPaths = updateTsConfigPaths;
5
+ exports.validateElementNameUnique = validateElementNameUnique;
5
6
  exports.updateUnisphereConfig = updateUnisphereConfig;
6
7
  exports.validateRuntimeExists = validateRuntimeExists;
7
8
  exports.findCorePackageAlias = findCorePackageAlias;
@@ -14,6 +15,8 @@ exports.getSubdirectoryFromScope = getSubdirectoryFromScope;
14
15
  exports.extractSubdirectoryFromSourceRoot = extractSubdirectoryFromSourceRoot;
15
16
  exports.extractPackageNameFromSourceRoot = extractPackageNameFromSourceRoot;
16
17
  exports.addScriptToRootPackageJson = addScriptToRootPackageJson;
18
+ exports.extractApplicationSubdirectory = extractApplicationSubdirectory;
19
+ exports.renameScriptInRootPackageJson = renameScriptInRootPackageJson;
17
20
  const devkit_1 = require("@nx/devkit");
18
21
  /**
19
22
  * Extracts visual type names from a runtime.tsx file
@@ -171,6 +174,27 @@ function updateTsConfigPaths(tree, pathKey, pathValue) {
171
174
  }
172
175
  }
173
176
  }
177
+ function validateElementNameUnique(tree, elementName, targetType) {
178
+ if (!tree.exists('.unisphere')) {
179
+ return;
180
+ }
181
+ const config = (0, devkit_1.readJson)(tree, '.unisphere');
182
+ const elements = config.elements || {};
183
+ const allTypes = ['packages', 'runtimes', 'applications', 'documentation'];
184
+ for (const type of allTypes) {
185
+ if (elements[type] && elements[type][elementName]) {
186
+ if (type === targetType) {
187
+ throw new Error(`A ${type.slice(0, -1)} named "${elementName}" already exists.\n` +
188
+ ` Registered in .unisphere under elements.${type}.`);
189
+ }
190
+ else {
191
+ throw new Error(`The name "${elementName}" is already used by a ${type.slice(0, -1)}.\n` +
192
+ ` Registered in .unisphere under elements.${type}.\n` +
193
+ ` Names must be unique across all element types (packages, runtimes, applications, documentation).`);
194
+ }
195
+ }
196
+ }
197
+ }
174
198
  function updateUnisphereConfig(tree, elementType, elementName, elementConfig) {
175
199
  const existingConfig = (0, devkit_1.readJson)(tree, '.unisphere');
176
200
  // Ensure elements structure exists
@@ -494,3 +518,26 @@ function addScriptToRootPackageJson(tree, scriptName, scriptCommand) {
494
518
  devkit_1.logger.warn(`⚠️ Failed to add script to package.json: ${error instanceof Error ? error.message : 'Unknown error'}`);
495
519
  }
496
520
  }
521
+ function extractApplicationSubdirectory(sourceRoot) {
522
+ const parts = sourceRoot.split('/');
523
+ if (parts.length === 4 && parts[0] === 'unisphere' && parts[1] === 'applications') {
524
+ const subdirectory = parts[2];
525
+ if (['local', 'server'].includes(subdirectory)) {
526
+ return subdirectory;
527
+ }
528
+ }
529
+ return null;
530
+ }
531
+ function renameScriptInRootPackageJson(tree, oldScriptName, newScriptName, newScriptCommand) {
532
+ if (!tree.exists('package.json')) {
533
+ return;
534
+ }
535
+ const packageJson = (0, devkit_1.readJson)(tree, 'package.json');
536
+ if (!packageJson.scripts?.[oldScriptName]) {
537
+ return;
538
+ }
539
+ delete packageJson.scripts[oldScriptName];
540
+ packageJson.scripts[newScriptName] = newScriptCommand;
541
+ (0, devkit_1.writeJson)(tree, 'package.json', packageJson);
542
+ devkit_1.logger.info(`✅ Renamed serve script: ${oldScriptName} → ${newScriptName}`);
543
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"add-experience-documentation.d.ts","sourceRoot":"","sources":["../../../src/migrations/3-15-0/add-experience-documentation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,IAAI,EAAU,MAAM,YAAY,CAAC;AAG1C,wBAA8B,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAS9D"}
1
+ {"version":3,"file":"add-experience-documentation.d.ts","sourceRoot":"","sources":["../../../src/migrations/3-15-0/add-experience-documentation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,IAAI,EAAU,MAAM,YAAY,CAAC;AAG1C,wBAA8B,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ9D"}
@@ -13,7 +13,6 @@ const add_documentation_1 = require("../../generators/add-documentation/add-docu
13
13
  async function update(tree) {
14
14
  devkit_1.logger.info('📖 Creating experience-level documentation site...');
15
15
  await (0, add_documentation_1.addDocumentationGenerator)(tree, {
16
- isExperienceLevel: true,
17
16
  skipInstall: true,
18
17
  });
19
18
  devkit_1.logger.info('✅ Documentation site created successfully.');
package/generators.json CHANGED
@@ -35,6 +35,16 @@
35
35
  "schema": "./dist/generators/change-package-scope/schema.json",
36
36
  "description": "Change a package's npm scope by moving it between subdirectories"
37
37
  },
38
+ "rename-application": {
39
+ "factory": "./dist/generators/rename-application/rename-application",
40
+ "schema": "./dist/generators/rename-application/schema.json",
41
+ "description": "Rename a unisphere application and update all references"
42
+ },
43
+ "change-application-scope": {
44
+ "factory": "./dist/generators/change-application-scope/change-application-scope",
45
+ "schema": "./dist/generators/change-application-scope/schema.json",
46
+ "description": "Move an application between local and server subdirectories"
47
+ },
38
48
  "remove": {
39
49
  "factory": "./dist/generators/remove/remove",
40
50
  "schema": "./dist/generators/remove/schema.json",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unisphere/nx",
3
- "version": "4.4.1",
3
+ "version": "4.5.0",
4
4
  "private": false,
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",