@clerk/upgrade 0.0.1
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/README.md +25 -0
- package/dist/app.js +136 -0
- package/dist/cli.js +50 -0
- package/dist/constants/sdks.js +46 -0
- package/dist/constants/versions.js +7 -0
- package/dist/scan.js +103 -0
- package/dist/test.js +100 -0
- package/dist/util/expandable-list.js +143 -0
- package/dist/util/generate-changelog.js +28 -0
- package/dist/util/get-clerk-version.js +7 -0
- package/dist/util/guess-framework.js +22 -0
- package/dist/util/load-change.js +31 -0
- package/dist/util/step-sequencer.js +31 -0
- package/dist/util/test.js +100 -0
- package/dist/versions/v5/backend/clerk-import.md +15 -0
- package/dist/versions/v5/backend/clockskewinseconds.md +7 -0
- package/dist/versions/v5/backend/createclerkclient-apikey.md +21 -0
- package/dist/versions/v5/backend/createclerkclient-frontendapi.md +21 -0
- package/dist/versions/v5/backend/externalaccount-picture.md +0 -0
- package/dist/versions/v5/backend/externalaccountjson-avatarurl.md +0 -0
- package/dist/versions/v5/backend/getpendingorganizationinvitationlist.md +12 -0
- package/dist/versions/v5/backend/organization-logourl.md +0 -0
- package/dist/versions/v5/backend/organizationjson-logourl.md +0 -0
- package/dist/versions/v5/backend/organizationmembershippublicuserdata-profileimageurl.md +0 -0
- package/dist/versions/v5/backend/organizationmembershippublicuserdatajson-profileimageurl.md +0 -0
- package/dist/versions/v5/backend/pkgversion.md +0 -0
- package/dist/versions/v5/backend/user-profileimageurl.md +0 -0
- package/dist/versions/v5/backend/userjson-profileimageurl.md +0 -0
- package/dist/versions/v5/chromeExtension/clerkprovider-tokencache.md +26 -0
- package/dist/versions/v5/common/api-key-to-secret-key.md +6 -0
- package/dist/versions/v5/common/clerkprovider-frontendapi.md +7 -0
- package/dist/versions/v5/common/frontend-api-to-publishable-key.md +6 -0
- package/dist/versions/v5/common/handlemagiclinkverification.md +7 -0
- package/dist/versions/v5/common/ismagiclinkerror.md +7 -0
- package/dist/versions/v5/common/magiclinkerror.md +7 -0
- package/dist/versions/v5/common/magiclinkerrorcode.md +7 -0
- package/dist/versions/v5/common/navigate-to-routerpush-routerreplace.md +16 -0
- package/dist/versions/v5/common/setsession.md +32 -0
- package/dist/versions/v5/common/usemagiclink.md +7 -0
- package/dist/versions/v5/expo/apikey-to-publishable-key.md +6 -0
- package/dist/versions/v5/expo/clerkprovider-frontendapi.md +17 -0
- package/dist/versions/v5/fastify/api-url-value-change.md +6 -0
- package/dist/versions/v5/fastify/clerkplugin-frontendapi.md +17 -0
- package/dist/versions/v5/fastify/createclerkclient-apikey.md +17 -0
- package/dist/versions/v5/fastify/createclerkclient-frontendapi.md +17 -0
- package/dist/versions/v5/gatsby/api-url-value-change.md +6 -0
- package/dist/versions/v5/gatsby/apikey-to-publishable-key.md +6 -0
- package/dist/versions/v5/gatsby/createclerkclient-apikey.md +17 -0
- package/dist/versions/v5/gatsby/createclerkclient-frontendapi.md +17 -0
- package/dist/versions/v5/gatsby/withserverauth-return-type.md +43 -0
- package/dist/versions/v5/index.js +63 -0
- package/dist/versions/v5/js/afterswitchorganizationurl.md +15 -0
- package/dist/versions/v5/js/appearance-organizationpreview-organizationswitcher.md +8 -0
- package/dist/versions/v5/js/experimental-canusecaptcha.md +6 -0
- package/dist/versions/v5/js/experimental-captchasitekey.md +6 -0
- package/dist/versions/v5/js/experimental-captchaurl.md +6 -0
- package/dist/versions/v5/js/external-account-avatarurl.md +7 -0
- package/dist/versions/v5/js/getorganizationmemberships.md +14 -0
- package/dist/versions/v5/js/lastorganizationinvitation-member.md +6 -0
- package/dist/versions/v5/js/organization-create-string.md +15 -0
- package/dist/versions/v5/js/organization-getpendinginvitations.md +14 -0
- package/dist/versions/v5/js/organization-logourl.md +7 -0
- package/dist/versions/v5/js/redirecttohome.md +13 -0
- package/dist/versions/v5/js/signup-attemptweb3walletverification-generatedsignature.md +20 -0
- package/dist/versions/v5/js/unstable-invitationupdate.md +6 -0
- package/dist/versions/v5/js/unstable-membershipupdate.md +6 -0
- package/dist/versions/v5/js/useorganization-invitationlist.md +25 -0
- package/dist/versions/v5/js/useorganization-membershiplist.md +24 -0
- package/dist/versions/v5/js/useorganizations.md +26 -0
- package/dist/versions/v5/js/user-createexternalaccount-redirecturl.md +7 -0
- package/dist/versions/v5/js/user-orgpublicdata-profileimageurl.md +7 -0
- package/dist/versions/v5/js/user-update-password.md +19 -0
- package/dist/versions/v5/js/userprofile-prop.md +7 -0
- package/dist/versions/v5/next/api-url-value-change.md +6 -0
- package/dist/versions/v5/next/auth-middleware-deprecated.md +10 -0
- package/dist/versions/v5/next/authmiddleware-apikey.md +17 -0
- package/dist/versions/v5/next/authmiddleware-frontendapi.md +9 -0
- package/dist/versions/v5/next/clerk-js-version-next-public.md +8 -0
- package/dist/versions/v5/next/createclerkclient-apikey.md +17 -0
- package/dist/versions/v5/next/createclerkclient-frontendapi.md +17 -0
- package/dist/versions/v5/next/getauth-apikey.md +9 -0
- package/dist/versions/v5/next/import-api-url.md +7 -0
- package/dist/versions/v5/next/import-api-version.md +7 -0
- package/dist/versions/v5/next/import-clerk-js-url.md +7 -0
- package/dist/versions/v5/next/import-clerk-js-version.md +7 -0
- package/dist/versions/v5/next/import-domain.md +7 -0
- package/dist/versions/v5/next/import-is-satellite.md +7 -0
- package/dist/versions/v5/next/import-nextjs-api.md +22 -0
- package/dist/versions/v5/next/import-nextjs-app-beta.md +10 -0
- package/dist/versions/v5/next/import-nextjs-edge-middleware.md +6 -0
- package/dist/versions/v5/next/import-nextjs-edge-middlewarefiles.md +6 -0
- package/dist/versions/v5/next/import-nextjs-ssr.md +7 -0
- package/dist/versions/v5/next/import-proxy-url.md +7 -0
- package/dist/versions/v5/next/import-publishable-key.md +7 -0
- package/dist/versions/v5/next/import-secret-key.md +7 -0
- package/dist/versions/v5/next/import-sign-in-url.md +7 -0
- package/dist/versions/v5/next/import-sign-up-url.md +6 -0
- package/dist/versions/v5/next/with-clerk-middleware-removed.md +10 -0
- package/dist/versions/v5/node/api-url-value-change.md +6 -0
- package/dist/versions/v5/node/cjs-esm-instance.md +16 -0
- package/dist/versions/v5/node/clerkexpressrequireauth-apikey.md +17 -0
- package/dist/versions/v5/node/clerkexpressrequireauth-frontendapi.md +17 -0
- package/dist/versions/v5/node/clerkexpresswithauth-apikey.md +17 -0
- package/dist/versions/v5/node/clerkexpresswithauth-frontendapi.md +17 -0
- package/dist/versions/v5/node/createclerkclient-apikey.md +17 -0
- package/dist/versions/v5/node/createclerkclient-frontendapi.md +17 -0
- package/dist/versions/v5/node/createclerkexpressrequireauth-apikey.md +17 -0
- package/dist/versions/v5/node/createclerkexpressrequireauth-frontendapi.md +17 -0
- package/dist/versions/v5/node/createclerkexpresswithauth-apikey.md +17 -0
- package/dist/versions/v5/node/createclerkexpresswithauth-frontendapi.md +17 -0
- package/dist/versions/v5/node/package-rename.md +6 -0
- package/dist/versions/v5/node/setclerkapikey.md +17 -0
- package/dist/versions/v5/node/setclerkapiversion.md +17 -0
- package/dist/versions/v5/node/setclerkhttpoptions.md +17 -0
- package/dist/versions/v5/node/setclerkserverapiurl.md +20 -0
- package/dist/versions/v5/react/api-url-value-change.md +6 -0
- package/dist/versions/v5/shared/buildrequesturl.md +14 -0
- package/dist/versions/v5/shared/organizationcontext.md +7 -0
- package/dist/versions/v5/shared/useorganizationlist-organizationlist.md +19 -0
- package/package.json +63 -0
package/README.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# @clerk/upgrade
|
|
2
|
+
|
|
3
|
+
A tool that helps with upgrading major versions of Clerk's SDKs.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx @clerk/upgrade
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Caveats
|
|
12
|
+
|
|
13
|
+
This tool uses regular expressions to scan for patterns that match breaking changes. This makes it run substantially faster and makes it more accessible for us at Clerk to author matchers for each breaking change, however it means that _we cannot gurarantee 100% accuracy of the results_. As such, it's important to treat this as a tool that can help you to complete your major version upgrades, rather than an automatic fix to all issues.
|
|
14
|
+
|
|
15
|
+
The main thing that this tool will miss is cases where _unusual import patterns_ are used in your codebase.As an example, if we made a breaking change to the `getAuth` function exported from `@clerk/nextjs`, we would likely look for something like `import { getAuth } from "@clerk/nextjs"` in order to detect whether you need to make some changes. If you were running your imports like `import * as ClerkNext from "@clerk/nextjs"`, you could use `getAuth` without us detecting it with our matcher.
|
|
16
|
+
|
|
17
|
+
It will also be very likely to miss if you bind a method on an object to a separate variable and call it from there, or pass a bound method through a function param. For example, something like this:
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
const updateUser = user.update.bind(user);
|
|
21
|
+
|
|
22
|
+
updateUser({ username: 'foo' });
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Overall, there's a very good chance that this tool catches everything, but it's not a guarantee, so make sure that you also test your app before deploying, and that you have good e2e test coverage, which are good practices normally anyway, rather than blindly trusting that since the clerk upgrade tool was run, you are for sure covered.
|
package/dist/app.js
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { Text, Newline } from 'ink';
|
|
3
|
+
import { Select, MultiSelect, TextInput } from '@inkjs/ui';
|
|
4
|
+
import SDKS from './constants/sdks.js';
|
|
5
|
+
import VERSIONS from './constants/versions.js';
|
|
6
|
+
import Scan from './scan.js';
|
|
7
|
+
import guessFrameworks from './util/guess-framework.js';
|
|
8
|
+
import getClerkMajorVersion from './util/get-clerk-version.js';
|
|
9
|
+
import Gradient from 'ink-gradient';
|
|
10
|
+
import BigText from 'ink-big-text';
|
|
11
|
+
export default function App({
|
|
12
|
+
_fromVersion,
|
|
13
|
+
_toVersion,
|
|
14
|
+
_sdk,
|
|
15
|
+
_dir = false,
|
|
16
|
+
_ignore = []
|
|
17
|
+
}) {
|
|
18
|
+
const [sdks, setSdks] = useState(_sdk ? [_sdk] : []);
|
|
19
|
+
const [sdkGuesses, setSdkGuesses] = useState([]);
|
|
20
|
+
const [sdkGuessConfirmed, setSdkGuessConfirmed] = useState(false);
|
|
21
|
+
const [sdkGuessAttempted, setSdkGuessAttempted] = useState(false);
|
|
22
|
+
const [fromVersion, setFromVersion] = useState(_fromVersion);
|
|
23
|
+
const [fromVersionGuessAttempted, fromVersionSdkGuessAttempted] = useState(false);
|
|
24
|
+
const [toVersion, setToVersion] = useState(_toVersion);
|
|
25
|
+
const [dir, setDir] = useState(_dir);
|
|
26
|
+
const [ignore, setIgnore] = useState(_ignore);
|
|
27
|
+
const [configComplete, setConfigComplete] = useState(false);
|
|
28
|
+
const [configVerified, setConfigVerified] = useState(false);
|
|
29
|
+
let fromVersionGuess = false;
|
|
30
|
+
|
|
31
|
+
// We try to guess which SDK they are using
|
|
32
|
+
if (isEmpty(sdks) && isEmpty(sdkGuesses) && !sdkGuessAttempted) {
|
|
33
|
+
if (!dir) return setDir(process.cwd());
|
|
34
|
+
setSdkGuesses(guessFrameworks(dir)); // this is the suspect line
|
|
35
|
+
setSdkGuessAttempted(true);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// We try to guess which version of Clerk they are using
|
|
39
|
+
if (!fromVersion && !fromVersionGuess && !fromVersionGuessAttempted) {
|
|
40
|
+
fromVersionGuess = getClerkMajorVersion();
|
|
41
|
+
setFromVersionGuessAttempted(true);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// No support for v3 or below, sadly
|
|
45
|
+
if (parseInt(fromVersion) < 4) {
|
|
46
|
+
return /*#__PURE__*/React.createElement(Text, {
|
|
47
|
+
color: "red"
|
|
48
|
+
}, "We're so sorry, but this tool only supports migration from version 4 and above.");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// If they are trying to/from the same version, that's an error
|
|
52
|
+
if (parseInt(fromVersion) === parseInt(toVersion)) {
|
|
53
|
+
return /*#__PURE__*/React.createElement(Text, {
|
|
54
|
+
color: "red"
|
|
55
|
+
}, "You are already on version ", toVersion, ", so there's no need to migrate!");
|
|
56
|
+
}
|
|
57
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Gradient, {
|
|
58
|
+
name: "vice"
|
|
59
|
+
}, /*#__PURE__*/React.createElement(BigText, {
|
|
60
|
+
text: "Clerk Upgrade",
|
|
61
|
+
font: "tiny"
|
|
62
|
+
})), !configComplete && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Text, null, /*#__PURE__*/React.createElement(Text, {
|
|
63
|
+
color: "blue"
|
|
64
|
+
}, "Hello friend!"), " We're excited to help you upgrade Clerk", fromVersion ? ` from v${fromVersion}` : '', toVersion ? ` to v${toVersion}` : '', ". Before we get started, a couple questions..."), /*#__PURE__*/React.createElement(Newline, null)), isEmpty(sdks) && !isEmpty(sdkGuesses) && !sdkGuessConfirmed && /*#__PURE__*/React.createElement(React.Fragment, null, sdkGuesses.length > 1 ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Text, null, "It looks like you are using the following Clerk SDKs in your project:"), sdkGuesses.map(guess => /*#__PURE__*/React.createElement(Text, {
|
|
65
|
+
key: guess.value
|
|
66
|
+
}, ' ', "- ", guess.label)), /*#__PURE__*/React.createElement(Text, null, "Is that right?")) : /*#__PURE__*/React.createElement(Text, null, "It looks like you are using the \"", sdkGuesses[0].label, "\" Clerk SDK in your project. Is that right?"), /*#__PURE__*/React.createElement(Select, {
|
|
67
|
+
options: [{
|
|
68
|
+
label: 'yes',
|
|
69
|
+
value: 'yes'
|
|
70
|
+
}, {
|
|
71
|
+
label: 'no',
|
|
72
|
+
value: 'no'
|
|
73
|
+
}],
|
|
74
|
+
onChange: item => {
|
|
75
|
+
setSdkGuessConfirmed(true);
|
|
76
|
+
// if true, we were right so we set the sdk
|
|
77
|
+
if (item === 'yes') setSdks(sdkGuesses.map(guess => guess.value));
|
|
78
|
+
}
|
|
79
|
+
})), isEmpty(sdks) && isEmpty(sdkGuesses) && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Text, null, "Please select which Clerk SDK(s) you're using for your app:"), /*#__PURE__*/React.createElement(Text, {
|
|
80
|
+
color: "gray"
|
|
81
|
+
}, "(select with space bar, multiple can be selected, press enter when finished)"), /*#__PURE__*/React.createElement(MultiSelect, {
|
|
82
|
+
options: SDKS,
|
|
83
|
+
onSubmit: value => setSdks(value),
|
|
84
|
+
visibleOptionCount: SDKS.length
|
|
85
|
+
})), !isEmpty(sdks) > 0 && fromVersion && toVersion && !dir && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Text, null, "Where would you like for us to scan for files in your project?"), /*#__PURE__*/React.createElement(Text, {
|
|
86
|
+
color: "gray"
|
|
87
|
+
}, "(globstar syntax supported)"), /*#__PURE__*/React.createElement(TextInput, {
|
|
88
|
+
defaultValue: "**/*",
|
|
89
|
+
onSubmit: val => setDir(val)
|
|
90
|
+
})), !isEmpty(sdks) && fromVersion && toVersion && dir && isEmpty(ignore) && !configComplete && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Text, null, "Are there any files or directories you'd like to ignore? If so, you can add them below, separated by commas. We ignore \"node_modules\" and \".git\" by default."), /*#__PURE__*/React.createElement(Text, {
|
|
91
|
+
color: "gray"
|
|
92
|
+
}, "(globstar syntax supported)"), /*#__PURE__*/React.createElement(TextInput, {
|
|
93
|
+
placeholder: "docs/**, images/**",
|
|
94
|
+
defaultValue: ignore,
|
|
95
|
+
onSubmit: val => {
|
|
96
|
+
setIgnore(val.includes(',') ? val.split(/\s*,\s*/) : [].concat(val));
|
|
97
|
+
setConfigComplete(true);
|
|
98
|
+
}
|
|
99
|
+
})), configComplete && !configVerified && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Text, null, "Ok, here's our configuration:"), /*#__PURE__*/React.createElement(Newline, null), /*#__PURE__*/React.createElement(Text, null, "Clerk ", sdks.length > 1 ? 'SDKs' : 'SDK', " used:", /*#__PURE__*/React.createElement(Text, {
|
|
100
|
+
color: "green"
|
|
101
|
+
}, " ", sdks.toString())), /*#__PURE__*/React.createElement(Text, null, "Migrating from", /*#__PURE__*/React.createElement(Text, {
|
|
102
|
+
color: "green"
|
|
103
|
+
}, " v", fromVersion, " "), "to", /*#__PURE__*/React.createElement(Text, {
|
|
104
|
+
color: "green"
|
|
105
|
+
}, " v", toVersion)), /*#__PURE__*/React.createElement(Text, null, "Looking in the directory", /*#__PURE__*/React.createElement(Text, {
|
|
106
|
+
color: "green"
|
|
107
|
+
}, " ", dir, " "), ignore.length > 0 && /*#__PURE__*/React.createElement(React.Fragment, null, "and ignoring", /*#__PURE__*/React.createElement(Text, {
|
|
108
|
+
color: "green"
|
|
109
|
+
}, " ", ignore.join(', ')))), /*#__PURE__*/React.createElement(Newline, null), /*#__PURE__*/React.createElement(Text, null, "Does this look right?"), /*#__PURE__*/React.createElement(Select, {
|
|
110
|
+
options: [{
|
|
111
|
+
label: 'yes',
|
|
112
|
+
value: true
|
|
113
|
+
}, {
|
|
114
|
+
label: 'no - exit, and i will try again',
|
|
115
|
+
value: false
|
|
116
|
+
}],
|
|
117
|
+
onChange: value => {
|
|
118
|
+
if (!value) {
|
|
119
|
+
process.exit();
|
|
120
|
+
} else {
|
|
121
|
+
setConfigVerified(true);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
})), configVerified && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Scan, {
|
|
125
|
+
fromVersion,
|
|
126
|
+
toVersion,
|
|
127
|
+
sdks,
|
|
128
|
+
dir,
|
|
129
|
+
ignore
|
|
130
|
+
})));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// small util to make the logic blocks easier to visually parse
|
|
134
|
+
function isEmpty(arr) {
|
|
135
|
+
return !arr.length;
|
|
136
|
+
}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { render } from 'ink';
|
|
4
|
+
import meow from 'meow';
|
|
5
|
+
import App from './app.js';
|
|
6
|
+
import sdks from './constants/sdks.js';
|
|
7
|
+
const cli = meow(`
|
|
8
|
+
Usage
|
|
9
|
+
$ clerk-upgrade
|
|
10
|
+
|
|
11
|
+
Options
|
|
12
|
+
--from Major version number you're upgrading from
|
|
13
|
+
--to Major version number you're upgrading to
|
|
14
|
+
--sdk Name of the SDK you're upgrading
|
|
15
|
+
--dir Directory you'd like to scan for files
|
|
16
|
+
--ignore Any files or directories you'd like to ignore
|
|
17
|
+
|
|
18
|
+
Examples
|
|
19
|
+
$ clerk-upgrade --from=4 --to=5 --sdk=nextjs --dir=src/**
|
|
20
|
+
Hello, Jane
|
|
21
|
+
`, {
|
|
22
|
+
importMeta: import.meta,
|
|
23
|
+
flags: {
|
|
24
|
+
from: {
|
|
25
|
+
type: 'string',
|
|
26
|
+
default: '4'
|
|
27
|
+
},
|
|
28
|
+
to: {
|
|
29
|
+
type: 'string',
|
|
30
|
+
default: '5'
|
|
31
|
+
},
|
|
32
|
+
sdk: {
|
|
33
|
+
type: 'string',
|
|
34
|
+
choices: sdks.map(i => i.value)
|
|
35
|
+
},
|
|
36
|
+
dir: {
|
|
37
|
+
type: 'string'
|
|
38
|
+
},
|
|
39
|
+
ignore: {
|
|
40
|
+
type: 'string',
|
|
41
|
+
isMultiple: true
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
render( /*#__PURE__*/React.createElement(App, {
|
|
46
|
+
_fromVersion: cli.flags.from,
|
|
47
|
+
_toVersion: cli.flags.to,
|
|
48
|
+
_sdk: cli.flags.sdk,
|
|
49
|
+
_dir: cli.flags.dir
|
|
50
|
+
}));
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export default [{
|
|
2
|
+
label: '@clerk/nextjs',
|
|
3
|
+
value: 'nextjs'
|
|
4
|
+
}, {
|
|
5
|
+
label: '@clerk/remix',
|
|
6
|
+
value: 'remix'
|
|
7
|
+
}, {
|
|
8
|
+
label: 'gatsby-plugin-clerk',
|
|
9
|
+
value: 'gatsby'
|
|
10
|
+
}, {
|
|
11
|
+
label: '@clerk/redwood',
|
|
12
|
+
value: 'redwood'
|
|
13
|
+
}, {
|
|
14
|
+
label: '@clerk/react',
|
|
15
|
+
value: 'react'
|
|
16
|
+
}, {
|
|
17
|
+
label: '@clerk/expo',
|
|
18
|
+
value: 'expo'
|
|
19
|
+
}, {
|
|
20
|
+
label: '@clerk/fastify',
|
|
21
|
+
value: 'fastify'
|
|
22
|
+
}, {
|
|
23
|
+
label: '@clerk/express',
|
|
24
|
+
value: 'express'
|
|
25
|
+
}, {
|
|
26
|
+
label: '@clerk/clerk-js',
|
|
27
|
+
value: 'js'
|
|
28
|
+
}, {
|
|
29
|
+
label: '@clerk/clerk-sdk-node',
|
|
30
|
+
value: 'node'
|
|
31
|
+
}, {
|
|
32
|
+
label: '@clerk/backend',
|
|
33
|
+
value: 'backend'
|
|
34
|
+
}, {
|
|
35
|
+
label: '@clerk/localizations',
|
|
36
|
+
value: 'localizations'
|
|
37
|
+
}, {
|
|
38
|
+
label: '@clerk/shared',
|
|
39
|
+
value: 'shared'
|
|
40
|
+
}, {
|
|
41
|
+
label: '@clerk/types',
|
|
42
|
+
value: 'types'
|
|
43
|
+
}, {
|
|
44
|
+
label: '@clerk/chrome-extension',
|
|
45
|
+
value: 'chromeExtension'
|
|
46
|
+
}];
|
package/dist/scan.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import { Text, Newline, Box } from 'ink';
|
|
3
|
+
import { globby } from 'globby';
|
|
4
|
+
import fs from 'fs/promises';
|
|
5
|
+
import { ProgressBar } from '@inkjs/ui';
|
|
6
|
+
import indexToPosition from 'index-to-position';
|
|
7
|
+
import ExpandableList from './util/expandable-list.js';
|
|
8
|
+
export default function Scan({
|
|
9
|
+
fromVersion,
|
|
10
|
+
toVersion,
|
|
11
|
+
sdks,
|
|
12
|
+
dir,
|
|
13
|
+
ignore
|
|
14
|
+
}) {
|
|
15
|
+
// NOTE: if the difference between fromVersion and toVersion is greater than 1
|
|
16
|
+
// we need to do a little extra work here and import two matchers,
|
|
17
|
+
// sequence them after each other, and clearly mark which version migration
|
|
18
|
+
// applies to each log.
|
|
19
|
+
//
|
|
20
|
+
// This is not yet implemented though since the current state of the script
|
|
21
|
+
// only handles a single version.
|
|
22
|
+
const [status, setStatus] = useState('Initializing');
|
|
23
|
+
const [progress, setProgress] = useState(0);
|
|
24
|
+
const [complete, setComplete] = useState(false);
|
|
25
|
+
const [matchers, setMatchers] = useState();
|
|
26
|
+
const [files, setFiles] = useState();
|
|
27
|
+
const [results, setResults] = useState([]);
|
|
28
|
+
|
|
29
|
+
// Load matchers
|
|
30
|
+
// -------------
|
|
31
|
+
// result = `matchers` set to format:
|
|
32
|
+
// { sdkName: [{ title: 'x', matcher: /x/, slug: 'x', ... }] }
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
setStatus(`Loading data for v${toVersion} migration`);
|
|
35
|
+
import(`./versions/v${toVersion}/index.js`).then(version => {
|
|
36
|
+
setMatchers(sdks.reduce((m, sdk) => {
|
|
37
|
+
m[sdk] = version.default[sdk];
|
|
38
|
+
return m;
|
|
39
|
+
}, {}));
|
|
40
|
+
});
|
|
41
|
+
}, [toVersion]);
|
|
42
|
+
|
|
43
|
+
// Get all files from the glob matcher
|
|
44
|
+
// -----------------------------------
|
|
45
|
+
// result = `files` set to format: ['/filename', '/other/filename']
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
setStatus('Collecting files to scan');
|
|
48
|
+
ignore.push('node_modules/**', '**/node_modules/**', '.git/**', 'package.json', 'package-lock.json', 'yarn.lock', 'pnpm-lock.yaml');
|
|
49
|
+
globby(dir, {
|
|
50
|
+
ignore: [...ignore.filter(x => x)]
|
|
51
|
+
}).then(files => setFiles(files));
|
|
52
|
+
}, [dir, ignore]);
|
|
53
|
+
|
|
54
|
+
// Read files and scan regexes
|
|
55
|
+
// ---------------------------
|
|
56
|
+
// result = `results` set to format
|
|
57
|
+
//
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
if (!matchers || !files) return;
|
|
60
|
+
Promise.all(
|
|
61
|
+
// first we read all the files
|
|
62
|
+
files.map(async (file, idx) => {
|
|
63
|
+
setStatus(`Scanning ${file}`);
|
|
64
|
+
setProgress(Math.ceil(idx / files.length * 100));
|
|
65
|
+
const content = await fs.readFile(file, 'utf8');
|
|
66
|
+
|
|
67
|
+
// then we run each of the matchers against the file contents
|
|
68
|
+
// TODO: combine results on the same match, add multiple file/positions
|
|
69
|
+
for (const sdk in matchers) {
|
|
70
|
+
matchers[sdk].map(matcher => {
|
|
71
|
+
const matches = content.matchAll(matcher.matcher);
|
|
72
|
+
if (!matches) return;
|
|
73
|
+
Array.from(matches).map(match => {
|
|
74
|
+
// TODO: index should be converted to line/col
|
|
75
|
+
results.push({
|
|
76
|
+
sdk,
|
|
77
|
+
file,
|
|
78
|
+
position: indexToPosition(content, match.index),
|
|
79
|
+
...matcher
|
|
80
|
+
});
|
|
81
|
+
setResults(results);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
})).then(() => {
|
|
86
|
+
setComplete(true);
|
|
87
|
+
if (results.length < 1) {
|
|
88
|
+
setStatus('It looks like you have nothing you need to change, upgrade away!');
|
|
89
|
+
} else {
|
|
90
|
+
setStatus('File scan complete. See results below!');
|
|
91
|
+
}
|
|
92
|
+
}).catch(err => {
|
|
93
|
+
console.error(err);
|
|
94
|
+
});
|
|
95
|
+
}, [matchers, files]);
|
|
96
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, complete ? /*#__PURE__*/React.createElement(Text, {
|
|
97
|
+
color: "green"
|
|
98
|
+
}, "\u2713 ", status) : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ProgressBar, {
|
|
99
|
+
value: progress
|
|
100
|
+
}), /*#__PURE__*/React.createElement(Text, null, status)), /*#__PURE__*/React.createElement(Newline, null), !!results.length && /*#__PURE__*/React.createElement(ExpandableList, {
|
|
101
|
+
items: results
|
|
102
|
+
}));
|
|
103
|
+
}
|
package/dist/test.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import React, { useReducer, useMemo } from 'react';
|
|
2
|
+
import { Text, Newline, useInput, Box, render } from 'ink';
|
|
3
|
+
function ExpandableList({
|
|
4
|
+
items
|
|
5
|
+
}) {
|
|
6
|
+
// add focused/expanded state on the set of items
|
|
7
|
+
const initialItems = useMemo(() => {
|
|
8
|
+
return items.map((i, idx) => {
|
|
9
|
+
i.focused = idx === 0 ? true : false;
|
|
10
|
+
i.expanded = false;
|
|
11
|
+
return i;
|
|
12
|
+
});
|
|
13
|
+
}, [items]);
|
|
14
|
+
|
|
15
|
+
// set up the focus/expanded state machine
|
|
16
|
+
const [state, dispatch] = useReducer(reducer, initialItems);
|
|
17
|
+
|
|
18
|
+
// this is what lets us respond to keyboard input
|
|
19
|
+
useInput((input, key) => {
|
|
20
|
+
if (key.downArrow) {
|
|
21
|
+
dispatch({
|
|
22
|
+
type: 'focus-next-option'
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
if (key.upArrow) {
|
|
26
|
+
dispatch({
|
|
27
|
+
type: 'focus-previous-option'
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
if (input === ' ') {
|
|
31
|
+
dispatch({
|
|
32
|
+
type: 'toggle-focused-option'
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// and here's the actual markup we render for each list item!
|
|
38
|
+
return state.map(item => {
|
|
39
|
+
return /*#__PURE__*/React.createElement(Box, {
|
|
40
|
+
borderStyle: "round",
|
|
41
|
+
flexDirection: "column",
|
|
42
|
+
borderColor: item.focused ? 'blue' : 'white',
|
|
43
|
+
key: item.title
|
|
44
|
+
}, /*#__PURE__*/React.createElement(Text, {
|
|
45
|
+
bold: true
|
|
46
|
+
}, item.title), /*#__PURE__*/React.createElement(Text, null, "Location: ", result.file, ":", result.position.line, ":", result.position.column), item.expanded && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Newline, null), /*#__PURE__*/React.createElement(Text, {
|
|
47
|
+
color: "gray"
|
|
48
|
+
}, "changed in ", item.sdk, " SDK"), /*#__PURE__*/React.createElement(Link, {
|
|
49
|
+
url: item.link
|
|
50
|
+
}, /*#__PURE__*/React.createElement(Text, null, "Migration guide entry \xBB")), /*#__PURE__*/React.createElement(Text, null, item.content)));
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// I'd like to recognize that this logic is kinda crazy, but it works 💖
|
|
55
|
+
function reducer(state, action) {
|
|
56
|
+
// if the current item is focused and a next item exists
|
|
57
|
+
// un-focus it and tee up the next one to be focused
|
|
58
|
+
if (action.type === 'focus-next-option') {
|
|
59
|
+
let nextIdx;
|
|
60
|
+
return state.map((item, idx) => {
|
|
61
|
+
if (item.focused && state[idx + 1]) {
|
|
62
|
+
nextIdx = idx + 1;
|
|
63
|
+
item.focused = false;
|
|
64
|
+
return item;
|
|
65
|
+
}
|
|
66
|
+
if (idx === nextIdx) {
|
|
67
|
+
item.focused = true;
|
|
68
|
+
return item;
|
|
69
|
+
}
|
|
70
|
+
return item;
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// if the next item is focused, focus this one and tee up the next one to be un-focused
|
|
75
|
+
if (action.type === 'focus-previous-option') {
|
|
76
|
+
let nextIdx;
|
|
77
|
+
return state.map((item, idx) => {
|
|
78
|
+
if (state[idx + 1]?.focused) {
|
|
79
|
+
item.focused = true;
|
|
80
|
+
nextIdx = idx + 1;
|
|
81
|
+
return item;
|
|
82
|
+
}
|
|
83
|
+
if (idx === nextIdx) {
|
|
84
|
+
item.focused = false;
|
|
85
|
+
return item;
|
|
86
|
+
}
|
|
87
|
+
return item;
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// if the space bar is hit, toggle expand/contract on the currently focused item
|
|
92
|
+
if (action.type === 'toggle-focused-option') {
|
|
93
|
+
return state.map(item => {
|
|
94
|
+
if (item.focused) {
|
|
95
|
+
item.expanded = !item.expanded;
|
|
96
|
+
}
|
|
97
|
+
return item;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import React, { useReducer, useMemo } from 'react';
|
|
2
|
+
import { Text, Newline, useInput, Box } from 'ink';
|
|
3
|
+
import Link from 'ink-link';
|
|
4
|
+
import Markdown from 'ink-markdown';
|
|
5
|
+
|
|
6
|
+
// A listing of items which can be navigated with arrow keys and expanded/contracted
|
|
7
|
+
// with space bar. Limits the number visible at a time to prevent rendering issues with
|
|
8
|
+
// super long lists
|
|
9
|
+
export default function ExpandableList({
|
|
10
|
+
items,
|
|
11
|
+
numberVisible = 10
|
|
12
|
+
}) {
|
|
13
|
+
// set up our little state machine
|
|
14
|
+
const [state, dispatch] = useReducer(reducer, items, items => {
|
|
15
|
+
// add focused/expanded state on the set of items
|
|
16
|
+
const all = items.map((i, idx) => {
|
|
17
|
+
i.focused = idx === 0 ? true : false;
|
|
18
|
+
i.expanded = false;
|
|
19
|
+
return i;
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// start idx, end idx
|
|
23
|
+
const visible = [0, numberVisible];
|
|
24
|
+
return {
|
|
25
|
+
numberVisible,
|
|
26
|
+
all,
|
|
27
|
+
visible
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// this is what lets us respond to keyboard input
|
|
32
|
+
useInput((input, key) => {
|
|
33
|
+
if (key.downArrow) {
|
|
34
|
+
dispatch({
|
|
35
|
+
type: 'focus-next-option'
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
if (key.upArrow) {
|
|
39
|
+
dispatch({
|
|
40
|
+
type: 'focus-previous-option'
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
if (input === ' ') {
|
|
44
|
+
dispatch({
|
|
45
|
+
type: 'toggle-focused-option'
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// and here's the actual markup we render for each list item!
|
|
51
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Text, {
|
|
52
|
+
color: "blue"
|
|
53
|
+
}, "Navigation Instructions:"), /*#__PURE__*/React.createElement(Text, null, "Navigate through items with \u2191 and \u2193 arrow keys. Expand the details of any item with space bar. \u2193 key on the last item goes to the next page, \u2191 on the first item goes to the previous page. To exit this interface, use \"control + c\"."), /*#__PURE__*/React.createElement(Newline, null), state.all.reduce((memo, item, idx) => {
|
|
54
|
+
if (idx < state.visible[0] || idx >= state.visible[1]) return memo;
|
|
55
|
+
const loc = `${item.file}:${item.position.line}:${item.position.column}`;
|
|
56
|
+
memo.push( /*#__PURE__*/React.createElement(Box, {
|
|
57
|
+
borderStyle: item.focused ? 'double' : 'single',
|
|
58
|
+
flexDirection: "column",
|
|
59
|
+
borderColor: item.focused ? 'blue' : 'white',
|
|
60
|
+
paddingX: 1,
|
|
61
|
+
key: loc
|
|
62
|
+
}, /*#__PURE__*/React.createElement(Markdown, null, item.title), /*#__PURE__*/React.createElement(Text, null, "Location: ", loc), item.expanded && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Newline, null), /*#__PURE__*/React.createElement(Markdown, null, item.content), /*#__PURE__*/React.createElement(Link, {
|
|
63
|
+
url: item.link
|
|
64
|
+
}, /*#__PURE__*/React.createElement(Text, null, "See in migration guide \xBB")))));
|
|
65
|
+
return memo;
|
|
66
|
+
}, []), state.all.length > state.numberVisible && /*#__PURE__*/React.createElement(Text, null, "Showing ", state.visible[0] + 1, " - ", Math.min(state.visible[1], state.all.length), " of ", state.all.length));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// I'd like to recognize that this logic is kinda crazy, but it works 💖
|
|
70
|
+
function reducer(state, action) {
|
|
71
|
+
if (action.type === 'focus-next-option') {
|
|
72
|
+
let nextIdx;
|
|
73
|
+
|
|
74
|
+
// if the current item is focused and a next item exists
|
|
75
|
+
// un-focus it and tee up the next one to be focused
|
|
76
|
+
const all = state.all.map((item, idx) => {
|
|
77
|
+
if (item.focused && state.all[idx + 1]) {
|
|
78
|
+
nextIdx = idx + 1;
|
|
79
|
+
item.focused = false;
|
|
80
|
+
return item;
|
|
81
|
+
}
|
|
82
|
+
if (idx === nextIdx) {
|
|
83
|
+
item.focused = true;
|
|
84
|
+
return item;
|
|
85
|
+
}
|
|
86
|
+
return item;
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// if we're scrolling past the last item in the list, shift the visible window
|
|
90
|
+
let visible = state.visible;
|
|
91
|
+
if (nextIdx >= state.visible[1]) {
|
|
92
|
+
visible = [state.visible[0] + state.numberVisible, state.visible[1] + state.numberVisible];
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
all,
|
|
96
|
+
visible,
|
|
97
|
+
numberVisible: state.numberVisible
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
if (action.type === 'focus-previous-option') {
|
|
101
|
+
let nextIdx;
|
|
102
|
+
|
|
103
|
+
// if the next item is focused, focus this one and tee up the next one to be un-focused
|
|
104
|
+
const all = state.all.map((item, idx) => {
|
|
105
|
+
if (state.all[idx + 1]?.focused) {
|
|
106
|
+
item.focused = true;
|
|
107
|
+
nextIdx = idx + 1;
|
|
108
|
+
return item;
|
|
109
|
+
}
|
|
110
|
+
if (idx === nextIdx) {
|
|
111
|
+
item.focused = false;
|
|
112
|
+
return item;
|
|
113
|
+
}
|
|
114
|
+
return item;
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// if we're scrolling to before the first item in the list, shift the visible window
|
|
118
|
+
let visible = state.visible;
|
|
119
|
+
if (nextIdx - 1 < state.visible[0]) {
|
|
120
|
+
visible = [state.visible[0] - state.numberVisible, state.visible[1] - state.numberVisible];
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
all,
|
|
124
|
+
visible,
|
|
125
|
+
numberVisible: state.numberVisible
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// if the space bar is hit, toggle expand/contract on the currently focused item
|
|
130
|
+
if (action.type === 'toggle-focused-option') {
|
|
131
|
+
const all = state.all.map(item => {
|
|
132
|
+
if (item.focused) {
|
|
133
|
+
item.expanded = !item.expanded;
|
|
134
|
+
}
|
|
135
|
+
return item;
|
|
136
|
+
});
|
|
137
|
+
return {
|
|
138
|
+
all,
|
|
139
|
+
visible: state.visible,
|
|
140
|
+
numberVisible: state.numberVisible
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import SDKS from '../constants/sdks.js';
|
|
2
|
+
import { parseInline } from 'marked';
|
|
3
|
+
const VERSION = 'v5';
|
|
4
|
+
async function generate() {
|
|
5
|
+
let output = '';
|
|
6
|
+
output += `# Clerk SDKs ${VERSION} Changelog\n\n`;
|
|
7
|
+
output += `Below is a listing of all the changes made to Clerk SDKs in ${VERSION} - each section describes the changes to one SDK. Note that some changes may be repeated between different SDKs.\n\n`;
|
|
8
|
+
const data = (await import(`../versions/${VERSION}/index.js`)).default;
|
|
9
|
+
for (let sdk in data) {
|
|
10
|
+
output += `### ${getSdkName(sdk)}\n\n---\n\n`;
|
|
11
|
+
data[sdk].map(entry => {
|
|
12
|
+
// Note: make sure to add a custom anchor link here to match the cli output
|
|
13
|
+
// anchor should be `entry.slug`
|
|
14
|
+
output += `<details>
|
|
15
|
+
<summary>${parseInline(entry.title)}</summary>
|
|
16
|
+
|
|
17
|
+
Regex matcher: \`${entry.matcher}\`
|
|
18
|
+
|
|
19
|
+
${entry.content}
|
|
20
|
+
</details>\n\n`;
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
return output;
|
|
24
|
+
}
|
|
25
|
+
generate().then(console.log);
|
|
26
|
+
function getSdkName(val) {
|
|
27
|
+
return SDKS.find(sdk => val === sdk.value).label;
|
|
28
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { readPackageSync } from 'read-pkg';
|
|
2
|
+
import semverRegex from 'semver-regex';
|
|
3
|
+
export default function getClerkMajorVersion() {
|
|
4
|
+
const pkg = readPackageSync();
|
|
5
|
+
const clerk = pkg.dependencies.clerk;
|
|
6
|
+
return clerk ? semverRegex.exec(clerk)[0][0] : false;
|
|
7
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { readPackageSync } from 'read-pkg';
|
|
2
|
+
import SDKS from '../constants/sdks.js';
|
|
3
|
+
export default function guessFrameworks(dir) {
|
|
4
|
+
const pkg = readPackageSync({
|
|
5
|
+
cwd: dir
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
// no guessing if there are no deps
|
|
9
|
+
if (!pkg.dependencies && !pkg.devDependencies) return [];
|
|
10
|
+
const deps = pkg.dependencies ? Object.keys(pkg.dependencies) : [];
|
|
11
|
+
const devDeps = pkg.devDependencies ? Object.keys(pkg.devDependencies) : [];
|
|
12
|
+
return SDKS.reduce((m, {
|
|
13
|
+
label,
|
|
14
|
+
value
|
|
15
|
+
}) => {
|
|
16
|
+
if (deps.includes(label) || devDeps.includes(label)) m.push({
|
|
17
|
+
label,
|
|
18
|
+
value
|
|
19
|
+
});
|
|
20
|
+
return m;
|
|
21
|
+
}, []);
|
|
22
|
+
}
|