preclaim 0.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 (98) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/dist/commands/check.d.ts +2 -0
  3. package/dist/commands/check.d.ts.map +1 -0
  4. package/dist/commands/check.js +25 -0
  5. package/dist/commands/check.js.map +1 -0
  6. package/dist/commands/config.d.ts +5 -0
  7. package/dist/commands/config.d.ts.map +1 -0
  8. package/dist/commands/config.js +37 -0
  9. package/dist/commands/config.js.map +1 -0
  10. package/dist/commands/init.d.ts +5 -0
  11. package/dist/commands/init.d.ts.map +1 -0
  12. package/dist/commands/init.js +95 -0
  13. package/dist/commands/init.js.map +1 -0
  14. package/dist/commands/install-hooks.d.ts +2 -0
  15. package/dist/commands/install-hooks.d.ts.map +1 -0
  16. package/dist/commands/install-hooks.js +58 -0
  17. package/dist/commands/install-hooks.js.map +1 -0
  18. package/dist/commands/lock.d.ts +5 -0
  19. package/dist/commands/lock.d.ts.map +1 -0
  20. package/dist/commands/lock.js +27 -0
  21. package/dist/commands/lock.js.map +1 -0
  22. package/dist/commands/login.d.ts +2 -0
  23. package/dist/commands/login.d.ts.map +1 -0
  24. package/dist/commands/login.js +106 -0
  25. package/dist/commands/login.js.map +1 -0
  26. package/dist/commands/status.d.ts +2 -0
  27. package/dist/commands/status.d.ts.map +1 -0
  28. package/dist/commands/status.js +12 -0
  29. package/dist/commands/status.js.map +1 -0
  30. package/dist/commands/unlock.d.ts +5 -0
  31. package/dist/commands/unlock.d.ts.map +1 -0
  32. package/dist/commands/unlock.js +20 -0
  33. package/dist/commands/unlock.js.map +1 -0
  34. package/dist/commands/whoami.d.ts +2 -0
  35. package/dist/commands/whoami.d.ts.map +1 -0
  36. package/dist/commands/whoami.js +13 -0
  37. package/dist/commands/whoami.js.map +1 -0
  38. package/dist/hooks/heartbeat-daemon.d.ts +3 -0
  39. package/dist/hooks/heartbeat-daemon.d.ts.map +1 -0
  40. package/dist/hooks/heartbeat-daemon.js +41 -0
  41. package/dist/hooks/heartbeat-daemon.js.map +1 -0
  42. package/dist/hooks/post-tool-use.d.ts +3 -0
  43. package/dist/hooks/post-tool-use.d.ts.map +1 -0
  44. package/dist/hooks/post-tool-use.js +41 -0
  45. package/dist/hooks/post-tool-use.js.map +1 -0
  46. package/dist/hooks/pre-tool-use.d.ts +3 -0
  47. package/dist/hooks/pre-tool-use.d.ts.map +1 -0
  48. package/dist/hooks/pre-tool-use.js +101 -0
  49. package/dist/hooks/pre-tool-use.js.map +1 -0
  50. package/dist/hooks/session-start.d.ts +3 -0
  51. package/dist/hooks/session-start.d.ts.map +1 -0
  52. package/dist/hooks/session-start.js +77 -0
  53. package/dist/hooks/session-start.js.map +1 -0
  54. package/dist/hooks/stop.d.ts +3 -0
  55. package/dist/hooks/stop.d.ts.map +1 -0
  56. package/dist/hooks/stop.js +40 -0
  57. package/dist/hooks/stop.js.map +1 -0
  58. package/dist/index.d.ts +3 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +62 -0
  61. package/dist/index.js.map +1 -0
  62. package/dist/lib/auth.d.ts +3 -0
  63. package/dist/lib/auth.d.ts.map +1 -0
  64. package/dist/lib/auth.js +15 -0
  65. package/dist/lib/auth.js.map +1 -0
  66. package/dist/lib/client-factory.d.ts +8 -0
  67. package/dist/lib/client-factory.d.ts.map +1 -0
  68. package/dist/lib/client-factory.js +17 -0
  69. package/dist/lib/client-factory.js.map +1 -0
  70. package/dist/lib/hook-io.d.ts +13 -0
  71. package/dist/lib/hook-io.d.ts.map +1 -0
  72. package/dist/lib/hook-io.js +24 -0
  73. package/dist/lib/hook-io.js.map +1 -0
  74. package/dist/lib/output.d.ts +4 -0
  75. package/dist/lib/output.d.ts.map +1 -0
  76. package/dist/lib/output.js +17 -0
  77. package/dist/lib/output.js.map +1 -0
  78. package/package.json +24 -0
  79. package/src/commands/check.ts +28 -0
  80. package/src/commands/config.ts +43 -0
  81. package/src/commands/init.ts +109 -0
  82. package/src/commands/install-hooks.ts +72 -0
  83. package/src/commands/lock.ts +30 -0
  84. package/src/commands/login.ts +120 -0
  85. package/src/commands/status.ts +15 -0
  86. package/src/commands/unlock.ts +25 -0
  87. package/src/commands/whoami.ts +15 -0
  88. package/src/hooks/heartbeat-daemon.ts +49 -0
  89. package/src/hooks/post-tool-use.ts +44 -0
  90. package/src/hooks/pre-tool-use.ts +110 -0
  91. package/src/hooks/session-start.ts +87 -0
  92. package/src/hooks/stop.ts +43 -0
  93. package/src/index.ts +74 -0
  94. package/src/lib/auth.ts +17 -0
  95. package/src/lib/client-factory.ts +26 -0
  96. package/src/lib/hook-io.ts +37 -0
  97. package/src/lib/output.ts +20 -0
  98. package/tsconfig.json +8 -0
