@unisphere/nx 1.13.0 → 1.19.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 (54) hide show
  1. package/README.md +4 -4
  2. package/dist/generators/add-application/add-application.d.ts.map +1 -1
  3. package/dist/generators/add-application/add-application.js +74 -30
  4. package/dist/generators/add-application/schema.d.ts +2 -1
  5. package/dist/generators/add-application/schema.json +16 -33
  6. package/dist/generators/add-application/templates/default/package.json.template +2 -1
  7. package/dist/generators/add-application/templates/default/src/app/app.tsx.template +24 -3
  8. package/dist/generators/add-application/templates/{interactive-playground → local-dev-playground}/package.json +2 -4
  9. package/dist/generators/add-application/templates/{interactive-playground → local-dev-playground}/src/app/app.tsx.template +8 -12
  10. package/dist/generators/add-application/templates/{interactive-playground → local-dev-playground}/src/app/components/header.tsx.template +1 -1
  11. package/dist/generators/add-package/add-package.d.ts.map +1 -1
  12. package/dist/generators/add-package/add-package.js +10 -2
  13. package/dist/generators/add-package/schema.d.ts +1 -0
  14. package/dist/generators/add-package/schema.json +29 -1
  15. package/dist/generators/add-runtime/add-runtime.d.ts.map +1 -1
  16. package/dist/generators/add-runtime/add-runtime.js +26 -20
  17. package/dist/generators/add-runtime/schema.d.ts +2 -1
  18. package/dist/generators/add-runtime/schema.json +46 -11
  19. package/dist/generators/add-runtime/templates/core-templates/__runtimeName__-runtime/runtime-types.ts.template +2 -2
  20. package/dist/generators/add-runtime/templates/new-runtime/src/lib/create-factory.tsx.template +13 -12
  21. package/dist/generators/dependency-config.d.ts +23 -0
  22. package/dist/generators/dependency-config.d.ts.map +1 -0
  23. package/dist/generators/dependency-config.js +134 -0
  24. package/dist/generators/rename-package/rename-package.d.ts +18 -0
  25. package/dist/generators/rename-package/rename-package.d.ts.map +1 -0
  26. package/dist/generators/rename-package/rename-package.js +274 -0
  27. package/dist/generators/rename-package/schema.d.ts +4 -0
  28. package/dist/generators/rename-package/schema.json +23 -0
  29. package/dist/generators/unisphere-migrate/run-locally.md +4 -1
  30. package/dist/generators/unisphere-migrate/upgrade-guide.md +22 -6
  31. package/dist/migrations/update-1-1-5/templates/_publish-artifacts.template +210 -0
  32. package/dist/migrations/update-1-1-5/templates/cicd.template +13 -3
  33. package/dist/migrations/update-1-1-5/update-github-workflow.d.ts.map +1 -1
  34. package/dist/migrations/update-1-1-5/update-github-workflow.js +28 -17
  35. package/generators.json +5 -0
  36. package/package.json +2 -2
  37. /package/dist/generators/add-application/templates/{interactive-playground → local-dev-playground}/.babelrc +0 -0
  38. /package/dist/generators/add-application/templates/{interactive-playground → local-dev-playground}/.eslintrc.json +0 -0
  39. /package/dist/generators/add-application/templates/{interactive-playground → local-dev-playground}/jest.config.ts +0 -0
  40. /package/dist/generators/add-application/templates/{interactive-playground → local-dev-playground}/project.json +0 -0
  41. /package/dist/generators/add-application/templates/{interactive-playground → local-dev-playground}/src/app/components/settings-buttons.tsx +0 -0
  42. /package/dist/generators/add-application/templates/{interactive-playground → local-dev-playground}/src/app/components/settings-form.tsx +0 -0
  43. /package/dist/generators/add-application/templates/{interactive-playground → local-dev-playground}/src/app/components/settings.tsx +0 -0
  44. /package/dist/generators/add-application/templates/{interactive-playground → local-dev-playground}/src/app/configuration-provider.tsx +0 -0
  45. /package/dist/generators/add-application/templates/{interactive-playground → local-dev-playground}/src/app/definitions.ts +0 -0
  46. /package/dist/generators/add-application/templates/{interactive-playground → local-dev-playground}/src/app/utils/merge-deep.ts +0 -0
  47. /package/dist/generators/add-application/templates/{interactive-playground → local-dev-playground}/src/favicon.ico +0 -0
  48. /package/dist/generators/add-application/templates/{interactive-playground → local-dev-playground}/src/index.html +0 -0
  49. /package/dist/generators/add-application/templates/{interactive-playground → local-dev-playground}/src/main.tsx +0 -0
  50. /package/dist/generators/add-application/templates/{interactive-playground → local-dev-playground}/src/styles.css +0 -0
  51. /package/dist/generators/add-application/templates/{interactive-playground → local-dev-playground}/tsconfig.app.json +0 -0
  52. /package/dist/generators/add-application/templates/{interactive-playground → local-dev-playground}/tsconfig.json +0 -0
  53. /package/dist/generators/add-application/templates/{interactive-playground → local-dev-playground}/tsconfig.spec.json +0 -0
  54. /package/dist/generators/add-application/templates/{interactive-playground → local-dev-playground}/webpack.config.js +0 -0
