ng-zorro-antd
Version:
An enterprise-class UI components based on Ant Design and Angular
283 lines • 12.1 kB
JavaScript
"use strict";
/**
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.DateAdapterMigration = void 0;
const schematics_1 = require("@angular/cdk/schematics");
const ng_ast_utils_1 = require("@schematics/angular/utility/ng-ast-utils");
const app_config_1 = require("@schematics/angular/utility/standalone/app_config");
const util_1 = require("@schematics/angular/utility/standalone/util");
const ts = __importStar(require("typescript"));
/**
* Migration that adds `provideNzDateFnsAdapter()` to root providers.
*
* Starting from v22, date components require an explicit `NzDateAdapter` provider.
* This migration makes the previous default (date-fns) explicit in projects where it can do so safely.
* Projects that already configure a date adapter are left unchanged.
*/
class DateAdapterMigration extends schematics_1.DevkitMigration {
constructor() {
super(...arguments);
/** Provider APIs that indicate the project already has an explicit date adapter choice. */
this.dateAdapterProviderPattern = /^(provideNzDateAdapter|provideNzDateFnsAdapter|provideNzNativeDateAdapter)$/;
/** Always enabled; the migration is scoped by project target in postAnalysis. */
this.enabled = true;
}
postAnalysis() {
if (this.context.isTestTarget) {
return;
}
const mainFile = (0, schematics_1.getProjectMainFile)(this.context.project);
if (this.addProviderToStandaloneApp(mainFile)) {
return;
}
this.addProviderToNgModuleApp(mainFile);
}
addProviderToStandaloneApp(mainFile) {
try {
const bootstrapCall = (0, util_1.findBootstrapApplicationCall)(this.context.tree, mainFile);
const appConfig = (0, app_config_1.findAppConfig)(bootstrapCall, this.context.tree, mainFile);
if (appConfig) {
const appConfigSource = this.getSourceFile(appConfig.filePath);
if (this.hasDateAdapterProvider(appConfigSource)) {
return true;
}
const providersLiteral = (0, util_1.findProvidersLiteral)(appConfig.node);
const filePath = this.fileSystem.resolve(appConfig.filePath);
this.insertProviderImport(appConfigSource, filePath);
if (providersLiteral) {
this.addProviderToArray(providersLiteral, filePath);
}
else {
this.addProvidersProperty(appConfig.node, filePath);
}
return true;
}
const mainSource = this.getSourceFile(mainFile);
if (this.hasDateAdapterProvider(mainSource)) {
return true;
}
const filePath = this.fileSystem.resolve(mainFile);
this.insertProviderImport(mainSource, filePath);
this.addProviderToBootstrapCall(bootstrapCall, filePath);
return true;
}
catch (_a) {
return false;
}
}
addProviderToBootstrapCall(bootstrapCall, filePath) {
const providerConfig = `{\n providers: [provideNzDateFnsAdapter()]\n}`;
if (bootstrapCall.arguments.length === 1) {
this.fileSystem.edit(filePath).insertRight(bootstrapCall.arguments[0].getEnd(), `, ${providerConfig}`);
return;
}
const secondArgument = bootstrapCall.arguments[1];
if ((0, util_1.isMergeAppConfigCall)(secondArgument)) {
const separator = secondArgument.arguments.length === 0 ? '' : ', ';
this.fileSystem.edit(filePath).insertRight(secondArgument.getEnd() - 1, `${separator}${providerConfig}`);
return;
}
this.failures.push({
filePath,
message: 'Could not statically analyze bootstrapApplication config to add provideNzDateFnsAdapter().'
});
}
addProviderToNgModuleApp(mainFile) {
let appModulePath;
try {
appModulePath = (0, ng_ast_utils_1.getAppModulePath)(this.context.tree, mainFile);
}
catch (_a) {
this.createFailureAtMainFile(mainFile, 'Could not find root providers to add provideNzDateFnsAdapter(). Please add it manually.');
return;
}
const sourceFile = this.getSourceFile(appModulePath);
if (this.hasDateAdapterProvider(sourceFile)) {
return;
}
const ngModuleMetadata = this.findNgModuleMetadata(sourceFile);
if (!ngModuleMetadata) {
this.createFailureAtMainFile(appModulePath, 'Could not find NgModule metadata to add provideNzDateFnsAdapter(). Please add it manually.');
return;
}
const filePath = this.fileSystem.resolve(appModulePath);
const providersLiteral = this.findProvidersProperty(ngModuleMetadata);
this.insertProviderImport(sourceFile, filePath);
if (providersLiteral) {
this.addProviderToArray(providersLiteral, filePath);
}
else {
this.addProvidersProperty(ngModuleMetadata, filePath);
}
}
hasDateAdapterProvider(sourceFile) {
let hasProvider = false;
const visit = (node) => {
if (hasProvider) {
return;
}
if (ts.isCallExpression(node)) {
const expression = node.expression;
if (ts.isIdentifier(expression) && this.dateAdapterProviderPattern.test(expression.text)) {
hasProvider = true;
return;
}
}
if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name) && node.name.text === 'provide') {
const initializer = node.initializer;
if (ts.isIdentifier(initializer) && initializer.text === 'NzDateAdapter') {
hasProvider = true;
return;
}
}
ts.forEachChild(node, visit);
};
visit(sourceFile);
return hasProvider;
}
findNgModuleMetadata(sourceFile) {
let metadata = null;
const visit = (node) => {
if (metadata) {
return;
}
if (ts.isDecorator(node) && ts.isCallExpression(node.expression)) {
const expression = node.expression.expression;
const args = node.expression.arguments;
if (ts.isIdentifier(expression) &&
expression.text === 'NgModule' &&
args.length > 0 &&
ts.isObjectLiteralExpression(args[0])) {
metadata = args[0];
return;
}
}
ts.forEachChild(node, visit);
};
visit(sourceFile);
return metadata;
}
findProvidersProperty(metadata) {
for (const property of metadata.properties) {
if (ts.isPropertyAssignment(property) &&
ts.isIdentifier(property.name) &&
property.name.text === 'providers' &&
ts.isArrayLiteralExpression(property.initializer)) {
return property.initializer;
}
}
return null;
}
addProvidersProperty(metadata, filePath) {
const providerProperty = 'providers: [provideNzDateFnsAdapter()]';
const properties = metadata.properties;
if (properties.length === 0) {
this.fileSystem.edit(filePath).insertRight(metadata.getStart() + 1, providerProperty);
return;
}
const lastProperty = properties[properties.length - 1];
this.fileSystem.edit(filePath).insertRight(lastProperty.getEnd(), `, ${providerProperty}`);
}
/** Add provider to array */
addProviderToArray(arrayNode, filePath) {
const elements = arrayNode.elements;
for (const element of elements) {
if (ts.isCallExpression(element)) {
const expr = element.expression;
if (ts.isIdentifier(expr) && expr.getText() === 'provideNzDateFnsAdapter') {
return;
}
}
}
const providerCall = 'provideNzDateFnsAdapter()';
if (elements.length === 0) {
this.fileSystem.edit(filePath).insertRight(arrayNode.getStart() + 1, providerCall);
}
else {
const lastElement = elements[elements.length - 1];
this.fileSystem.edit(filePath).insertRight(lastElement.getEnd(), `, ${providerCall}`);
}
}
insertProviderImport(sourceFile, filePath) {
if (this.hasNamedImport(sourceFile, 'provideNzDateFnsAdapter', 'ng-zorro-antd/core/time')) {
return;
}
let lastImport = null;
ts.forEachChild(sourceFile, node => {
if (ts.isImportDeclaration(node)) {
lastImport = node;
}
});
const importToAdd = `\nimport { provideNzDateFnsAdapter } from 'ng-zorro-antd/core/time';\n`;
if (lastImport) {
this.fileSystem.edit(filePath).insertRight(lastImport.getEnd(), importToAdd);
}
else {
this.fileSystem.edit(filePath).insertRight(0, `${importToAdd}\n`);
}
}
hasNamedImport(sourceFile, symbolName, moduleName) {
var _a;
for (const statement of sourceFile.statements) {
if (!ts.isImportDeclaration(statement) ||
!ts.isStringLiteralLike(statement.moduleSpecifier) ||
statement.moduleSpecifier.text !== moduleName ||
!((_a = statement.importClause) === null || _a === void 0 ? void 0 : _a.namedBindings) ||
!ts.isNamedImports(statement.importClause.namedBindings)) {
continue;
}
if (statement.importClause.namedBindings.elements.some(element => element.name.text === symbolName)) {
return true;
}
}
return false;
}
getSourceFile(filePath) {
const sourceText = this.context.tree.readText(filePath);
return ts.createSourceFile(filePath, sourceText, ts.ScriptTarget.Latest, true);
}
createFailureAtMainFile(filePath, message) {
this.failures.push({
filePath: this.fileSystem.resolve(filePath),
message
});
}
}
exports.DateAdapterMigration = DateAdapterMigration;
//# sourceMappingURL=date-adapter.js.map