@unisphere/nx 4.9.0 → 4.11.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 (27) hide show
  1. package/dist/generators/add-runtime/add-runtime.d.ts +1 -1
  2. package/dist/generators/add-runtime/add-runtime.d.ts.map +1 -1
  3. package/dist/generators/add-runtime/add-runtime.js +149 -0
  4. package/dist/generators/add-runtime/schema.d.ts +1 -0
  5. package/dist/generators/add-runtime/schema.json +5 -0
  6. package/dist/generators/add-runtime/templates/new-flavor/runtime-__flavorName__.tsx.template +63 -0
  7. package/dist/generators/add-runtime/templates/new-flavor-types/runtime-__flavorName__-types.ts.template +20 -0
  8. package/dist/generators/add-runtime/templates/new-runtime/src/lib/runtime.tsx.template +1 -1
  9. package/dist/generators/add-visual/add-visual.d.ts +2 -0
  10. package/dist/generators/add-visual/add-visual.d.ts.map +1 -1
  11. package/dist/generators/add-visual/add-visual.js +45 -22
  12. package/dist/generators/add-visual/schema.d.ts +1 -0
  13. package/dist/generators/add-visual/schema.json +4 -0
  14. package/dist/migrations/4-10-1/add-get-workspace-to-get-service.d.ts +9 -0
  15. package/dist/migrations/4-10-1/add-get-workspace-to-get-service.d.ts.map +1 -0
  16. package/dist/migrations/4-10-1/add-get-workspace-to-get-service.js +54 -0
  17. package/dist/migrations/4-10-1/update-unisphere-visual-target.d.ts +10 -0
  18. package/dist/migrations/4-10-1/update-unisphere-visual-target.d.ts.map +1 -0
  19. package/dist/migrations/4-10-1/update-unisphere-visual-target.js +168 -0
  20. package/dist/migrations/4-10-1/wrap-tiny-data-store-initial-value.d.ts +9 -0
  21. package/dist/migrations/4-10-1/wrap-tiny-data-store-initial-value.d.ts.map +1 -0
  22. package/dist/migrations/4-10-1/wrap-tiny-data-store-initial-value.js +65 -0
  23. package/dist/migrations/4-11-0/migrate-analytics-types.d.ts +9 -0
  24. package/dist/migrations/4-11-0/migrate-analytics-types.d.ts.map +1 -0
  25. package/dist/migrations/4-11-0/migrate-analytics-types.js +102 -0
  26. package/migrations.json +55 -0
  27. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  import { Tree } from '@nx/devkit';
2
2
  import { AddRuntimeGeneratorSchema } from './schema';
3
- export declare function addRuntimeGenerator(tree: Tree, options: AddRuntimeGeneratorSchema): Promise<() => void>;
3
+ export declare function addRuntimeGenerator(tree: Tree, options: AddRuntimeGeneratorSchema): Promise<any>;
4
4
  export default addRuntimeGenerator;
5
5
  //# sourceMappingURL=add-runtime.d.ts.map
@@ -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;AAgErD,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,yBAAyB,uBA4GnC;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;AAUlG,OAAO,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AA0SrD,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,yBAAyB,gBAgHnC;AAED,eAAe,mBAAmB,CAAC"}
@@ -4,8 +4,10 @@ exports.addRuntimeGenerator = addRuntimeGenerator;
4
4
  const tslib_1 = require("tslib");
5
5
  const devkit_1 = require("@nx/devkit");
6
6
  const path = tslib_1.__importStar(require("path"));
7
+ const ts_morph_1 = require("ts-morph");
7
8
  const utils_1 = require("../utils");
8
9
  const dependency_config_1 = require("../dependency-config");
