From a3ee8d08b250d23a8881b2bd00bffc166db4d1f0 Mon Sep 17 00:00:00 2001 From: Nikita Barsukov Date: Mon, 5 Feb 2024 18:36:25 +0300 Subject: [PATCH] chore(cdk): schematics for legacy mask utils (#6688) --- projects/cdk/schematics/ng-update/v4/index.ts | 8 +- .../v4/steps/constants/migration-warnings.ts | 106 +++++++++++++++--- .../schematics/ng-update/v4/steps/index.ts | 1 + .../ng-update/v4/steps/migrate-legacy-mask.ts | 89 +++++++++++++++ .../schematic-migrate-legacy-mask.spec.ts | 94 ++++++++++++++++ 5 files changed, 283 insertions(+), 15 deletions(-) create mode 100644 projects/cdk/schematics/ng-update/v4/steps/migrate-legacy-mask.ts create mode 100644 projects/cdk/schematics/ng-update/v4/tests/schematic-migrate-legacy-mask.spec.ts diff --git a/projects/cdk/schematics/ng-update/v4/index.ts b/projects/cdk/schematics/ng-update/v4/index.ts index 8e7cc3e164ce..2e2b5950c018 100644 --- a/projects/cdk/schematics/ng-update/v4/index.ts +++ b/projects/cdk/schematics/ng-update/v4/index.ts @@ -10,7 +10,12 @@ import {getExecutionTime} from '../../utils/get-execution-time'; import {projectRoot} from '../../utils/project-root'; import {replaceIdentifiers} from '../steps/replace-identifier'; import {showWarnings} from '../steps/show-warnings'; -import {migrateTemplates, restoreTuiMapper, restoreTuiMatcher} from './steps'; +import { + migrateLegacyMask, + migrateTemplates, + restoreTuiMapper, + restoreTuiMatcher, +} from './steps'; import {MIGRATION_WARNINGS} from './steps/constants'; import {IDENTIFIERS_TO_REPLACE} from './steps/constants/identifiers-to-replace'; @@ -24,6 +29,7 @@ function main(options: TuiSchema): Rule { restoreTuiMapper(options); restoreTuiMatcher(options); + migrateLegacyMask(options); migrateTemplates(fileSystem, options); showWarnings(context, MIGRATION_WARNINGS); diff --git a/projects/cdk/schematics/ng-update/v4/steps/constants/migration-warnings.ts b/projects/cdk/schematics/ng-update/v4/steps/constants/migration-warnings.ts index 73ed7c629e7e..681d39ff9d51 100644 --- a/projects/cdk/schematics/ng-update/v4/steps/constants/migration-warnings.ts +++ b/projects/cdk/schematics/ng-update/v4/steps/constants/migration-warnings.ts @@ -1,58 +1,136 @@ import {MigrationWarning} from '../../../interfaces'; export const MIGRATION_WARNINGS: MigrationWarning[] = [ + { + name: 'TuiNumberMaskOptions', + moduleSpecifier: '@taiga-ui/core', + message: 'Use Number mask from Maskito instead https://maskito.dev/kit/number', + }, + { + name: 'tuiCreateAutoCorrectedNumberPipe', + moduleSpecifier: '@taiga-ui/core', + message: 'Use Number mask from Maskito instead https://maskito.dev/kit/number', + }, + { + name: 'tuiCreateNumberMask', + moduleSpecifier: '@taiga-ui/core', + message: 'Use Number mask from Maskito instead https://maskito.dev/kit/number', + }, + { + name: 'tuiEnableAutoCorrectDecimalSymbol', + moduleSpecifier: '@taiga-ui/core', + message: 'Use Number mask from Maskito instead https://maskito.dev/kit/number', + }, + { + name: 'TuiTextMaskConfig', + moduleSpecifier: '@taiga-ui/core', + message: 'Use Maskito instead https://maskito.dev', + }, + { + name: 'TuiTextMaskCorrectionHandler', + moduleSpecifier: '@taiga-ui/core', + message: 'Use Maskito instead https://maskito.dev', + }, + { + name: 'TuiTextMaskListHandler', + moduleSpecifier: '@taiga-ui/core', + message: 'Use Maskito instead https://maskito.dev', + }, + { + name: 'TuiTextMaskList', + moduleSpecifier: '@taiga-ui/core', + message: 'Use Maskito instead https://maskito.dev', + }, + { + name: 'TuiTextMaskOptions', + moduleSpecifier: '@taiga-ui/core', + message: 'Use Maskito instead https://maskito.dev', + }, + { + name: 'TuiTextMaskPipeHandler', + moduleSpecifier: '@taiga-ui/core', + message: 'Use Maskito instead https://maskito.dev', + }, + { + name: 'TuiTextMaskPipeResult', + moduleSpecifier: '@taiga-ui/core', + message: 'Use Maskito instead https://maskito.dev', + }, + { + name: 'tuiCreateCorrectionMask', + moduleSpecifier: '@taiga-ui/core', + message: + 'Use processors from Maskito instead https://maskito.dev/core-concepts/processors', + }, { name: 'tuiCreateTimeMask', moduleSpecifier: '@taiga-ui/kit', - message: - 'tuiCreateTimeMask has been removed. Use Time mask from Maskito instead https://maskito.dev/kit/time', + message: 'Use Time mask from Maskito instead https://maskito.dev/kit/time', }, { name: 'tuiCreateDateRangeMask', moduleSpecifier: '@taiga-ui/kit', message: - 'tuiCreateDateRangeMask has been removed. Use DateRange mask from Maskito instead https://maskito.dev/kit/date-range', + 'Use DateRange mask from Maskito instead https://maskito.dev/kit/date-range', }, { name: 'tuiCreateDateMask', moduleSpecifier: '@taiga-ui/kit', - message: - 'tuiCreateDateMask has been removed. Use Date mask from Maskito instead https://maskito.dev/kit/date', + message: 'Use Date mask from Maskito instead https://maskito.dev/kit/date', }, { name: 'tuiCreateAutoCorrectedTimePipe', moduleSpecifier: '@taiga-ui/kit', - message: - 'tuiCreateAutoCorrectedTimePipe has been removed. Use Time mask from Maskito instead https://maskito.dev/kit/time', + message: 'Use Time mask from Maskito instead https://maskito.dev/kit/time', }, { name: 'tuiCreateAutoCorrectedDateTimePipe', moduleSpecifier: '@taiga-ui/kit', message: - 'tuiCreateAutoCorrectedDateTimePipe has been removed. Use DateTime mask from Maskito instead https://maskito.dev/kit/date-time', + 'Use DateTime mask from Maskito instead https://maskito.dev/kit/date-time', }, { name: 'tuiCreateAutoCorrectedDateRangePipe', moduleSpecifier: '@taiga-ui/kit', message: - 'tuiCreateAutoCorrectedDateRangePipe has been removed. Use DateRange mask from Maskito instead https://maskito.dev/kit/date-range', + 'Use DateRange mask from Maskito instead https://maskito.dev/kit/date-range', }, { name: 'tuiCreateAutoCorrectedDatePipe', moduleSpecifier: '@taiga-ui/kit', - message: - 'tuiCreateAutoCorrectedDatePipe has been removed. Use Date mask from Maskito instead https://maskito.dev/kit/date', + message: 'Use Date mask from Maskito instead https://maskito.dev/kit/date', }, { name: 'TuiAutoCorrectedDatePipeConfigs', moduleSpecifier: '@taiga-ui/kit', - message: - 'TuiAutoCorrectedDatePipeConfigs has been removed. Use Date mask from Maskito instead https://maskito.dev/kit/date', + message: 'Use Date mask from Maskito instead https://maskito.dev/kit/date', }, { name: 'tuiNormalizeDateValue', moduleSpecifier: '@taiga-ui/kit', + message: 'Use Date mask from Maskito instead https://maskito.dev/kit/date', + }, + { + name: 'EMPTY_MASK', + moduleSpecifier: '@taiga-ui/kit', + message: + 'Use Maskito instead https://maskito.dev (use MASKITO_DEFAULT_OPTIONS or just pass null to [maskito]-directive)', + }, + { + name: 'TextMaskModule', + moduleSpecifier: '@taiga-ui/kit', + message: 'Use Maskito instead https://maskito.dev', + }, + + { + name: 'cardHolderMask', + moduleSpecifier: '@taiga-ui/addon-commerce', + message: 'Use TUI_CARD_HOLDER_MASK with Maskito instead https://maskito.dev', + }, + { + name: 'tuiCreateAutoCorrectedExpirePipe', + moduleSpecifier: '@taiga-ui/addon-commerce', message: - 'tuiNormalizeDateValue has been removed. Use Date mask from Maskito instead https://maskito.dev/kit/date', + 'Use Date mask (with [mode]="mm/yyyy") from Maskito instead https://maskito.dev/kit/date/API?mode=mm%2Fyyyy', }, ]; diff --git a/projects/cdk/schematics/ng-update/v4/steps/index.ts b/projects/cdk/schematics/ng-update/v4/steps/index.ts index 06b13f925591..610877274f9d 100644 --- a/projects/cdk/schematics/ng-update/v4/steps/index.ts +++ b/projects/cdk/schematics/ng-update/v4/steps/index.ts @@ -1,3 +1,4 @@ +export * from './migrate-legacy-mask'; export * from './migrate-templates'; export * from './restore-tui-mapper'; export * from './restore-tui-matcher'; diff --git a/projects/cdk/schematics/ng-update/v4/steps/migrate-legacy-mask.ts b/projects/cdk/schematics/ng-update/v4/steps/migrate-legacy-mask.ts new file mode 100644 index 000000000000..448ecce6a8d1 --- /dev/null +++ b/projects/cdk/schematics/ng-update/v4/steps/migrate-legacy-mask.ts @@ -0,0 +1,89 @@ +import { + addUniqueImport, + FINISH_SYMBOL, + getNamedImportReferences, + infoLog, + removeImport, + REPLACE_SYMBOL, + SMALL_TAB_SYMBOL, + titleLog, +} from '@taiga-ui/cdk/schematics'; +import {Node} from 'ng-morph'; + +import {TuiSchema} from '../../../ng-add/schema'; + +export function migrateLegacyMask(options: TuiSchema): void { + !options['skip-logs'] && + infoLog(`${SMALL_TAB_SYMBOL}${REPLACE_SYMBOL} migrating legacy mask utils...`); + + migrateTuiMaskedMoneyValueIsEmpty(options); + migrateTuiMaskedNumberStringToNumber(options); + + !options['skip-logs'] && titleLog(`${FINISH_SYMBOL} successfully migrated \n`); +} + +function migrateTuiMaskedMoneyValueIsEmpty(options: TuiSchema): void { + !options['skip-logs'] && + infoLog(`${SMALL_TAB_SYMBOL}${REPLACE_SYMBOL} tuiMaskedMoneyValueIsEmpty`); + + const references = getNamedImportReferences( + 'tuiMaskedMoneyValueIsEmpty', + '@taiga-ui/core', + ); + + references.forEach(ref => { + if (ref.wasForgotten()) { + return; + } + + const parent = ref.getParent(); + + if (Node.isImportSpecifier(parent)) { + removeImport(parent); + addUniqueImport( + parent.getSourceFile().getFilePath(), + 'maskitoParseNumber', + '@maskito/kit', + ); + } else if (Node.isCallExpression(parent)) { + const [value] = parent.getArguments(); + + parent.replaceWithText( + `Number.isNaN(maskitoParseNumber(${value.getText()}, ','))`, + ); + } + }); +} + +function migrateTuiMaskedNumberStringToNumber(options: TuiSchema): void { + !options['skip-logs'] && + infoLog(`${SMALL_TAB_SYMBOL}${REPLACE_SYMBOL} tuiMaskedNumberStringToNumber`); + + const references = getNamedImportReferences( + 'tuiMaskedNumberStringToNumber', + '@taiga-ui/core', + ); + + references.forEach(ref => { + if (ref.wasForgotten()) { + return; + } + + const parent = ref.getParent(); + + if (Node.isImportSpecifier(parent)) { + removeImport(parent); + addUniqueImport( + parent.getSourceFile().getFilePath(), + 'maskitoParseNumber', + '@maskito/kit', + ); + } else if (Node.isCallExpression(parent)) { + const [value, decimalSeparator] = parent.getArguments(); + + parent.replaceWithText( + `maskitoParseNumber(${value.getText()}, ${decimalSeparator.getText()})`, + ); + } + }); +} diff --git a/projects/cdk/schematics/ng-update/v4/tests/schematic-migrate-legacy-mask.spec.ts b/projects/cdk/schematics/ng-update/v4/tests/schematic-migrate-legacy-mask.spec.ts new file mode 100644 index 000000000000..7219c5e2502c --- /dev/null +++ b/projects/cdk/schematics/ng-update/v4/tests/schematic-migrate-legacy-mask.spec.ts @@ -0,0 +1,94 @@ +import {HostTree} from '@angular-devkit/schematics'; +import {SchematicTestRunner, UnitTestTree} from '@angular-devkit/schematics/testing'; +import {TuiSchema} from '@taiga-ui/cdk/schematics/ng-add/schema'; +import { + createProject, + createSourceFile, + resetActiveProject, + saveActiveProject, + setActiveProject, +} from 'ng-morph'; +import {join} from 'path'; + +const collectionPath = join(__dirname, '../../../migration.json'); + +const BEFORE = ` +import { + AModule, + tuiMaskedMoneyValueIsEmpty, + BModule, + tuiMaskedNumberStringToNumber, + CModule +} from '@taiga-ui/core'; + +@Component({ + standalone: true + template: '', + imports: [AModule, BModule, CModule], +}) +export class TestComponent { + onClick(): void { + const isEmpty = tuiMaskedMoneyValueIsEmpty('123,45'); + const parsedValue = tuiMaskedNumberStringToNumber('123,45', ',', ' '); + const parsedValueAgain = tuiMaskedNumberStringToNumber( + this.value, + this.decimalSeparator, + CHAR_NO_BREAK_SPACE + ); + console.info(isEmpty, parsedValue, parsedValueAgain); + } +}`.trim(); + +const AFTER = ` +import { maskitoParseNumber } from "@maskito/kit"; +import { + AModule, + BModule, + CModule +} from '@taiga-ui/core'; + +@Component({ + standalone: true + template: '', + imports: [AModule, BModule, CModule], +}) +export class TestComponent { + onClick(): void { + const isEmpty = Number.isNaN(maskitoParseNumber('123,45', ',')); + const parsedValue = maskitoParseNumber('123,45', ','); + const parsedValueAgain = maskitoParseNumber(this.value, this.decimalSeparator); + console.info(isEmpty, parsedValue, parsedValueAgain); + } +}`.trim(); + +describe('ng-update', () => { + let host: UnitTestTree; + let runner: SchematicTestRunner; + + beforeEach(() => { + host = new UnitTestTree(new HostTree()); + runner = new SchematicTestRunner('schematics', collectionPath); + + setActiveProject(createProject(host)); + + createSourceFile('test/app/test.component.ts', BEFORE); + + saveActiveProject(); + }); + + it('migration works', async () => { + const tree = await runner + .runSchematicAsync( + 'updateToV4', + {'skip-logs': process.env['TUI_CI'] === 'true'} as Partial, + host, + ) + .toPromise(); + + const modifiedFile = tree.readContent('test/app/test.component.ts'); + + expect(modifiedFile).toEqual(AFTER); + }); + + afterEach(() => resetActiveProject()); +});