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/package.json
CHANGED
|
@@ -1,64 +1,95 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "auth",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"
|
|
3
|
+
"version": "1.5.0-beta.15",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "The CLI for Better Auth",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
5
7
|
"repository": {
|
|
6
8
|
"type": "git",
|
|
7
|
-
"url": "git+https://github.com/
|
|
9
|
+
"url": "git+https://github.com/better-auth/better-auth.git",
|
|
10
|
+
"directory": "packages/cli"
|
|
8
11
|
},
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
],
|
|
17
|
-
"license": "MIT",
|
|
18
|
-
"type": "module",
|
|
19
|
-
"bin": {
|
|
20
|
-
"auth": "index.js"
|
|
12
|
+
"homepage": "https://www.better-auth.com/docs/concepts/cli",
|
|
13
|
+
"main": "./dist/index.mjs",
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public",
|
|
16
|
+
"executableFiles": [
|
|
17
|
+
"./dist/index.mjs"
|
|
18
|
+
]
|
|
21
19
|
},
|
|
22
|
-
"
|
|
23
|
-
"*.d.ts*",
|
|
24
|
-
"*.js",
|
|
25
|
-
"!scripts",
|
|
26
|
-
"commands",
|
|
27
|
-
"lib",
|
|
28
|
-
"src"
|
|
29
|
-
],
|
|
20
|
+
"license": "MIT",
|
|
30
21
|
"keywords": [
|
|
31
|
-
"
|
|
32
|
-
"cli"
|
|
22
|
+
"auth",
|
|
23
|
+
"cli",
|
|
24
|
+
"typescript",
|
|
25
|
+
"better-auth"
|
|
33
26
|
],
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"ora": "8.1.0",
|
|
41
|
-
"prompts": "2.4.2",
|
|
42
|
-
"yoctocolors": "2.1.1",
|
|
43
|
-
"zod": "3.23.8"
|
|
44
|
-
},
|
|
45
|
-
"prettier": {
|
|
46
|
-
"semi": false
|
|
27
|
+
"exports": {
|
|
28
|
+
".": "./dist/index.mjs",
|
|
29
|
+
"./api": {
|
|
30
|
+
"types": "./dist/api.d.mts",
|
|
31
|
+
"default": "./dist/api.mjs"
|
|
32
|
+
}
|
|
47
33
|
},
|
|
48
|
-
"
|
|
49
|
-
"
|
|
34
|
+
"typesVersions": {
|
|
35
|
+
"*": {
|
|
36
|
+
"api": [
|
|
37
|
+
"./dist/api.d.mts"
|
|
38
|
+
]
|
|
39
|
+
}
|
|
50
40
|
},
|
|
51
|
-
"
|
|
52
|
-
"
|
|
41
|
+
"bin": {
|
|
42
|
+
"better-auth": "./dist/index.mjs"
|
|
53
43
|
},
|
|
54
|
-
"
|
|
55
|
-
"
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
46
|
+
"@types/prompts": "^2.4.9",
|
|
47
|
+
"@types/semver": "^7.7.1",
|
|
48
|
+
"better-sqlite3": "^12.6.2",
|
|
49
|
+
"jiti": "^2.6.0",
|
|
50
|
+
"memfs": "^4.56.10",
|
|
51
|
+
"tsdown": "^0.20.3",
|
|
52
|
+
"tsx": "^4.20.6",
|
|
53
|
+
"type-fest": "^5.4.4",
|
|
54
|
+
"typescript": "^5.9.3",
|
|
55
|
+
"@better-auth/passkey": "1.5.0-beta.15"
|
|
56
56
|
},
|
|
57
|
-
"
|
|
58
|
-
|
|
59
|
-
"
|
|
57
|
+
"dependencies": {
|
|
58
|
+
"@babel/core": "^7.28.4",
|
|
59
|
+
"@babel/preset-react": "^7.27.1",
|
|
60
|
+
"@babel/preset-typescript": "^7.27.1",
|
|
61
|
+
"@better-auth/utils": "0.3.1",
|
|
62
|
+
"@clack/prompts": "^0.11.0",
|
|
63
|
+
"@mrleebo/prisma-ast": "^0.13.1",
|
|
64
|
+
"@prisma/client": "^5.22.0",
|
|
65
|
+
"@types/pg": "^8.15.5",
|
|
66
|
+
"c12": "^3.3.3",
|
|
67
|
+
"chalk": "^5.6.2",
|
|
68
|
+
"commander": "^12.1.0",
|
|
69
|
+
"dotenv": "^17.2.4",
|
|
70
|
+
"drizzle-orm": "^0.41.0",
|
|
71
|
+
"open": "^10.2.0",
|
|
72
|
+
"pg": "^8.16.3",
|
|
73
|
+
"prettier": "^3.8.1",
|
|
74
|
+
"prompts": "^2.4.2",
|
|
75
|
+
"semver": "^7.7.2",
|
|
76
|
+
"yocto-spinner": "^0.2.3",
|
|
77
|
+
"zod": "^4.3.6",
|
|
78
|
+
"@better-auth/core": "1.5.0-beta.15",
|
|
79
|
+
"@better-auth/telemetry": "1.5.0-beta.15",
|
|
80
|
+
"better-auth": "1.5.0-beta.15"
|
|
60
81
|
},
|
|
82
|
+
"files": [
|
|
83
|
+
"dist"
|
|
84
|
+
],
|
|
61
85
|
"scripts": {
|
|
62
|
-
"
|
|
86
|
+
"build": "tsdown",
|
|
87
|
+
"start": "node ./dist/index.mjs",
|
|
88
|
+
"lint:package": "publint run --strict",
|
|
89
|
+
"lint:types": "attw --profile esm-only --pack .",
|
|
90
|
+
"dev": "tsx ./src/index.ts",
|
|
91
|
+
"test": "vitest",
|
|
92
|
+
"coverage": "vitest run --coverage --coverage.provider=istanbul",
|
|
93
|
+
"typecheck": "tsc --project tsconfig.json"
|
|
63
94
|
}
|
|
64
95
|
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2024 Auth.js
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
package/commands/add.js
DELETED
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
import * as y from "yoctocolors"
|
|
4
|
-
import open from "open"
|
|
5
|
-
import clipboard from "clipboardy"
|
|
6
|
-
import { select, input, password, number } from "@inquirer/prompts"
|
|
7
|
-
import { requireFramework } from "../lib/detect.js"
|
|
8
|
-
import { updateEnvFile } from "../lib/write-env.js"
|
|
9
|
-
import { providers, frameworks } from "../lib/meta.js"
|
|
10
|
-
import { link, markdownToAnsi } from "../lib/markdown.js"
|
|
11
|
-
import { appleGenSecret } from "../lib/apple-gen-secret.js"
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* @param {string} label
|
|
15
|
-
* @param {string} [defaultValue]
|
|
16
|
-
*/
|
|
17
|
-
async function promptInput(label, defaultValue) {
|
|
18
|
-
return input({
|
|
19
|
-
message: `Paste ${y.magenta(label)}:`,
|
|
20
|
-
validate: (value) => !!value,
|
|
21
|
-
default: defaultValue,
|
|
22
|
-
})
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/** @param {string} label */
|
|
26
|
-
async function promptPassword(label) {
|
|
27
|
-
return password({
|
|
28
|
-
message: `Paste ${y.magenta(label)}:`,
|
|
29
|
-
mask: true,
|
|
30
|
-
validate: (value) => !!value,
|
|
31
|
-
})
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const choices = Object.entries(providers)
|
|
35
|
-
.filter(([, { setupUrl }]) => !!setupUrl)
|
|
36
|
-
.map(([value, { name }]) => ({ name, value }))
|
|
37
|
-
|
|
38
|
-
/** @param {string | undefined} providerId */
|
|
39
|
-
export async function action(providerId) {
|
|
40
|
-
try {
|
|
41
|
-
providerId ??= await select({
|
|
42
|
-
message: "What provider do you want to set up?",
|
|
43
|
-
choices: choices,
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
const provider = providers[providerId]
|
|
47
|
-
if (!provider?.setupUrl) {
|
|
48
|
-
console.error(
|
|
49
|
-
y.red(
|
|
50
|
-
`Missing instructions for ${
|
|
51
|
-
provider?.name ?? providerId
|
|
52
|
-
}.\nInstructions are available for: ${y.bold(
|
|
53
|
-
choices.map((choice) => choice.name).join(", ")
|
|
54
|
-
)}`
|
|
55
|
-
)
|
|
56
|
-
)
|
|
57
|
-
return
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const frameworkId = await requireFramework()
|
|
61
|
-
const framework = frameworks[frameworkId]
|
|
62
|
-
|
|
63
|
-
console.log(
|
|
64
|
-
y.dim(
|
|
65
|
-
`Setting up OAuth provider in your ${framework.name} app (${link(
|
|
66
|
-
"more info",
|
|
67
|
-
"https://authjs.dev/getting-started/authentication/oauth"
|
|
68
|
-
)})...\n`
|
|
69
|
-
)
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
const url = new URL(
|
|
73
|
-
`${framework.path}/callback/${providerId}`,
|
|
74
|
-
`http://localhost:${framework.port}`
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
clipboard.writeSync(url.toString())
|
|
78
|
-
console.log(
|
|
79
|
-
`\
|
|
80
|
-
${y.bold("Setup URL")}: ${provider.setupUrl}
|
|
81
|
-
${y.bold("Callback URL (copied to clipboard)")}: ${url}`
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
console.log("_________________________")
|
|
85
|
-
if (provider.instructions) {
|
|
86
|
-
console.log(y.dim("\nFollow the instructions:\n"))
|
|
87
|
-
console.log(markdownToAnsi(provider.instructions))
|
|
88
|
-
}
|
|
89
|
-
console.log(
|
|
90
|
-
y.dim(
|
|
91
|
-
`\nProvider documentation: https://providers.authjs.dev/${providerId}\n`
|
|
92
|
-
)
|
|
93
|
-
)
|
|
94
|
-
console.log("‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾")
|
|
95
|
-
console.log(y.dim("Opening setup URL in your browser...\n"))
|
|
96
|
-
await new Promise((resolve) => setTimeout(resolve, 3000))
|
|
97
|
-
|
|
98
|
-
await open(provider.setupUrl)
|
|
99
|
-
|
|
100
|
-
if (providerId === "apple") {
|
|
101
|
-
const clientId = await promptInput("Client ID")
|
|
102
|
-
const keyId = await promptInput("Key ID")
|
|
103
|
-
const teamId = await promptInput("Team ID")
|
|
104
|
-
const privateKey = await input({
|
|
105
|
-
message: "Path to Private Key",
|
|
106
|
-
validate: (value) => !!value,
|
|
107
|
-
default: "./private-key.p8",
|
|
108
|
-
})
|
|
109
|
-
|
|
110
|
-
const expiresInDays =
|
|
111
|
-
(await number({
|
|
112
|
-
message: "Expires in days (default: 180)",
|
|
113
|
-
required: false,
|
|
114
|
-
default: 180,
|
|
115
|
-
})) ?? 180
|
|
116
|
-
|
|
117
|
-
console.log(y.dim("Updating environment variable file..."))
|
|
118
|
-
|
|
119
|
-
await updateEnvFile({ AUTH_APPLE_ID: clientId })
|
|
120
|
-
|
|
121
|
-
const secret = await appleGenSecret({
|
|
122
|
-
teamId,
|
|
123
|
-
clientId,
|
|
124
|
-
keyId,
|
|
125
|
-
privateKey,
|
|
126
|
-
expiresInDays,
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
await updateEnvFile({ AUTH_APPLE_SECRET: secret })
|
|
130
|
-
} else {
|
|
131
|
-
const clientId = await promptInput("Client ID")
|
|
132
|
-
const clientSecret = await promptPassword("Client Secret")
|
|
133
|
-
|
|
134
|
-
console.log(y.dim("Updating environment variable file..."))
|
|
135
|
-
|
|
136
|
-
const varPrefix = `AUTH_${providerId.toUpperCase()}`
|
|
137
|
-
await updateEnvFile({
|
|
138
|
-
[`${varPrefix}_ID`]: clientId,
|
|
139
|
-
[`${varPrefix}_SECRET`]: clientSecret,
|
|
140
|
-
})
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
console.log("\n🎉 Done! You can now use this provider in your app.")
|
|
144
|
-
} catch (error) {
|
|
145
|
-
if (!(error instanceof Error)) return
|
|
146
|
-
if (error.message.startsWith("User force closed")) return
|
|
147
|
-
throw error
|
|
148
|
-
}
|
|
149
|
-
}
|
package/commands/ask.js
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
import * as y from "yoctocolors"
|
|
4
|
-
import { input } from "@inquirer/prompts"
|
|
5
|
-
import { InkeepAI } from "@inkeep/ai-api"
|
|
6
|
-
import { ChatModeOptions } from "@inkeep/ai-api/models/components/index.js"
|
|
7
|
-
import * as ora from "ora"
|
|
8
|
-
import { link, markdownToAnsi, breakStringToLines } from "../lib/markdown.js"
|
|
9
|
-
|
|
10
|
-
const INKEEP_API_KEY = "e32967a320a48a2cd933922099e1f38f6ebb4ab62ff98343"
|
|
11
|
-
const INKEEP_INTEGRATION_ID = "clvn0fdez000cip0e5w2oaobw"
|
|
12
|
-
|
|
13
|
-
const inkeepAI = new InkeepAI({ apiKey: INKEEP_API_KEY })
|
|
14
|
-
|
|
15
|
-
function randomSpinner() {
|
|
16
|
-
const allSpinners = Object.keys(ora.spinners)
|
|
17
|
-
const max = allSpinners.length - 1
|
|
18
|
-
const random = Math.floor(Math.random() * (max + 1))
|
|
19
|
-
return allSpinners[random]
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export async function action({ stream = false, raw = false }) {
|
|
23
|
-
const format = raw ? (i) => i : markdownToAnsi
|
|
24
|
-
const newLocal = randomSpinner()
|
|
25
|
-
const spinner = ora.default({
|
|
26
|
-
text: "Understanding question",
|
|
27
|
-
// @ts-expect-error
|
|
28
|
-
spinner: newLocal,
|
|
29
|
-
})
|
|
30
|
-
try {
|
|
31
|
-
const content = await input({ message: "What would you like to know: " })
|
|
32
|
-
|
|
33
|
-
spinner.start()
|
|
34
|
-
|
|
35
|
-
const result = await inkeepAI.chatSession.create({
|
|
36
|
-
integrationId: INKEEP_INTEGRATION_ID,
|
|
37
|
-
stream,
|
|
38
|
-
chatSession: { messages: [{ content, role: "user" }] },
|
|
39
|
-
chatMode: ChatModeOptions.Auto,
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
if (stream) {
|
|
43
|
-
if (result.chatResultStream == null) {
|
|
44
|
-
throw new Error("failed to create stream: received null value")
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
spinner.stop().clear()
|
|
48
|
-
|
|
49
|
-
for await (const event of result.chatResultStream) {
|
|
50
|
-
if (event.event === "message_chunk") {
|
|
51
|
-
const content = format(event.data.contentChunk)
|
|
52
|
-
process.stdout.write(content)
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
} else {
|
|
56
|
-
const answer = result.chatResult?.message.content
|
|
57
|
-
if (!answer) return console.error(y.red("Could not get an answer."))
|
|
58
|
-
|
|
59
|
-
console.log(breakStringToLines(format(answer), 80))
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
console.log(
|
|
63
|
-
y.italic(
|
|
64
|
-
`\n\nAnswered by ${y.cyan(
|
|
65
|
-
link("Inkeep AI", "https://inkeep.com")
|
|
66
|
-
)}. Check out the official ${y.magenta(
|
|
67
|
-
link("Auth.js", "https://authjs.dev")
|
|
68
|
-
)} docs.`
|
|
69
|
-
)
|
|
70
|
-
)
|
|
71
|
-
} catch (e) {
|
|
72
|
-
spinner.stop().clear()
|
|
73
|
-
if (!(e instanceof Error)) return
|
|
74
|
-
if (e.message.startsWith("User force closed")) return
|
|
75
|
-
|
|
76
|
-
console.error(y.red(e.stack ?? e.message))
|
|
77
|
-
console.error(
|
|
78
|
-
y.bold(
|
|
79
|
-
y.red(
|
|
80
|
-
`\n This is a bug. Please report it on ${link(
|
|
81
|
-
"GitHub",
|
|
82
|
-
"https://github.com/nextauthjs/auth-cli/issues"
|
|
83
|
-
)}.`
|
|
84
|
-
)
|
|
85
|
-
)
|
|
86
|
-
)
|
|
87
|
-
} finally {
|
|
88
|
-
spinner.stop().clear()
|
|
89
|
-
}
|
|
90
|
-
}
|
package/commands/index.js
DELETED
package/commands/init.js
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
import { execSync } from "node:child_process"
|
|
3
|
-
import { input, confirm, select, checkbox } from "@inquirer/prompts"
|
|
4
|
-
import * as y from "yoctocolors"
|
|
5
|
-
import { action as secretAction } from "./secret.js"
|
|
6
|
-
|
|
7
|
-
import { getPkgManager, install } from "../lib/pkg-manager.js"
|
|
8
|
-
import * as meta from "../lib/meta.js"
|
|
9
|
-
import { updateEnvFile } from "../lib/write-env.js"
|
|
10
|
-
import { mkdir } from "node:fs/promises"
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* @param {string} framework
|
|
14
|
-
* @param {{example?: boolean}} options
|
|
15
|
-
* @returns
|
|
16
|
-
*/
|
|
17
|
-
export async function action(framework, options) {
|
|
18
|
-
try {
|
|
19
|
-
if (!framework) {
|
|
20
|
-
framework = await select({
|
|
21
|
-
message: "Select a framework",
|
|
22
|
-
choices: Object.entries(meta.frameworks).map(([key, value]) => ({
|
|
23
|
-
name: `${value.name} ${y.dim(`(${key})`)}`,
|
|
24
|
-
value: key,
|
|
25
|
-
})),
|
|
26
|
-
})
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const dir = await input({
|
|
30
|
-
message: "Name of the project",
|
|
31
|
-
default: `my-${framework}-app`,
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
if (options.example) await createFromExample(framework, dir)
|
|
35
|
-
|
|
36
|
-
const providers = await checkbox({
|
|
37
|
-
instructions: false,
|
|
38
|
-
message: "Select one or multiple providers",
|
|
39
|
-
choices: Object.entries(meta.providers).map(([value, { name }]) => ({
|
|
40
|
-
name,
|
|
41
|
-
value,
|
|
42
|
-
})),
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
/** @type {string|undefined} */
|
|
46
|
-
let adapter = await select({
|
|
47
|
-
default: "none",
|
|
48
|
-
message: "Select a database adapter",
|
|
49
|
-
choices: Object.entries(meta.adapters).map(([value, name]) => ({
|
|
50
|
-
name,
|
|
51
|
-
value,
|
|
52
|
-
})),
|
|
53
|
-
})
|
|
54
|
-
adapter = adapter === "none" ? undefined : adapter
|
|
55
|
-
|
|
56
|
-
await scaffoldProject({ framework, dir, providers, adapter })
|
|
57
|
-
} catch (e) {
|
|
58
|
-
if (!(e instanceof Error)) return
|
|
59
|
-
if (e.message.startsWith("User force closed")) return
|
|
60
|
-
|
|
61
|
-
console.error(y.red(e.message))
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* @param {string} framework
|
|
67
|
-
* @param {string} dir
|
|
68
|
-
*/
|
|
69
|
-
async function createFromExample(framework, dir) {
|
|
70
|
-
const { src, demo } = meta.frameworks[framework]
|
|
71
|
-
execSync(`git clone ${src} ${dir}`)
|
|
72
|
-
if (
|
|
73
|
-
await confirm({
|
|
74
|
-
message: "Initiailze .env with `AUTH_SECRET`",
|
|
75
|
-
default: true,
|
|
76
|
-
})
|
|
77
|
-
) {
|
|
78
|
-
execSync(`cd ${dir}`)
|
|
79
|
-
await secretAction({ path: dir })
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
await install()
|
|
83
|
-
|
|
84
|
-
console.log(`
|
|
85
|
-
Project ${y.italic(`\`${dir}\``)} has been created.
|
|
86
|
-
Source code: ${src}
|
|
87
|
-
Deployed demo: ${demo}`)
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* @param {{framework: string, dir: string, providers: string[], adapter?: string}} options
|
|
92
|
-
*/
|
|
93
|
-
async function scaffoldProject(options) {
|
|
94
|
-
const { framework, providers, dir, adapter } = options
|
|
95
|
-
const pkgManager = getPkgManager()
|
|
96
|
-
console.log(
|
|
97
|
-
`Scaffolding ${y.bold(framework)} project with ${y.bold(
|
|
98
|
-
pkgManager
|
|
99
|
-
)} at ${y.bold(dir)}...`
|
|
100
|
-
)
|
|
101
|
-
throw new Error("Scaffolding not implemented. Please use `init --example`")
|
|
102
|
-
console.log(`Create directory ${dir}`)
|
|
103
|
-
await mkdir(dir)
|
|
104
|
-
console.log(`Change directory to ${dir}`)
|
|
105
|
-
execSync(`cd ${dir}`)
|
|
106
|
-
console.log(`Initialize ${pkgManager} project`)
|
|
107
|
-
execSync(`${pkgManager} init`)
|
|
108
|
-
// console.log(`Add ${framework} to ${pkgManager}`)
|
|
109
|
-
// execSync(`${pkgManager} install ${framework}`)
|
|
110
|
-
for (const provider of providers) {
|
|
111
|
-
const id = `AUTH_${provider.toUpperCase()}_ID`
|
|
112
|
-
const secret = `AUTH_${provider.toUpperCase()}_SECRET`
|
|
113
|
-
await updateEnvFile(
|
|
114
|
-
{
|
|
115
|
-
[id]: "",
|
|
116
|
-
[secret]: "",
|
|
117
|
-
},
|
|
118
|
-
dir
|
|
119
|
-
)
|
|
120
|
-
}
|
|
121
|
-
}
|
package/commands/secret.js
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
import * as y from "yoctocolors"
|
|
4
|
-
import clipboard from "clipboardy"
|
|
5
|
-
import { requireFramework } from "../lib/detect.js"
|
|
6
|
-
import { updateEnvFile } from "../lib/write-env.js"
|
|
7
|
-
|
|
8
|
-
/** Web compatible method to create a random string of a given length */
|
|
9
|
-
function randomString(size = 32) {
|
|
10
|
-
const bytes = crypto.getRandomValues(new Uint8Array(size))
|
|
11
|
-
// @ts-expect-error
|
|
12
|
-
return Buffer.from(bytes, "base64").toString("base64")
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* @param {{
|
|
17
|
-
* copy?: boolean
|
|
18
|
-
* path?: string
|
|
19
|
-
* raw?: boolean
|
|
20
|
-
* }} options
|
|
21
|
-
*/
|
|
22
|
-
export async function action(options) {
|
|
23
|
-
const key = "AUTH_SECRET"
|
|
24
|
-
const value = randomString()
|
|
25
|
-
if (options.raw) return console.log(value)
|
|
26
|
-
|
|
27
|
-
const line = `${key}="${value}"`
|
|
28
|
-
const message = {
|
|
29
|
-
introClipboard:
|
|
30
|
-
"Secret generated. It has been copied to your clipboard, paste it to your .env/.env.local file to continue.",
|
|
31
|
-
introCopy:
|
|
32
|
-
"Secret generated. Copy it to your .env/.env.local file (depending on your framework):",
|
|
33
|
-
value: `\n${line}`,
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (options.copy) {
|
|
37
|
-
try {
|
|
38
|
-
clipboard.writeSync(line)
|
|
39
|
-
console.log(message.introClipboard)
|
|
40
|
-
} catch (error) {
|
|
41
|
-
console.error(y.red(error))
|
|
42
|
-
console.log(message.introCopy)
|
|
43
|
-
} finally {
|
|
44
|
-
console.log(message.value)
|
|
45
|
-
process.exit(0)
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
try {
|
|
50
|
-
await requireFramework(options.path)
|
|
51
|
-
await updateEnvFile({ [key]: value }, options.path)
|
|
52
|
-
} catch (error) {
|
|
53
|
-
console.error(y.red(error))
|
|
54
|
-
}
|
|
55
|
-
}
|
package/index.js
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// @ts-check
|
|
4
|
-
|
|
5
|
-
import { Command, InvalidArgumentError } from "commander"
|
|
6
|
-
import * as y from "yoctocolors"
|
|
7
|
-
import { ask, init, secret, add } from "./commands/index.js"
|
|
8
|
-
|
|
9
|
-
// import pkg from "./package.json" assert { type: "json" }
|
|
10
|
-
|
|
11
|
-
import fs from "node:fs/promises"
|
|
12
|
-
import { join } from "node:path"
|
|
13
|
-
import { fileURLToPath } from "node:url"
|
|
14
|
-
|
|
15
|
-
const __dirname = fileURLToPath(new URL(".", import.meta.url))
|
|
16
|
-
const pkg = JSON.parse(
|
|
17
|
-
await fs.readFile(join(__dirname, "./package.json"), "utf-8")
|
|
18
|
-
)
|
|
19
|
-
const { name, description, version } = pkg
|
|
20
|
-
|
|
21
|
-
try {
|
|
22
|
-
// TODO: Remove when Node.js 18 is not maintained anymore
|
|
23
|
-
// @ts-expect-error
|
|
24
|
-
globalThis.crypto ??= (await import("crypto")).webcrypto
|
|
25
|
-
} catch {}
|
|
26
|
-
|
|
27
|
-
const program = new Command()
|
|
28
|
-
|
|
29
|
-
program
|
|
30
|
-
.name(name)
|
|
31
|
-
.description(description.replace("Auth.js", y.magenta(y.bold("Auth.js"))))
|
|
32
|
-
.version(version)
|
|
33
|
-
|
|
34
|
-
program
|
|
35
|
-
.command("ask")
|
|
36
|
-
.option("--stream", "Stream the response.")
|
|
37
|
-
.option("--raw", "Show the Markdown response without formatting.")
|
|
38
|
-
.description("Ask about docs, API, or auth concepts.")
|
|
39
|
-
.action(ask.action)
|
|
40
|
-
|
|
41
|
-
program
|
|
42
|
-
.command("init")
|
|
43
|
-
.argument("[framework]", "The framework to use.")
|
|
44
|
-
.option("-e, --example", "Clone a full example.")
|
|
45
|
-
.description("Initialize a project.")
|
|
46
|
-
.action(init.action)
|
|
47
|
-
|
|
48
|
-
program
|
|
49
|
-
.command("secret")
|
|
50
|
-
.option("--raw", "Output the string without any formatting.")
|
|
51
|
-
.option("--copy", 'Copy AUTH_SECRET="value".')
|
|
52
|
-
.description("Generate a random string and add it to the .env file.")
|
|
53
|
-
.action(secret.action)
|
|
54
|
-
|
|
55
|
-
program
|
|
56
|
-
.command("add")
|
|
57
|
-
.argument("[provider]", "The authentication provider.")
|
|
58
|
-
.description('Register a new authentication provider')
|
|
59
|
-
.action(add.action)
|
|
60
|
-
|
|
61
|
-
program.parse()
|
|
62
|
-
|
|
63
|
-
export { program }
|