@calltelemetry/cli 0.5.18 → 0.6.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 (37) hide show
  1. package/dist/lib/certs.d.ts +16 -2
  2. package/dist/lib/certs.d.ts.map +1 -1
  3. package/dist/lib/certs.js +80 -8
  4. package/dist/lib/certs.js.map +1 -1
  5. package/dist/lib/identity.d.ts +38 -0
  6. package/dist/lib/identity.d.ts.map +1 -0
  7. package/dist/lib/identity.js +85 -0
  8. package/dist/lib/identity.js.map +1 -0
  9. package/dist/lib/prefs.d.ts +4 -0
  10. package/dist/lib/prefs.d.ts.map +1 -1
  11. package/dist/lib/prefs.js.map +1 -1
  12. package/dist/lib/time.d.ts +57 -0
  13. package/dist/lib/time.d.ts.map +1 -0
  14. package/dist/lib/time.js +200 -0
  15. package/dist/lib/time.js.map +1 -0
  16. package/dist/lib/users.d.ts.map +1 -1
  17. package/dist/lib/users.js +13 -5
  18. package/dist/lib/users.js.map +1 -1
  19. package/dist/lib/version.d.ts +1 -1
  20. package/dist/lib/version.d.ts.map +1 -1
  21. package/dist/lib/version.js +1 -1
  22. package/dist/lib/version.js.map +1 -1
  23. package/dist/shell/commands/config.d.ts +3 -0
  24. package/dist/shell/commands/config.d.ts.map +1 -1
  25. package/dist/shell/commands/config.js +76 -3
  26. package/dist/shell/commands/config.js.map +1 -1
  27. package/dist/shell/commands/diag.d.ts.map +1 -1
  28. package/dist/shell/commands/diag.js +73 -0
  29. package/dist/shell/commands/diag.js.map +1 -1
  30. package/dist/shell/commands/registry.d.ts.map +1 -1
  31. package/dist/shell/commands/registry.js +16 -2
  32. package/dist/shell/commands/registry.js.map +1 -1
  33. package/dist/shell/network-onboarding.d.ts +40 -10
  34. package/dist/shell/network-onboarding.d.ts.map +1 -1
  35. package/dist/shell/network-onboarding.js +638 -177
  36. package/dist/shell/network-onboarding.js.map +1 -1
  37. package/package.json +1 -1
@@ -1,3 +1,17 @@
1
- export declare function generateSelfSignedCerts(): Promise<void>;
2
- export declare function resetCerts(): Promise<void>;
1
+ export declare function generateSelfSignedCerts(hostnameOverride?: string, ip?: string): Promise<void>;
2
+ export declare function resetCerts(hostnameOverride?: string, ip?: string): Promise<void>;
3
+ /** Generate a CSR (Certificate Signing Request) for CA signing. Returns CSR PEM string. */
4
+ export declare function generateCsr(hostnameOverride: string): Promise<string>;
5
+ /** Import a CA-signed certificate + key. Validates cert/key match before copying. */
6
+ export declare function importCert(certPath: string, keyPath: string): Promise<{
7
+ ok: boolean;
8
+ error?: string;
9
+ }>;
10
+ /** Get current certificate info (CN, SAN, expiry, issuer). */
11
+ export declare function getCertInfo(): {
12
+ cn: string;
13
+ san: string[];
14
+ expiry: string;
15
+ issuer: string;
16
+ } | null;
3
17
  //# sourceMappingURL=certs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"certs.d.ts","sourceRoot":"","sources":["../../src/lib/certs.ts"],"names":[],"mappings":"AAMA,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,IAAI,CAAC,CAkB7D;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAQhD"}
