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.
- package/.turbo/turbo-build.log +4 -0
- package/dist/commands/check.d.ts +2 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +25 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/config.d.ts +5 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +37 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/init.d.ts +5 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +95 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/install-hooks.d.ts +2 -0
- package/dist/commands/install-hooks.d.ts.map +1 -0
- package/dist/commands/install-hooks.js +58 -0
- package/dist/commands/install-hooks.js.map +1 -0
- package/dist/commands/lock.d.ts +5 -0
- package/dist/commands/lock.d.ts.map +1 -0
- package/dist/commands/lock.js +27 -0
- package/dist/commands/lock.js.map +1 -0
- package/dist/commands/login.d.ts +2 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +106 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +12 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/unlock.d.ts +5 -0
- package/dist/commands/unlock.d.ts.map +1 -0
- package/dist/commands/unlock.js +20 -0
- package/dist/commands/unlock.js.map +1 -0
- package/dist/commands/whoami.d.ts +2 -0
- package/dist/commands/whoami.d.ts.map +1 -0
- package/dist/commands/whoami.js +13 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/hooks/heartbeat-daemon.d.ts +3 -0
- package/dist/hooks/heartbeat-daemon.d.ts.map +1 -0
- package/dist/hooks/heartbeat-daemon.js +41 -0
- package/dist/hooks/heartbeat-daemon.js.map +1 -0
- package/dist/hooks/post-tool-use.d.ts +3 -0
- package/dist/hooks/post-tool-use.d.ts.map +1 -0
- package/dist/hooks/post-tool-use.js +41 -0
- package/dist/hooks/post-tool-use.js.map +1 -0
- package/dist/hooks/pre-tool-use.d.ts +3 -0
- package/dist/hooks/pre-tool-use.d.ts.map +1 -0
- package/dist/hooks/pre-tool-use.js +101 -0
- package/dist/hooks/pre-tool-use.js.map +1 -0
- package/dist/hooks/session-start.d.ts +3 -0
- package/dist/hooks/session-start.d.ts.map +1 -0
- package/dist/hooks/session-start.js +77 -0
- package/dist/hooks/session-start.js.map +1 -0
- package/dist/hooks/stop.d.ts +3 -0
- package/dist/hooks/stop.d.ts.map +1 -0
- package/dist/hooks/stop.js +40 -0
- package/dist/hooks/stop.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +62 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/auth.d.ts +3 -0
- package/dist/lib/auth.d.ts.map +1 -0
- package/dist/lib/auth.js +15 -0
- package/dist/lib/auth.js.map +1 -0
- package/dist/lib/client-factory.d.ts +8 -0
- package/dist/lib/client-factory.d.ts.map +1 -0
- package/dist/lib/client-factory.js +17 -0
- package/dist/lib/client-factory.js.map +1 -0
- package/dist/lib/hook-io.d.ts +13 -0
- package/dist/lib/hook-io.d.ts.map +1 -0
- package/dist/lib/hook-io.js +24 -0
- package/dist/lib/hook-io.js.map +1 -0
- package/dist/lib/output.d.ts +4 -0
- package/dist/lib/output.d.ts.map +1 -0
- package/dist/lib/output.js +17 -0
- package/dist/lib/output.js.map +1 -0
- package/package.json +24 -0
- package/src/commands/check.ts +28 -0
- package/src/commands/config.ts +43 -0
- package/src/commands/init.ts +109 -0
- package/src/commands/install-hooks.ts +72 -0
- package/src/commands/lock.ts +30 -0
- package/src/commands/login.ts +120 -0
- package/src/commands/status.ts +15 -0
- package/src/commands/unlock.ts +25 -0
- package/src/commands/whoami.ts +15 -0
- package/src/hooks/heartbeat-daemon.ts +49 -0
- package/src/hooks/post-tool-use.ts +44 -0
- package/src/hooks/pre-tool-use.ts +110 -0
- package/src/hooks/session-start.ts +87 -0
- package/src/hooks/stop.ts +43 -0
- package/src/index.ts +74 -0
- package/src/lib/auth.ts +17 -0
- package/src/lib/client-factory.ts +26 -0
- package/src/lib/hook-io.ts +37 -0
- package/src/lib/output.ts +20 -0
- package/tsconfig.json +8 -0
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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":"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"}
|
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
1
|
+
{"version":3,"file":"post-tool-use.d.ts","sourceRoot":"","sources":["../../src/hooks/post-tool-use.ts"],"names":[],"mappings":""}
|