@clerk/upgrade 2.0.0-canary-core3.v20251203060337 → 2.0.0-snapshot.v20251203152900

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,199 @@
1
+ export const fixtures = [{
2
+ name: 'ClerkProvider legacy redirect props',
3
+ source: `
4
+ import { ClerkProvider } from '@clerk/nextjs';
5
+
6
+ export function App({ children }) {
7
+ return (
8
+ <ClerkProvider
9
+ afterSignInUrl='/dashboard'
10
+ afterSignUpUrl='/welcome'
11
+ >
12
+ {children}
13
+ </ClerkProvider>
14
+ );
15
+ }
16
+ `,
17
+ output: `
18
+ import { ClerkProvider } from '@clerk/nextjs';
19
+
20
+ export function App({ children }) {
21
+ return (
22
+ <ClerkProvider
23
+ signInFallbackRedirectUrl='/dashboard'
24
+ signUpFallbackRedirectUrl='/welcome'
25
+ >
26
+ {children}
27
+ </ClerkProvider>
28
+ );
29
+ }
30
+ `
31
+ }, {
32
+ name: 'SignIn legacy props',
33
+ source: `
34
+ import { SignIn as MySignIn } from '@clerk/nextjs';
35
+
36
+ export const Page = () => (
37
+ <MySignIn
38
+ afterSignInUrl='/home'
39
+ afterSignUpUrl='/after-sign-up'
40
+ fallbackRedirectUrl='/existing'
41
+ />
42
+ );
43
+ `,
44
+ output: `
45
+ import { SignIn as MySignIn } from '@clerk/nextjs';
46
+
47
+ export const Page = () => (
48
+ <MySignIn
49
+ signUpFallbackRedirectUrl='/after-sign-up'
50
+ fallbackRedirectUrl='/existing' />
51
+ );
52
+ `
53
+ }, {
54
+ name: 'SignUp legacy props',
55
+ source: `
56
+ import { SignUp } from '@clerk/react';
57
+
58
+ export function Example() {
59
+ return (
60
+ <SignUp afterSignUpUrl='/done' afterSignInUrl='/in' />
61
+ );
62
+ }
63
+ `,
64
+ output: `
65
+ import { SignUp } from '@clerk/react';
66
+
67
+ export function Example() {
68
+ return (<SignUp fallbackRedirectUrl='/done' signInFallbackRedirectUrl='/in' />);
69
+ }
70
+ `
71
+ }, {
72
+ name: 'ClerkProvider redirectUrl only',
73
+ source: `
74
+ import { ClerkProvider } from '@clerk/react';
75
+
76
+ export const Provider = ({ children }) => (
77
+ <ClerkProvider redirectUrl='/legacy'>{children}</ClerkProvider>
78
+ );
79
+ `,
80
+ output: `
81
+ import { ClerkProvider } from '@clerk/react';
82
+
83
+ export const Provider = ({ children }) => (
84
+ <ClerkProvider signInFallbackRedirectUrl="/legacy" signUpFallbackRedirectUrl="/legacy">{children}</ClerkProvider>
85
+ );
86
+ `
87
+ }, {
88
+ name: 'SignIn redirectUrl only',
89
+ source: `
90
+ import { SignIn } from '@clerk/nextjs';
91
+
92
+ export const Page = () => <SignIn redirectUrl='/legacy' />;
93
+ `,
94
+ output: `
95
+ import { SignIn } from '@clerk/nextjs';
96
+
97
+ export const Page = () => <SignIn fallbackRedirectUrl="/legacy" />;
98
+ `
99
+ }, {
100
+ name: 'UserButton and organization props',
101
+ source: `
102
+ import { UserButton, OrganizationSwitcher, CreateOrganization } from '@clerk/react';
103
+
104
+ export const Actions = () => (
105
+ <>
106
+ <UserButton afterSignOutUrl='/bye' afterMultiSessionSingleSignOutUrl='/multi' />
107
+ <OrganizationSwitcher hideSlug afterSwitchOrganizationUrl='/org' />
108
+ <CreateOrganization hideSlug />
109
+ </>
110
+ );
111
+ `,
112
+ output: `
113
+ import { UserButton, OrganizationSwitcher, CreateOrganization } from '@clerk/react';
114
+
115
+ export const Actions = () => (
116
+ <>
117
+ <UserButton />
118
+ <OrganizationSwitcher afterSelectOrganizationUrl='/org' />
119
+ <CreateOrganization />
120
+ </>
121
+ );
122
+ `
123
+ }, {
124
+ name: 'Object literals and destructuring',
125
+ source: `
126
+ const config = {
127
+ afterSignInUrl: '/one',
128
+ afterSignUpUrl: '/two',
129
+ activeSessions,
130
+ };
131
+
132
+ const { afterSignInUrl, afterSignUpUrl: custom, activeSessions: current } = config;
133
+ `,
134
+ output: `
135
+ const config = {
136
+ signInFallbackRedirectUrl: '/one',
137
+ signUpFallbackRedirectUrl: '/two',
138
+ signedInSessions: activeSessions,
139
+ };
140
+
141
+ const { signInFallbackRedirectUrl: afterSignInUrl, signUpFallbackRedirectUrl: custom, signedInSessions: current } = config;
142
+ `
143
+ }, {
144
+ name: 'Member expressions and optional chaining',
145
+ source: `
146
+ const signInTarget = options.afterSignInUrl;
147
+ const signUpTarget = options?.afterSignUpUrl;
148
+ const fallback = options['afterSignInUrl'];
149
+ const hasSessions = client?.activeSessions?.length > 0 && client['activeSessions'];
150
+ `,
151
+ output: `
152
+ const signInTarget = options.signInFallbackRedirectUrl;
153
+ const signUpTarget = options?.signUpFallbackRedirectUrl;
154
+ const fallback = options["signInFallbackRedirectUrl"];
155
+ const hasSessions = client?.signedInSessions?.length > 0 && client["signedInSessions"];
156
+ `
157
+ }, {
158
+ name: 'setActive beforeEmit callback',
159
+ source: `
160
+ await setActive({
161
+ session: '123',
162
+ beforeEmit: handleBeforeEmit,
163
+ });
164
+ `,
165
+ output: `
166
+ await setActive({
167
+ session: '123',
168
+ navigate: params => handleBeforeEmit(params.session),
169
+ });
170
+ `
171
+ }, {
172
+ name: 'ClerkMiddlewareAuthObject type rename',
173
+ source: `
174
+ import type { ClerkMiddlewareAuthObject } from '@clerk/nextjs/server';
175
+
176
+ type Handler = (auth: ClerkMiddlewareAuthObject) => void;
177
+ `,
178
+ output: `
179
+ import type { ClerkMiddlewareSessionAuthObject } from '@clerk/nextjs/server';
180
+
181
+ type Handler = (auth: ClerkMiddlewareSessionAuthObject) => void;
182
+ `
183
+ }, {
184
+ name: 'Namespace import support',
185
+ source: `
186
+ import * as Clerk from '@clerk/nextjs';
187
+
188
+ export const Provider = ({ children }) => (
189
+ <Clerk.ClerkProvider redirectUrl='/deep' />
190
+ );
191
+ `,
192
+ output: `
193
+ import * as Clerk from '@clerk/nextjs';
194
+
195
+ export const Provider = ({ children }) => (
196
+ <Clerk.ClerkProvider signInFallbackRedirectUrl="/deep" signUpFallbackRedirectUrl="/deep" />
197
+ );
198
+ `
199
+ }];
@@ -0,0 +1,15 @@
1
+ import { applyTransform } from 'jscodeshift/dist/testUtils';
2
+ import { describe, expect, it } from 'vitest';
3
+ import transformer from '../transform-remove-deprecated-props.cjs';
4
+ import { fixtures } from './__fixtures__/transform-remove-deprecated-props.fixtures';
5
+ describe('transform-remove-deprecated-props', () => {
6
+ it.each(fixtures)('$name', ({
7
+ source,
8
+ output
9
+ }) => {
10
+ const result = applyTransform(transformer, {}, {
11
+ source
12
+ });
13
+ expect(result).toEqual(output.trim());
14
+ });
15
+ });
@@ -0,0 +1,428 @@
1
+ const CLERK_PACKAGE_PREFIX = '@clerk/';
2
+ const COMPONENTS_WITH_HIDE_SLUG = new Set(['CreateOrganization', 'OrganizationSwitcher', 'OrganizationList']);
3
+ const COMPONENT_RENAMES = new Map([['ClerkProvider', {
4
+ afterSignInUrl: 'signInFallbackRedirectUrl',
5
+ afterSignUpUrl: 'signUpFallbackRedirectUrl'
6
+ }], ['SignIn', {
7
+ afterSignInUrl: 'fallbackRedirectUrl',
8
+ afterSignUpUrl: 'signUpFallbackRedirectUrl'
9
+ }], ['SignUp', {
10
+ afterSignInUrl: 'signInFallbackRedirectUrl',
11
+ afterSignUpUrl: 'fallbackRedirectUrl'
12
+ }]]);
13
+ const COMPONENT_REDIRECT_ATTR = new Map([['ClerkProvider', {
14
+ targetAttrs: ['signInFallbackRedirectUrl', 'signUpFallbackRedirectUrl']
15
+ }], ['SignIn', {
16
+ targetAttrs: ['fallbackRedirectUrl']
17
+ }], ['SignUp', {
18
+ targetAttrs: ['fallbackRedirectUrl']
19
+ }]]);
20
+ const COMPONENTS_WITH_USER_BUTTON_REMOVALS = new Map([['UserButton', ['afterSignOutUrl', 'afterMultiSessionSingleSignOutUrl']]]);
21
+ const ORGANIZATION_SWITCHER_RENAMES = new Map([['afterSwitchOrganizationUrl', 'afterSelectOrganizationUrl']]);
22
+ module.exports = function transformDeprecatedProps({
23
+ source
24
+ }, {
25
+ jscodeshift: j
26
+ }) {
27
+ const root = j(source);
28
+ let dirty = false;
29
+ const {
30
+ namedImports,
31
+ namespaceImports
32
+ } = collectClerkImports(root, j);
33
+ root.find(j.JSXOpeningElement).forEach(path => {
34
+ const canonicalName = getCanonicalComponentName(path.node.name, namedImports, namespaceImports);
35
+ if (!canonicalName) {
36
+ return;
37
+ }
38
+ const jsxNode = path.node;
39
+ if (COMPONENTS_WITH_HIDE_SLUG.has(canonicalName)) {
40
+ if (removeJsxAttribute(j, jsxNode, 'hideSlug')) {
41
+ dirty = true;
42
+ }
43
+ }
44
+ if (COMPONENTS_WITH_USER_BUTTON_REMOVALS.has(canonicalName)) {
45
+ for (const attrName of COMPONENTS_WITH_USER_BUTTON_REMOVALS.get(canonicalName)) {
46
+ if (removeJsxAttribute(j, jsxNode, attrName)) {
47
+ dirty = true;
48
+ }
49
+ }
50
+ }
51
+ if (COMPONENT_RENAMES.has(canonicalName)) {
52
+ const renameMap = COMPONENT_RENAMES.get(canonicalName);
53
+ for (const [oldName, newName] of Object.entries(renameMap)) {
54
+ if (renameJsxAttribute(j, jsxNode, oldName, newName)) {
55
+ dirty = true;
56
+ }
57
+ }
58
+ }
59
+ if (COMPONENT_REDIRECT_ATTR.has(canonicalName)) {
60
+ if (handleRedirectAttribute(j, jsxNode, canonicalName)) {
61
+ dirty = true;
62
+ }
63
+ }
64
+ if (canonicalName === 'OrganizationSwitcher') {
65
+ for (const [oldName, newName] of ORGANIZATION_SWITCHER_RENAMES) {
66
+ if (renameJsxAttribute(j, jsxNode, oldName, newName)) {
67
+ dirty = true;
68
+ }
69
+ }
70
+ }
71
+ });
72
+ if (renameObjectProperties(root, j, 'afterSignInUrl', 'signInFallbackRedirectUrl')) {
73
+ dirty = true;
74
+ }
75
+ if (renameObjectProperties(root, j, 'afterSignUpUrl', 'signUpFallbackRedirectUrl')) {
76
+ dirty = true;
77
+ }
78
+ if (renameMemberExpressions(root, j, 'afterSignInUrl', 'signInFallbackRedirectUrl')) {
79
+ dirty = true;
80
+ }
81
+ if (renameMemberExpressions(root, j, 'afterSignUpUrl', 'signUpFallbackRedirectUrl')) {
82
+ dirty = true;
83
+ }
84
+ if (renameTSPropertySignatures(root, j, 'afterSignInUrl', 'signInFallbackRedirectUrl')) {
85
+ dirty = true;
86
+ }
87
+ if (renameTSPropertySignatures(root, j, 'afterSignUpUrl', 'signUpFallbackRedirectUrl')) {
88
+ dirty = true;
89
+ }
90
+ if (renameTSPropertySignatures(root, j, 'activeSessions', 'signedInSessions')) {
91
+ dirty = true;
92
+ }
93
+ if (renameMemberExpressions(root, j, 'activeSessions', 'signedInSessions')) {
94
+ dirty = true;
95
+ }
96
+ if (renameObjectProperties(root, j, 'activeSessions', 'signedInSessions')) {
97
+ dirty = true;
98
+ }
99
+ if (transformSetActiveBeforeEmit(root, j)) {
100
+ dirty = true;
101
+ }
102
+ if (renameTypeReferences(root, j, 'ClerkMiddlewareAuthObject', 'ClerkMiddlewareSessionAuthObject')) {
103
+ dirty = true;
104
+ }
105
+ return dirty ? root.toSource() : undefined;
106
+ };
107
+ module.exports.parser = 'tsx';
108
+ function collectClerkImports(root, j) {
109
+ const namedImports = new Map();
110
+ const namespaceImports = new Set();
111
+ root.find(j.ImportDeclaration).forEach(path => {
112
+ const sourceVal = path.node.source.value;
113
+ if (typeof sourceVal !== 'string' || !sourceVal.startsWith(CLERK_PACKAGE_PREFIX)) {
114
+ return;
115
+ }
116
+ for (const specifier of path.node.specifiers || []) {
117
+ if (j.ImportSpecifier.check(specifier)) {
118
+ const localName = specifier.local ? specifier.local.name : specifier.imported.name;
119
+ namedImports.set(localName, specifier.imported.name);
120
+ } else if (j.ImportNamespaceSpecifier.check(specifier) || j.ImportDefaultSpecifier.check(specifier)) {
121
+ namespaceImports.add(specifier.local.name);
122
+ }
123
+ }
124
+ });
125
+ return {
126
+ namedImports,
127
+ namespaceImports
128
+ };
129
+ }
130
+ function getCanonicalComponentName(nameNode, namedImports, namespaceImports) {
131
+ if (!nameNode) {
132
+ return null;
133
+ }
134
+ if (nameNode.type === 'JSXIdentifier') {
135
+ return namedImports.get(nameNode.name) || nameNode.name;
136
+ }
137
+ if (nameNode.type === 'JSXMemberExpression') {
138
+ const identifierName = getNamespaceMemberName(nameNode, namespaceImports);
139
+ if (identifierName) {
140
+ return identifierName;
141
+ }
142
+ }
143
+ return null;
144
+ }
145
+ function getNamespaceMemberName(memberNode, namespaceImports) {
146
+ if (memberNode.object.type === 'JSXIdentifier') {
147
+ return namespaceImports.has(memberNode.object.name) ? memberNode.property.name : null;
148
+ }
149
+ if (memberNode.object.type === 'JSXMemberExpression') {
150
+ const resolved = getNamespaceMemberName(memberNode.object, namespaceImports);
151
+ return resolved ? memberNode.property.name : null;
152
+ }
153
+ return null;
154
+ }
155
+ function renameJsxAttribute(j, jsxNode, oldName, newName) {
156
+ if (!jsxNode.attributes) {
157
+ return false;
158
+ }
159
+ const attrIndex = jsxNode.attributes.findIndex(attr => isJsxAttrNamed(attr, oldName));
160
+ if (attrIndex === -1) {
161
+ return false;
162
+ }
163
+ const targetExists = jsxNode.attributes.some(attr => isJsxAttrNamed(attr, newName));
164
+ if (targetExists) {
165
+ jsxNode.attributes.splice(attrIndex, 1);
166
+ return true;
167
+ }
168
+ const attribute = jsxNode.attributes[attrIndex];
169
+ attribute.name.name = newName;
170
+ return true;
171
+ }
172
+ function removeJsxAttribute(j, jsxNode, name) {
173
+ if (!jsxNode.attributes) {
174
+ return false;
175
+ }
176
+ const initialLength = jsxNode.attributes.length;
177
+ jsxNode.attributes = jsxNode.attributes.filter(attr => !isJsxAttrNamed(attr, name));
178
+ return jsxNode.attributes.length !== initialLength;
179
+ }
180
+ function isJsxAttrNamed(attribute, name) {
181
+ return attribute && attribute.type === 'JSXAttribute' && attribute.name && attribute.name.name === name;
182
+ }
183
+ function handleRedirectAttribute(j, jsxNode, canonicalName) {
184
+ if (!jsxNode.attributes) {
185
+ return false;
186
+ }
187
+ const data = COMPONENT_REDIRECT_ATTR.get(canonicalName);
188
+ const attrIndex = jsxNode.attributes.findIndex(attr => isJsxAttrNamed(attr, 'redirectUrl'));
189
+ if (attrIndex === -1) {
190
+ return false;
191
+ }
192
+ const redirectAttr = jsxNode.attributes[attrIndex];
193
+ const insertions = [];
194
+ for (const targetName of data.targetAttrs) {
195
+ if (!jsxNode.attributes.some(attr => isJsxAttrNamed(attr, targetName))) {
196
+ insertions.push(createJsxAttributeWithClonedValue(j, targetName, redirectAttr.value));
197
+ }
198
+ }
199
+ jsxNode.attributes.splice(attrIndex, 1, ...insertions);
200
+ return true;
201
+ }
202
+ function createJsxAttributeWithClonedValue(j, name, value) {
203
+ let clonedValue = null;
204
+ if (value) {
205
+ clonedValue = clone(value);
206
+ }
207
+ return j.jsxAttribute(j.jsxIdentifier(name), clonedValue);
208
+ }
209
+ function clone(node) {
210
+ return node ? JSON.parse(JSON.stringify(node)) : node;
211
+ }
212
+ function renameObjectProperties(root, j, oldName, newName) {
213
+ let changed = false;
214
+ root.find(j.ObjectProperty).forEach(path => {
215
+ if (!isPropertyKeyNamed(path.node.key, oldName)) {
216
+ return;
217
+ }
218
+ const parent = path.parentPath && path.parentPath.node;
219
+ const isPattern = parent && parent.type === 'ObjectPattern';
220
+ const originalLocalName = getLocalIdentifierName(path.node);
221
+ if (path.node.shorthand) {
222
+ path.node.shorthand = false;
223
+ const identifierName = originalLocalName || oldName;
224
+ path.node.value = j.identifier(identifierName);
225
+ }
226
+ if (path.node.key.type === 'Identifier') {
227
+ path.node.key.name = newName;
228
+ } else if (path.node.key.type === 'StringLiteral') {
229
+ path.node.key.value = newName;
230
+ } else if (path.node.key.type === 'Literal') {
231
+ path.node.key.value = newName;
232
+ }
233
+ changed = true;
234
+ });
235
+ return changed;
236
+ }
237
+ function getLocalIdentifierName(propertyNode) {
238
+ if (!propertyNode) {
239
+ return null;
240
+ }
241
+ if (propertyNode.value && propertyNode.value.type === 'Identifier') {
242
+ return propertyNode.value.name;
243
+ }
244
+ if (propertyNode.shorthand && propertyNode.key && propertyNode.key.type === 'Identifier') {
245
+ return propertyNode.key.name;
246
+ }
247
+ return null;
248
+ }
249
+ function isPropertyKeyNamed(keyNode, name) {
250
+ if (!keyNode) {
251
+ return false;
252
+ }
253
+ if (keyNode.type === 'Identifier') {
254
+ return keyNode.name === name;
255
+ }
256
+ if (keyNode.type === 'StringLiteral' || keyNode.type === 'Literal') {
257
+ return keyNode.value === name;
258
+ }
259
+ return false;
260
+ }
261
+ function renameMemberExpressions(root, j, oldName, newName) {
262
+ let changed = false;
263
+ root.find(j.MemberExpression, {
264
+ property: {
265
+ type: 'Identifier',
266
+ name: oldName
267
+ },
268
+ computed: false
269
+ }).forEach(path => {
270
+ path.node.property.name = newName;
271
+ changed = true;
272
+ });
273
+ root.find(j.MemberExpression, {
274
+ computed: true
275
+ }).forEach(path => {
276
+ if (path.node.property.type === 'Literal' && path.node.property.value === oldName) {
277
+ path.node.property.value = newName;
278
+ changed = true;
279
+ }
280
+ if (path.node.property.type === 'StringLiteral' && path.node.property.value === oldName) {
281
+ path.node.property.value = newName;
282
+ changed = true;
283
+ }
284
+ });
285
+ root.find(j.OptionalMemberExpression, {
286
+ property: {
287
+ type: 'Identifier',
288
+ name: oldName
289
+ },
290
+ computed: false
291
+ }).forEach(path => {
292
+ path.node.property.name = newName;
293
+ changed = true;
294
+ });
295
+ root.find(j.OptionalMemberExpression, {
296
+ computed: true
297
+ }).forEach(path => {
298
+ if (path.node.property.type === 'Literal' && path.node.property.value === oldName) {
299
+ path.node.property.value = newName;
300
+ changed = true;
301
+ }
302
+ if (path.node.property.type === 'StringLiteral' && path.node.property.value === oldName) {
303
+ path.node.property.value = newName;
304
+ changed = true;
305
+ }
306
+ });
307
+ return changed;
308
+ }
309
+ function renameTSPropertySignatures(root, j, oldName, newName) {
310
+ let changed = false;
311
+ root.find(j.TSPropertySignature).forEach(path => {
312
+ if (!isPropertyKeyNamed(path.node.key, oldName)) {
313
+ return;
314
+ }
315
+ if (path.node.key.type === 'Identifier') {
316
+ path.node.key.name = newName;
317
+ } else if (path.node.key.type === 'StringLiteral') {
318
+ path.node.key.value = newName;
319
+ }
320
+ changed = true;
321
+ });
322
+ return changed;
323
+ }
324
+ function transformSetActiveBeforeEmit(root, j) {
325
+ let changed = false;
326
+ root.find(j.CallExpression).filter(path => isSetActiveCall(path.node.callee, j)).forEach(path => {
327
+ const [args0] = path.node.arguments;
328
+ if (!args0 || args0.type !== 'ObjectExpression') {
329
+ return;
330
+ }
331
+ const beforeEmitIndex = args0.properties.findIndex(prop => isPropertyNamed(prop, 'beforeEmit'));
332
+ if (beforeEmitIndex === -1) {
333
+ return;
334
+ }
335
+ const beforeEmitProp = args0.properties[beforeEmitIndex];
336
+ if (!beforeEmitProp || beforeEmitProp.type !== 'ObjectProperty') {
337
+ return;
338
+ }
339
+ const originalValue = getPropertyValueExpression(beforeEmitProp.value, j);
340
+ if (!originalValue) {
341
+ args0.properties.splice(beforeEmitIndex, 1);
342
+ changed = true;
343
+ return;
344
+ }
345
+ const navigateProp = j.objectProperty(j.identifier('navigate'), buildNavigateArrowFunction(j, originalValue));
346
+ args0.properties.splice(beforeEmitIndex, 1, navigateProp);
347
+ changed = true;
348
+ });
349
+ return changed;
350
+ }
351
+ function isSetActiveCall(callee, j) {
352
+ if (!callee) {
353
+ return false;
354
+ }
355
+ if (callee.type === 'Identifier') {
356
+ return callee.name === 'setActive';
357
+ }
358
+ if (callee.type === 'MemberExpression' || callee.type === 'OptionalMemberExpression') {
359
+ const property = callee.property;
360
+ return property && property.type === 'Identifier' && property.name === 'setActive';
361
+ }
362
+ return false;
363
+ }
364
+ function isPropertyNamed(prop, name) {
365
+ return prop && prop.type === 'ObjectProperty' && isPropertyKeyNamed(prop.key, name);
366
+ }
367
+ function getPropertyValueExpression(valueNode, j) {
368
+ if (!valueNode) {
369
+ return null;
370
+ }
371
+ if (valueNode.type === 'JSXExpressionContainer') {
372
+ return valueNode.expression;
373
+ }
374
+ return valueNode;
375
+ }
376
+ function buildNavigateArrowFunction(j, originalExpression) {
377
+ const paramIdentifier = j.identifier('params');
378
+ const calleeExpression = clone(originalExpression);
379
+ const callExpression = j.callExpression(calleeExpression, [j.memberExpression(paramIdentifier, j.identifier('session'))]);
380
+ return j.arrowFunctionExpression([paramIdentifier], callExpression);
381
+ }
382
+ function renameTypeReferences(root, j, oldName, newName) {
383
+ let changed = false;
384
+ root.find(j.ImportSpecifier).forEach(path => {
385
+ const imported = path.node.imported;
386
+ if (imported && imported.type === 'Identifier' && imported.name === oldName) {
387
+ imported.name = newName;
388
+ if (path.node.local && path.node.local.name === oldName) {
389
+ path.node.local.name = newName;
390
+ }
391
+ changed = true;
392
+ }
393
+ });
394
+ root.find(j.TSTypeReference).forEach(path => {
395
+ if (renameEntityName(path.node.typeName, oldName, newName)) {
396
+ changed = true;
397
+ }
398
+ });
399
+ root.find(j.TSExpressionWithTypeArguments).forEach(path => {
400
+ if (renameEntityName(path.node.expression, oldName, newName)) {
401
+ changed = true;
402
+ }
403
+ });
404
+ root.find(j.TSQualifiedName).forEach(path => {
405
+ if (path.node.right.type === 'Identifier' && path.node.right.name === oldName) {
406
+ path.node.right.name = newName;
407
+ changed = true;
408
+ }
409
+ });
410
+ return changed;
411
+ }
412
+ function renameEntityName(entity, oldName, newName) {
413
+ if (!entity) {
414
+ return false;
415
+ }
416
+ if (entity.type === 'Identifier' && entity.name === oldName) {
417
+ entity.name = newName;
418
+ return true;
419
+ }
420
+ if (entity.type === 'TSQualifiedName') {
421
+ if (entity.right.type === 'Identifier' && entity.right.name === oldName) {
422
+ entity.right.name = newName;
423
+ return true;
424
+ }
425
+ return renameEntityName(entity.left, oldName, newName);
426
+ }
427
+ return false;
428
+ }
@@ -7,6 +7,11 @@ import { Codemod } from './Codemod.js';
7
7
  import { Command } from './Command.js';
