@next/codemod 16.0.0-canary.8 → 16.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.
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = transformer;
4
+ const parser_1 = require("../lib/parser");
5
+ function transformer(file, _api) {
6
+ // Run on App Router page/layout/route files, except for test environment.
7
+ if (process.env.NODE_ENV !== 'test' &&
8
+ !/[/\\]app[/\\](?:.*[/\\])?(page|layout|route)(\.[^/\\]*)?$/.test(file.path)) {
9
+ return file.source;
10
+ }
11
+ const j = (0, parser_1.createParserFromPath)(file.path);
12
+ const root = j(file.source);
13
+ let hasChanges = false;
14
+ // Remove export const experimental_ppr = boolean
15
+ const directExports = root.find(j.ExportNamedDeclaration, {
16
+ declaration: {
17
+ type: 'VariableDeclaration',
18
+ declarations: [
19
+ {
20
+ id: { name: 'experimental_ppr' },
21
+ },
22
+ ],
23
+ },
24
+ });
25
+ if (directExports.size() > 0) {
26
+ directExports.remove();
27
+ hasChanges = true;
28
+ }
29
+ // Remove const experimental_ppr = boolean declarations
30
+ const variableDeclarations = root.find(j.VariableDeclaration).filter((path) => path.node.declarations.some((decl) => {
31
+ if (j.VariableDeclarator.check(decl) && j.Identifier.check(decl.id)) {
32
+ return decl.id.name === 'experimental_ppr';
33
+ }
34
+ return false;
35
+ }));
36
+ if (variableDeclarations.size() > 0) {
37
+ variableDeclarations.remove();
38
+ hasChanges = true;
39
+ }
40
+ // Handle export { experimental_ppr } and export { experimental_ppr, other }
41
+ const namedExports = root
42
+ .find(j.ExportNamedDeclaration)
43
+ .filter((path) => path.node.specifiers && path.node.specifiers.length > 0);
44
+ namedExports.forEach((path) => {
45
+ const specifiers = path.node.specifiers;
46
+ if (!specifiers)
47
+ return;
48
+ const filteredSpecifiers = specifiers.filter((spec) => {
49
+ if (j.ExportSpecifier.check(spec) && j.Identifier.check(spec.local)) {
50
+ return spec.local.name !== 'experimental_ppr';
51
+ }
52
+ return true;
53
+ });
54
+ // If we removed any specifiers
55
+ if (filteredSpecifiers.length !== specifiers.length) {
56
+ hasChanges = true;
57
+ // If no specifiers left, remove the entire export statement
58
+ if (filteredSpecifiers.length === 0) {
59
+ j(path).remove();
60
+ }
61
+ else {
62
+ // Update the specifiers array
63
+ path.node.specifiers = filteredSpecifiers;
64
+ }
65
+ }
66
+ });
67
+ if (hasChanges) {
68
+ return root.toSource();
69
+ }
70
+ return file.source;
71
+ }
72
+ //# sourceMappingURL=remove-experimental-ppr.js.map
@@ -0,0 +1,297 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = transformer;
4
+ const parser_1 = require("../lib/parser");
5
+ // Mapping of unstable APIs to their stable counterparts
6
+ // This can be easily extended when new APIs are stabilized
7
+ const UNSTABLE_TO_STABLE_MAPPING = {
8
+ unstable_cacheTag: 'cacheTag',
9
+ unstable_cacheLife: 'cacheLife',
10
+ };
11
+ // Helper function to check if a property name should be renamed
12
+ function shouldRenameProperty(propertyName) {
13
+ return propertyName in UNSTABLE_TO_STABLE_MAPPING;
14
+ }
15
+ function transformer(file, _api, options) {
16
+ const j = (0, parser_1.createParserFromPath)(file.path);
17
+ const root = j(file.source);
18
+ let hasChanges = false;
19
+ try {
20
+ // Track identifier renames that need to be applied
21
+ const identifierRenames = [];
22
+ // Track variables assigned from next/cache imports/requires
23
+ const cacheVariables = new Set();
24
+ // Handle ES6 imports: import { unstable_cacheTag } from 'next/cache'
25
+ root
26
+ .find(j.ImportDeclaration, { source: { value: 'next/cache' } })
27
+ .forEach((path) => {
28
+ path.node.specifiers?.forEach((specifier) => {
29
+ if (specifier.type === 'ImportSpecifier' &&
30
+ specifier.imported?.type === 'Identifier' &&
31
+ shouldRenameProperty(specifier.imported.name)) {
32
+ const oldName = specifier.imported.name;
33
+ const newName = UNSTABLE_TO_STABLE_MAPPING[oldName];
34
+ // Handle alias scenarios
35
+ if (specifier.local && specifier.local.name === newName) {
36
+ // Same alias name: { unstable_cacheTag as cacheTag } -> { cacheTag }
37
+ const newSpecifier = j.importSpecifier(j.identifier(newName));
38
+ const specifierIndex = path.node.specifiers.indexOf(specifier);
39
+ path.node.specifiers[specifierIndex] = newSpecifier;
40
+ identifierRenames.push({ oldName, newName });
41
+ }
42
+ else {
43
+ // Normal case: just update the imported name
44
+ specifier.imported = j.identifier(newName);
45
+ if (!specifier.local || specifier.local.name === oldName) {
46
+ // Not aliased or aliased with old name: add to identifier renames
47
+ identifierRenames.push({ oldName, newName });
48
+ }
49
+ }
50
+ hasChanges = true;
51
+ }
52
+ else if (specifier.type === 'ImportNamespaceSpecifier') {
53
+ // Handle namespace imports: import * as cache from 'next/cache'
54
+ cacheVariables.add(specifier.local.name);
55
+ }
56
+ });
57
+ });
58
+ // Handle export statements: export { unstable_cacheTag } from 'next/cache'
59
+ root
60
+ .find(j.ExportNamedDeclaration, { source: { value: 'next/cache' } })
61
+ .forEach((path) => {
62
+ path.node.specifiers?.forEach((specifier) => {
63
+ if (specifier.type === 'ExportSpecifier' &&
64
+ specifier.local?.type === 'Identifier' &&
65
+ shouldRenameProperty(specifier.local.name)) {
66
+ const oldName = specifier.local.name;
67
+ const newName = UNSTABLE_TO_STABLE_MAPPING[oldName];
68
+ specifier.local = j.identifier(newName);
69
+ // Handle export alias scenarios
70
+ if (specifier.exported && specifier.exported.name === newName) {
71
+ // Same alias name: { unstable_cacheTag as cacheTag } -> { cacheTag }
72
+ specifier.exported = specifier.local;
73
+ }
74
+ else if (!specifier.exported ||
75
+ specifier.exported.name === oldName) {
76
+ // Not aliased or aliased with old name
77
+ specifier.exported = j.identifier(newName);
78
+ }
79
+ hasChanges = true;
80
+ }
81
+ });
82
+ });
83
+ // Handle require('next/cache') calls and destructuring
84
+ root
85
+ .find(j.CallExpression, { callee: { name: 'require' } })
86
+ .forEach((path) => {
87
+ if (path.node.arguments[0]?.type === 'StringLiteral' &&
88
+ path.node.arguments[0].value === 'next/cache') {
89
+ // Track variable assignments: const cache = require('next/cache')
90
+ const parent = path.parent?.node;
91
+ if (parent?.type === 'VariableDeclarator' &&
92
+ parent.id?.type === 'Identifier') {
93
+ cacheVariables.add(parent.id.name);
94
+ }
95
+ // Handle destructuring: const { unstable_cacheTag } = require('next/cache')
96
+ if (parent?.type === 'VariableDeclarator' &&
97
+ parent.id?.type === 'ObjectPattern') {
98
+ parent.id.properties?.forEach((property) => {
99
+ if (property.type === 'ObjectProperty' &&
100
+ property.key?.type === 'Identifier' &&
101
+ shouldRenameProperty(property.key.name)) {
102
+ const oldName = property.key.name;
103
+ const newName = UNSTABLE_TO_STABLE_MAPPING[oldName];
104
+ property.key = j.identifier(newName);
105
+ // Handle both shorthand and explicit destructuring
106
+ if (!property.value) {
107
+ property.value = j.identifier(newName);
108
+ identifierRenames.push({ oldName, newName });
109
+ }
110
+ else if (property.value.type === 'Identifier') {
111
+ const localName = property.value.name;
112
+ if (localName === oldName) {
113
+ property.value = j.identifier(newName);
114
+ identifierRenames.push({ oldName, newName });
115
+ }
116
+ else if (localName === newName) {
117
+ // Same alias name: { unstable_cacheTag: cacheTag } -> { cacheTag }
118
+ property.value = j.identifier(newName);
119
+ property.shorthand = true;
120
+ identifierRenames.push({ oldName, newName });
121
+ }
122
+ }
123
+ hasChanges = true;
124
+ }
125
+ });
126
+ }
127
+ }
128
+ });
129
+ // Handle await import('next/cache') calls and destructuring
130
+ root.find(j.AwaitExpression).forEach((path) => {
131
+ const arg = path.node.argument;
132
+ if (arg?.type === 'CallExpression' &&
133
+ arg.callee?.type === 'Import' &&
134
+ arg.arguments[0]?.type === 'StringLiteral' &&
135
+ arg.arguments[0].value === 'next/cache') {
136
+ // Track variable assignments: const cache = await import('next/cache')
137
+ const parent = path.parent?.node;
138
+ if (parent?.type === 'VariableDeclarator' &&
139
+ parent.id?.type === 'Identifier') {
140
+ cacheVariables.add(parent.id.name);
141
+ }
142
+ // Handle destructuring: const { unstable_cacheTag } = await import('next/cache')
143
+ if (parent?.type === 'VariableDeclarator' &&
144
+ parent.id?.type === 'ObjectPattern') {
145
+ parent.id.properties?.forEach((property) => {
146
+ if (property.type === 'ObjectProperty' &&
147
+ property.key?.type === 'Identifier' &&
148
+ shouldRenameProperty(property.key.name)) {
149
+ const oldName = property.key.name;
150
+ const newName = UNSTABLE_TO_STABLE_MAPPING[oldName];
151
+ property.key = j.identifier(newName);
152
+ if (!property.value) {
153
+ property.value = j.identifier(newName);
154
+ identifierRenames.push({ oldName, newName });
155
+ }
156
+ else if (property.value.type === 'Identifier') {
157
+ const localName = property.value.name;
158
+ if (localName === oldName) {
159
+ property.value = j.identifier(newName);
160
+ identifierRenames.push({ oldName, newName });
161
+ }
162
+ else if (localName === newName) {
163
+ // Same alias name: { unstable_cacheTag: cacheTag } -> { cacheTag }
164
+ property.value = j.identifier(newName);
165
+ property.shorthand = true;
166
+ identifierRenames.push({ oldName, newName });
167
+ }
168
+ }
169
+ hasChanges = true;
170
+ }
171
+ });
172
+ }
173
+ }
174
+ });
175
+ // Handle .then() chains: import('next/cache').then(({ unstable_cacheTag }) => ...)
176
+ root.find(j.CallExpression).forEach((path) => {
177
+ if (path.node.callee?.type === 'MemberExpression' &&
178
+ path.node.callee.property?.type === 'Identifier' &&
179
+ path.node.callee.property.name === 'then' &&
180
+ path.node.callee.object?.type === 'CallExpression' &&
181
+ path.node.callee.object.callee?.type === 'Import' &&
182
+ path.node.callee.object.arguments[0]?.type === 'StringLiteral' &&
183
+ path.node.callee.object.arguments[0].value === 'next/cache' &&
184
+ path.node.arguments.length > 0) {
185
+ const callback = path.node.arguments[0];
186
+ let params = null;
187
+ if (callback.type === 'ArrowFunctionExpression') {
188
+ params = callback.params;
189
+ }
190
+ else if (callback.type === 'FunctionExpression') {
191
+ params = callback.params;
192
+ }
193
+ if (params && params.length > 0 && params[0].type === 'ObjectPattern') {
194
+ params[0].properties?.forEach((property) => {
195
+ if (property.type === 'ObjectProperty' &&
196
+ property.key?.type === 'Identifier' &&
197
+ shouldRenameProperty(property.key.name)) {
198
+ const oldName = property.key.name;
199
+ const newName = UNSTABLE_TO_STABLE_MAPPING[oldName];
200
+ property.key = j.identifier(newName);
201
+ if (!property.value) {
202
+ property.value = j.identifier(newName);
203
+ identifierRenames.push({ oldName, newName });
204
+ }
205
+ else if (property.value.type === 'Identifier') {
206
+ const localName = property.value.name;
207
+ if (localName === oldName) {
208
+ property.value = j.identifier(newName);
209
+ identifierRenames.push({ oldName, newName });
210
+ }
211
+ else if (localName === newName) {
212
+ // Same alias name: { unstable_cacheTag: cacheTag } -> { cacheTag }
213
+ property.value = j.identifier(newName);
214
+ property.shorthand = true;
215
+ identifierRenames.push({ oldName, newName });
216
+ }
217
+ }
218
+ hasChanges = true;
219
+ }
220
+ });
221
+ }
222
+ }
223
+ });
224
+ // Handle member expressions
225
+ root.find(j.MemberExpression).forEach((path) => {
226
+ const node = path.node;
227
+ // Handle direct property access: require('next/cache').unstable_cacheTag
228
+ if (node.object?.type === 'CallExpression' &&
229
+ node.object.callee?.type === 'Identifier' &&
230
+ node.object.callee.name === 'require' &&
231
+ node.object.arguments[0]?.type === 'StringLiteral' &&
232
+ node.object.arguments[0].value === 'next/cache') {
233
+ if (node.computed &&
234
+ node.property?.type === 'StringLiteral' &&
235
+ shouldRenameProperty(node.property.value)) {
236
+ const newName = UNSTABLE_TO_STABLE_MAPPING[node.property.value];
237
+ node.property = j.stringLiteral(newName);
238
+ hasChanges = true;
239
+ }
240
+ else if (!node.computed &&
241
+ node.property?.type === 'Identifier' &&
242
+ shouldRenameProperty(node.property.name)) {
243
+ const newName = UNSTABLE_TO_STABLE_MAPPING[node.property.name];
244
+ node.property = j.identifier(newName);
245
+ hasChanges = true;
246
+ }
247
+ }
248
+ // Handle property access on cache variables: cache.unstable_cacheTag or cache['unstable_cacheTag']
249
+ if (node.object?.type === 'Identifier' &&
250
+ cacheVariables.has(node.object.name)) {
251
+ if (node.computed &&
252
+ node.property?.type === 'StringLiteral' &&
253
+ shouldRenameProperty(node.property.value)) {
254
+ const newName = UNSTABLE_TO_STABLE_MAPPING[node.property.value];
255
+ node.property = j.stringLiteral(newName);
256
+ hasChanges = true;
257
+ }
258
+ else if (!node.computed &&
259
+ node.property?.type === 'Identifier' &&
260
+ shouldRenameProperty(node.property.name)) {
261
+ const newName = UNSTABLE_TO_STABLE_MAPPING[node.property.name];
262
+ node.property = j.identifier(newName);
263
+ hasChanges = true;
264
+ }
265
+ }
266
+ });
267
+ // Apply all identifier renames with better scope awareness
268
+ identifierRenames.forEach(({ oldName, newName }) => {
269
+ root
270
+ .find(j.Identifier, { name: oldName })
271
+ .filter((identifierPath) => {
272
+ // Skip renaming declarations themselves
273
+ const parent = identifierPath.parent;
274
+ return !(parent.node.type === 'ImportSpecifier' ||
275
+ parent.node.type === 'ExportSpecifier' ||
276
+ (parent.node.type === 'ObjectProperty' &&
277
+ parent.node.key === identifierPath.node) ||
278
+ (parent.node.type === 'VariableDeclarator' &&
279
+ parent.node.id === identifierPath.node) ||
280
+ (parent.node.type === 'FunctionDeclaration' &&
281
+ parent.node.id === identifierPath.node) ||
282
+ (parent.node.type === 'Property' &&
283
+ parent.node.key === identifierPath.node &&
284
+ !parent.node.computed));
285
+ })
286
+ .forEach((identifierPath) => {
287
+ identifierPath.node.name = newName;
288
+ });
289
+ });
290
+ return hasChanges ? root.toSource(options) : file.source;
291
+ }
292
+ catch (error) {
293
+ console.warn(`Failed to transform ${file.path}: ${error.message}`);
294
+ return file.source;
295
+ }
296
+ }
297
+ //# sourceMappingURL=remove-unstable-prefix.js.map