@inixiative/archive 0.8.0 → 0.10.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/README.md +3 -1
- package/package.json +3 -3
- package/src/cli.ts +11 -1
- package/src/kingdom.ts +36 -64
package/README.md
CHANGED
|
@@ -76,7 +76,9 @@ First, pair this Archive with Kingdom:
|
|
|
76
76
|
bun run archive pair --kingdom https://api.your-kingdom.example --name "Work laptop"
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
-
`pair`
|
|
79
|
+
`pair` registers this Archive with Kingdom as an **Installation**, named by a key kept in `<home>/kingdom/<kingdom host>/`. The same key is reused for every owner it registers with. It then asks to be registered as an integration and prints a review code with a link.
|
|
80
|
+
|
|
81
|
+
Open the link, choose the owner and the hosted Archives this machine may write to, and approve. The command waits for approval, then shows which owner it was registered with and asks you to accept. Pass `--yes` to accept without the prompt; without a terminal, `--yes` is required. Only then does it collect the Signet (0600) and list the libraries it may write to. Confirming the owner protects you if someone else claimed your code into their own owner.
|
|
80
82
|
|
|
81
83
|
Next, route a project to one of those libraries:
|
|
82
84
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inixiative/archive",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./src/index.ts",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"prepare": "if git rev-parse --git-dir >/dev/null 2>&1; then lefthook install; fi && prisma generate"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@inixiative/signet": "^0.
|
|
38
|
+
"@inixiative/signet": "^0.3.0",
|
|
39
39
|
"@prisma/client": "^6.6.0",
|
|
40
40
|
"js-tiktoken": "1.0.21",
|
|
41
41
|
"prisma": "^6.6.0",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@biomejs/biome": "2.5.2",
|
|
46
|
-
"@inixiative/config": "^0.5.
|
|
46
|
+
"@inixiative/config": "^0.5.62",
|
|
47
47
|
"@types/bun": "1.4.2",
|
|
48
48
|
"lefthook": "2.1.9",
|
|
49
49
|
"typescript": "6.0.3"
|
package/src/cli.ts
CHANGED
|
@@ -71,6 +71,7 @@ export async function runCli(args = Bun.argv.slice(2)) {
|
|
|
71
71
|
watch: { type: 'boolean', default: false },
|
|
72
72
|
sync: { type: 'boolean', default: false },
|
|
73
73
|
remote: { type: 'boolean', default: false },
|
|
74
|
+
yes: { type: 'boolean', default: false },
|
|
74
75
|
help: { type: 'boolean' },
|
|
75
76
|
},
|
|
76
77
|
});
|
|
@@ -87,7 +88,7 @@ export async function runCli(args = Bun.argv.slice(2)) {
|
|
|
87
88
|
'import --file PATH --source codex|claude-code|chatgpt --project-id ID [--tag TAG]\n' +
|
|
88
89
|
'collect --directory HISTORY --source codex|claude-code --project-root EXACT_CWD [--project-root ...] [--worktrees] [--atlas] --project-id ID [--watch]\n' +
|
|
89
90
|
'list | export --id ID | tag --id ID [--tag TAG ...] [--untag TAG ...] | search --query TEXT [--remote]\n' +
|
|
90
|
-
'pair --kingdom KINGDOM_API_URL [--name NAME] (
|
|
91
|
+
'pair --kingdom KINGDOM_API_URL [--name NAME] [--yes] (register this Archive with Kingdom; claim the review code there, then confirm the owner)\n' +
|
|
91
92
|
'connect --url HTTPS_URL --project-id ID (--token-env ENV | --token-file PATH) (a remote Archive, for serve --sync)\n' +
|
|
92
93
|
'connect --kind kingdom --url KINGDOM_API_URL --credential-file PATH --integration-id UUID --resource-id UUID --project-id ID (a hosted Archive through Kingdom)\n' +
|
|
93
94
|
'sync | routes (DATABASE_URL: publish to, or preview, destinations once)\n' +
|
|
@@ -191,6 +192,15 @@ export async function runCli(args = Bun.argv.slice(2)) {
|
|
|
191
192
|
sourceId: await local.sourceId(),
|
|
192
193
|
directory: join(home, 'kingdom'),
|
|
193
194
|
onReview: (review) => console.error(JSON.stringify(review)),
|
|
195
|
+
onError: (error) =>
|
|
196
|
+
console.error(`Still waiting: ${error instanceof Error ? error.message : String(error)}`),
|
|
197
|
+
confirmOwner: async ({ ownerName }) => {
|
|
198
|
+
if (v.yes) return true;
|
|
199
|
+
if (!process.stdin.isTTY)
|
|
200
|
+
throw new Error(`Registered with ${ownerName}; rerun with --yes to accept it`);
|
|
201
|
+
const answer = prompt(`Kingdom registered this Archive with ${ownerName}. Accept? [y/N]`);
|
|
202
|
+
return /^y(es)?$/i.test(answer?.trim() ?? '');
|
|
203
|
+
},
|
|
194
204
|
}),
|
|
195
205
|
);
|
|
196
206
|
return;
|
package/src/kingdom.ts
CHANGED
|
@@ -1,18 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { join } from 'node:path';
|
|
3
|
-
import {
|
|
4
|
-
collectPairing,
|
|
5
|
-
generateSignetKey,
|
|
6
|
-
kingdomUrl,
|
|
7
|
-
requestPairing,
|
|
8
|
-
SignetClient,
|
|
9
|
-
saveCollectedSignet,
|
|
10
|
-
writePrivateJson,
|
|
11
|
-
} from '@inixiative/signet';
|
|
1
|
+
import { pairInstallation, SignetClient } from '@inixiative/signet';
|
|
12
2
|
import type { ArchiveDestination } from './config';
|
|
13
3
|
|
|
14
|
-
const pollMs = 3000;
|
|
15
|
-
|
|
16
4
|
/** Libraries this Archive's Signet may write to, as Kingdom describes them. */
|
|
17
5
|
export async function writableLibraries(credentialFile: string) {
|
|
18
6
|
const description = await (await SignetClient.fromFile(credentialFile)).describe();
|
|
@@ -27,65 +15,49 @@ export async function writableLibraries(credentialFile: string) {
|
|
|
27
15
|
);
|
|
28
16
|
}
|
|
29
17
|
|
|
30
|
-
|
|
31
|
-
* Pairs this Archive with Kingdom as a local Archive integration bound to its sourceId. The owner
|
|
32
|
-
* approves the review code in Kingdom and chooses which hosted Archives it may write to.
|
|
33
|
-
*/
|
|
34
|
-
export async function pairWithKingdom(input: {
|
|
18
|
+
type Pairing = {
|
|
35
19
|
kingdom: string;
|
|
36
20
|
name: string;
|
|
37
21
|
sourceId: string;
|
|
38
22
|
directory: string;
|
|
39
23
|
onReview: (review: { reviewCode: string; review: string; expiresAt: string }) => void;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
await writePrivateJson(keyFile, generateSignetKey());
|
|
45
|
-
try {
|
|
46
|
-
return await awaitPairing(kingdom, keyFile, input);
|
|
47
|
-
} catch (error) {
|
|
48
|
-
await rm(keyFile, { force: true });
|
|
49
|
-
throw error;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
24
|
+
confirmOwner: (owner: { ownerName: string | null; owner: unknown }) => Promise<boolean>;
|
|
25
|
+
onError?: (error: unknown) => void;
|
|
26
|
+
socketOptions?: { pollMs?: number; retryBaseMs?: number; authTimeoutMs?: number };
|
|
27
|
+
};
|
|
52
28
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
) {
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Pairs this Archive with Kingdom as an Installation: a person claims the review code, the Archive
|
|
31
|
+
* confirms the owner locally, then collects the Signet for its local Archive integration.
|
|
32
|
+
*/
|
|
33
|
+
export async function pairWithKingdom(input: Pairing) {
|
|
34
|
+
const paired = await pairInstallation({
|
|
35
|
+
url: input.kingdom,
|
|
36
|
+
root: input.directory,
|
|
37
|
+
kind: 'archive',
|
|
61
38
|
name: input.name,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
39
|
+
sourceId: input.sourceId,
|
|
40
|
+
terms: {
|
|
41
|
+
name: input.name,
|
|
42
|
+
lifecycle: 'ongoing',
|
|
43
|
+
resources: [],
|
|
44
|
+
expiresAt: null,
|
|
45
|
+
maxRequests: null,
|
|
46
|
+
maxConcurrent: 4,
|
|
47
|
+
},
|
|
48
|
+
onReview: input.onReview,
|
|
49
|
+
confirmOwner: input.confirmOwner,
|
|
50
|
+
onError: input.onError,
|
|
51
|
+
socketOptions: input.socketOptions,
|
|
71
52
|
});
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
integrationId: collected.integrationId,
|
|
81
|
-
credentialFile,
|
|
82
|
-
libraries: await writableLibraries(credentialFile),
|
|
83
|
-
next: 'archive connect --kind kingdom --url KINGDOM --credential-file FILE --integration-id ID --resource-id ID --project-id PROJECT',
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
await sleep(pollMs);
|
|
87
|
-
}
|
|
88
|
-
throw new Error('The review code expired before it was approved; run archive pair again');
|
|
53
|
+
return {
|
|
54
|
+
paired: true,
|
|
55
|
+
owner: paired.ownerName,
|
|
56
|
+
integrationId: paired.integrationId,
|
|
57
|
+
credentialFile: paired.credentialFile,
|
|
58
|
+
libraries: await writableLibraries(paired.credentialFile),
|
|
59
|
+
next: 'archive connect --kind kingdom --url KINGDOM --credential-file FILE --integration-id ID --resource-id ID --project-id PROJECT',
|
|
60
|
+
};
|
|
89
61
|
}
|
|
90
62
|
|
|
91
63
|
export async function verifyKingdomDestination(
|