@kodus/cli 0.1.11 → 0.1.12

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 (80) hide show
  1. package/dist/commands/__tests__/auth.login-logout.test.d.ts +2 -0
  2. package/dist/commands/__tests__/auth.login-logout.test.d.ts.map +1 -0
  3. package/dist/commands/__tests__/auth.login-logout.test.js +125 -0
  4. package/dist/commands/__tests__/auth.login-logout.test.js.map +1 -0
  5. package/dist/commands/__tests__/auth.team-key.test.d.ts +2 -0
  6. package/dist/commands/__tests__/auth.team-key.test.d.ts.map +1 -0
  7. package/dist/commands/__tests__/auth.team-key.test.js +129 -0
  8. package/dist/commands/__tests__/auth.team-key.test.js.map +1 -0
  9. package/dist/commands/__tests__/hook.test.js +1 -1
  10. package/dist/commands/__tests__/hook.test.js.map +1 -1
  11. package/dist/commands/auth/index.js +1 -1
  12. package/dist/commands/auth/index.js.map +1 -1
  13. package/dist/commands/auth/login.d.ts.map +1 -1
  14. package/dist/commands/auth/login.js +5 -2
  15. package/dist/commands/auth/login.js.map +1 -1
  16. package/dist/commands/auth/logout.js +1 -1
  17. package/dist/commands/auth/logout.js.map +1 -1
  18. package/dist/commands/auth/team-key.d.ts.map +1 -1
  19. package/dist/commands/auth/team-key.js +37 -4
  20. package/dist/commands/auth/team-key.js.map +1 -1
  21. package/dist/commands/hook/index.d.ts.map +1 -1
  22. package/dist/commands/hook/index.js +5 -5
  23. package/dist/commands/hook/index.js.map +1 -1
  24. package/dist/commands/hook/install.d.ts.map +1 -1
  25. package/dist/commands/hook/install.js +35 -8
  26. package/dist/commands/hook/install.js.map +1 -1
  27. package/dist/commands/hook/status.js +4 -4
  28. package/dist/commands/hook/status.js.map +1 -1
  29. package/dist/commands/hook/uninstall.js +4 -4
  30. package/dist/commands/hook/uninstall.js.map +1 -1
  31. package/dist/services/__tests__/auth.service.test.js +36 -2
  32. package/dist/services/__tests__/auth.service.test.js.map +1 -1
  33. package/dist/services/__tests__/review.service.auth-fallback.test.d.ts +2 -0
  34. package/dist/services/__tests__/review.service.auth-fallback.test.d.ts.map +1 -0
  35. package/dist/services/__tests__/review.service.auth-fallback.test.js +63 -0
  36. package/dist/services/__tests__/review.service.auth-fallback.test.js.map +1 -0
  37. package/dist/services/__tests__/review.suggestions-auth.test.d.ts +2 -0
  38. package/dist/services/__tests__/review.suggestions-auth.test.d.ts.map +1 -0
  39. package/dist/services/__tests__/review.suggestions-auth.test.js +81 -0
  40. package/dist/services/__tests__/review.suggestions-auth.test.js.map +1 -0
  41. package/dist/services/api/__tests__/api.real.test.d.ts +2 -0
  42. package/dist/services/api/__tests__/api.real.test.d.ts.map +1 -0
  43. package/dist/services/api/__tests__/api.real.test.js +171 -0
  44. package/dist/services/api/__tests__/api.real.test.js.map +1 -0
  45. package/dist/services/api/api.real.d.ts.map +1 -1
  46. package/dist/services/api/api.real.js +94 -9
  47. package/dist/services/api/api.real.js.map +1 -1
  48. package/dist/services/auth.service.d.ts +2 -0
  49. package/dist/services/auth.service.d.ts.map +1 -1
  50. package/dist/services/auth.service.js +45 -20
  51. package/dist/services/auth.service.js.map +1 -1
  52. package/dist/services/git.service.d.ts.map +1 -1
  53. package/dist/services/git.service.js +18 -15
  54. package/dist/services/git.service.js.map +1 -1
  55. package/dist/services/review.service.d.ts.map +1 -1
  56. package/dist/services/review.service.js +22 -1
  57. package/dist/services/review.service.js.map +1 -1
  58. package/dist/utils/__tests__/config.test.d.ts +2 -0
  59. package/dist/utils/__tests__/config.test.d.ts.map +1 -0
  60. package/dist/utils/__tests__/config.test.js +79 -0
  61. package/dist/utils/__tests__/config.test.js.map +1 -0
  62. package/dist/utils/__tests__/credentials.test.d.ts +2 -0
  63. package/dist/utils/__tests__/credentials.test.d.ts.map +1 -0
  64. package/dist/utils/__tests__/credentials.test.js +89 -0
  65. package/dist/utils/__tests__/credentials.test.js.map +1 -0
  66. package/dist/utils/__tests__/device.test.d.ts +2 -0
  67. package/dist/utils/__tests__/device.test.d.ts.map +1 -0
  68. package/dist/utils/__tests__/device.test.js +108 -0
  69. package/dist/utils/__tests__/device.test.js.map +1 -0
  70. package/dist/utils/config.d.ts.map +1 -1
  71. package/dist/utils/config.js +15 -5
  72. package/dist/utils/config.js.map +1 -1
  73. package/dist/utils/credentials.d.ts.map +1 -1
  74. package/dist/utils/credentials.js +15 -5
  75. package/dist/utils/credentials.js.map +1 -1
  76. package/dist/utils/device.d.ts +7 -0
  77. package/dist/utils/device.d.ts.map +1 -0
  78. package/dist/utils/device.js +118 -0
  79. package/dist/utils/device.js.map +1 -0
  80. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AACrD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAQzD,KAAK,UAAU,eAAe;IAC5B,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAiB;IAChD,MAAM,eAAe,EAAE,CAAC;IACxB,MAAM,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;QAC/D,QAAQ,EAAE,OAAO;QACjB,IAAI,EAAE,KAAK;KACZ,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACxD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAc,CAAC;IAC1C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AACrD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAQzD,SAAS,gBAAgB,CAAC,KAAc;IACtC,OAAO,KAAK,YAAY,WAAW,CAAC;AACtC,CAAC;AAED,KAAK,UAAU,eAAe;IAC5B,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAiB;IAChD,MAAM,eAAe,EAAE,CAAC;IACxB,MAAM,OAAO,GAAG,GAAG,WAAW,IAAI,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC;IAClE,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAEhD,MAAM,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACzE,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACxD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAc,CAAC;IAC1C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,GAAI,KAA+B,CAAC,IAAI,CAAC;QACnD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,mFAAmF;QACnF,IAAI,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5B,MAAM,UAAU,GAAG,GAAG,WAAW,cAAc,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YAC5D,MAAM,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YACzD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/utils/credentials.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAyB,MAAM,mBAAmB,CAAC;AAelF,wBAAsB,eAAe,IAAI,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAUzE;AAED,wBAAsB,eAAe,CAAC,WAAW,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAMnF;AAED,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAQtD;AAED,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC,CAOzD"}