@@ -10,24 +10,59 @@
10
10
  "pattern": "^[a-zA-Z][a-zA-Z0-9\\-\\s]*$",
11
11
  "x-prompt": "What's the runtime name? (letters, numbers, dashes and spaces allowed)"
12
12
  },
13
- "usage": {
14
- "type": "string",
15
- "description": "How will this runtime be used?",
13
+ "standalone": {
14
+ "type": "boolean",
15
+ "description": "Is this experience being loaded by the host application, or by another experience (not this one)?",
16
16
  "x-prompt": {
17
- "message": "How will this runtime be used?",
17
+ "message": "Is this experience being loaded by the host application, or by another experience (not this one)?",
18
18
  "type": "list",
19
19
  "items": [
20
20
  {
21
- "value": "loadedByExternalHost",
22
- "label": "Independent experience used as an entry point (loaded by host or another experience)"
21
+ "value": true,
22
+ "label": "Yes -loaded by host application"
23
+ },
24
+ {
25
+ "value": false,
26
+ "label": "No - loaded by another experience"
27
+ }
28
+ ]
29
+ }
30
+ },
31
+ "dependencies": {
32
+ "type": "array",
33
+ "description": "Select packages to install (use space to select, enter to confirm)",
34
+ "items": {
35
+ "type": "string",
36
+ "enum": [
37
+ "react",
38
+ "ds",
39
+ "mui"
40
+ ]
41
+ },
42
+ "default": [],
43
+ "x-prompt": {
44
+ "message": "Select dependencies to install (use space to select, enter to confirm):",
45
+ "type": "list",
46
+ "multiselect": true,
47
+ "items": [
48
+ {
49
+ "value": "react",
50
+ "label": "React - UI library for building components"
51
+ },
52
+ {
53
+ "value": "ds",
54
+ "label": "Kaltura DS - Design System (requires GIT_TOKEN)"
23
55
  },
24
56
  {
25
- "value": "composedIntoAnotherRuntime",
26
- "label": "Composed into another runtime of this experience (not used as an entry point)"
27
- }
57
+ "value": "mui",
58
+ "label": "Material UI - Component library"
59
+ }
28
60
  ]
29
61
  }
30
62
  }
31
63
  },
32
- "required": ["name", "usage"]
33
- }
64
+ "required": [
65
+ "name",
66
+ "standalone"
67
+ ]
68
+ }
@@ -1,11 +1,11 @@
1
1
  import { ValidatorSchema } from '@unisphere/core';
2
2
  import { UnisphereRuntimeBaseType } from '@unisphere/runtime';
3
- import { WidgetName } from '../widget-types';
3
+ import { widgetName } from '../widget-types';
4
4
 
5
5
  export const <%= runtimeName__pascalCase %>RuntimeName = '<%= runtimeName__lowerDashCase %>' as const;
6
6
 
7
7
  export type <%= runtimeName__pascalCase %>Runtime = UnisphereRuntimeBaseType<<%= runtimeName__pascalCase %>RuntimeSettings> & {
8
- readonly widgetName: typeof WidgetName;
8
+ readonly widgetName: typeof widgetName;
9
9
  readonly runtimeName: typeof <%= runtimeName__pascalCase %>RuntimeName;
10
10
  };
11
11
 
@@ -1,21 +1,22 @@
1
- import { Root } from 'react-dom/client';
2
- import { Runtime } from './runtime';
3
- import { <%= runtimeName__pascalCase %>RuntimeSettings } from '<%= coreAlias %>'
4
1
  import {
5
- CreateElementOptions,
6
2
  UnisphereElementBase,
7
3
  UnisphereElementFactory,
4
+ CreateElementOptions,
8
5
  } from '@unisphere/runtime-js';
6
+ import { Root } from 'react-dom/client';
7
+ import { Runtime } from './runtime';
9
8
 
