@passwd/passwd-cli 1.1.0

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.
Files changed (55) hide show
  1. package/dist/commands/contacts.d.ts +3 -0
  2. package/dist/commands/contacts.js +14 -0
  3. package/dist/commands/contacts.js.map +1 -0
  4. package/dist/commands/create.d.ts +19 -0
  5. package/dist/commands/create.js +66 -0
  6. package/dist/commands/create.js.map +1 -0
  7. package/dist/commands/delete.d.ts +3 -0
  8. package/dist/commands/delete.js +21 -0
  9. package/dist/commands/delete.js.map +1 -0
  10. package/dist/commands/envs.d.ts +3 -0
  11. package/dist/commands/envs.js +24 -0
  12. package/dist/commands/envs.js.map +1 -0
  13. package/dist/commands/exec.d.ts +3 -0
  14. package/dist/commands/exec.js +49 -0
  15. package/dist/commands/exec.js.map +1 -0
  16. package/dist/commands/get.d.ts +4 -0
  17. package/dist/commands/get.js +23 -0
  18. package/dist/commands/get.js.map +1 -0
  19. package/dist/commands/groups.d.ts +3 -0
  20. package/dist/commands/groups.js +14 -0
  21. package/dist/commands/groups.js.map +1 -0
  22. package/dist/commands/list.d.ts +7 -0
  23. package/dist/commands/list.js +20 -0
  24. package/dist/commands/list.js.map +1 -0
  25. package/dist/commands/login.d.ts +1 -0
  26. package/dist/commands/login.js +20 -0
  27. package/dist/commands/login.js.map +1 -0
  28. package/dist/commands/resolve.d.ts +10 -0
  29. package/dist/commands/resolve.js +81 -0
  30. package/dist/commands/resolve.js.map +1 -0
  31. package/dist/commands/share.d.ts +4 -0
  32. package/dist/commands/share.js +21 -0
  33. package/dist/commands/share.js.map +1 -0
  34. package/dist/commands/totp.d.ts +3 -0
  35. package/dist/commands/totp.js +26 -0
  36. package/dist/commands/totp.js.map +1 -0
  37. package/dist/commands/update.d.ts +19 -0
  38. package/dist/commands/update.js +68 -0
  39. package/dist/commands/update.js.map +1 -0
  40. package/dist/commands/whoami.d.ts +3 -0
  41. package/dist/commands/whoami.js +12 -0
  42. package/dist/commands/whoami.js.map +1 -0
  43. package/dist/index.d.ts +2 -0
  44. package/dist/index.js +154 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/util/envs.d.ts +7 -0
  47. package/dist/util/envs.js +49 -0
  48. package/dist/util/envs.js.map +1 -0
  49. package/dist/util/format.d.ts +4 -0
  50. package/dist/util/format.js +15 -0
  51. package/dist/util/format.js.map +1 -0
  52. package/dist/util/parse-ref.d.ts +7 -0
  53. package/dist/util/parse-ref.js +21 -0
  54. package/dist/util/parse-ref.js.map +1 -0
  55. package/package.json +35 -0
