pulse-cli-divakar 0.0.0-stage → 1.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/src/index.js ADDED
@@ -0,0 +1,66 @@
1
+
2
+ import "dotenv/config";
3
+
4
+ import express from "express";
5
+ import cors from "cors";
6
+ import { toNodeHandler, fromNodeHeaders } from "better-auth/node";
7
+ import { auth } from "./lib/auth.js";
8
+
9
+ const app = express();
10
+
11
+ const frontendUrl =
12
+ process.env.CLIENT_URL || "http://localhost:3000";
13
+
14
+ const allowedOrigins = [
15
+ "http://localhost:3000",
16
+ frontendUrl,
17
+ ].filter(Boolean);
18
+
19
+ app.set("trust proxy", 1);
20
+
21
+ app.use(
22
+ cors({
23
+ origin: allowedOrigins,
24
+ methods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
25
+ credentials: true,
26
+ })
27
+ );
28
+
29
+ // Better Auth handler must come before express.json().
30
+ app.all("/api/auth/*splat", toNodeHandler(auth));
31
+
32
+ app.use(express.json());
33
+
34
+ app.get("/api/me", async (req, res, next) => {
35
+ try {
36
+ const session = await auth.api.getSession({
37
+ headers: fromNodeHeaders(req.headers),
38
+ });
39
+
40
+ return res.json(session);
41
+ } catch (error) {
42
+ next(error);
43
+ }
44
+ });
45
+
46
+ app.get("/device", (req, res) => {
47
+ const userCode = req.query.user_code;
48
+
49
+ const destination = new URL("/device", frontendUrl);
50
+
51
+ if (typeof userCode === "string") {
52
+ destination.searchParams.set("user_code", userCode);
53
+ }
54
+
55
+ return res.redirect(destination.toString());
56
+ });
57
+
58
+ app.get("/", (_req, res) => {
59
+ res.status(200).send("Pulse API is running");
60
+ });
61
+
62
+ const port = process.env.PORT || 3004;
63
+
64
+ app.listen(port, "0.0.0.0", () => {
65
+ console.log(`Pulse API listening on port ${port}`);
66
+ });
@@ -0,0 +1,29 @@
1
+ import { betterAuth } from "better-auth";
2
+ import { prismaAdapter } from "better-auth/adapters/prisma";
3
+ import { deviceAuthorization } from "better-auth/plugins";
4
+
5
+ import { prisma } from "./db.js";
6
+
7
+ export const auth = betterAuth({
8
+ baseURL: process.env.BETTER_AUTH_URL,
9
+ database: prismaAdapter(prisma, {
10
+ provider: "postgresql",
11
+ }),
12
+ basePath:"/api/auth",
13
+ trustedOrigins:["http://localhost:3000",
14
+ process.env.CLIENT_URL,
15
+ ],
16
+ socialProviders: {
17
+ github: {
18
+ clientId: process.env.GITHUB_CLIENT_ID,
19
+ clientSecret: process.env.GITHUB_CLIENT_SECRET,
20
+ },
21
+ },
22
+ plugins: [
23
+ deviceAuthorization({
24
+ verificationUri: "/device",
25
+ expiresIn:"30m",
26
+ interval:"5s"
27
+ }),
28
+ ],
29
+ });
package/src/lib/db.js ADDED
@@ -0,0 +1,9 @@
1
+ import "dotenv/config";
2
+ import { PrismaNeon } from "@prisma/adapter-neon";
3
+ import { PrismaClient } from "../generated/prisma/client.js";
4
+
5
+ const adapter = new PrismaNeon({
6
+ connectionString: process.env.DATABASE_URL,
7
+ });
8
+
9
+ export const prisma = new PrismaClient({ adapter });
@@ -0,0 +1,84 @@
1
+ import chalk from "chalk";
2
+ import { CONFIG_DIR, TOKEN_FILE } from "../cli/commands/auth/login.js";
3
+ import fs from "node:fs/promises"
4
+
5
+
6
+ export async function getStoredToken() {
7
+ try {
8
+ const data = await fs.readFile(TOKEN_FILE, "utf-8");
9
+ const token = JSON.parse(data);
10
+ return token;
11
+ } catch (error) {
12
+ // File doesn't exist or can't be read
13
+ return null;
14
+ }
15
+ }
16
+
17
+ export async function storeToken(token) {
18
+ try {
19
+ // Ensure config directory exists
20
+ await fs.mkdir(CONFIG_DIR, { recursive: true });
21
+
22
+ // Store token with metadata
23
+ const tokenData = {
24
+ access_token: token.access_token,
25
+ refresh_token: token.refresh_token, // Store if available
26
+ token_type: token.token_type || "Bearer",
27
+ scope: token.scope,
28
+ expires_at: token.expires_in
29
+ ? new Date(Date.now() + token.expires_in * 1000).toISOString()
30
+ : null,
31
+ created_at: new Date().toISOString(),
32
+ };
33
+
34
+ await fs.writeFile(TOKEN_FILE, JSON.stringify(tokenData, null, 2), "utf-8");
35
+ return true;
36
+ } catch (error) {
37
+ console.error(chalk.red("Failed to store token:"), error.message);
38
+ return false;
39
+ }
40
+ }
41
+
42
+ export async function clearStoredToken() {
43
+ try {
44
+ await fs.unlink(TOKEN_FILE);
45
+ return true;
46
+ } catch (error) {
47
+ // File doesn't exist or can't be deleted
48
+ return false;
49
+ }
50
+ }
51
+
52
+ export async function isTokenExpired() {
53
+ const token = await getStoredToken();
54
+ if (!token || !token.expires_at) {
55
+ return true;
56
+ }
57
+
58
+ const expiresAt = new Date(token.expires_at);
59
+ const now = new Date();
60
+
61
+ // Consider expired if less than 5 minutes remaining
62
+ return expiresAt.getTime() - now.getTime() < 5 * 60 * 1000;
63
+ }
64
+
65
+ export async function requireAuth() {
66
+ const token = await getStoredToken();
67
+
68
+ if (!token) {
69
+ console.log(
70
+ chalk.red("❌ Not authenticated. Please run 'your-cli login' first."),
71
+ );
72
+ process.exit(1);
73
+ }
74
+
75
+ if (await isTokenExpired()) {
76
+ console.log(
77
+ chalk.yellow("⚠️ Your session has expired. Please login again."),
78
+ );
79
+ console.log(chalk.gray(" Run: your-cli login\n"));
80
+ process.exit(1);
81
+ }
82
+
83
+ return token;
84
+ }
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.