spudmobile-bridge 1.0.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/appicon.png +0 -0
- package/dist/autostart.d.ts +3 -0
- package/dist/autostart.js +234 -0
- package/dist/codex.d.ts +32 -0
- package/dist/codex.js +106 -0
- package/dist/config.d.ts +25 -0
- package/dist/config.js +48 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +263 -0
- package/dist/pairing.d.ts +14 -0
- package/dist/pairing.js +137 -0
- package/dist/supabase.d.ts +96 -0
- package/dist/supabase.js +362 -0
- package/package.json +43 -0
package/appicon.png
ADDED
|
Binary file
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import { writeFileSync, unlinkSync, existsSync, mkdirSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { platform, homedir } from 'os';
|
|
5
|
+
const SERVICE_NAME = 'com.spudmobile-bridge';
|
|
6
|
+
const LABEL = 'SpudMobile Bridge';
|
|
7
|
+
/**
|
|
8
|
+
* Get the path to the globally installed bridge binary
|
|
9
|
+
*/
|
|
10
|
+
function getBridgePath() {
|
|
11
|
+
try {
|
|
12
|
+
// Try to find the global install
|
|
13
|
+
const globalBin = execSync('which spudmobile-bridge', { encoding: 'utf-8' }).trim();
|
|
14
|
+
if (globalBin)
|
|
15
|
+
return globalBin;
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
// not found
|
|
19
|
+
}
|
|
20
|
+
// Fallback: use npx
|
|
21
|
+
try {
|
|
22
|
+
const npxPath = execSync('which npx', { encoding: 'utf-8' }).trim();
|
|
23
|
+
return `${npxPath} spudmobile-bridge`;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
throw new Error('Neither spudmobile-bridge nor npx found in PATH');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Get the full PATH from current shell (needed for LaunchAgent)
|
|
31
|
+
*/
|
|
32
|
+
function getShellPath() {
|
|
33
|
+
try {
|
|
34
|
+
return execSync('echo $PATH', { encoding: 'utf-8', shell: '/bin/zsh' }).trim();
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return '/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin';
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// ─── macOS LaunchAgent ────────────────────────────────────
|
|
41
|
+
function getMacPlistPath() {
|
|
42
|
+
return join(homedir(), 'Library', 'LaunchAgents', `${SERVICE_NAME}.plist`);
|
|
43
|
+
}
|
|
44
|
+
function installMac(projectPath) {
|
|
45
|
+
const shellPath = getShellPath();
|
|
46
|
+
const logDir = join(homedir(), '.spudmobile-bridge');
|
|
47
|
+
try {
|
|
48
|
+
if (!existsSync(logDir)) {
|
|
49
|
+
mkdirSync(logDir, { recursive: true });
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// Directory might already exist or be created by another process
|
|
54
|
+
}
|
|
55
|
+
// Always use npx with @latest to ensure the latest version runs
|
|
56
|
+
let npxPath;
|
|
57
|
+
try {
|
|
58
|
+
npxPath = execSync('which npx', { encoding: 'utf-8', shell: '/bin/zsh' }).trim();
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
npxPath = '/usr/local/bin/npx';
|
|
62
|
+
}
|
|
63
|
+
let programArgs = ` <string>${npxPath}</string>\n <string>-y</string>\n <string>spudmobile-bridge@latest</string>`;
|
|
64
|
+
if (projectPath) {
|
|
65
|
+
programArgs += `\n <string>--path</string>\n <string>${projectPath}</string>`;
|
|
66
|
+
}
|
|
67
|
+
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
68
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
69
|
+
<plist version="1.0">
|
|
70
|
+
<dict>
|
|
71
|
+
<key>Label</key>
|
|
72
|
+
<string>${SERVICE_NAME}</string>
|
|
73
|
+
<key>ProgramArguments</key>
|
|
74
|
+
<array>
|
|
75
|
+
${programArgs}
|
|
76
|
+
</array>
|
|
77
|
+
<key>RunAtLoad</key>
|
|
78
|
+
<true/>
|
|
79
|
+
<key>KeepAlive</key>
|
|
80
|
+
<true/>
|
|
81
|
+
<key>EnvironmentVariables</key>
|
|
82
|
+
<dict>
|
|
83
|
+
<key>PATH</key>
|
|
84
|
+
<string>${shellPath}</string>
|
|
85
|
+
<key>HOME</key>
|
|
86
|
+
<string>${homedir()}</string>
|
|
87
|
+
</dict>
|
|
88
|
+
<key>StandardOutPath</key>
|
|
89
|
+
<string>${logDir}/bridge.log</string>
|
|
90
|
+
<key>StandardErrorPath</key>
|
|
91
|
+
<string>${logDir}/bridge-error.log</string>
|
|
92
|
+
<key>WorkingDirectory</key>
|
|
93
|
+
<string>${projectPath || homedir()}</string>
|
|
94
|
+
</dict>
|
|
95
|
+
</plist>`;
|
|
96
|
+
const plistPath = getMacPlistPath();
|
|
97
|
+
writeFileSync(plistPath, plist);
|
|
98
|
+
// Load the agent
|
|
99
|
+
try {
|
|
100
|
+
execSync(`launchctl unload "${plistPath}" 2>/dev/null`, { stdio: 'ignore' });
|
|
101
|
+
}
|
|
102
|
+
catch { /* ignore */ }
|
|
103
|
+
execSync(`launchctl load "${plistPath}"`);
|
|
104
|
+
console.log('✅ Auto-launch installed (macOS LaunchAgent)');
|
|
105
|
+
console.log(` Plist: ${plistPath}`);
|
|
106
|
+
console.log(` Logs: ${logDir}/bridge.log`);
|
|
107
|
+
console.log(' Bridge will start automatically on login.');
|
|
108
|
+
}
|
|
109
|
+
function uninstallMac() {
|
|
110
|
+
const plistPath = getMacPlistPath();
|
|
111
|
+
if (!existsSync(plistPath)) {
|
|
112
|
+
console.log('ℹ️ Auto-launch is not installed.');
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
try {
|
|
116
|
+
execSync(`launchctl unload "${plistPath}"`, { stdio: 'ignore' });
|
|
117
|
+
}
|
|
118
|
+
catch { /* ignore */ }
|
|
119
|
+
unlinkSync(plistPath);
|
|
120
|
+
console.log('✅ Auto-launch removed (macOS LaunchAgent)');
|
|
121
|
+
}
|
|
122
|
+
// ─── Linux systemd ───────────────────────────────────────
|
|
123
|
+
function getLinuxServicePath() {
|
|
124
|
+
const dir = join(homedir(), '.config', 'systemd', 'user');
|
|
125
|
+
if (!existsSync(dir)) {
|
|
126
|
+
mkdirSync(dir, { recursive: true });
|
|
127
|
+
}
|
|
128
|
+
return join(dir, 'spudmobile-bridge.service');
|
|
129
|
+
}
|
|
130
|
+
function installLinux(projectPath) {
|
|
131
|
+
const bridgePath = getBridgePath();
|
|
132
|
+
const shellPath = getShellPath();
|
|
133
|
+
const logDir = join(homedir(), '.spudmobile-bridge');
|
|
134
|
+
try {
|
|
135
|
+
if (!existsSync(logDir)) {
|
|
136
|
+
mkdirSync(logDir, { recursive: true });
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
// ignore
|
|
141
|
+
}
|
|
142
|
+
let execStart = bridgePath;
|
|
143
|
+
if (projectPath) {
|
|
144
|
+
execStart += ` --path "${projectPath}"`;
|
|
145
|
+
}
|
|
146
|
+
const service = `[Unit]
|
|
147
|
+
Description=${LABEL}
|
|
148
|
+
After=network-online.target
|
|
149
|
+
Wants=network-online.target
|
|
150
|
+
|
|
151
|
+
[Service]
|
|
152
|
+
Type=simple
|
|
153
|
+
ExecStart=${execStart}
|
|
154
|
+
Restart=on-failure
|
|
155
|
+
RestartSec=10
|
|
156
|
+
Environment=PATH=${shellPath}
|
|
157
|
+
Environment=HOME=${homedir()}
|
|
158
|
+
WorkingDirectory=${projectPath || homedir()}
|
|
159
|
+
|
|
160
|
+
[Install]
|
|
161
|
+
WantedBy=default.target
|
|
162
|
+
`;
|
|
163
|
+
const servicePath = getLinuxServicePath();
|
|
164
|
+
writeFileSync(servicePath, service);
|
|
165
|
+
// Enable and start
|
|
166
|
+
try {
|
|
167
|
+
execSync('systemctl --user daemon-reload');
|
|
168
|
+
execSync('systemctl --user enable spudmobile-bridge');
|
|
169
|
+
execSync('systemctl --user start spudmobile-bridge');
|
|
170
|
+
}
|
|
171
|
+
catch (err) {
|
|
172
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
173
|
+
console.log(`⚠️ Could not start service: ${msg}`);
|
|
174
|
+
console.log(' Try manually: systemctl --user start spudmobile-bridge');
|
|
175
|
+
}
|
|
176
|
+
console.log('✅ Auto-launch installed (systemd user service)');
|
|
177
|
+
console.log(` Service: ${servicePath}`);
|
|
178
|
+
console.log(' Bridge will start automatically on login.');
|
|
179
|
+
console.log(' Status: systemctl --user status spudmobile-bridge');
|
|
180
|
+
}
|
|
181
|
+
function uninstallLinux() {
|
|
182
|
+
const servicePath = getLinuxServicePath();
|
|
183
|
+
if (!existsSync(servicePath)) {
|
|
184
|
+
console.log('ℹ️ Auto-launch is not installed.');
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
try {
|
|
188
|
+
execSync('systemctl --user stop spudmobile-bridge', { stdio: 'ignore' });
|
|
189
|
+
execSync('systemctl --user disable spudmobile-bridge', { stdio: 'ignore' });
|
|
190
|
+
}
|
|
191
|
+
catch { /* ignore */ }
|
|
192
|
+
unlinkSync(servicePath);
|
|
193
|
+
try {
|
|
194
|
+
execSync('systemctl --user daemon-reload');
|
|
195
|
+
}
|
|
196
|
+
catch { /* ignore */ }
|
|
197
|
+
console.log('✅ Auto-launch removed (systemd user service)');
|
|
198
|
+
}
|
|
199
|
+
// ─── Public API ──────────────────────────────────────────
|
|
200
|
+
export function installAutostart(projectPath) {
|
|
201
|
+
const os = platform();
|
|
202
|
+
if (os === 'darwin') {
|
|
203
|
+
installMac(projectPath);
|
|
204
|
+
}
|
|
205
|
+
else if (os === 'linux') {
|
|
206
|
+
installLinux(projectPath);
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
console.log(`❌ Auto-launch is not supported on ${os}`);
|
|
210
|
+
console.log(' Supported: macOS (LaunchAgent), Linux (systemd)');
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
export function uninstallAutostart() {
|
|
214
|
+
const os = platform();
|
|
215
|
+
if (os === 'darwin') {
|
|
216
|
+
uninstallMac();
|
|
217
|
+
}
|
|
218
|
+
else if (os === 'linux') {
|
|
219
|
+
uninstallLinux();
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
console.log(`❌ Auto-launch is not supported on ${os}`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
export function isAutostartInstalled() {
|
|
226
|
+
const os = platform();
|
|
227
|
+
if (os === 'darwin') {
|
|
228
|
+
return existsSync(getMacPlistPath());
|
|
229
|
+
}
|
|
230
|
+
else if (os === 'linux') {
|
|
231
|
+
return existsSync(getLinuxServicePath());
|
|
232
|
+
}
|
|
233
|
+
return false;
|
|
234
|
+
}
|
package/dist/codex.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ChildProcess } from 'child_process';
|
|
2
|
+
/**
|
|
3
|
+
* Find the Codex CLI binary path
|
|
4
|
+
*/
|
|
5
|
+
export declare function findCodexCLI(): string | null;
|
|
6
|
+
export interface CodexOptions {
|
|
7
|
+
model?: string;
|
|
8
|
+
cwd?: string;
|
|
9
|
+
continueSession?: boolean;
|
|
10
|
+
timeout?: number;
|
|
11
|
+
}
|
|
12
|
+
export interface CodexResult {
|
|
13
|
+
output: string;
|
|
14
|
+
exitCode: number;
|
|
15
|
+
killed: boolean;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Run Codex CLI in non-interactive (exec) mode with streaming output
|
|
19
|
+
*
|
|
20
|
+
* Uses `codex exec "prompt"` for one-shot execution
|
|
21
|
+
* Uses `codex exec resume --last "prompt"` to continue the last session
|
|
22
|
+
*
|
|
23
|
+
* @param prompt The prompt to send
|
|
24
|
+
* @param cliPath Path to codex binary
|
|
25
|
+
* @param options Additional options
|
|
26
|
+
* @param onChunk Called with each chunk of stdout for streaming
|
|
27
|
+
* @returns Full result when completed
|
|
28
|
+
*/
|
|
29
|
+
export declare function runCodex(prompt: string, cliPath: string, options?: CodexOptions, onChunk?: (chunk: string, fullOutput: string) => void): {
|
|
30
|
+
process: ChildProcess;
|
|
31
|
+
result: Promise<CodexResult>;
|
|
32
|
+
};
|
package/dist/codex.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { spawn, execSync } from 'child_process';
|
|
2
|
+
/**
|
|
3
|
+
* Find the Codex CLI binary path
|
|
4
|
+
*/
|
|
5
|
+
export function findCodexCLI() {
|
|
6
|
+
// Try `which` first
|
|
7
|
+
try {
|
|
8
|
+
const result = execSync('which codex', { encoding: 'utf-8' }).trim();
|
|
9
|
+
if (result)
|
|
10
|
+
return result;
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
// not in PATH
|
|
14
|
+
}
|
|
15
|
+
const commonPaths = [
|
|
16
|
+
'/usr/local/bin/codex',
|
|
17
|
+
'/opt/homebrew/bin/codex',
|
|
18
|
+
`${process.env.HOME}/.local/bin/codex`,
|
|
19
|
+
`${process.env.HOME}/.npm-global/bin/codex`,
|
|
20
|
+
];
|
|
21
|
+
for (const p of commonPaths) {
|
|
22
|
+
try {
|
|
23
|
+
execSync(`test -x "${p}"`, { stdio: 'ignore' });
|
|
24
|
+
return p;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// not found
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Run Codex CLI in non-interactive (exec) mode with streaming output
|
|
34
|
+
*
|
|
35
|
+
* Uses `codex exec "prompt"` for one-shot execution
|
|
36
|
+
* Uses `codex exec resume --last "prompt"` to continue the last session
|
|
37
|
+
*
|
|
38
|
+
* @param prompt The prompt to send
|
|
39
|
+
* @param cliPath Path to codex binary
|
|
40
|
+
* @param options Additional options
|
|
41
|
+
* @param onChunk Called with each chunk of stdout for streaming
|
|
42
|
+
* @returns Full result when completed
|
|
43
|
+
*/
|
|
44
|
+
export function runCodex(prompt, cliPath, options = {}, onChunk) {
|
|
45
|
+
const args = [];
|
|
46
|
+
if (options.continueSession) {
|
|
47
|
+
// Resume the last session: codex exec resume --last "prompt"
|
|
48
|
+
args.push('exec', 'resume', '--last', prompt);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
// One-shot: codex exec "prompt"
|
|
52
|
+
args.push('exec', prompt);
|
|
53
|
+
}
|
|
54
|
+
if (options.model) {
|
|
55
|
+
args.push('--model', options.model);
|
|
56
|
+
}
|
|
57
|
+
// Full auto approval mode — no interactive prompts
|
|
58
|
+
args.push('--full-auto');
|
|
59
|
+
const timeout = options.timeout || 10 * 60 * 1000; // 10 min default
|
|
60
|
+
const proc = spawn(cliPath, args, {
|
|
61
|
+
cwd: options.cwd || process.cwd(),
|
|
62
|
+
env: { ...process.env },
|
|
63
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
64
|
+
});
|
|
65
|
+
// Close stdin immediately — exec mode doesn't need it
|
|
66
|
+
if (proc.stdin) {
|
|
67
|
+
proc.stdin.end();
|
|
68
|
+
}
|
|
69
|
+
const result = new Promise((resolve) => {
|
|
70
|
+
let output = '';
|
|
71
|
+
let stderr = '';
|
|
72
|
+
let killed = false;
|
|
73
|
+
const timer = setTimeout(() => {
|
|
74
|
+
killed = true;
|
|
75
|
+
proc.kill('SIGTERM');
|
|
76
|
+
}, timeout);
|
|
77
|
+
proc.stdout?.on('data', (data) => {
|
|
78
|
+
const chunk = data.toString('utf-8');
|
|
79
|
+
output += chunk;
|
|
80
|
+
onChunk?.(chunk, output);
|
|
81
|
+
});
|
|
82
|
+
proc.stderr?.on('data', (data) => {
|
|
83
|
+
stderr += data.toString('utf-8');
|
|
84
|
+
});
|
|
85
|
+
proc.on('close', (code) => {
|
|
86
|
+
clearTimeout(timer);
|
|
87
|
+
if (stderr && !output) {
|
|
88
|
+
output = `⚠️ Codex CLI Error:\n${stderr}`;
|
|
89
|
+
}
|
|
90
|
+
resolve({
|
|
91
|
+
output: output || '(empty response)',
|
|
92
|
+
exitCode: code ?? 1,
|
|
93
|
+
killed,
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
proc.on('error', (err) => {
|
|
97
|
+
clearTimeout(timer);
|
|
98
|
+
resolve({
|
|
99
|
+
output: `⚠️ Failed to start Codex CLI: ${err.message}`,
|
|
100
|
+
exitCode: 1,
|
|
101
|
+
killed: false,
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
return { process: proc, result };
|
|
106
|
+
}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface BridgeConfig {
|
|
2
|
+
supabaseUrl: string;
|
|
3
|
+
supabaseAnonKey: string;
|
|
4
|
+
pairId: string | null;
|
|
5
|
+
pairCode: string | null;
|
|
6
|
+
projectPath: string | null;
|
|
7
|
+
port: number;
|
|
8
|
+
}
|
|
9
|
+
interface SavedConfig {
|
|
10
|
+
pairId?: string;
|
|
11
|
+
pairCode?: string;
|
|
12
|
+
projectPath?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Save config to ~/.claude-mobile/config.json
|
|
16
|
+
*/
|
|
17
|
+
export declare function saveConfig(updates: Partial<SavedConfig>): void;
|
|
18
|
+
/**
|
|
19
|
+
* Build the full BridgeConfig from env + saved config + CLI args
|
|
20
|
+
*/
|
|
21
|
+
export declare function getConfig(options: {
|
|
22
|
+
path?: string;
|
|
23
|
+
port?: number;
|
|
24
|
+
}): BridgeConfig;
|
|
25
|
+
export {};
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
2
|
+
import { homedir } from 'os';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
// Config file location: ~/.claude-mobile/config.json
|
|
5
|
+
const CONFIG_DIR = join(homedir(), '.spudmobile');
|
|
6
|
+
const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
|
|
7
|
+
/**
|
|
8
|
+
* Load saved config from ~/.claude-mobile/config.json
|
|
9
|
+
*/
|
|
10
|
+
function loadSavedConfig() {
|
|
11
|
+
try {
|
|
12
|
+
if (existsSync(CONFIG_FILE)) {
|
|
13
|
+
const data = readFileSync(CONFIG_FILE, 'utf-8');
|
|
14
|
+
return JSON.parse(data);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
// ignore
|
|
19
|
+
}
|
|
20
|
+
return {};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Save config to ~/.claude-mobile/config.json
|
|
24
|
+
*/
|
|
25
|
+
export function saveConfig(updates) {
|
|
26
|
+
const current = loadSavedConfig();
|
|
27
|
+
const merged = { ...current, ...updates };
|
|
28
|
+
if (!existsSync(CONFIG_DIR)) {
|
|
29
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
30
|
+
}
|
|
31
|
+
writeFileSync(CONFIG_FILE, JSON.stringify(merged, null, 2), 'utf-8');
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Build the full BridgeConfig from env + saved config + CLI args
|
|
35
|
+
*/
|
|
36
|
+
export function getConfig(options) {
|
|
37
|
+
const saved = loadSavedConfig();
|
|
38
|
+
const supabaseUrl = process.env.SUPABASE_URL || 'https://dtaegtkfdwgdbyolcxht.supabase.co';
|
|
39
|
+
const supabaseAnonKey = process.env.SUPABASE_ANON_KEY || 'sb_publishable__giFEuM62kLTFecXfufGIw_a-Dv9y6O';
|
|
40
|
+
return {
|
|
41
|
+
supabaseUrl,
|
|
42
|
+
supabaseAnonKey,
|
|
43
|
+
pairId: saved.pairId || null,
|
|
44
|
+
pairCode: saved.pairCode || null,
|
|
45
|
+
projectPath: options.path || process.cwd(),
|
|
46
|
+
port: options.port || 38473,
|
|
47
|
+
};
|
|
48
|
+
}
|
package/dist/index.d.ts
ADDED