10
+ const visual_utils_1 = require("../add-visual/visual-utils");
9
11
  function validateOptions(options) {
10
12
  if (!options.name || options.name.trim() === '') {
11
13
  throw new Error(`Missing required option: 'name'\n` +
@@ -21,6 +23,150 @@ function validateOptions(options) {
21
23
  ` Received: ${options.name}`);
22
24
  }
23
25
  }
26
+ function validateFlavorName(flavor) {
27
+ if (!flavor || flavor.trim() === '') {
28
+ throw new Error(`Missing required option: 'flavor'\n` +
29
+ ` Description: The name of the flavor to add\n` +
30
+ ` Pattern: ^[a-zA-Z][a-zA-Z0-9\\-\\s]*$`);
31
+ }
32
+ const namePattern = /^[a-zA-Z][a-zA-Z0-9\-\s]*$/;
33
+ if (!namePattern.test(flavor)) {
34
+ throw new Error(`Invalid value '${flavor}' for option 'flavor'\n` +
35
+ ` Pattern: ^[a-zA-Z][a-zA-Z0-9\\-\\s]*$\n` +
36
+ ` Received: ${flavor}`);
37
+ }
38
+ if ((0, devkit_1.names)(flavor).fileName === 'default') {
39
+ throw new Error(`Flavor name 'default' is reserved. The default flavor is runtime.tsx.\n` +
40
+ ` Please choose a different flavor name.`);
41
+ }
42
+ }
43
+ function updateCreateFactory(tree, sourceRoot, flavorNames, project) {
44
+ const factoryPath = [`${sourceRoot}/src/lib/create-factory.tsx`, `${sourceRoot}/src/lib/create-factory.ts`]
45
+ .find((p) => tree.exists(p));
46
+ if (!factoryPath) {
47
+ throw new Error(`Create factory file not found in ${sourceRoot}/src/lib/.\n` +
48
+ ` Expected: create-factory.tsx or create-factory.ts`);
49
+ }
50
+ const sourceFile = (0, visual_utils_1.loadSourceFile)(tree, factoryPath, project);
51
+ const flavorLowerDash = flavorNames['flavorName__lowerDashCase'];
52
+ const flavorPascal = flavorNames['flavorName__pascalCase'];
53
+ const className = `Runtime${flavorPascal}`;
54
+ const alreadyImported = sourceFile
55
+ .getImportDeclarations()
56
+ .some((decl) => decl.getNamedImports().some((imp) => imp.getName() === className));
57
+ if (alreadyImported) {
58
+ console.log(`⚠️ Import for ${className} already exists in create-factory.`);
59
+ return;
60
+ }
61
+ sourceFile.addImportDeclaration({
62
+ kind: ts_morph_1.StructureKind.ImportDeclaration,
63
+ namedImports: [className],
64
+ moduleSpecifier: `./runtime-${flavorLowerDash}`,
65
+ });
66
+ const switchStatement = sourceFile.getDescendantsOfKind(ts_morph_1.SyntaxKind.SwitchStatement)[0];
67
+ if (!switchStatement) {
68
+ const createMethod = sourceFile
69
+ .getDescendantsOfKind(ts_morph_1.SyntaxKind.MethodDeclaration)
70
+ .find((m) => m.getName() === 'create');
71
+ (0, visual_utils_1.throwIfNotFound)(createMethod, `No 'create' method found in ${factoryPath}`);
72
+ const returnStatement = createMethod.getDescendantsOfKind(ts_morph_1.SyntaxKind.ReturnStatement)[0];
73
+ (0, visual_utils_1.throwIfNotFound)(returnStatement, `No return statement found in create method in ${factoryPath}`);
74
+ const returnExpr = returnStatement.getExpression()?.getText() || 'new Runtime(options)';
75
+ returnStatement.replaceWithText(`switch (options.flavor) {\n` +
76
+ ` case '${flavorLowerDash}':\n` +
77
+ ` return new ${className}(options) as any;\n` +
78
+ ` default:\n` +
79
+ ` return ${returnExpr};\n` +
80
+ ` }`);
81
+ }
82
+ else {
83
+ const caseBlock = switchStatement.getCaseBlock();
84
+ const cases = caseBlock.getClauses();
85
+ const caseExists = cases.some((c) => {
86
+ if (c.getKind() === ts_morph_1.SyntaxKind.CaseClause) {
87
+ const clause = c;
88
+ return clause.getExpression()?.getText().replace(/['"]/g, '') === flavorLowerDash;
89
+ }
90
+ return false;
91
+ });
92
+ if (caseExists) {
93
+ console.log(`⚠️ Switch case for flavor '${flavorLowerDash}' already exists.`);
94
+ return;
95
+ }
96
+ const newCase = `case '${flavorLowerDash}':\n return new ${className}(options) as any;`;
97
+ const defaultIndex = cases.findIndex((c) => c.getKind() === ts_morph_1.SyntaxKind.DefaultClause);
98
+ if (defaultIndex !== -1) {
99
+ const defaultClause = cases[defaultIndex];
100
+ defaultClause.replaceWithText(`${newCase}\n ${defaultClause.getText()}`);
101
+ }
102
+ else {
103
+ const lastCase = cases[cases.length - 1];
104
+ lastCase.replaceWithText(`${lastCase.getText()}\n ${newCase}`);
105
+ }
106
+ }
107
+ (0, visual_utils_1.saveSourceFile)(tree, factoryPath, sourceFile.getFullText());
108
+ console.log(`✅ Updated create-factory with flavor '${flavorLowerDash}'`);
109
+ }
110
+ function updateFlavorTypesIndexExport(tree, runtimeName, flavorLowerDash, typesPackageInfo) {
111
+ const indexPath = `${typesPackageInfo.basePath}/src/lib/${runtimeName}-runtime/index.ts`;
112
+ if (!tree.exists(indexPath)) {
113
+ throw new Error(`Runtime types index not found at ${indexPath}`);
114
+ }
115
+ const currentContent = tree.read(indexPath, 'utf-8');
116
+ if (!currentContent) {
117
+ throw new Error(`Failed to read content from ${indexPath}`);
118
+ }
119
+ const exportLine = `export * from './runtime-${flavorLowerDash}-types';`;
120
+ if (currentContent.includes(exportLine)) {
121
+ return;
122
+ }
123
+ const updatedContent = currentContent.replace(/\n\n$/, '\n') + exportLine;
124
+ tree.write(indexPath, updatedContent);
125
+ }
126
+ async function addFlavorToRuntime(tree, options) {
127
+ const runtimeName = (0, devkit_1.names)(options.name).fileName;
128
+ const flavor = options.flavor;
129
+ validateFlavorName(flavor);
130
+ const unisphereConfig = (0, utils_1.validateUnisphereConfig)(tree);
131
+ const sourceRoot = (0, utils_1.validateRuntimeExists)(tree, runtimeName);
132
+ const typesPackageInfo = (0, utils_1.findTypesOrCorePackageInfo)(tree);
133
+ const flavorLowerDash = (0, devkit_1.names)(flavor).fileName;
134
+ const flavorFilePath = `${sourceRoot}/src/lib/runtime-${flavorLowerDash}.tsx`;
135
+ if (tree.exists(flavorFilePath)) {
136
+ throw new Error(`Flavor file already exists at ${flavorFilePath}.\n` +
137
+ ` Choose a different flavor name or remove the existing file.`);
138
+ }
139
+ const flavorTypesPath = `${typesPackageInfo.basePath}/src/lib/${runtimeName}-runtime/runtime-${flavorLowerDash}-types.ts`;
140
+ if (tree.exists(flavorTypesPath)) {
141
+ throw new Error(`Flavor types file already exists at ${flavorTypesPath}.\n` +
142
+ ` Choose a different flavor name or remove the existing file.`);
143
+ }
144
+ const runtimeNames = (0, utils_1.createNameTransforms)(runtimeName, 'runtimeName');
145
+ const flavorNames = (0, utils_1.createNameTransforms)(flavorLowerDash, 'flavorName');
146
+ const widgetNames = (0, utils_1.createNameTransforms)(unisphereConfig.name, 'widgetName');
147
+ const templateVariables = {
148
+ ...runtimeNames,
149
+ ...flavorNames,
150
+ ...widgetNames,
151
+ typesAlias: typesPackageInfo.alias,
152
+ tmpl: '',
153
+ };
154
+ (0, devkit_1.generateFiles)(tree, path.join(__dirname, 'templates/new-flavor'), `${sourceRoot}/src/lib`, templateVariables);
155
+ (0, devkit_1.generateFiles)(tree, path.join(__dirname, 'templates/new-flavor-types'), `${typesPackageInfo.basePath}/src/lib/${runtimeName}-runtime`, templateVariables);
156
+ updateFlavorTypesIndexExport(tree, runtimeName, flavorLowerDash, typesPackageInfo);
157
+ const project = new ts_morph_1.Project({
158
+ useInMemoryFileSystem: true,
159
+ skipAddingFilesFromTsConfig: true,
160
+ });
161
+ updateCreateFactory(tree, sourceRoot, flavorNames, project);
162
+ await (0, devkit_1.formatFiles)(tree);
163
+ console.log(`\n🎉 Successfully added flavor '${flavorLowerDash}' to runtime '${runtimeName}'!`);
164
+ console.log(` Flavor file: ${flavorFilePath}`);
165
+ console.log(` Types file: ${flavorTypesPath}`);
166
+ return () => {
167
+ return { runtimeName, flavor: flavorLowerDash };
168
+ };
169
+ }
24
170
  function updateTypesIndexExport(tree, runtimeName, basePath) {
25
171
  const indexPath = `${basePath}/src/index.ts`;
26
172
  if (!tree.exists(indexPath)) {
@@ -41,6 +187,9 @@ function updateTypesIndexExport(tree, runtimeName, basePath) {
41
187
  }
42
188
  async function addRuntimeGenerator(tree, options) {
43
189
  validateOptions(options);
190
+ if (options.flavor) {
191
+ return addFlavorToRuntime(tree, options);
192
+ }
44
193
  // Validate and read .unisphere configuration
45
194
  const unisphereConfig = (0, utils_1.validateUnisphereConfig)(tree);
46
195
  // Validate dependencies
@@ -2,4 +2,5 @@ export interface AddRuntimeGeneratorSchema {
2
2
  name: string;
3
3
  dependencies?: string[];
4
4
  analyticsAppId?: number;
5
+ flavor?: string;
5
6
  }
@@ -21,6 +21,11 @@
21
21
  "analyticsAppId": {
22
22
  "type": "number",
23
23
  "description": "Analytics app ID (optional, can be set later in runtime constructor)"
24
+ },
25
+ "flavor": {
26
+ "type": "string",
27
+ "description": "Name of the flavor to add to an existing runtime (e.g. 'player-plugin')",
28
+ "pattern": "^[a-zA-Z][a-zA-Z0-9\\-\\s]*$"
24
29
  }
25
30
  },
26
31
  "required": [
@@ -0,0 +1,63 @@
1
+ import * as ReactDOM from 'react-dom/client';
2
+ import { Root } from 'react-dom/client';
3
+ import {
4
+ CreateElementOptions,
5
+ UnisphereRuntimeBase,
6
+ } from '@unisphere/runtime-js';
7
+ import {
8
+ <%= runtimeName__pascalCase %>Runtime<%= flavorName__pascalCase %>Settings,
9
+ <%= runtimeName__camelCase %>Runtime<%= flavorName__pascalCase %>SettingsSchema,
10
+ <%= runtimeName__pascalCase %>RuntimeName,
11
+ <%= runtimeName__pascalCase %><%= flavorName__pascalCase %>Runtime,
12
+ widgetName,
13
+ } from '<%= typesAlias %>';
14
+ import { HtmlDomRuntimeVisual } from '@unisphere/runtime';
15
+
16
+ export class Runtime<%= flavorName__pascalCase %>
17
+ extends UnisphereRuntimeBase<<%= runtimeName__pascalCase %>Runtime<%= flavorName__pascalCase %>Settings, Root>
18
+ implements <%= runtimeName__pascalCase %><%= flavorName__pascalCase %>Runtime {
19
+ readonly id = widgetName;
20
+ readonly runtime = <%= runtimeName__pascalCase %>RuntimeName;
21
+ readonly widgetName = widgetName;
22
+ readonly runtimeName = <%= runtimeName__pascalCase %>RuntimeName;
23
+ readonly flavor = '<%= flavorName__lowerDashCase %>';
24
+
25
+ protected _onKilled(): void {
26
+ this._logger.log('runtime killed');
27
+ }
28
+
29
+ constructor(options: CreateElementOptions<<%= runtimeName__pascalCase %>Runtime<%= flavorName__pascalCase %>Settings>) {
30
+ super({
31
+ ...options,
32
+ settingsSchema: <%= runtimeName__camelCase %>Runtime<%= flavorName__pascalCase %>SettingsSchema,
33
+ visualTypes: {},
34
+ });
35
+
36
+ this._logger.log('runtime initialized', {
37
+ data: {
38
+ widgetName: this.widgetName,
39
+ runtimeName: this.runtimeName,
40
+ flavor: this.flavor,
41
+ },
42
+ });
43
+ }
44
+
45
+ override _createVisualContainer(htmlElement: HTMLElement): Root {
46
+ return ReactDOM.createRoot(htmlElement);
47
+ }
48
+
49
+ override _onVisualMount(visual: HtmlDomRuntimeVisual<Root>) {
50
+ switch (visual.type) {
51
+ default:
52
+ return false;
53
+ }
54
+ }
55
+
56
+ override _onVisualUnmount(visual: HtmlDomRuntimeVisual<Root>) {
57
+ visual.htmlContainer?.unmount();
58
+ }
59
+
60
+ protected _onSettingsUpdated(settings: <%= runtimeName__pascalCase %>Runtime<%= flavorName__pascalCase %>Settings) {
61
+ // use this method to react to settings changes
62
+ }
63
+ }
@@ -0,0 +1,20 @@
1
+ import { ValidatorSchema } from '@unisphere/core';
2
+ import { UnisphereRuntimeBaseType } from '@unisphere/runtime';
3
+ import { widgetName } from '../widget-types';
4
+ import { <%= runtimeName__pascalCase %>RuntimeName } from './runtime-types';
5
+
6
+ export interface <%= runtimeName__pascalCase %>Runtime<%= flavorName__pascalCase %>Settings {
7
+ schemaVersion?: string;
8
+ }
9
+
10
+ export const <%= runtimeName__camelCase %>Runtime<%= flavorName__pascalCase %>SettingsSchema: ValidatorSchema = {
11
+ type: 'object',
12
+ properties: {
13
+ schemaVersion: { type: 'literal', value: '1', optional: true },
14
+ },
15
+ };
16
+
17
+ export type <%= runtimeName__pascalCase %><%= flavorName__pascalCase %>Runtime = UnisphereRuntimeBaseType<<%= runtimeName__pascalCase %>Runtime<%= flavorName__pascalCase %>Settings> & {
18
+ readonly widgetName: typeof widgetName;
19
+ readonly runtimeName: typeof <%= runtimeName__pascalCase %>RuntimeName;
20
+ }
@@ -9,9 +9,9 @@ import {
9
9
  <%= runtimeName__pascalCase %>RuntimeName,
10
10
  <%= runtimeName__pascalCase %>RuntimeSettings,
11
11
  <%= runtimeName__camelCase %>RuntimeSettingsSchema,
12
+ widgetName,
12
13
  } from '<%= typesAlias %>';
13
14
  import { HtmlDomRuntimeVisual, KalturaAnalyticsServiceType } from '@unisphere/runtime';
14
- import { widgetName } from '<%= typesAlias %>'
15
15
 
16
16
  export class Runtime
17
17
  extends UnisphereRuntimeBase<<%= runtimeName__pascalCase %>RuntimeSettings, Root>
@@ -1,5 +1,7 @@
1
1
  import { Tree } from '@nx/devkit';
2
2
  import { AddVisualGeneratorSchema } from './schema';
3
+ export declare function discoverAvailableFlavors(tree: Tree, sourceRoot: string): string[];
4
+ export declare function resolveTargetFile(tree: Tree, sourceRoot: string, flavor: string | undefined): string;
3
5
  /**
4
6
  * Nx generator to create a new visual within a specified runtime.
5
7
  */
@@ -1 +1 @@
1
- {"version":3,"file":"add-visual.d.ts","sourceRoot":"","sources":["../../../src/generators/add-visual/add-visual.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,IAAI,EAAE,MAAM,YAAY,CAAC;AAsB9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAmapD;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,GAAG,CAAC,CA2Fd;AAED,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"add-visual.d.ts","sourceRoot":"","sources":["../../../src/generators/add-visual/add-visual.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,IAAI,EAAE,MAAM,YAAY,CAAC;AAsB9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAapD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAUjF;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GAAG,SAAS,GACzB,MAAM,CAuBR;AAwZD;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,GAAG,CAAC,CA6Ed;AAED,eAAe,kBAAkB,CAAC"}
@@ -1,5 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.discoverAvailableFlavors = discoverAvailableFlavors;
4
+ exports.resolveTargetFile = resolveTargetFile;
3
5
  exports.addVisualGenerator = addVisualGenerator;
4
6
  const tslib_1 = require("tslib");
5
7
  const devkit_1 = require("@nx/devkit");
@@ -7,6 +9,37 @@ const path = tslib_1.__importStar(require("path"));
7
9
  const ts_morph_1 = require("ts-morph");
8
10
  const utils_1 = require("../utils");
9
11
  const visual_utils_1 = require("./visual-utils");
12
+ function discoverAvailableFlavors(tree, sourceRoot) {
13
+ const libDir = `${sourceRoot}/src/lib`;
14
+ if (!tree.exists(libDir)) {
15
+ return [];
16
+ }
17
+ return tree
18
+ .children(libDir)
19
+ .filter((f) => /^(runtime-.+|.+-runtime-base)\.tsx$/.test(f))
20
+ .map((f) => f.replace('.tsx', ''))
21
+ .sort();
22
+ }
23
+ function resolveTargetFile(tree, sourceRoot, flavor) {
24
+ const libDir = `${sourceRoot}/src/lib`;
25
+ if (!flavor) {
26
+ const defaultPath = `${libDir}/runtime.tsx`;
27
+ if (!tree.exists(defaultPath)) {
28
+ throw new Error(`Default runtime file not found at ${defaultPath}`);
29
+ }
30
+ return defaultPath;
31
+ }
32
+ const targetPath = `${libDir}/${flavor}.tsx`;
33
+ if (!tree.exists(targetPath)) {
34
+ const available = discoverAvailableFlavors(tree, sourceRoot);
35
+ throw new Error(`Flavor file '${flavor}.tsx' not found in ${libDir}.\n` +
36
+ (available.length > 0
37
+ ? ` Available flavors: ${available.join(', ')}\n`
38
+ : '') +
39
+ ` Omit --flavor to target the default runtime.`);
40
+ }
41
+ return targetPath;
42
+ }
10
43
  function validateOptions(options) {
11
44
  if (!options.runtimeName || options.runtimeName.trim() === '') {
12
45
  throw new Error(`Missing required option: 'runtimeName'\n` +
@@ -130,8 +163,7 @@ function addVisualTypesToConstructor(sourceFilePath, tree, vars, project, isSing
130
163
  const visualTypesProp = (0, visual_utils_1.throwIfNotFound)(objectLiteral
131
164
  .getProperties()
132
165
  .find((prop) => prop.getKind() === ts_morph_1.SyntaxKind.PropertyAssignment &&
133
- prop.getName() === 'visualTypes'), // Assert type after finding
134
- `Could not find visualTypes property in super() call in ${sourceFilePath}`);
166
+ ['visualTypes', 'flavorVisualTypes'].includes(prop.getName())), `Could not find visualTypes or flavorVisualTypes property in super() call in ${sourceFilePath}`);
135
167
  const visualTypesObject = (0, visual_utils_1.throwIfNotFound)(visualTypesProp.getInitializer(), // Assert type after getting initializer
136
168
  `visualTypes is not an object literal in ${sourceFilePath}`);
137
169
  if ((0, visual_utils_1.propertyExists)(visualTypesObject, visualCamel)) {
@@ -287,18 +319,14 @@ async function addVisualGenerator(tree, options) {
287
319
  const isSingleOccurrence = options.isSingleOccurrence ?? false;
288
320
  // Extract environment variables
289
321
  const widgetName = unisphereConfig.name;
290
- // Validate runtime existence and get source root path.
291
322
  const runtimeSourceRoot = (0, utils_1.validateRuntimeExists)(tree, runtimeName);
292
- const runtimeTSxPath = `${runtimeSourceRoot}/src/lib/runtime.tsx`;
293
- // Find types package (or fallback to core)
323
+ const targetFile = resolveTargetFile(tree, runtimeSourceRoot, options.flavor);
294
324
  const typesPackageInfo = (0, utils_1.findTypesOrCorePackageInfo)(tree);
295
325
  const runtimeNames = (0, utils_1.createNameTransforms)(runtimeName, 'runtimeName');
296
326
  const visualNames = (0, utils_1.createNameTransforms)(visualName, 'visualName');
297
327
  const widgetNames = (0, utils_1.createNameTransforms)(widgetName, 'widgetName');
298
- // Derive specific names for runtime visual settings and schema based on transforms.
299
328
  const runtimeVisualSettings = `${runtimeNames.runtimeName__pascalCase}Runtime${visualNames.visualName__pascalCase}VisualSettings`;
300
329
  const runtimeVisualSchema = `${runtimeNames.runtimeName__camelCase}Runtime${visualNames.visualName__pascalCase}VisualSettingsSchema`;
301
- // Combine all template variables for easy access and passing to functions.
302
330
  const templateVariables = {
303
331
  ...runtimeNames,
304
332
  ...visualNames,
@@ -307,30 +335,25 @@ async function addVisualGenerator(tree, options) {
307
335
  runtimeVisualSchema,
308
336
  typesAlias: typesPackageInfo.alias,
309
337
  };
310
- // Ensure the target runtime file exists before proceeding.
311
- if (!tree.exists(runtimeTSxPath)) {
312
- throw new Error(`Runtime file not found at ${runtimeTSxPath}`);
313
- }
314
- // Initialize ts-morph project with an in-memory file system for modifications.
315
338
  const project = new ts_morph_1.Project({
316
339
  useInMemoryFileSystem: true,
317
340
  skipAddingFilesFromTsConfig: true,
318
341
  });
319
- // Execute all code modification steps.
320
- addImportToRuntime(runtimeTSxPath, tree, templateVariables, project);
321
- addVisualTypesToConstructor(runtimeTSxPath, tree, templateVariables, project, isSingleOccurrence);
322
- addSwitchCaseToRuntime(runtimeTSxPath, tree, templateVariables, project);
323
- addRenderMethod(runtimeTSxPath, tree, templateVariables, project, typesPackageInfo);
324
- // 'project' parameter is not needed here as createVisualTypes directly writes to the tree.
342
+ if (options.flavor) {
343
+ console.log(`\nProcessing flavor '${options.flavor}'...`);
344
+ }
345
+ addImportToRuntime(targetFile, tree, templateVariables, project);
346
+ addVisualTypesToConstructor(targetFile, tree, templateVariables, project, isSingleOccurrence);
347
+ addSwitchCaseToRuntime(targetFile, tree, templateVariables, project);
348
+ addRenderMethod(targetFile, tree, templateVariables, project, typesPackageInfo);
325
349
  createVisualTypes(tree, templateVariables, typesPackageInfo);
326
- // Format all modified files for consistent code style.
327
350
  await (0, devkit_1.formatFiles)(tree);
328
- // Log success and summary information to the console.
329
- console.log(`\n🎉 Successfully added visual '${visualName}' to runtime '${runtimeName}'!`);
351
+ const flavorSummary = options.flavor ? ` (flavor: ${options.flavor})` : '';
352
+ console.log(`\n🎉 Successfully added visual '${visualName}' to runtime '${runtimeName}'${flavorSummary}!`);
330
353
  console.log(` Runtime: ${runtimeName} (${runtimeSourceRoot})`);
354
+ console.log(` Target: ${targetFile}`);
331
355
  console.log(` Visual: ${visualName}`);
332
356
  console.log(` Single occurrence: ${isSingleOccurrence ? 'Yes' : 'No'}`);
333
- console.log(` Modified file: ${runtimeTSxPath}`);
334
357
  return () => {
335
358
  return { visualName };
336
359
  };
@@ -2,4 +2,5 @@ export interface AddVisualGeneratorSchema {
2
2
  runtimeName?: string;
3
3
  visualName?: string;
4
4
  isSingleOccurrence?: boolean;
5
+ flavor?: string;
5
6
  }
@@ -18,6 +18,10 @@
18
18
  "type": "boolean",
19
19
  "description": "Whether this visual is limited to single occurrence",
20
20
  "default": false
21
+ },
22
+ "flavor": {
23
+ "type": "string",
24
+ "description": "Target file name without .tsx extension (e.g. 'runtime-player-plugin', 'chat-runtime-base'). Omit to target the default runtime.tsx."
21
25
  }
22
26
  },
23
27
  "required": ["runtimeName", "visualName"]
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Migration: Add getWorkspace() call before getService in runtime files
3
+ *
4
+ * Transforms this._options.getService to this._options.getWorkspace().getService
5
+ * in runtime project files.
6
+ */
7
+ import { Tree } from '@nx/devkit';
8
+ export default function update(tree: Tree): Promise<void>;
9
+ //# sourceMappingURL=add-get-workspace-to-get-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-get-workspace-to-get-service.d.ts","sourceRoot":"","sources":["../../../src/migrations/4-10-1/add-get-workspace-to-get-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAA6C,MAAM,YAAY,CAAC;AAE7E,wBAA8B,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CA0D9D"}
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ /**
3
+ * Migration: Add getWorkspace() call before getService in runtime files
4
+ *
5
+ * Transforms this._options.getService to this._options.getWorkspace().getService
6
+ * in runtime project files.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.default = update;
10
+ const devkit_1 = require("@nx/devkit");
11
+ async function update(tree) {
12
+ devkit_1.logger.info('🔄 Adding getWorkspace() before getService calls in runtime projects...');
13
+ const runtimesDir = 'unisphere/runtimes';
14
+ if (!tree.exists(runtimesDir)) {
15
+ devkit_1.logger.info('ℹ️ No runtimes directory found');
16
+ return;
17
+ }
18
+ let updatedCount = 0;
19
+ (0, devkit_1.visitNotIgnoredFiles)(tree, runtimesDir, (filePath) => {
20
+ if (!filePath.endsWith('.ts') && !filePath.endsWith('.tsx'))
21
+ return;
22
+ const content = tree.read(filePath, 'utf-8');
23
+ if (!content)
24
+ return;
25
+ if (!content.includes('_options') || !content.includes('getService'))
26
+ return;
27
+ // Match this._options followed by optional whitespace/newline/dot then .getService
28
+ // Handles: this._options.getService / this._options.\n .getService / this._options\n .getService
29
+ const pattern = /this\._options\.?\s*\.getService/g;
30
+ if (!pattern.test(content))
31
+ return;
32
+ // Already migrated check: if getWorkspace().getService exists, skip
33
+ if (content.includes('.getWorkspace().getService') || content.includes('.getWorkspace()\n')) {
34
+ // More precise check: see if all occurrences are already migrated
35
+ const unmigrated = content.replace(/this\._options\.getWorkspace\(\)\s*\.getService/g, '');
36
+ if (!/this\._options\.?\s*\.getService/.test(unmigrated)) {
37
+ return;
38
+ }
39
+ }
40
+ const updatedContent = content.replace(/this\._options\.?\s*\.\s*getService/g, 'this._options.getWorkspace().getService');
41
+ if (updatedContent !== content) {
42
+ tree.write(filePath, updatedContent);
43
+ updatedCount++;
44
+ devkit_1.logger.info(` ✅ Updated ${filePath}`);
45
+ }
46
+ });
47
+ if (updatedCount === 0) {
48
+ devkit_1.logger.info('ℹ️ No runtime files needed getWorkspace() insertion before getService');
49
+ }
50
+ else {
51
+ await (0, devkit_1.formatFiles)(tree);
52
+ devkit_1.logger.info(`✅ Updated ${updatedCount} runtime file(s)`);
53
+ }
54
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Migration: Update UnisphereVisualTarget usage
3
+ *
4
+ * 1. Renames `target` property to `type` in visual target object literals
5
+ * (where value is 'body' or 'element')
6
+ * 2. Converts string visual targets to { type: 'element', elementId: '<string>' }
7
+ */
8
+ import { Tree } from '@nx/devkit';
9
+ export default function update(tree: Tree): Promise<void>;
10
+ //# sourceMappingURL=update-unisphere-visual-target.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-unisphere-visual-target.d.ts","sourceRoot":"","sources":["../../../src/migrations/4-10-1/update-unisphere-visual-target.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,IAAI,EAA6C,MAAM,YAAY,CAAC;AAS7E,wBAA8B,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAoF9D"}
@@ -0,0 +1,168 @@
1
+ "use strict";
2
+ /**
3
+ * Migration: Update UnisphereVisualTarget usage
4
+ *
5
+ * 1. Renames `target` property to `type` in visual target object literals
6
+ * (where value is 'body' or 'element')
7
+ * 2. Converts string visual targets to { type: 'element', elementId: '<string>' }
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.default = update;
11
+ const devkit_1 = require("@nx/devkit");
12
+ const ts_morph_1 = require("ts-morph");
13
+ async function update(tree) {
14
+ devkit_1.logger.info('🔄 Updating UnisphereVisualTarget usage...');
15
+ const project = new ts_morph_1.Project({
16
+ manipulationSettings: { quoteKind: ts_morph_1.QuoteKind.Single },
17
+ });
18
+ let updatedCount = 0;
19
+ (0, devkit_1.visitNotIgnoredFiles)(tree, '.', (filePath) => {
20
+ if (!filePath.endsWith('.ts') && !filePath.endsWith('.tsx'))
21
+ return;
22
+ if (!filePath.includes('unisphere/'))
23
+ return;
24
+ const content = tree.read(filePath, 'utf-8');
25
+ if (!content)
26
+ return;
27
+ if (!content.includes('target'))
28
+ return;
29
+ const sourceFile = project.createSourceFile(filePath, content, {
30
+ overwrite: true,
31
+ });
32
+ let hasChanges = false;
33
+ // Pass 1: Rename target → type in object literals where value is 'body' or 'element'
34
+ // Only in visual target contexts (mountVisual args, visuals config, nested in target property)
35
+ const allPropertyAssignments = sourceFile.getDescendantsOfKind(ts_morph_1.SyntaxKind.PropertyAssignment);
36
+ for (const prop of allPropertyAssignments) {
37
+ if (prop.getName() !== 'target')
38
+ continue;
39
+ const initializer = prop.getInitializerIfKind(ts_morph_1.SyntaxKind.StringLiteral);
40
+ if (!initializer)
41
+ continue;
42
+ const value = initializer.getLiteralValue();
43
+ if (value !== 'body' && value !== 'element')
44
+ continue;
45
+ if (!isVisualTargetObjectContext(prop))
46
+ continue;
47
+ prop.getNameNode().replaceWithText('type');
48
+ hasChanges = true;
49
+ }
50
+ // Pass 2: Convert string targets to objects in mountVisual calls and visuals config
51
+ // Re-query after Pass 1 modifications
52
+ const propertyAssignments = sourceFile.getDescendantsOfKind(ts_morph_1.SyntaxKind.PropertyAssignment);
53
+ for (const prop of propertyAssignments) {
54
+ if (prop.getName() !== 'target')
55
+ continue;
56
+ const initializer = prop.getInitializerIfKind(ts_morph_1.SyntaxKind.StringLiteral);
57
+ if (!initializer)
58
+ continue;
59
+ const value = initializer.getLiteralValue();
60
+ // Skip 'body' and 'element' - those were handled in Pass 1
61
+ if (value === 'body' || value === 'element')
62
+ continue;
63
+ // Check if this is in a visual target context
64
+ if (!isVisualTargetContext(prop))
65
+ continue;
66
+ // Transform string to { type: 'element', elementId: '<string>' }
67
+ initializer.replaceWithText(`{ type: 'element', elementId: '${value}' }`);
68
+ hasChanges = true;
69
+ }
70
+ if (hasChanges) {
71
+ tree.write(filePath, sourceFile.getFullText());
72
+ updatedCount++;
73
+ devkit_1.logger.info(` ✅ Updated ${filePath}`);
74
+ }
75
+ });
76
+ if (updatedCount === 0) {
77
+ devkit_1.logger.info('ℹ️ No UnisphereVisualTarget usages needed transformation');
78
+ }
79
+ else {
80
+ await (0, devkit_1.formatFiles)(tree);
81
+ devkit_1.logger.info(`✅ Updated UnisphereVisualTarget usage in ${updatedCount} file(s)`);
82
+ }
83
+ }
84
+ /**
85
+ * Checks if a `target` property with value 'body'/'element' is inside a UnisphereVisualTarget object.
86
+ * The object itself (containing target: 'body') is the visual target value, so we check
87
+ * whether it's nested inside a `target` property of a parent, a mountVisual call, or visuals array.
88
+ */
89
+ function isVisualTargetObjectContext(prop) {
90
+ const objLiteral = prop.getParent();
91
+ if (!ts_morph_1.Node.isObjectLiteralExpression(objLiteral))
92
+ return false;
93
+ const objParent = objLiteral.getParent();
94
+ // Context 1: Object is value of a `target` property in a parent object
95
+ // e.g., mountVisual({ target: { target: 'body' } }) — inner object is the visual target
96
+ if (ts_morph_1.Node.isPropertyAssignment(objParent) && objParent.getName() === 'target')
97
+ return true;
98
+ // Context 2: Object is inside a mountVisual() call directly
99
+ // e.g., mountVisual({ target: 'body' }) — less common but possible
100
+ if (ts_morph_1.Node.isCallExpression(objParent)) {
101
+ const expr = objParent.getExpression();
102
+ if (expr.getText().endsWith('mountVisual'))
103
+ return true;
104
+ }
105
+ // Context 3: Object is inside a visuals array item's target property
106
+ // e.g., visuals: [{ target: { target: 'body' } }]
107
+ if (ts_morph_1.Node.isPropertyAssignment(objParent) && objParent.getName() === 'target') {
108
+ const outerObj = objParent.getParent();
109
+ if (ts_morph_1.Node.isObjectLiteralExpression(outerObj)) {
110
+ const arrayParent = outerObj.getParent();
111
+ if (ts_morph_1.Node.isArrayLiteralExpression(arrayParent)) {
112
+ const arrayPropParent = arrayParent.getParent();
113
+ if (ts_morph_1.Node.isPropertyAssignment(arrayPropParent) &&
114
+ arrayPropParent.getName() === 'visuals')
115
+ return true;
116
+ }
117
+ }
118
+ }
119
+ // Context 4: Object has sibling properties that indicate it's a visual target
120
+ // (has elementId for 'element' type, or classNames/style for 'body' type)
121
+ if (objLiteral.getProperty('elementId'))
122
+ return true;
123
+ if (objLiteral.getProperty('classNames'))
124
+ return true;
125
+ if (objLiteral.getProperty('style'))
126
+ return true;
127
+ return false;
128
+ }
129
+ /**
130
+ * Checks if a `target` property with a string value is in a visual target context
131
+ * (the string IS the visual target value, needing conversion to object).
132
+ */
133
+ function isVisualTargetContext(prop) {
134
+ const parent = prop.getParent();
135
+ if (!ts_morph_1.Node.isObjectLiteralExpression(parent))
136
+ return false;
137
+ // Context 1: Inside mountVisual() call argument
138
+ // e.g., super.mountVisual({ type: 'popup', target: 'someId', settings: {} })
139
+ const grandparent = parent.getParent();
140
+ if (ts_morph_1.Node.isCallExpression(grandparent)) {
141
+ const expr = grandparent.getExpression();
142
+ if (expr.getText().endsWith('mountVisual'))
143
+ return true;
144
+ }
145
+ // Context 2: Inside a visuals array item
146
+ // e.g., visuals: [{ target: 'someId', ... }]
147
+ if (ts_morph_1.Node.isArrayLiteralExpression(grandparent)) {
148
+ const arrayParent = grandparent.getParent();
149
+ if (ts_morph_1.Node.isPropertyAssignment(arrayParent)) {
150
+ if (arrayParent.getName() === 'visuals')
151
+ return true;
152
+ }
153
+ }
154
+ // Context 3: Parent object has siblings suggesting visual config
155
+ // (has 'type' property with value like 'popup', 'inline', etc.)
156
+ const typeProp = parent.getProperty('type');
157
+ if (typeProp && ts_morph_1.Node.isPropertyAssignment(typeProp)) {
158
+ const typeInit = typeProp.getInitializerIfKind(ts_morph_1.SyntaxKind.StringLiteral);
159
+ if (typeInit) {
160
+ const typeValue = typeInit.getLiteralValue();
161
+ if (typeValue === 'popup' ||
162
+ typeValue === 'inline' ||
163
+ typeValue === 'drawer')
164
+ return true;
165
+ }
166
+ }
167
+ return false;
168
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Migration: Wrap TinyDataStore/TinyStorage constructor arguments in initialValue
3
+ *
4
+ * Transforms constructor calls to wrap the argument in an { initialValue: ... } object.
5
+ * Skips instances that already have an initialValue property.
6
+ */
7
+ import { Tree } from '@nx/devkit';
8
+ export default function update(tree: Tree): Promise<void>;
9
+ //# sourceMappingURL=wrap-tiny-data-store-initial-value.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wrap-tiny-data-store-initial-value.d.ts","sourceRoot":"","sources":["../../../src/migrations/4-10-1/wrap-tiny-data-store-initial-value.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAA6C,MAAM,YAAY,CAAC;AAK7E,wBAA8B,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAmE9D"}
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ /**
3
+ * Migration: Wrap TinyDataStore/TinyStorage constructor arguments in initialValue
4
+ *
5
+ * Transforms constructor calls to wrap the argument in an { initialValue: ... } object.
6
+ * Skips instances that already have an initialValue property.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.default = update;
10
+ const devkit_1 = require("@nx/devkit");
11
+ const ts_morph_1 = require("ts-morph");
12
+ const TARGET_CLASSES = ['TinyDataStore', 'TinyStorage'];
13
+ async function update(tree) {
14
+ devkit_1.logger.info('🔄 Wrapping TinyDataStore/TinyStorage constructor arguments in initialValue...');
15
+ const project = new ts_morph_1.Project({
16
+ manipulationSettings: { quoteKind: ts_morph_1.QuoteKind.Single },
17
+ });
18
+ let updatedCount = 0;
19
+ (0, devkit_1.visitNotIgnoredFiles)(tree, '.', (filePath) => {
20
+ if (!filePath.endsWith('.ts') && !filePath.endsWith('.tsx'))
21
+ return;
22
+ if (!filePath.includes('unisphere/'))
23
+ return;
24
+ const content = tree.read(filePath, 'utf-8');
25
+ if (!content)
26
+ return;
27
+ if (!TARGET_CLASSES.some((cls) => content.includes(cls)))
28
+ return;
29
+ const sourceFile = project.createSourceFile(filePath, content, {
30
+ overwrite: true,
31
+ });
32
+ let hasChanges = false;
33
+ const newExpressions = sourceFile.getDescendantsOfKind(ts_morph_1.SyntaxKind.NewExpression);
34
+ for (const expr of newExpressions) {
35
+ const exprText = expr.getExpression().getText();
36
+ if (!TARGET_CLASSES.includes(exprText))
37
+ continue;
38
+ const args = expr.getArguments();
39
+ if (args.length !== 1)
40
+ continue;
41
+ const arg = args[0];
42
+ // Skip if argument already has an initialValue property
43
+ if (arg.getKind() === ts_morph_1.SyntaxKind.ObjectLiteralExpression) {
44
+ const objLiteral = arg.asKind(ts_morph_1.SyntaxKind.ObjectLiteralExpression);
45
+ if (objLiteral?.getProperty('initialValue'))
46
+ continue;
47
+ }
48
+ const argText = arg.getText();
49
+ arg.replaceWithText(`{\n initialValue: ${argText},\n }`);
50
+ hasChanges = true;
51
+ }
52
+ if (hasChanges) {
53
+ tree.write(filePath, sourceFile.getFullText());
54
+ updatedCount++;
55
+ devkit_1.logger.info(` ✅ Updated ${filePath}`);
56
+ }
57
+ });
58
+ if (updatedCount === 0) {
59
+ devkit_1.logger.info('ℹ️ No TinyDataStore/TinyStorage instances needed transformation');
60
+ }
61
+ else {
62
+ await (0, devkit_1.formatFiles)(tree);
63
+ devkit_1.logger.info(`✅ Wrapped constructor arguments in initialValue for ${updatedCount} file(s)`);
64
+ }
65
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Migration: Migrate Kava analytics types to Application Events bucket types
3
+ *
4
+ * Renames enums/types and adds the required `bucket: AnalyticsBucket.ApplicationEvents`
5
+ * field to all report() calls.
6
+ */
7
+ import { Tree } from '@nx/devkit';
8
+ export default function update(tree: Tree): Promise<void>;
9
+ //# sourceMappingURL=migrate-analytics-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate-analytics-types.d.ts","sourceRoot":"","sources":["../../../src/migrations/4-11-0/migrate-analytics-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAA6C,MAAM,YAAY,CAAC;AAa7E,wBAA8B,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CA2G9D"}
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ /**
3
+ * Migration: Migrate Kava analytics types to Application Events bucket types
4
+ *
5
+ * Renames enums/types and adds the required `bucket: AnalyticsBucket.ApplicationEvents`
6
+ * field to all report() calls.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.default = update;
10
+ const devkit_1 = require("@nx/devkit");
11
+ const ts_morph_1 = require("ts-morph");
12
+ const RENAMES = {
13
+ KavaEventTypes: 'ApplicationEventTypes',
14
+ KavaButtonsTypes: 'ApplicationButtonTypes',
15
+ KavaPageTypes: 'ApplicationPageTypes',
16
+ KavaBaseTypePayload: 'ApplicationEventsBasePayload',
17
+ KavaButtonTypePayload: 'ApplicationButtonPayload',
18
+ KavaPageTypePayload: 'ApplicationPagePayload',
19
+ KavaRequestPayloadByType: 'AnalyticsPayloadByBucket',
20
+ };
21
+ async function update(tree) {
22
+ devkit_1.logger.info('🔄 Migrating Kava analytics types to Application Events bucket types...');
23
+ const runtimesDir = 'unisphere/runtimes';
24
+ if (!tree.exists(runtimesDir)) {
25
+ devkit_1.logger.info('ℹ️ No runtimes directory found');
26
+ return;
27
+ }
28
+ const project = new ts_morph_1.Project({
29
+ manipulationSettings: { quoteKind: ts_morph_1.QuoteKind.Single },
30
+ });
31
+ let updatedCount = 0;
32
+ (0, devkit_1.visitNotIgnoredFiles)(tree, runtimesDir, (filePath) => {
33
+ if (!filePath.endsWith('.ts') && !filePath.endsWith('.tsx'))
34
+ return;
35
+ const content = tree.read(filePath, 'utf-8');
36
+ if (!content)
37
+ return;
38
+ const hasOldTypes = Object.keys(RENAMES).some((old) => content.includes(old));
39
+ if (!hasOldTypes)
40
+ return;
41
+ const sourceFile = project.createSourceFile(filePath, content, {
42
+ overwrite: true,
43
+ });
44
+ let hasChanges = false;
45
+ // Step 1: Add `bucket: AnalyticsBucket.ApplicationEvents` to any object literal
46
+ // containing an `eventType: KavaEventTypes.*` property (covers direct .report() calls
47
+ // and indirect patterns like wrapper functions).
48
+ const objectLiterals = sourceFile.getDescendantsOfKind(ts_morph_1.SyntaxKind.ObjectLiteralExpression);
49
+ for (const objLiteral of objectLiterals) {
50
+ if (objLiteral.getProperty('bucket'))
51
+ continue;
52
+ const eventTypeProp = objLiteral.getProperty('eventType');
53
+ if (!eventTypeProp)
54
+ continue;
55
+ const eventTypeText = eventTypeProp.getText();
56
+ if (!eventTypeText.includes('KavaEventTypes.') &&
57
+ !eventTypeText.includes('ApplicationEventTypes.'))
58
+ continue;
59
+ objLiteral.insertPropertyAssignment(0, {
60
+ name: 'bucket',
61
+ initializer: 'AnalyticsBucket.ApplicationEvents',
62
+ });
63
+ hasChanges = true;
64
+ }
65
+ // Step 2: Rename all old type/enum references
66
+ let updatedText = sourceFile.getFullText();
67
+ for (const [oldName, newName] of Object.entries(RENAMES)) {
68
+ const regex = new RegExp(`\\b${oldName}\\b`, 'g');
69
+ if (regex.test(updatedText)) {
70
+ updatedText = updatedText.replace(regex, newName);
71
+ hasChanges = true;
72
+ }
73
+ }
74
+ // Step 3: Add AnalyticsBucket to imports from @unisphere/runtime
75
+ if (hasChanges) {
76
+ if (updatedText.includes('AnalyticsBucket') &&
77
+ !updatedText.match(/import\s*\{[^}]*AnalyticsBucket[^}]*\}\s*from\s*['"]@unisphere\/runtime['"]/)) {
78
+ updatedText = updatedText.replace(/(import\s*\{)([^}]*)(}\s*from\s*['"]@unisphere\/runtime['"])/, (_match, start, imports, end) => {
79
+ const importList = imports
80
+ .split(',')
81
+ .map((s) => s.trim())
82
+ .filter(Boolean);
83
+ if (!importList.includes('AnalyticsBucket')) {
84
+ importList.push('AnalyticsBucket');
85
+ importList.sort();
86
+ }
87
+ return `${start}\n ${importList.join(',\n ')},\n${end}`;
88
+ });
89
+ }
90
+ tree.write(filePath, updatedText);
91
+ updatedCount++;
92
+ devkit_1.logger.info(` ✅ Updated ${filePath}`);
93
+ }
94
+ });
95
+ if (updatedCount === 0) {
96
+ devkit_1.logger.info('ℹ️ No files needed analytics type migration');
97
+ }
98
+ else {
99
+ await (0, devkit_1.formatFiles)(tree);
100
+ devkit_1.logger.info(`✅ Migrated analytics types in ${updatedCount} file(s)`);
101
+ }
102
+ }
package/migrations.json CHANGED
@@ -458,6 +458,38 @@
458
458
  "cli": {
459
459
  "postUpdateMessage": "✅ Security Audit step restored in cicd.yml"
460
460
  }
461
+ },
462
+ "4-10-1-wrap-tiny-data-store-initial-value": {
463
+ "version": "4.10.1",
464
+ "description": "Wraps TinyDataStore/TinyStorage constructor arguments in initialValue property",
465
+ "factory": "./dist/migrations/4-10-1/wrap-tiny-data-store-initial-value.js",
466
+ "cli": {
467
+ "postUpdateMessage": "✅ TinyDataStore/TinyStorage constructor arguments wrapped in initialValue"
468
+ }
469
+ },
470
+ "4-10-1-add-get-workspace-to-get-service": {
471
+ "version": "4.10.1",
472
+ "description": "Adds getWorkspace() call before getService in runtime files",
473
+ "factory": "./dist/migrations/4-10-1/add-get-workspace-to-get-service.js",
474
+ "cli": {
475
+ "postUpdateMessage": "✅ Runtime files updated: this._options.getService → this._options.getWorkspace().getService"
476
+ }
477
+ },
478
+ "4-10-1-update-unisphere-visual-target": {
479
+ "version": "4.10.1",
480
+ "description": "Updates UnisphereVisualTarget usage: renames target→type, converts string targets to objects",
481
+ "factory": "./dist/migrations/4-10-1/update-unisphere-visual-target.js",
482
+ "cli": {
483
+ "postUpdateMessage": "✅ UnisphereVisualTarget usage updated (target→type, string→object)"
484
+ }
485
+ },
486
+ "4-11-0-migrate-analytics-types": {
487
+ "version": "4.11.0",
488
+ "description": "Migrates Kava analytics types to Application Events bucket types (KavaEventTypes→ApplicationEventTypes, KavaButtonsTypes→ApplicationButtonTypes, adds bucket field)",
489
+ "factory": "./dist/migrations/4-11-0/migrate-analytics-types.js",
490
+ "cli": {
491
+ "postUpdateMessage": "✅ Analytics types migrated to Application Events bucket pattern"
492
+ }
461
493
  }
462
494
  },
463
495
  "packageJsonUpdates": {
@@ -791,6 +823,29 @@
791
823
  "alwaysAddToPackageJson": false
792
824
  }
793
825
  }
826
+ },
827
+ "4.10.1": {
828
+ "version": "4.10.1",
829
+ "cli": "nx",
830
+ "postUpdateMessage": "🎉 Migration to @unisphere/nx 4.10.1 completed successfully!",
831
+ "packages": {
832
+ "@unisphere/core": {
833
+ "version": "^1.97.1",
834
+ "alwaysAddToPackageJson": false
835
+ },
836
+ "@unisphere/runtime": {
837
+ "version": "^1.97.0",
838
+ "alwaysAddToPackageJson": false
839
+ },
840
+ "@unisphere/runtime-js": {
841
+ "version": "^1.93.0",
842
+ "alwaysAddToPackageJson": false
843
+ },
844
+ "@unisphere/runtime-react": {
845
+ "version": "^1.87.0",
846
+ "alwaysAddToPackageJson": false
847
+ }
848
+ }
794
849
  }
795
850
  }
796
851
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unisphere/nx",
3
- "version": "4.9.0",
3
+ "version": "4.11.0",
4
4
  "private": false,
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",