@next/codemod 15.0.0-canary.162 → 15.0.0-canary.163
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/bin/cli.js
CHANGED
|
@@ -23,7 +23,7 @@ const path_1 = __importDefault(require("path"));
|
|
|
23
23
|
const execa_1 = __importDefault(require("execa"));
|
|
24
24
|
const picocolors_1 = require("picocolors");
|
|
25
25
|
const is_git_clean_1 = __importDefault(require("is-git-clean"));
|
|
26
|
-
const
|
|
26
|
+
const handle_package_1 = require("../lib/handle-package");
|
|
27
27
|
exports.jscodeshiftExecutable = require.resolve('.bin/jscodeshift');
|
|
28
28
|
exports.transformerDirectory = path_1.default.join(__dirname, '../', 'transforms');
|
|
29
29
|
function checkGitStatus(force) {
|
|
@@ -87,12 +87,16 @@ function runTransform({ files, flags, transformer }) {
|
|
|
87
87
|
if (!dry && transformer === 'built-in-next-font') {
|
|
88
88
|
console.log('Uninstalling `@next/font`');
|
|
89
89
|
try {
|
|
90
|
-
(0,
|
|
90
|
+
(0, handle_package_1.uninstallPackage)('@next/font');
|
|
91
91
|
}
|
|
92
92
|
catch (_a) {
|
|
93
93
|
console.error("Couldn't uninstall `@next/font`, please uninstall it manually");
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
|
+
if (!dry && transformer === 'next-request-geo-ip') {
|
|
97
|
+
console.log('Installing `@vercel/functions`...');
|
|
98
|
+
(0, handle_package_1.installPackage)('@vercel/functions');
|
|
99
|
+
}
|
|
96
100
|
}
|
|
97
101
|
const TRANSFORMER_INQUIRER_CHOICES = [
|
|
98
102
|
{
|
|
@@ -143,6 +147,10 @@ const TRANSFORMER_INQUIRER_CHOICES = [
|
|
|
143
147
|
name: 'built-in-next-font: Uninstall `@next/font` and transform imports to `next/font`',
|
|
144
148
|
value: 'built-in-next-font',
|
|
145
149
|
},
|
|
150
|
+
{
|
|
151
|
+
name: 'next-request-geo-ip: Install `@vercel/functions` to replace `geo` and `ip` properties on `NextRequest`',
|
|
152
|
+
value: 'next-request-geo-ip',
|
|
153
|
+
},
|
|
146
154
|
];
|
|
147
155
|
function expandFilePathsIfNeeded(filesBeforeExpansion) {
|
|
148
156
|
const shouldExpandFiles = filesBeforeExpansion.some((file) => file.includes('*'));
|
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.uninstallPackage = uninstallPackage;
|
|
7
|
+
exports.installPackage = installPackage;
|
|
7
8
|
const fs_1 = __importDefault(require("fs"));
|
|
8
9
|
const path_1 = __importDefault(require("path"));
|
|
9
10
|
const execa_1 = __importDefault(require("execa"));
|
|
@@ -28,4 +29,15 @@ function uninstallPackage(packageToUninstall) {
|
|
|
28
29
|
}
|
|
29
30
|
execa_1.default.sync(pkgManager, [command, packageToUninstall], { stdio: 'inherit' });
|
|
30
31
|
}
|
|
31
|
-
|
|
32
|
+
function installPackage(packageToInstall) {
|
|
33
|
+
const pkgManager = getPkgManager(process.cwd());
|
|
34
|
+
if (!pkgManager)
|
|
35
|
+
throw new Error('Failed to find package manager');
|
|
36
|
+
try {
|
|
37
|
+
execa_1.default.sync(pkgManager, ['add', packageToInstall], { stdio: 'inherit' });
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
throw new Error(`Failed to install "${packageToInstall}". Please install it manually.`, { cause: error });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=handle-package.js.map
|
package/package.json
CHANGED
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = default_1;
|
|
4
|
+
const GEO = 'geo';
|
|
5
|
+
const IP = 'ip';
|
|
6
|
+
const GEOLOCATION = 'geolocation';
|
|
7
|
+
const IP_ADDRESS = 'ipAddress';
|
|
8
|
+
const GEO_TYPE = 'Geo';
|
|
9
|
+
function default_1(fileInfo, api) {
|
|
10
|
+
const j = api.jscodeshift.withParser('tsx');
|
|
11
|
+
const root = j(fileInfo.source);
|
|
12
|
+
if (!root.length) {
|
|
13
|
+
return fileInfo.source;
|
|
14
|
+
}
|
|
15
|
+
const nextReqType = root
|
|
16
|
+
.find(j.FunctionDeclaration)
|
|
17
|
+
.find(j.Identifier, (id) => {
|
|
18
|
+
var _a;
|
|
19
|
+
if (((_a = id.typeAnnotation) === null || _a === void 0 ? void 0 : _a.type) !== 'TSTypeAnnotation') {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
const typeAnn = id.typeAnnotation.typeAnnotation;
|
|
23
|
+
return (typeAnn.type === 'TSTypeReference' &&
|
|
24
|
+
typeAnn.typeName.type === 'Identifier' &&
|
|
25
|
+
typeAnn.typeName.name === 'NextRequest');
|
|
26
|
+
});
|
|
27
|
+
const vercelFuncImports = root.find(j.ImportDeclaration, {
|
|
28
|
+
source: {
|
|
29
|
+
value: '@vercel/functions',
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
const vercelFuncImportSpecifiers = vercelFuncImports
|
|
33
|
+
.find(j.ImportSpecifier)
|
|
34
|
+
.nodes();
|
|
35
|
+
const vercelFuncImportNames = new Set(vercelFuncImportSpecifiers.map((node) => node.imported.name));
|
|
36
|
+
const hasGeolocation = vercelFuncImportNames.has(GEOLOCATION);
|
|
37
|
+
const hasIpAddress = vercelFuncImportNames.has(IP_ADDRESS);
|
|
38
|
+
const hasGeoType = vercelFuncImportNames.has(GEO_TYPE);
|
|
39
|
+
let identifierNames = new Set();
|
|
40
|
+
// if all identifiers are already imported, we don't need to create
|
|
41
|
+
// a unique identifier for them, therefore we don't look for all
|
|
42
|
+
// identifier names in the file
|
|
43
|
+
if (!hasGeolocation || !hasIpAddress || !hasGeoType) {
|
|
44
|
+
const allIdentifiers = root.find(j.Identifier).nodes();
|
|
45
|
+
identifierNames = new Set(allIdentifiers.map((node) => node.name));
|
|
46
|
+
}
|
|
47
|
+
let geoIdentifier = hasGeolocation
|
|
48
|
+
? getExistingIdentifier(vercelFuncImportSpecifiers, GEOLOCATION)
|
|
49
|
+
: getUniqueIdentifier(identifierNames, GEOLOCATION);
|
|
50
|
+
let ipIdentifier = hasIpAddress
|
|
51
|
+
? getExistingIdentifier(vercelFuncImportSpecifiers, IP_ADDRESS)
|
|
52
|
+
: getUniqueIdentifier(identifierNames, IP_ADDRESS);
|
|
53
|
+
let geoTypeIdentifier = hasGeoType
|
|
54
|
+
? getExistingIdentifier(vercelFuncImportSpecifiers, GEO_TYPE)
|
|
55
|
+
: getUniqueIdentifier(identifierNames, GEO_TYPE);
|
|
56
|
+
let { needImportGeolocation, needImportIpAddress } = replaceGeoIpValues(j, nextReqType, geoIdentifier, ipIdentifier);
|
|
57
|
+
let { needImportGeoType, hasChangedIpType } = replaceGeoIpTypes(j, root, geoTypeIdentifier);
|
|
58
|
+
let needChanges = needImportGeolocation ||
|
|
59
|
+
needImportIpAddress ||
|
|
60
|
+
needImportGeoType ||
|
|
61
|
+
hasChangedIpType;
|
|
62
|
+
if (!needChanges) {
|
|
63
|
+
return fileInfo.source;
|
|
64
|
+
}
|
|
65
|
+
// Even if there was a change above, if there's an existing import,
|
|
66
|
+
// we don't need to import them again.
|
|
67
|
+
needImportGeolocation = !hasGeolocation && needImportGeolocation;
|
|
68
|
+
needImportIpAddress = !hasIpAddress && needImportIpAddress;
|
|
69
|
+
needImportGeoType = !hasGeoType && needImportGeoType;
|
|
70
|
+
insertImportDeclarations(j, root, vercelFuncImports, needImportGeolocation, needImportIpAddress, needImportGeoType, geoIdentifier, ipIdentifier, geoTypeIdentifier);
|
|
71
|
+
return root.toSource();
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Returns an existing identifier from the Vercel functions import declaration.
|
|
75
|
+
*/
|
|
76
|
+
function getExistingIdentifier(vercelFuncImportSpecifiers, identifier) {
|
|
77
|
+
var _a;
|
|
78
|
+
const existingIdentifier = vercelFuncImportSpecifiers.find((node) => node.imported.name === identifier);
|
|
79
|
+
return (((_a = existingIdentifier === null || existingIdentifier === void 0 ? void 0 : existingIdentifier.local) === null || _a === void 0 ? void 0 : _a.name) ||
|
|
80
|
+
existingIdentifier.imported.name ||
|
|
81
|
+
identifier);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Returns a unique identifier by adding a suffix to the original identifier
|
|
85
|
+
* if it already exists in the set.
|
|
86
|
+
*/
|
|
87
|
+
function getUniqueIdentifier(identifierNames, identifier) {
|
|
88
|
+
let suffix = 1;
|
|
89
|
+
let uniqueIdentifier = identifier;
|
|
90
|
+
while (identifierNames.has(uniqueIdentifier)) {
|
|
91
|
+
uniqueIdentifier = `${identifier}${suffix}`;
|
|
92
|
+
suffix++;
|
|
93
|
+
}
|
|
94
|
+
return uniqueIdentifier;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Replaces accessors `geo` and `ip` of NextRequest with corresponding
|
|
98
|
+
* function calls from `@vercel/functions`.
|
|
99
|
+
*
|
|
100
|
+
* Creates new variable declarations for destructuring assignments.
|
|
101
|
+
*/
|
|
102
|
+
function replaceGeoIpValues(j, nextReqType, geoIdentifier, ipIdentifier) {
|
|
103
|
+
let needImportGeolocation = false;
|
|
104
|
+
let needImportIpAddress = false;
|
|
105
|
+
for (const nextReqPath of nextReqType.paths()) {
|
|
106
|
+
const fnPath = nextReqPath.parentPath.parentPath;
|
|
107
|
+
const fn = j(fnPath);
|
|
108
|
+
const blockStatement = fn.find(j.BlockStatement);
|
|
109
|
+
const varDeclarators = fn.find(j.VariableDeclarator);
|
|
110
|
+
// req.geo, req.ip
|
|
111
|
+
const geoAccesses = blockStatement.find(j.MemberExpression, (me) => me.object.type === 'Identifier' &&
|
|
112
|
+
me.object.name === nextReqPath.node.name &&
|
|
113
|
+
me.property.type === 'Identifier' &&
|
|
114
|
+
me.property.name === GEO);
|
|
115
|
+
const ipAccesses = blockStatement.find(j.MemberExpression, (me) => me.object.type === 'Identifier' &&
|
|
116
|
+
me.object.name === nextReqPath.node.name &&
|
|
117
|
+
me.property.type === 'Identifier' &&
|
|
118
|
+
me.property.name === IP);
|
|
119
|
+
// var { geo, ip } = req
|
|
120
|
+
const geoDestructuring = varDeclarators.filter((path) => path.node.id.type === 'ObjectPattern' &&
|
|
121
|
+
path.node.id.properties.some((prop) => prop.type === 'ObjectProperty' &&
|
|
122
|
+
prop.key.type === 'Identifier' &&
|
|
123
|
+
prop.key.name === GEO));
|
|
124
|
+
const ipDestructuring = varDeclarators.filter((path) => path.node.id.type === 'ObjectPattern' &&
|
|
125
|
+
path.node.id.properties.some((prop) => prop.type === 'ObjectProperty' &&
|
|
126
|
+
prop.key.type === 'Identifier' &&
|
|
127
|
+
prop.key.name === IP));
|
|
128
|
+
// geolocation(req), ipAddress(req)
|
|
129
|
+
const geoCall = j.callExpression(j.identifier(geoIdentifier), [
|
|
130
|
+
Object.assign(Object.assign({}, nextReqPath.node), { typeAnnotation: null }),
|
|
131
|
+
]);
|
|
132
|
+
const ipCall = j.callExpression(j.identifier(ipIdentifier), [
|
|
133
|
+
Object.assign(Object.assign({}, nextReqPath.node), { typeAnnotation: null }),
|
|
134
|
+
]);
|
|
135
|
+
geoAccesses.replaceWith(geoCall);
|
|
136
|
+
ipAccesses.replaceWith(ipCall);
|
|
137
|
+
/**
|
|
138
|
+
* For each destructuring assignment, we create a new variable
|
|
139
|
+
* declaration and insert it after the current block statement.
|
|
140
|
+
*
|
|
141
|
+
* Before:
|
|
142
|
+
*
|
|
143
|
+
* ```
|
|
144
|
+
* const { buildId, geo, ip } = req;
|
|
145
|
+
* ```
|
|
146
|
+
*
|
|
147
|
+
* After:
|
|
148
|
+
*
|
|
149
|
+
* ```
|
|
150
|
+
* const { buildId } = req;
|
|
151
|
+
* const geo = geolocation(req);
|
|
152
|
+
* const ip = ipAddress(req);
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
geoDestructuring.forEach((path) => {
|
|
156
|
+
if (path.node.id.type === 'ObjectPattern') {
|
|
157
|
+
const properties = path.node.id.properties;
|
|
158
|
+
const geoProperty = properties.find((prop) => prop.type === 'ObjectProperty' &&
|
|
159
|
+
prop.key.type === 'Identifier' &&
|
|
160
|
+
prop.key.name === GEO);
|
|
161
|
+
const otherProperties = properties.filter((prop) => prop !== geoProperty);
|
|
162
|
+
const geoDeclaration = j.variableDeclaration('const', [
|
|
163
|
+
j.variableDeclarator(j.identifier(
|
|
164
|
+
// Use alias from destructuring (if present) to retain references:
|
|
165
|
+
// const { geo: geoAlias } = req; -> const geoAlias = geolocation(req);
|
|
166
|
+
// This prevents errors from undeclared variables.
|
|
167
|
+
geoProperty.type === 'ObjectProperty' &&
|
|
168
|
+
geoProperty.value.type === 'Identifier'
|
|
169
|
+
? geoProperty.value.name
|
|
170
|
+
: GEO), geoCall),
|
|
171
|
+
]);
|
|
172
|
+
path.node.id.properties = otherProperties;
|
|
173
|
+
path.parent.insertAfter(geoDeclaration);
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
ipDestructuring.forEach((path) => {
|
|
177
|
+
if (path.node.id.type === 'ObjectPattern') {
|
|
178
|
+
const properties = path.node.id.properties;
|
|
179
|
+
const ipProperty = properties.find((prop) => prop.type === 'ObjectProperty' &&
|
|
180
|
+
prop.key.type === 'Identifier' &&
|
|
181
|
+
prop.key.name === IP);
|
|
182
|
+
const otherProperties = properties.filter((prop) => prop !== ipProperty);
|
|
183
|
+
const ipDeclaration = j.variableDeclaration('const', [
|
|
184
|
+
j.variableDeclarator(j.identifier(
|
|
185
|
+
// Use alias from destructuring (if present) to retain references:
|
|
186
|
+
// const { ip: ipAlias } = req; -> const ipAlias = ipAddress(req);
|
|
187
|
+
// This prevents errors from undeclared variables.
|
|
188
|
+
ipProperty.type === 'ObjectProperty' &&
|
|
189
|
+
ipProperty.value.type === 'Identifier'
|
|
190
|
+
? ipProperty.value.name
|
|
191
|
+
: IP), ipCall),
|
|
192
|
+
]);
|
|
193
|
+
path.node.id.properties = otherProperties;
|
|
194
|
+
path.parent.insertAfter(ipDeclaration);
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
needImportGeolocation =
|
|
198
|
+
needImportGeolocation ||
|
|
199
|
+
geoAccesses.length > 0 ||
|
|
200
|
+
geoDestructuring.length > 0;
|
|
201
|
+
needImportIpAddress =
|
|
202
|
+
needImportIpAddress || ipAccesses.length > 0 || ipDestructuring.length > 0;
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
needImportGeolocation,
|
|
206
|
+
needImportIpAddress,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Replaces the types of `NextRequest["geo"]` and `NextRequest["ip"]` with
|
|
211
|
+
* corresponding types from `@vercel/functions`.
|
|
212
|
+
*/
|
|
213
|
+
function replaceGeoIpTypes(j, root, geoTypeIdentifier) {
|
|
214
|
+
let needImportGeoType = false;
|
|
215
|
+
let hasChangedIpType = false;
|
|
216
|
+
// get the type of NextRequest that has accessed for ip and geo
|
|
217
|
+
// NextRequest['geo'], NextRequest['ip']
|
|
218
|
+
const nextReqGeoType = root.find(j.TSIndexedAccessType, (tsIndexedAccessType) => {
|
|
219
|
+
return (tsIndexedAccessType.objectType.type === 'TSTypeReference' &&
|
|
220
|
+
tsIndexedAccessType.objectType.typeName.type === 'Identifier' &&
|
|
221
|
+
tsIndexedAccessType.objectType.typeName.name === 'NextRequest' &&
|
|
222
|
+
tsIndexedAccessType.indexType.type === 'TSLiteralType' &&
|
|
223
|
+
tsIndexedAccessType.indexType.literal.type === 'StringLiteral' &&
|
|
224
|
+
tsIndexedAccessType.indexType.literal.value === GEO);
|
|
225
|
+
});
|
|
226
|
+
const nextReqIpType = root.find(j.TSIndexedAccessType, (tsIndexedAccessType) => {
|
|
227
|
+
return (tsIndexedAccessType.objectType.type === 'TSTypeReference' &&
|
|
228
|
+
tsIndexedAccessType.objectType.typeName.type === 'Identifier' &&
|
|
229
|
+
tsIndexedAccessType.objectType.typeName.name === 'NextRequest' &&
|
|
230
|
+
tsIndexedAccessType.indexType.type === 'TSLiteralType' &&
|
|
231
|
+
tsIndexedAccessType.indexType.literal.type === 'StringLiteral' &&
|
|
232
|
+
tsIndexedAccessType.indexType.literal.value === IP);
|
|
233
|
+
});
|
|
234
|
+
if (nextReqGeoType.length > 0) {
|
|
235
|
+
needImportGeoType = true;
|
|
236
|
+
// replace with type Geo
|
|
237
|
+
nextReqGeoType.replaceWith(j.identifier(geoTypeIdentifier));
|
|
238
|
+
}
|
|
239
|
+
if (nextReqIpType.length > 0) {
|
|
240
|
+
hasChangedIpType = true;
|
|
241
|
+
// replace with type string | undefined
|
|
242
|
+
nextReqIpType.replaceWith(j.tsUnionType([j.tsStringKeyword(), j.tsUndefinedKeyword()]));
|
|
243
|
+
}
|
|
244
|
+
return {
|
|
245
|
+
needImportGeoType,
|
|
246
|
+
hasChangedIpType,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Inserts import declarations from `"@vercel/functions"`.
|
|
251
|
+
*
|
|
252
|
+
* For the `Geo` type that needs to be imported to replace `NextRequest["geo"]`,
|
|
253
|
+
* if it is the only import needed, we import it as a type.
|
|
254
|
+
*
|
|
255
|
+
* ```ts
|
|
256
|
+
* import type { Geo } from "@vercel/functions";
|
|
257
|
+
* ```
|
|
258
|
+
*
|
|
259
|
+
* Otherwise, we import it as an inline type import.
|
|
260
|
+
*
|
|
261
|
+
* ```ts
|
|
262
|
+
* import { type Geo, ... } from "@vercel/functions";
|
|
263
|
+
* ```
|
|
264
|
+
*/
|
|
265
|
+
function insertImportDeclarations(j, root, vercelFuncImports, needImportGeolocation, needImportIpAddress, needImportGeoType, geoIdentifier, ipIdentifier, geoTypeIdentifier) {
|
|
266
|
+
// No need inserting import.
|
|
267
|
+
if (!needImportGeolocation && !needImportIpAddress && !needImportGeoType) {
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
// As we run this only when `NextRequest` is imported, there should be
|
|
271
|
+
// a "next/server" import.
|
|
272
|
+
const firstNextServerImport = root
|
|
273
|
+
.find(j.ImportDeclaration, { source: { value: 'next/server' } })
|
|
274
|
+
.at(0);
|
|
275
|
+
const firstVercelFuncImport = vercelFuncImports.at(0);
|
|
276
|
+
const hasVercelFuncImport = firstVercelFuncImport.length > 0;
|
|
277
|
+
// If there's no "@vercel/functions" import, and we only need to import
|
|
278
|
+
// `Geo` type, we create a type import to avoid side effect with
|
|
279
|
+
// `verbatimModuleSyntax`.
|
|
280
|
+
// x-ref: https://typescript-eslint.io/rules/no-import-type-side-effects
|
|
281
|
+
if (!hasVercelFuncImport &&
|
|
282
|
+
!needImportGeolocation &&
|
|
283
|
+
!needImportIpAddress &&
|
|
284
|
+
needImportGeoType) {
|
|
285
|
+
const geoTypeImportDeclaration = j.importDeclaration([
|
|
286
|
+
needImportGeoType
|
|
287
|
+
? j.importSpecifier(j.identifier(GEO_TYPE), j.identifier(geoTypeIdentifier))
|
|
288
|
+
: null,
|
|
289
|
+
].filter(Boolean), j.literal('@vercel/functions'),
|
|
290
|
+
// import type { Geo } ...
|
|
291
|
+
'type');
|
|
292
|
+
firstNextServerImport.insertAfter(geoTypeImportDeclaration);
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
const importDeclaration = j.importDeclaration([
|
|
296
|
+
// If there was a duplicate identifier, we add an
|
|
297
|
+
// incremental number suffix to it and we use alias:
|
|
298
|
+
// `import { geolocation as geolocation1 } from ...`
|
|
299
|
+
needImportGeolocation
|
|
300
|
+
? j.importSpecifier(j.identifier(GEOLOCATION), j.identifier(geoIdentifier))
|
|
301
|
+
: null,
|
|
302
|
+
needImportIpAddress
|
|
303
|
+
? j.importSpecifier(j.identifier(IP_ADDRESS), j.identifier(ipIdentifier))
|
|
304
|
+
: null,
|
|
305
|
+
needImportGeoType
|
|
306
|
+
? j.importSpecifier(j.identifier(GEO_TYPE), j.identifier(geoTypeIdentifier))
|
|
307
|
+
: null,
|
|
308
|
+
].filter(Boolean), j.literal('@vercel/functions'));
|
|
309
|
+
if (hasVercelFuncImport) {
|
|
310
|
+
firstVercelFuncImport
|
|
311
|
+
.get()
|
|
312
|
+
.node.specifiers.push(...importDeclaration.specifiers);
|
|
313
|
+
if (needImportGeoType) {
|
|
314
|
+
const targetGeo = firstVercelFuncImport
|
|
315
|
+
.get()
|
|
316
|
+
.node.specifiers.find((specifier) => specifier.imported.name === GEO_TYPE);
|
|
317
|
+
if (targetGeo) {
|
|
318
|
+
targetGeo.importKind = 'type';
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
if (needImportGeoType) {
|
|
324
|
+
const targetGeo = importDeclaration.specifiers.find((specifier) => specifier.type === 'ImportSpecifier' &&
|
|
325
|
+
specifier.imported.name === GEO_TYPE);
|
|
326
|
+
if (targetGeo) {
|
|
327
|
+
// @ts-expect-error -- Missing types in jscodeshift.
|
|
328
|
+
targetGeo.importKind = 'type';
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
firstNextServerImport.insertAfter(importDeclaration);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
//# sourceMappingURL=next-request-geo-ip.js.map
|