-
-
Notifications
You must be signed in to change notification settings - Fork 9
feat(add): init Guided provider setup #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+567
−255
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
efa78e6
Adds `auth add <provider>` command
joshnuss 610b801
Extracts logic for requiring framework
joshnuss aa10436
Adds framework detection to `auth add`
joshnuss fb2fc62
Refactors to use provider names from lib/meta
joshnuss d84e471
Computes urls for base and callbacks
joshnuss 6c8ae1b
Prompts and opens setup page in browser
joshnuss 31a4813
Adds prompt to copy callback url to clipboard
joshnuss e84de0f
Prompts for client id & secret and writes env
joshnuss 6685f22
Fixes base url
joshnuss 89d2057
Masks client secret input
joshnuss aa0c75a
suggestions
balazsorban44 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
// @ts-check | ||
|
||
import * as y from "yoctocolors" | ||
import open from "open" | ||
import clipboard from "clipboardy" | ||
import { select, input, password } from "@inquirer/prompts" | ||
import { requireFramework } from "../lib/detect.js" | ||
import { updateEnvFile } from "../lib/write-env.js" | ||
import { providers, frameworks } from "../lib/meta.js" | ||
import { secret } from "./index.js" | ||
import { link, markdownToAnsi } from "../lib/markdown.js" | ||
|
||
const choices = Object.entries(providers) | ||
.filter(([, { setupUrl }]) => !!setupUrl) | ||
.map(([value, { name }]) => ({ name, value })) | ||
|
||
/** @param {string | undefined} providerId */ | ||
export async function action(providerId) { | ||
try { | ||
if (!providerId) { | ||
providerId = await select({ | ||
message: "What provider do you want to set up?", | ||
choices: choices, | ||
}) | ||
} | ||
|
||
const provider = providers[providerId] | ||
if (!provider?.setupUrl) { | ||
console.error( | ||
y.red( | ||
`Missing instructions for ${ | ||
provider?.name ?? providerId | ||
}.\nInstructions are available for: ${y.bold( | ||
choices.map((choice) => choice.name).join(", ") | ||
)}` | ||
) | ||
) | ||
return | ||
} | ||
|
||
const frameworkId = await requireFramework() | ||
const framework = frameworks[frameworkId] | ||
|
||
console.log( | ||
y.dim( | ||
`Setting up OAuth provider in your ${framework.name} app (${link( | ||
"more info", | ||
"https://authjs.dev/getting-started/authentication/oauth" | ||
)})...\n` | ||
) | ||
) | ||
|
||
const url = new URL( | ||
`${framework.path}/callback/${providerId}`, | ||
`http://localhost:${framework.port}` | ||
) | ||
|
||
clipboard.writeSync(url.toString()) | ||
console.log( | ||
`\ | ||
${y.bold("Setup URL")}: ${provider.setupUrl} | ||
${y.bold("Callback URL (copied to clipboard)")}: ${url}` | ||
) | ||
|
||
console.log("_________________________") | ||
if (provider.instructions) { | ||
console.log(y.dim("\nFollow the instructions:\n")) | ||
console.log(markdownToAnsi(provider.instructions)) | ||
} | ||
console.log( | ||
y.dim( | ||
`\nProvider documentation: https://providers.authjs.dev/${providerId}\n` | ||
) | ||
) | ||
console.log("‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾") | ||
console.log(y.dim("Opening setup URL in your browser...\n")) | ||
await new Promise((resolve) => setTimeout(resolve, 3000)) | ||
|
||
await open(provider.setupUrl) | ||
|
||
const clientId = await input({ | ||
message: `Paste ${y.magenta("Client ID")}:`, | ||
validate: (value) => !!value, | ||
}) | ||
const clientSecret = await password({ | ||
message: `Paste ${y.magenta("Client secret")}:`, | ||
mask: true, | ||
validate: (value) => !!value, | ||
}) | ||
|
||
console.log(y.dim(`Updating environment variable file...`)) | ||
|
||
const varPrefix = `AUTH_${providerId.toUpperCase()}` | ||
|
||
await updateEnvFile({ | ||
[`${varPrefix}_ID`]: clientId, | ||
[`${varPrefix}_SECRET`]: clientSecret, | ||
}) | ||
|
||
console.log( | ||
y.dim( | ||
`\nEnsuring that ${link( | ||
"AUTH_SECRET", | ||
"https://authjs.dev/getting-started/installation#setup-environment" | ||
)} is set...` | ||
) | ||
) | ||
|
||
await secret.action({}) | ||
|
||
console.log("\n🎉 Done! You can now use this provider in your app.") | ||
} catch (error) { | ||
if (!(error instanceof Error)) return | ||
if (error.message.startsWith("User force closed")) return | ||
throw error | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
export * as ask from "./ask.js" | ||
export * as init from "./init.js" | ||
export * as secret from "./secret.js" | ||
export * as add from './add.js' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// @ts-check | ||
import * as y from "yoctocolors" | ||
|
||
// double char markdown matchers | ||
const BOLD_REGEX = /\*{2}([^*]+)\*{2}/g | ||
const UNDERLINE_REGEX = /_{2}([^_]+)_{2}/g | ||
const STRIKETHROUGH_REGEX = /~{2}([^~]+)~{2}/g | ||
const LINK_REGEX = /\[([^\]]+)\]\(([^)]+)\)/g | ||
|
||
// single char markdown matchers | ||
const ITALIC_REGEX = /(?<!\\)\*(.+)(?<!\\)\*|(?<!\\)_(.+)(?<!\\)_/g | ||
|
||
export function link(text, url) { | ||
return `\x1b]8;;${url}\x1b\\${text}\x1b]8;;\x1b\\` | ||
} | ||
|
||
/** | ||
* @param {string} input | ||
* @returns {string} | ||
*/ | ||
export function markdownToAnsi(input) { | ||
input = input.replace(BOLD_REGEX, (...args) => y.bold(args[1])) | ||
input = input.replace(UNDERLINE_REGEX, (...args) => y.underline(args[1])) | ||
input = input.replace(STRIKETHROUGH_REGEX, (...args) => | ||
y.strikethrough(args[1]) | ||
) | ||
input = input.replace(ITALIC_REGEX, (...args) => y.italic(args[1] || args[2])) | ||
input = input.replace(/(?<!\\)\\/g, "") | ||
|
||
// @ts-expect-error | ||
input = input.replaceAll(LINK_REGEX, (...args) => | ||
y.blue(" " + link(args[2], args[1])) | ||
) | ||
return input | ||
} | ||
|
||
/** | ||
* @param {string} str | ||
* @param {number} maxLineLength | ||
* @returns {string} | ||
*/ | ||
export function breakStringToLines(str, maxLineLength) { | ||
let result = "" | ||
let line = "" | ||
|
||
str.split(" ").forEach((word) => { | ||
if (line.length + word.length + 1 > maxLineLength) { | ||
result += line + "\n" | ||
line = word | ||
} else { | ||
if (line) line += " " | ||
line += word | ||
} | ||
}) | ||
|
||
if (line) result += line | ||
|
||
return result | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@balazsorban44 Is this imported anywhere?