@openrewrite/recipes-date-libraries 0.0.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/date-fns-to-temporal.d.ts +8 -0
- package/dist/date-fns-to-temporal.d.ts.map +1 -0
- package/dist/date-fns-to-temporal.js +214 -0
- package/dist/date-fns-to-temporal.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/moment-to-temporal.d.ts +8 -0
- package/dist/moment-to-temporal.d.ts.map +1 -0
- package/dist/moment-to-temporal.js +194 -0
- package/dist/moment-to-temporal.js.map +1 -0
- package/package.json +35 -0
- package/src/date-fns-to-temporal.ts +225 -0
- package/src/index.ts +23 -0
- package/src/moment-to-temporal.ts +217 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ExecutionContext, Recipe, TreeVisitor } from "@openrewrite/rewrite";
|
|
2
|
+
export declare class DateFnsToTemporal extends Recipe {
|
|
3
|
+
name: string;
|
|
4
|
+
displayName: string;
|
|
5
|
+
description: string;
|
|
6
|
+
editor(): Promise<TreeVisitor<any, ExecutionContext>>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=date-fns-to-temporal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"date-fns-to-temporal.d.ts","sourceRoot":"","sources":["../src/date-fns-to-temporal.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAC,gBAAgB,EAAE,MAAM,EAAE,WAAW,EAAC,MAAM,sBAAsB,CAAC;AAuB3E,qBAAa,iBAAkB,SAAQ,MAAM;IACzC,IAAI,SAAsE;IAC1E,WAAW,SAAsC;IACjD,WAAW,SAAwF;IAE7F,MAAM,IAAI,OAAO,CAAC,WAAW,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;CAG9D"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.DateFnsToTemporal = void 0;
|
|
13
|
+
const rewrite_1 = require("@openrewrite/rewrite");
|
|
14
|
+
const javascript_1 = require("@openrewrite/rewrite/javascript");
|
|
15
|
+
const java_1 = require("@openrewrite/rewrite/java");
|
|
16
|
+
const DATE_FNS_FUNCTIONS = new Set([
|
|
17
|
+
'addDays', 'addMonths', 'addYears',
|
|
18
|
+
'subDays', 'subMonths', 'subYears',
|
|
19
|
+
'isAfter', 'isBefore', 'isEqual',
|
|
20
|
+
'differenceInDays', 'differenceInHours', 'differenceInMinutes',
|
|
21
|
+
'startOfDay', 'startOfMonth', 'startOfYear',
|
|
22
|
+
'endOfDay', 'endOfMonth', 'endOfYear',
|
|
23
|
+
]);
|
|
24
|
+
class DateFnsToTemporal extends rewrite_1.Recipe {
|
|
25
|
+
constructor() {
|
|
26
|
+
super(...arguments);
|
|
27
|
+
this.name = "org.openrewrite.javascript.migrate.date-fns.date-fns-to-temporal";
|
|
28
|
+
this.displayName = "Migrate date-fns to Temporal API";
|
|
29
|
+
this.description = "Replaces common date-fns function calls with equivalent native Temporal API usage.";
|
|
30
|
+
}
|
|
31
|
+
editor() {
|
|
32
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
33
|
+
return new DateFnsToTemporalVisitor();
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.DateFnsToTemporal = DateFnsToTemporal;
|
|
38
|
+
class DateFnsToTemporalVisitor extends javascript_1.JavaScriptVisitor {
|
|
39
|
+
constructor() {
|
|
40
|
+
super(...arguments);
|
|
41
|
+
this.importedDateFnsFunctions = new Set();
|
|
42
|
+
this.aliasToOriginal = new Map();
|
|
43
|
+
this._ruleCache = new Map();
|
|
44
|
+
}
|
|
45
|
+
visitJsCompilationUnit(cu, ctx) {
|
|
46
|
+
const _super = Object.create(null, {
|
|
47
|
+
visitJsCompilationUnit: { get: () => super.visitJsCompilationUnit }
|
|
48
|
+
});
|
|
49
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
+
var _a, _b;
|
|
51
|
+
this.importedDateFnsFunctions = new Set();
|
|
52
|
+
this.aliasToOriginal = new Map();
|
|
53
|
+
for (const stmt of cu.statements) {
|
|
54
|
+
const s = (_a = stmt.element) !== null && _a !== void 0 ? _a : stmt;
|
|
55
|
+
if (s.kind === javascript_1.JS.Kind.Import) {
|
|
56
|
+
this.collectDateFnsImports(s);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (this.importedDateFnsFunctions.size === 0) {
|
|
60
|
+
return cu;
|
|
61
|
+
}
|
|
62
|
+
const result = yield _super.visitJsCompilationUnit.call(this, cu, ctx);
|
|
63
|
+
for (const fn of this.importedDateFnsFunctions) {
|
|
64
|
+
const originalName = (_b = this.aliasToOriginal.get(fn)) !== null && _b !== void 0 ? _b : fn;
|
|
65
|
+
(0, javascript_1.maybeRemoveImport)(this, 'date-fns', originalName);
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
collectDateFnsImports(imp) {
|
|
71
|
+
const moduleSpecifier = imp.moduleSpecifier;
|
|
72
|
+
if (!moduleSpecifier)
|
|
73
|
+
return;
|
|
74
|
+
const literal = moduleSpecifier.element;
|
|
75
|
+
if (literal.kind !== java_1.J.Kind.Literal)
|
|
76
|
+
return;
|
|
77
|
+
if (literal.value !== 'date-fns')
|
|
78
|
+
return;
|
|
79
|
+
const importClause = imp.importClause;
|
|
80
|
+
if (!(importClause === null || importClause === void 0 ? void 0 : importClause.namedBindings))
|
|
81
|
+
return;
|
|
82
|
+
if (importClause.namedBindings.kind !== javascript_1.JS.Kind.NamedImports)
|
|
83
|
+
return;
|
|
84
|
+
const namedImports = importClause.namedBindings;
|
|
85
|
+
for (const elem of namedImports.elements.elements) {
|
|
86
|
+
const specifier = elem.element;
|
|
87
|
+
const specifierNode = specifier.specifier;
|
|
88
|
+
if ((0, java_1.isIdentifier)(specifierNode) && DATE_FNS_FUNCTIONS.has(specifierNode.simpleName)) {
|
|
89
|
+
this.importedDateFnsFunctions.add(specifierNode.simpleName);
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (specifierNode.kind === javascript_1.JS.Kind.Alias) {
|
|
93
|
+
const alias = specifierNode;
|
|
94
|
+
const imported = alias.propertyName.element;
|
|
95
|
+
const local = alias.alias;
|
|
96
|
+
if ((0, java_1.isIdentifier)(imported) && (0, java_1.isIdentifier)(local) && DATE_FNS_FUNCTIONS.has(imported.simpleName)) {
|
|
97
|
+
this.importedDateFnsFunctions.add(local.simpleName);
|
|
98
|
+
this.aliasToOriginal.set(local.simpleName, imported.simpleName);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
visitMethodInvocation(method, ctx) {
|
|
104
|
+
const _super = Object.create(null, {
|
|
105
|
+
visitMethodInvocation: { get: () => super.visitMethodInvocation }
|
|
106
|
+
});
|
|
107
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
108
|
+
var _a, _b;
|
|
109
|
+
method = (yield _super.visitMethodInvocation.call(this, method, ctx));
|
|
110
|
+
if (this.importedDateFnsFunctions.size === 0)
|
|
111
|
+
return method;
|
|
112
|
+
const name = (_a = method.name) === null || _a === void 0 ? void 0 : _a.simpleName;
|
|
113
|
+
if (!name || !this.importedDateFnsFunctions.has(name))
|
|
114
|
+
return method;
|
|
115
|
+
const originalName = (_b = this.aliasToOriginal.get(name)) !== null && _b !== void 0 ? _b : name;
|
|
116
|
+
const rule = this.getRuleForFunction(name, originalName);
|
|
117
|
+
if (!rule)
|
|
118
|
+
return method;
|
|
119
|
+
return (yield rule.tryOn(this.cursor, method)) || method;
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
visitFunctionCall(functionCall, ctx) {
|
|
123
|
+
const _super = Object.create(null, {
|
|
124
|
+
visitFunctionCall: { get: () => super.visitFunctionCall }
|
|
125
|
+
});
|
|
126
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
127
|
+
var _a, _b;
|
|
128
|
+
functionCall = (yield _super.visitFunctionCall.call(this, functionCall, ctx));
|
|
129
|
+
if (this.importedDateFnsFunctions.size === 0)
|
|
130
|
+
return functionCall;
|
|
131
|
+
const fn = (_a = functionCall.function) === null || _a === void 0 ? void 0 : _a.element;
|
|
132
|
+
if (!fn || !(0, java_1.isIdentifier)(fn))
|
|
133
|
+
return functionCall;
|
|
134
|
+
const name = fn.simpleName;
|
|
135
|
+
if (!this.importedDateFnsFunctions.has(name))
|
|
136
|
+
return functionCall;
|
|
137
|
+
const originalName = (_b = this.aliasToOriginal.get(name)) !== null && _b !== void 0 ? _b : name;
|
|
138
|
+
const rule = this.getRuleForFunction(name, originalName);
|
|
139
|
+
if (!rule)
|
|
140
|
+
return functionCall;
|
|
141
|
+
return (yield rule.tryOn(this.cursor, functionCall)) || functionCall;
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
getRuleForFunction(localName, originalName) {
|
|
145
|
+
if (this._ruleCache.has(localName))
|
|
146
|
+
return this._ruleCache.get(localName);
|
|
147
|
+
const rule = this.buildRule(localName, originalName);
|
|
148
|
+
if (rule)
|
|
149
|
+
this._ruleCache.set(localName, rule);
|
|
150
|
+
return rule;
|
|
151
|
+
}
|
|
152
|
+
buildRule(localName, originalName) {
|
|
153
|
+
switch (originalName) {
|
|
154
|
+
case 'addDays': return this.addSubRule(localName, 'days', 'add');
|
|
155
|
+
case 'addMonths': return this.addSubRule(localName, 'months', 'add');
|
|
156
|
+
case 'addYears': return this.addSubRule(localName, 'years', 'add');
|
|
157
|
+
case 'subDays': return this.addSubRule(localName, 'days', 'subtract');
|
|
158
|
+
case 'subMonths': return this.addSubRule(localName, 'months', 'subtract');
|
|
159
|
+
case 'subYears': return this.addSubRule(localName, 'years', 'subtract');
|
|
160
|
+
case 'isAfter': return this.compareRule(localName, '> 0');
|
|
161
|
+
case 'isBefore': return this.compareRule(localName, '< 0');
|
|
162
|
+
case 'isEqual': return this.compareRule(localName, '=== 0');
|
|
163
|
+
case 'differenceInDays': return this.differenceRule(localName, 'day', 'days');
|
|
164
|
+
case 'differenceInHours': return this.differenceRule(localName, 'hour', 'hours');
|
|
165
|
+
case 'differenceInMinutes': return this.differenceRule(localName, 'minute', 'minutes');
|
|
166
|
+
case 'startOfDay': return this.singleArgRule(localName, 'Temporal.PlainDate.from(', ').toPlainDateTime()');
|
|
167
|
+
case 'startOfMonth': return this.singleArgRule(localName, 'Temporal.PlainDate.from(', ').with({day: 1}).toPlainDateTime()');
|
|
168
|
+
case 'startOfYear': return this.singleArgRule(localName, 'Temporal.PlainDate.from(', ').with({month: 1, day: 1}).toPlainDateTime()');
|
|
169
|
+
case 'endOfDay': return this.singleArgRule(localName, 'Temporal.PlainDate.from(', ').toPlainDateTime({hour: 23, minute: 59, second: 59, millisecond: 999})');
|
|
170
|
+
case 'endOfMonth': return this.endOfMonthRule(localName);
|
|
171
|
+
case 'endOfYear': return this.singleArgRule(localName, 'Temporal.PlainDate.from(', ').with({month: 12, day: 31}).toPlainDateTime({hour: 23, minute: 59, second: 59, millisecond: 999})');
|
|
172
|
+
default: return undefined;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
addSubRule(fnName, unit, method) {
|
|
176
|
+
const date = (0, javascript_1.capture)();
|
|
177
|
+
const amount = (0, javascript_1.capture)();
|
|
178
|
+
return (0, javascript_1.rewrite)(() => ({
|
|
179
|
+
before: (0, javascript_1.pattern) `${(0, javascript_1.raw)(fnName)}(${date}, ${amount})`,
|
|
180
|
+
after: (0, javascript_1.template) `Temporal.PlainDate.from(${date}).${(0, javascript_1.raw)(method)}({${(0, javascript_1.raw)(unit)}: ${amount}})`
|
|
181
|
+
}));
|
|
182
|
+
}
|
|
183
|
+
compareRule(fnName, operator) {
|
|
184
|
+
const a = (0, javascript_1.capture)();
|
|
185
|
+
const b = (0, javascript_1.capture)();
|
|
186
|
+
return (0, javascript_1.rewrite)(() => ({
|
|
187
|
+
before: (0, javascript_1.pattern) `${(0, javascript_1.raw)(fnName)}(${a}, ${b})`,
|
|
188
|
+
after: (0, javascript_1.template) `Temporal.PlainDateTime.compare(${a}, ${b}) ${(0, javascript_1.raw)(operator)}`
|
|
189
|
+
}));
|
|
190
|
+
}
|
|
191
|
+
differenceRule(fnName, largestUnit, field) {
|
|
192
|
+
const a = (0, javascript_1.capture)();
|
|
193
|
+
const b = (0, javascript_1.capture)();
|
|
194
|
+
return (0, javascript_1.rewrite)(() => ({
|
|
195
|
+
before: (0, javascript_1.pattern) `${(0, javascript_1.raw)(fnName)}(${a}, ${b})`,
|
|
196
|
+
after: (0, javascript_1.template) `${a}.since(${b}, {largestUnit: "${(0, javascript_1.raw)(largestUnit)}"}).${(0, javascript_1.raw)(field)}`
|
|
197
|
+
}));
|
|
198
|
+
}
|
|
199
|
+
singleArgRule(fnName, prefix, suffix) {
|
|
200
|
+
const date = (0, javascript_1.capture)();
|
|
201
|
+
return (0, javascript_1.rewrite)(() => ({
|
|
202
|
+
before: (0, javascript_1.pattern) `${(0, javascript_1.raw)(fnName)}(${date})`,
|
|
203
|
+
after: (0, javascript_1.template) `${(0, javascript_1.raw)(prefix)}${date}${(0, javascript_1.raw)(suffix)}`
|
|
204
|
+
}));
|
|
205
|
+
}
|
|
206
|
+
endOfMonthRule(fnName = 'endOfMonth') {
|
|
207
|
+
const date = (0, javascript_1.capture)();
|
|
208
|
+
return (0, javascript_1.rewrite)(() => ({
|
|
209
|
+
before: (0, javascript_1.pattern) `${(0, javascript_1.raw)(fnName)}(${date})`,
|
|
210
|
+
after: (0, javascript_1.template) `((d) => d.with({day: d.daysInMonth}).toPlainDateTime({hour: 23, minute: 59, second: 59, millisecond: 999}))(Temporal.PlainDate.from(${date}))`
|
|
211
|
+
}));
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=date-fns-to-temporal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"date-fns-to-temporal.js","sourceRoot":"","sources":["../src/date-fns-to-temporal.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { CategoryDescriptor, RecipeMarketplace } from "@openrewrite/rewrite";
|
|
2
|
+
export declare const Migrate: CategoryDescriptor[];
|
|
3
|
+
export declare const MigrateDateFns: CategoryDescriptor[];
|
|
4
|
+
export declare const MigrateMoment: CategoryDescriptor[];
|
|
5
|
+
export declare function activate(marketplace: RecipeMarketplace): Promise<void>;
|
|
6
|
+
export { DateFnsToTemporal } from "./date-fns-to-temporal";
|
|
7
|
+
export { MomentToTemporal } from "./moment-to-temporal";
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,kBAAkB,EAAE,iBAAiB,EAAC,MAAM,sBAAsB,CAAC;AAI3E,eAAO,MAAM,OAAO,EAAE,kBAAkB,EAA+B,CAAC;AAExE,eAAO,MAAM,cAAc,EAAE,kBAAkB,EAG7C,CAAC;AAEH,eAAO,MAAM,aAAa,EAAE,kBAAkB,EAG5C,CAAC;AAEH,wBAAsB,QAAQ,CAAC,WAAW,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAG5E;AAED,OAAO,EAAC,iBAAiB,EAAC,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAC,gBAAgB,EAAC,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.MomentToTemporal = exports.DateFnsToTemporal = exports.MigrateMoment = exports.MigrateDateFns = exports.Migrate = void 0;
|
|
13
|
+
exports.activate = activate;
|
|
14
|
+
const date_fns_to_temporal_1 = require("./date-fns-to-temporal");
|
|
15
|
+
const moment_to_temporal_1 = require("./moment-to-temporal");
|
|
16
|
+
exports.Migrate = [{ displayName: "Migrate" }];
|
|
17
|
+
exports.MigrateDateFns = [...exports.Migrate, {
|
|
18
|
+
displayName: "date-fns",
|
|
19
|
+
description: "Migrate from date-fns to the native Temporal API."
|
|
20
|
+
}];
|
|
21
|
+
exports.MigrateMoment = [...exports.Migrate, {
|
|
22
|
+
displayName: "Moment.js",
|
|
23
|
+
description: "Migrate from Moment.js to the native Temporal API."
|
|
24
|
+
}];
|
|
25
|
+
function activate(marketplace) {
|
|
26
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
27
|
+
yield marketplace.install(date_fns_to_temporal_1.DateFnsToTemporal, exports.MigrateDateFns);
|
|
28
|
+
yield marketplace.install(moment_to_temporal_1.MomentToTemporal, exports.MigrateMoment);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
var date_fns_to_temporal_2 = require("./date-fns-to-temporal");
|
|
32
|
+
Object.defineProperty(exports, "DateFnsToTemporal", { enumerable: true, get: function () { return date_fns_to_temporal_2.DateFnsToTemporal; } });
|
|
33
|
+
var moment_to_temporal_2 = require("./moment-to-temporal");
|
|
34
|
+
Object.defineProperty(exports, "MomentToTemporal", { enumerable: true, get: function () { return moment_to_temporal_2.MomentToTemporal; } });
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;AAgBA,4BAGC;AAlBD,iEAAyD;AACzD,6DAAsD;AAEzC,QAAA,OAAO,GAAyB,CAAC,EAAC,WAAW,EAAE,SAAS,EAAC,CAAC,CAAC;AAE3D,QAAA,cAAc,GAAyB,CAAC,GAAG,eAAO,EAAE;QAC7D,WAAW,EAAE,UAAU;QACvB,WAAW,EAAE,mDAAmD;KACnE,CAAC,CAAC;AAEU,QAAA,aAAa,GAAyB,CAAC,GAAG,eAAO,EAAE;QAC5D,WAAW,EAAE,WAAW;QACxB,WAAW,EAAE,oDAAoD;KACpE,CAAC,CAAC;AAEH,SAAsB,QAAQ,CAAC,WAA8B;;QACzD,MAAM,WAAW,CAAC,OAAO,CAAC,wCAAiB,EAAE,sBAAc,CAAC,CAAC;QAC7D,MAAM,WAAW,CAAC,OAAO,CAAC,qCAAgB,EAAE,qBAAa,CAAC,CAAC;IAC/D,CAAC;CAAA;AAED,+DAAyD;AAAjD,yHAAA,iBAAiB,OAAA;AACzB,2DAAsD;AAA9C,sHAAA,gBAAgB,OAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ExecutionContext, Recipe, TreeVisitor } from "@openrewrite/rewrite";
|
|
2
|
+
export declare class MomentToTemporal extends Recipe {
|
|
3
|
+
name: string;
|
|
4
|
+
displayName: string;
|
|
5
|
+
description: string;
|
|
6
|
+
editor(): Promise<TreeVisitor<any, ExecutionContext>>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=moment-to-temporal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"moment-to-temporal.d.ts","sourceRoot":"","sources":["../src/moment-to-temporal.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAC,gBAAgB,EAAE,MAAM,EAAE,WAAW,EAAC,MAAM,sBAAsB,CAAC;AAgC3E,qBAAa,gBAAiB,SAAQ,MAAM;IACxC,IAAI,SAAkE;IACtE,WAAW,SAAuC;IAClD,WAAW,SAAmF;IAExF,MAAM,IAAI,OAAO,CAAC,WAAW,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;CAG9D"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.MomentToTemporal = void 0;
|
|
13
|
+
const rewrite_1 = require("@openrewrite/rewrite");
|
|
14
|
+
const javascript_1 = require("@openrewrite/rewrite/javascript");
|
|
15
|
+
const java_1 = require("@openrewrite/rewrite/java");
|
|
16
|
+
const UNIT_MAP = {
|
|
17
|
+
'years': 'years', 'year': 'years', 'y': 'years',
|
|
18
|
+
'months': 'months', 'month': 'months', 'M': 'months',
|
|
19
|
+
'weeks': 'weeks', 'week': 'weeks', 'w': 'weeks',
|
|
20
|
+
'days': 'days', 'day': 'days', 'd': 'days',
|
|
21
|
+
'hours': 'hours', 'hour': 'hours', 'h': 'hours',
|
|
22
|
+
'minutes': 'minutes', 'minute': 'minutes', 'm': 'minutes',
|
|
23
|
+
'seconds': 'seconds', 'second': 'seconds', 's': 'seconds',
|
|
24
|
+
'milliseconds': 'milliseconds', 'millisecond': 'milliseconds', 'ms': 'milliseconds',
|
|
25
|
+
};
|
|
26
|
+
const STARTOF_MAP = {
|
|
27
|
+
'day': '.toPlainDate().toPlainDateTime()',
|
|
28
|
+
'month': '.with({day: 1}).toPlainDate().toPlainDateTime()',
|
|
29
|
+
'year': '.with({month: 1, day: 1}).toPlainDate().toPlainDateTime()',
|
|
30
|
+
};
|
|
31
|
+
class MomentToTemporal extends rewrite_1.Recipe {
|
|
32
|
+
constructor() {
|
|
33
|
+
super(...arguments);
|
|
34
|
+
this.name = "org.openrewrite.javascript.migrate.moment.moment-to-temporal";
|
|
35
|
+
this.displayName = "Migrate Moment.js to Temporal API";
|
|
36
|
+
this.description = "Replaces common Moment.js patterns with equivalent native Temporal API usage.";
|
|
37
|
+
}
|
|
38
|
+
editor() {
|
|
39
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
40
|
+
return new MomentToTemporalVisitor();
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
exports.MomentToTemporal = MomentToTemporal;
|
|
45
|
+
class MomentToTemporalVisitor extends javascript_1.JavaScriptVisitor {
|
|
46
|
+
visitJsCompilationUnit(cu, ctx) {
|
|
47
|
+
const _super = Object.create(null, {
|
|
48
|
+
visitJsCompilationUnit: { get: () => super.visitJsCompilationUnit }
|
|
49
|
+
});
|
|
50
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
51
|
+
var _a;
|
|
52
|
+
this.momentImportName = undefined;
|
|
53
|
+
this.rules = undefined;
|
|
54
|
+
for (const stmt of cu.statements) {
|
|
55
|
+
const s = (_a = stmt.element) !== null && _a !== void 0 ? _a : stmt;
|
|
56
|
+
if (s.kind === javascript_1.JS.Kind.Import) {
|
|
57
|
+
this.detectMomentImport(s);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (!this.momentImportName) {
|
|
61
|
+
return cu;
|
|
62
|
+
}
|
|
63
|
+
this.rules = this.buildRules();
|
|
64
|
+
const result = yield _super.visitJsCompilationUnit.call(this, cu, ctx);
|
|
65
|
+
(0, javascript_1.maybeRemoveImport)(this, 'moment', 'default');
|
|
66
|
+
return result;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
detectMomentImport(imp) {
|
|
70
|
+
const moduleSpecifier = imp.moduleSpecifier;
|
|
71
|
+
if (!moduleSpecifier)
|
|
72
|
+
return;
|
|
73
|
+
const literal = moduleSpecifier.element;
|
|
74
|
+
if (literal.kind !== java_1.J.Kind.Literal)
|
|
75
|
+
return;
|
|
76
|
+
if (literal.value !== 'moment')
|
|
77
|
+
return;
|
|
78
|
+
const importClause = imp.importClause;
|
|
79
|
+
if (!(importClause === null || importClause === void 0 ? void 0 : importClause.name))
|
|
80
|
+
return;
|
|
81
|
+
const nameElem = importClause.name.element;
|
|
82
|
+
if ((0, java_1.isIdentifier)(nameElem)) {
|
|
83
|
+
this.momentImportName = nameElem.simpleName;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
visitFunctionCall(functionCall, ctx) {
|
|
87
|
+
const _super = Object.create(null, {
|
|
88
|
+
visitFunctionCall: { get: () => super.visitFunctionCall }
|
|
89
|
+
});
|
|
90
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
91
|
+
functionCall = (yield _super.visitFunctionCall.call(this, functionCall, ctx));
|
|
92
|
+
if (!this.momentImportName || !this.rules)
|
|
93
|
+
return functionCall;
|
|
94
|
+
return (yield this.rules.tryOn(this.cursor, functionCall)) || functionCall;
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
visitMethodInvocation(method, ctx) {
|
|
98
|
+
const _super = Object.create(null, {
|
|
99
|
+
visitMethodInvocation: { get: () => super.visitMethodInvocation }
|
|
100
|
+
});
|
|
101
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
102
|
+
method = (yield _super.visitMethodInvocation.call(this, method, ctx));
|
|
103
|
+
if (!this.momentImportName || !this.rules)
|
|
104
|
+
return method;
|
|
105
|
+
return (yield this.rules.tryOn(this.cursor, method)) || method;
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
buildRules() {
|
|
109
|
+
return this.createNoArgRule()
|
|
110
|
+
.orElse(this.createOneArgRule())
|
|
111
|
+
.orElse(this.utcNoArgRule())
|
|
112
|
+
.orElse(this.utcOneArgRule())
|
|
113
|
+
.orElse(this.addSubtractRule('add'))
|
|
114
|
+
.orElse(this.addSubtractRule('subtract'))
|
|
115
|
+
.orElse(this.comparisonRule('isBefore', '< 0'))
|
|
116
|
+
.orElse(this.comparisonRule('isAfter', '> 0'))
|
|
117
|
+
.orElse(this.comparisonRule('isSame', '=== 0'))
|
|
118
|
+
.orElse(this.cloneRule())
|
|
119
|
+
.orElse(this.startOfRule());
|
|
120
|
+
}
|
|
121
|
+
createNoArgRule() {
|
|
122
|
+
return (0, javascript_1.rewrite)(() => ({
|
|
123
|
+
before: (0, javascript_1.pattern) `${(0, javascript_1.raw)(this.momentImportName)}()`,
|
|
124
|
+
after: (0, javascript_1.template) `Temporal.Now.plainDateTimeISO()`
|
|
125
|
+
}));
|
|
126
|
+
}
|
|
127
|
+
createOneArgRule() {
|
|
128
|
+
const arg = (0, javascript_1.capture)();
|
|
129
|
+
return (0, javascript_1.rewrite)(() => ({
|
|
130
|
+
before: (0, javascript_1.pattern) `${(0, javascript_1.raw)(this.momentImportName)}(${arg})`,
|
|
131
|
+
after: (0, javascript_1.template) `Temporal.PlainDateTime.from(${arg})`
|
|
132
|
+
}));
|
|
133
|
+
}
|
|
134
|
+
utcNoArgRule() {
|
|
135
|
+
return (0, javascript_1.rewrite)(() => ({
|
|
136
|
+
before: (0, javascript_1.pattern) `${(0, javascript_1.raw)(this.momentImportName)}.utc()`,
|
|
137
|
+
after: (0, javascript_1.template) `Temporal.Now.instant()`
|
|
138
|
+
}));
|
|
139
|
+
}
|
|
140
|
+
utcOneArgRule() {
|
|
141
|
+
const arg = (0, javascript_1.capture)();
|
|
142
|
+
return (0, javascript_1.rewrite)(() => ({
|
|
143
|
+
before: (0, javascript_1.pattern) `${(0, javascript_1.raw)(this.momentImportName)}.utc(${arg})`,
|
|
144
|
+
after: (0, javascript_1.template) `Temporal.Instant.from(${arg})`
|
|
145
|
+
}));
|
|
146
|
+
}
|
|
147
|
+
addSubtractRule(methodName) {
|
|
148
|
+
return (0, javascript_1.rewrite)(() => {
|
|
149
|
+
const obj = (0, javascript_1.capture)();
|
|
150
|
+
const amount = (0, javascript_1.capture)();
|
|
151
|
+
const unit = (0, javascript_1.capture)({
|
|
152
|
+
constraint: (n) => (0, java_1.isLiteral)(n) && typeof n.value === 'string' && UNIT_MAP[n.value] !== undefined
|
|
153
|
+
});
|
|
154
|
+
return {
|
|
155
|
+
before: (0, javascript_1.pattern) `${obj}.${(0, javascript_1.raw)(methodName)}(${amount}, ${unit})`,
|
|
156
|
+
after: (match) => {
|
|
157
|
+
const unitStr = match.get(unit).value;
|
|
158
|
+
return (0, javascript_1.template) `${obj}.${(0, javascript_1.raw)(methodName)}({${(0, javascript_1.raw)(UNIT_MAP[unitStr])}: ${amount}})`;
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
comparisonRule(methodName, operator) {
|
|
164
|
+
const a = (0, javascript_1.capture)();
|
|
165
|
+
const b = (0, javascript_1.capture)();
|
|
166
|
+
return (0, javascript_1.rewrite)(() => ({
|
|
167
|
+
before: (0, javascript_1.pattern) `${a}.${(0, javascript_1.raw)(methodName)}(${b})`,
|
|
168
|
+
after: (0, javascript_1.template) `Temporal.PlainDateTime.compare(${a}, ${b}) ${(0, javascript_1.raw)(operator)}`
|
|
169
|
+
}));
|
|
170
|
+
}
|
|
171
|
+
cloneRule() {
|
|
172
|
+
const obj = (0, javascript_1.capture)();
|
|
173
|
+
return (0, javascript_1.rewrite)(() => ({
|
|
174
|
+
before: (0, javascript_1.pattern) `${obj}.clone()`,
|
|
175
|
+
after: (0, javascript_1.template) `${obj}`
|
|
176
|
+
}));
|
|
177
|
+
}
|
|
178
|
+
startOfRule() {
|
|
179
|
+
return (0, javascript_1.rewrite)(() => {
|
|
180
|
+
const obj = (0, javascript_1.capture)();
|
|
181
|
+
const unit = (0, javascript_1.capture)({
|
|
182
|
+
constraint: (n) => (0, java_1.isLiteral)(n) && typeof n.value === 'string' && STARTOF_MAP[n.value] !== undefined
|
|
183
|
+
});
|
|
184
|
+
return {
|
|
185
|
+
before: (0, javascript_1.pattern) `${obj}.startOf(${unit})`,
|
|
186
|
+
after: (match) => {
|
|
187
|
+
const unitStr = match.get(unit).value;
|
|
188
|
+
return (0, javascript_1.template) `${obj}${(0, javascript_1.raw)(STARTOF_MAP[unitStr])}`;
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=moment-to-temporal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"moment-to-temporal.js","sourceRoot":"","sources":["../src/moment-to-temporal.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@openrewrite/recipes-date-libraries",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"license": "Moderne Source Available License",
|
|
5
|
+
"description": "OpenRewrite recipes for migrating JavaScript/TypeScript date libraries to the native Temporal API.",
|
|
6
|
+
"homepage": "https://github.com/moderneinc/recipes-javascript",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist/**",
|
|
11
|
+
"src/**"
|
|
12
|
+
],
|
|
13
|
+
"exports": {
|
|
14
|
+
".": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "rm -rf ./dist tsconfig.build.tsbuildinfo && tsc --build tsconfig.build.json",
|
|
21
|
+
"dev": "tsc --watch -p tsconfig.json",
|
|
22
|
+
"test": "npm run build && vitest run",
|
|
23
|
+
"ci:test": "vitest run"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@openrewrite/rewrite": "next",
|
|
27
|
+
"immer": "^10.1.1"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/node": "^22.5.4",
|
|
31
|
+
"tmp-promise": "^3.0.3",
|
|
32
|
+
"typescript": "^5.6.2",
|
|
33
|
+
"vitest": "^4.1.9"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 the original author or authors.
|
|
3
|
+
* <p>
|
|
4
|
+
* Licensed under the Moderne Source Available License (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
* <p>
|
|
8
|
+
* https://docs.moderne.io/licensing/moderne-source-available-license
|
|
9
|
+
* <p>
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import {ExecutionContext, Recipe, TreeVisitor} from "@openrewrite/rewrite";
|
|
18
|
+
import {
|
|
19
|
+
capture,
|
|
20
|
+
JavaScriptVisitor,
|
|
21
|
+
JS,
|
|
22
|
+
maybeRemoveImport,
|
|
23
|
+
pattern,
|
|
24
|
+
raw,
|
|
25
|
+
rewrite,
|
|
26
|
+
RewriteRule,
|
|
27
|
+
template
|
|
28
|
+
} from "@openrewrite/rewrite/javascript";
|
|
29
|
+
import {J, isIdentifier} from "@openrewrite/rewrite/java";
|
|
30
|
+
|
|
31
|
+
const DATE_FNS_FUNCTIONS = new Set([
|
|
32
|
+
'addDays', 'addMonths', 'addYears',
|
|
33
|
+
'subDays', 'subMonths', 'subYears',
|
|
34
|
+
'isAfter', 'isBefore', 'isEqual',
|
|
35
|
+
'differenceInDays', 'differenceInHours', 'differenceInMinutes',
|
|
36
|
+
'startOfDay', 'startOfMonth', 'startOfYear',
|
|
37
|
+
'endOfDay', 'endOfMonth', 'endOfYear',
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
export class DateFnsToTemporal extends Recipe {
|
|
41
|
+
name = "org.openrewrite.javascript.migrate.date-fns.date-fns-to-temporal";
|
|
42
|
+
displayName = "Migrate date-fns to Temporal API";
|
|
43
|
+
description = "Replaces common date-fns function calls with equivalent native Temporal API usage.";
|
|
44
|
+
|
|
45
|
+
async editor(): Promise<TreeVisitor<any, ExecutionContext>> {
|
|
46
|
+
return new DateFnsToTemporalVisitor();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
class DateFnsToTemporalVisitor extends JavaScriptVisitor<ExecutionContext> {
|
|
51
|
+
private importedDateFnsFunctions = new Set<string>();
|
|
52
|
+
private aliasToOriginal = new Map<string, string>();
|
|
53
|
+
|
|
54
|
+
protected override async visitJsCompilationUnit(cu: JS.CompilationUnit, ctx: ExecutionContext): Promise<J | undefined> {
|
|
55
|
+
this.importedDateFnsFunctions = new Set();
|
|
56
|
+
this.aliasToOriginal = new Map();
|
|
57
|
+
|
|
58
|
+
for (const stmt of cu.statements) {
|
|
59
|
+
const s = stmt.element ?? stmt;
|
|
60
|
+
if (s.kind === JS.Kind.Import) {
|
|
61
|
+
this.collectDateFnsImports(s as JS.Import);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (this.importedDateFnsFunctions.size === 0) {
|
|
66
|
+
return cu;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const result = await super.visitJsCompilationUnit(cu, ctx);
|
|
70
|
+
|
|
71
|
+
for (const fn of this.importedDateFnsFunctions) {
|
|
72
|
+
const originalName = this.aliasToOriginal.get(fn) ?? fn;
|
|
73
|
+
maybeRemoveImport(this, 'date-fns', originalName);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private collectDateFnsImports(imp: JS.Import): void {
|
|
80
|
+
const moduleSpecifier = imp.moduleSpecifier;
|
|
81
|
+
if (!moduleSpecifier) return;
|
|
82
|
+
|
|
83
|
+
const literal = moduleSpecifier.element;
|
|
84
|
+
if (literal.kind !== J.Kind.Literal) return;
|
|
85
|
+
if ((literal as J.Literal).value !== 'date-fns') return;
|
|
86
|
+
|
|
87
|
+
const importClause = imp.importClause;
|
|
88
|
+
if (!importClause?.namedBindings) return;
|
|
89
|
+
if (importClause.namedBindings.kind !== JS.Kind.NamedImports) return;
|
|
90
|
+
|
|
91
|
+
const namedImports = importClause.namedBindings as JS.NamedImports;
|
|
92
|
+
for (const elem of namedImports.elements.elements) {
|
|
93
|
+
const specifier = elem.element;
|
|
94
|
+
const specifierNode = specifier.specifier;
|
|
95
|
+
|
|
96
|
+
// Simple import: import { addDays } from 'date-fns'
|
|
97
|
+
if (isIdentifier(specifierNode) && DATE_FNS_FUNCTIONS.has(specifierNode.simpleName)) {
|
|
98
|
+
this.importedDateFnsFunctions.add(specifierNode.simpleName);
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Aliased import: import { addDays as plusDays } from 'date-fns'
|
|
103
|
+
if (specifierNode.kind === JS.Kind.Alias) {
|
|
104
|
+
const alias = specifierNode as JS.Alias;
|
|
105
|
+
const imported = alias.propertyName.element;
|
|
106
|
+
const local = alias.alias;
|
|
107
|
+
if (isIdentifier(imported) && isIdentifier(local) && DATE_FNS_FUNCTIONS.has(imported.simpleName)) {
|
|
108
|
+
this.importedDateFnsFunctions.add(local.simpleName);
|
|
109
|
+
this.aliasToOriginal.set(local.simpleName, imported.simpleName);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
protected override async visitMethodInvocation(method: J.MethodInvocation, ctx: ExecutionContext): Promise<J | undefined> {
|
|
116
|
+
method = await super.visitMethodInvocation(method, ctx) as J.MethodInvocation;
|
|
117
|
+
if (this.importedDateFnsFunctions.size === 0) return method;
|
|
118
|
+
|
|
119
|
+
const name = (method.name as J.Identifier)?.simpleName;
|
|
120
|
+
if (!name || !this.importedDateFnsFunctions.has(name)) return method;
|
|
121
|
+
|
|
122
|
+
const originalName = this.aliasToOriginal.get(name) ?? name;
|
|
123
|
+
const rule = this.getRuleForFunction(name, originalName);
|
|
124
|
+
if (!rule) return method;
|
|
125
|
+
|
|
126
|
+
return await rule.tryOn(this.cursor, method) || method;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
protected override async visitFunctionCall(functionCall: JS.FunctionCall, ctx: ExecutionContext): Promise<J | undefined> {
|
|
130
|
+
functionCall = await super.visitFunctionCall(functionCall, ctx) as JS.FunctionCall;
|
|
131
|
+
if (this.importedDateFnsFunctions.size === 0) return functionCall;
|
|
132
|
+
|
|
133
|
+
const fn = functionCall.function?.element;
|
|
134
|
+
if (!fn || !isIdentifier(fn)) return functionCall;
|
|
135
|
+
|
|
136
|
+
const name = fn.simpleName;
|
|
137
|
+
if (!this.importedDateFnsFunctions.has(name)) return functionCall;
|
|
138
|
+
|
|
139
|
+
const originalName = this.aliasToOriginal.get(name) ?? name;
|
|
140
|
+
const rule = this.getRuleForFunction(name, originalName);
|
|
141
|
+
if (!rule) return functionCall;
|
|
142
|
+
|
|
143
|
+
return await rule.tryOn(this.cursor, functionCall) || functionCall;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
private _ruleCache = new Map<string, RewriteRule>();
|
|
147
|
+
|
|
148
|
+
private getRuleForFunction(localName: string, originalName: string): RewriteRule | undefined {
|
|
149
|
+
if (this._ruleCache.has(localName)) return this._ruleCache.get(localName)!;
|
|
150
|
+
const rule = this.buildRule(localName, originalName);
|
|
151
|
+
if (rule) this._ruleCache.set(localName, rule);
|
|
152
|
+
return rule;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
private buildRule(localName: string, originalName: string): RewriteRule | undefined {
|
|
156
|
+
switch (originalName) {
|
|
157
|
+
case 'addDays': return this.addSubRule(localName, 'days', 'add');
|
|
158
|
+
case 'addMonths': return this.addSubRule(localName, 'months', 'add');
|
|
159
|
+
case 'addYears': return this.addSubRule(localName, 'years', 'add');
|
|
160
|
+
case 'subDays': return this.addSubRule(localName, 'days', 'subtract');
|
|
161
|
+
case 'subMonths': return this.addSubRule(localName, 'months', 'subtract');
|
|
162
|
+
case 'subYears': return this.addSubRule(localName, 'years', 'subtract');
|
|
163
|
+
|
|
164
|
+
case 'isAfter': return this.compareRule(localName, '> 0');
|
|
165
|
+
case 'isBefore': return this.compareRule(localName, '< 0');
|
|
166
|
+
case 'isEqual': return this.compareRule(localName, '=== 0');
|
|
167
|
+
|
|
168
|
+
case 'differenceInDays': return this.differenceRule(localName, 'day', 'days');
|
|
169
|
+
case 'differenceInHours': return this.differenceRule(localName, 'hour', 'hours');
|
|
170
|
+
case 'differenceInMinutes': return this.differenceRule(localName, 'minute', 'minutes');
|
|
171
|
+
|
|
172
|
+
case 'startOfDay': return this.singleArgRule(localName, 'Temporal.PlainDate.from(', ').toPlainDateTime()');
|
|
173
|
+
case 'startOfMonth': return this.singleArgRule(localName, 'Temporal.PlainDate.from(', ').with({day: 1}).toPlainDateTime()');
|
|
174
|
+
case 'startOfYear': return this.singleArgRule(localName, 'Temporal.PlainDate.from(', ').with({month: 1, day: 1}).toPlainDateTime()');
|
|
175
|
+
case 'endOfDay': return this.singleArgRule(localName, 'Temporal.PlainDate.from(', ').toPlainDateTime({hour: 23, minute: 59, second: 59, millisecond: 999})');
|
|
176
|
+
case 'endOfMonth': return this.endOfMonthRule(localName);
|
|
177
|
+
case 'endOfYear': return this.singleArgRule(localName, 'Temporal.PlainDate.from(', ').with({month: 12, day: 31}).toPlainDateTime({hour: 23, minute: 59, second: 59, millisecond: 999})');
|
|
178
|
+
|
|
179
|
+
default: return undefined;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
private addSubRule(fnName: string, unit: string, method: 'add' | 'subtract'): RewriteRule {
|
|
184
|
+
const date = capture();
|
|
185
|
+
const amount = capture();
|
|
186
|
+
return rewrite(() => ({
|
|
187
|
+
before: pattern`${raw(fnName)}(${date}, ${amount})`,
|
|
188
|
+
after: template`Temporal.PlainDate.from(${date}).${raw(method)}({${raw(unit)}: ${amount}})`
|
|
189
|
+
}));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
private compareRule(fnName: string, operator: string): RewriteRule {
|
|
193
|
+
const a = capture();
|
|
194
|
+
const b = capture();
|
|
195
|
+
return rewrite(() => ({
|
|
196
|
+
before: pattern`${raw(fnName)}(${a}, ${b})`,
|
|
197
|
+
after: template`Temporal.PlainDateTime.compare(${a}, ${b}) ${raw(operator)}`
|
|
198
|
+
}));
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
private differenceRule(fnName: string, largestUnit: string, field: string): RewriteRule {
|
|
202
|
+
const a = capture();
|
|
203
|
+
const b = capture();
|
|
204
|
+
return rewrite(() => ({
|
|
205
|
+
before: pattern`${raw(fnName)}(${a}, ${b})`,
|
|
206
|
+
after: template`${a}.since(${b}, {largestUnit: "${raw(largestUnit)}"}).${raw(field)}`
|
|
207
|
+
}));
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
private singleArgRule(fnName: string, prefix: string, suffix: string): RewriteRule {
|
|
211
|
+
const date = capture();
|
|
212
|
+
return rewrite(() => ({
|
|
213
|
+
before: pattern`${raw(fnName)}(${date})`,
|
|
214
|
+
after: template`${raw(prefix)}${date}${raw(suffix)}`
|
|
215
|
+
}));
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
private endOfMonthRule(fnName: string = 'endOfMonth'): RewriteRule {
|
|
219
|
+
const date = capture();
|
|
220
|
+
return rewrite(() => ({
|
|
221
|
+
before: pattern`${raw(fnName)}(${date})`,
|
|
222
|
+
after: template`((d) => d.with({day: d.daysInMonth}).toPlainDateTime({hour: 23, minute: 59, second: 59, millisecond: 999}))(Temporal.PlainDate.from(${date}))`
|
|
223
|
+
}));
|
|
224
|
+
}
|
|
225
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {CategoryDescriptor, RecipeMarketplace} from "@openrewrite/rewrite";
|
|
2
|
+
import {DateFnsToTemporal} from "./date-fns-to-temporal";
|
|
3
|
+
import {MomentToTemporal} from "./moment-to-temporal";
|
|
4
|
+
|
|
5
|
+
export const Migrate: CategoryDescriptor[] = [{displayName: "Migrate"}];
|
|
6
|
+
|
|
7
|
+
export const MigrateDateFns: CategoryDescriptor[] = [...Migrate, {
|
|
8
|
+
displayName: "date-fns",
|
|
9
|
+
description: "Migrate from date-fns to the native Temporal API."
|
|
10
|
+
}];
|
|
11
|
+
|
|
12
|
+
export const MigrateMoment: CategoryDescriptor[] = [...Migrate, {
|
|
13
|
+
displayName: "Moment.js",
|
|
14
|
+
description: "Migrate from Moment.js to the native Temporal API."
|
|
15
|
+
}];
|
|
16
|
+
|
|
17
|
+
export async function activate(marketplace: RecipeMarketplace): Promise<void> {
|
|
18
|
+
await marketplace.install(DateFnsToTemporal, MigrateDateFns);
|
|
19
|
+
await marketplace.install(MomentToTemporal, MigrateMoment);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export {DateFnsToTemporal} from "./date-fns-to-temporal";
|
|
23
|
+
export {MomentToTemporal} from "./moment-to-temporal";
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 the original author or authors.
|
|
3
|
+
* <p>
|
|
4
|
+
* Licensed under the Moderne Source Available License (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
* <p>
|
|
8
|
+
* https://docs.moderne.io/licensing/moderne-source-available-license
|
|
9
|
+
* <p>
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import {ExecutionContext, Recipe, TreeVisitor} from "@openrewrite/rewrite";
|
|
18
|
+
import {
|
|
19
|
+
capture,
|
|
20
|
+
JavaScriptVisitor,
|
|
21
|
+
JS,
|
|
22
|
+
maybeRemoveImport,
|
|
23
|
+
pattern,
|
|
24
|
+
raw,
|
|
25
|
+
rewrite,
|
|
26
|
+
RewriteRule,
|
|
27
|
+
template
|
|
28
|
+
} from "@openrewrite/rewrite/javascript";
|
|
29
|
+
import {J, isIdentifier, isLiteral} from "@openrewrite/rewrite/java";
|
|
30
|
+
|
|
31
|
+
const UNIT_MAP: Record<string, string> = {
|
|
32
|
+
'years': 'years', 'year': 'years', 'y': 'years',
|
|
33
|
+
'months': 'months', 'month': 'months', 'M': 'months',
|
|
34
|
+
'weeks': 'weeks', 'week': 'weeks', 'w': 'weeks',
|
|
35
|
+
'days': 'days', 'day': 'days', 'd': 'days',
|
|
36
|
+
'hours': 'hours', 'hour': 'hours', 'h': 'hours',
|
|
37
|
+
'minutes': 'minutes', 'minute': 'minutes', 'm': 'minutes',
|
|
38
|
+
'seconds': 'seconds', 'second': 'seconds', 's': 'seconds',
|
|
39
|
+
'milliseconds': 'milliseconds', 'millisecond': 'milliseconds', 'ms': 'milliseconds',
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// Moment's startOf() zeroes time components; round-trip through PlainDate to achieve this
|
|
43
|
+
const STARTOF_MAP: Record<string, string> = {
|
|
44
|
+
'day': '.toPlainDate().toPlainDateTime()',
|
|
45
|
+
'month': '.with({day: 1}).toPlainDate().toPlainDateTime()',
|
|
46
|
+
'year': '.with({month: 1, day: 1}).toPlainDate().toPlainDateTime()',
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export class MomentToTemporal extends Recipe {
|
|
50
|
+
name = "org.openrewrite.javascript.migrate.moment.moment-to-temporal";
|
|
51
|
+
displayName = "Migrate Moment.js to Temporal API";
|
|
52
|
+
description = "Replaces common Moment.js patterns with equivalent native Temporal API usage.";
|
|
53
|
+
|
|
54
|
+
async editor(): Promise<TreeVisitor<any, ExecutionContext>> {
|
|
55
|
+
return new MomentToTemporalVisitor();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
class MomentToTemporalVisitor extends JavaScriptVisitor<ExecutionContext> {
|
|
60
|
+
private momentImportName: string | undefined;
|
|
61
|
+
private rules: RewriteRule | undefined;
|
|
62
|
+
|
|
63
|
+
protected override async visitJsCompilationUnit(cu: JS.CompilationUnit, ctx: ExecutionContext): Promise<J | undefined> {
|
|
64
|
+
this.momentImportName = undefined;
|
|
65
|
+
this.rules = undefined;
|
|
66
|
+
|
|
67
|
+
for (const stmt of cu.statements) {
|
|
68
|
+
const s = stmt.element ?? stmt;
|
|
69
|
+
if (s.kind === JS.Kind.Import) {
|
|
70
|
+
this.detectMomentImport(s as JS.Import);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (!this.momentImportName) {
|
|
75
|
+
return cu;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
this.rules = this.buildRules();
|
|
79
|
+
|
|
80
|
+
const result = await super.visitJsCompilationUnit(cu, ctx);
|
|
81
|
+
|
|
82
|
+
maybeRemoveImport(this, 'moment', 'default');
|
|
83
|
+
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private detectMomentImport(imp: JS.Import): void {
|
|
88
|
+
const moduleSpecifier = imp.moduleSpecifier;
|
|
89
|
+
if (!moduleSpecifier) return;
|
|
90
|
+
|
|
91
|
+
const literal = moduleSpecifier.element;
|
|
92
|
+
if (literal.kind !== J.Kind.Literal) return;
|
|
93
|
+
if ((literal as J.Literal).value !== 'moment') return;
|
|
94
|
+
|
|
95
|
+
const importClause = imp.importClause;
|
|
96
|
+
if (!importClause?.name) return;
|
|
97
|
+
|
|
98
|
+
const nameElem = importClause.name.element;
|
|
99
|
+
if (isIdentifier(nameElem)) {
|
|
100
|
+
this.momentImportName = nameElem.simpleName;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
protected override async visitFunctionCall(functionCall: JS.FunctionCall, ctx: ExecutionContext): Promise<J | undefined> {
|
|
105
|
+
functionCall = await super.visitFunctionCall(functionCall, ctx) as JS.FunctionCall;
|
|
106
|
+
if (!this.momentImportName || !this.rules) return functionCall;
|
|
107
|
+
return await this.rules.tryOn(this.cursor, functionCall) || functionCall;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
protected override async visitMethodInvocation(method: J.MethodInvocation, ctx: ExecutionContext): Promise<J | undefined> {
|
|
111
|
+
method = await super.visitMethodInvocation(method, ctx) as J.MethodInvocation;
|
|
112
|
+
if (!this.momentImportName || !this.rules) return method;
|
|
113
|
+
return await this.rules.tryOn(this.cursor, method) || method;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private buildRules(): RewriteRule {
|
|
117
|
+
return this.createNoArgRule()
|
|
118
|
+
.orElse(this.createOneArgRule())
|
|
119
|
+
.orElse(this.utcNoArgRule())
|
|
120
|
+
.orElse(this.utcOneArgRule())
|
|
121
|
+
.orElse(this.addSubtractRule('add'))
|
|
122
|
+
.orElse(this.addSubtractRule('subtract'))
|
|
123
|
+
.orElse(this.comparisonRule('isBefore', '< 0'))
|
|
124
|
+
.orElse(this.comparisonRule('isAfter', '> 0'))
|
|
125
|
+
.orElse(this.comparisonRule('isSame', '=== 0'))
|
|
126
|
+
.orElse(this.cloneRule())
|
|
127
|
+
.orElse(this.startOfRule());
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// moment() -> Temporal.Now.plainDateTimeISO()
|
|
131
|
+
private createNoArgRule(): RewriteRule {
|
|
132
|
+
return rewrite(() => ({
|
|
133
|
+
before: pattern`${raw(this.momentImportName!)}()`,
|
|
134
|
+
after: template`Temporal.Now.plainDateTimeISO()`
|
|
135
|
+
}));
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// moment(x) -> Temporal.PlainDateTime.from(x)
|
|
139
|
+
private createOneArgRule(): RewriteRule {
|
|
140
|
+
const arg = capture();
|
|
141
|
+
return rewrite(() => ({
|
|
142
|
+
before: pattern`${raw(this.momentImportName!)}(${arg})`,
|
|
143
|
+
after: template`Temporal.PlainDateTime.from(${arg})`
|
|
144
|
+
}));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// moment.utc() -> Temporal.Now.instant()
|
|
148
|
+
private utcNoArgRule(): RewriteRule {
|
|
149
|
+
return rewrite(() => ({
|
|
150
|
+
before: pattern`${raw(this.momentImportName!)}.utc()`,
|
|
151
|
+
after: template`Temporal.Now.instant()`
|
|
152
|
+
}));
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// moment.utc(x) -> Temporal.Instant.from(x)
|
|
156
|
+
private utcOneArgRule(): RewriteRule {
|
|
157
|
+
const arg = capture();
|
|
158
|
+
return rewrite(() => ({
|
|
159
|
+
before: pattern`${raw(this.momentImportName!)}.utc(${arg})`,
|
|
160
|
+
after: template`Temporal.Instant.from(${arg})`
|
|
161
|
+
}));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// .add(amount, unit) / .subtract(amount, unit)
|
|
165
|
+
private addSubtractRule(methodName: 'add' | 'subtract'): RewriteRule {
|
|
166
|
+
return rewrite(() => {
|
|
167
|
+
const obj = capture();
|
|
168
|
+
const amount = capture();
|
|
169
|
+
const unit = capture({
|
|
170
|
+
constraint: (n: any) => isLiteral(n) && typeof n.value === 'string' && UNIT_MAP[n.value] !== undefined
|
|
171
|
+
});
|
|
172
|
+
return {
|
|
173
|
+
before: pattern`${obj}.${raw(methodName)}(${amount}, ${unit})`,
|
|
174
|
+
after: (match) => {
|
|
175
|
+
const unitStr = (match.get(unit) as J.Literal).value as string;
|
|
176
|
+
return template`${obj}.${raw(methodName)}({${raw(UNIT_MAP[unitStr])}: ${amount}})`;
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// .isBefore(other) / .isAfter(other) / .isSame(other)
|
|
183
|
+
private comparisonRule(methodName: string, operator: string): RewriteRule {
|
|
184
|
+
const a = capture();
|
|
185
|
+
const b = capture();
|
|
186
|
+
return rewrite(() => ({
|
|
187
|
+
before: pattern`${a}.${raw(methodName)}(${b})`,
|
|
188
|
+
after: template`Temporal.PlainDateTime.compare(${a}, ${b}) ${raw(operator)}`
|
|
189
|
+
}));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// .clone() — Temporal is immutable, just return the receiver
|
|
193
|
+
private cloneRule(): RewriteRule {
|
|
194
|
+
const obj = capture();
|
|
195
|
+
return rewrite(() => ({
|
|
196
|
+
before: pattern`${obj}.clone()`,
|
|
197
|
+
after: template`${obj}`
|
|
198
|
+
}));
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// .startOf(unit) — needs dynamic after for STARTOF_MAP lookup
|
|
202
|
+
private startOfRule(): RewriteRule {
|
|
203
|
+
return rewrite(() => {
|
|
204
|
+
const obj = capture();
|
|
205
|
+
const unit = capture({
|
|
206
|
+
constraint: (n: any) => isLiteral(n) && typeof n.value === 'string' && STARTOF_MAP[n.value] !== undefined
|
|
207
|
+
});
|
|
208
|
+
return {
|
|
209
|
+
before: pattern`${obj}.startOf(${unit})`,
|
|
210
|
+
after: (match) => {
|
|
211
|
+
const unitStr = (match.get(unit) as J.Literal).value as string;
|
|
212
|
+
return template`${obj}${raw(STARTOF_MAP[unitStr])}`;
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
}
|