@unisphere/nx 3.21.0 → 3.22.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.
- package/dist/generators/change-package-scope/change-package-scope.d.ts +23 -0
- package/dist/generators/change-package-scope/change-package-scope.d.ts.map +1 -0
- package/dist/generators/change-package-scope/change-package-scope.js +345 -0
- package/dist/generators/change-package-scope/schema.d.ts +4 -0
- package/dist/generators/change-package-scope/schema.json +24 -0
- package/dist/generators/change-package-scope/utils.d.ts +38 -0
- package/dist/generators/change-package-scope/utils.d.ts.map +1 -0
- package/dist/generators/change-package-scope/utils.js +116 -0
- package/generators.json +5 -0
- package/package.json +1 -1
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Change Package Scope Generator
|
|
3
|
+
*
|
|
4
|
+
* Changes a package's npm scope by:
|
|
5
|
+
* 1. Validating the package exists and target scope is valid
|
|
6
|
+
* 2. Parsing the package.json name to extract current scope and package name
|
|
7
|
+
* 3. Using Nx's built-in move generator to handle:
|
|
8
|
+
* - Directory and file moves
|
|
9
|
+
* - Import statement updates across the workspace
|
|
10
|
+
* - TypeScript path mappings in tsconfig.base.json
|
|
11
|
+
* 4. Performing Unisphere-specific cleanup:
|
|
12
|
+
* - Updating .unisphere configuration
|
|
13
|
+
* - Ensuring package.json name matches conventions
|
|
14
|
+
* - Updating package-lock.json path keys
|
|
15
|
+
* - Updating vite.config.ts cache directory paths
|
|
16
|
+
* - Updating project.json lintFilePatterns and comments
|
|
17
|
+
* - Updating README.md with new package name
|
|
18
|
+
*/
|
|
19
|
+
import { Tree } from '@nx/devkit';
|
|
20
|
+
import { ChangePackageScopeGeneratorSchema } from './schema';
|
|
21
|
+
export declare function changePackageScopeGenerator(tree: Tree, options: ChangePackageScopeGeneratorSchema): Promise<void>;
|
|
22
|
+
export default changePackageScopeGenerator;
|
|
23
|
+
//# sourceMappingURL=change-package-scope.d.ts.map
|
|
@@ -0,0 +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;AAiW7D,wBAAsB,2BAA2B,CAC/C,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,iCAAiC,iBAoH3C;AAED,eAAe,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Change Package Scope Generator
|
|
4
|
+
*
|
|
5
|
+
* Changes a package's npm scope by:
|
|
6
|
+
* 1. Validating the package exists and target scope is valid
|
|
7
|
+
* 2. Parsing the package.json name to extract current scope and package name
|
|
8
|
+
* 3. Using Nx's built-in move generator to handle:
|
|
9
|
+
* - Directory and file moves
|
|
10
|
+
* - Import statement updates across the workspace
|
|
11
|
+
* - TypeScript path mappings in tsconfig.base.json
|
|
12
|
+
* 4. Performing Unisphere-specific cleanup:
|
|
13
|
+
* - Updating .unisphere configuration
|
|
14
|
+
* - Ensuring package.json name matches conventions
|
|
15
|
+
* - Updating package-lock.json path keys
|
|
16
|
+
* - Updating vite.config.ts cache directory paths
|
|
17
|
+
* - Updating project.json lintFilePatterns and comments
|
|
18
|
+
* - Updating README.md with new package name
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.changePackageScopeGenerator = changePackageScopeGenerator;
|
|
22
|
+
const devkit_1 = require("@nx/devkit");
|
|
23
|
+
const generators_1 = require("@nx/workspace/generators");
|
|
24
|
+
const utils_1 = require("../utils");
|
|
25
|
+
const utils_2 = require("./utils");
|
|
26
|
+
/**
|
|
27
|
+
* Finds a package in .unisphere config by matching the package.json name.
|
|
28
|
+
* Extracts package information needed for scope change.
|
|
29
|
+
*/
|
|
30
|
+
function findPackageInUnisphere(tree, packageJsonName, experienceName) {
|
|
31
|
+
const unisphereConfig = (0, devkit_1.readJson)(tree, '.unisphere');
|
|
32
|
+
if (!unisphereConfig.elements?.packages) {
|
|
33
|
+
throw new Error('No packages found in .unisphere configuration.\n' +
|
|
34
|
+
'Cannot find package to change scope.');
|
|
35
|
+
}
|
|
36
|
+
// Parse the provided package.json name to get package identifier
|
|
37
|
+
const { packageName } = (0, utils_2.parsePackageJsonName)(packageJsonName, experienceName);
|
|
38
|
+
// Find the package by identifier in .unisphere
|
|
39
|
+
const packageConfig = unisphereConfig.elements.packages[packageName];
|
|
40
|
+
if (!packageConfig) {
|
|
41
|
+
throw new Error(`Package with identifier "${packageName}" not found in .unisphere configuration.\n` +
|
|
42
|
+
'Available packages: ' +
|
|
43
|
+
Object.keys(unisphereConfig.elements.packages).join(', '));
|
|
44
|
+
}
|
|
45
|
+
const sourceRoot = packageConfig.sourceRoot;
|
|
46
|
+
if (!sourceRoot) {
|
|
47
|
+
throw new Error(`Package "${packageName}" exists but has no sourceRoot configured in .unisphere`);
|
|
48
|
+
}
|
|
49
|
+
// Verify the directory exists
|
|
50
|
+
if (!tree.exists(sourceRoot)) {
|
|
51
|
+
throw new Error(`Package directory not found at ${sourceRoot}.\n` +
|
|
52
|
+
'The .unisphere configuration references a package that does not exist.');
|
|
53
|
+
}
|
|
54
|
+
// Read the package.json to verify the name matches
|
|
55
|
+
const packageJsonPath = `${sourceRoot}/package.json`;
|
|
56
|
+
if (!tree.exists(packageJsonPath)) {
|
|
57
|
+
throw new Error(`package.json not found at ${packageJsonPath}.\n` +
|
|
58
|
+
'The package directory exists but is missing package.json.');
|
|
59
|
+
}
|
|
60
|
+
const packageJson = (0, devkit_1.readJson)(tree, packageJsonPath);
|
|
61
|
+
if (packageJson.name !== packageJsonName) {
|
|
62
|
+
throw new Error(`Package name mismatch!\n` +
|
|
63
|
+
`Expected: ${packageJsonName}\n` +
|
|
64
|
+
`Found in package.json: ${packageJson.name}\n` +
|
|
65
|
+
`Location: ${packageJsonPath}`);
|
|
66
|
+
}
|
|
67
|
+
const subdirectory = (0, utils_1.extractSubdirectoryFromSourceRoot)(sourceRoot);
|
|
68
|
+
const currentScope = (0, utils_2.extractScopeFromSubdirectory)(subdirectory);
|
|
69
|
+
return {
|
|
70
|
+
packageIdentifier: packageName,
|
|
71
|
+
packageJsonName,
|
|
72
|
+
currentScope,
|
|
73
|
+
sourceRoot,
|
|
74
|
+
subdirectory,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Validates that the target scope is different from current scope.
|
|
79
|
+
*/
|
|
80
|
+
function validateDifferentScope(currentScope, newScope) {
|
|
81
|
+
if (currentScope === newScope) {
|
|
82
|
+
throw new Error(`Package is already in the target scope "${newScope}".\n` +
|
|
83
|
+
'No changes needed.');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Validates that the target subdirectory doesn't already have a package with this identifier.
|
|
88
|
+
*/
|
|
89
|
+
function validateNoCollision(tree, packageIdentifier, newSubdirectory) {
|
|
90
|
+
// Check if directory exists on filesystem
|
|
91
|
+
const newPath = `unisphere/packages/${newSubdirectory}/${packageIdentifier}`;
|
|
92
|
+
if (tree.exists(newPath)) {
|
|
93
|
+
throw new Error(`Directory already exists at ${newPath}.\n` +
|
|
94
|
+
'Please choose a different scope or remove the existing directory first.');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Validates special package restrictions (e.g., types package scope rules).
|
|
99
|
+
*/
|
|
100
|
+
function validateSpecialPackageRestrictions(packageIdentifier, newScope) {
|
|
101
|
+
if (packageIdentifier === 'types') {
|
|
102
|
+
const allowedScopes = ['@unisphere', '@kaltura-corp'];
|
|
103
|
+
if (!allowedScopes.includes(newScope)) {
|
|
104
|
+
throw new Error(`The "types" package can only exist in @unisphere or @kaltura-corp scopes.\n` +
|
|
105
|
+
`You attempted to move it to ${newScope}.\n` +
|
|
106
|
+
`Allowed scopes: ${allowedScopes.join(', ')}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Update .unisphere configuration with the new sourceRoot.
|
|
112
|
+
*/
|
|
113
|
+
function updateUnisphereConfiguration(tree, packageIdentifier, newSourceRoot) {
|
|
114
|
+
const unisphereConfig = (0, devkit_1.readJson)(tree, '.unisphere');
|
|
115
|
+
const oldPackageConfig = unisphereConfig.elements.packages[packageIdentifier];
|
|
116
|
+
unisphereConfig.elements.packages[packageIdentifier] = {
|
|
117
|
+
...oldPackageConfig,
|
|
118
|
+
sourceRoot: newSourceRoot,
|
|
119
|
+
};
|
|
120
|
+
(0, devkit_1.writeJson)(tree, '.unisphere', unisphereConfig);
|
|
121
|
+
devkit_1.logger.info(`✅ Updated .unisphere configuration`);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Update package.json name to ensure it matches Unisphere naming conventions
|
|
125
|
+
* Nx move generator sets the package name, but we verify it matches our conventions
|
|
126
|
+
*/
|
|
127
|
+
function updatePackageJson(tree, packagePath, newPackageJsonName) {
|
|
128
|
+
const packageJsonPath = `${packagePath}/package.json`;
|
|
129
|
+
if (!tree.exists(packageJsonPath)) {
|
|
130
|
+
devkit_1.logger.warn(`⚠️ package.json not found at ${packageJsonPath}`);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const packageJson = (0, devkit_1.readJson)(tree, packageJsonPath);
|
|
134
|
+
// Only update if Nx didn't set it to our expected name
|
|
135
|
+
if (packageJson.name !== newPackageJsonName) {
|
|
136
|
+
packageJson.name = newPackageJsonName;
|
|
137
|
+
(0, devkit_1.writeJson)(tree, packageJsonPath, packageJson);
|
|
138
|
+
devkit_1.logger.info(`✅ Updated package.json name to "${newPackageJsonName}"`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Update package-lock.json to rename the package path keys
|
|
143
|
+
* Nx's move generator doesn't handle package-lock.json updates
|
|
144
|
+
*/
|
|
145
|
+
function updatePackageLock(tree, oldPath, newPath) {
|
|
146
|
+
const packageLockPath = 'package-lock.json';
|
|
147
|
+
if (!tree.exists(packageLockPath)) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const packageLock = (0, devkit_1.readJson)(tree, packageLockPath);
|
|
151
|
+
let updated = false;
|
|
152
|
+
if (packageLock.packages) {
|
|
153
|
+
const packagesEntries = Object.entries(packageLock.packages);
|
|
154
|
+
const newPackages = {};
|
|
155
|
+
for (const [key, value] of packagesEntries) {
|
|
156
|
+
// Check if this key is exactly the old package path
|
|
157
|
+
if (key === oldPath) {
|
|
158
|
+
newPackages[newPath] = value;
|
|
159
|
+
updated = true;
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
newPackages[key] = value;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
packageLock.packages = newPackages;
|
|
166
|
+
}
|
|
167
|
+
// Update resolved paths if they exist
|
|
168
|
+
if (packageLock.packages) {
|
|
169
|
+
for (const [, value] of Object.entries(packageLock.packages)) {
|
|
170
|
+
if (value && typeof value === 'object' && 'resolved' in value) {
|
|
171
|
+
const pkg = value;
|
|
172
|
+
if (pkg.resolved === oldPath) {
|
|
173
|
+
pkg.resolved = newPath;
|
|
174
|
+
updated = true;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (updated) {
|
|
180
|
+
(0, devkit_1.writeJson)(tree, packageLockPath, packageLock);
|
|
181
|
+
devkit_1.logger.info(`✅ Updated package-lock.json path keys`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Update vite.config.ts to rename cache directory paths
|
|
186
|
+
* Nx's move generator doesn't update arbitrary string literals in code files
|
|
187
|
+
*/
|
|
188
|
+
function updateViteConfig(tree, newPath, packageIdentifier) {
|
|
189
|
+
const viteConfigPath = `${newPath}/vite.config.ts`;
|
|
190
|
+
if (!tree.exists(viteConfigPath)) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
let content = tree.read(viteConfigPath, 'utf-8');
|
|
194
|
+
if (!content) {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
const pattern = `package-${packageIdentifier}`;
|
|
198
|
+
// The cache directory already uses the package identifier, so we just verify it's there
|
|
199
|
+
// No changes needed for scope change
|
|
200
|
+
if (content.includes(pattern)) {
|
|
201
|
+
devkit_1.logger.info(`✅ Verified vite.config.ts cache directory`);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Update project.json to fix lintFilePatterns and comments
|
|
206
|
+
* Nx's move generator updates root/sourceRoot but not arbitrary strings in options
|
|
207
|
+
*/
|
|
208
|
+
function updateProjectJson(tree, newPath, oldPath, nxProjectName) {
|
|
209
|
+
const projectJsonPath = `${newPath}/project.json`;
|
|
210
|
+
if (!tree.exists(projectJsonPath)) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
let content = tree.read(projectJsonPath, 'utf-8');
|
|
214
|
+
if (!content) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
let updated = false;
|
|
218
|
+
// Update lintFilePatterns that still reference the old path
|
|
219
|
+
if (content.includes(oldPath)) {
|
|
220
|
+
content = content.replace(new RegExp(escapeRegExp(oldPath), 'g'), newPath);
|
|
221
|
+
updated = true;
|
|
222
|
+
}
|
|
223
|
+
if (updated) {
|
|
224
|
+
tree.write(projectJsonPath, content);
|
|
225
|
+
devkit_1.logger.info(`✅ Updated project.json paths and comments`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Update README.md to reflect the new package name
|
|
230
|
+
* Nx's move generator doesn't update documentation files
|
|
231
|
+
*/
|
|
232
|
+
function updateReadme(tree, newPath, oldPackageJsonName, newPackageJsonName) {
|
|
233
|
+
const readmePath = `${newPath}/README.md`;
|
|
234
|
+
if (!tree.exists(readmePath)) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
let content = tree.read(readmePath, 'utf-8');
|
|
238
|
+
if (!content) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
let updated = false;
|
|
242
|
+
// Replace old package.json name with new package.json name
|
|
243
|
+
if (content.includes(oldPackageJsonName)) {
|
|
244
|
+
content = content.replace(new RegExp(escapeRegExp(oldPackageJsonName), 'g'), newPackageJsonName);
|
|
245
|
+
updated = true;
|
|
246
|
+
}
|
|
247
|
+
if (updated) {
|
|
248
|
+
tree.write(readmePath, content);
|
|
249
|
+
devkit_1.logger.info(`✅ Updated README.md`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Escape special regex characters in a string
|
|
254
|
+
*/
|
|
255
|
+
function escapeRegExp(string) {
|
|
256
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
257
|
+
}
|
|
258
|
+
async function changePackageScopeGenerator(tree, options) {
|
|
259
|
+
devkit_1.logger.info('');
|
|
260
|
+
devkit_1.logger.info('🔄 Starting package scope change...');
|
|
261
|
+
devkit_1.logger.info('');
|
|
262
|
+
// Validate .unisphere exists and get experience name
|
|
263
|
+
const unisphereConfig = (0, utils_1.validateUnisphereConfig)(tree);
|
|
264
|
+
const experienceName = unisphereConfig.name;
|
|
265
|
+
// Convert scope from schema format (without @) to internal format (with @)
|
|
266
|
+
// Schema provides: "kaltura-sdk", we need: "@kaltura-sdk"
|
|
267
|
+
const newScope = `@${options.newScope}`;
|
|
268
|
+
// Find package in .unisphere and validate it exists
|
|
269
|
+
const packageInfo = findPackageInUnisphere(tree, options.packageJsonName, experienceName);
|
|
270
|
+
devkit_1.logger.info(`📦 Package: ${packageInfo.packageIdentifier}`);
|
|
271
|
+
devkit_1.logger.info(`🏷️ Current: ${packageInfo.packageJsonName} (${packageInfo.subdirectory || 'root'}/)`);
|
|
272
|
+
// Validate target scope is different from current
|
|
273
|
+
validateDifferentScope(packageInfo.currentScope, newScope);
|
|
274
|
+
// Calculate new subdirectory and paths
|
|
275
|
+
const newSubdirectory = (0, utils_2.scopeToSubdirectory)(newScope);
|
|
276
|
+
// Validate no collision in target subdirectory
|
|
277
|
+
validateNoCollision(tree, packageInfo.packageIdentifier, newSubdirectory);
|
|
278
|
+
// Validate special package restrictions
|
|
279
|
+
validateSpecialPackageRestrictions(packageInfo.packageIdentifier, newScope);
|
|
280
|
+
// Calculate new package.json name
|
|
281
|
+
const newPackageJsonName = (0, utils_2.calculateNewPackageJsonName)(packageInfo.packageIdentifier, experienceName, newScope);
|
|
282
|
+
// Calculate new paths
|
|
283
|
+
const newPath = `unisphere/packages/${newSubdirectory}/${packageInfo.packageIdentifier}`;
|
|
284
|
+
const nxProjectName = `unisphere-package-${packageInfo.packageIdentifier}`;
|
|
285
|
+
devkit_1.logger.info(`🏷️ Target: ${newPackageJsonName} (${newSubdirectory}/)`);
|
|
286
|
+
devkit_1.logger.info(`📁 Moving: ${packageInfo.sourceRoot} → ${newPath}`);
|
|
287
|
+
devkit_1.logger.info('');
|
|
288
|
+
// Run Nx's built-in move generator
|
|
289
|
+
devkit_1.logger.info('🔧 Running Nx move generator...');
|
|
290
|
+
try {
|
|
291
|
+
await (0, generators_1.moveGenerator)(tree, {
|
|
292
|
+
projectName: nxProjectName,
|
|
293
|
+
destination: newPath,
|
|
294
|
+
newProjectName: nxProjectName,
|
|
295
|
+
importPath: newPackageJsonName,
|
|
296
|
+
updateImportPath: true,
|
|
297
|
+
skipFormat: false,
|
|
298
|
+
});
|
|
299
|
+
devkit_1.logger.info(`✅ Nx moved project and updated imports`);
|
|
300
|
+
}
|
|
301
|
+
catch (error) {
|
|
302
|
+
devkit_1.logger.error(`❌ Failed to move project with Nx: ${error}`);
|
|
303
|
+
throw error;
|
|
304
|
+
}
|
|
305
|
+
devkit_1.logger.info('');
|
|
306
|
+
devkit_1.logger.info('🧹 Performing Unisphere-specific cleanup...');
|
|
307
|
+
// Update .unisphere configuration
|
|
308
|
+
updateUnisphereConfiguration(tree, packageInfo.packageIdentifier, newPath);
|
|
309
|
+
// Update package.json to ensure correct naming
|
|
310
|
+
updatePackageJson(tree, newPath, newPackageJsonName);
|
|
311
|
+
// Update package-lock.json
|
|
312
|
+
updatePackageLock(tree, packageInfo.sourceRoot, newPath);
|
|
313
|
+
// Update vite.config.ts
|
|
314
|
+
updateViteConfig(tree, newPath, packageInfo.packageIdentifier);
|
|
315
|
+
// Update project.json
|
|
316
|
+
updateProjectJson(tree, newPath, packageInfo.sourceRoot, nxProjectName);
|
|
317
|
+
// Update README.md
|
|
318
|
+
updateReadme(tree, newPath, packageInfo.packageJsonName, newPackageJsonName);
|
|
319
|
+
devkit_1.logger.info('');
|
|
320
|
+
devkit_1.logger.info('✅ Package scope changed successfully!');
|
|
321
|
+
devkit_1.logger.info('');
|
|
322
|
+
devkit_1.logger.info('📋 Summary:');
|
|
323
|
+
devkit_1.logger.info(` • Package: ${packageInfo.packageIdentifier}`);
|
|
324
|
+
devkit_1.logger.info(` • Old scope: ${packageInfo.currentScope || 'none'}`);
|
|
325
|
+
devkit_1.logger.info(` • New scope: ${newScope}`);
|
|
326
|
+
devkit_1.logger.info(` • Old location: ${packageInfo.sourceRoot}`);
|
|
327
|
+
devkit_1.logger.info(` • New location: ${newPath}`);
|
|
328
|
+
devkit_1.logger.info(` • Old package.json name: ${packageInfo.packageJsonName}`);
|
|
329
|
+
devkit_1.logger.info(` • New package.json name: ${newPackageJsonName}`);
|
|
330
|
+
devkit_1.logger.info('');
|
|
331
|
+
devkit_1.logger.info('⚠️ IMPORTANT - Consumers must update:');
|
|
332
|
+
devkit_1.logger.info(' • Update all import statements from old to new package name');
|
|
333
|
+
devkit_1.logger.info(' • Update package.json dependencies if they reference this package');
|
|
334
|
+
devkit_1.logger.info(' • Run npm install to update lock file');
|
|
335
|
+
devkit_1.logger.info('');
|
|
336
|
+
devkit_1.logger.info('📝 Next steps:');
|
|
337
|
+
devkit_1.logger.info(' 1. Review the changes: git status');
|
|
338
|
+
devkit_1.logger.info(' 2. Stage all changes: git add -A');
|
|
339
|
+
devkit_1.logger.info(' Git will detect the directory move as a rename (preserving history)');
|
|
340
|
+
devkit_1.logger.info(' 3. Run: npm install (to update package-lock.json)');
|
|
341
|
+
devkit_1.logger.info(' 4. Run: npm run build (to verify everything builds)');
|
|
342
|
+
devkit_1.logger.info(' 5. Commit the changes: git commit -m "Change package scope..."');
|
|
343
|
+
devkit_1.logger.info('');
|
|
344
|
+
}
|
|
345
|
+
exports.default = changePackageScopeGenerator;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/schema",
|
|
3
|
+
"$id": "ChangePackageScope",
|
|
4
|
+
"title": "Change Package Scope Generator",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"packageJsonName": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "The full package.json name (e.g., @kaltura-corp/unisphere-rtc-avatar)",
|
|
10
|
+
"pattern": "^@[a-z0-9-]+/[a-z0-9-]+$",
|
|
11
|
+
"x-prompt": "What is the full package.json name? (from the package's package.json)"
|
|
12
|
+
},
|
|
13
|
+
"newScope": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "The target scope for the package",
|
|
16
|
+
"enum": ["unisphere", "kaltura-corp", "kaltura-sdk", "kaltura-apps", "kaltura-ui", "local"],
|
|
17
|
+
"x-prompt": "What scope should the package move to?"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"required": [
|
|
21
|
+
"packageJsonName",
|
|
22
|
+
"newScope"
|
|
23
|
+
]
|
|
24
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface ParsedPackageName {
|
|
2
|
+
scope: string;
|
|
3
|
+
packageName: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Parses a full package.json name to extract scope and package name.
|
|
7
|
+
* Handles the unisphere- prefix rules and tolerates incorrect prefixes.
|
|
8
|
+
*
|
|
9
|
+
* @param packageJsonName - Full package name (e.g., "@kaltura-corp/unisphere-rtc-avatar")
|
|
10
|
+
* @param experienceName - Experience name from .unisphere config (e.g., "rtc")
|
|
11
|
+
* @returns Parsed scope and package name
|
|
12
|
+
*/
|
|
13
|
+
export declare function parsePackageJsonName(packageJsonName: string, experienceName: string): ParsedPackageName;
|
|
14
|
+
/**
|
|
15
|
+
* Calculates the new package.json name based on target scope and package name.
|
|
16
|
+
* Automatically handles unisphere- prefix rules.
|
|
17
|
+
*
|
|
18
|
+
* @param packageName - Package identifier (e.g., "avatar", "models")
|
|
19
|
+
* @param experienceName - Experience name from .unisphere config (e.g., "rtc")
|
|
20
|
+
* @param newScope - Target scope (e.g., "@kaltura-corp", "@unisphere")
|
|
21
|
+
* @returns New package.json name
|
|
22
|
+
*/
|
|
23
|
+
export declare function calculateNewPackageJsonName(packageName: string, experienceName: string, newScope: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Extracts the scope from a subdirectory name.
|
|
26
|
+
*
|
|
27
|
+
* @param subdirectory - Subdirectory name (e.g., "kaltura-corp") or null for flat structure
|
|
28
|
+
* @returns Scope (e.g., "@kaltura-corp") or null
|
|
29
|
+
*/
|
|
30
|
+
export declare function extractScopeFromSubdirectory(subdirectory: string | null): string | null;
|
|
31
|
+
/**
|
|
32
|
+
* Converts a scope to a subdirectory name.
|
|
33
|
+
*
|
|
34
|
+
* @param scope - Scope (e.g., "@kaltura-corp")
|
|
35
|
+
* @returns Subdirectory name (e.g., "kaltura-corp")
|
|
36
|
+
*/
|
|
37
|
+
export declare function scopeToSubdirectory(scope: string): string;
|
|
38
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/generators/change-package-scope/utils.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,eAAe,EAAE,MAAM,EACvB,cAAc,EAAE,MAAM,GACrB,iBAAiB,CAkDnB;AAED;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,CACzC,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,MAAM,GACf,MAAM,CAiCR;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAKvF;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAWzD"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parsePackageJsonName = parsePackageJsonName;
|
|
4
|
+
exports.calculateNewPackageJsonName = calculateNewPackageJsonName;
|
|
5
|
+
exports.extractScopeFromSubdirectory = extractScopeFromSubdirectory;
|
|
6
|
+
exports.scopeToSubdirectory = scopeToSubdirectory;
|
|
7
|
+
/**
|
|
8
|
+
* Parses a full package.json name to extract scope and package name.
|
|
9
|
+
* Handles the unisphere- prefix rules and tolerates incorrect prefixes.
|
|
10
|
+
*
|
|
11
|
+
* @param packageJsonName - Full package name (e.g., "@kaltura-corp/unisphere-rtc-avatar")
|
|
12
|
+
* @param experienceName - Experience name from .unisphere config (e.g., "rtc")
|
|
13
|
+
* @returns Parsed scope and package name
|
|
14
|
+
*/
|
|
15
|
+
function parsePackageJsonName(packageJsonName, experienceName) {
|
|
16
|
+
if (!packageJsonName?.trim()) {
|
|
17
|
+
throw new Error('packageJsonName cannot be empty');
|
|
18
|
+
}
|
|
19
|
+
if (!experienceName?.trim()) {
|
|
20
|
+
throw new Error('experienceName cannot be empty');
|
|
21
|
+
}
|
|
22
|
+
// Validate format: must start with @scope/
|
|
23
|
+
const scopeMatch = packageJsonName.match(/^(@[^/]+)\//);
|
|
24
|
+
if (!scopeMatch) {
|
|
25
|
+
throw new Error(`Invalid package.json name format: "${packageJsonName}"\n` +
|
|
26
|
+
'Expected format: @scope/package-name');
|
|
27
|
+
}
|
|
28
|
+
const scope = scopeMatch[1];
|
|
29
|
+
let nameAfterScope = packageJsonName.substring(scope.length + 1); // +1 for the '/'
|
|
30
|
+
// Remove unisphere- prefix if present (handle incorrect usage)
|
|
31
|
+
if (nameAfterScope.startsWith('unisphere-')) {
|
|
32
|
+
nameAfterScope = nameAfterScope.substring('unisphere-'.length);
|
|
33
|
+
}
|
|
34
|
+
// Remove experience prefix
|
|
35
|
+
if (nameAfterScope === experienceName) {
|
|
36
|
+
// Special case: package name is same as experience (e.g., "@unisphere/rtc")
|
|
37
|
+
return { scope, packageName: experienceName };
|
|
38
|
+
}
|
|
39
|
+
const expectedPrefix = `${experienceName}-`;
|
|
40
|
+
if (!nameAfterScope.startsWith(expectedPrefix)) {
|
|
41
|
+
throw new Error(`Package name "${packageJsonName}" does not follow expected format.\n` +
|
|
42
|
+
`Expected: ${scope}/${expectedPrefix}package-name or ${scope}/${experienceName}\n` +
|
|
43
|
+
`Found: ${packageJsonName}`);
|
|
44
|
+
}
|
|
45
|
+
const packageName = nameAfterScope.substring(expectedPrefix.length);
|
|
46
|
+
if (!packageName) {
|
|
47
|
+
throw new Error(`Package name "${packageJsonName}" results in empty package name.\n` +
|
|
48
|
+
`Expected: ${scope}/${expectedPrefix}<package-name>`);
|
|
49
|
+
}
|
|
50
|
+
return { scope, packageName };
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Calculates the new package.json name based on target scope and package name.
|
|
54
|
+
* Automatically handles unisphere- prefix rules.
|
|
55
|
+
*
|
|
56
|
+
* @param packageName - Package identifier (e.g., "avatar", "models")
|
|
57
|
+
* @param experienceName - Experience name from .unisphere config (e.g., "rtc")
|
|
58
|
+
* @param newScope - Target scope (e.g., "@kaltura-corp", "@unisphere")
|
|
59
|
+
* @returns New package.json name
|
|
60
|
+
*/
|
|
61
|
+
function calculateNewPackageJsonName(packageName, experienceName, newScope) {
|
|
62
|
+
if (!packageName?.trim()) {
|
|
63
|
+
throw new Error('packageName cannot be empty');
|
|
64
|
+
}
|
|
65
|
+
if (!experienceName?.trim()) {
|
|
66
|
+
throw new Error('experienceName cannot be empty');
|
|
67
|
+
}
|
|
68
|
+
if (!newScope?.trim()) {
|
|
69
|
+
throw new Error('newScope cannot be empty');
|
|
70
|
+
}
|
|
71
|
+
if (!newScope.startsWith('@')) {
|
|
72
|
+
throw new Error(`Invalid scope format: "${newScope}"\n` +
|
|
73
|
+
'Expected format: @scope (e.g., @unisphere, @kaltura-corp)');
|
|
74
|
+
}
|
|
75
|
+
// Special case: package name equals experience name
|
|
76
|
+
if (packageName === experienceName) {
|
|
77
|
+
if (newScope === '@kaltura-corp') {
|
|
78
|
+
return `@kaltura-corp/unisphere-${experienceName}`;
|
|
79
|
+
}
|
|
80
|
+
return `${newScope}/${experienceName}`;
|
|
81
|
+
}
|
|
82
|
+
// Regular case: experience-package
|
|
83
|
+
const baseName = `${experienceName}-${packageName}`;
|
|
84
|
+
if (newScope === '@kaltura-corp') {
|
|
85
|
+
return `@kaltura-corp/unisphere-${baseName}`;
|
|
86
|
+
}
|
|
87
|
+
return `${newScope}/${baseName}`;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Extracts the scope from a subdirectory name.
|
|
91
|
+
*
|
|
92
|
+
* @param subdirectory - Subdirectory name (e.g., "kaltura-corp") or null for flat structure
|
|
93
|
+
* @returns Scope (e.g., "@kaltura-corp") or null
|
|
94
|
+
*/
|
|
95
|
+
function extractScopeFromSubdirectory(subdirectory) {
|
|
96
|
+
if (!subdirectory?.trim()) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
return `@${subdirectory}`;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Converts a scope to a subdirectory name.
|
|
103
|
+
*
|
|
104
|
+
* @param scope - Scope (e.g., "@kaltura-corp")
|
|
105
|
+
* @returns Subdirectory name (e.g., "kaltura-corp")
|
|
106
|
+
*/
|
|
107
|
+
function scopeToSubdirectory(scope) {
|
|
108
|
+
if (!scope?.trim()) {
|
|
109
|
+
throw new Error('scope cannot be empty');
|
|
110
|
+
}
|
|
111
|
+
if (!scope.startsWith('@')) {
|
|
112
|
+
throw new Error(`Invalid scope format: "${scope}"\n` +
|
|
113
|
+
'Expected format: @scope (e.g., @unisphere, @kaltura-corp)');
|
|
114
|
+
}
|
|
115
|
+
return scope.substring(1);
|
|
116
|
+
}
|
package/generators.json
CHANGED
|
@@ -30,6 +30,11 @@
|
|
|
30
30
|
"schema": "./dist/generators/rename-package/schema.json",
|
|
31
31
|
"description": "Rename a unisphere package and update all references"
|
|
32
32
|
},
|
|
33
|
+
"change-package-scope": {
|
|
34
|
+
"factory": "./dist/generators/change-package-scope/change-package-scope",
|
|
35
|
+
"schema": "./dist/generators/change-package-scope/schema.json",
|
|
36
|
+
"description": "Change a package's npm scope by moving it between subdirectories"
|
|
37
|
+
},
|
|
33
38
|
"remove": {
|
|
34
39
|
"factory": "./dist/generators/remove/remove",
|
|
35
40
|
"schema": "./dist/generators/remove/schema.json",
|