@@ -0,0 +1,3 @@
1
+ export declare function contactsCommand(opts: {
2
+ json?: boolean;
3
+ }): Promise<void>;
@@ -0,0 +1,14 @@
1
+ import { listContacts } from "@passwd/passwd-lib";
2
+ import { formatJson } from "../util/format.js";
3
+ export async function contactsCommand(opts) {
4
+ const contacts = await listContacts();
5
+ if (opts.json) {
6
+ console.log(formatJson(contacts));
7
+ }
8
+ else {
9
+ for (const c of contacts) {
10
+ console.log(`${c.id}\t${c.name}\t${c.email}`);
11
+ }
12
+ }
13
+ }
14
+ //# sourceMappingURL=contacts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contacts.js","sourceRoot":"","sources":["../../src/commands/contacts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAwB;IAC5D,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;IACtC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;IACpC,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,19 @@
1
+ export declare function createCommand(opts: {
2
+ type: string;
3
+ name: string;
4
+ username?: string;
5
+ password?: string;
6
+ web?: string;
7
+ note?: string;
8
+ tags?: string[];
9
+ group?: string[];
10
+ user?: string[];
11
+ file?: string;
12
+ visibleToAll?: boolean;
13
+ totp?: string;
14
+ cardNumber?: string;
15
+ cvvCode?: string;
16
+ credentials?: string;
17
+ privateKey?: string;
18
+ secureNote?: string;
19
+ }): Promise<void>;
@@ -0,0 +1,66 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { basename } from "node:path";
3
+ import { createSecret } from "@passwd/passwd-lib";
4
+ import { formatJson } from "../util/format.js";
5
+ import { parseRefFlag } from "../util/parse-ref.js";
6
+ export async function createCommand(opts) {
7
+ const payload = {
8
+ type: opts.type,
9
+ name: opts.name,
10
+ };
11
+ if (opts.username !== undefined)
12
+ payload.username = opts.username;
13
+ if (opts.password !== undefined)
14
+ payload.password = opts.password;
15
+ if (opts.web !== undefined)
16
+ payload.web = opts.web;
17
+ if (opts.note !== undefined)
18
+ payload.note = opts.note;
19
+ if (opts.tags !== undefined)
20
+ payload.tags = opts.tags;
21
+ if (opts.group !== undefined) {
22
+ payload.groups = opts.group.map(parseRefFlag);
23
+ }
24
+ if (opts.user !== undefined) {
25
+ payload.whitelistUsers = opts.user.map(parseRefFlag);
26
+ }
27
+ if (opts.file !== undefined) {
28
+ const buf = readFileSync(opts.file);
29
+ const name = basename(opts.file);
30
+ const ext = name.split(".").pop() ?? "";
31
+ const mime = guessMime(ext);
32
+ payload.file = { name, data: `data:${mime};base64,${buf.toString("base64")}` };
33
+ }
34
+ if (opts.visibleToAll !== undefined)
35
+ payload.visibleToAll = opts.visibleToAll;
36
+ if (opts.totp !== undefined)
37
+ payload.TOTP = opts.totp;
38
+ if (opts.cardNumber !== undefined)
39
+ payload.cardNumber = opts.cardNumber;
40
+ if (opts.cvvCode !== undefined)
41
+ payload.cvvCode = opts.cvvCode;
42
+ if (opts.credentials !== undefined)
43
+ payload.credentials = opts.credentials;
44
+ if (opts.privateKey !== undefined)
45
+ payload.privateKey = opts.privateKey;
46
+ if (opts.secureNote !== undefined)
47
+ payload.secureNote = opts.secureNote;
48
+ const secret = await createSecret(payload);
49
+ console.log(formatJson(secret));
50
+ }
51
+ function guessMime(ext) {
52
+ const map = {
53
+ txt: "text/plain",
54
+ pdf: "application/pdf",
55
+ png: "image/png",
56
+ jpg: "image/jpeg",
57
+ jpeg: "image/jpeg",
58
+ gif: "image/gif",
59
+ json: "application/json",
60
+ xml: "application/xml",
61
+ csv: "text/csv",
62
+ zip: "application/zip",
63
+ };
64
+ return map[ext.toLowerCase()] ?? "application/octet-stream";
65
+ }
66
+ //# sourceMappingURL=create.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.js","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function deleteCommand(id: string, opts: {
2
+ yes?: boolean;
3
+ }): Promise<void>;
@@ -0,0 +1,21 @@
1
+ import { createInterface } from "node:readline/promises";
2
+ import { stdin, stdout } from "node:process";
3
+ import { deleteSecret } from "@passwd/passwd-lib";
4
+ export async function deleteCommand(id, opts) {
5
+ if (!opts.yes) {
6
+ const rl = createInterface({ input: stdin, output: stdout });
7
+ try {
8
+ const answer = await rl.question(`Delete secret ${id}? This is irreversible. [y/N] `);
9
+ if (answer.trim().toLowerCase() !== "y") {
10
+ console.log("Aborted.");
11
+ return;
12
+ }
13
+ }
14
+ finally {
15
+ rl.close();
16
+ }
17
+ }
18
+ await deleteSecret(id);
19
+ console.log(`Deleted secret ${id}.`);
20
+ }
21
+ //# sourceMappingURL=delete.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete.js","sourceRoot":"","sources":["../../src/commands/delete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,EAAU,EACV,IAAuB;IAEvB,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QACd,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QAC7D,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,iBAAiB,EAAE,gCAAgC,CAAC,CAAC;YACtF,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,GAAG,EAAE,CAAC;gBACxC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;gBACxB,OAAO;YACT,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,EAAE,CAAC,KAAK,EAAE,CAAC;QACb,CAAC;IACH,CAAC;IAED,MAAM,YAAY,CAAC,EAAE,CAAC,CAAC;IACvB,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;AACvC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function envsCommand(opts: {
2
+ json?: boolean;
3
+ }): Promise<void>;
@@ -0,0 +1,24 @@
1
+ import { getTokenDir } from "@passwd/passwd-lib";
2
+ import { scanTokenFiles } from "../util/envs.js";
3
+ export async function envsCommand(opts) {
4
+ const envs = await scanTokenFiles(getTokenDir());
5
+ if (envs.length === 0) {
6
+ console.log("No known environments. Log in with PASSWD_ORIGIN set first.");
7
+ return;
8
+ }
9
+ const currentOrigin = process.env.PASSWD_ORIGIN?.replace(/\/+$/, "");
10
+ if (opts.json) {
11
+ const out = envs.map((e) => ({
12
+ origin: e.origin,
13
+ current: e.origin === currentOrigin,
14
+ savedAt: e.savedAt,
15
+ }));
16
+ console.log(JSON.stringify(out, null, 2));
17
+ return;
18
+ }
19
+ for (const env of envs) {
20
+ const marker = env.origin === currentOrigin ? " *" : "";
21
+ console.log(`${env.origin}${marker}`);
22
+ }
23
+ }
24
+ //# sourceMappingURL=envs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envs.js","sourceRoot":"","sources":["../../src/commands/envs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAwB;IACxD,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,WAAW,EAAE,CAAC,CAAC;IAEjD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,6DAA6D,CAAC,CAAC;QAC3E,OAAO;IACT,CAAC;IAED,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAErE,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC3B,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,OAAO,EAAE,CAAC,CAAC,MAAM,KAAK,aAAa;YACnC,OAAO,EAAE,CAAC,CAAC,OAAO;SACnB,CAAC,CAAC,CAAC;QACJ,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC1C,OAAO;IACT,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,KAAK,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACxD,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IACxC,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function execCommand(args: string[], opts: {
2
+ inject?: string[];
3
+ }): Promise<void>;
@@ -0,0 +1,49 @@
1
+ import { spawn } from "node:child_process";
2
+ import { getSecret } from "@passwd/passwd-lib";
3
+ export async function execCommand(args, opts) {
4
+ if (!args.length) {
5
+ console.error("Usage: passwd exec --inject VAR=SECRET_ID:FIELD -- command [args...]");
6
+ process.exitCode = 1;
7
+ return;
8
+ }
9
+ const injections = opts.inject ?? [];
10
+ const env = { ...process.env };
11
+ // Scrub passwd credentials so the child only gets the specific fields requested
12
+ delete env.PASSWD_ACCESS_TOKEN;
13
+ delete env.PASSWD_API_URL;
14
+ delete env.PASSWD_CLIENT_ID;
15
+ // Parse and fetch all injections in parallel
16
+ const tasks = injections.map(async (spec) => {
17
+ const eqIdx = spec.indexOf("=");
18
+ if (eqIdx === -1) {
19
+ throw new Error(`Invalid --inject format: '${spec}'. Expected VAR=SECRET_ID:FIELD`);
20
+ }
21
+ const varName = spec.slice(0, eqIdx);
22
+ const rest = spec.slice(eqIdx + 1);
23
+ const colonIdx = rest.indexOf(":");
24
+ if (colonIdx === -1) {
25
+ throw new Error(`Invalid --inject format: '${spec}'. Expected VAR=SECRET_ID:FIELD`);
26
+ }
27
+ const secretId = rest.slice(0, colonIdx);
28
+ const field = rest.slice(colonIdx + 1);
29
+ const secret = await getSecret(secretId);
30
+ const value = secret[field];
31
+ if (value === undefined) {
32
+ throw new Error(`Field '${field}' not found in secret '${secretId}'`);
33
+ }
34
+ return { varName, value: String(value) };
35
+ });
36
+ const resolved = await Promise.all(tasks);
37
+ for (const { varName, value } of resolved) {
38
+ env[varName] = value;
39
+ }
40
+ const [cmd, ...cmdArgs] = args;
41
+ const child = spawn(cmd, cmdArgs, {
42
+ env,
43
+ stdio: "inherit",
44
+ });
45
+ child.on("close", (code) => {
46
+ process.exitCode = code ?? 1;
47
+ });
48
+ }
49
+ //# sourceMappingURL=exec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exec.js","sourceRoot":"","sources":["../../src/commands/exec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAc,EACd,IAA2B;IAE3B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACjB,OAAO,CAAC,KAAK,CAAC,sEAAsE,CAAC,CAAC;QACtF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;IACrC,MAAM,GAAG,GAA2B,EAAE,GAAG,OAAO,CAAC,GAAG,EAA4B,CAAC;IAEjF,gFAAgF;IAChF,OAAO,GAAG,CAAC,mBAAmB,CAAC;IAC/B,OAAO,GAAG,CAAC,cAAc,CAAC;IAC1B,OAAO,GAAG,CAAC,gBAAgB,CAAC;IAE5B,6CAA6C;IAC7C,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,6BAA6B,IAAI,iCAAiC,CAAC,CAAC;QACtF,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,6BAA6B,IAAI,iCAAiC,CAAC,CAAC;QACtF,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;QACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;QAEvC,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,KAAK,GAAI,MAA6C,CAAC,KAAK,CAAC,CAAC;QACpE,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,UAAU,KAAK,0BAA0B,QAAQ,GAAG,CAAC,CAAC;QACxE,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC1C,KAAK,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,QAAQ,EAAE,CAAC;QAC1C,GAAG,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC;IACvB,CAAC;IAED,MAAM,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC;IAC/B,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE;QAChC,GAAG;QACH,KAAK,EAAE,SAAS;KACjB,CAAC,CAAC;IAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;QACzB,OAAO,CAAC,QAAQ,GAAG,IAAI,IAAI,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function getCommand(id: string, opts: {
2
+ field?: string;
3
+ json?: boolean;
4
+ }): Promise<void>;
@@ -0,0 +1,23 @@
1
+ import { getSecret } from "@passwd/passwd-lib";
2
+ import { formatJson } from "../util/format.js";
3
+ export async function getCommand(id, opts) {
4
+ const secret = await getSecret(id);
5
+ if (opts.field) {
6
+ const value = secret[opts.field];
7
+ if (value === undefined) {
8
+ process.stderr.write(`Field '${opts.field}' not found\n`);
9
+ process.exitCode = 1;
10
+ return;
11
+ }
12
+ // Raw value, no trailing newline — designed for $() and piping
13
+ process.stdout.write(String(value));
14
+ return;
15
+ }
16
+ if (opts.json) {
17
+ console.log(formatJson(secret));
18
+ }
19
+ else {
20
+ console.log(formatJson(secret));
21
+ }
22
+ }
23
+ //# sourceMappingURL=get.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get.js","sourceRoot":"","sources":["../../src/commands/get.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,EAAU,EACV,IAAwC;IAExC,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,EAAE,CAAC,CAAC;IAEnC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,MAAM,KAAK,GAAI,MAA6C,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzE,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,KAAK,eAAe,CAAC,CAAC;YAC1D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QACD,+DAA+D;QAC/D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACpC,OAAO;IACT,CAAC;IAED,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IAClC,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IAClC,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function groupsCommand(opts: {
2
+ json?: boolean;
3
+ }): Promise<void>;
@@ -0,0 +1,14 @@
1
+ import { listGroups } from "@passwd/passwd-lib";
2
+ import { formatJson } from "../util/format.js";
3
+ export async function groupsCommand(opts) {
4
+ const groups = await listGroups();
5
+ if (opts.json) {
6
+ console.log(formatJson(groups));
7
+ }
8
+ else {
9
+ for (const g of groups) {
10
+ console.log(`${g.id}\t${g.name}\t${g.email}`);
11
+ }
12
+ }
13
+ }
14
+ //# sourceMappingURL=groups.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"groups.js","sourceRoot":"","sources":["../../src/commands/groups.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAwB;IAC1D,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAClC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IAClC,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;YACvB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ export declare function listCommand(opts: {
2
+ query?: string;
3
+ type?: string;
4
+ limit?: string;
5
+ offset?: string;
6
+ json?: boolean;
7
+ }): Promise<void>;
@@ -0,0 +1,20 @@
1
+ import { listSecrets } from "@passwd/passwd-lib";
2
+ import { formatJson, formatSecretRow } from "../util/format.js";
3
+ export async function listCommand(opts) {
4
+ const result = await listSecrets({
5
+ query: opts.query,
6
+ secretType: opts.type,
7
+ limit: opts.limit !== undefined ? Number(opts.limit) : undefined,
8
+ offset: opts.offset !== undefined ? Number(opts.offset) : undefined,
9
+ });
10
+ if (opts.json) {
11
+ console.log(formatJson(result));
12
+ }
13
+ else {
14
+ console.log(`Total: ${result.totalCount}`);
15
+ for (const s of result.secrets) {
16
+ console.log(formatSecretRow(s));
17
+ }
18
+ }
19
+ }
20
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEhE,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAMjC;IACC,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC;QAC/B,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,UAAU,EAAE,IAAI,CAAC,IAAI;QACrB,KAAK,EAAE,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS;QAChE,MAAM,EAAE,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;KACpE,CAAC,CAAC;IAEH,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IAClC,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,UAAU,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;QAC3C,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YAC/B,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function loginCommand(): Promise<void>;
@@ -0,0 +1,20 @@
1
+ import { createInterface } from "node:readline/promises";
2
+ import { stdin, stdout } from "node:process";
3
+ import { buildOAuthUrl, extractCodeFromRedirectUrl, exchangeCode } from "@passwd/passwd-lib";
4
+ export async function loginCommand() {
5
+ const oauthUrl = await buildOAuthUrl();
6
+ console.log("Open this URL in your browser to authenticate:\n");
7
+ console.log(oauthUrl);
8
+ console.log();
9
+ const rl = createInterface({ input: stdin, output: stdout });
10
+ try {
11
+ const redirectUrl = await rl.question("Paste the redirect URL here: ");
12
+ const code = extractCodeFromRedirectUrl(redirectUrl.trim());
13
+ await exchangeCode(code);
14
+ console.log("Authenticated successfully. Token saved to ~/.passwd/");
15
+ }
16
+ finally {
17
+ rl.close();
18
+ }
19
+ }
20
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,0BAA0B,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE7F,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,QAAQ,GAAG,MAAM,aAAa,EAAE,CAAC;IAEvC,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;IAChE,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACtB,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7D,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC,CAAC;QACvE,MAAM,IAAI,GAAG,0BAA0B,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5D,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,uDAAuD,CAAC,CAAC;IACvE,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * OpenClaw exec secrets provider protocol.
3
+ *
4
+ * Reads a JSON request from stdin:
5
+ * { "protocolVersion": 1, "provider": "passwd", "ids": ["secretId:field", ...] }
6
+ *
7
+ * Writes a JSON response to stdout:
8
+ * { "protocolVersion": 1, "values": { "secretId:field": "value", ... }, "errors": { "id": "msg", ... } }
9
+ */
10
+ export declare function resolveCommand(): Promise<void>;
@@ -0,0 +1,81 @@
1
+ import { getSecret } from "@passwd/passwd-lib";
2
+ /**
3
+ * OpenClaw exec secrets provider protocol.
4
+ *
5
+ * Reads a JSON request from stdin:
6
+ * { "protocolVersion": 1, "provider": "passwd", "ids": ["secretId:field", ...] }
7
+ *
8
+ * Writes a JSON response to stdout:
9
+ * { "protocolVersion": 1, "values": { "secretId:field": "value", ... }, "errors": { "id": "msg", ... } }
10
+ */
11
+ export async function resolveCommand() {
12
+ const input = await readStdin();
13
+ let request;
14
+ try {
15
+ request = JSON.parse(input);
16
+ }
17
+ catch {
18
+ writeResponse({}, { _parse: "Invalid JSON on stdin" });
19
+ return;
20
+ }
21
+ const ids = request.ids ?? [];
22
+ if (!Array.isArray(ids) || ids.length === 0) {
23
+ writeResponse({}, {});
24
+ return;
25
+ }
26
+ // Deduplicate secret IDs to minimize API calls
27
+ const secretIds = [...new Set(ids.map((id) => id.split(":")[0]))];
28
+ const secrets = new Map();
29
+ const fetchErrors = new Map();
30
+ const results = await Promise.allSettled(secretIds.map(async (sid) => {
31
+ const secret = await getSecret(sid);
32
+ return { sid, secret };
33
+ }));
34
+ for (const result of results) {
35
+ if (result.status === "fulfilled") {
36
+ secrets.set(result.value.sid, result.value.secret);
37
+ }
38
+ else {
39
+ const sid = secretIds[results.indexOf(result)];
40
+ fetchErrors.set(sid, String(result.reason));
41
+ }
42
+ }
43
+ const values = {};
44
+ const errors = {};
45
+ for (const id of ids) {
46
+ const [secretId, field = "password"] = id.split(":");
47
+ const fetchError = fetchErrors.get(secretId);
48
+ if (fetchError) {
49
+ errors[id] = fetchError;
50
+ continue;
51
+ }
52
+ const secret = secrets.get(secretId);
53
+ if (!secret) {
54
+ errors[id] = "Secret not found";
55
+ continue;
56
+ }
57
+ const value = secret[field];
58
+ if (value === undefined || value === null) {
59
+ errors[id] = `Field '${field}' not found`;
60
+ continue;
61
+ }
62
+ values[id] = String(value);
63
+ }
64
+ writeResponse(values, errors);
65
+ }
66
+ function writeResponse(values, errors) {
67
+ const response = { protocolVersion: 1, values };
68
+ if (Object.keys(errors).length > 0) {
69
+ response.errors = errors;
70
+ }
71
+ process.stdout.write(JSON.stringify(response) + "\n");
72
+ }
73
+ function readStdin() {
74
+ return new Promise((resolve, reject) => {
75
+ const chunks = [];
76
+ process.stdin.on("data", (chunk) => chunks.push(chunk));
77
+ process.stdin.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8")));
78
+ process.stdin.on("error", reject);
79
+ });
80
+ }
81
+ //# sourceMappingURL=resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/commands/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,KAAK,GAAG,MAAM,SAAS,EAAE,CAAC;IAEhC,IAAI,OAAqD,CAAC;IAC1D,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,aAAa,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,uBAAuB,EAAE,CAAC,CAAC;QACvD,OAAO;IACT,CAAC;IAED,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5C,aAAa,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QACtB,OAAO;IACT,CAAC;IAED,+CAA+C;IAC/C,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClE,MAAM,OAAO,GAAG,IAAI,GAAG,EAAmC,CAAC;IAC3D,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;IAE9C,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CACtC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QAC1B,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;QACpC,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;IACzB,CAAC,CAAC,CACH,CAAC;IAEF,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAClC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,MAA4C,CAAC,CAAC;QAC3F,CAAC;aAAM,CAAC;YACN,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;YAC/C,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,MAAM,MAAM,GAA2B,EAAE,CAAC;IAE1C,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,MAAM,CAAC,QAAQ,EAAE,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrD,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7C,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC;YACxB,SAAS;QACX,CAAC;QACD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,CAAC,EAAE,CAAC,GAAG,kBAAkB,CAAC;YAChC,SAAS;QACX,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5B,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YAC1C,MAAM,CAAC,EAAE,CAAC,GAAG,UAAU,KAAK,aAAa,CAAC;YAC1C,SAAS;QACX,CAAC;QACD,MAAM,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IAED,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,aAAa,CAAC,MAA8B,EAAE,MAA8B;IACnF,MAAM,QAAQ,GAA4B,EAAE,eAAe,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;IACzE,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC;IAC3B,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QACxD,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAChF,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function shareCommand(id: string, opts: {
2
+ revoke?: boolean;
3
+ json?: boolean;
4
+ }): Promise<void>;
@@ -0,0 +1,21 @@
1
+ import { enableSharing, revokeSharing } from "@passwd/passwd-lib";
2
+ import { formatJson } from "../util/format.js";
3
+ export async function shareCommand(id, opts) {
4
+ if (opts.revoke) {
5
+ await revokeSharing(id);
6
+ console.log(`Sharing revoked for secret ${id}.`);
7
+ }
8
+ else {
9
+ const result = await enableSharing(id);
10
+ if (opts.json) {
11
+ console.log(formatJson(result));
12
+ }
13
+ else {
14
+ console.log(`Sharing enabled for secret ${id}.`);
15
+ if (result.shareId) {
16
+ console.log(`Share ID: ${result.shareId}`);
17
+ }
18
+ }
19
+ }
20
+ }
21
+ //# sourceMappingURL=share.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"share.js","sourceRoot":"","sources":["../../src/commands/share.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,EAAU,EACV,IAA0C;IAE1C,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,MAAM,aAAa,CAAC,EAAE,CAAC,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE,GAAG,CAAC,CAAC;IACnD,CAAC;SAAM,CAAC;QACN,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,EAAE,CAAC,CAAC;QACvC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;QAClC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE,GAAG,CAAC,CAAC;YACjD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function totpCommand(id: string, opts: {
2
+ json?: boolean;
3
+ }): Promise<void>;
@@ -0,0 +1,26 @@
1
+ import { getTotpCode } from "@passwd/passwd-lib";
2
+ import { formatJson } from "../util/format.js";
3
+ export async function totpCommand(id, opts) {
4
+ const codes = await getTotpCode(id);
5
+ if (opts.json) {
6
+ console.log(formatJson(codes));
7
+ }
8
+ else {
9
+ // Find the currently valid code
10
+ const now = Math.floor(Date.now() / 1000);
11
+ const current = codes.find((c) => now >= c.validityStart && now < c.validityEnd);
12
+ if (current) {
13
+ const remaining = current.validityEnd - now;
14
+ console.log(`${current.code} (${remaining}s remaining)`);
15
+ }
16
+ else if (codes.length > 0) {
17
+ // Fallback: show the first code
18
+ console.log(codes[0].code);
19
+ }
20
+ else {
21
+ console.error("No TOTP codes returned");
22
+ process.exitCode = 1;
23
+ }
24
+ }
25
+ }
26
+ //# sourceMappingURL=totp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"totp.js","sourceRoot":"","sources":["../../src/commands/totp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,EAAU,EACV,IAAwB;IAExB,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,EAAE,CAAC,CAAC;IACpC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;IACjC,CAAC;SAAM,CAAC;QACN,gCAAgC;QAChC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAC1C,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,aAAa,IAAI,GAAG,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC;QACjF,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,GAAG,GAAG,CAAC;YAC5C,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,KAAK,SAAS,cAAc,CAAC,CAAC;QAC3D,CAAC;aAAM,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,gCAAgC;YAChC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;YACxC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,19 @@
1
+ export declare function updateCommand(id: string, opts: {
2
+ name?: string;
3
+ username?: string;
4
+ password?: string;
5
+ web?: string;
6
+ note?: string;
7
+ tags?: string[];
8
+ group?: string[];
9
+ user?: string[];
10
+ file?: string;
11
+ removeFile?: boolean;
12
+ visibleToAll?: boolean;
13
+ totp?: string;
14
+ cardNumber?: string;
15
+ cvvCode?: string;
16
+ credentials?: string;
17
+ privateKey?: string;
18
+ secureNote?: string;
19
+ }): Promise<void>;
@@ -0,0 +1,68 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { basename } from "node:path";
3
+ import { updateSecret } from "@passwd/passwd-lib";
4
+ import { formatJson } from "../util/format.js";
5
+ import { parseRefFlag } from "../util/parse-ref.js";
6
+ export async function updateCommand(id, opts) {
7
+ const updates = {};
8
+ if (opts.name !== undefined)
9
+ updates.name = opts.name;
10
+ if (opts.username !== undefined)
11
+ updates.username = opts.username;
12
+ if (opts.password !== undefined)
13
+ updates.password = opts.password;
14
+ if (opts.web !== undefined)
15
+ updates.web = opts.web;
16
+ if (opts.note !== undefined)
17
+ updates.note = opts.note;
18
+ if (opts.tags !== undefined)
19
+ updates.tags = opts.tags;
20
+ if (opts.group !== undefined) {
21
+ updates.groups = opts.group.map(parseRefFlag);
22
+ }
23
+ if (opts.user !== undefined) {
24
+ updates.whitelistUsers = opts.user.map(parseRefFlag);
25
+ }
26
+ if (opts.removeFile) {
27
+ updates.file = null;
28
+ }
29
+ else if (opts.file !== undefined) {
30
+ const buf = readFileSync(opts.file);
31
+ const name = basename(opts.file);
32
+ const ext = name.split(".").pop() ?? "";
33
+ const mime = guessMime(ext);
34
+ updates.file = { name, data: `data:${mime};base64,${buf.toString("base64")}` };
35
+ }
36
+ if (opts.visibleToAll !== undefined)
37
+ updates.visibleToAll = opts.visibleToAll;
38
+ if (opts.totp !== undefined)
39
+ updates.TOTP = opts.totp;
40
+ if (opts.cardNumber !== undefined)
41
+ updates.cardNumber = opts.cardNumber;
42
+ if (opts.cvvCode !== undefined)
43
+ updates.cvvCode = opts.cvvCode;
44
+ if (opts.credentials !== undefined)
45
+ updates.credentials = opts.credentials;
46
+ if (opts.privateKey !== undefined)
47
+ updates.privateKey = opts.privateKey;
48
+ if (opts.secureNote !== undefined)
49
+ updates.secureNote = opts.secureNote;
50
+ const secret = await updateSecret(id, updates);
51
+ console.log(formatJson(secret));
52
+ }
53
+ function guessMime(ext) {
54
+ const map = {
55
+ txt: "text/plain",
56
+ pdf: "application/pdf",
57
+ png: "image/png",
58
+ jpg: "image/jpeg",
59
+ jpeg: "image/jpeg",
60
+ gif: "image/gif",
61
+ json: "application/json",
62
+ xml: "application/xml",
63
+ csv: "text/csv",
64
+ zip: "application/zip",
65
+ };
66
+ return map[ext.toLowerCase()] ?? "application/octet-stream";
67
+ }
68
+ //# sourceMappingURL=update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function whoamiCommand(opts: {
2
+ json?: boolean;
3
+ }): Promise<void>;
@@ -0,0 +1,12 @@
1
+ import { getCurrentUser } from "@passwd/passwd-lib";
2
+ import { formatJson } from "../util/format.js";
3
+ export async function whoamiCommand(opts) {
4
+ const user = await getCurrentUser();
5
+ if (opts.json) {
6
+ console.log(formatJson(user));
7
+ }
8
+ else {
9
+ console.log(`${user.name} <${user.email}>`);
10
+ }
11
+ }
12
+ //# sourceMappingURL=whoami.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAwB;IAC1D,MAAM,IAAI,GAAG,MAAM,cAAc,EAAE,CAAC;IACpC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IAChC,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,154 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { loginCommand } from "./commands/login.js";
4
+ import { whoamiCommand } from "./commands/whoami.js";
5
+ import { listCommand } from "./commands/list.js";
6
+ import { getCommand } from "./commands/get.js";
7
+ import { createCommand } from "./commands/create.js";
8
+ import { updateCommand } from "./commands/update.js";
9
+ import { deleteCommand } from "./commands/delete.js";
10
+ import { totpCommand } from "./commands/totp.js";
11
+ import { shareCommand } from "./commands/share.js";
12
+ import { execCommand } from "./commands/exec.js";
13
+ import { groupsCommand } from "./commands/groups.js";
14
+ import { contactsCommand } from "./commands/contacts.js";
15
+ import { envsCommand } from "./commands/envs.js";
16
+ import { resolveCommand } from "./commands/resolve.js";
17
+ import { formatError } from "./util/format.js";
18
+ import { resolveEnv } from "./util/envs.js";
19
+ import { resetDiscoveryCache, getTokenDir } from "@passwd/passwd-lib";
20
+ const program = new Command();
21
+ program
22
+ .name("passwd")
23
+ .description("CLI for passwd.team password manager")
24
+ .version("1.1.0")
25
+ .enablePositionalOptions()
26
+ .option("--env <name>", "Target a specific environment (substring match against known origins)");
27
+ program.hook("preAction", async (thisCommand) => {
28
+ const envName = thisCommand.opts().env;
29
+ if (envName) {
30
+ const origin = await resolveEnv(envName, getTokenDir());
31
+ process.env.PASSWD_ORIGIN = origin;
32
+ resetDiscoveryCache();
33
+ }
34
+ });
35
+ program
36
+ .command("login")
37
+ .description("Authenticate with Google OAuth")
38
+ .action(() => loginCommand().catch(die));
39
+ program
40
+ .command("whoami")
41
+ .description("Show current user")
42
+ .option("--json", "Output as JSON")
43
+ .action((opts) => whoamiCommand(opts).catch(die));
44
+ program
45
+ .command("list")
46
+ .description("List secrets")
47
+ .option("-q, --query <text>", "Search by name, username, or URL")
48
+ .option("-t, --type <type>", "Filter by secret type")
49
+ .option("-l, --limit <n>", "Maximum results")
50
+ .option("-o, --offset <n>", "Skip first N results")
51
+ .option("--json", "Output as JSON")
52
+ .action((opts) => listCommand(opts).catch(die));
53
+ program
54
+ .command("get <id>")
55
+ .description("Get a secret")
56
+ .option("-f, --field <name>", "Output a single field (raw, no newline)")
57
+ .option("--json", "Output as JSON")
58
+ .action((id, opts) => getCommand(id, opts).catch(die));
59
+ program
60
+ .command("create")
61
+ .description("Create a new secret")
62
+ .requiredOption("-t, --type <type>", "Secret type (password, paymentCard, apiCredentials, databaseCredentials, sshKey, secureNote)")
63
+ .requiredOption("-n, --name <name>", "Secret name")
64
+ .option("-u, --username <user>", "Username")
65
+ .option("-p, --password <pass>", "Password")
66
+ .option("-w, --web <url>", "Website URL")
67
+ .option("--note <text>", "Note")
68
+ .option("--tags <tags...>", "Tags")
69
+ .option("--group <id:perms>", "Share with group (ID:read,write — repeatable)", collect, undefined)
70
+ .option("--user <id:perms>", "Share with user (ID:read,write — repeatable)", collect, undefined)
71
+ .option("--file <path>", "Attach a file")
72
+ .option("--visible-to-all", "Make visible to all workspace users")
73
+ .option("--totp <secret>", "TOTP secret key")
74
+ .option("--card-number <num>", "Card number")
75
+ .option("--cvv-code <code>", "CVV code")
76
+ .option("--credentials <creds>", "Database credentials")
77
+ .option("--private-key <key>", "SSH private key")
78
+ .option("--secure-note <text>", "Secure note content")
79
+ .action((opts) => createCommand(opts).catch(die));
80
+ program
81
+ .command("update <id>")
82
+ .description("Update a secret")
83
+ .option("-n, --name <name>", "Name")
84
+ .option("-u, --username <user>", "Username")
85
+ .option("-p, --password <pass>", "Password")
86
+ .option("-w, --web <url>", "Website URL")
87
+ .option("--note <text>", "Note")
88
+ .option("--tags <tags...>", "Tags")
89
+ .option("--group <id:perms>", "Share with group (ID:read,write — repeatable)", collect, undefined)
90
+ .option("--user <id:perms>", "Share with user (ID:read,write — repeatable)", collect, undefined)
91
+ .option("--file <path>", "Attach a file")
92
+ .option("--remove-file", "Remove existing file attachment")
93
+ .option("--visible-to-all", "Make visible to all workspace users")
94
+ .option("--totp <secret>", "TOTP secret key")
95
+ .option("--card-number <num>", "Card number")
96
+ .option("--cvv-code <code>", "CVV code")
97
+ .option("--credentials <creds>", "Database credentials")
98
+ .option("--private-key <key>", "SSH private key")
99
+ .option("--secure-note <text>", "Secure note content")
100
+ .action((id, opts) => updateCommand(id, opts).catch(die));
101
+ program
102
+ .command("delete <id>")
103
+ .description("Delete a secret (irreversible)")
104
+ .option("-y, --yes", "Skip confirmation prompt")
105
+ .action((id, opts) => deleteCommand(id, opts).catch(die));
106
+ program
107
+ .command("totp <id>")
108
+ .description("Get current TOTP code")
109
+ .option("--json", "Output as JSON (includes remaining seconds)")
110
+ .action((id, opts) => totpCommand(id, opts).catch(die));
111
+ program
112
+ .command("share <id>")
113
+ .description("Enable or revoke sharing")
114
+ .option("--revoke", "Revoke sharing instead of enabling")
115
+ .option("--json", "Output as JSON")
116
+ .action((id, opts) => shareCommand(id, opts).catch(die));
117
+ program
118
+ .command("groups")
119
+ .description("List available groups")
120
+ .option("--json", "Output as JSON")
121
+ .action((opts) => groupsCommand(opts).catch(die));
122
+ program
123
+ .command("contacts")
124
+ .description("List available contacts")
125
+ .option("--json", "Output as JSON")
126
+ .action((opts) => contactsCommand(opts).catch(die));
127
+ program
128
+ .command("envs")
129
+ .description("List known environments")
130
+ .option("--json", "Output as JSON")
131
+ .action((opts) => envsCommand(opts).catch(die));
132
+ program
133
+ .command("resolve", { hidden: true })
134
+ .description("Resolve secrets for exec secrets provider (reads JSON from stdin)")
135
+ .action(() => resolveCommand().catch(die));
136
+ program
137
+ .command("exec")
138
+ .description("Run a command with secrets injected as environment variables")
139
+ .option("--inject <mapping...>", "VAR=SECRET_ID:FIELD (repeatable)")
140
+ .argument("[args...]", "Command to execute (after --)")
141
+ .passThroughOptions()
142
+ .action((args, opts) => {
143
+ execCommand(args, opts).catch(die);
144
+ });
145
+ /** Commander repeatable-option accumulator. */
146
+ function collect(val, prev) {
147
+ return prev ? [...prev, val] : [val];
148
+ }
149
+ function die(err) {
150
+ console.error(`Error: ${formatError(err)}`);
151
+ process.exitCode = 1;
152
+ }
153
+ program.parse();
154
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface EnvInfo {
2
+ origin: string;
3
+ file: string;
4
+ savedAt?: number;
5
+ }
6
+ export declare function scanTokenFiles(tokenDir: string): Promise<EnvInfo[]>;
7
+ export declare function resolveEnv(name: string, tokenDir: string): Promise<string>;
@@ -0,0 +1,49 @@
1
+ import { readdir, readFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ export async function scanTokenFiles(tokenDir) {
4
+ let files;
5
+ try {
6
+ files = await readdir(tokenDir);
7
+ }
8
+ catch {
9
+ return [];
10
+ }
11
+ const results = [];
12
+ for (const file of files) {
13
+ if (!file.startsWith("tokens-") || !file.endsWith(".json"))
14
+ continue;
15
+ try {
16
+ const content = await readFile(join(tokenDir, file), "utf-8");
17
+ const tokens = JSON.parse(content);
18
+ if (tokens.origin) {
19
+ results.push({
20
+ origin: tokens.origin,
21
+ file,
22
+ savedAt: tokens.saved_at,
23
+ });
24
+ }
25
+ }
26
+ catch {
27
+ // skip unreadable/corrupt files
28
+ }
29
+ }
30
+ return results;
31
+ }
32
+ export async function resolveEnv(name, tokenDir) {
33
+ const envs = await scanTokenFiles(tokenDir);
34
+ if (envs.length === 0) {
35
+ throw new Error("No known environments. Log in with PASSWD_ORIGIN set first.");
36
+ }
37
+ const lower = name.toLowerCase();
38
+ const matches = envs.filter((e) => e.origin.toLowerCase().includes(lower));
39
+ if (matches.length === 0) {
40
+ const known = envs.map((e) => ` ${e.origin}`).join("\n");
41
+ throw new Error(`No environment matching "${name}". Known environments:\n${known}`);
42
+ }
43
+ if (matches.length > 1) {
44
+ const list = matches.map((e) => ` ${e.origin}`).join("\n");
45
+ throw new Error(`Ambiguous match for "${name}". Matching environments:\n${list}\nBe more specific.`);
46
+ }
47
+ return matches[0].origin;
48
+ }
49
+ //# sourceMappingURL=envs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envs.js","sourceRoot":"","sources":["../../src/util/envs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AASjC,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,QAAgB;IACnD,IAAI,KAAe,CAAC;IACpB,IAAI,CAAC;QACH,KAAK,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,OAAO,GAAc,EAAE,CAAC;IAC9B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,SAAS;QACrE,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;YAC9D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAe,CAAC;YACjD,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClB,OAAO,CAAC,IAAI,CAAC;oBACX,MAAM,EAAE,MAAM,CAAC,MAAM;oBACrB,IAAI;oBACJ,OAAO,EAAE,MAAM,CAAC,QAAQ;iBACzB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,gCAAgC;QAClC,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,IAAY,EACZ,QAAgB;IAEhB,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC5C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CACb,6DAA6D,CAC9D,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IAE3E,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1D,MAAM,IAAI,KAAK,CACb,4BAA4B,IAAI,2BAA2B,KAAK,EAAE,CACnE,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5D,MAAM,IAAI,KAAK,CACb,wBAAwB,IAAI,8BAA8B,IAAI,qBAAqB,CACpF,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { SecretListItem } from "@passwd/passwd-lib";
2
+ export declare function formatError(error: unknown): string;
3
+ export declare function formatJson(data: unknown): string;
4
+ export declare function formatSecretRow(s: SecretListItem): string;
@@ -0,0 +1,15 @@
1
+ export function formatError(error) {
2
+ return error instanceof Error ? error.message : String(error);
3
+ }
4
+ export function formatJson(data) {
5
+ return JSON.stringify(data, null, 2);
6
+ }
7
+ export function formatSecretRow(s) {
8
+ const parts = [s.id, s.type, s.name];
9
+ if (s.username)
10
+ parts.push(s.username);
11
+ if (s.web)
12
+ parts.push(s.web);
13
+ return parts.join("\t");
14
+ }
15
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/util/format.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAa;IACtC,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,CAAiB;IAC/C,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,CAAC,CAAC,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,CAAC,CAAC,GAAG;QAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC7B,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { GroupRef, UserRef } from "@passwd/passwd-lib";
2
+ /**
3
+ * Parse a CLI flag value like "ID:read,write" into a ref object.
4
+ * Format: <id>:<perm1>,<perm2>,...
5
+ * Example: "028h4q:read,write" → { id: "028h4q", accessPermissions: ["read", "write"] }
6
+ */
7
+ export declare function parseRefFlag(value: string): GroupRef | UserRef;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Parse a CLI flag value like "ID:read,write" into a ref object.
3
+ * Format: <id>:<perm1>,<perm2>,...
4
+ * Example: "028h4q:read,write" → { id: "028h4q", accessPermissions: ["read", "write"] }
5
+ */
6
+ export function parseRefFlag(value) {
7
+ const colonIdx = value.indexOf(":");
8
+ if (colonIdx === -1) {
9
+ throw new Error(`Invalid ref format "${value}". Expected ID:permissions (e.g. "abc123:read,write")`);
10
+ }
11
+ const id = value.slice(0, colonIdx);
12
+ const perms = value.slice(colonIdx + 1).split(",").map((p) => p.trim());
13
+ const valid = new Set(["read", "write", "autofillOnly", "passkeyOnly"]);
14
+ for (const p of perms) {
15
+ if (!valid.has(p)) {
16
+ throw new Error(`Invalid permission "${p}". Valid: ${[...valid].join(", ")}`);
17
+ }
18
+ }
19
+ return { id, accessPermissions: perms };
20
+ }
21
+ //# sourceMappingURL=parse-ref.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-ref.js","sourceRoot":"","sources":["../../src/util/parse-ref.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CACb,uBAAuB,KAAK,uDAAuD,CACpF,CAAC;IACJ,CAAC;IACD,MAAM,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IACpC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACxE,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,aAAa,CAAC,CAAC,CAAC;IACxE,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,aAAa,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChF,CAAC;IACH,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,iBAAiB,EAAE,KAA8D,EAAE,CAAC;AACnG,CAAC"}
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@passwd/passwd-cli",
3
+ "version": "1.1.0",
4
+ "description": "CLI for passwd.team password manager",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "passwd": "dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc -b"
15
+ },
16
+ "keywords": [
17
+ "passwd",
18
+ "password-manager",
19
+ "cli",
20
+ "passwd-team"
21
+ ],
22
+ "license": "MIT",
23
+ "dependencies": {
24
+ "@passwd/passwd-lib": "1.1.0",
25
+ "commander": "^13.1.0"
26
+ },
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/pepuscz/passwd.git",
30
+ "directory": "packages/passwd-cli"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public"
34
+ }
35
+ }