@popoverai/dotrequirements 0.24.0 → 0.24.2
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 +4 -3
- package/dist/cli.js +0 -0
- package/dist/codebase-to-spec/claude.d.ts +1 -0
- package/dist/codebase-to-spec/claude.js +9 -0
- package/dist/codebase-to-spec/pack.d.ts +16 -0
- package/dist/codebase-to-spec/pack.js +17 -3
- package/dist/codebase-to-spec/present.d.ts +8 -1
- package/dist/codebase-to-spec/present.js +7 -4
- package/dist/codebase-to-spec/progress.d.ts +6 -0
- package/dist/codebase-to-spec/progress.js +34 -0
- package/dist/codebase-to-spec/prompts/outline-reviewer.d.ts +1 -1
- package/dist/codebase-to-spec/prompts/outline-reviewer.js +3 -1
- package/dist/codebase-to-spec/prompts/planner-initial.d.ts +1 -1
- package/dist/codebase-to-spec/prompts/planner-initial.js +4 -0
- package/dist/codebase-to-spec/prompts/planner-revise.d.ts +1 -1
- package/dist/codebase-to-spec/prompts/planner-revise.js +2 -2
- package/dist/codebase-to-spec/prompts/spec-reviewer.d.ts +1 -1
- package/dist/codebase-to-spec/prompts/spec-reviewer.js +6 -1
- package/dist/codebase-to-spec/prompts/specifier.d.ts +1 -1
- package/dist/codebase-to-spec/prompts/specifier.js +6 -4
- package/dist/codebase-to-spec/prompts/style-check.d.ts +10 -2
- package/dist/codebase-to-spec/prompts/style-check.js +76 -46
- package/dist/codebase-to-spec/schemas.d.ts +85 -1
- package/dist/codebase-to-spec/schemas.js +25 -1
- package/dist/codebase-to-spec/specifier.js +6 -0
- package/dist/commands/codebase-to-spec/index.js +13 -0
- package/dist/commands/codebase-to-spec/pack.d.ts +6 -0
- package/dist/commands/codebase-to-spec/pack.js +1 -0
- package/dist/commands/codebase-to-spec/present.d.ts +5 -0
- package/dist/commands/codebase-to-spec/present.js +6 -1
- package/dist/commands/codebase-to-spec/run.js +1 -0
- package/package.json +5 -6
- package/dist/codebase-to-spec/prompts/planner-apply.d.ts +0 -12
- package/dist/codebase-to-spec/prompts/planner-apply.js +0 -32
- package/dist/commands/browsertest.d.ts +0 -6
- package/dist/commands/browsertest.js +0 -212
- package/dist/commands/login.d.ts +0 -12
- package/dist/commands/login.js +0 -117
- package/dist/commands/logout.d.ts +0 -5
- package/dist/commands/logout.js +0 -17
- package/dist/commands/mcp-setup.d.ts +0 -5
- package/dist/commands/mcp-setup.js +0 -441
- package/dist/commands/test.d.ts +0 -6
- package/dist/commands/test.js +0 -72
- package/dist/mcp/grep.d.ts +0 -24
- package/dist/mcp/grep.js +0 -306
- package/dist/mcp/handlers/coverage.d.ts +0 -44
- package/dist/mcp/handlers/coverage.js +0 -103
- package/dist/mcp/requirements.d.ts +0 -57
- package/dist/mcp/requirements.js +0 -155
- package/dist/mcp/testCodeExtractor.d.ts +0 -22
- package/dist/mcp/testCodeExtractor.js +0 -150
- package/dist/mcp/types.d.ts +0 -27
- package/dist/mcp/types.js +0 -2
- package/dist/utils/local-project.d.ts +0 -31
- package/dist/utils/local-project.js +0 -33
- package/dist/utils/token-refresh.d.ts +0 -24
- package/dist/utils/token-refresh.js +0 -69
- package/dist/utils/token-storage.d.ts +0 -31
- package/dist/utils/token-storage.js +0 -57
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Extract test code context using @babel/parser AST traversal.
|
|
3
|
-
*
|
|
4
|
-
* Finds requirement() call references and extracts the enclosing
|
|
5
|
-
* meaningful code block (function, describe, test, etc.)
|
|
6
|
-
*/
|
|
7
|
-
import * as fs from "node:fs";
|
|
8
|
-
import { parse } from "@babel/parser";
|
|
9
|
-
import traverse from "@babel/traverse";
|
|
10
|
-
import * as t from "@babel/types";
|
|
11
|
-
/**
|
|
12
|
-
* Find all test code blocks that reference a specific requirement
|
|
13
|
-
*/
|
|
14
|
-
export function findTestCodeForRequirement(filePath, requirementId) {
|
|
15
|
-
try {
|
|
16
|
-
const code = fs.readFileSync(filePath, "utf-8");
|
|
17
|
-
const results = [];
|
|
18
|
-
// Parse with TypeScript and JSX support
|
|
19
|
-
const ast = parse(code, {
|
|
20
|
-
sourceType: "module",
|
|
21
|
-
plugins: ["typescript", "jsx"],
|
|
22
|
-
errorRecovery: true,
|
|
23
|
-
});
|
|
24
|
-
// Handle both ES module and CommonJS exports
|
|
25
|
-
const traverseFunc =
|
|
26
|
-
// biome-ignore lint/suspicious/noExplicitAny: @babel/traverse CJS default-export interop (callable function vs namespace import)
|
|
27
|
-
typeof traverse === "function" ? traverse : traverse.default;
|
|
28
|
-
traverseFunc(ast, {
|
|
29
|
-
CallExpression(path) {
|
|
30
|
-
// Check if this is a requirement('ID', ...) call
|
|
31
|
-
const callee = path.node.callee;
|
|
32
|
-
if (t.isIdentifier(callee) && callee.name === "requirement") {
|
|
33
|
-
const args = path.node.arguments;
|
|
34
|
-
// Extract all string literal arguments (supports multi-requirement calls)
|
|
35
|
-
const refIds = [];
|
|
36
|
-
for (const arg of args) {
|
|
37
|
-
if (t.isStringLiteral(arg)) {
|
|
38
|
-
refIds.push(arg.value);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
// Check if any argument matches the requirement we're looking for
|
|
42
|
-
// Match exact ID or if it's a child (e.g., searching for REQ-123 matches REQ-123.0)
|
|
43
|
-
for (const refId of refIds) {
|
|
44
|
-
const isMatch = refId === requirementId || refId.startsWith(`${requirementId}.`);
|
|
45
|
-
if (isMatch) {
|
|
46
|
-
// Find the meaningful enclosing block
|
|
47
|
-
const contextNode = findMeaningfulParent(path);
|
|
48
|
-
if (contextNode?.node.loc) {
|
|
49
|
-
const { start, end } = contextNode.node.loc;
|
|
50
|
-
const nodeStart = contextNode.node.start ?? 0;
|
|
51
|
-
const nodeEnd = contextNode.node.end ?? code.length;
|
|
52
|
-
results.push({
|
|
53
|
-
file: filePath,
|
|
54
|
-
startLine: start.line,
|
|
55
|
-
endLine: end.line,
|
|
56
|
-
code: code.slice(nodeStart, nodeEnd),
|
|
57
|
-
requirementId: refId,
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
// Only add one result per call expression, even if multiple refs match
|
|
61
|
-
break;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
},
|
|
66
|
-
});
|
|
67
|
-
return results;
|
|
68
|
-
}
|
|
69
|
-
catch (error) {
|
|
70
|
-
console.error(`Error parsing ${filePath}:`, error);
|
|
71
|
-
return [];
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Walk up the AST to find the nearest "meaningful" parent node.
|
|
76
|
-
* This could be a function, describe/test/it call, method, etc.
|
|
77
|
-
*/
|
|
78
|
-
function findMeaningfulParent(path) {
|
|
79
|
-
let current = path;
|
|
80
|
-
while (current) {
|
|
81
|
-
const node = current.node;
|
|
82
|
-
// Check for various meaningful boundaries
|
|
83
|
-
if (t.isFunctionDeclaration(node) ||
|
|
84
|
-
t.isFunctionExpression(node) ||
|
|
85
|
-
t.isArrowFunctionExpression(node) ||
|
|
86
|
-
t.isClassMethod(node) ||
|
|
87
|
-
t.isObjectMethod(node)) {
|
|
88
|
-
return current;
|
|
89
|
-
}
|
|
90
|
-
// Check for call expressions (describe, test, it, etc.)
|
|
91
|
-
if (t.isCallExpression(node)) {
|
|
92
|
-
const callee = node.callee;
|
|
93
|
-
// Common test framework function names
|
|
94
|
-
const testFunctionNames = [
|
|
95
|
-
"describe",
|
|
96
|
-
"it",
|
|
97
|
-
"test",
|
|
98
|
-
"suite",
|
|
99
|
-
"context",
|
|
100
|
-
"beforeEach",
|
|
101
|
-
"afterEach",
|
|
102
|
-
"beforeAll",
|
|
103
|
-
"afterAll",
|
|
104
|
-
];
|
|
105
|
-
if (t.isIdentifier(callee) && testFunctionNames.includes(callee.name)) {
|
|
106
|
-
return current;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
// Check for variable declarations that might contain test functions
|
|
110
|
-
if (t.isVariableDeclarator(node)) {
|
|
111
|
-
return current;
|
|
112
|
-
}
|
|
113
|
-
// Check for export declarations (for Storybook stories, etc.)
|
|
114
|
-
if (t.isExportNamedDeclaration(node) ||
|
|
115
|
-
t.isExportDefaultDeclaration(node)) {
|
|
116
|
-
return current;
|
|
117
|
-
}
|
|
118
|
-
current = current.parentPath;
|
|
119
|
-
}
|
|
120
|
-
return null;
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Find all files that reference a requirement
|
|
124
|
-
*/
|
|
125
|
-
export function findFilesWithRequirement(files, requirementId) {
|
|
126
|
-
const matchingFiles = [];
|
|
127
|
-
for (const file of files) {
|
|
128
|
-
try {
|
|
129
|
-
const code = fs.readFileSync(file, "utf-8");
|
|
130
|
-
// Check for exact match or child references (e.g., AUTH-VALID-LOGIN or AUTH-VALID-LOGIN.0)
|
|
131
|
-
// Simple string search first for performance
|
|
132
|
-
// Patterns match both single and multi-arg calls:
|
|
133
|
-
// requirement('REQ-123')
|
|
134
|
-
// requirement('REQ-123', 'REQ-456')
|
|
135
|
-
// requirement('REQ-456', 'REQ-123') <-- ID anywhere in args
|
|
136
|
-
const hasMatch = code.includes(`'${requirementId}'`) ||
|
|
137
|
-
code.includes(`"${requirementId}"`) ||
|
|
138
|
-
code.includes(`\`${requirementId}\``) ||
|
|
139
|
-
code.includes(`'${requirementId}.`) ||
|
|
140
|
-
code.includes(`"${requirementId}.`) ||
|
|
141
|
-
code.includes(`\`${requirementId}.`);
|
|
142
|
-
if (hasMatch) {
|
|
143
|
-
matchingFiles.push(file);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
catch (error) { }
|
|
147
|
-
}
|
|
148
|
-
return matchingFiles;
|
|
149
|
-
}
|
|
150
|
-
//# sourceMappingURL=testCodeExtractor.js.map
|
package/dist/mcp/types.d.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Re-export shared types from CLI schema module
|
|
3
|
-
*/
|
|
4
|
-
export type { Metadata, RequirementNode, RequirementsFile, } from "../schema/index.js";
|
|
5
|
-
/**
|
|
6
|
-
* Flattened requirement for search results
|
|
7
|
-
*/
|
|
8
|
-
export interface FlattenedRequirement {
|
|
9
|
-
id: string;
|
|
10
|
-
rootId: string;
|
|
11
|
-
label: string;
|
|
12
|
-
content: string;
|
|
13
|
-
path: string[];
|
|
14
|
-
sourceFile: string;
|
|
15
|
-
documentTitle: string;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Test reference found in codebase
|
|
19
|
-
*/
|
|
20
|
-
export interface TestReference {
|
|
21
|
-
file: string;
|
|
22
|
-
line: number;
|
|
23
|
-
column: number;
|
|
24
|
-
requirementId: string;
|
|
25
|
-
context: string;
|
|
26
|
-
}
|
|
27
|
-
//# sourceMappingURL=types.d.ts.map
|
package/dist/mcp/types.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Utilities for detecting and working with local-only projects.
|
|
3
|
-
*
|
|
4
|
-
* Local-only projects use placeholder credentials and have no cloud features.
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
7
|
-
* Check if a project is local-only (no cloud features).
|
|
8
|
-
*
|
|
9
|
-
* Local-only projects have placeholder credentials:
|
|
10
|
-
* - DOTREQUIREMENTS_PROJECT_ID=local
|
|
11
|
-
* - DOTREQUIREMENTS_PROJECT_SECRET=local
|
|
12
|
-
*
|
|
13
|
-
* These projects can use local features (test harness, MCP local operations)
|
|
14
|
-
* but cannot use cloud features (coverage reporting, push/pull, AI features).
|
|
15
|
-
*
|
|
16
|
-
* @param projectId - The project ID to check
|
|
17
|
-
* @returns true if the project is local-only, false otherwise
|
|
18
|
-
*/
|
|
19
|
-
export declare function isLocalOnlyProject(projectId: string | undefined): boolean;
|
|
20
|
-
/**
|
|
21
|
-
* Placeholder credentials for local-only projects.
|
|
22
|
-
*/
|
|
23
|
-
export declare const LOCAL_PROJECT_CREDENTIALS: {
|
|
24
|
-
readonly projectId: "local";
|
|
25
|
-
readonly secret: "local";
|
|
26
|
-
};
|
|
27
|
-
/**
|
|
28
|
-
* Error message for when cloud features are attempted on local-only projects.
|
|
29
|
-
*/
|
|
30
|
-
export declare const CLOUD_FEATURES_REQUIRE_AUTH_MESSAGE = "Cloud features require authentication. Run `dotrequirements login` to enable cloud features.";
|
|
31
|
-
//# sourceMappingURL=local-project.d.ts.map
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Utilities for detecting and working with local-only projects.
|
|
3
|
-
*
|
|
4
|
-
* Local-only projects use placeholder credentials and have no cloud features.
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
7
|
-
* Check if a project is local-only (no cloud features).
|
|
8
|
-
*
|
|
9
|
-
* Local-only projects have placeholder credentials:
|
|
10
|
-
* - DOTREQUIREMENTS_PROJECT_ID=local
|
|
11
|
-
* - DOTREQUIREMENTS_PROJECT_SECRET=local
|
|
12
|
-
*
|
|
13
|
-
* These projects can use local features (test harness, MCP local operations)
|
|
14
|
-
* but cannot use cloud features (coverage reporting, push/pull, AI features).
|
|
15
|
-
*
|
|
16
|
-
* @param projectId - The project ID to check
|
|
17
|
-
* @returns true if the project is local-only, false otherwise
|
|
18
|
-
*/
|
|
19
|
-
export function isLocalOnlyProject(projectId) {
|
|
20
|
-
return projectId === 'local';
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Placeholder credentials for local-only projects.
|
|
24
|
-
*/
|
|
25
|
-
export const LOCAL_PROJECT_CREDENTIALS = {
|
|
26
|
-
projectId: 'local',
|
|
27
|
-
secret: 'local',
|
|
28
|
-
};
|
|
29
|
-
/**
|
|
30
|
-
* Error message for when cloud features are attempted on local-only projects.
|
|
31
|
-
*/
|
|
32
|
-
export const CLOUD_FEATURES_REQUIRE_AUTH_MESSAGE = 'Cloud features require authentication. Run `dotrequirements login` to enable cloud features.';
|
|
33
|
-
//# sourceMappingURL=local-project.js.map
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Token refresh utilities for maintaining long-lived CLI sessions.
|
|
3
|
-
*
|
|
4
|
-
* WorkOS access tokens expire after 5 minutes, but refresh tokens can be used
|
|
5
|
-
* to obtain new access/refresh token pairs. Refresh tokens are single-use and
|
|
6
|
-
* get rotated on each refresh.
|
|
7
|
-
*/
|
|
8
|
-
/**
|
|
9
|
-
* Get a valid access token, refreshing if needed.
|
|
10
|
-
*
|
|
11
|
-
* This function should be called before making any authenticated Convex requests.
|
|
12
|
-
* It checks if the current access token is expired and refreshes it if necessary.
|
|
13
|
-
*
|
|
14
|
-
* Returns null if no tokens are stored (user needs to login).
|
|
15
|
-
*/
|
|
16
|
-
export declare function getValidAccessToken(): Promise<string | null>;
|
|
17
|
-
/**
|
|
18
|
-
* Ensure user is authenticated with a valid access token.
|
|
19
|
-
*
|
|
20
|
-
* Throws an error if not logged in or if token refresh fails.
|
|
21
|
-
* Use this at the start of commands that require authentication.
|
|
22
|
-
*/
|
|
23
|
-
export declare function requireAuth(): Promise<string>;
|
|
24
|
-
//# sourceMappingURL=token-refresh.d.ts.map
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Token refresh utilities for maintaining long-lived CLI sessions.
|
|
3
|
-
*
|
|
4
|
-
* WorkOS access tokens expire after 5 minutes, but refresh tokens can be used
|
|
5
|
-
* to obtain new access/refresh token pairs. Refresh tokens are single-use and
|
|
6
|
-
* get rotated on each refresh.
|
|
7
|
-
*/
|
|
8
|
-
import { ConvexHttpClient } from 'convex/browser';
|
|
9
|
-
import { getTokens, storeTokens, areTokensExpired } from './token-storage.js';
|
|
10
|
-
import { getConvexUrl } from '../config.js';
|
|
11
|
-
import { api } from '../convex.js';
|
|
12
|
-
/**
|
|
13
|
-
* Get a valid access token, refreshing if needed.
|
|
14
|
-
*
|
|
15
|
-
* This function should be called before making any authenticated Convex requests.
|
|
16
|
-
* It checks if the current access token is expired and refreshes it if necessary.
|
|
17
|
-
*
|
|
18
|
-
* Returns null if no tokens are stored (user needs to login).
|
|
19
|
-
*/
|
|
20
|
-
export async function getValidAccessToken() {
|
|
21
|
-
const tokens = await getTokens();
|
|
22
|
-
if (!tokens) {
|
|
23
|
-
return null; // Not logged in
|
|
24
|
-
}
|
|
25
|
-
// If tokens are still valid, return current access token
|
|
26
|
-
if (!areTokensExpired(tokens)) {
|
|
27
|
-
return tokens.accessToken;
|
|
28
|
-
}
|
|
29
|
-
// Tokens expired, refresh them
|
|
30
|
-
try {
|
|
31
|
-
console.log('Access token expired, refreshing...');
|
|
32
|
-
// Refresh tokens via Convex action (server-side WorkOS call)
|
|
33
|
-
const client = new ConvexHttpClient(getConvexUrl());
|
|
34
|
-
const result = await client.action(api.lib.authActions.refreshAccessToken, {
|
|
35
|
-
refreshToken: tokens.refreshToken,
|
|
36
|
-
});
|
|
37
|
-
if (!result.success) {
|
|
38
|
-
throw new Error(`Token refresh failed: ${result.error}`);
|
|
39
|
-
}
|
|
40
|
-
const { accessToken, refreshToken, expiresAt } = result;
|
|
41
|
-
// Store new tokens (IMPORTANT: refresh token is single-use, must update)
|
|
42
|
-
await storeTokens({
|
|
43
|
-
accessToken,
|
|
44
|
-
refreshToken, // New refresh token from response
|
|
45
|
-
expiresAt,
|
|
46
|
-
});
|
|
47
|
-
console.log('✓ Token refreshed successfully');
|
|
48
|
-
return accessToken;
|
|
49
|
-
}
|
|
50
|
-
catch (error) {
|
|
51
|
-
console.error('Failed to refresh access token:', error);
|
|
52
|
-
console.log('Please run "dotrequirements login" to re-authenticate.');
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Ensure user is authenticated with a valid access token.
|
|
58
|
-
*
|
|
59
|
-
* Throws an error if not logged in or if token refresh fails.
|
|
60
|
-
* Use this at the start of commands that require authentication.
|
|
61
|
-
*/
|
|
62
|
-
export async function requireAuth() {
|
|
63
|
-
const accessToken = await getValidAccessToken();
|
|
64
|
-
if (!accessToken) {
|
|
65
|
-
throw new Error('Not authenticated. Please run "dotrequirements login" first.');
|
|
66
|
-
}
|
|
67
|
-
return accessToken;
|
|
68
|
-
}
|
|
69
|
-
//# sourceMappingURL=token-refresh.js.map
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Token storage utilities for OAuth access tokens and refresh tokens.
|
|
3
|
-
*
|
|
4
|
-
* Uses file-based storage at ~/.dotrequirements/tokens.json with restricted permissions.
|
|
5
|
-
*/
|
|
6
|
-
export interface StoredTokens {
|
|
7
|
-
accessToken: string;
|
|
8
|
-
refreshToken: string;
|
|
9
|
-
expiresAt: number;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Store tokens in file storage with restricted permissions
|
|
13
|
-
*/
|
|
14
|
-
export declare function storeTokens(tokens: StoredTokens): Promise<void>;
|
|
15
|
-
/**
|
|
16
|
-
* Retrieve stored tokens from file
|
|
17
|
-
*/
|
|
18
|
-
export declare function getTokens(): Promise<StoredTokens | null>;
|
|
19
|
-
/**
|
|
20
|
-
* Delete stored tokens
|
|
21
|
-
*/
|
|
22
|
-
export declare function deleteTokens(): Promise<void>;
|
|
23
|
-
/**
|
|
24
|
-
* Check if tokens are expired
|
|
25
|
-
*/
|
|
26
|
-
export declare function areTokensExpired(tokens: StoredTokens): boolean;
|
|
27
|
-
/**
|
|
28
|
-
* Check if tokens exist and are valid
|
|
29
|
-
*/
|
|
30
|
-
export declare function hasValidTokens(): Promise<boolean>;
|
|
31
|
-
//# sourceMappingURL=token-storage.d.ts.map
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Token storage utilities for OAuth access tokens and refresh tokens.
|
|
3
|
-
*
|
|
4
|
-
* Uses file-based storage at ~/.dotrequirements/tokens.json with restricted permissions.
|
|
5
|
-
*/
|
|
6
|
-
import * as fs from 'fs';
|
|
7
|
-
import * as path from 'path';
|
|
8
|
-
import * as os from 'os';
|
|
9
|
-
const TOKEN_DIR = path.join(os.homedir(), '.dotrequirements');
|
|
10
|
-
const TOKEN_FILE = path.join(TOKEN_DIR, 'tokens.json');
|
|
11
|
-
/**
|
|
12
|
-
* Store tokens in file storage with restricted permissions
|
|
13
|
-
*/
|
|
14
|
-
export async function storeTokens(tokens) {
|
|
15
|
-
if (!fs.existsSync(TOKEN_DIR)) {
|
|
16
|
-
fs.mkdirSync(TOKEN_DIR, { recursive: true, mode: 0o700 });
|
|
17
|
-
}
|
|
18
|
-
fs.writeFileSync(TOKEN_FILE, JSON.stringify(tokens, null, 2), { mode: 0o600 });
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Retrieve stored tokens from file
|
|
22
|
-
*/
|
|
23
|
-
export async function getTokens() {
|
|
24
|
-
if (fs.existsSync(TOKEN_FILE)) {
|
|
25
|
-
try {
|
|
26
|
-
const content = fs.readFileSync(TOKEN_FILE, 'utf-8');
|
|
27
|
-
return JSON.parse(content);
|
|
28
|
-
}
|
|
29
|
-
catch (error) {
|
|
30
|
-
console.error('Failed to read stored tokens:', error);
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
return null;
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Delete stored tokens
|
|
38
|
-
*/
|
|
39
|
-
export async function deleteTokens() {
|
|
40
|
-
if (fs.existsSync(TOKEN_FILE)) {
|
|
41
|
-
fs.unlinkSync(TOKEN_FILE);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Check if tokens are expired
|
|
46
|
-
*/
|
|
47
|
-
export function areTokensExpired(tokens) {
|
|
48
|
-
return Date.now() >= tokens.expiresAt;
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Check if tokens exist and are valid
|
|
52
|
-
*/
|
|
53
|
-
export async function hasValidTokens() {
|
|
54
|
-
const tokens = await getTokens();
|
|
55
|
-
return tokens !== null && !areTokensExpired(tokens);
|
|
56
|
-
}
|
|
57
|
-
//# sourceMappingURL=token-storage.js.map
|