10
- class ContextFactory extends UnisphereElementFactory<
11
- <%= runtimeName__pascalCase %>RuntimeSettings,
12
- Root
13
- > {
14
- create(
15
- options: CreateElementOptions<<%= runtimeName__pascalCase %>RuntimeSettings>
16
- ): UnisphereElementBase<<%= runtimeName__pascalCase %>RuntimeSettings, Root> {
17
- return new Runtime(options);
9
+ class ContextFactory extends UnisphereElementFactory<Record<string, any>, Root> {
10
+ create<T extends Record<string, any>>(
11
+ options: CreateElementOptions<T>
12
+ ): UnisphereElementBase<T, Root> {
13
+ switch (options.flavor) {
14
+ default:
15
+ return new Runtime(options) as any;
16
+ }
18
17
  }
19
18
  }
20
19
 
21
20
  export const createFactory = () => new ContextFactory();
21
+
22
+
@@ -0,0 +1,23 @@
1
+ import { Tree } from '@nx/devkit';
2
+ /**
3
+ * Dependency version mappings with default versions from workspace
4
+ */
5
+ export declare const DEPENDENCY_MAP: Record<string, {
6
+ packages: string[];
7
+ defaultVersions?: Record<string, string>;
8
+ }>;
9
+ /**
10
+ * Validates that GIT_TOKEN environment variable exists when Kaltura DS is selected
11
+ * @throws Error if GIT_TOKEN is not found
12
+ */
13
+ export declare function validateGitToken(selectedDependencies: string[]): void;
14
+ /**
15
+ * Validates and auto-corrects package/runtime name to include -react suffix
16
+ * when React or Kaltura DS dependencies are selected
17
+ */
18
+ export declare function validateReactNaming(name: string, selectedDependencies: string[]): string;
19
+ /**
20
+ * Installs selected dependencies, skipping those already installed
21
+ */
22
+ export declare function installSelectedDependencies(tree: Tree, selectedDependencies: string[]): void;
23
+ //# sourceMappingURL=dependency-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-config.d.ts","sourceRoot":"","sources":["../../src/generators/dependency-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAU,MAAM,YAAY,CAAC;AAI1C;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CACjC,MAAM,EACN;IAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAgDjE,CAAC;AAEF;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,oBAAoB,EAAE,MAAM,EAAE,GAAG,IAAI,CAkBrE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,oBAAoB,EAAE,MAAM,EAAE,GAC7B,MAAM,CAiBR;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,IAAI,EACV,oBAAoB,EAAE,MAAM,EAAE,GAC7B,IAAI,CA0CN"}
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEPENDENCY_MAP = void 0;
4
+ exports.validateGitToken = validateGitToken;
5
+ exports.validateReactNaming = validateReactNaming;
6
+ exports.installSelectedDependencies = installSelectedDependencies;
7
+ const devkit_1 = require("@nx/devkit");
8
+ const child_process_1 = require("child_process");
9
+ const utils_1 = require("./utils");
10
+ /**
11
+ * Dependency version mappings with default versions from workspace
12
+ */
13
+ exports.DEPENDENCY_MAP = {
14
+ react: {
15
+ packages: ['react', 'react-dom'],
16
+ defaultVersions: {
17
+ 'react': '^19.0.0',
18
+ 'react-dom': '^19.0.0',
19
+ },
20
+ },
21
+ ds: {
22
+ packages: [
23
+ '@kaltura/ds-react-bits',
24
+ '@kaltura/ds-react-icons',
25
+ '@kaltura/ds-react-theme',
26
+ '@kaltura/ds-react-utils',
27
+ '@mui/material',
28
+ '@mui/icons-material',
29
+ '@emotion/react',
30
+ '@emotion/styled',
31
+ ],
32
+ defaultVersions: {
33
+ '@kaltura/ds-react-bits': '^12.2.0',
34
+ '@kaltura/ds-react-icons': '^12.2.0',
35
+ '@kaltura/ds-react-theme': '^12.2.0',
36
+ '@kaltura/ds-react-utils': '^12.2.0',
37
+ '@mui/material': '^7.3.4',
38
+ '@mui/icons-material': '^7.3.4',
39
+ '@emotion/react': '11.14.0',
40
+ '@emotion/styled': '11.14.1',
41
+ },
42
+ },
43
+ mui: {
44
+ packages: ['@mui/material', '@mui/icons-material', '@emotion/react', '@emotion/styled'],
45
+ defaultVersions: {
46
+ '@mui/material': '^7.3.4',
47
+ '@mui/icons-material': '^7.3.4',
48
+ '@emotion/react': '11.14.0',
49
+ '@emotion/styled': '11.14.1',
50
+ },
51
+ },
52
+ 'react-hook-form': {
53
+ packages: ['react-hook-form', 'react', 'react-dom'],
54
+ defaultVersions: {
55
+ 'react-hook-form': '^7.52.0',
56
+ 'react': '^19.0.0',
57
+ 'react-dom': '^19.0.0',
58
+ },
59
+ },
60
+ };
61
+ /**
62
+ * Validates that GIT_TOKEN environment variable exists when Kaltura DS is selected
63
+ * @throws Error if GIT_TOKEN is not found
64
+ */
65
+ function validateGitToken(selectedDependencies) {
66
+ if (selectedDependencies.includes('ds')) {
67
+ const gitToken = process.env.GIT_TOKEN;
68
+ if (!gitToken) {
69
+ devkit_1.logger.error('');
70
+ devkit_1.logger.error('❌ Error: Kaltura DS requires GIT_TOKEN environment variable');
71
+ devkit_1.logger.error('');
72
+ devkit_1.logger.error('Please set up your GitHub token to access Kaltura packages.');
73
+ devkit_1.logger.error('Documentation: https://unisphere.kaltura.com/docs/create/overview');
74
+ devkit_1.logger.error('');
75
+ throw new Error('GIT_TOKEN environment variable is required for Kaltura DS');
76
+ }
77
+ }
78
+ }
79
+ /**
80
+ * Validates and auto-corrects package/runtime name to include -react suffix
81
+ * when React or Kaltura DS dependencies are selected
82
+ */
83
+ function validateReactNaming(name, selectedDependencies) {
84
+ const needsReactSuffix = selectedDependencies.includes('react') ||
85
+ selectedDependencies.includes('ds');
86
+ if (needsReactSuffix && !name.endsWith('-react')) {
87
+ const suggestedName = `${name}-react`;
88
+ devkit_1.logger.warn('');
89
+ devkit_1.logger.warn(`⚠️ Package/Runtime name should end with '-react' when using React or Kaltura DS`);
90
+ devkit_1.logger.info(` Renaming to: ${suggestedName}`);
91
+ devkit_1.logger.warn('');
92
+ return suggestedName;
93
+ }
94
+ return name;
95
+ }
96
+ /**
97
+ * Installs selected dependencies, skipping those already installed
98
+ */
99
+ function installSelectedDependencies(tree, selectedDependencies) {
100
+ if (!selectedDependencies || selectedDependencies.length === 0) {
101
+ return;
102
+ }
103
+ devkit_1.logger.info('');
104
+ devkit_1.logger.info('📦 Installing selected dependencies...');
105
+ for (const dep of selectedDependencies) {
106
+ const depConfig = exports.DEPENDENCY_MAP[dep];
107
+ if (!depConfig) {
108
+ devkit_1.logger.warn(`⚠️ Unknown dependency: ${dep}`);
109
+ continue;
110
+ }
111
+ for (const packageName of depConfig.packages) {
112
+ const installedVersion = (0, utils_1.isPackageInstalled)(tree, packageName);
113
+ if (installedVersion) {
114
+ devkit_1.logger.info(`✅ ${packageName}@${installedVersion} already installed`);
115
+ continue;
116
+ }
117
+ // Determine version to install from defaultVersions map or fallback
118
+ const version = depConfig.defaultVersions?.[packageName] || '^1.0.0';
119
+ const installCommand = `npm install ${packageName}@${version}`;
120
+ devkit_1.logger.info(` Installing ${packageName}@${version}...`);
121
+ try {
122
+ (0, child_process_1.execSync)(installCommand, {
123
+ cwd: process.cwd(),
124
+ stdio: 'inherit',
125
+ });
126
+ devkit_1.logger.info(`✅ ${packageName}@${version} installed successfully`);
127
+ }
128
+ catch (error) {
129
+ devkit_1.logger.error(`❌ Failed to install ${packageName}: ${error}`);
130
+ }
131
+ }
132
+ }
133
+ devkit_1.logger.info('');
134
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Rename Package Generator
3
+ *
4
+ * This generator renames a Unisphere package by:
5
+ * 1. Using Nx's built-in move generator to handle:
6
+ * - Directory and file moves
7
+ * - Import statement updates across the workspace
8
+ * - TypeScript path mappings in tsconfig.base.json
9
+ * 2. Performing Unisphere-specific cleanup:
10
+ * - Updating .unisphere configuration
11
+ * - Ensuring package.json name matches Unisphere conventions
12
+ * - Updating package-lock.json path keys (Nx doesn't handle this)
13
+ */
14
+ import { Tree } from '@nx/devkit';
15
+ import { RenamePackageGeneratorSchema } from './schema';
16
+ export declare function renamePackageGenerator(tree: Tree, options: RenamePackageGeneratorSchema): Promise<() => void>;
17
+ export default renamePackageGenerator;
18
+ //# sourceMappingURL=rename-package.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rename-package.d.ts","sourceRoot":"","sources":["../../../src/generators/rename-package/rename-package.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EACL,IAAI,EAKL,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,4BAA4B,EAAE,MAAM,UAAU,CAAC;AAyPxD,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,4BAA4B,uBAsGtC;AAED,eAAe,sBAAsB,CAAC"}
@@ -0,0 +1,274 @@
1
+ "use strict";
2
+ /**
3
+ * Rename Package Generator
4
+ *
5
+ * This generator renames a Unisphere package by:
6
+ * 1. Using Nx's built-in move generator to handle:
7
+ * - Directory and file moves
8
+ * - Import statement updates across the workspace
9
+ * - TypeScript path mappings in tsconfig.base.json
10
+ * 2. Performing Unisphere-specific cleanup:
11
+ * - Updating .unisphere configuration
12
+ * - Ensuring package.json name matches Unisphere conventions
13
+ * - Updating package-lock.json path keys (Nx doesn't handle this)
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.renamePackageGenerator = renamePackageGenerator;
17
+ const devkit_1 = require("@nx/devkit");
18
+ const generators_1 = require("@nx/workspace/generators");
19
+ const child_process_1 = require("child_process");
20
+ const utils_1 = require("../utils");
21
+ /**
22
+ * Validates that the old package exists in .unisphere configuration
23
+ */
24
+ function validateOldPackageExists(tree, oldPackageName) {
25
+ const unisphereConfig = (0, devkit_1.readJson)(tree, '.unisphere');
26
+ const normalizedOldName = (0, devkit_1.names)(oldPackageName).fileName;
27
+ if (!unisphereConfig.elements?.packages?.[normalizedOldName]) {
28
+ throw new Error(`Package "${normalizedOldName}" not found in .unisphere configuration.\n` +
29
+ 'Available packages: ' +
30
+ Object.keys(unisphereConfig.elements?.packages || {}).join(', '));
31
+ }
32
+ const packageConfig = unisphereConfig.elements.packages[normalizedOldName];
33
+ const oldPath = `unisphere/packages/${normalizedOldName}`;
34
+ // Verify the directory exists
35
+ if (!tree.exists(oldPath)) {
36
+ throw new Error(`Package directory not found at ${oldPath}.\n` +
37
+ 'The .unisphere configuration references a package that does not exist.');
38
+ }
39
+ // Read the package.json to get the current package name
40
+ const packageJsonPath = `${oldPath}/package.json`;
41
+ if (!tree.exists(packageJsonPath)) {
42
+ throw new Error(`package.json not found at ${packageJsonPath}.\n` +
43
+ 'The package directory exists but is missing package.json.');
44
+ }
45
+ const packageJson = (0, devkit_1.readJson)(tree, packageJsonPath);
46
+ const packageJsonName = packageJson.name;
47
+ return {
48
+ packageJsonName,
49
+ distributionChannel: packageConfig.distributionChannel || 'none',
50
+ scope: packageConfig.scope || 'widget',
51
+ sourceRoot: packageConfig.sourceRoot,
52
+ oldPath,
53
+ newPath: `unisphere/packages/${normalizedOldName}`,
54
+ };
55
+ }
56
+ /**
57
+ * Validates that the new package name doesn't already exist
58
+ */
59
+ function validateNewPackageDoesNotExist(tree, newPackageName) {
60
+ const unisphereConfig = (0, devkit_1.readJson)(tree, '.unisphere');
61
+ const normalizedNewName = (0, devkit_1.names)(newPackageName).fileName;
62
+ if (unisphereConfig.elements?.packages?.[normalizedNewName]) {
63
+ throw new Error(`Package "${normalizedNewName}" already exists in .unisphere configuration.\n` +
64
+ 'Please choose a different package name.');
65
+ }
66
+ const newPath = `unisphere/packages/${normalizedNewName}`;
67
+ if (tree.exists(newPath)) {
68
+ throw new Error(`Package directory already exists at ${newPath}.\n` +
69
+ 'Please choose a different package name or remove the existing directory.');
70
+ }
71
+ }
72
+ /**
73
+ * Calculate the new package.json name based on scope and experience name
74
+ */
75
+ function calculateNewPackageJsonName(tree, newPackageName, oldPackageJsonName) {
76
+ const unisphereConfig = (0, utils_1.validateUnisphereConfig)(tree);
77
+ const experienceName = unisphereConfig.name;
78
+ const normalizedNewName = (0, devkit_1.names)(newPackageName).fileName;
79
+ // Determine the prefix from the old package name
80
+ let prefix;
81
+ if (oldPackageJsonName.startsWith('@unisphere/')) {
82
+ prefix = '@unisphere/';
83
+ }
84
+ else if (oldPackageJsonName.startsWith('@kaltura/unisphere-')) {
85
+ prefix = '@kaltura/unisphere-';
86
+ }
87
+ else {
88
+ // Private package, no prefix
89
+ return normalizedNewName;
90
+ }
91
+ // Calculate new package name
92
+ let packageJsonName;
93
+ if (experienceName === normalizedNewName) {
94
+ packageJsonName = normalizedNewName;
95
+ }
96
+ else {
97
+ packageJsonName = `${experienceName}-${normalizedNewName}`;
98
+ }
99
+ return prefix + packageJsonName;
100
+ }
101
+ /**
102
+ * Update .unisphere configuration
103
+ */
104
+ function updateUnisphereConfiguration(tree, oldPackageName, newPackageName, packageInfo) {
105
+ const unisphereConfig = (0, devkit_1.readJson)(tree, '.unisphere');
106
+ const normalizedNewName = (0, devkit_1.names)(newPackageName).fileName;
107
+ const normalizedOldName = (0, devkit_1.names)(oldPackageName).fileName;
108
+ // Get the old package config
109
+ const oldPackageConfig = unisphereConfig.elements.packages[normalizedOldName];
110
+ // Update sourceRoot
111
+ const newSourceRoot = `unisphere/packages/${normalizedNewName}`;
112
+ // Preserve package order by rebuilding the packages object
113
+ const newPackages = {};
114
+ Object.keys(unisphereConfig.elements.packages).forEach((key) => {
115
+ if (key === normalizedOldName) {
116
+ // Replace old package with new one at the same position
117
+ newPackages[normalizedNewName] = {
118
+ ...oldPackageConfig,
119
+ sourceRoot: newSourceRoot,
120
+ };
121
+ }
122
+ else {
123
+ newPackages[key] = unisphereConfig.elements.packages[key];
124
+ }
125
+ });
126
+ unisphereConfig.elements.packages = newPackages;
127
+ (0, devkit_1.writeJson)(tree, '.unisphere', unisphereConfig);
128
+ devkit_1.logger.info(`✅ Updated .unisphere configuration`);
129
+ }
130
+ /**
131
+ * Update package.json name to ensure it matches Unisphere naming conventions
132
+ * Nx move generator sets the package name, but we verify it matches our conventions
133
+ */
134
+ function updatePackageJson(tree, packagePath, newPackageJsonName) {
135
+ const packageJsonPath = `${packagePath}/package.json`;
136
+ if (!tree.exists(packageJsonPath)) {
137
+ devkit_1.logger.warn(`⚠️ package.json not found at ${packageJsonPath}`);
138
+ return;
139
+ }
140
+ const packageJson = (0, devkit_1.readJson)(tree, packageJsonPath);
141
+ // Only update if Nx didn't set it to our expected name
142
+ if (packageJson.name !== newPackageJsonName) {
143
+ packageJson.name = newPackageJsonName;
144
+ (0, devkit_1.writeJson)(tree, packageJsonPath, packageJson);
145
+ devkit_1.logger.info(`✅ Updated package.json name to "${newPackageJsonName}"`);
146
+ }
147
+ }
148
+ /**
149
+ * Update package-lock.json to rename the package path keys
150
+ * Nx's move generator doesn't handle package-lock.json updates
151
+ */
152
+ function updatePackageLock(tree, oldPackageName, newPackageName) {
153
+ const packageLockPath = 'package-lock.json';
154
+ if (!tree.exists(packageLockPath)) {
155
+ return;
156
+ }
157
+ const packageLock = (0, devkit_1.readJson)(tree, packageLockPath);
158
+ const normalizedOldName = (0, devkit_1.names)(oldPackageName).fileName;
159
+ const normalizedNewName = (0, devkit_1.names)(newPackageName).fileName;
160
+ const oldPath = `unisphere/packages/${normalizedOldName}`;
161
+ const newPath = `unisphere/packages/${normalizedNewName}`;
162
+ let updated = false;
163
+ if (packageLock.packages) {
164
+ const packagesEntries = Object.entries(packageLock.packages);
165
+ const newPackages = {};
166
+ for (const [key, value] of packagesEntries) {
167
+ // Check if this key is exactly the old package path
168
+ if (key === oldPath) {
169
+ newPackages[newPath] = value;
170
+ updated = true;
171
+ }
172
+ else {
173
+ newPackages[key] = value;
174
+ }
175
+ }
176
+ packageLock.packages = newPackages;
177
+ }
178
+ // Update resolved paths if they exist
179
+ if (packageLock.packages) {
180
+ for (const [, value] of Object.entries(packageLock.packages)) {
181
+ if (value && typeof value === 'object' && 'resolved' in value) {
182
+ const pkg = value;
183
+ if (pkg.resolved === oldPath) {
184
+ pkg.resolved = newPath;
185
+ updated = true;
186
+ }
187
+ }
188
+ }
189
+ }
190
+ if (updated) {
191
+ (0, devkit_1.writeJson)(tree, packageLockPath, packageLock);
192
+ devkit_1.logger.info(`✅ Updated package-lock.json path keys`);
193
+ }
194
+ }
195
+ async function renamePackageGenerator(tree, options) {
196
+ devkit_1.logger.info('');
197
+ devkit_1.logger.info('🔄 Starting package rename...');
198
+ devkit_1.logger.info('');
199
+ // Validate .unisphere exists
200
+ (0, utils_1.validateUnisphereConfig)(tree);
201
+ // Normalize package names
202
+ const normalizedOldName = (0, devkit_1.names)(options.oldPackageName).fileName;
203
+ const normalizedNewName = (0, devkit_1.names)(options.newPackageName).fileName;
204
+ // Validate old package exists
205
+ const packageInfo = validateOldPackageExists(tree, normalizedOldName);
206
+ // Validate new package doesn't exist
207
+ validateNewPackageDoesNotExist(tree, normalizedNewName);
208
+ // Calculate new package.json name
209
+ const newPackageJsonName = calculateNewPackageJsonName(tree, normalizedNewName, packageInfo.packageJsonName);
210
+ const oldNxProjectName = `unisphere-package-${normalizedOldName}`;
211
+ const newNxProjectName = `unisphere-package-${normalizedNewName}`;
212
+ const newPath = `unisphere/packages/${normalizedNewName}`;
213
+ devkit_1.logger.info(`📦 Old package name: ${normalizedOldName}`);
214
+ devkit_1.logger.info(`📦 New package name: ${normalizedNewName}`);
215
+ devkit_1.logger.info(`🏷️ Old package.json name: ${packageInfo.packageJsonName}`);
216
+ devkit_1.logger.info(`🏷️ New package.json name: ${newPackageJsonName}`);
217
+ devkit_1.logger.info(`🏷️ Nx project name: ${oldNxProjectName} → ${newNxProjectName}`);
218
+ devkit_1.logger.info('');
219
+ // Step 1: Run Nx's built-in move generator
220
+ devkit_1.logger.info('🔧 Running Nx move generator...');
221
+ try {
222
+ await (0, generators_1.moveGenerator)(tree, {
223
+ projectName: oldNxProjectName,
224
+ destination: newPath,
225
+ newProjectName: newNxProjectName,
226
+ importPath: newPackageJsonName,
227
+ updateImportPath: true,
228
+ skipFormat: false,
229
+ });
230
+ devkit_1.logger.info(`✅ Nx moved project from ${packageInfo.oldPath} to ${newPath}`);
231
+ }
232
+ catch (error) {
233
+ devkit_1.logger.error(`❌ Failed to move project with Nx: ${error}`);
234
+ throw error;
235
+ }
236
+ devkit_1.logger.info('');
237
+ devkit_1.logger.info('🧹 Performing Unisphere-specific cleanup...');
238
+ // Step 2: Update .unisphere configuration (Unisphere-specific)
239
+ updateUnisphereConfiguration(tree, normalizedOldName, normalizedNewName, packageInfo);
240
+ // Step 3: Update package.json name to match Unisphere conventions
241
+ updatePackageJson(tree, newPath, newPackageJsonName);
242
+ // Step 4: Update package-lock.json path keys (Nx doesn't handle this)
243
+ updatePackageLock(tree, normalizedOldName, normalizedNewName);
244
+ devkit_1.logger.info('');
245
+ devkit_1.logger.info('✅ Package renamed successfully!');
246
+ devkit_1.logger.info('');
247
+ devkit_1.logger.info('📋 Summary:');
248
+ devkit_1.logger.info(` • Old name: ${normalizedOldName}`);
249
+ devkit_1.logger.info(` • New name: ${normalizedNewName}`);
250
+ devkit_1.logger.info(` • Old location: ${packageInfo.oldPath}`);
251
+ devkit_1.logger.info(` • New location: ${newPath}`);
252
+ devkit_1.logger.info(` • Package.json name: ${newPackageJsonName}`);
253
+ devkit_1.logger.info('');
254
+ devkit_1.logger.info('📝 Next steps:');
255
+ devkit_1.logger.info(' 1. Review the changes: git status');
256
+ devkit_1.logger.info(' 2. Stage all changes: git add -A');
257
+ devkit_1.logger.info(' Git will detect the directory move as a rename (preserving history)');
258
+ devkit_1.logger.info(' 3. Run: npm install (to update package-lock.json)');
259
+ devkit_1.logger.info(' 4. Run: npm run build (to verify everything builds)');
260
+ devkit_1.logger.info(' 5. Commit the changes: git commit -m "Rename package..."');
261
+ devkit_1.logger.info('');
262
+ return () => {
263
+ // This function runs after all changes are applied
264
+ try {
265
+ // Auto-stage changes to help Git detect renames
266
+ (0, child_process_1.execSync)('git add -A', { stdio: 'ignore' });
267
+ devkit_1.logger.info('✅ Automatically staged changes to help Git detect renames');
268
+ }
269
+ catch (e) {
270
+ // Ignore errors if git is not available or not a git repo
271
+ }
272
+ };
273
+ }
274
+ exports.default = renamePackageGenerator;
@@ -0,0 +1,4 @@
1
+ export interface RenamePackageGeneratorSchema {
2
+ oldPackageName: string;
3
+ newPackageName: string;
4
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "$schema": "https://json-schema.org/schema",
3
+ "$id": "RenamePackage",
4
+ "title": "Rename Package Generator",
5
+ "type": "object",
6
+ "properties": {
7
+ "oldPackageName": {
8
+ "type": "string",
9
+ "description": "The current name of the package to rename",
10
+ "x-prompt": "What is the current package name?"
11
+ },
12
+ "newPackageName": {
13
+ "type": "string",
14
+ "description": "The new name for the package",
15
+ "pattern": "^[a-zA-Z][a-zA-Z0-9\\-\\s]*$",
16
+ "x-prompt": "What should the new package name be? (alphanumeric with dashes and spaces allowed)"
17
+ }
18
+ },
19
+ "required": [
20
+ "oldPackageName",
21
+ "newPackageName"
22
+ ]
23
+ }
@@ -15,4 +15,7 @@ npx nx g {path}/unisphere-nx-workspace-plugin/packages/nx:unisphere-migrate
15
15
  This will run ALL migrations defined in migrations.json manually.
16
16
 
17
17
 
18
- npx nx g /home/tokomeno/kaltura/unisphere/pl/unisphere-nx-workspace-plugin/packages/nx:unisphere-migrate
18
+ npx nx g /home/tokomeno/kaltura/unisphere/unisphere-nx-workspace-plugin/packages/nx:unisphere-migrate
19
+
20
+
21
+ npx nx g /home/tokomeno/kaltura/unisphere/unisphere-nx-workspace-plugin/packages/nx:add-application
@@ -1,3 +1,25 @@
1
+
2
+ ### Unisphere-migrate
3
+
4
+ **Purpose:** A comprehensive migration guide and generator for upgrading Unisphere workspaces to the latest tech stack.
5
+
6
+ **What It Does:**
7
+ - Guides developers through a major version upgrade of their Unisphere workspace
8
+ - Automates code transformations for breaking changes across:
9
+ - React 18 → 19 (breaking changes in types and patterns)
10
+ - MUI v5/v6 → v7 (breaking API changes)
11
+ - Node.js version upgrades
12
+ - All @unisphere and @kaltura packages
13
+ - Sequences upgrade steps in the correct order (Nx first, then Unisphere)
14
+ - Provides safety measures (git commits, clean installs, verification steps)
15
+
16
+ **Key Features:**
17
+ - User-facing documentation for manual steps (environment setup, Node.js switching)
18
+ - Automated migration generator for code transformations
19
+ - Handles dependencies across multiple major version bumps
20
+ - Verification steps to ensure successful upgrade
21
+
22
+
1
23
  # Unisphere Nx Workspace Upgrade Guide
2
24
 
3
25
  This guide walks you through upgrading your Unisphere workspace to the latest version with Nx 22, React 19, MUI v7, and Node.js 24.
@@ -84,9 +106,3 @@ If you encounter React 19 compatibility issues, you may need to:
84
106
  npm run check
85
107
  ```
86
108
 
87
- ## What Changed
88
-
89
- - **React**: Upgraded to v19
90
- - **MUI**: Upgraded to v7
91
- - **Node.js**: Updated to v24
92
- - **All @unisphere and @kaltura packages**: Updated to latest versions