8
8
  import { Header } from './Header.js';
9
9
  import { UpgradeSDK } from './UpgradeSDK.js';
10
+ const CODEMODS = {
11
+ ASYNC_REQUEST: 'transform-async-request',
12
+ CLERK_REACT_V6: 'transform-clerk-react-v6',
13
+ REMOVE_DEPRECATED_PROPS: 'transform-remove-deprecated-props'
14
+ };
10
15
  function versionNeedsUpgrade(sdk, version) {
11
16
  if (sdk === 'clerk-react' && version === 5) {
12
17
  return true;
@@ -50,95 +55,180 @@ export function SDKWorkflow(props) {
50
55
  }, "@clerk/", sdk), " at the moment.");
51
56
  }
52
57
  if (sdk === 'nextjs') {
53
- // Right now, we only have one codemod for the `@clerk/nextjs` async request transformation
54
- return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Header, null), /*#__PURE__*/React.createElement(Text, null, "Clerk SDK used: ", /*#__PURE__*/React.createElement(Text, {
55
- color: "green"
56
- }, "@clerk/", sdk)), /*#__PURE__*/React.createElement(Text, null, "Migrating from version: ", /*#__PURE__*/React.createElement(Text, {
57
- color: "green"
58
- }, version)), runCodemod ? /*#__PURE__*/React.createElement(Text, null, "Executing codemod: ", /*#__PURE__*/React.createElement(Text, {
59
- color: "green"
60
- }, "yes")) : null, /*#__PURE__*/React.createElement(Newline, null), version === 5 && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(UpgradeSDK, {
61
- callback: setUpgradeComplete,
62
- sdk: sdk
63
- }), upgradeComplete ? /*#__PURE__*/React.createElement(Codemod, {
64
- callback: setDone,
58
+ return /*#__PURE__*/React.createElement(NextjsWorkflow, {
59
+ done: done,
60
+ runCodemod: runCodemod,
65
61
  sdk: sdk,
66
- transform: "transform-async-request"
67
- }) : null), version === 6 && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(UpgradeSDK, {
68
- callback: setUpgradeComplete,
69
- sdk: sdk
70
- }), upgradeComplete ? /*#__PURE__*/React.createElement(Codemod, {
71
- callback: setDone,
72
- sdk: sdk,
73
- transform: "transform-clerk-react-v6"
74
- }) : null), version === 7 && /*#__PURE__*/React.createElement(React.Fragment, null, runCodemod ? /*#__PURE__*/React.createElement(Codemod, {
75
- sdk: sdk,
76
- callback: setDone,
77
- transform: "transform-clerk-react-v6"
78
- }) : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Text, null, "Looks like you are already on the latest version of ", /*#__PURE__*/React.createElement(Text, {
79
- bold: true
80
- }, "@clerk/", sdk), ". Would you like to run the associated codemod?"), /*#__PURE__*/React.createElement(Select, {
81
- options: [{
82
- label: 'yes',
83
- value: 'yes'
84
- }, {
85
- label: 'no',
86
- value: 'no'
87
- }],
88
- onChange: value => {
89
- if (value === 'yes') {
90
- setRunCodemod(true);
91
- } else {
92
- setDone(true);
93
- }
94
- }
95
- }))), done && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(StatusMessage, {
96
- variant: "success"
97
- }, "Done upgrading ", /*#__PURE__*/React.createElement(Text, {
98
- bold: true
99
- }, "@clerk/nextjs")), /*#__PURE__*/React.createElement(Command, {
100
- cmd: 'grep -rE "import.*\\\\{.*useAuth.*\\\\}.*from.*[\'\\\\\\"]@clerk/nextjs[\'\\\\\\"]" . --exclude-dir={node_modules,dist}',
101
- message: /*#__PURE__*/React.createElement(Spinner, {
102
- label: 'Checking for `useAuth` usage in your project...'
103
- }),
104
- onError: () => null,
105
- onSuccess: () => /*#__PURE__*/React.createElement(StatusMessage, {
106
- variant: "warning"
107
- }, /*#__PURE__*/React.createElement(Text, null, "We have detected that your application might be using the ", /*#__PURE__*/React.createElement(Text, {
108
- bold: true
109
- }, "useAuth"), " hook from", ' ', /*#__PURE__*/React.createElement(Text, {
110
- bold: true
111
- }, "@clerk/nextjs"), "."), /*#__PURE__*/React.createElement(Newline, null), /*#__PURE__*/React.createElement(Text, null, "If usages of this hook are server-side rendered, you might need to add the ", /*#__PURE__*/React.createElement(Text, {
112
- bold: true
113
- }, "dynamic"), ' ', "prop to your application's root ", /*#__PURE__*/React.createElement(Text, {
114
- bold: true
115
- }, "ClerkProvider"), "."), /*#__PURE__*/React.createElement(Newline, null), /*#__PURE__*/React.createElement(Text, null, "You can find more information about this change in the Clerk documentation at", ' ', /*#__PURE__*/React.createElement(Link, {
116
- url: "https://clerk.com/docs/references/nextjs/rendering-modes"
117
- }, "https://clerk.com/docs/references/nextjs/rendering-modes"), "."))
118
- })));
62
+ setDone: setDone,
63
+ setRunCodemod: setRunCodemod,
64
+ setUpgradeComplete: setUpgradeComplete,
65
+ upgradeComplete: upgradeComplete,
66
+ version: version
67
+ });
119
68
  }
