1
2
The LastPass Raycast Extension project provides an integration
3
for LastPass within the Raycast productivity tool.
4
5
This extension enables users to manage and access their passwords
6
directly from Raycast, enhancing efficiency and security.
7
8
The project focuses on providing a seamless user experience while
9
maintaining robust security measures, making password management
10
both convenient and secure.
11
12
13
15
16
const serializeFromJson = (jsonArray: string): Account[] => {
17
const array: { last_modified_gmt: string; last_touch: string }[] = JSON.parse(jsonArray);
18
const res = array.map(
19
(obj) =>
20
({
21
...obj,
22
lastModified: new Date(parseInt(obj.last_modified_gmt, 10) * 1000),
23
lastTouch: new Date(parseInt(obj.last_touch, 10) * 1000),
24
} as unknown as Account)
25
);
26
return res;
27
};
28
29
// Platform-specific command builders
30
const buildMacOSCommand = (command: string): string => {
31
const PATH = "/usr/gnu/bin:/usr/local/bin:/bin:/usr/bin:.:/opt/homebrew/bin";
32
return `zsh -l -c 'export PATH="$PATH:${PATH}" && ${command}'`;
33
};
34
35
36
37
38
39
40
const serializeFromJson = (jsonArray: string): Account[] => {
const array: { last_modified_gmt: string; last_touch: string }[] = JSON.parse(jsonArray);
const res = array.map(
(obj) =>
({
...obj,
lastModified: new Date(parseInt(obj.last_modified_gmt, 10) * 1000),
lastTouch: new Date(parseInt(obj.last_touch, 10) * 1000),
} as unknown as Account)
);
return res;
};
// Platform-specific command builders
const buildMacOSCommand = (command: string): string => {
const PATH = "/usr/gnu/bin:/usr/local/bin:/bin:/usr/bin:.:/opt/homebrew/bin";
return `zsh -l -c 'export PATH="$PATH:${PATH}" && ${command}'`;
};
const execute = async (command: string) => {
const wrappedCommand = isWindows ? buildWindowsCommand(command) : buildMacOSCommand(command);
console.log(`Executing: ${wrappedCommand}`);
const startTimestamp = Date.now();
return new Promise<string>((res, rej) =>
exec(
wrappedCommand,
{ maxBuffer: 4 * 1024 * 1024 }, // 4 times bigger stdout buffer size for large sets of credentials
(error: ExecException | null, stdout: string, stderr: string) => {
const tookSeconds = (Date.now() - startTimestamp) / 1000;
if (error) {
console.error(`[${tookSeconds}s] Failed:\n${stderr}`);
rej({
...error,
message: error.message,
});
}
console.log(`[${tookSeconds}s] Success:\n${stdout}`);
res(stdout.trim());
}
)
);
};
const authorizeMacOS = (subcommand: string, password: string): string => {
const quote = password?.includes('"') ? "'" : '"';
return `echo ${quote}${password}${quote} | LPASS_DISABLE_PINENTRY=1 lpass ${subcommand}`;
};
const authorizeWindows = (subcommand: string, password: string): string => {
// PowerShell requires backtick escaping for special characters
// Escape backticks FIRST (since backtick is the escape character)
let escapedPassword = password.replace(/`/g, "``");
// Then escape other special characters: dollar ($), double-quote (")
escapedPassword = escapedPassword.replace(/[$"]/g, "`$&");
// Use double quotes with properly escaped password
return `$env:LPASS_DISABLE_PINENTRY=1; echo "${escapedPassword}" | lpass ${subcommand}`;
};
const authorize = (subcommand: string, opts: { password: string }) => {
const { password } = opts;
return isWindows ? authorizeWindows(subcommand, password) : authorizeMacOS(subcommand, password);
};
export const isValidUrl = (urlLike: string | undefined) => urlLike && urlLike !== "http://sn";
export const getDomainFavicon = (url: string | undefined): Image.ImageLike => {
if (!url) {
return Icon.Key;
}
try {
new URL(url || "");
return getFavicon(url);
} catch {
return Icon.Key;
}
};