@@ -0,0 +1,4 @@
1
+
2
+ > preclaim@0.1.0 build /Users/paulveth/projects/preclaim/packages/cli
3
+ > tsc
4
+
@@ -0,0 +1,2 @@
1
+ export declare function checkCommand(filePaths: string[]): Promise<void>;
2
+ //# sourceMappingURL=check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AAEA,wBAAsB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,iBAyBrD"}
@@ -0,0 +1,25 @@
1
+ import { resolveContext } from '../lib/client-factory.js';
2
+ export async function checkCommand(filePaths) {
3
+ if (filePaths.length === 0) {
4
+ console.error('Specify one or more file paths to check.');
5
+ process.exit(1);
6
+ }
7
+ const { client, config } = await resolveContext();
8
+ const result = await client.batchCheck({
9
+ project_id: config.projectId,
10
+ file_paths: filePaths,
11
+ });
12
+ if (result.error) {
13
+ console.error(`Failed to check: ${result.error}`);
14
+ process.exit(1);
15
+ }
16
+ for (const [path, lock] of Object.entries(result.data.locks)) {
17
+ if (lock) {
18
+ console.log(`LOCKED ${path} (session: ${lock.session_id.slice(0, 8)}… expires: ${new Date(lock.expires_at).toLocaleTimeString()})`);
19
+ }
20
+ else {
21
+ console.log(`FREE ${path}`);
22
+ }
23
+ }
24
+ }
25
+ //# sourceMappingURL=check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,SAAmB;IACpD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,cAAc,EAAE,CAAC;IAElD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC;QACrC,UAAU,EAAE,MAAM,CAAC,SAAS;QAC5B,UAAU,EAAE,SAAS;KACtB,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,OAAO,CAAC,KAAK,CAAC,oBAAoB,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,IAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9D,IAAI,IAAI,EAAE,CAAC;YACT,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,eAAe,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,eAAe,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;QACzI,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function configCommand(opts: {
2
+ get?: string;
3
+ set?: string;
4
+ }): Promise<void>;
5
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAGA,wBAAsB,aAAa,CAAC,IAAI,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,iBAuCvE"}
@@ -0,0 +1,37 @@
1
+ import { readFile, writeFile } from 'node:fs/promises';
2
+ import { findConfig } from '@preclaim/core';
3
+ export async function configCommand(opts) {
4
+ const found = await findConfig();
5
+ if (!found) {
6
+ console.error('No .preclaim.json found. Run `preclaim init` first.');
7
+ process.exit(1);
8
+ }
9
+ if (opts.get) {
10
+ const value = found.config[opts.get];
11
+ console.log(JSON.stringify(value, null, 2));
12
+ return;
13
+ }
14
+ if (opts.set) {
15
+ const [key, ...rest] = opts.set.split('=');
16
+ const value = rest.join('=');
17
+ if (!key || !value) {
18
+ console.error('Usage: preclaim config --set key=value');
19
+ process.exit(1);
20
+ }
21
+ const raw = await readFile(found.configPath, 'utf-8');
22
+ const config = JSON.parse(raw);
23
+ // Try to parse as JSON, fallback to string
24
+ try {
25
+ config[key] = JSON.parse(value);
26
+ }
27
+ catch {
28
+ config[key] = value;
29
+ }
30
+ await writeFile(found.configPath, JSON.stringify(config, null, 2) + '\n');
31
+ console.log(`Set ${key} = ${JSON.stringify(config[key])}`);
32
+ return;
33
+ }
34
+ // No flags — show full config
35
+ console.log(JSON.stringify(found.config, null, 2));
36
+ }
37
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAuB,MAAM,gBAAgB,CAAC;AAEjE,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAoC;IACtE,MAAM,KAAK,GAAG,MAAM,UAAU,EAAE,CAAC;IACjC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QACb,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAA2B,CAAC,CAAC;QAC7D,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC5C,OAAO;IACT,CAAC;IAED,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAE7B,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;YACnB,OAAO,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;YACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACtD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA4B,CAAC;QAE1D,2CAA2C;QAC3C,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAClC,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACtB,CAAC;QAED,MAAM,SAAS,CAAC,KAAK,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QAC1E,OAAO,CAAC,GAAG,CAAC,OAAO,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;QAC3D,OAAO;IACT,CAAC;IAED,8BAA8B;IAC9B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AACrD,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function initCommand(opts: {
2
+ backend?: string;
3
+ projectId?: string;
4
+ }): Promise<void>;
5
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAOA,wBAAsB,WAAW,CAAC,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,iBA6F/E"}
@@ -0,0 +1,95 @@
1
+ import { writeFile, readFile } from 'node:fs/promises';
2
+ import { join, basename } from 'node:path';
3
+ import { defaultConfig, loadCredentials, PreclaimClient } from '@preclaim/core';
4
+ import { loginCommand } from './login.js';
5
+ const DEFAULT_BACKEND = 'https://preclaim.dev';
6
+ export async function initCommand(opts) {
7
+ const configPath = join(process.cwd(), '.preclaim.json');
8
+ // Check if already exists
9
+ try {
10
+ await readFile(configPath, 'utf-8');
11
+ console.log('.preclaim.json already exists. Use `preclaim config` to modify.');
12
+ return;
13
+ }
14
+ catch {
15
+ // File doesn't exist, proceed
16
+ }
17
+ const backend = opts.backend ?? DEFAULT_BACKEND;
18
+ // If project ID provided directly, skip onboarding
19
+ if (opts.projectId) {
20
+ const config = defaultConfig(opts.projectId, backend);
21
+ await writeFile(configPath, JSON.stringify(config, null, 2) + '\n');
22
+ console.log(`Created .preclaim.json (project: ${opts.projectId})`);
23
+ printNextSteps();
24
+ return;
25
+ }
26
+ // Check if logged in, if not: login first
27
+ let creds = await loadCredentials();
28
+ if (!creds) {
29
+ console.log('Not logged in. Starting authentication...\n');
30
+ await loginCommand();
31
+ creds = await loadCredentials();
32
+ if (!creds) {
33
+ console.error('Login failed. Please try again.');
34
+ process.exit(1);
35
+ }
36
+ console.log('');
37
+ }
38
+ // Derive project name from directory
39
+ const dirName = basename(process.cwd());
40
+ const projectSlug = dirName.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-');
41
+ const projectName = dirName;
42
+ console.log(`Setting up Preclaim for "${projectName}"...`);
43
+ // Call onboard API
44
+ const client = new PreclaimClient({
45
+ baseUrl: backend,
46
+ accessToken: creds.accessToken,
47
+ timeoutMs: 10000,
48
+ });
49
+ const res = await fetch(`${backend}/api/v1/onboard`, {
50
+ method: 'POST',
51
+ headers: {
52
+ 'Content-Type': 'application/json',
53
+ 'Authorization': `Bearer ${creds.accessToken}`,
54
+ },
55
+ body: JSON.stringify({
56
+ project_name: projectName,
57
+ project_slug: projectSlug,
58
+ }),
59
+ });
60
+ if (!res.ok) {
61
+ const body = await res.text();
62
+ console.error(`Failed to create project: ${body}`);
63
+ process.exit(1);
64
+ }
65
+ const { data } = await res.json();
66
+ if (data.already_existed) {
67
+ console.log(`Project "${projectName}" already exists, using existing project.`);
68
+ }
69
+ else {
70
+ console.log(`Project "${projectName}" created.`);
71
+ }
72
+ // Update credentials with org_id
73
+ if (creds.user.orgId !== data.org_id) {
74
+ creds.user.orgId = data.org_id;
75
+ const { getCredentialsPath } = await import('@preclaim/core');
76
+ const { writeFile: wf, mkdir } = await import('node:fs/promises');
77
+ const { dirname } = await import('node:path');
78
+ const credPath = getCredentialsPath();
79
+ await mkdir(dirname(credPath), { recursive: true });
80
+ await wf(credPath, JSON.stringify(creds, null, 2) + '\n', { mode: 0o600 });
81
+ }
82
+ // Write config
83
+ const config = defaultConfig(data.project_id, backend);
84
+ await writeFile(configPath, JSON.stringify(config, null, 2) + '\n');
85
+ console.log(`\nCreated .preclaim.json`);
86
+ printNextSteps();
87
+ }
88
+ function printNextSteps() {
89
+ console.log('');
90
+ console.log('Next steps:');
91
+ console.log(' 1. preclaim install-hooks');
92
+ console.log(' 2. Commit .preclaim.json to your repo');
93
+ console.log(' 3. Open multiple Claude Code terminals — locks are automatic');
94
+ }
95
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function installHooksCommand(): Promise<void>;
2
+ //# sourceMappingURL=install-hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-hooks.d.ts","sourceRoot":"","sources":["../../src/commands/install-hooks.ts"],"names":[],"mappings":"AAgBA,wBAAsB,mBAAmB,kBAuDxC"}
@@ -0,0 +1,58 @@
1
+ import { readFile, writeFile, mkdir } from 'node:fs/promises';
2
+ import { join, dirname } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ const __dirname = dirname(fileURLToPath(import.meta.url));
5
+ export async function installHooksCommand() {
6
+ const hooksDir = join(__dirname, '..', 'hooks');
7
+ const settingsDir = join(process.cwd(), '.claude');
8
+ const settingsPath = join(settingsDir, 'settings.json');
9
+ // Read existing settings or create new
10
+ let settings = {};
11
+ try {
12
+ const raw = await readFile(settingsPath, 'utf-8');
13
+ settings = JSON.parse(raw);
14
+ }
15
+ catch {
16
+ // File doesn't exist
17
+ }
18
+ settings.hooks = {
19
+ PreToolUse: [{
20
+ matcher: '',
21
+ hooks: [{
22
+ type: 'command',
23
+ command: `node ${join(hooksDir, 'pre-tool-use.js')}`,
24
+ }],
25
+ }],
26
+ PostToolUse: [{
27
+ matcher: '',
28
+ hooks: [{
29
+ type: 'command',
30
+ command: `node ${join(hooksDir, 'post-tool-use.js')}`,
31
+ }],
32
+ }],
33
+ Stop: [{
34
+ matcher: '',
35
+ hooks: [{
36
+ type: 'command',
37
+ command: `node ${join(hooksDir, 'stop.js')}`,
38
+ }],
39
+ }],
40
+ SessionStart: [{
41
+ matcher: '',
42
+ hooks: [{
43
+ type: 'command',
44
+ command: `node ${join(hooksDir, 'session-start.js')}`,
45
+ }],
46
+ }],
47
+ };
48
+ await mkdir(settingsDir, { recursive: true });
49
+ await writeFile(settingsPath, JSON.stringify(settings, null, 2) + '\n');
50
+ console.log('Claude Code hooks installed in .claude/settings.json');
51
+ console.log('');
52
+ console.log('Hooks configured:');
53
+ console.log(' - PreToolUse: file lock gatekeeper');
54
+ console.log(' - PostToolUse: commit detection → release locks');
55
+ console.log(' - Stop: session cleanup');
56
+ console.log(' - SessionStart: session registration + heartbeat');
57
+ }
58
+ //# sourceMappingURL=install-hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-hooks.js","sourceRoot":"","sources":["../../src/commands/install-hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAY1D,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAChD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;IACnD,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;IAExD,uCAAuC;IACvC,IAAI,QAAQ,GAAmB,EAAE,CAAC;IAClC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAClD,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,qBAAqB;IACvB,CAAC;IAED,QAAQ,CAAC,KAAK,GAAG;QACf,UAAU,EAAE,CAAC;gBACX,OAAO,EAAE,EAAE;gBACX,KAAK,EAAE,CAAC;wBACN,IAAI,EAAE,SAAS;wBACf,OAAO,EAAE,QAAQ,IAAI,CAAC,QAAQ,EAAE,iBAAiB,CAAC,EAAE;qBACrD,CAAC;aACH,CAAC;QACF,WAAW,EAAE,CAAC;gBACZ,OAAO,EAAE,EAAE;gBACX,KAAK,EAAE,CAAC;wBACN,IAAI,EAAE,SAAS;wBACf,OAAO,EAAE,QAAQ,IAAI,CAAC,QAAQ,EAAE,kBAAkB,CAAC,EAAE;qBACtD,CAAC;aACH,CAAC;QACF,IAAI,EAAE,CAAC;gBACL,OAAO,EAAE,EAAE;gBACX,KAAK,EAAE,CAAC;wBACN,IAAI,EAAE,SAAS;wBACf,OAAO,EAAE,QAAQ,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE;qBAC7C,CAAC;aACH,CAAC;QACF,YAAY,EAAE,CAAC;gBACb,OAAO,EAAE,EAAE;gBACX,KAAK,EAAE,CAAC;wBACN,IAAI,EAAE,SAAS;wBACf,OAAO,EAAE,QAAQ,IAAI,CAAC,QAAQ,EAAE,kBAAkB,CAAC,EAAE;qBACtD,CAAC;aACH,CAAC;KACH,CAAC;IAEF,MAAM,KAAK,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,MAAM,SAAS,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAExE,OAAO,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAC;IACpE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IACjC,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;IACjE,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC;AACpE,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function lockCommand(filePath: string, opts: {
2
+ session?: string;
3
+ ttl?: string;
4
+ }): Promise<void>;
5
+ //# sourceMappingURL=lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../../src/commands/lock.ts"],"names":[],"mappings":"AAEA,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,iBA2B3F"}
@@ -0,0 +1,27 @@
1
+ import { resolveContext } from '../lib/client-factory.js';
2
+ export async function lockCommand(filePath, opts) {
3
+ const { client, config, credentials } = await resolveContext();
4
+ const sessionId = opts.session ?? `manual_${crypto.randomUUID().slice(0, 8)}`;
5
+ const ttl = opts.ttl ? parseInt(opts.ttl, 10) : config.ttl;
6
+ const result = await client.claimFile({
7
+ project_id: config.projectId,
8
+ file_path: filePath,
9
+ session_id: sessionId,
10
+ ttl_minutes: ttl,
11
+ });
12
+ if (result.error) {
13
+ console.error(`Failed to lock: ${result.error}`);
14
+ process.exit(1);
15
+ }
16
+ const data = result.data;
17
+ if (data.status === 'acquired' || data.status === 'already_held') {
18
+ console.log(`Locked: ${filePath} (expires: ${new Date(data.expires_at).toLocaleTimeString()})`);
19
+ }
20
+ else if (data.status === 'conflict') {
21
+ console.error(`Conflict: ${filePath} is locked by session ${data.holder.session_id.slice(0, 8)}…`);
22
+ console.error(` Acquired: ${new Date(data.holder.acquired_at).toLocaleTimeString()}`);
23
+ console.error(` Expires: ${new Date(data.holder.expires_at).toLocaleTimeString()}`);
24
+ process.exit(1);
25
+ }
26
+ }
27
+ //# sourceMappingURL=lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.js","sourceRoot":"","sources":["../../src/commands/lock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAAgB,EAAE,IAAwC;IAC1F,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,cAAc,EAAE,CAAC;IAC/D,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,IAAI,UAAU,MAAM,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IAC9E,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;IAE3D,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC;QACpC,UAAU,EAAE,MAAM,CAAC,SAAS;QAC5B,SAAS,EAAE,QAAQ;QACnB,UAAU,EAAE,SAAS;QACrB,WAAW,EAAE,GAAG;KACjB,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,OAAO,CAAC,KAAK,CAAC,mBAAmB,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QACjD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAK,CAAC;IAE1B,IAAI,IAAI,CAAC,MAAM,KAAK,UAAU,IAAI,IAAI,CAAC,MAAM,KAAK,cAAc,EAAE,CAAC;QACjE,OAAO,CAAC,GAAG,CAAC,WAAW,QAAQ,cAAc,IAAI,IAAI,CAAC,IAAI,CAAC,UAAW,CAAC,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;IACnG,CAAC;SAAM,IAAI,IAAI,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QACtC,OAAO,CAAC,KAAK,CAAC,aAAa,QAAQ,yBAAyB,IAAI,CAAC,MAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;QACpG,OAAO,CAAC,KAAK,CAAC,eAAe,IAAI,IAAI,CAAC,IAAI,CAAC,MAAO,CAAC,WAAW,CAAC,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC;QACxF,OAAO,CAAC,KAAK,CAAC,eAAe,IAAI,IAAI,CAAC,IAAI,CAAC,MAAO,CAAC,UAAU,CAAC,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC;QACvF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function loginCommand(): Promise<void>;
2
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAQA,wBAAsB,YAAY,kBAoBjC"}
@@ -0,0 +1,106 @@
1
+ import { createServer } from 'node:http';
2
+ import { writeFile, mkdir } from 'node:fs/promises';
3
+ import { dirname } from 'node:path';
4
+ import { getCredentialsPath } from '@preclaim/core';
5
+ const SUPABASE_URL = 'https://aawbukcvngdffueowjsa.supabase.co';
6
+ const SUPABASE_ANON_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImFhd2J1a2N2bmdkZmZ1ZW93anNhIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzM3NjI2NTcsImV4cCI6MjA4OTMzODY1N30.pwAyjgnbdoZmmJdsG2jF0nbvT4hueb8UZvstsdYhFFs';
7
+ export async function loginCommand() {
8
+ const server = createServer();
9
+ const port = await new Promise((resolve) => {
10
+ server.listen(0, () => {
11
+ resolve(server.address().port);
12
+ });
13
+ });
14
+ const redirectTo = `http://localhost:${port}/callback`;
15
+ const oauthUrl = `${SUPABASE_URL}/auth/v1/authorize?provider=github&redirect_to=${encodeURIComponent(redirectTo)}`;
16
+ console.log('Opening browser for GitHub authentication...');
17
+ console.log(`If browser doesn't open, visit:\n${oauthUrl}\n`);
18
+ const { exec } = await import('node:child_process');
19
+ const openCmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open';
20
+ exec(`${openCmd} "${oauthUrl}"`);
21
+ await handleAuthCallback(server);
22
+ }
23
+ function handleAuthCallback(server) {
24
+ return new Promise((resolve, reject) => {
25
+ server.on('request', async (req, res) => {
26
+ const url = new URL(req.url, `http://localhost`);
27
+ if (url.pathname === '/callback') {
28
+ // Supabase implicit flow: tokens come in hash fragment.
29
+ // Serve a page that extracts them and POSTs to /token.
30
+ res.writeHead(200, { 'Content-Type': 'text/html' });
31
+ res.end(`<!DOCTYPE html><html><body>
32
+ <h1>Logging in to Preclaim...</h1>
33
+ <script>
34
+ const hash = window.location.hash.substring(1);
35
+ const params = new URLSearchParams(hash);
36
+ const access_token = params.get('access_token');
37
+ const refresh_token = params.get('refresh_token');
38
+ const expires_in = params.get('expires_in');
39
+ if (access_token) {
40
+ fetch('/token', {
41
+ method: 'POST',
42
+ headers: { 'Content-Type': 'application/json' },
43
+ body: JSON.stringify({ access_token, refresh_token, expires_in })
44
+ }).then(() => {
45
+ document.body.innerHTML = '<h1>Logged in to Preclaim!</h1><p>You can close this tab.</p>';
46
+ });
47
+ } else {
48
+ document.body.innerHTML = '<h1>Login failed</h1><p>No token received. Check the URL.</p>';
49
+ }
50
+ </script></body></html>`);
51
+ return;
52
+ }
53
+ if (url.pathname === '/token' && req.method === 'POST') {
54
+ let body = '';
55
+ req.on('data', (chunk) => { body += chunk; });
56
+ req.on('end', async () => {
57
+ try {
58
+ const { access_token, refresh_token, expires_in } = JSON.parse(body);
59
+ // Get user info
60
+ const userRes = await fetch(`${SUPABASE_URL}/auth/v1/user`, {
61
+ headers: {
62
+ 'Authorization': `Bearer ${access_token}`,
63
+ 'apikey': SUPABASE_ANON_KEY,
64
+ },
65
+ });
66
+ if (!userRes.ok)
67
+ throw new Error(`Failed to get user info: ${userRes.status}`);
68
+ const user = await userRes.json();
69
+ // Save credentials
70
+ const credPath = getCredentialsPath();
71
+ await mkdir(dirname(credPath), { recursive: true });
72
+ await writeFile(credPath, JSON.stringify({
73
+ accessToken: access_token,
74
+ refreshToken: refresh_token,
75
+ expiresAt: new Date(Date.now() + parseInt(expires_in) * 1000).toISOString(),
76
+ user: {
77
+ id: user.id,
78
+ email: user.email ?? '',
79
+ orgId: '',
80
+ },
81
+ }, null, 2) + '\n', { mode: 0o600 });
82
+ res.writeHead(200);
83
+ res.end('ok');
84
+ console.log(`Logged in as ${user.email ?? user.id}`);
85
+ server.close();
86
+ resolve();
87
+ }
88
+ catch (err) {
89
+ res.writeHead(500);
90
+ res.end('error');
91
+ console.error('Login failed:', err);
92
+ server.close();
93
+ reject(err);
94
+ }
95
+ });
96
+ return;
97
+ }
98
+ });
99
+ setTimeout(() => {
100
+ console.error('Login timed out.');
101
+ server.close();
102
+ process.exit(1);
103
+ }, 120_000);
104
+ });
105
+ }
106
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAe,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,kBAAkB,EAAc,MAAM,gBAAgB,CAAC;AAEhE,MAAM,YAAY,GAAG,0CAA0C,CAAC;AAChE,MAAM,iBAAiB,GAAG,kNAAkN,CAAC;AAE7O,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAE9B,MAAM,IAAI,GAAG,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;QACjD,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE;YACpB,OAAO,CAAE,MAAM,CAAC,OAAO,EAAuB,CAAC,IAAI,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,oBAAoB,IAAI,WAAW,CAAC;IACvD,MAAM,QAAQ,GAAG,GAAG,YAAY,kDAAkD,kBAAkB,CAAC,UAAU,CAAC,EAAE,CAAC;IAEnH,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;IAC5D,OAAO,CAAC,GAAG,CAAC,oCAAoC,QAAQ,IAAI,CAAC,CAAC;IAE9D,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC;IAC7G,IAAI,CAAC,GAAG,OAAO,KAAK,QAAQ,GAAG,CAAC,CAAC;IAEjC,MAAM,kBAAkB,CAAC,MAAM,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAc;IACxC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;YACtC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAI,EAAE,kBAAkB,CAAC,CAAC;YAElD,IAAI,GAAG,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;gBACjC,wDAAwD;gBACxD,uDAAuD;gBACvD,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,CAAC;gBACpD,GAAG,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;wBAmBQ,CAAC,CAAC;gBAClB,OAAO;YACT,CAAC;YAED,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBACvD,IAAI,IAAI,GAAG,EAAE,CAAC;gBACd,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,GAAG,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;gBACtD,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE;oBACvB,IAAI,CAAC;wBACH,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;wBAErE,gBAAgB;wBAChB,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,GAAG,YAAY,eAAe,EAAE;4BAC1D,OAAO,EAAE;gCACP,eAAe,EAAE,UAAU,YAAY,EAAE;gCACzC,QAAQ,EAAE,iBAAiB;6BAC5B;yBACF,CAAC,CAAC;wBAEH,IAAI,CAAC,OAAO,CAAC,EAAE;4BAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;wBAE/E,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,EAAoC,CAAC;wBAEpE,mBAAmB;wBACnB,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAC;wBACtC,MAAM,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;wBACpD,MAAM,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC;4BACvC,WAAW,EAAE,YAAY;4BACzB,YAAY,EAAE,aAAa;4BAC3B,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE;4BAC3E,IAAI,EAAE;gCACJ,EAAE,EAAE,IAAI,CAAC,EAAE;gCACX,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE;gCACvB,KAAK,EAAE,EAAE;6BACV;yBACF,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;wBAErC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;wBACnB,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;wBAEd,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;wBACrD,MAAM,CAAC,KAAK,EAAE,CAAC;wBACf,OAAO,EAAE,CAAC;oBACZ,CAAC;oBAAC,OAAO,GAAG,EAAE,CAAC;wBACb,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;wBACnB,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;wBACjB,OAAO,CAAC,KAAK,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC;wBACpC,MAAM,CAAC,KAAK,EAAE,CAAC;wBACf,MAAM,CAAC,GAAG,CAAC,CAAC;oBACd,CAAC;gBACH,CAAC,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,UAAU,CAAC,GAAG,EAAE;YACd,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;YAClC,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,EAAE,OAAO,CAAC,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function statusCommand(): Promise<void>;
2
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAGA,wBAAsB,aAAa,kBAWlC"}
@@ -0,0 +1,12 @@
1
+ import { resolveContext } from '../lib/client-factory.js';
2
+ import { formatLockTable } from '../lib/output.js';
3
+ export async function statusCommand() {
4
+ const { client, config } = await resolveContext();
5
+ const result = await client.listLocks(config.projectId);
6
+ if (result.error) {
7
+ console.error(`Failed to fetch status: ${result.error}`);
8
+ process.exit(1);
9
+ }
10
+ console.log(formatLockTable(result.data));
11
+ }
12
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,cAAc,EAAE,CAAC;IAElD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAExD,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,OAAO,CAAC,KAAK,CAAC,2BAA2B,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,MAAM,CAAC,IAAK,CAAC,CAAC,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function unlockCommand(filePath: string | undefined, opts: {
2
+ session?: string;
3
+ all?: boolean;
4
+ }): Promise<void>;
5
+ //# sourceMappingURL=unlock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unlock.d.ts","sourceRoot":"","sources":["../../src/commands/unlock.ts"],"names":[],"mappings":"AAEA,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,iBAsB1G"}
@@ -0,0 +1,20 @@
1
+ import { resolveContext } from '../lib/client-factory.js';
2
+ export async function unlockCommand(filePath, opts) {
3
+ const { client, config } = await resolveContext();
4
+ if (!filePath && !opts.all) {
5
+ console.error('Specify a file path or use --all to release all locks.');
6
+ process.exit(1);
7
+ }
8
+ const sessionId = opts.session ?? `manual_${crypto.randomUUID().slice(0, 8)}`;
9
+ const result = await client.releaseLocks({
10
+ project_id: config.projectId,
11
+ file_path: filePath,
12
+ session_id: sessionId,
13
+ });
14
+ if (result.error) {
15
+ console.error(`Failed to unlock: ${result.error}`);
16
+ process.exit(1);
17
+ }
18
+ console.log(`Released ${result.data.released} lock(s).`);
19
+ }
20
+ //# sourceMappingURL=unlock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unlock.js","sourceRoot":"","sources":["../../src/commands/unlock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAA4B,EAAE,IAAyC;IACzG,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,cAAc,EAAE,CAAC;IAElD,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QAC3B,OAAO,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;QACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,IAAI,UAAU,MAAM,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IAE9E,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC;QACvC,UAAU,EAAE,MAAM,CAAC,SAAS;QAC5B,SAAS,EAAE,QAAQ;QACnB,UAAU,EAAE,SAAS;KACtB,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,OAAO,CAAC,KAAK,CAAC,qBAAqB,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,IAAK,CAAC,QAAQ,WAAW,CAAC,CAAC;AAC5D,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function whoamiCommand(): Promise<void>;
2
+ //# sourceMappingURL=whoami.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whoami.d.ts","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AAEA,wBAAsB,aAAa,kBAYlC"}
@@ -0,0 +1,13 @@
1
+ import { loadCredentials } from '@preclaim/core';
2
+ export async function whoamiCommand() {
3
+ const creds = await loadCredentials();
4
+ if (!creds) {
5
+ console.log('Not logged in. Run `preclaim login` to authenticate.');
6
+ return;
7
+ }
8
+ console.log(`Email: ${creds.user.email}`);
9
+ console.log(`User: ${creds.user.id}`);
10
+ console.log(`Org: ${creds.user.orgId ?? 'none'}`);
11
+ console.log(`Expires: ${new Date(creds.expiresAt).toLocaleString()}`);
12
+ }
13
+ //# sourceMappingURL=whoami.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,KAAK,GAAG,MAAM,eAAe,EAAE,CAAC;IAEtC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAC;QACpE,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IAC3C,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,MAAM,EAAE,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;AACxE,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=heartbeat-daemon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heartbeat-daemon.d.ts","sourceRoot":"","sources":["../../src/hooks/heartbeat-daemon.ts"],"names":[],"mappings":""}
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env node
2
+ // Heartbeat daemon — runs as detached background process
3
+ // Extends TTL on all session locks every 60s
4
+ import { PreclaimClient } from '@preclaim/core';
5
+ const sessionId = process.env.PRECLAIM_SESSION_ID;
6
+ const backend = process.env.PRECLAIM_BACKEND;
7
+ const accessToken = process.env.PRECLAIM_ACCESS_TOKEN;
8
+ if (!sessionId || !backend || !accessToken) {
9
+ process.exit(1);
10
+ }
11
+ const client = new PreclaimClient({
12
+ baseUrl: backend,
13
+ accessToken,
14
+ timeoutMs: 5000,
15
+ });
16
+ const INTERVAL_MS = 60_000;
17
+ const MAX_FAILURES = 5;
18
+ let failures = 0;
19
+ async function heartbeat() {
20
+ const result = await client.heartbeat({ session_id: sessionId });
21
+ if (result.error) {
22
+ failures++;
23
+ if (failures >= MAX_FAILURES) {
24
+ process.exit(1);
25
+ }
26
+ }
27
+ else {
28
+ failures = 0;
29
+ }
30
+ }
31
+ // Run immediately, then every 60s
32
+ heartbeat();
33
+ const interval = setInterval(heartbeat, INTERVAL_MS);
34
+ // Cleanup on signals
35
+ function shutdown() {
36
+ clearInterval(interval);
37
+ process.exit(0);
38
+ }
39
+ process.on('SIGTERM', shutdown);
40
+ process.on('SIGINT', shutdown);
41
+ //# sourceMappingURL=heartbeat-daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heartbeat-daemon.js","sourceRoot":"","sources":["../../src/hooks/heartbeat-daemon.ts"],"names":[],"mappings":";AACA,yDAAyD;AACzD,6CAA6C;AAE7C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;AAClD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;AAC7C,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;AAEtD,IAAI,CAAC,SAAS,IAAI,CAAC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;IAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC;IAChC,OAAO,EAAE,OAAO;IAChB,WAAW;IACX,SAAS,EAAE,IAAI;CAChB,CAAC,CAAC;AAEH,MAAM,WAAW,GAAG,MAAM,CAAC;AAC3B,MAAM,YAAY,GAAG,CAAC,CAAC;AACvB,IAAI,QAAQ,GAAG,CAAC,CAAC;AAEjB,KAAK,UAAU,SAAS;IACtB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,SAAU,EAAE,CAAC,CAAC;IAElE,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,QAAQ,EAAE,CAAC;QACX,IAAI,QAAQ,IAAI,YAAY,EAAE,CAAC;YAC7B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;SAAM,CAAC;QACN,QAAQ,GAAG,CAAC,CAAC;IACf,CAAC;AACH,CAAC;AAED,kCAAkC;AAClC,SAAS,EAAE,CAAC;AACZ,MAAM,QAAQ,GAAG,WAAW,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;AAErD,qBAAqB;AACrB,SAAS,QAAQ;IACf,aAAa,CAAC,QAAQ,CAAC,CAAC;IACxB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AAChC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=post-tool-use.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-tool-use.d.ts","sourceRoot":"","sources":["../../src/hooks/post-tool-use.ts"],"names":[],"mappings":""}