@spool-lab/core 0.3.3

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 (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +39 -0
  3. package/dist/connectors/capabilities/cookies-chrome.d.ts +19 -0
  4. package/dist/connectors/capabilities/cookies-chrome.d.ts.map +1 -0
  5. package/dist/connectors/capabilities/cookies-chrome.js +199 -0
  6. package/dist/connectors/capabilities/cookies-chrome.js.map +1 -0
  7. package/dist/connectors/capabilities/exec-impl.d.ts +3 -0
  8. package/dist/connectors/capabilities/exec-impl.d.ts.map +1 -0
  9. package/dist/connectors/capabilities/exec-impl.js +108 -0
  10. package/dist/connectors/capabilities/exec-impl.js.map +1 -0
  11. package/dist/connectors/capabilities/fetch-impl.d.ts +3 -0
  12. package/dist/connectors/capabilities/fetch-impl.d.ts.map +1 -0
  13. package/dist/connectors/capabilities/fetch-impl.js +4 -0
  14. package/dist/connectors/capabilities/fetch-impl.js.map +1 -0
  15. package/dist/connectors/capabilities/index.d.ts +6 -0
  16. package/dist/connectors/capabilities/index.d.ts.map +1 -0
  17. package/dist/connectors/capabilities/index.js +6 -0
  18. package/dist/connectors/capabilities/index.js.map +1 -0
  19. package/dist/connectors/capabilities/log-impl.d.ts +3 -0
  20. package/dist/connectors/capabilities/log-impl.d.ts.map +1 -0
  21. package/dist/connectors/capabilities/log-impl.js +26 -0
  22. package/dist/connectors/capabilities/log-impl.js.map +1 -0
  23. package/dist/connectors/capabilities/sqlite-impl.d.ts +3 -0
  24. package/dist/connectors/capabilities/sqlite-impl.d.ts.map +1 -0
  25. package/dist/connectors/capabilities/sqlite-impl.js +19 -0
  26. package/dist/connectors/capabilities/sqlite-impl.js.map +1 -0
  27. package/dist/connectors/loader.d.ts +47 -0
  28. package/dist/connectors/loader.d.ts.map +1 -0
  29. package/dist/connectors/loader.js +328 -0
  30. package/dist/connectors/loader.js.map +1 -0
  31. package/dist/connectors/npm-install.d.ts +26 -0
  32. package/dist/connectors/npm-install.d.ts.map +1 -0
  33. package/dist/connectors/npm-install.js +71 -0
  34. package/dist/connectors/npm-install.js.map +1 -0
  35. package/dist/connectors/prerequisites.d.ts +14 -0
  36. package/dist/connectors/prerequisites.d.ts.map +1 -0
  37. package/dist/connectors/prerequisites.js +109 -0
  38. package/dist/connectors/prerequisites.js.map +1 -0
  39. package/dist/connectors/registry-fetch.d.ts +22 -0
  40. package/dist/connectors/registry-fetch.d.ts.map +1 -0
  41. package/dist/connectors/registry-fetch.js +54 -0
  42. package/dist/connectors/registry-fetch.js.map +1 -0
  43. package/dist/connectors/registry.d.ts +23 -0
  44. package/dist/connectors/registry.d.ts.map +1 -0
  45. package/dist/connectors/registry.js +59 -0
  46. package/dist/connectors/registry.js.map +1 -0
  47. package/dist/connectors/sync-engine.d.ts +30 -0
  48. package/dist/connectors/sync-engine.d.ts.map +1 -0
  49. package/dist/connectors/sync-engine.js +589 -0
  50. package/dist/connectors/sync-engine.js.map +1 -0
  51. package/dist/connectors/sync-scheduler.d.ts +56 -0
  52. package/dist/connectors/sync-scheduler.d.ts.map +1 -0
  53. package/dist/connectors/sync-scheduler.js +238 -0
  54. package/dist/connectors/sync-scheduler.js.map +1 -0
  55. package/dist/connectors/trust-store.d.ts +13 -0
  56. package/dist/connectors/trust-store.d.ts.map +1 -0
  57. package/dist/connectors/trust-store.js +48 -0
  58. package/dist/connectors/trust-store.js.map +1 -0
  59. package/dist/connectors/types.d.ts +111 -0
  60. package/dist/connectors/types.d.ts.map +1 -0
  61. package/dist/connectors/types.js +50 -0
  62. package/dist/connectors/types.js.map +1 -0
  63. package/dist/db/db.d.ts +6 -0
  64. package/dist/db/db.d.ts.map +1 -0
  65. package/dist/db/db.js +347 -0
  66. package/dist/db/db.js.map +1 -0
  67. package/dist/db/queries.d.ts +68 -0
  68. package/dist/db/queries.d.ts.map +1 -0
  69. package/dist/db/queries.js +828 -0
  70. package/dist/db/queries.js.map +1 -0
  71. package/dist/db/search-query.d.ts +13 -0
  72. package/dist/db/search-query.d.ts.map +1 -0
  73. package/dist/db/search-query.js +62 -0
  74. package/dist/db/search-query.js.map +1 -0
  75. package/dist/index.d.ts +29 -0
  76. package/dist/index.d.ts.map +1 -0
  77. package/dist/index.js +24 -0
  78. package/dist/index.js.map +1 -0
  79. package/dist/parsers/claude.d.ts +9 -0
  80. package/dist/parsers/claude.d.ts.map +1 -0
  81. package/dist/parsers/claude.js +153 -0
  82. package/dist/parsers/claude.js.map +1 -0
  83. package/dist/parsers/codex.d.ts +5 -0
  84. package/dist/parsers/codex.d.ts.map +1 -0
  85. package/dist/parsers/codex.js +192 -0
  86. package/dist/parsers/codex.js.map +1 -0
  87. package/dist/parsers/gemini.d.ts +4 -0
  88. package/dist/parsers/gemini.d.ts.map +1 -0
  89. package/dist/parsers/gemini.js +149 -0
  90. package/dist/parsers/gemini.js.map +1 -0
  91. package/dist/sync/source-paths.d.ts +5 -0
  92. package/dist/sync/source-paths.d.ts.map +1 -0
  93. package/dist/sync/source-paths.js +119 -0
  94. package/dist/sync/source-paths.js.map +1 -0
  95. package/dist/sync/syncer.d.ts +19 -0
  96. package/dist/sync/syncer.d.ts.map +1 -0
  97. package/dist/sync/syncer.js +308 -0
  98. package/dist/sync/syncer.js.map +1 -0
  99. package/dist/sync/watcher.d.ts +19 -0
  100. package/dist/sync/watcher.d.ts.map +1 -0
  101. package/dist/sync/watcher.js +67 -0
  102. package/dist/sync/watcher.js.map +1 -0
  103. package/dist/types.d.ts +112 -0
  104. package/dist/types.d.ts.map +1 -0
  105. package/dist/types.js +2 -0
  106. package/dist/types.js.map +1 -0
  107. package/dist/util/resolve-bin.d.ts +6 -0
  108. package/dist/util/resolve-bin.d.ts.map +1 -0
  109. package/dist/util/resolve-bin.js +66 -0
  110. package/dist/util/resolve-bin.js.map +1 -0
  111. package/package.json +43 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Spool Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # @spool-lab/core
2
+
3
+ The engine behind [Spool](https://spool.pro) — a local search engine for your AI sessions and connected sources.
4
+
5
+ This package provides the core runtime: session parsing, full-text search, the connector sync engine, and the SQLite database layer. It powers both the Spool desktop app and the `@spool-lab/cli`.
6
+
7
+ ## Usage
8
+
9
+ ```ts
10
+ import { getDB, searchFragments, listRecentSessions, Syncer } from '@spool-lab/core'
11
+
12
+ const db = getDB()
13
+
14
+ // Search across all indexed sessions
15
+ const results = searchFragments(db, 'authentication middleware', { limit: 10 })
16
+
17
+ // List recent sessions
18
+ const sessions = listRecentSessions(db, 20)
19
+
20
+ // Sync new sessions from Claude, Codex, Gemini
21
+ const syncer = new Syncer(db)
22
+ syncer.syncAll()
23
+ ```
24
+
25
+ ## What's inside
26
+
27
+ - **Session parsers** — reads Claude Code, Codex, and Gemini CLI session files
28
+ - **Full-text search** — FTS5 with unicode + trigram indexes for CJK support
29
+ - **Sync engine** — paginated connector sync with cursor-based state, backfill, and error recovery
30
+ - **Connector loader** — discovers and loads connector plugins from `~/.spool/connectors/`
31
+ - **Connector registry** — in-memory registry of available connectors
32
+
33
+ ## Native dependency
34
+
35
+ This package depends on [`better-sqlite3`](https://github.com/WiseLibs/better-sqlite3), which includes a native C++ addon. On most platforms, prebuilt binaries are downloaded automatically during install. If that fails, you'll need a C++ toolchain (Python 3, node-gyp).
36
+
37
+ ## License
38
+
39
+ MIT
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Chrome cookie extraction for X/Twitter authentication.
3
+ *
4
+ * Adapted from fieldtheory-cli (https://github.com/afar1/fieldtheory-cli).
5
+ * Reads Chrome's encrypted cookie database on macOS, decrypts auth_token and
6
+ * ct0 (CSRF) cookies for x.com using the macOS Keychain.
7
+ */
8
+ import type { CookiesCapability } from '@spool-lab/connector-sdk';
9
+ export declare function decryptCookieValue(encryptedValue: Buffer, key: Buffer, dbVersion?: number): string;
10
+ /**
11
+ * Enumerate every Chrome `host_key` value that should match a request to `host`
12
+ * per RFC 6265 §5.1.3. Chrome stores host-only cookies under the bare hostname
13
+ * and domain cookies under `.parent.example.com`; a request to `www.example.com`
14
+ * must see cookies at `www.example.com`, `.www.example.com`, and `.example.com`
15
+ * but not anything scoped to a sibling (`.other.example.com`) or a TLD alone.
16
+ */
17
+ export declare function getMatchingHostKeys(host: string): string[];
18
+ export declare function makeChromeCookiesCapability(): CookiesCapability;
19
+ //# sourceMappingURL=cookies-chrome.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cookies-chrome.d.ts","sourceRoot":"","sources":["../../../src/connectors/capabilities/cookies-chrome.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,KAAK,EAAE,iBAAiB,EAAuB,MAAM,0BAA0B,CAAA;AAmCtF,wBAAgB,kBAAkB,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,SAAI,GAAG,MAAM,CAmB7F;AA0DD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAe1D;AAgDD,wBAAgB,2BAA2B,IAAI,iBAAiB,CAoD/D"}
@@ -0,0 +1,199 @@
1
+ /**
2
+ * Chrome cookie extraction for X/Twitter authentication.
3
+ *
4
+ * Adapted from fieldtheory-cli (https://github.com/afar1/fieldtheory-cli).
5
+ * Reads Chrome's encrypted cookie database on macOS, decrypts auth_token and
6
+ * ct0 (CSRF) cookies for x.com using the macOS Keychain.
7
+ */
8
+ import { execFileSync } from 'node:child_process';
9
+ import { existsSync, unlinkSync, copyFileSync } from 'node:fs';
10
+ import { join } from 'node:path';
11
+ import { tmpdir, platform, homedir } from 'node:os';
12
+ import { pbkdf2Sync, createDecipheriv, randomUUID } from 'node:crypto';
13
+ import { SyncError, SyncErrorCode } from '@spool-lab/connector-sdk';
14
+ function getMacOSChromeKey() {
15
+ const candidates = [
16
+ { service: 'Chrome Safe Storage', account: 'Chrome' },
17
+ { service: 'Chrome Safe Storage', account: 'Google Chrome' },
18
+ { service: 'Google Chrome Safe Storage', account: 'Chrome' },
19
+ { service: 'Google Chrome Safe Storage', account: 'Google Chrome' },
20
+ { service: 'Chromium Safe Storage', account: 'Chromium' },
21
+ { service: 'Brave Safe Storage', account: 'Brave' },
22
+ { service: 'Brave Browser Safe Storage', account: 'Brave Browser' },
23
+ ];
24
+ for (const candidate of candidates) {
25
+ try {
26
+ const password = execFileSync('security', ['find-generic-password', '-w', '-s', candidate.service, '-a', candidate.account], { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
27
+ if (password) {
28
+ return pbkdf2Sync(password, 'saltysalt', 1003, 16, 'sha1');
29
+ }
30
+ }
31
+ catch {
32
+ // Try the next known browser/keychain naming pair.
33
+ }
34
+ }
35
+ throw new SyncError(SyncErrorCode.AUTH_KEYCHAIN_DENIED, 'Could not read a browser Safe Storage password from the macOS Keychain.');
36
+ }
37
+ export function decryptCookieValue(encryptedValue, key, dbVersion = 0) {
38
+ if (encryptedValue.length === 0)
39
+ return '';
40
+ if (encryptedValue[0] === 0x76 && encryptedValue[1] === 0x31 && encryptedValue[2] === 0x30) {
41
+ const iv = Buffer.alloc(16, 0x20); // 16 spaces
42
+ const ciphertext = encryptedValue.subarray(3);
43
+ const decipher = createDecipheriv('aes-128-cbc', key, iv);
44
+ let decrypted = decipher.update(ciphertext);
45
+ decrypted = Buffer.concat([decrypted, decipher.final()]);
46
+ // Chrome DB version >= 24 (Chrome ~130+) prepends SHA256(host_key) to plaintext
47
+ if (dbVersion >= 24 && decrypted.length > 32) {
48
+ decrypted = decrypted.subarray(32);
49
+ }
50
+ return decrypted.toString('utf8');
51
+ }
52
+ return encryptedValue.toString('utf8');
53
+ }
54
+ function detectChromeUserDataDir() {
55
+ const os = platform();
56
+ const home = homedir();
57
+ if (os === 'darwin')
58
+ return join(home, 'Library', 'Application Support', 'Google', 'Chrome');
59
+ if (os === 'linux')
60
+ return join(home, '.config', 'google-chrome');
61
+ if (os === 'win32')
62
+ return join(home, 'AppData', 'Local', 'Google', 'Chrome', 'User Data');
63
+ throw new SyncError(SyncErrorCode.AUTH_CHROME_NOT_FOUND, `Unsupported platform for Chrome cookie extraction: ${os}`);
64
+ }
65
+ /**
66
+ * Run a sqlite3 query with fallback to a temp copy (Chrome locks the DB while running).
67
+ * Returns raw stdout string.
68
+ */
69
+ function runSqliteQuery(dbPath, sql) {
70
+ const tryQuery = (path) => execFileSync('sqlite3', ['-json', path, sql], {
71
+ encoding: 'utf8',
72
+ stdio: ['pipe', 'pipe', 'pipe'],
73
+ timeout: 10000,
74
+ }).trim();
75
+ try {
76
+ return tryQuery(dbPath);
77
+ }
78
+ catch {
79
+ const tmpDb = join(tmpdir(), `spool-cookies-${randomUUID()}.db`);
80
+ try {
81
+ copyFileSync(dbPath, tmpDb);
82
+ return tryQuery(tmpDb);
83
+ }
84
+ catch (e2) {
85
+ throw new SyncError(SyncErrorCode.AUTH_COOKIE_DECRYPT_FAILED, `Could not read Chrome Cookies database at ${dbPath}. ${e2 instanceof Error ? e2.message : ''}`, e2);
86
+ }
87
+ finally {
88
+ try {
89
+ unlinkSync(tmpDb);
90
+ }
91
+ catch { }
92
+ }
93
+ }
94
+ }
95
+ /**
96
+ * Enumerate every Chrome `host_key` value that should match a request to `host`
97
+ * per RFC 6265 §5.1.3. Chrome stores host-only cookies under the bare hostname
98
+ * and domain cookies under `.parent.example.com`; a request to `www.example.com`
99
+ * must see cookies at `www.example.com`, `.www.example.com`, and `.example.com`
100
+ * but not anything scoped to a sibling (`.other.example.com`) or a TLD alone.
101
+ */
102
+ export function getMatchingHostKeys(host) {
103
+ const normalized = host.toLowerCase().replace(/^\./, '');
104
+ if (!normalized || !normalized.includes('.'))
105
+ return [];
106
+ const keys = [normalized, `.${normalized}`];
107
+ let cur = normalized;
108
+ while (true) {
109
+ const idx = cur.indexOf('.');
110
+ if (idx < 0)
111
+ break;
112
+ const parent = cur.substring(idx + 1);
113
+ if (!parent.includes('.'))
114
+ break;
115
+ keys.push(`.${parent}`);
116
+ cur = parent;
117
+ }
118
+ return keys;
119
+ }
120
+ function queryAllCookiesForHost(dbPath, host) {
121
+ if (!existsSync(dbPath)) {
122
+ throw new SyncError(SyncErrorCode.AUTH_CHROME_NOT_FOUND, `Chrome Cookies database not found at: ${dbPath}`);
123
+ }
124
+ const keys = getMatchingHostKeys(host);
125
+ if (keys.length === 0)
126
+ return { cookies: [], dbVersion: 0 };
127
+ const quoted = keys.map(k => `'${k.replace(/'/g, "''")}'`).join(',');
128
+ // Fetch cookies and DB version in one sqlite3 invocation to avoid double process spawn
129
+ const sql = `SELECT name, host_key, path, hex(encrypted_value) as encrypted_value_hex, value, expires_utc, is_secure, is_httponly, (SELECT value FROM meta WHERE key='version') as db_version FROM cookies WHERE host_key IN (${quoted});`;
130
+ const output = runSqliteQuery(dbPath, sql);
131
+ if (!output || output === '[]')
132
+ return { cookies: [], dbVersion: 0 };
133
+ try {
134
+ const rows = JSON.parse(output);
135
+ const dbVersion = rows.length > 0 ? parseInt(rows[0]?.db_version ?? '0', 10) || 0 : 0;
136
+ return { cookies: rows, dbVersion };
137
+ }
138
+ catch {
139
+ return { cookies: [], dbVersion: 0 };
140
+ }
141
+ }
142
+ const CHROMIUM_EPOCH_DELTA = 11644473600;
143
+ function chromiumExpiresToUnix(expiresUtc) {
144
+ const raw = typeof expiresUtc === 'string' ? parseInt(expiresUtc, 10) : expiresUtc;
145
+ if (!raw || raw === 0)
146
+ return null;
147
+ return raw / 1_000_000 - CHROMIUM_EPOCH_DELTA;
148
+ }
149
+ function domainFromUrl(url) {
150
+ try {
151
+ return new URL(url).hostname;
152
+ }
153
+ catch {
154
+ return url;
155
+ }
156
+ }
157
+ export function makeChromeCookiesCapability() {
158
+ return {
159
+ async get(query) {
160
+ if (query.browser !== 'chrome') {
161
+ throw new SyncError(SyncErrorCode.AUTH_CHROME_NOT_FOUND, `Unsupported browser: ${query.browser}. Only 'chrome' is supported.`);
162
+ }
163
+ const os = platform();
164
+ if (os !== 'darwin') {
165
+ throw new SyncError(SyncErrorCode.AUTH_CHROME_NOT_FOUND, `Direct cookie extraction is currently supported on macOS only (detected: ${os}).`);
166
+ }
167
+ const profile = query.profile ?? 'Default';
168
+ const dataDir = detectChromeUserDataDir();
169
+ const dbPath = join(dataDir, profile, 'Cookies');
170
+ const key = getMacOSChromeKey();
171
+ const host = domainFromUrl(query.url);
172
+ const result = queryAllCookiesForHost(dbPath, host);
173
+ const cookies = [];
174
+ for (const raw of result.cookies) {
175
+ let value;
176
+ const hexVal = raw.encrypted_value_hex;
177
+ if (hexVal && hexVal.length > 0) {
178
+ const buf = Buffer.from(hexVal, 'hex');
179
+ const decrypted = decryptCookieValue(buf, key, result.dbVersion);
180
+ value = decrypted.replace(/\0+$/g, '').trim();
181
+ }
182
+ else {
183
+ value = raw.value ?? '';
184
+ }
185
+ cookies.push({
186
+ name: raw.name,
187
+ value,
188
+ domain: raw.host_key,
189
+ path: raw.path || '/',
190
+ expires: chromiumExpiresToUnix(raw.expires_utc),
191
+ secure: raw.is_secure === '1' || raw.is_secure === 'true',
192
+ httpOnly: raw.is_httponly === '1' || raw.is_httponly === 'true',
193
+ });
194
+ }
195
+ return cookies;
196
+ },
197
+ };
198
+ }
199
+ //# sourceMappingURL=cookies-chrome.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cookies-chrome.js","sourceRoot":"","sources":["../../../src/connectors/capabilities/cookies-chrome.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACnD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAEtE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAEnE,SAAS,iBAAiB;IACxB,MAAM,UAAU,GAAG;QACjB,EAAE,OAAO,EAAE,qBAAqB,EAAE,OAAO,EAAE,QAAQ,EAAE;QACrD,EAAE,OAAO,EAAE,qBAAqB,EAAE,OAAO,EAAE,eAAe,EAAE;QAC5D,EAAE,OAAO,EAAE,4BAA4B,EAAE,OAAO,EAAE,QAAQ,EAAE;QAC5D,EAAE,OAAO,EAAE,4BAA4B,EAAE,OAAO,EAAE,eAAe,EAAE;QACnE,EAAE,OAAO,EAAE,uBAAuB,EAAE,OAAO,EAAE,UAAU,EAAE;QACzD,EAAE,OAAO,EAAE,oBAAoB,EAAE,OAAO,EAAE,OAAO,EAAE;QACnD,EAAE,OAAO,EAAE,4BAA4B,EAAE,OAAO,EAAE,eAAe,EAAE;KACpE,CAAA;IAED,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,YAAY,CAC3B,UAAU,EACV,CAAC,uBAAuB,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,OAAO,CAAC,EACjF,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CACtD,CAAC,IAAI,EAAE,CAAA;YACR,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,UAAU,CAAC,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,CAAC,CAAA;YAC5D,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,mDAAmD;QACrD,CAAC;IACH,CAAC;IAED,MAAM,IAAI,SAAS,CACjB,aAAa,CAAC,oBAAoB,EAClC,yEAAyE,CAC1E,CAAA;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,cAAsB,EAAE,GAAW,EAAE,SAAS,GAAG,CAAC;IACnF,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IAE1C,IAAI,cAAc,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,cAAc,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,cAAc,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC3F,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,CAAA,CAAC,YAAY;QAC9C,MAAM,UAAU,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;QAC7C,MAAM,QAAQ,GAAG,gBAAgB,CAAC,aAAa,EAAE,GAAG,EAAE,EAAE,CAAC,CAAA;QACzD,IAAI,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;QAC3C,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;QAExD,gFAAgF;QAChF,IAAI,SAAS,IAAI,EAAE,IAAI,SAAS,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;YAC7C,SAAS,GAAG,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;QACpC,CAAC;QAED,OAAO,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;IACnC,CAAC;IAED,OAAO,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;AACxC,CAAC;AAED,SAAS,uBAAuB;IAC9B,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAA;IACrB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAA;IACtB,IAAI,EAAE,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,qBAAqB,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAA;IAC5F,IAAI,EAAE,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,eAAe,CAAC,CAAA;IACjE,IAAI,EAAE,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAA;IAC1F,MAAM,IAAI,SAAS,CACjB,aAAa,CAAC,qBAAqB,EACnC,sDAAsD,EAAE,EAAE,CAC3D,CAAA;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,cAAc,CAAC,MAAc,EAAE,GAAW;IACjD,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAU,EAAE,CACxC,YAAY,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE;QAC5C,QAAQ,EAAE,MAAM;QAChB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;QAC/B,OAAO,EAAE,KAAK;KACf,CAAC,CAAC,IAAI,EAAE,CAAA;IAEX,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAA;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,iBAAiB,UAAU,EAAE,KAAK,CAAC,CAAA;QAChE,IAAI,CAAC;YACH,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;YAC3B,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAA;QACxB,CAAC;QAAC,OAAO,EAAW,EAAE,CAAC;YACrB,MAAM,IAAI,SAAS,CACjB,aAAa,CAAC,0BAA0B,EACxC,6CAA6C,MAAM,KAAK,EAAE,YAAY,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,EAC/F,EAAE,CACH,CAAA;QACH,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC;gBAAC,UAAU,CAAC,KAAK,CAAC,CAAA;YAAC,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;QACpC,CAAC;IACH,CAAC;AACH,CAAC;AAeD;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IACxD,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAA;IAEvD,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,IAAI,UAAU,EAAE,CAAC,CAAA;IAC3C,IAAI,GAAG,GAAG,UAAU,CAAA;IACpB,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QAC5B,IAAI,GAAG,GAAG,CAAC;YAAE,MAAK;QAClB,MAAM,MAAM,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,GAAG,CAAC,CAAC,CAAA;QACrC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,MAAK;QAChC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,EAAE,CAAC,CAAA;QACvB,GAAG,GAAG,MAAM,CAAA;IACd,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,SAAS,sBAAsB,CAC7B,MAAc,EACd,IAAY;IAEZ,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,SAAS,CACjB,aAAa,CAAC,qBAAqB,EACnC,yCAAyC,MAAM,EAAE,CAClD,CAAA;IACH,CAAC;IAED,MAAM,IAAI,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAA;IACtC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,CAAA;IAE3D,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACpE,uFAAuF;IACvF,MAAM,GAAG,GAAG,oNAAoN,MAAM,IAAI,CAAA;IAE1O,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAE1C,IAAI,CAAC,MAAM,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,CAAA;IACpE,IAAI,CAAC;QACH,MAAM,IAAI,GAAmD,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;QAC/E,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,UAAU,IAAI,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QACrF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAA;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,CAAA;IACtC,CAAC;AACH,CAAC;AAED,MAAM,oBAAoB,GAAG,WAAW,CAAA;AAExC,SAAS,qBAAqB,CAAC,UAA2B;IACxD,MAAM,GAAG,GAAG,OAAO,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAA;IAClF,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IAClC,OAAO,GAAG,GAAG,SAAS,GAAG,oBAAoB,CAAA;AAC/C,CAAC;AAED,SAAS,aAAa,CAAC,GAAW;IAChC,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAA;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,CAAA;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,2BAA2B;IACzC,OAAO;QACL,KAAK,CAAC,GAAG,CAAC,KAAkB;YAC1B,IAAI,KAAK,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;gBAC/B,MAAM,IAAI,SAAS,CACjB,aAAa,CAAC,qBAAqB,EACnC,wBAAwB,KAAK,CAAC,OAAO,+BAA+B,CACrE,CAAA;YACH,CAAC;YAED,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAA;YACrB,IAAI,EAAE,KAAK,QAAQ,EAAE,CAAC;gBACpB,MAAM,IAAI,SAAS,CACjB,aAAa,CAAC,qBAAqB,EACnC,4EAA4E,EAAE,IAAI,CACnF,CAAA;YACH,CAAC;YAED,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,SAAS,CAAA;YAC1C,MAAM,OAAO,GAAG,uBAAuB,EAAE,CAAA;YACzC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,CAAA;YAChD,MAAM,GAAG,GAAG,iBAAiB,EAAE,CAAA;YAE/B,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;YACrC,MAAM,MAAM,GAAG,sBAAsB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;YAEnD,MAAM,OAAO,GAAa,EAAE,CAAA;YAC5B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACjC,IAAI,KAAa,CAAA;gBACjB,MAAM,MAAM,GAAG,GAAG,CAAC,mBAAmB,CAAA;gBACtC,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAChC,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;oBACtC,MAAM,SAAS,GAAG,kBAAkB,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA;oBAChE,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;gBAC/C,CAAC;qBAAM,CAAC;oBACN,KAAK,GAAG,GAAG,CAAC,KAAK,IAAI,EAAE,CAAA;gBACzB,CAAC;gBAED,OAAO,CAAC,IAAI,CAAC;oBACX,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,KAAK;oBACL,MAAM,EAAE,GAAG,CAAC,QAAQ;oBACpB,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,GAAG;oBACrB,OAAO,EAAE,qBAAqB,CAAC,GAAG,CAAC,WAAW,CAAC;oBAC/C,MAAM,EAAE,GAAG,CAAC,SAAS,KAAK,GAAG,IAAI,GAAG,CAAC,SAAS,KAAK,MAAM;oBACzD,QAAQ,EAAE,GAAG,CAAC,WAAW,KAAK,GAAG,IAAI,GAAG,CAAC,WAAW,KAAK,MAAM;iBAChE,CAAC,CAAA;YACJ,CAAC;YAED,OAAO,OAAO,CAAA;QAChB,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ExecCapability } from '@spool-lab/connector-sdk';
2
+ export declare function makeExecCapability(): ExecCapability;
3
+ //# sourceMappingURL=exec-impl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exec-impl.d.ts","sourceRoot":"","sources":["../../../src/connectors/capabilities/exec-impl.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,0BAA0B,CAAA;AAoC1E,wBAAgB,kBAAkB,IAAI,cAAc,CA6EnD"}
@@ -0,0 +1,108 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { readdirSync } from 'node:fs';
3
+ import { homedir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ const DEFAULT_TIMEOUT = 60_000;
6
+ function buildEnrichedPath() {
7
+ const home = homedir();
8
+ const base = process.env['PATH'] ?? '';
9
+ const nvmBins = [];
10
+ const versionsDir = join(home, '.nvm', 'versions', 'node');
11
+ try {
12
+ for (const d of readdirSync(versionsDir)) {
13
+ if (d.startsWith('v'))
14
+ nvmBins.push(join(versionsDir, d, 'bin'));
15
+ }
16
+ nvmBins.sort().reverse();
17
+ }
18
+ catch { }
19
+ const extras = [
20
+ '/opt/homebrew/bin',
21
+ '/usr/local/bin',
22
+ `${home}/.local/bin`,
23
+ `${home}/.nvm/current/bin`,
24
+ `${home}/.fnm/aliases/default/bin`,
25
+ ...nvmBins,
26
+ ];
27
+ return [...extras, base].join(':');
28
+ }
29
+ /** POSIX single-quote escaping: wraps in '...' and escapes embedded single quotes. */
30
+ function shellQuote(s) {
31
+ return `'${s.replace(/'/g, `'\\''`)}'`;
32
+ }
33
+ let enrichedPath = null;
34
+ export function makeExecCapability() {
35
+ if (!enrichedPath)
36
+ enrichedPath = buildEnrichedPath();
37
+ const isWin = process.platform === 'win32';
38
+ return {
39
+ run(bin, args, opts) {
40
+ const timeout = opts?.timeout ?? DEFAULT_TIMEOUT;
41
+ return new Promise((resolve, reject) => {
42
+ // GUI-launched apps on macOS don't inherit the user's shell env (no
43
+ // proxy vars, no nvm PATH, etc.) — running through a login shell
44
+ // sources .zprofile / .bash_profile so subprocesses get a realistic
45
+ // env. zsh additionally needs -i to source .zshrc where most users
46
+ // keep proxy/PATH tweaks; bash -i emits "cannot set terminal process
47
+ // group" warnings in non-TTY contexts (eg. CI) so we stick to plain
48
+ // -lc for bash and rely on .bash_profile to source .bashrc as is
49
+ // standard. On Windows there is no equivalent concept, spawn direct.
50
+ const shellPath = process.env['SHELL'] || '/bin/zsh';
51
+ const useInteractive = /\bzsh$/.test(shellPath);
52
+ const proc = isWin
53
+ ? spawn(bin, args, {
54
+ stdio: ['pipe', 'pipe', 'pipe'],
55
+ env: { ...process.env, PATH: enrichedPath },
56
+ })
57
+ : spawn(shellPath, [useInteractive ? '-ilc' : '-lc', [bin, ...args].map(shellQuote).join(' ')], {
58
+ stdio: ['pipe', 'pipe', 'pipe'],
59
+ env: { ...process.env, PATH: enrichedPath },
60
+ // Run in own process group so timeout kills the inner command
61
+ // too, not just the shell wrapper.
62
+ detached: true,
63
+ });
64
+ let stdout = '';
65
+ let stderr = '';
66
+ let timedOut = false;
67
+ const killGroup = () => {
68
+ if (!isWin && proc.pid) {
69
+ // Kill the whole process group so the shell wrapper AND the
70
+ // inner command both terminate. Without this, killing only the
71
+ // shell leaves the inner command orphaned and stdio pipes open.
72
+ try {
73
+ process.kill(-proc.pid, 'SIGKILL');
74
+ }
75
+ catch {
76
+ proc.kill('SIGKILL');
77
+ }
78
+ }
79
+ else {
80
+ proc.kill();
81
+ }
82
+ };
83
+ const timer = setTimeout(() => {
84
+ timedOut = true;
85
+ killGroup();
86
+ // Resolve immediately rather than waiting for stdio drain — the
87
+ // 'close' handler may not fire promptly when the process group is
88
+ // killed because orphaned descendants can keep pipes open.
89
+ reject(new Error(`Process timed out after ${timeout}ms`));
90
+ }, timeout);
91
+ proc.stdout.on('data', (d) => { stdout += d.toString(); });
92
+ proc.stderr.on('data', (d) => { stderr += d.toString(); });
93
+ proc.on('close', () => {
94
+ clearTimeout(timer);
95
+ if (!timedOut) {
96
+ resolve({ stdout, stderr, exitCode: proc.exitCode ?? 1 });
97
+ }
98
+ });
99
+ proc.on('error', (err) => {
100
+ clearTimeout(timer);
101
+ if (!timedOut)
102
+ reject(err);
103
+ });
104
+ });
105
+ },
106
+ };
107
+ }
108
+ //# sourceMappingURL=exec-impl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exec-impl.js","sourceRoot":"","sources":["../../../src/connectors/capabilities/exec-impl.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { FetchCapability } from '@spool-lab/connector-sdk';
2
+ export declare function makeFetchCapability(fetchFn?: typeof globalThis.fetch): FetchCapability;
3
+ //# sourceMappingURL=fetch-impl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-impl.d.ts","sourceRoot":"","sources":["../../../src/connectors/capabilities/fetch-impl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAE/D,wBAAgB,mBAAmB,CACjC,OAAO,GAAE,OAAO,UAAU,CAAC,KAAwB,GAClD,eAAe,CAEjB"}
@@ -0,0 +1,4 @@
1
+ export function makeFetchCapability(fetchFn = globalThis.fetch) {
2
+ return fetchFn;
3
+ }
4
+ //# sourceMappingURL=fetch-impl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-impl.js","sourceRoot":"","sources":["../../../src/connectors/capabilities/fetch-impl.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,mBAAmB,CACjC,UAAmC,UAAU,CAAC,KAAK;IAEnD,OAAO,OAAO,CAAA;AAChB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { makeFetchCapability } from './fetch-impl.js';
2
+ export { makeChromeCookiesCapability } from './cookies-chrome.js';
3
+ export { makeLogCapabilityFor } from './log-impl.js';
4
+ export { makeSqliteCapability } from './sqlite-impl.js';
5
+ export { makeExecCapability } from './exec-impl.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/connectors/capabilities/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AACrD,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAA;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA"}
@@ -0,0 +1,6 @@
1
+ export { makeFetchCapability } from './fetch-impl.js';
2
+ export { makeChromeCookiesCapability } from './cookies-chrome.js';
3
+ export { makeLogCapabilityFor } from './log-impl.js';
4
+ export { makeSqliteCapability } from './sqlite-impl.js';
5
+ export { makeExecCapability } from './exec-impl.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/connectors/capabilities/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AACrD,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAA;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA"}
@@ -0,0 +1,3 @@
1
+ import type { LogCapability } from '@spool-lab/connector-sdk';
2
+ export declare function makeLogCapabilityFor(connectorId: string): LogCapability;
3
+ //# sourceMappingURL=log-impl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-impl.d.ts","sourceRoot":"","sources":["../../../src/connectors/capabilities/log-impl.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAa,MAAM,0BAA0B,CAAA;AAExE,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,CAuCvE"}
@@ -0,0 +1,26 @@
1
+ import { Effect } from 'effect';
2
+ export function makeLogCapabilityFor(connectorId) {
3
+ const baseAttrs = { 'connector.id': connectorId };
4
+ const emit = (level, msg, fields) => {
5
+ const attrs = { ...baseAttrs, ...fields };
6
+ const effect = level === 'Debug' ? Effect.logDebug(msg) :
7
+ level === 'Info' ? Effect.logInfo(msg) :
8
+ level === 'Warning' ? Effect.logWarning(msg) :
9
+ Effect.logError(msg);
10
+ Effect.runFork(effect.pipe(Effect.annotateLogs(attrs)));
11
+ };
12
+ return {
13
+ debug(msg, fields) { emit('Debug', msg, fields); },
14
+ info(msg, fields) { emit('Info', msg, fields); },
15
+ warn(msg, fields) { emit('Warning', msg, fields); },
16
+ error(msg, fields) { emit('Error', msg, fields); },
17
+ async span(name, fn, opts) {
18
+ const attrs = { ...baseAttrs, ...opts?.attributes };
19
+ return Effect.runPromise(Effect.tryPromise({
20
+ try: fn,
21
+ catch: e => e,
22
+ }).pipe(Effect.withSpan(`connector.${name}`, { attributes: attrs })));
23
+ },
24
+ };
25
+ }
26
+ //# sourceMappingURL=log-impl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-impl.js","sourceRoot":"","sources":["../../../src/connectors/capabilities/log-impl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAG/B,MAAM,UAAU,oBAAoB,CAAC,WAAmB;IACtD,MAAM,SAAS,GAAc,EAAE,cAAc,EAAE,WAAW,EAAE,CAAA;IAE5D,MAAM,IAAI,GAAG,CACX,KAA6C,EAC7C,GAAW,EACX,MAAkB,EAClB,EAAE;QACF,MAAM,KAAK,GAAG,EAAE,GAAG,SAAS,EAAE,GAAG,MAAM,EAAE,CAAA;QACzC,MAAM,MAAM,GACV,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;YAC1C,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;gBACxC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;oBAC9C,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;QACtB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IACzD,CAAC,CAAA;IAED,OAAO;QACL,KAAK,CAAC,GAAG,EAAE,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA,CAAC,CAAC;QACjD,IAAI,CAAC,GAAG,EAAE,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA,CAAC,CAAC;QAC/C,IAAI,CAAC,GAAG,EAAE,MAAM,IAAI,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA,CAAC,CAAC;QAClD,KAAK,CAAC,GAAG,EAAE,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA,CAAC,CAAC;QAEjD,KAAK,CAAC,IAAI,CACR,IAAY,EACZ,EAAoB,EACpB,IAAiC;YAEjC,MAAM,KAAK,GAAG,EAAE,GAAG,SAAS,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,CAAA;YACnD,OAAO,MAAM,CAAC,UAAU,CACtB,MAAM,CAAC,UAAU,CAAC;gBAChB,GAAG,EAAE,EAAE;gBACP,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;aACd,CAAC,CAAC,IAAI,CACL,MAAM,CAAC,QAAQ,CAAC,aAAa,IAAI,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAC5D,CACF,CAAA;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { SqliteCapability } from '@spool-lab/connector-sdk';
2
+ export declare function makeSqliteCapability(): SqliteCapability;
3
+ //# sourceMappingURL=sqlite-impl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-impl.d.ts","sourceRoot":"","sources":["../../../src/connectors/capabilities/sqlite-impl.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAmC,MAAM,0BAA0B,CAAA;AAEjG,wBAAgB,oBAAoB,IAAI,gBAAgB,CAgBvD"}
@@ -0,0 +1,19 @@
1
+ import Database from 'better-sqlite3';
2
+ export function makeSqliteCapability() {
3
+ return {
4
+ openReadonly(path) {
5
+ const db = new Database(path, { readonly: true, fileMustExist: true });
6
+ return {
7
+ prepare(sql) {
8
+ const stmt = db.prepare(sql);
9
+ return {
10
+ all: (...params) => stmt.all(...params),
11
+ get: (...params) => stmt.get(...params),
12
+ };
13
+ },
14
+ close: () => { db.close(); },
15
+ };
16
+ },
17
+ };
18
+ }
19
+ //# sourceMappingURL=sqlite-impl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-impl.js","sourceRoot":"","sources":["../../../src/connectors/capabilities/sqlite-impl.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAA;AAGrC,MAAM,UAAU,oBAAoB;IAClC,OAAO;QACL,YAAY,CAAC,IAAY;YACvB,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAA;YACtE,OAAO;gBACL,OAAO,CAAc,GAAW;oBAC9B,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;oBAC5B,OAAO;wBACL,GAAG,EAAE,CAAC,GAAG,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAQ;wBAC9C,GAAG,EAAE,CAAC,GAAG,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAkB;qBACzD,CAAA;gBACH,CAAC;gBACD,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,CAAA,CAAC,CAAC;aAC5B,CAAA;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,47 @@
1
+ import type { CookiesCapability, ExecCapability, FetchCapability, LogCapability, Prerequisite, PrerequisitesCapability, SqliteCapability } from '@spool-lab/connector-sdk';
2
+ import type { ConnectorRegistry } from './registry.js';
3
+ interface BaseLogger {
4
+ info(msg: string, fields?: Record<string, unknown>): void;
5
+ warn(msg: string, fields?: Record<string, unknown>): void;
6
+ error(msg: string, fields?: Record<string, unknown>): void;
7
+ }
8
+ import { TrustStore } from './trust-store.js';
9
+ export declare function validatePrerequisites(prereqs: unknown[], packageName: string): Prerequisite[];
10
+ export interface CapabilityImpls {
11
+ fetch: FetchCapability;
12
+ cookies: CookiesCapability;
13
+ sqlite: SqliteCapability;
14
+ exec: ExecCapability;
15
+ logFor(connectorId: string): LogCapability;
16
+ /** Returns the prerequisites capability for the given package id, or undefined if not supported. */
17
+ prerequisitesFor?: (packageId: string) => PrerequisitesCapability;
18
+ }
19
+ export interface LoaderLogger extends BaseLogger {
20
+ child?(attrs: Record<string, unknown>): LoaderLogger;
21
+ }
22
+ export interface LoadDeps {
23
+ connectorsDir: string;
24
+ capabilityImpls: CapabilityImpls;
25
+ registry: ConnectorRegistry;
26
+ log: LoaderLogger;
27
+ trustStore: TrustStore;
28
+ }
29
+ export type LoadResult = {
30
+ status: 'loaded';
31
+ name: string;
32
+ version: string;
33
+ } | {
34
+ status: 'failed';
35
+ name: string;
36
+ error: unknown;
37
+ } | {
38
+ status: 'skipped';
39
+ name: string;
40
+ reason: 'not-in-allowlist' | 'bad-manifest';
41
+ };
42
+ export interface LoadReport {
43
+ loadResults: LoadResult[];
44
+ }
45
+ export declare function loadConnectors(deps: LoadDeps): Promise<LoadReport>;
46
+ export {};
47
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/connectors/loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAGV,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,aAAa,EACb,YAAY,EACZ,uBAAuB,EACvB,gBAAgB,EACjB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACtD,UAAU,UAAU;IAClB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IACzD,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IACzD,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;CAC3D;AACD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,YAAY,EAAE,CAgC7F;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,eAAe,CAAA;IACtB,OAAO,EAAE,iBAAiB,CAAA;IAC1B,MAAM,EAAE,gBAAgB,CAAA;IACxB,IAAI,EAAE,cAAc,CAAA;IACpB,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,CAAA;IAC1C,oGAAoG;IACpG,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,uBAAuB,CAAA;CAClE;AAED,MAAM,WAAW,YAAa,SAAQ,UAAU;IAC9C,KAAK,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,YAAY,CAAA;CACrD;AAED,MAAM,WAAW,QAAQ;IACvB,aAAa,EAAE,MAAM,CAAA;IACrB,eAAe,EAAE,eAAe,CAAA;IAChC,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,GAAG,EAAE,YAAY,CAAA;IACjB,UAAU,EAAE,UAAU,CAAA;CACvB;AAED,MAAM,MAAM,UAAU,GAClB;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAClD;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,kBAAkB,GAAG,cAAc,CAAA;CAAE,CAAA;AAEpF,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,UAAU,EAAE,CAAA;CAC1B;AAwBD,wBAAsB,cAAc,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAexE"}