1
+ {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/utils/credentials.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAyB,MAAM,mBAAmB,CAAC;AAmBlF,wBAAsB,eAAe,IAAI,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAmBzE;AAED,wBAAsB,eAAe,CAAC,WAAW,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAOnF;AAED,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAQtD;AAED,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC,CAOzD"}
@@ -3,6 +3,9 @@ import path from 'path';
3
3
  import os from 'os';
4
4
  const KODUS_DIR = path.join(os.homedir(), '.kodus');
5
5
  const CREDENTIALS_FILE = path.join(KODUS_DIR, 'credentials.json');
6
+ function isJsonParseError(error) {
7
+ return error instanceof SyntaxError;
8
+ }
6
9
  async function ensureKodusDir() {
7
10
  try {
8
11
  await fs.mkdir(KODUS_DIR, { recursive: true, mode: 0o700 });
@@ -19,7 +22,14 @@ export async function loadCredentials() {
19
22
  return JSON.parse(content);
20
23
  }
21
24
  catch (error) {
22
- if (error.code === 'ENOENT') {
25
+ const code = error.code;
26
+ if (code === 'ENOENT') {
27
+ return null;
28
+ }
29
+ // Self-heal malformed JSON by isolating the broken file and treating as no credentials.
30
+ if (isJsonParseError(error)) {
31
+ const brokenFile = `${CREDENTIALS_FILE}.corrupted.${Date.now()}`;
32
+ await fs.rename(CREDENTIALS_FILE, brokenFile).catch(() => { });
23
33
  return null;
24
34
  }
25
35
  throw error;
@@ -27,10 +37,10 @@ export async function loadCredentials() {
27
37
  }
28
38
  export async function saveCredentials(credentials) {
29
39
  await ensureKodusDir();
30
- await fs.writeFile(CREDENTIALS_FILE, JSON.stringify(credentials, null, 2), {
31
- encoding: 'utf-8',
32
- mode: 0o600,
33
- });
40
+ const tmpFile = `${CREDENTIALS_FILE}.${process.pid}.${Date.now()}.tmp`;
41
+ const content = JSON.stringify(credentials, null, 2);
42
+ await fs.writeFile(tmpFile, content, { encoding: 'utf-8', mode: 0o600 });
43
+ await fs.rename(tmpFile, CREDENTIALS_FILE);
34
44
  }
35
45
  export async function clearCredentials() {
36
46
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/utils/credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AAGpB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AACpD,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;AAElE,KAAK,UAAU,cAAc;IAC3B,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;QAC7D,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAsB,CAAC;IAClD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,WAA8B;IAClE,MAAM,cAAc,EAAE,CAAC;IACvB,MAAM,EAAE,CAAC,SAAS,CAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;QACzE,QAAQ,EAAE,OAAO;QACjB,IAAI,EAAE,KAAK;KACZ,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/utils/credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AAGpB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AACpD,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;AAElE,SAAS,gBAAgB,CAAC,KAAc;IACtC,OAAO,KAAK,YAAY,WAAW,CAAC;AACtC,CAAC;AAED,KAAK,UAAU,cAAc;IAC3B,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;QAC7D,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAsB,CAAC;IAClD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,GAAI,KAA+B,CAAC,IAAI,CAAC;QACnD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,wFAAwF;QACxF,IAAI,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5B,MAAM,UAAU,GAAG,GAAG,gBAAgB,cAAc,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YACjE,MAAM,EAAE,CAAC,MAAM,CAAC,gBAAgB,EAAE,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YAC9D,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,WAA8B;IAClE,MAAM,cAAc,EAAE,CAAC;IACvB,MAAM,OAAO,GAAG,GAAG,gBAAgB,IAAI,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC;IACvE,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAErD,MAAM,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACzE,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ export declare function getDeviceIdentity(): Promise<{
2
+ deviceId: string;
3
+ deviceToken?: string;
4
+ }>;
5
+ export declare function getOrCreateDeviceId(): Promise<string>;
6
+ export declare function updateDeviceToken(deviceToken: string): Promise<void>;
7
+ //# sourceMappingURL=device.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device.d.ts","sourceRoot":"","sources":["../../src/utils/device.ts"],"names":[],"mappings":"AAqEA,wBAAsB,iBAAiB,IAAI,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAsC7F;AAED,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC,CAG3D;AAED,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0B1E"}
@@ -0,0 +1,118 @@
1
+ import fs from 'fs/promises';
2
+ import os from 'os';
3
+ import path from 'path';
4
+ import { randomUUID } from 'crypto';
5
+ const KODUS_DIR = path.join(os.homedir(), '.kodus');
6
+ const DEVICE_FILE = path.join(KODUS_DIR, 'device.json');
7
+ const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
8
+ let cachedDevice = null;
9
+ let initializationPromise = null;
10
+ function isValidDeviceId(value) {
11
+ return typeof value === 'string' && UUID_REGEX.test(value);
12
+ }
13
+ function isValidDeviceToken(value) {
14
+ return typeof value === 'string' && value.trim().length > 0;
15
+ }
16
+ async function ensureKodusDir() {
17
+ try {
18
+ await fs.mkdir(KODUS_DIR, { recursive: true, mode: 0o700 });
19
+ }
20
+ catch (error) {
21
+ if (error.code !== 'EEXIST') {
22
+ throw error;
23
+ }
24
+ }
25
+ }
26
+ async function writeDeviceData(data) {
27
+ await ensureKodusDir();
28
+ const tmpFile = `${DEVICE_FILE}.${process.pid}.${Date.now()}.tmp`;
29
+ await fs.writeFile(tmpFile, JSON.stringify(data, null, 2), {
30
+ encoding: 'utf-8',
31
+ mode: 0o600,
32
+ });
33
+ await fs.rename(tmpFile, DEVICE_FILE);
34
+ }
35
+ async function readStoredDeviceData() {
36
+ try {
37
+ const content = await fs.readFile(DEVICE_FILE, 'utf-8');
38
+ const parsed = JSON.parse(content);
39
+ if (!isValidDeviceId(parsed.deviceId)) {
40
+ return null;
41
+ }
42
+ return {
43
+ deviceId: parsed.deviceId,
44
+ createdAt: typeof parsed.createdAt === 'string' ? parsed.createdAt : new Date().toISOString(),
45
+ ...(isValidDeviceToken(parsed.deviceToken) ? { deviceToken: parsed.deviceToken } : {}),
46
+ ...(typeof parsed.tokenUpdatedAt === 'string' ? { tokenUpdatedAt: parsed.tokenUpdatedAt } : {}),
47
+ };
48
+ }
49
+ catch (error) {
50
+ if (error.code === 'ENOENT') {
51
+ return null;
52
+ }
53
+ return null;
54
+ }
55
+ }
56
+ export async function getDeviceIdentity() {
57
+ if (cachedDevice) {
58
+ return {
59
+ deviceId: cachedDevice.deviceId,
60
+ ...(cachedDevice.deviceToken ? { deviceToken: cachedDevice.deviceToken } : {}),
61
+ };
62
+ }
63
+ if (initializationPromise) {
64
+ return initializationPromise;
65
+ }
66
+ initializationPromise = (async () => {
67
+ const existing = await readStoredDeviceData();
68
+ if (existing) {
69
+ cachedDevice = existing;
70
+ return {
71
+ deviceId: existing.deviceId,
72
+ ...(existing.deviceToken ? { deviceToken: existing.deviceToken } : {}),
73
+ };
74
+ }
75
+ const created = {
76
+ deviceId: randomUUID(),
77
+ createdAt: new Date().toISOString(),
78
+ };
79
+ cachedDevice = created;
80
+ try {
81
+ await writeDeviceData(created);
82
+ }
83
+ catch {
84
+ // If persistence fails, still return a process-stable identity.
85
+ }
86
+ return { deviceId: created.deviceId };
87
+ })();
88
+ return initializationPromise;
89
+ }
90
+ export async function getOrCreateDeviceId() {
91
+ const identity = await getDeviceIdentity();
92
+ return identity.deviceId;
93
+ }
94
+ export async function updateDeviceToken(deviceToken) {
95
+ if (!isValidDeviceToken(deviceToken)) {
96
+ return;
97
+ }
98
+ const current = cachedDevice ?? await readStoredDeviceData() ?? {
99
+ deviceId: randomUUID(),
100
+ createdAt: new Date().toISOString(),
101
+ };
102
+ if (current.deviceToken === deviceToken && cachedDevice) {
103
+ return;
104
+ }
105
+ const next = {
106
+ ...current,
107
+ deviceToken,
108
+ tokenUpdatedAt: new Date().toISOString(),
109
+ };
110
+ cachedDevice = next;
111
+ try {
112
+ await writeDeviceData(next);
113
+ }
114
+ catch {
115
+ // Keep in-memory token even if disk persistence fails.
116
+ }
117
+ }
118
+ //# sourceMappingURL=device.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device.js","sourceRoot":"","sources":["../../src/utils/device.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kodus/cli",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "Kodus CLI - AI-powered code review from your terminal",
5
5
  "type": "module",
6
6
  "bin": {