1
+ {"version":3,"file":"certs.d.ts","sourceRoot":"","sources":["../../src/lib/certs.ts"],"names":[],"mappings":"AASA,wBAAsB,uBAAuB,CAAC,gBAAgB,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0BnG;AAED,wBAAsB,UAAU,CAAC,gBAAgB,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQtF;AAED,2FAA2F;AAC3F,wBAAsB,WAAW,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgB3E;AAED,qFAAqF;AACrF,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA2B5G;AAED,8DAA8D;AAC9D,wBAAgB,WAAW,IAAI;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAwBlG"}
package/dist/lib/certs.js CHANGED
@@ -1,29 +1,101 @@
1
- import { existsSync } from 'node:fs';
1
+ import { existsSync, readFileSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
+ import { execSync } from 'node:child_process';
4
+ import { hostname } from 'node:os';
3
5
  import { exec } from './exec.js';
4
6
  import { getPaths } from './paths.js';
5
7
  import { mkdirSafe } from './fs.js';
6
- export async function generateSelfSignedCerts() {
8
+ // Keep backward compat — no-args version uses system hostname
9
+ export async function generateSelfSignedCerts(hostnameOverride, ip) {
7
10
  const { certsDir } = getPaths();
8
11
  const certFile = join(certsDir, 'appliance.crt');
9
12
  const keyFile = join(certsDir, 'appliance_key.pem');
10
- if (existsSync(certFile) && existsSync(keyFile)) {
11
- return;
13
+ if (existsSync(certFile) && existsSync(keyFile) && !hostnameOverride) {
14
+ return; // Don't regenerate if certs exist and no hostname override
12
15
  }
13
16
  await mkdirSafe(certsDir);
17
+ const cn = hostnameOverride || hostname() || 'appliance.calltelemetry.internal';
18
+ // Build SAN extension for IP + hostname
19
+ const sanParts = [`DNS:${cn}`];
20
+ if (ip)
21
+ sanParts.push(`IP:${ip}`);
22
+ const sanExt = `subjectAltName=${sanParts.join(',')}`;
14
23
  await exec('openssl', [
15
- 'req', '-x509', '-nodes', '-days', '365',
24
+ 'req', '-x509', '-nodes', '-days', '3650',
16
25
  '-newkey', 'rsa:2048',
17
26
  '-keyout', keyFile,
18
27
  '-out', certFile,
19
- '-subj', '/CN=appliance.calltelemetry.internal',
28
+ '-subj', `/CN=${cn}`,
29
+ '-addext', sanExt,
20
30
  ]);
21
31
  }
22
- export async function resetCerts() {
32
+ export async function resetCerts(hostnameOverride, ip) {
23
33
  const { certsDir } = getPaths();
24
34
  if (existsSync(certsDir)) {
25
35
  await exec('sudo', ['rm', '-rf', certsDir]);
26
36
  }
27
- await generateSelfSignedCerts();
37
+ await generateSelfSignedCerts(hostnameOverride, ip);
38
+ }
39
+ /** Generate a CSR (Certificate Signing Request) for CA signing. Returns CSR PEM string. */
40
+ export async function generateCsr(hostnameOverride) {
41
+ const { certsDir } = getPaths();
42
+ await mkdirSafe(certsDir);
43
+ const csrFile = join(certsDir, 'appliance.csr');
44
+ const keyFile = join(certsDir, 'appliance_csr_key.pem');
45
+ await exec('openssl', [
46
+ 'req', '-new', '-nodes',
47
+ '-newkey', 'rsa:2048',
48
+ '-keyout', keyFile,
49
+ '-out', csrFile,
50
+ '-subj', `/CN=${hostnameOverride}`,
51
+ ]);
52
+ return readFileSync(csrFile, 'utf-8');
53
+ }
54
+ /** Import a CA-signed certificate + key. Validates cert/key match before copying. */
55
+ export async function importCert(certPath, keyPath) {
56
+ if (!existsSync(certPath))
57
+ return { ok: false, error: `Certificate file not found: ${certPath}` };
58
+ if (!existsSync(keyPath))
59
+ return { ok: false, error: `Key file not found: ${keyPath}` };
60
+ // Verify cert and key match by comparing modulus
61
+ try {
62
+ const certMod = execSync(`openssl x509 -noout -modulus -in "${certPath}"`, { encoding: 'utf-8' }).trim();
63
+ const keyMod = execSync(`openssl rsa -noout -modulus -in "${keyPath}"`, { encoding: 'utf-8' }).trim();
64
+ if (certMod !== keyMod) {
65
+ return { ok: false, error: 'Certificate and key do not match (modulus mismatch)' };
66
+ }
67
+ }
68
+ catch {
69
+ return { ok: false, error: 'Failed to verify certificate/key pair — check PEM format' };
70
+ }
71
+ const { certsDir } = getPaths();
72
+ await mkdirSafe(certsDir);
73
+ const destCert = join(certsDir, 'appliance.crt');
74
+ const destKey = join(certsDir, 'appliance_key.pem');
75
+ await exec('sudo', ['cp', certPath, destCert]);
76
+ await exec('sudo', ['cp', keyPath, destKey]);
77
+ await exec('sudo', ['chmod', '644', destCert]);
78
+ await exec('sudo', ['chmod', '600', destKey]);
79
+ return { ok: true };
80
+ }
81
+ /** Get current certificate info (CN, SAN, expiry, issuer). */
82
+ export function getCertInfo() {
83
+ const { certsDir } = getPaths();
84
+ const certFile = join(certsDir, 'appliance.crt');
85
+ if (!existsSync(certFile))
86
+ return null;
87
+ try {
88
+ const text = execSync(`openssl x509 -in "${certFile}" -noout -subject -enddate -issuer -ext subjectAltName`, { encoding: 'utf-8' });
89
+ const cn = text.match(/subject=.*?CN\s*=\s*([^\n/]+)/)?.[1]?.trim() ?? 'unknown';
90
+ const expiry = text.match(/notAfter=(.+)/)?.[1]?.trim() ?? 'unknown';
91
+ const issuer = text.match(/issuer=.*?CN\s*=\s*([^\n/]+)/)?.[1]?.trim() ?? 'unknown';
92
+ const sanMatch = text.match(/DNS:([^\s,]+)/g) ?? [];
93
+ const ipMatch = text.match(/IP Address:([^\s,]+)/g) ?? [];
94
+ const san = [...sanMatch, ...ipMatch].map(s => s.replace(/^(DNS:|IP Address:)/, ''));
95
+ return { cn, san, expiry, issuer };
96
+ }
97
+ catch {
98
+ return null;
99
+ }
28
100
  }
29
101
  //# sourceMappingURL=certs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"certs.js","sourceRoot":"","sources":["../../src/lib/certs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,MAAM,CAAC,KAAK,UAAU,uBAAuB;IAC3C,MAAM,EAAE,QAAQ,EAAE,GAAG,QAAQ,EAAE,CAAC;IAChC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;IACjD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;IAEpD,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAChD,OAAO;IACT,CAAC;IAED,MAAM,SAAS,CAAC,QAAQ,CAAC,CAAC;IAE1B,MAAM,IAAI,CAAC,SAAS,EAAE;QACpB,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK;QACxC,SAAS,EAAE,UAAU;QACrB,SAAS,EAAE,OAAO;QAClB,MAAM,EAAE,QAAQ;QAChB,OAAO,EAAE,sCAAsC;KAChD,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,EAAE,QAAQ,EAAE,GAAG,QAAQ,EAAE,CAAC;IAEhC,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,uBAAuB,EAAE,CAAC;AAClC,CAAC"}
1
+ {"version":3,"file":"certs.js","sourceRoot":"","sources":["../../src/lib/certs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Hostname, admin password, and system identity helpers.
3
+ */
4
+ /**
5
+ * Get the current static hostname via hostnamectl.
6
+ * Falls back to 'ct-appliance' on error.
7
+ */
8
+ export declare function getHostname(): string;
9
+ /**
10
+ * Validate a hostname per RFC 1123.
11
+ * Alphanumeric + hyphens, 1-63 chars, no leading/trailing hyphen, no dots.
12
+ */
13
+ export declare function isValidHostname(h: string): boolean;
14
+ /**
15
+ * Build a fully qualified domain name from hostname and search domain.
16
+ * Returns just the hostname if the domain is empty.
17
+ */
18
+ export declare function buildFqdn(hostname: string, searchDomain: string): string;
19
+ /**
20
+ * Apply a hostname to the system via hostnamectl.
21
+ * Returns true if the command succeeds.
22
+ */
23
+ export declare function applyHostname(h: string): boolean;
24
+ /**
25
+ * Validate password strength.
26
+ * Requires minimum 12 characters, uppercase, lowercase, and digit.
27
+ */
28
+ export declare function isStrongPassword(pw: string): {
29
+ valid: boolean;
30
+ reason?: string;
31
+ };
32
+ /**
33
+ * Apply a new admin (root) password via chpasswd.
34
+ * IMPORTANT: never log the password.
35
+ * Returns true if the command succeeds.
36
+ */
37
+ export declare function applyAdminPassword(pw: string): boolean;
38
+ //# sourceMappingURL=identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/lib/identity.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;GAGG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAMpC;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAElD;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAKxE;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAShD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAchF;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAUtD"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Hostname, admin password, and system identity helpers.
3
+ */
4
+ import { execSync, spawnSync } from 'node:child_process';
5
+ /**
6
+ * Get the current static hostname via hostnamectl.
7
+ * Falls back to 'ct-appliance' on error.
8
+ */
9
+ export function getHostname() {
10
+ try {
11
+ return execSync('hostnamectl --static', { encoding: 'utf-8' }).trim();
12
+ }
13
+ catch {
14
+ return 'ct-appliance';
15
+ }
16
+ }
17
+ /**
18
+ * Validate a hostname per RFC 1123.
19
+ * Alphanumeric + hyphens, 1-63 chars, no leading/trailing hyphen, no dots.
20
+ */
21
+ export function isValidHostname(h) {
22
+ return /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/.test(h);
23
+ }
24
+ /**
25
+ * Build a fully qualified domain name from hostname and search domain.
26
+ * Returns just the hostname if the domain is empty.
27
+ */
28
+ export function buildFqdn(hostname, searchDomain) {
29
+ if (searchDomain && searchDomain.trim().length > 0) {
30
+ return `${hostname}.${searchDomain.trim()}`;
31
+ }
32
+ return hostname;
33
+ }
34
+ /**
35
+ * Apply a hostname to the system via hostnamectl.
36
+ * Returns true if the command succeeds.
37
+ */
38
+ export function applyHostname(h) {
39
+ try {
40
+ const result = spawnSync('sudo', ['hostnamectl', 'set-hostname', h], {
41
+ stdio: 'pipe',
42
+ });
43
+ return result.status === 0;
44
+ }
45
+ catch {
46
+ return false;
47
+ }
48
+ }
49
+ /**
50
+ * Validate password strength.
51
+ * Requires minimum 12 characters, uppercase, lowercase, and digit.
52
+ */
53
+ export function isStrongPassword(pw) {
54
+ if (pw.length < 12) {
55
+ return { valid: false, reason: 'Too short (min 12 characters)' };
56
+ }
57
+ if (!/[A-Z]/.test(pw)) {
58
+ return { valid: false, reason: 'Must contain at least one uppercase letter' };
59
+ }
60
+ if (!/[a-z]/.test(pw)) {
61
+ return { valid: false, reason: 'Must contain at least one lowercase letter' };
62
+ }
63
+ if (!/[0-9]/.test(pw)) {
64
+ return { valid: false, reason: 'Must contain at least one digit' };
65
+ }
66
+ return { valid: true };
67
+ }
68
+ /**
69
+ * Apply a new admin (root) password via chpasswd.
70
+ * IMPORTANT: never log the password.
71
+ * Returns true if the command succeeds.
72
+ */
73
+ export function applyAdminPassword(pw) {
74
+ try {
75
+ const result = spawnSync('sudo', ['chpasswd'], {
76
+ input: `root:${pw}`,
77
+ stdio: 'pipe',
78
+ });
79
+ return result.status === 0;
80
+ }
81
+ catch {
82
+ return false;
83
+ }
84
+ }
85
+ //# sourceMappingURL=identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/lib/identity.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEzD;;;GAGG;AACH,MAAM,UAAU,WAAW;IACzB,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,sBAAsB,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACxE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,cAAc,CAAC;IACxB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,CAAS;IACvC,OAAO,+CAA+C,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACjE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,QAAgB,EAAE,YAAoB;IAC9D,IAAI,YAAY,IAAI,YAAY,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnD,OAAO,GAAG,QAAQ,IAAI,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC;IAC9C,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,CAAS;IACrC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,aAAa,EAAE,cAAc,EAAE,CAAC,CAAC,EAAE;YACnE,KAAK,EAAE,MAAM;SACd,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,EAAU;IACzC,IAAI,EAAE,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACnB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,+BAA+B,EAAE,CAAC;IACnE,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,4CAA4C,EAAE,CAAC;IAChF,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,4CAA4C,EAAE,CAAC;IAChF,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,iCAAiC,EAAE,CAAC;IACrE,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACzB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,EAAU;IAC3C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,EAAE;YAC7C,KAAK,EAAE,QAAQ,EAAE,EAAE;YACnB,KAAK,EAAE,MAAM;SACd,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -6,6 +6,10 @@ export interface Preferences {
6
6
  deploymentMode: 'docker-compose' | 'k3s';
7
7
  k8sNamespace: string;
8
8
  k8sEnvironment: 'ct-dev' | 'ct-prod' | 'ct-test';
9
+ timezone?: string;
10
+ ntpServers?: string[];
11
+ hostname?: string;
12
+ location?: string;
9
13
  }
10
14
  /**
11
15
  * Load preferences from ~/.ct/preferences.json.
@@ -1 +1 @@
1
- {"version":3,"file":"prefs.d.ts","sourceRoot":"","sources":["../../src/lib/prefs.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,cAAc,EAAE,gBAAgB,GAAG,KAAK,CAAC;IACzC,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;CAClD;AAeD;;;GAGG;AACH,wBAAgB,SAAS,IAAI,WAAW,GAAG,IAAI,CAU9C;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAQlD;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI,WAAW,CAEtC"}
1
+ {"version":3,"file":"prefs.d.ts","sourceRoot":"","sources":["../../src/lib/prefs.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,cAAc,EAAE,gBAAgB,GAAG,KAAK,CAAC;IACzC,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAeD;;;GAGG;AACH,wBAAgB,SAAS,IAAI,WAAW,GAAG,IAAI,CAU9C;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAQlD;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI,WAAW,CAEtC"}
@@ -1 +1 @@
1
- {"version":3,"file":"prefs.js","sourceRoot":"","sources":["../../src/lib/prefs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAYjC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,CAAC,CAAC;AACzC,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;AAEvD,MAAM,QAAQ,GAAgB;IAC5B,UAAU,EAAE,KAAK;IACjB,IAAI,EAAE,KAAK;IACX,IAAI,EAAE,KAAK;IACX,KAAK,EAAE,KAAK;IACZ,cAAc,EAAE,gBAAgB;IAChC,YAAY,EAAE,IAAI;IAClB,cAAc,EAAE,QAAQ;CACzB,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;YAAE,OAAO,IAAI,CAAC;QACzC,MAAM,GAAG,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,OAAO,EAAE,GAAG,QAAQ,EAAE,GAAG,MAAM,EAAE,CAAC;IACpC,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,KAAK,CAAC,+BAA+B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,KAAkB;IAC1C,IAAI,CAAC;QACH,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1C,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;QAC1E,KAAK,CAAC,wBAAwB,UAAU,EAAE,CAAC,CAAC;IAC9C,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,KAAK,CAAC,+BAA+B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IACtD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ;IACtB,OAAO,SAAS,EAAE,IAAI,QAAQ,CAAC;AACjC,CAAC"}
1
+ {"version":3,"file":"prefs.js","sourceRoot":"","sources":["../../src/lib/prefs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAgBjC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,CAAC,CAAC;AACzC,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;AAEvD,MAAM,QAAQ,GAAgB;IAC5B,UAAU,EAAE,KAAK;IACjB,IAAI,EAAE,KAAK;IACX,IAAI,EAAE,KAAK;IACX,KAAK,EAAE,KAAK;IACZ,cAAc,EAAE,gBAAgB;IAChC,YAAY,EAAE,IAAI;IAClB,cAAc,EAAE,QAAQ;CACzB,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;YAAE,OAAO,IAAI,CAAC;QACzC,MAAM,GAAG,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,OAAO,EAAE,GAAG,QAAQ,EAAE,GAAG,MAAM,EAAE,CAAC;IACpC,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,KAAK,CAAC,+BAA+B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,KAAkB;IAC1C,IAAI,CAAC;QACH,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1C,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;QAC1E,KAAK,CAAC,wBAAwB,UAAU,EAAE,CAAC,CAAC;IAC9C,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,KAAK,CAAC,+BAA+B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IACtD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ;IACtB,OAAO,SAAS,EAAE,IAAI,QAAQ,CAAC;AACjC,CAAC"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Timezone and NTP system helpers using timedatectl and systemd-timesyncd.
3
+ */
4
+ export interface TimezoneEntry {
5
+ value: string;
6
+ label: string;
7
+ offset: string;
8
+ note?: string;
9
+ }
10
+ export interface TimezoneRegion {
11
+ name: string;
12
+ zones: TimezoneEntry[];
13
+ }
14
+ export declare const TIMEZONE_REGIONS: TimezoneRegion[];
15
+ export declare const DEFAULT_NTP: string[];
16
+ /**
17
+ * Get the current system timezone via timedatectl.
18
+ * Falls back to 'UTC' on error.
19
+ */
20
+ export declare function getSystemTimezone(): string;
21
+ /**
22
+ * Search available timezones by query string.
23
+ * Returns up to 10 matches with label/offset metadata when available.
24
+ */
25
+ export declare function searchTimezones(query: string): TimezoneEntry[];
26
+ /**
27
+ * Check if a timezone string is valid according to the system.
28
+ */
29
+ export declare function isValidTimezone(tz: string): boolean;
30
+ /**
31
+ * Apply a timezone to the system via timedatectl.
32
+ * Returns true if the command succeeds.
33
+ */
34
+ export declare function applyTimezone(tz: string): boolean;
35
+ /**
36
+ * Compute the current UTC offset for a given IANA timezone.
37
+ * Returns a string like 'UTC-6' or 'UTC+9'.
38
+ */
39
+ export declare function getUtcOffset(tz: string): string;
40
+ /**
41
+ * Get NTP synchronization status from timedatectl.
42
+ */
43
+ export declare function getNtpSyncStatus(): {
44
+ synced: boolean;
45
+ server?: string;
46
+ };
47
+ /**
48
+ * Apply custom NTP servers by writing a timesyncd drop-in config
49
+ * and restarting the service.
50
+ * Returns true if both the write and restart succeed.
51
+ */
52
+ export declare function applyNtpServers(server1: string, server2?: string): boolean;
53
+ /**
54
+ * Check if NTP is currently synchronized.
55
+ */
56
+ export declare function checkNtpSync(): boolean;
57
+ //# sourceMappingURL=time.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time.d.ts","sourceRoot":"","sources":["../../src/lib/time.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,aAAa,EAAE,CAAC;CACxB;AAED,eAAO,MAAM,gBAAgB,EAAE,cAAc,EA4C5C,CAAC;AAEF,eAAO,MAAM,WAAW,UAAuC,CAAC;AAKhE;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAQ1C;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,EAAE,CAoB9D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAQnD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CASjD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAgB/C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAkBvE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CA0B1E;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAEtC"}
@@ -0,0 +1,200 @@
1
+ /**
2
+ * Timezone and NTP system helpers using timedatectl and systemd-timesyncd.
3
+ */
4
+ import { execSync, spawnSync } from 'node:child_process';
5
+ export const TIMEZONE_REGIONS = [
6
+ {
7
+ name: 'Americas',
8
+ zones: [
9
+ { value: 'America/New_York', label: 'Eastern', offset: 'UTC-5' },
10
+ { value: 'America/Chicago', label: 'Central', offset: 'UTC-6' },
11
+ { value: 'America/Denver', label: 'Mountain', offset: 'UTC-7' },
12
+ { value: 'America/Los_Angeles', label: 'Pacific', offset: 'UTC-8' },
13
+ { value: 'America/Anchorage', label: 'Alaska', offset: 'UTC-9' },
14
+ { value: 'Pacific/Honolulu', label: 'Hawaii', offset: 'UTC-10', note: 'no DST' },
15
+ { value: 'America/Phoenix', label: 'Arizona', offset: 'UTC-7', note: 'no DST' },
16
+ { value: 'America/Toronto', label: 'Eastern CA', offset: 'UTC-5' },
17
+ { value: 'America/Winnipeg', label: 'Central CA', offset: 'UTC-6' },
18
+ { value: 'America/Vancouver', label: 'Pacific CA', offset: 'UTC-8' },
19
+ { value: 'America/Sao_Paulo', label: 'Brazil', offset: 'UTC-3' },
20
+ { value: 'America/Mexico_City', label: 'Mexico', offset: 'UTC-6' },
21
+ ],
22
+ },
23
+ {
24
+ name: 'Europe',
25
+ zones: [
26
+ { value: 'Europe/London', label: 'GMT', offset: 'UTC+0' },
27
+ { value: 'Europe/Berlin', label: 'CET', offset: 'UTC+1' },
28
+ { value: 'Europe/Paris', label: 'CET', offset: 'UTC+1' },
29
+ { value: 'Europe/Madrid', label: 'CET', offset: 'UTC+1' },
30
+ { value: 'Europe/Moscow', label: 'MSK', offset: 'UTC+3' },
31
+ { value: 'Europe/Istanbul', label: 'TRT', offset: 'UTC+3' },
32
+ { value: 'Europe/Warsaw', label: 'CET', offset: 'UTC+1' },
33
+ { value: 'Europe/Athens', label: 'EET', offset: 'UTC+2' },
34
+ ],
35
+ },
36
+ {
37
+ name: 'Asia / Pacific',
38
+ zones: [
39
+ { value: 'Asia/Tokyo', label: 'JST', offset: 'UTC+9' },
40
+ { value: 'Asia/Shanghai', label: 'CST', offset: 'UTC+8' },
41
+ { value: 'Asia/Kolkata', label: 'IST', offset: 'UTC+5:30' },
42
+ { value: 'Asia/Dubai', label: 'GST', offset: 'UTC+4' },
43
+ { value: 'Asia/Singapore', label: 'SGT', offset: 'UTC+8' },
44
+ { value: 'Australia/Sydney', label: 'AEST', offset: 'UTC+10' },
45
+ { value: 'Pacific/Auckland', label: 'NZST', offset: 'UTC+12' },
46
+ { value: 'Asia/Seoul', label: 'KST', offset: 'UTC+9' },
47
+ ],
48
+ },
49
+ ];
50
+ export const DEFAULT_NTP = ['0.pool.ntp.org', '1.pool.ntp.org'];
51
+ /** All known timezone entries flattened for quick lookup. */
52
+ const ALL_ZONES = TIMEZONE_REGIONS.flatMap(r => r.zones);
53
+ /**
54
+ * Get the current system timezone via timedatectl.
55
+ * Falls back to 'UTC' on error.
56
+ */
57
+ export function getSystemTimezone() {
58
+ try {
59
+ return execSync('timedatectl show --property=Timezone --value', {
60
+ encoding: 'utf-8',
61
+ }).trim();
62
+ }
63
+ catch {
64
+ return 'UTC';
65
+ }
66
+ }
67
+ /**
68
+ * Search available timezones by query string.
69
+ * Returns up to 10 matches with label/offset metadata when available.
70
+ */
71
+ export function searchTimezones(query) {
72
+ try {
73
+ const output = execSync('timedatectl list-timezones', { encoding: 'utf-8' });
74
+ const allTimezones = output.trim().split('\n');
75
+ const lowerQuery = query.toLowerCase();
76
+ const matches = allTimezones.filter(tz => tz.toLowerCase().includes(lowerQuery));
77
+ return matches.slice(0, 10).map(tz => {
78
+ const known = ALL_ZONES.find(z => z.value === tz);
79
+ if (known)
80
+ return known;
81
+ return {
82
+ value: tz,
83
+ label: tz.split('/').pop() ?? tz,
84
+ offset: getUtcOffset(tz),
85
+ };
86
+ });
87
+ }
88
+ catch {
89
+ return [];
90
+ }
91
+ }
92
+ /**
93
+ * Check if a timezone string is valid according to the system.
94
+ */
95
+ export function isValidTimezone(tz) {
96
+ try {
97
+ const output = execSync('timedatectl list-timezones', { encoding: 'utf-8' });
98
+ const allTimezones = output.trim().split('\n');
99
+ return allTimezones.includes(tz);
100
+ }
101
+ catch {
102
+ return false;
103
+ }
104
+ }
105
+ /**
106
+ * Apply a timezone to the system via timedatectl.
107
+ * Returns true if the command succeeds.
108
+ */
109
+ export function applyTimezone(tz) {
110
+ try {
111
+ const result = spawnSync('sudo', ['timedatectl', 'set-timezone', tz], {
112
+ stdio: 'pipe',
113
+ });
114
+ return result.status === 0;
115
+ }
116
+ catch {
117
+ return false;
118
+ }
119
+ }
120
+ /**
121
+ * Compute the current UTC offset for a given IANA timezone.
122
+ * Returns a string like 'UTC-6' or 'UTC+9'.
123
+ */
124
+ export function getUtcOffset(tz) {
125
+ try {
126
+ const formatter = new Intl.DateTimeFormat('en-US', {
127
+ timeZone: tz,
128
+ timeZoneName: 'shortOffset',
129
+ });
130
+ const parts = formatter.formatToParts(new Date());
131
+ const tzPart = parts.find(p => p.type === 'timeZoneName');
132
+ if (tzPart) {
133
+ // Intl returns e.g. 'GMT-6' or 'GMT+5:30' — normalize to UTC prefix
134
+ return tzPart.value.replace('GMT', 'UTC');
135
+ }
136
+ return 'UTC';
137
+ }
138
+ catch {
139
+ return 'UTC';
140
+ }
141
+ }
142
+ /**
143
+ * Get NTP synchronization status from timedatectl.
144
+ */
145
+ export function getNtpSyncStatus() {
146
+ try {
147
+ const output = execSync('timedatectl show', { encoding: 'utf-8' });
148
+ const lines = output.trim().split('\n');
149
+ let synced = false;
150
+ let server;
151
+ for (const line of lines) {
152
+ if (line.startsWith('NTPSynchronized=')) {
153
+ synced = line.split('=')[1]?.trim().toLowerCase() === 'yes';
154
+ }
155
+ }
156
+ return server ? { synced, server } : { synced };
157
+ }
158
+ catch {
159
+ return { synced: false };
160
+ }
161
+ }
162
+ /**
163
+ * Apply custom NTP servers by writing a timesyncd drop-in config
164
+ * and restarting the service.
165
+ * Returns true if both the write and restart succeed.
166
+ */
167
+ export function applyNtpServers(server1, server2) {
168
+ try {
169
+ const ntpLine = server2 ? `${server1} ${server2}` : server1;
170
+ const conf = `[Time]\nNTP=${ntpLine}\n`;
171
+ // Ensure the drop-in directory exists
172
+ const mkdirResult = spawnSync('sudo', ['mkdir', '-p', '/etc/systemd/timesyncd.conf.d'], {
173
+ stdio: 'pipe',
174
+ });
175
+ if (mkdirResult.status !== 0)
176
+ return false;
177
+ // Write the config via sudo tee
178
+ const teeResult = spawnSync('sudo', ['tee', '/etc/systemd/timesyncd.conf.d/ct-ntp.conf'], {
179
+ input: conf,
180
+ stdio: 'pipe',
181
+ });
182
+ if (teeResult.status !== 0)
183
+ return false;
184
+ // Restart timesyncd
185
+ const restartResult = spawnSync('sudo', ['systemctl', 'restart', 'systemd-timesyncd'], {
186
+ stdio: 'pipe',
187
+ });
188
+ return restartResult.status === 0;
189
+ }
190
+ catch {
191
+ return false;
192
+ }
193
+ }
194
+ /**
195
+ * Check if NTP is currently synchronized.
196
+ */
197
+ export function checkNtpSync() {
198
+ return getNtpSyncStatus().synced;
199
+ }
200
+ //# sourceMappingURL=time.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time.js","sourceRoot":"","sources":["../../src/lib/time.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"users.d.ts","sourceRoot":"","sources":["../../src/lib/users.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAQpD;AAED;;GAEG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAYnD;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAarE;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQvF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,SAAK,GAAG,MAAM,CAExD"}
1
+ {"version":3,"file":"users.d.ts","sourceRoot":"","sources":["../../src/lib/users.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAQpD;AAED;;GAEG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAYnD;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAqBrE;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQvF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,SAAK,GAAG,MAAM,CAExD"}
package/dist/lib/users.js CHANGED
@@ -34,11 +34,19 @@ export async function listOrgs() {
34
34
  */
35
35
  export async function listOrgUsers(orgId) {
36
36
  const code = `
37
- org = Cdrcisco.Identity.get_org(${orgId})
38
- org.users
39
- |> Enum.map(fn u -> %{id: u.id, email: u.email, role: u.role, roles: u.roles || []} end)
40
- |> Jason.encode!()
41
- |> IO.puts()
37
+ try do
38
+ org = Cdrcisco.Identity.get_org(${orgId})
39
+ if org do
40
+ (org.users || [])
41
+ |> Enum.map(fn u -> %{id: u.id, email: u.email, role: u.role, roles: u.roles || []} end)
42
+ |> Jason.encode!()
43
+ |> IO.puts()
44
+ else
45
+ IO.puts("[]")
46
+ end
47
+ rescue
48
+ _ -> IO.puts("[]")
49
+ end
42
50
  `.trim();
43
51
  const stdout = await rpc(code);
44
52
  const trimmed = stdout.trim();
@@ -1 +1 @@
1
- {"version":3,"file":"users.js","sourceRoot":"","sources":["../../src/lib/users.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAc/B;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,CAAS;IAC1C,OAAO,CAAC;SACL,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAQ,mBAAmB;SAC7C,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAG,SAAS;SAClC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAM,SAAS;SACnC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAG,oCAAoC;SAC9D,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAK,eAAe;SACzC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAI,uBAAuB;AACtD,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,MAAM,IAAI,GAAG;;;;;GAKZ,CAAC,IAAI,EAAE,CAAC;IAET,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC;IAC5C,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAc,CAAC;AAC1C,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,KAAa;IAC9C,MAAM,IAAI,GAAG;sCACuB,KAAK;;;;;GAKxC,CAAC,IAAI,EAAE,CAAC;IAET,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC;IAC5C,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAe,CAAC;AAC3C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAAc,EAAE,QAAgB;IACtE,MAAM,OAAO,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,0CAA0C,MAAM,MAAM,OAAO,oBAAoB,CAAC;IAE/F,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,uBAAuB,CAAC,CAAC;IAC5D,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAM,GAAG,EAAE;IAC9C,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AACpE,CAAC"}
1
+ {"version":3,"file":"users.js","sourceRoot":"","sources":["../../src/lib/users.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAc/B;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,CAAS;IAC1C,OAAO,CAAC;SACL,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAQ,mBAAmB;SAC7C,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAG,SAAS;SAClC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAM,SAAS;SACnC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAG,oCAAoC;SAC9D,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAK,eAAe;SACzC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAI,uBAAuB;AACtD,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,MAAM,IAAI,GAAG;;;;;GAKZ,CAAC,IAAI,EAAE,CAAC;IAET,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC;IAC5C,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAc,CAAC;AAC1C,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,KAAa;IAC9C,MAAM,IAAI,GAAG;;wCAEyB,KAAK;;;;;;;;;;;;GAY1C,CAAC,IAAI,EAAE,CAAC;IAET,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC;IAC5C,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAe,CAAC;AAC3C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAAc,EAAE,QAAgB;IACtE,MAAM,OAAO,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,0CAA0C,MAAM,MAAM,OAAO,oBAAoB,CAAC;IAE/F,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,uBAAuB,CAAC,CAAC;IAC5D,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAM,GAAG,EAAE;IAC9C,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AACpE,CAAC"}
@@ -1,3 +1,3 @@
1
1
  /** Single source of truth for the CLI version. */
2
- export declare const VERSION = "0.5.18";
2
+ export declare const VERSION = "0.6.0";
3
3
  //# sourceMappingURL=version.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/lib/version.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,eAAO,MAAM,OAAO,WAAW,CAAC"}
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/lib/version.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,eAAO,MAAM,OAAO,UAAU,CAAC"}