auth 1.2.2 → 1.5.0-beta.15
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/LICENSE.md +20 -0
- package/README.md +29 -176
- package/dist/api.d.mts +45 -0
- package/dist/api.mjs +3 -0
- package/dist/generators-DNY9D4Si.mjs +661 -0
- package/dist/generators-DNY9D4Si.mjs.map +1 -0
- package/dist/index.d.mts +7 -0
- package/dist/index.mjs +5687 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +79 -48
- package/LICENSE +0 -21
- package/commands/add.js +0 -149
- package/commands/ask.js +0 -90
- package/commands/index.js +0 -4
- package/commands/init.js +0 -121
- package/commands/secret.js +0 -55
- package/index.js +0 -63
- package/lib/apple-gen-secret.js +0 -101
- package/lib/detect.js +0 -58
- package/lib/is-online.js +0 -46
- package/lib/markdown.js +0 -59
- package/lib/meta.js +0 -199
- package/lib/pkg-manager.js +0 -70
- package/lib/write-env.js +0 -61
package/lib/apple-gen-secret.js
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs"
|
|
2
|
-
import path from "node:path"
|
|
3
|
-
import * as y from "yoctocolors"
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Generates an Apple client secret.
|
|
7
|
-
*
|
|
8
|
-
* @param {object} options
|
|
9
|
-
* @param {string} options.teamId - Apple Team ID.
|
|
10
|
-
* @param {string} options.clientId - Apple Client ID.
|
|
11
|
-
* @param {string} options.keyId - Apple Key ID.
|
|
12
|
-
* @param {string} options.privateKey - Apple Private Key.
|
|
13
|
-
* @param {number} options.expiresInDays - Days until the secret expires.
|
|
14
|
-
*
|
|
15
|
-
* @see https://developer.apple.com/documentation/accountorganizationaldatasharing/creating-a-client-secret
|
|
16
|
-
*/
|
|
17
|
-
export async function appleGenSecret({
|
|
18
|
-
teamId: iss,
|
|
19
|
-
clientId: sub,
|
|
20
|
-
keyId: kid,
|
|
21
|
-
privateKey,
|
|
22
|
-
expiresInDays,
|
|
23
|
-
}) {
|
|
24
|
-
const expiresIn = 86400 * expiresInDays
|
|
25
|
-
const exp = Math.ceil(Date.now() / 1000) + expiresIn
|
|
26
|
-
|
|
27
|
-
const secret = await signJWT(sub, iss, kid, privateKey, exp)
|
|
28
|
-
|
|
29
|
-
console.log(
|
|
30
|
-
y.green(
|
|
31
|
-
`Apple client secret generated. Valid until: ${new Date(exp * 1000)}`
|
|
32
|
-
)
|
|
33
|
-
)
|
|
34
|
-
|
|
35
|
-
return secret
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
*
|
|
40
|
-
* @param {string} sub - Apple client ID.
|
|
41
|
-
* @param {string} iss - Apple team ID.
|
|
42
|
-
* @param {string} kid - Apple key ID.
|
|
43
|
-
* @param {string} privateKeyPath - Apple private key.
|
|
44
|
-
* @param {Date} exp - Expiry date.
|
|
45
|
-
*/
|
|
46
|
-
async function signJWT(sub, iss, kid, privateKeyPath, exp) {
|
|
47
|
-
const header = { alg: "ES256", kid }
|
|
48
|
-
|
|
49
|
-
const payload = {
|
|
50
|
-
iss,
|
|
51
|
-
iat: Date.now() / 1000,
|
|
52
|
-
exp,
|
|
53
|
-
aud: "https://appleid.apple.com",
|
|
54
|
-
sub,
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const parts = [
|
|
58
|
-
toBase64Url(encoder.encode(JSON.stringify(header))),
|
|
59
|
-
toBase64Url(encoder.encode(JSON.stringify(payload))),
|
|
60
|
-
]
|
|
61
|
-
|
|
62
|
-
const privateKey = fs.readFileSync(path.resolve(privateKeyPath), "utf8")
|
|
63
|
-
|
|
64
|
-
const signature = await sign(parts.join("."), privateKey)
|
|
65
|
-
|
|
66
|
-
parts.push(toBase64Url(signature))
|
|
67
|
-
return parts.join(".")
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const encoder = new TextEncoder()
|
|
71
|
-
function toBase64Url(data) {
|
|
72
|
-
return btoa(String.fromCharCode(...new Uint8Array(data)))
|
|
73
|
-
.replace(/\+/g, "-")
|
|
74
|
-
.replace(/\//g, "_")
|
|
75
|
-
.replace(/=+$/, "")
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
async function sign(data, private_key) {
|
|
79
|
-
const pem = private_key.replace(
|
|
80
|
-
/-----BEGIN PRIVATE KEY-----|\n|-----END PRIVATE KEY-----/g,
|
|
81
|
-
""
|
|
82
|
-
)
|
|
83
|
-
const binaryDerString = atob(pem)
|
|
84
|
-
const binaryDer = new Uint8Array(
|
|
85
|
-
[...binaryDerString].map((char) => char.charCodeAt(0))
|
|
86
|
-
)
|
|
87
|
-
|
|
88
|
-
const privateKey = await globalThis.crypto.subtle.importKey(
|
|
89
|
-
"pkcs8",
|
|
90
|
-
binaryDer.buffer,
|
|
91
|
-
{ name: "ECDSA", namedCurve: "P-256" },
|
|
92
|
-
true,
|
|
93
|
-
["sign"]
|
|
94
|
-
)
|
|
95
|
-
|
|
96
|
-
return await globalThis.crypto.subtle.sign(
|
|
97
|
-
{ name: "ECDSA", hash: { name: "SHA-256" } },
|
|
98
|
-
privateKey,
|
|
99
|
-
encoder.encode(data)
|
|
100
|
-
)
|
|
101
|
-
}
|
package/lib/detect.js
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
import { readFile } from "node:fs/promises"
|
|
3
|
-
import { join } from "node:path"
|
|
4
|
-
import { frameworks } from "../lib/meta.js"
|
|
5
|
-
import * as y from "yoctocolors"
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* When this function runs in a framework directory we support,
|
|
9
|
-
* it will return the framework's name
|
|
10
|
-
* @param {string} path
|
|
11
|
-
* @returns {Promise<import("./meta").SupportedFramework | "unknown">}
|
|
12
|
-
*/
|
|
13
|
-
export async function detectFramework(path = "") {
|
|
14
|
-
const dir = process.cwd()
|
|
15
|
-
const packageJsonPath = join(dir, path, "package.json")
|
|
16
|
-
try {
|
|
17
|
-
const packageJson = JSON.parse(await readFile(packageJsonPath, "utf-8"))
|
|
18
|
-
|
|
19
|
-
/** @type {import("./meta").SupportedFramework[]} */
|
|
20
|
-
const foundFrameworks = []
|
|
21
|
-
|
|
22
|
-
if (packageJson?.dependencies?.["next"]) foundFrameworks.push("next")
|
|
23
|
-
if (packageJson?.dependencies?.["express"]) foundFrameworks.push("express")
|
|
24
|
-
if (packageJson?.devDependencies?.["@sveltejs/kit"])
|
|
25
|
-
foundFrameworks.push("sveltekit")
|
|
26
|
-
|
|
27
|
-
if (foundFrameworks.length === 1) return foundFrameworks[0]
|
|
28
|
-
|
|
29
|
-
if (foundFrameworks.length > 1) {
|
|
30
|
-
console.error(
|
|
31
|
-
`Multiple supported frameworks detected: ${foundFrameworks.join(", ")}`
|
|
32
|
-
)
|
|
33
|
-
return "unknown"
|
|
34
|
-
}
|
|
35
|
-
return "unknown"
|
|
36
|
-
} catch (error) {
|
|
37
|
-
console.error(error)
|
|
38
|
-
return "unknown"
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export async function requireFramework(path = "") {
|
|
43
|
-
const framework = await detectFramework(path)
|
|
44
|
-
|
|
45
|
-
if (framework === "unknown") {
|
|
46
|
-
console.error(
|
|
47
|
-
y.red(
|
|
48
|
-
`No framework detected. Currently supported frameworks are: ${y.bold(
|
|
49
|
-
Object.keys(frameworks).join(", ")
|
|
50
|
-
)}`
|
|
51
|
-
)
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
process.exit(0)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return framework
|
|
58
|
-
}
|
package/lib/is-online.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
import { execSync } from "node:child_process"
|
|
4
|
-
import dns from "node:dns/promises"
|
|
5
|
-
|
|
6
|
-
function getProxy() {
|
|
7
|
-
if (process.env.https_proxy) {
|
|
8
|
-
return process.env.https_proxy
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
try {
|
|
12
|
-
const httpsProxy = execSync("npm config get https-proxy").toString().trim()
|
|
13
|
-
return httpsProxy !== "null" ? httpsProxy : undefined
|
|
14
|
-
} catch (e) {
|
|
15
|
-
return
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export async function getOnline() {
|
|
20
|
-
try {
|
|
21
|
-
await dns.lookup("registry.yarnpkg.com")
|
|
22
|
-
// If DNS lookup succeeds, we are online
|
|
23
|
-
return true
|
|
24
|
-
} catch {
|
|
25
|
-
// The DNS lookup failed, but we are still fine as long as a proxy has been set
|
|
26
|
-
const proxy = getProxy()
|
|
27
|
-
if (!proxy) {
|
|
28
|
-
return false
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const { hostname } = new URL(proxy)
|
|
32
|
-
if (!hostname) {
|
|
33
|
-
// Invalid proxy URL
|
|
34
|
-
return false
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
try {
|
|
38
|
-
await dns.lookup(hostname)
|
|
39
|
-
// If DNS lookup succeeds for the proxy server, we are online
|
|
40
|
-
return true
|
|
41
|
-
} catch {
|
|
42
|
-
// The DNS lookup for the proxy server also failed, so we are offline
|
|
43
|
-
return false
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
package/lib/markdown.js
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
import * as y from "yoctocolors"
|
|
3
|
-
|
|
4
|
-
// double char markdown matchers
|
|
5
|
-
const BOLD_REGEX = /\*{2}([^*]+)\*{2}/g
|
|
6
|
-
const UNDERLINE_REGEX = /_{2}([^_]+)_{2}/g
|
|
7
|
-
const STRIKETHROUGH_REGEX = /~{2}([^~]+)~{2}/g
|
|
8
|
-
const LINK_REGEX = /\[([^\]]+)\]\(([^)]+)\)/g
|
|
9
|
-
|
|
10
|
-
// single char markdown matchers
|
|
11
|
-
const ITALIC_REGEX = /(?<!\\)\*(.+)(?<!\\)\*|(?<!\\)_(.+)(?<!\\)_/g
|
|
12
|
-
|
|
13
|
-
export function link(text, url) {
|
|
14
|
-
return `\x1b]8;;${url}\x1b\\${text}\x1b]8;;\x1b\\`
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* @param {string} input
|
|
19
|
-
* @returns {string}
|
|
20
|
-
*/
|
|
21
|
-
export function markdownToAnsi(input) {
|
|
22
|
-
input = input.replace(BOLD_REGEX, (...args) => y.bold(args[1]))
|
|
23
|
-
input = input.replace(UNDERLINE_REGEX, (...args) => y.underline(args[1]))
|
|
24
|
-
input = input.replace(STRIKETHROUGH_REGEX, (...args) =>
|
|
25
|
-
y.strikethrough(args[1])
|
|
26
|
-
)
|
|
27
|
-
input = input.replace(ITALIC_REGEX, (...args) => y.italic(args[1] || args[2]))
|
|
28
|
-
input = input.replace(/(?<!\\)\\/g, "")
|
|
29
|
-
|
|
30
|
-
// @ts-expect-error
|
|
31
|
-
input = input.replaceAll(LINK_REGEX, (...args) =>
|
|
32
|
-
y.blue(" " + link(args[2], args[1]))
|
|
33
|
-
)
|
|
34
|
-
return input
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* @param {string} str
|
|
39
|
-
* @param {number} maxLineLength
|
|
40
|
-
* @returns {string}
|
|
41
|
-
*/
|
|
42
|
-
export function breakStringToLines(str, maxLineLength) {
|
|
43
|
-
let result = ""
|
|
44
|
-
let line = ""
|
|
45
|
-
|
|
46
|
-
str.split(" ").forEach((word) => {
|
|
47
|
-
if (line.length + word.length + 1 > maxLineLength) {
|
|
48
|
-
result += line + "\n"
|
|
49
|
-
line = word
|
|
50
|
-
} else {
|
|
51
|
-
if (line) line += " "
|
|
52
|
-
line += word
|
|
53
|
-
}
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
if (line) result += line
|
|
57
|
-
|
|
58
|
-
return result
|
|
59
|
-
}
|
package/lib/meta.js
DELETED
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
// TODO: Get these programmatically
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @typedef {"next" | "express" | "sveltekit"} SupportedFramework
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
export const frameworks = {
|
|
10
|
-
next: {
|
|
11
|
-
name: "Next.js",
|
|
12
|
-
src: "https://github.com/nextauthjs/next-auth-example",
|
|
13
|
-
demo: "https://next-auth-example.vercel.app",
|
|
14
|
-
path: "/api/auth",
|
|
15
|
-
port: 3000,
|
|
16
|
-
envFile: ".env.local",
|
|
17
|
-
},
|
|
18
|
-
sveltekit: {
|
|
19
|
-
name: "SvelteKit",
|
|
20
|
-
src: "https://github.com/nextauthjs/sveltekit-auth-example",
|
|
21
|
-
demo: "https://sveltekit-auth-example.vercel.app",
|
|
22
|
-
path: "/auth",
|
|
23
|
-
port: 5173,
|
|
24
|
-
envFile: ".env",
|
|
25
|
-
},
|
|
26
|
-
express: {
|
|
27
|
-
name: "Express",
|
|
28
|
-
src: "https://github.com/nextauthjs/express-auth-example",
|
|
29
|
-
demo: "https://express-auth-example.vercel.app",
|
|
30
|
-
path: "/auth",
|
|
31
|
-
port: 3000,
|
|
32
|
-
envFile: ".env",
|
|
33
|
-
},
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export const providers = {
|
|
37
|
-
"42-school": { name: "42 School", setupUrl: undefined },
|
|
38
|
-
apple: {
|
|
39
|
-
name: "Apple",
|
|
40
|
-
setupUrl:
|
|
41
|
-
"https://developer.apple.com/account/resources/identifiers/list/serviceId",
|
|
42
|
-
},
|
|
43
|
-
asgardeo: { name: "Asgardeo", setupUrl: undefined },
|
|
44
|
-
auth0: { name: "Auth0", setupUrl: undefined },
|
|
45
|
-
authentik: { name: "Authentik", setupUrl: undefined },
|
|
46
|
-
"azure-ad-b2c": { name: "Azure AD B2C", setupUrl: undefined },
|
|
47
|
-
"azure-ad": { name: "Azure AD", setupUrl: undefined },
|
|
48
|
-
"azure-devops": { name: "Azure DevOps", setupUrl: undefined },
|
|
49
|
-
battlenet: { name: "Battlenet", setupUrl: undefined },
|
|
50
|
-
beyondidentity: { name: "Beyond Identity", setupUrl: undefined },
|
|
51
|
-
box: { name: "Box", setupUrl: undefined },
|
|
52
|
-
"boxyhq-saml": { name: "Boxyhq SAML", setupUrl: undefined },
|
|
53
|
-
bungie: { name: "Bungie", setupUrl: undefined },
|
|
54
|
-
"click-up": { name: "Click-up", setupUrl: undefined },
|
|
55
|
-
cognito: { name: "Cognito", setupUrl: undefined },
|
|
56
|
-
coinbase: { name: "Coinbase", setupUrl: undefined },
|
|
57
|
-
credentials: { name: "Credentials", setupUrl: undefined },
|
|
58
|
-
descope: { name: "Descope", setupUrl: undefined },
|
|
59
|
-
discord: {
|
|
60
|
-
name: "Discord",
|
|
61
|
-
setupUrl: "https://discord.com/developers/applications",
|
|
62
|
-
instructions: `\
|
|
63
|
-
1. Click on *New Application*
|
|
64
|
-
2. Set *Application name* (can be anything)
|
|
65
|
-
3. Click on *OAuth2* in the side menu
|
|
66
|
-
4. Click on *Add Redirect* and paste the callback URI (on your clipboard)
|
|
67
|
-
5. Click on *Save Changes*
|
|
68
|
-
6. Copy and paste the *Client ID*
|
|
69
|
-
7. Copy and paste the *Client Secret*
|
|
70
|
-
`,
|
|
71
|
-
},
|
|
72
|
-
dribbble: { name: "Dribbble", setupUrl: undefined },
|
|
73
|
-
dropbox: { name: "Dropbox", setupUrl: undefined },
|
|
74
|
-
"duende-identity-server6": {
|
|
75
|
-
name: "Duende Identity Server 6",
|
|
76
|
-
setupUrl: undefined,
|
|
77
|
-
},
|
|
78
|
-
email: { name: "Email", setupUrl: undefined },
|
|
79
|
-
eveonline: { name: "Eveonline", setupUrl: undefined },
|
|
80
|
-
facebook: { name: "Facebook", setupUrl: undefined },
|
|
81
|
-
faceit: { name: "Faceit", setupUrl: undefined },
|
|
82
|
-
foursquare: { name: "Foursquare", setupUrl: undefined },
|
|
83
|
-
freshbooks: { name: "Freshbooks", setupUrl: undefined },
|
|
84
|
-
fusionauth: { name: "FusionAuth", setupUrl: undefined },
|
|
85
|
-
github: {
|
|
86
|
-
name: "GitHub",
|
|
87
|
-
setupUrl: "https://github.com/settings/applications/new",
|
|
88
|
-
instructions: `\
|
|
89
|
-
1. Set *Application name* (can be anything)
|
|
90
|
-
2. Set *Homepage URL* (your business/website, but can be anything)
|
|
91
|
-
3. Paste the redirect URI (on your clipboard) to *Authorization callback URL*
|
|
92
|
-
4. Click *Register application*
|
|
93
|
-
5. Paste the *Client ID* back here
|
|
94
|
-
6. Click *Generate a new client secret*
|
|
95
|
-
7. Paste the *Client secret* back here (Note: This is the only time you can see it)`,
|
|
96
|
-
},
|
|
97
|
-
gitlab: { name: "GitLab", setupUrl: undefined },
|
|
98
|
-
google: {
|
|
99
|
-
name: "Google",
|
|
100
|
-
setupUrl: "https://console.cloud.google.com/apis/credentials/oauthclient",
|
|
101
|
-
instructions: `\
|
|
102
|
-
1. Choose *Application Type: Web Application*
|
|
103
|
-
2. Paste the redirect URI (on your clipboard) to *Authorized redirect URIs*
|
|
104
|
-
3. Fill out the rest of the form
|
|
105
|
-
4. Click *Create*`,
|
|
106
|
-
},
|
|
107
|
-
hubspot: { name: "Hubspot", setupUrl: undefined },
|
|
108
|
-
"identity-server4": { name: "Identity Server 4", setupUrl: undefined },
|
|
109
|
-
instagram: { name: "Instagram", setupUrl: undefined },
|
|
110
|
-
kakao: { name: "Kakao", setupUrl: undefined },
|
|
111
|
-
keycloak: { name: "Keycloak", setupUrl: undefined },
|
|
112
|
-
line: { name: "Line", setupUrl: undefined },
|
|
113
|
-
linkedin: {
|
|
114
|
-
name: "LinkedIn",
|
|
115
|
-
setupUrl: "https://linkedin.com/developers/apps",
|
|
116
|
-
instructions: `\
|
|
117
|
-
1. Click on *Create app*
|
|
118
|
-
2. Set *App name* (can be anything)
|
|
119
|
-
3. Create a *LinkedIn page*
|
|
120
|
-
4. Set *LinkedIn Page URL* (LinkedIn page you created)
|
|
121
|
-
5. Set *App logo* (can be anything)
|
|
122
|
-
6. Navigate to *Auth* in the top menu
|
|
123
|
-
7. Set *Authorized redirect URLs for your app* (paste the callback URI on your clipboard)
|
|
124
|
-
8. Copy and paste the *Client ID*
|
|
125
|
-
9. Copy and paste the *Primary Client Secret*
|
|
126
|
-
`,
|
|
127
|
-
},
|
|
128
|
-
mailchimp: { name: "Mailchimp", setupUrl: undefined },
|
|
129
|
-
mailru: { name: "Mail.ru", setupUrl: undefined },
|
|
130
|
-
mastodon: { name: "Mastodon", setupUrl: undefined },
|
|
131
|
-
mattermost: { name: "Mattermost", setupUrl: undefined },
|
|
132
|
-
medium: { name: "Medium", setupUrl: undefined },
|
|
133
|
-
"microsoft-entra-id": { name: "Microsoft Entra ID", setupUrl: undefined },
|
|
134
|
-
naver: { name: "Naver", setupUrl: undefined },
|
|
135
|
-
netlify: { name: "Netlify", setupUrl: undefined },
|
|
136
|
-
netsuite: { name: "Netsuite", setupUrl: undefined },
|
|
137
|
-
nodemailer: { name: "Nodemailer", setupUrl: undefined },
|
|
138
|
-
notion: { name: "Notion", setupUrl: undefined },
|
|
139
|
-
okta: { name: "Okta", setupUrl: undefined },
|
|
140
|
-
onelogin: { name: "Onelogin", setupUrl: undefined },
|
|
141
|
-
"ory-hydra": { name: "Ory Hydra", setupUrl: undefined },
|
|
142
|
-
osso: { name: "Osso", setupUrl: undefined },
|
|
143
|
-
osu: { name: "Osu", setupUrl: undefined },
|
|
144
|
-
passage: { name: "Passage", setupUrl: undefined },
|
|
145
|
-
passkey: { name: "Passkey", setupUrl: undefined },
|
|
146
|
-
patreon: { name: "Patreon", setupUrl: undefined },
|
|
147
|
-
pinterest: { name: "Pinterest", setupUrl: undefined },
|
|
148
|
-
pipedrive: { name: "Pipedrive", setupUrl: undefined },
|
|
149
|
-
postmark: { name: "Postmark", setupUrl: undefined },
|
|
150
|
-
reddit: { name: "Reddit", setupUrl: undefined },
|
|
151
|
-
resend: { name: "Resend", setupUrl: undefined },
|
|
152
|
-
salesforce: { name: "Salesforce", setupUrl: undefined },
|
|
153
|
-
sendgrid: { name: "Sendgrid", setupUrl: undefined },
|
|
154
|
-
slack: { name: "Slack", setupUrl: undefined },
|
|
155
|
-
spotify: { name: "Spotify", setupUrl: undefined },
|
|
156
|
-
strava: { name: "Strava", setupUrl: undefined },
|
|
157
|
-
tiktok: { name: "Tiktok", setupUrl: undefined },
|
|
158
|
-
todoist: { name: "Todoist", setupUrl: undefined },
|
|
159
|
-
trakt: { name: "Trakt", setupUrl: undefined },
|
|
160
|
-
twitch: { name: "Twitch", setupUrl: undefined },
|
|
161
|
-
twitter: { name: "Twitter", setupUrl: undefined },
|
|
162
|
-
"united-effects": { name: "United Effects", setupUrl: undefined },
|
|
163
|
-
vk: { name: "Vk", setupUrl: undefined },
|
|
164
|
-
webex: { name: "Webex", setupUrl: undefined },
|
|
165
|
-
wikimedia: { name: "Wikimedia", setupUrl: undefined },
|
|
166
|
-
wordpress: { name: "Wordpress", setupUrl: undefined },
|
|
167
|
-
workos: { name: "WorkOS", setupUrl: undefined },
|
|
168
|
-
yandex: { name: "Yandex", setupUrl: undefined },
|
|
169
|
-
zitadel: { name: "Zitadel", setupUrl: undefined },
|
|
170
|
-
zoho: { name: "Zoho", setupUrl: undefined },
|
|
171
|
-
zoom: { name: "Zoom", setupUrl: undefined },
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
export const adapters = {
|
|
175
|
-
none: "None",
|
|
176
|
-
"adapter-azure-tables": "Azure Tables",
|
|
177
|
-
d1: "d1",
|
|
178
|
-
dgraph: "Dgraph",
|
|
179
|
-
drizzle: "Drizzle",
|
|
180
|
-
dynamodb: "DynamoDB",
|
|
181
|
-
edgedb: "EdgeDB",
|
|
182
|
-
fauna: "Fauna",
|
|
183
|
-
firebase: "Firebase",
|
|
184
|
-
hasura: "Hasura",
|
|
185
|
-
kysely: "Kysely",
|
|
186
|
-
"mikro-orm": "MikroORM",
|
|
187
|
-
mongodb: "MongoDB",
|
|
188
|
-
neo4j: "Neo4j",
|
|
189
|
-
pg: "PostgreSQL",
|
|
190
|
-
pouchdb: "PouchDB",
|
|
191
|
-
prisma: "Prisma",
|
|
192
|
-
sequelize: "Sequelize",
|
|
193
|
-
supabase: "Supabase",
|
|
194
|
-
surrealdb: "SurrealDB",
|
|
195
|
-
typeorm: "TypeORM",
|
|
196
|
-
unstorage: "Unstorage",
|
|
197
|
-
"upstash-redis": "Upstash Redis",
|
|
198
|
-
xata: "Xata",
|
|
199
|
-
}
|
package/lib/pkg-manager.js
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
import { yellow } from "yoctocolors"
|
|
4
|
-
import { spawn } from "node:child_process"
|
|
5
|
-
import { getOnline } from "./is-online.js"
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @typedef {'npm' | 'pnpm' | 'yarn' | 'bun'} PackageManager
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* @source https://github.com/vercel/next.js/blob/canary/packages/create-next-app/helpers/get-pkg-manager.ts
|
|
13
|
-
* @returns {PackageManager}
|
|
14
|
-
*/
|
|
15
|
-
export function getPkgManager() {
|
|
16
|
-
const userAgent = process.env.npm_config_user_agent || ""
|
|
17
|
-
|
|
18
|
-
if (userAgent.startsWith("pnpm")) {
|
|
19
|
-
return "pnpm"
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (userAgent.startsWith("bun")) {
|
|
23
|
-
return "bun"
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (userAgent.startsWith("yarn")) {
|
|
27
|
-
return "yarn"
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return "npm"
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* @source https://github.com/vercel/next.js/blob/canary/packages/create-next-app/helpers/install.ts
|
|
35
|
-
* Spawn a package manager installation based on user preference.
|
|
36
|
-
*
|
|
37
|
-
* @returns A Promise that resolves once the installation is finished.
|
|
38
|
-
*/
|
|
39
|
-
export async function install() {
|
|
40
|
-
const packageManager = getPkgManager()
|
|
41
|
-
/** @type {string[]} */
|
|
42
|
-
const args = ["install"]
|
|
43
|
-
if (!(await getOnline())) {
|
|
44
|
-
console.log(
|
|
45
|
-
yellow("You appear to be offline.\nFalling back to the local cache.")
|
|
46
|
-
)
|
|
47
|
-
args.push("--offline")
|
|
48
|
-
}
|
|
49
|
-
return new Promise((resolve, reject) => {
|
|
50
|
-
/** Spawn the installation process. */
|
|
51
|
-
const child = spawn(packageManager, args, {
|
|
52
|
-
stdio: "inherit",
|
|
53
|
-
env: {
|
|
54
|
-
...process.env,
|
|
55
|
-
ADBLOCK: "1",
|
|
56
|
-
// we set NODE_ENV to development as pnpm skips dev
|
|
57
|
-
// dependencies when production
|
|
58
|
-
NODE_ENV: "development",
|
|
59
|
-
DISABLE_OPENCOLLECTIVE: "1",
|
|
60
|
-
},
|
|
61
|
-
})
|
|
62
|
-
child.on("close", (code) => {
|
|
63
|
-
if (code !== 0) {
|
|
64
|
-
reject({ command: `${packageManager} ${args.join(" ")}` })
|
|
65
|
-
return
|
|
66
|
-
}
|
|
67
|
-
resolve(void 0)
|
|
68
|
-
})
|
|
69
|
-
})
|
|
70
|
-
}
|
package/lib/write-env.js
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
import * as y from "yoctocolors"
|
|
4
|
-
import { readFile, writeFile } from "node:fs/promises"
|
|
5
|
-
import prompt from "prompts"
|
|
6
|
-
import { join } from "node:path"
|
|
7
|
-
import { frameworks } from "./meta.js"
|
|
8
|
-
import { detectFramework } from "./detect.js"
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Add/update key-value pair(s) to a .env file
|
|
12
|
-
* @param {Record<string, string>} env
|
|
13
|
-
* @param {string|undefined} envPath
|
|
14
|
-
* @param {boolean} comment
|
|
15
|
-
*/
|
|
16
|
-
export async function updateEnvFile(env, envPath = "", comment = true) {
|
|
17
|
-
const framework = await detectFramework(envPath)
|
|
18
|
-
const dotEnvFile = frameworks[framework]?.envFile
|
|
19
|
-
const file = join(process.cwd(), envPath, dotEnvFile)
|
|
20
|
-
let content = ""
|
|
21
|
-
let read = false
|
|
22
|
-
let created = false
|
|
23
|
-
for (const [key, value] of Object.entries(env)) {
|
|
24
|
-
const line = `${key}="${value}"${
|
|
25
|
-
comment ? " # Added by `npx auth`. Read more: https://cli.authjs.dev" : ""
|
|
26
|
-
}`
|
|
27
|
-
try {
|
|
28
|
-
if (!read) {
|
|
29
|
-
content = await readFile(file, "utf-8")
|
|
30
|
-
read = true
|
|
31
|
-
}
|
|
32
|
-
if (!content.includes(`${key}=`)) {
|
|
33
|
-
console.log(`➕ Added \`${key}\` to ${y.italic(file)}.`)
|
|
34
|
-
content = content ? `${content}\n${line}` : line
|
|
35
|
-
} else {
|
|
36
|
-
const { overwrite } = await prompt({
|
|
37
|
-
type: "confirm",
|
|
38
|
-
name: "overwrite",
|
|
39
|
-
message: `Overwrite existing \`${key}\`?`,
|
|
40
|
-
initial: false,
|
|
41
|
-
})
|
|
42
|
-
if (!overwrite) continue
|
|
43
|
-
console.log(`✨ Updated \`${key}\` in ${y.italic(file)}.`)
|
|
44
|
-
content = content.replace(new RegExp(`${key}=(.*)`), `${line}`)
|
|
45
|
-
}
|
|
46
|
-
} catch (error) {
|
|
47
|
-
if (error.code === "ENOENT") {
|
|
48
|
-
if (!created) {
|
|
49
|
-
console.log(`📝 Created ${y.italic(file)} with \`${key}\`.`)
|
|
50
|
-
created = true
|
|
51
|
-
} else {
|
|
52
|
-
console.log(`➕ Added \`${key}\` to ${y.italic(file)}.`)
|
|
53
|
-
}
|
|
54
|
-
content = content ? `${content}\n${line}` : line
|
|
55
|
-
} else {
|
|
56
|
-
throw error
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
if (content) await writeFile(file, content)
|
|
61
|
-
}
|