@inixiative/archive 0.9.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inixiative/archive",
3
- "version": "0.9.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.2.1",
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.55",
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
@@ -192,6 +192,8 @@ export async function runCli(args = Bun.argv.slice(2)) {
192
192
  sourceId: await local.sourceId(),
193
193
  directory: join(home, 'kingdom'),
194
194
  onReview: (review) => console.error(JSON.stringify(review)),
195
+ onError: (error) =>
196
+ console.error(`Still waiting: ${error instanceof Error ? error.message : String(error)}`),
195
197
  confirmOwner: async ({ ownerName }) => {
196
198
  if (v.yes) return true;
197
199
  if (!process.stdin.isTTY)
package/src/kingdom.ts CHANGED
@@ -1,20 +1,6 @@
1
- import { existsSync } from 'node:fs';
2
- import { join } from 'node:path';
3
- import {
4
- collectSignet,
5
- generateSignetKey,
6
- installationInquiries,
7
- kingdomUrl,
8
- registerInstallation,
9
- requestRegistration,
10
- SignetClient,
11
- saveCollectedSignet,
12
- writePrivateJson,
13
- } from '@inixiative/signet';
1
+ import { pairInstallation, SignetClient } from '@inixiative/signet';
14
2
  import type { ArchiveDestination } from './config';
15
3
 
16
- const pollMs = 3000;
17
-
18
4
  /** Libraries this Archive's Signet may write to, as Kingdom describes them. */
19
5
  export async function writableLibraries(credentialFile: string) {
20
6
  const description = await (await SignetClient.fromFile(credentialFile)).describe();
@@ -36,74 +22,42 @@ type Pairing = {
36
22
  directory: string;
37
23
  onReview: (review: { reviewCode: string; review: string; expiresAt: string }) => void;
38
24
  confirmOwner: (owner: { ownerName: string | null; owner: unknown }) => Promise<boolean>;
39
- sleep?: (ms: number) => Promise<unknown>;
25
+ onError?: (error: unknown) => void;
26
+ socketOptions?: { pollMs?: number; retryBaseMs?: number; authTimeoutMs?: number };
40
27
  };
41
28
 
42
- /** The key that names this Archive to one Kingdom; reused for every owner it registers with. */
43
- async function installationKey(directory: string) {
44
- const keyFile = join(directory, 'installation-key.json');
45
- if (!existsSync(keyFile)) await writePrivateJson(keyFile, generateSignetKey());
46
- return keyFile;
47
- }
48
-
49
29
  /**
50
- * Registers this Archive with Kingdom as an Installation and asks to become an owner's local
51
- * Archive integration. A person claims the review code in Kingdom; once approved, the Archive
52
- * confirms the owner locally before collecting its Signet.
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.
53
32
  */
54
33
  export async function pairWithKingdom(input: Pairing) {
55
- const kingdom = kingdomUrl(input.kingdom);
56
- const directory = join(input.directory, new URL(kingdom).host);
57
- const keyFile = await installationKey(directory);
58
- await registerInstallation(kingdom, keyFile, {
34
+ const paired = await pairInstallation({
35
+ url: input.kingdom,
36
+ root: input.directory,
59
37
  kind: 'archive',
60
38
  name: input.name,
61
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,
62
52
  });
63
- const askedAt = Date.now();
64
- const pending = await requestRegistration(kingdom, keyFile, {
65
- name: input.name,
66
- lifecycle: 'ongoing',
67
- resources: [],
68
- expiresAt: null,
69
- maxRequests: null,
70
- maxConcurrent: 4,
71
- });
72
- input.onReview({
73
- reviewCode: pending.reviewCode,
74
- review: `${kingdom}/dashboard?reviewSignet=${pending.reviewCode}`,
75
- expiresAt: pending.expiresAt,
76
- });
77
- const sleep = input.sleep ?? Bun.sleep;
78
- for (;;) {
79
- const state = await installationInquiries(kingdom, keyFile);
80
- if (state.declinedAt && Date.parse(state.declinedAt) >= askedAt)
81
- throw new Error('The registration was declined in Kingdom');
82
- const inquiry = state.inquiries.find(
83
- (item) => item.type === 'registerIntegration' && Date.parse(item.createdAt) >= askedAt,
84
- );
85
- if (inquiry?.status === 'approved') {
86
- if (!(await input.confirmOwner({ ownerName: inquiry.ownerName, owner: inquiry.owner })))
87
- throw new Error('Not collected: the owner was not confirmed');
88
- const collected = await collectSignet(kingdom, keyFile, inquiry.id);
89
- if (!collected) throw new Error('Kingdom has not released the Signet yet; try again');
90
- const credentialFile = join(directory, `signet-${collected.signetId}.json`);
91
- await saveCollectedSignet(credentialFile, kingdom, keyFile, collected);
92
- return {
93
- paired: true,
94
- owner: inquiry.ownerName,
95
- integrationId: collected.integrationId,
96
- credentialFile,
97
- libraries: await writableLibraries(credentialFile),
98
- next: 'archive connect --kind kingdom --url KINGDOM --credential-file FILE --integration-id ID --resource-id ID --project-id PROJECT',
99
- };
100
- }
101
- if (inquiry && inquiry.status !== 'sent')
102
- throw new Error(`The registration was ${inquiry.status} in Kingdom`);
103
- if (!inquiry && !state.pending)
104
- throw new Error('The review code expired before it was claimed; run archive pair again');
105
- await sleep(pollMs);
106
- }
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
+ };
107
61
  }
108
62
 
109
63
  export async function verifyKingdomDestination(