120
69
  if (['clerk-react', 'clerk-expo', 'react-router', 'tanstack-react-start'].includes(sdk)) {
121
- const replacePackage = sdk === 'clerk-react' || sdk === 'clerk-expo';
122
- return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Header, null), /*#__PURE__*/React.createElement(Text, null, "Clerk SDK used: ", /*#__PURE__*/React.createElement(Text, {
123
- color: "green"
124
- }, "@clerk/", sdk)), /*#__PURE__*/React.createElement(Text, null, "Migrating from version: ", /*#__PURE__*/React.createElement(Text, {
125
- color: "green"
126
- }, version)), runCodemod ? /*#__PURE__*/React.createElement(Text, null, "Executing codemod: ", /*#__PURE__*/React.createElement(Text, {
127
- color: "green"
128
- }, "yes")) : null, /*#__PURE__*/React.createElement(Newline, null), versionNeedsUpgrade(sdk, version) && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(UpgradeSDK, {
129
- callback: setUpgradeComplete,
130
- sdk: sdk,
131
- replacePackage: replacePackage
132
- }), upgradeComplete ? /*#__PURE__*/React.createElement(Codemod, {
133
- callback: setDone,
70
+ return /*#__PURE__*/React.createElement(ReactSdkWorkflow, {
71
+ done: done,
72
+ runCodemod: runCodemod,
134
73
  sdk: sdk,
135
- transform: "transform-clerk-react-v6"
136
- }) : null), done && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(StatusMessage, {
137
- variant: "success"
138
- }, replacePackage ? /*#__PURE__*/React.createElement(React.Fragment, null, "Done upgrading to ", /*#__PURE__*/React.createElement(Text, {
74
+ setDone: setDone,
75
+ setRunCodemod: setRunCodemod,
76
+ setUpgradeComplete: setUpgradeComplete,
77
+ upgradeComplete: upgradeComplete,
78
+ version: version
79
+ });
80
+ }
81
+ }
82
+ function NextjsWorkflow({
83
+ done,
84
+ runCodemod,
85
+ sdk,
86
+ setDone,
87
+ setRunCodemod,
88
+ setUpgradeComplete,
89
+ upgradeComplete,
90
+ version
91
+ }) {
92
+ const [v6CodemodComplete, setV6CodemodComplete] = useState(false);
93
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Header, null), /*#__PURE__*/React.createElement(Text, null, "Clerk SDK used: ", /*#__PURE__*/React.createElement(Text, {
94
+ color: "green"
95
+ }, "@clerk/", sdk)), /*#__PURE__*/React.createElement(Text, null, "Migrating from version: ", /*#__PURE__*/React.createElement(Text, {
96
+ color: "green"
97
+ }, version)), runCodemod ? /*#__PURE__*/React.createElement(Text, null, "Executing codemod: ", /*#__PURE__*/React.createElement(Text, {
98
+ color: "green"
99
+ }, "yes")) : null, /*#__PURE__*/React.createElement(Newline, null), version === 5 && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(UpgradeSDK, {
100
+ callback: setUpgradeComplete,
101
+ sdk: sdk
102
+ }), upgradeComplete ? /*#__PURE__*/React.createElement(Codemod, {
103
+ callback: setV6CodemodComplete,
104
+ sdk: sdk,
105
+ transform: CODEMODS.ASYNC_REQUEST
106
+ }) : null, v6CodemodComplete ? /*#__PURE__*/React.createElement(Codemod, {
107
+ callback: setDone,
108
+ sdk: sdk,
109
+ transform: CODEMODS.REMOVE_DEPRECATED_PROPS
110
+ }) : null), version === 6 && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(UpgradeSDK, {
111
+ callback: setUpgradeComplete,
112
+ sdk: sdk
113
+ }), upgradeComplete ? /*#__PURE__*/React.createElement(Codemod, {
114
+ callback: setV6CodemodComplete,
115
+ sdk: sdk,
116
+ transform: CODEMODS.CLERK_REACT_V6
117
+ }) : null, v6CodemodComplete ? /*#__PURE__*/React.createElement(Codemod, {
118
+ callback: setDone,
119
+ sdk: sdk,
120
+ transform: CODEMODS.REMOVE_DEPRECATED_PROPS
121
+ }) : null), version === 7 && /*#__PURE__*/React.createElement(React.Fragment, null, runCodemod ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Codemod, {
122
+ callback: setV6CodemodComplete,
123
+ sdk: sdk,
124
+ transform: CODEMODS.CLERK_REACT_V6
125
+ }), v6CodemodComplete ? /*#__PURE__*/React.createElement(Codemod, {
126
+ callback: setDone,
127
+ sdk: sdk,
128
+ transform: CODEMODS.REMOVE_DEPRECATED_PROPS
129
+ }) : null) : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Text, null, "Looks like you are already on the latest version of ", /*#__PURE__*/React.createElement(Text, {
130
+ bold: true
131
+ }, "@clerk/", sdk), ". Would you like to run the associated codemods?"), /*#__PURE__*/React.createElement(Select, {
132
+ onChange: value => {
133
+ if (value === 'yes') {
134
+ setRunCodemod(true);
135
+ } else {
136
+ setDone(true);
137
+ }
138
+ },
139
+ options: [{
140
+ label: 'yes',
141
+ value: 'yes'
142
+ }, {
143
+ label: 'no',
144
+ value: 'no'
145
+ }]
146
+ }))), done && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(StatusMessage, {
147
+ variant: "success"
148
+ }, "Done upgrading ", /*#__PURE__*/React.createElement(Text, {
149
+ bold: true
150
+ }, "@clerk/nextjs")), /*#__PURE__*/React.createElement(Command, {
151
+ cmd: 'grep -rE "import.*\\\\{.*useAuth.*\\\\}.*from.*[\'\\\\\\"]@clerk/nextjs[\'\\\\\\"]" . --exclude-dir={node_modules,dist}',
152
+ message: /*#__PURE__*/React.createElement(Spinner, {
153
+ label: 'Checking for `useAuth` usage in your project...'
154
+ }),
155
+ onError: () => null,
156
+ onSuccess: () => /*#__PURE__*/React.createElement(StatusMessage, {
157
+ variant: "warning"
158
+ }, /*#__PURE__*/React.createElement(Text, null, "We have detected that your application might be using the ", /*#__PURE__*/React.createElement(Text, {
139
159
  bold: true
140
- }, "@clerk/", sdk.replace('clerk-', ''))) : /*#__PURE__*/React.createElement(React.Fragment, null, "Done upgrading ", /*#__PURE__*/React.createElement(Text, {
160
+ }, "useAuth"), " hook from", ' ', /*#__PURE__*/React.createElement(Text, {
141
161
  bold: true
142
- }, "@clerk/", sdk)))));
143
- }
162
+ }, "@clerk/nextjs"), "."), /*#__PURE__*/React.createElement(Newline, null), /*#__PURE__*/React.createElement(Text, null, "If usages of this hook are server-side rendered, you might need to add the ", /*#__PURE__*/React.createElement(Text, {
163
+ bold: true
164
+ }, "dynamic"), ' ', "prop to your application's root ", /*#__PURE__*/React.createElement(Text, {
165
+ bold: true
166
+ }, "ClerkProvider"), "."), /*#__PURE__*/React.createElement(Newline, null), /*#__PURE__*/React.createElement(Text, null, "You can find more information about this change in the Clerk documentation at", ' ', /*#__PURE__*/React.createElement(Link, {
167
+ url: "https://clerk.com/docs/references/nextjs/rendering-modes"
168
+ }, "https://clerk.com/docs/references/nextjs/rendering-modes"), "."))
169
+ })));
170
+ }
171
+ function ReactSdkWorkflow({
172
+ done,
173
+ runCodemod,
174
+ sdk,
175
+ setDone,
176
+ setRunCodemod,
177
+ setUpgradeComplete,
178
+ upgradeComplete,
179
+ version
180
+ }) {
181
+ const [v6CodemodComplete, setV6CodemodComplete] = useState(false);
182
+ const replacePackage = sdk === 'clerk-react' || sdk === 'clerk-expo';
183
+ const needsUpgrade = versionNeedsUpgrade(sdk, version);
184
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Header, null), /*#__PURE__*/React.createElement(Text, null, "Clerk SDK used: ", /*#__PURE__*/React.createElement(Text, {
185
+ color: "green"
186
+ }, "@clerk/", sdk)), /*#__PURE__*/React.createElement(Text, null, "Migrating from version: ", /*#__PURE__*/React.createElement(Text, {
187
+ color: "green"
188
+ }, version)), runCodemod ? /*#__PURE__*/React.createElement(Text, null, "Executing codemod: ", /*#__PURE__*/React.createElement(Text, {
189
+ color: "green"
190
+ }, "yes")) : null, /*#__PURE__*/React.createElement(Newline, null), needsUpgrade && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(UpgradeSDK, {
191
+ callback: setUpgradeComplete,
192
+ replacePackage: replacePackage,
193
+ sdk: sdk
194
+ }), upgradeComplete ? /*#__PURE__*/React.createElement(Codemod, {
195
+ callback: setV6CodemodComplete,
196
+ sdk: sdk,
197
+ transform: CODEMODS.CLERK_REACT_V6
198
+ }) : null, v6CodemodComplete ? /*#__PURE__*/React.createElement(Codemod, {
199
+ callback: setDone,
200
+ sdk: sdk,
201
+ transform: CODEMODS.REMOVE_DEPRECATED_PROPS
202
+ }) : null), !needsUpgrade && /*#__PURE__*/React.createElement(React.Fragment, null, runCodemod ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Codemod, {
203
+ callback: setV6CodemodComplete,
204
+ sdk: sdk,
205
+ transform: CODEMODS.CLERK_REACT_V6
206
+ }), v6CodemodComplete ? /*#__PURE__*/React.createElement(Codemod, {
207
+ callback: setDone,
208
+ sdk: sdk,
209
+ transform: CODEMODS.REMOVE_DEPRECATED_PROPS
210
+ }) : null) : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Text, null, "Looks like you are already on the latest version of ", /*#__PURE__*/React.createElement(Text, {
211
+ bold: true
212
+ }, "@clerk/", sdk), ". Would you like to run the associated codemods?"), /*#__PURE__*/React.createElement(Select, {
213
+ onChange: value => {
214
+ if (value === 'yes') {
215
+ setRunCodemod(true);
216
+ } else {
217
+ setDone(true);
218
+ }
219
+ },
220
+ options: [{
221
+ label: 'yes',
222
+ value: 'yes'
223
+ }, {
224
+ label: 'no',
225
+ value: 'no'
226
+ }]
227
+ }))), done && /*#__PURE__*/React.createElement(StatusMessage, {
228
+ variant: "success"
229
+ }, replacePackage ? /*#__PURE__*/React.createElement(React.Fragment, null, "Done upgrading to ", /*#__PURE__*/React.createElement(Text, {
230
+ bold: true
231
+ }, "@clerk/", sdk.replace('clerk-', ''))) : /*#__PURE__*/React.createElement(React.Fragment, null, "Done upgrading ", /*#__PURE__*/React.createElement(Text, {
232
+ bold: true
233
+ }, "@clerk/", sdk))));
144
234
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clerk/upgrade",
3
- "version": "2.0.0-canary-core3.v20251203060337",
3
+ "version": "2.0.0-snapshot.v20251203152900",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/clerk/javascript.git",