@lovelybunch/api 1.0.24 → 1.0.27

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.
@@ -1,25 +1,13 @@
1
1
  /**
2
- * Get the base path for .gait directory based on environment
3
- *
4
- * Priority order:
5
- * 1. Explicit basePath parameter
6
- * 2. Dev mode: GAIT_DEV_ROOT environment variable
7
- * 3. Production mode: GAIT_DATA_PATH environment variable
8
- * 4. Fallback: current working directory
2
+ * Find the .gait directory by traversing up from the current working directory
3
+ * If GAIT_DATA_PATH is set (from CLI), use that instead
9
4
  */
10
- export declare function getGaitBasePath(basePath?: string): string;
5
+ export declare function findGaitDirectory(startDir?: string): Promise<string | null>;
11
6
  /**
12
- * Get the full path to a specific .gait subdirectory
7
+ * Get the path to a context file, automatically finding the .gait directory
13
8
  */
14
- export declare function getGaitPath(subdirectory: string, basePath?: string): string;
9
+ export declare function getContextFilePath(fileName: string): Promise<string | null>;
15
10
  /**
16
- * Common .gait subdirectories
11
+ * Get the .gait config to read storage path settings
17
12
  */
18
- export declare const GAIT_PATHS: {
19
- readonly proposals: () => string;
20
- readonly context: () => string;
21
- readonly agents: () => string;
22
- readonly resources: () => string;
23
- readonly chats: () => string;
24
- readonly config: () => string;
25
- };
13
+ export declare function getGaitConfig(): Promise<any | null>;
@@ -1,45 +1,57 @@
1
+ import { promises as fs } from 'fs';
1
2
  import path from 'path';
2
3
  /**
3
- * Get the base path for .gait directory based on environment
4
- *
5
- * Priority order:
6
- * 1. Explicit basePath parameter
7
- * 2. Dev mode: GAIT_DEV_ROOT environment variable
8
- * 3. Production mode: GAIT_DATA_PATH environment variable
9
- * 4. Fallback: current working directory
4
+ * Find the .gait directory by traversing up from the current working directory
5
+ * If GAIT_DATA_PATH is set (from CLI), use that instead
10
6
  */
11
- export function getGaitBasePath(basePath) {
12
- if (basePath) {
13
- return basePath;
7
+ export async function findGaitDirectory(startDir) {
8
+ // If running from CLI (gait serve), use the directory where command was run
9
+ if (process.env.GAIT_DATA_PATH) {
10
+ const gaitPath = path.join(process.env.GAIT_DATA_PATH, '.gait');
11
+ try {
12
+ await fs.access(gaitPath);
13
+ return gaitPath;
14
+ }
15
+ catch {
16
+ // Fall through to directory traversal
17
+ }
14
18
  }
15
- if (process.env.NODE_ENV === 'development' && process.env.GAIT_DEV_ROOT) {
16
- // Dev mode: use project root .gait directory
17
- return process.env.GAIT_DEV_ROOT;
18
- }
19
- else if (process.env.GAIT_DATA_PATH) {
20
- // Production mode: use GAIT_DATA_PATH (set by CLI)
21
- return path.resolve(process.env.GAIT_DATA_PATH, '.gait');
22
- }
23
- else {
24
- // Fallback: use current directory .gait
25
- return path.resolve(process.cwd(), '.gait');
19
+ // Otherwise traverse up from start directory
20
+ let currentDir = startDir || process.cwd();
21
+ while (currentDir !== path.parse(currentDir).root) {
22
+ const gaitPath = path.join(currentDir, '.gait');
23
+ try {
24
+ await fs.access(gaitPath);
25
+ return gaitPath;
26
+ }
27
+ catch {
28
+ currentDir = path.dirname(currentDir);
29
+ }
26
30
  }
31
+ return null;
27
32
  }
28
33
  /**
29
- * Get the full path to a specific .gait subdirectory
34
+ * Get the path to a context file, automatically finding the .gait directory
30
35
  */
31
- export function getGaitPath(subdirectory, basePath) {
32
- const base = getGaitBasePath(basePath);
33
- return path.join(base, subdirectory);
36
+ export async function getContextFilePath(fileName) {
37
+ const gaitDir = await findGaitDirectory();
38
+ if (!gaitDir)
39
+ return null;
40
+ return path.join(gaitDir, 'context', fileName);
34
41
  }
35
42
  /**
36
- * Common .gait subdirectories
43
+ * Get the .gait config to read storage path settings
37
44
  */
38
- export const GAIT_PATHS = {
39
- proposals: () => getGaitPath('proposals'),
40
- context: () => getGaitPath('context'),
41
- agents: () => getGaitPath('agents'),
42
- resources: () => getGaitPath('resources'),
43
- chats: () => getGaitPath('chats'),
44
- config: () => getGaitPath(''),
45
- };
45
+ export async function getGaitConfig() {
46
+ const gaitDir = await findGaitDirectory();
47
+ if (!gaitDir)
48
+ return null;
49
+ const configPath = path.join(gaitDir, 'config.json');
50
+ try {
51
+ const config = await fs.readFile(configPath, 'utf-8');
52
+ return JSON.parse(config);
53
+ }
54
+ catch {
55
+ return null;
56
+ }
57
+ }
@@ -0,0 +1,48 @@
1
+ export declare function getRepoRoot(): Promise<string>;
2
+ export declare function getWorktreesBase(): Promise<string>;
3
+ export declare function sanitizeBranchName(name: string): string;
4
+ export declare function resolveSafeWorktreePath(name: string): Promise<string>;
5
+ export declare function runGit(args: string[], opts?: {
6
+ cwd?: string;
7
+ }): Promise<{
8
+ stdout: string;
9
+ stderr: string;
10
+ }>;
11
+ export declare function getRepoStatus(): Promise<{
12
+ branch: string;
13
+ ahead: number;
14
+ behind: number;
15
+ upstream?: string;
16
+ head?: string;
17
+ changes: {
18
+ path: string;
19
+ status: string;
20
+ }[];
21
+ }>;
22
+ export declare function listBranches(): Promise<{
23
+ name: string;
24
+ current: boolean;
25
+ }[]>;
26
+ export declare function createBranch(name: string, from?: string): Promise<void>;
27
+ export declare function deleteBranch(name: string): Promise<void>;
28
+ export declare function pushCurrent(): Promise<string>;
29
+ export declare function pullCurrent(): Promise<string>;
30
+ export interface WorktreeInfo {
31
+ name: string;
32
+ path: string;
33
+ branch: string;
34
+ head?: string;
35
+ locked: boolean;
36
+ }
37
+ export declare function listWorktrees(): Promise<WorktreeInfo[]>;
38
+ export declare function addWorktree(branch: string, from?: string): Promise<{
39
+ path: string;
40
+ branch: string;
41
+ from?: string;
42
+ }>;
43
+ export declare function removeWorktree(nameOrPath: string): Promise<void>;
44
+ export declare function commitInWorktree(name: string, message: string, files?: string[]): Promise<{
45
+ commitHash?: string;
46
+ }>;
47
+ export declare function pushWorktree(name: string): Promise<string>;
48
+ export declare function pullWorktree(name: string): Promise<string>;
@@ -0,0 +1,201 @@
1
+ import { promisify } from 'util';
2
+ import { execFile as _execFile } from 'child_process';
3
+ import path from 'path';
4
+ import { findGaitDirectory } from './gait-path.js';
5
+ import { promises as fs } from 'fs';
6
+ const execFile = promisify(_execFile);
7
+ // Base directory for worktrees under the repository root
8
+ export async function getRepoRoot() {
9
+ // Use .gait discovery to find project root, then go up one level
10
+ const gaitDir = await findGaitDirectory();
11
+ if (!gaitDir) {
12
+ // Fallback to process cwd
13
+ return process.cwd();
14
+ }
15
+ return path.dirname(gaitDir);
16
+ }
17
+ export async function getWorktreesBase() {
18
+ const repoRoot = await getRepoRoot();
19
+ return path.join(repoRoot, 'worktrees');
20
+ }
21
+ export function sanitizeBranchName(name) {
22
+ if (name.length > 120) {
23
+ throw new Error('Invalid branch/worktree name: too long');
24
+ }
25
+ if (!/^[A-Za-z0-9/_\-\.]+$/.test(name)) {
26
+ throw new Error('Invalid branch/worktree name');
27
+ }
28
+ return name;
29
+ }
30
+ export async function resolveSafeWorktreePath(name) {
31
+ const base = await getWorktreesBase();
32
+ const safeName = sanitizeBranchName(name);
33
+ const resolved = path.resolve(base, safeName);
34
+ if (!resolved.startsWith(base)) {
35
+ throw new Error('Invalid worktree path');
36
+ }
37
+ return resolved;
38
+ }
39
+ export async function runGit(args, opts) {
40
+ const repoRoot = await getRepoRoot();
41
+ const cwd = opts?.cwd || repoRoot;
42
+ return execFile('git', args, { cwd, maxBuffer: 10 * 1024 * 1024 });
43
+ }
44
+ // --- Status ---
45
+ export async function getRepoStatus() {
46
+ const { stdout } = await runGit(['status', '--porcelain=v1', '-b']);
47
+ const lines = stdout.trim().split('\n').filter(Boolean);
48
+ let branch = 'unknown';
49
+ let ahead = 0;
50
+ let behind = 0;
51
+ let upstream;
52
+ const changes = [];
53
+ for (const line of lines) {
54
+ if (line.startsWith('## ')) {
55
+ // Example: ## main...origin/main [ahead 1, behind 2]
56
+ const m = line.match(/^##\s+([^\.\s]+)(?:\.\.\.([^\s]+))?(?:.*?\bahead (\d+))?(?:.*?\bbehind (\d+))?/);
57
+ if (m) {
58
+ branch = m[1];
59
+ upstream = m[2] || undefined;
60
+ ahead = m[3] ? parseInt(m[3], 10) : 0;
61
+ behind = m[4] ? parseInt(m[4], 10) : 0;
62
+ }
63
+ else {
64
+ // Fallback to just branch name after ##
65
+ branch = line.slice(3).trim();
66
+ }
67
+ }
68
+ else {
69
+ // Porcelain entry e.g. " M src/app.ts" or "?? README.md"
70
+ const status = line.slice(0, 2).trim() || line.slice(0, 2);
71
+ const file = line.slice(3);
72
+ changes.push({ path: file, status });
73
+ }
74
+ }
75
+ let head;
76
+ try {
77
+ const { stdout: sha } = await runGit(['rev-parse', 'HEAD']);
78
+ head = sha.trim();
79
+ }
80
+ catch {
81
+ // ignore if no commits yet
82
+ }
83
+ return { branch, ahead, behind, upstream, head, changes };
84
+ }
85
+ // --- Branches ---
86
+ export async function listBranches() {
87
+ const { stdout } = await runGit(['branch', '--list']);
88
+ return stdout
89
+ .split('\n')
90
+ .filter(Boolean)
91
+ .map((l) => {
92
+ const current = l.trim().startsWith('* ');
93
+ const name = l.replace('*', '').trim();
94
+ return { name, current };
95
+ });
96
+ }
97
+ export async function createBranch(name, from = 'main') {
98
+ const safe = sanitizeBranchName(name);
99
+ await runGit(['branch', safe, from]);
100
+ }
101
+ export async function deleteBranch(name) {
102
+ const safe = sanitizeBranchName(name);
103
+ await runGit(['branch', '-D', safe]);
104
+ }
105
+ // --- Push / Pull ---
106
+ export async function pushCurrent() {
107
+ const { stdout } = await runGit(['push']);
108
+ return stdout;
109
+ }
110
+ export async function pullCurrent() {
111
+ const { stdout } = await runGit(['pull']);
112
+ return stdout;
113
+ }
114
+ export async function listWorktrees() {
115
+ const { stdout } = await runGit(['worktree', 'list', '--porcelain']);
116
+ // Parse porcelain groups separated by blank lines with fields: worktree <path>, HEAD <sha>, branch <refs/heads/x>, locked
117
+ const entries = [];
118
+ const blocks = stdout.split('\n\n').map((b) => b.trim()).filter(Boolean);
119
+ for (const block of blocks) {
120
+ const lines = block.split('\n');
121
+ let wtPath = '';
122
+ let head;
123
+ let branchRef = '';
124
+ let locked = false;
125
+ for (const l of lines) {
126
+ const [k, ...rest] = l.split(' ');
127
+ const v = rest.join(' ');
128
+ if (k === 'worktree')
129
+ wtPath = v;
130
+ if (k === 'HEAD')
131
+ head = v;
132
+ if (k === 'branch')
133
+ branchRef = v;
134
+ if (k === 'locked')
135
+ locked = true;
136
+ }
137
+ const branch = branchRef.replace('refs/heads/', '');
138
+ const name = path.basename(wtPath);
139
+ entries.push({ name, path: wtPath, branch, head, locked });
140
+ }
141
+ return entries;
142
+ }
143
+ async function getWorktreeByName(name) {
144
+ const all = await listWorktrees();
145
+ return all.find((w) => w.name === name || w.branch === name);
146
+ }
147
+ export async function addWorktree(branch, from) {
148
+ const safeBranch = sanitizeBranchName(branch);
149
+ const wtPath = await resolveSafeWorktreePath(safeBranch);
150
+ const base = await getWorktreesBase();
151
+ await fs.mkdir(base, { recursive: true });
152
+ // Ensure parent directory exists
153
+ // Use git worktree add -b when creating from another branch
154
+ if (from) {
155
+ await runGit(['worktree', 'add', '-b', safeBranch, wtPath, from]);
156
+ }
157
+ else {
158
+ await runGit(['worktree', 'add', wtPath, safeBranch]);
159
+ }
160
+ return { path: wtPath, branch: safeBranch, from };
161
+ }
162
+ export async function removeWorktree(nameOrPath) {
163
+ // If a named worktree exists, use its actual path; otherwise treat as path relative to base
164
+ let targetPath = nameOrPath;
165
+ if (!path.isAbsolute(nameOrPath)) {
166
+ const found = await getWorktreeByName(nameOrPath);
167
+ if (found) {
168
+ targetPath = found.path;
169
+ }
170
+ else {
171
+ targetPath = await resolveSafeWorktreePath(nameOrPath);
172
+ }
173
+ }
174
+ await runGit(['worktree', 'remove', targetPath]);
175
+ }
176
+ export async function commitInWorktree(name, message, files) {
177
+ const found = await getWorktreeByName(name);
178
+ const wtPath = found ? found.path : await resolveSafeWorktreePath(name);
179
+ // git -C <worktree> add ... && commit -m
180
+ if (files && files.length > 0) {
181
+ await runGit(['-C', wtPath, 'add', ...files]);
182
+ }
183
+ else {
184
+ await runGit(['-C', wtPath, 'add', '-A']);
185
+ }
186
+ await runGit(['-C', wtPath, 'commit', '-m', message]);
187
+ const { stdout } = await runGit(['-C', wtPath, 'rev-parse', 'HEAD']);
188
+ return { commitHash: stdout.trim() };
189
+ }
190
+ export async function pushWorktree(name) {
191
+ const found = await getWorktreeByName(name);
192
+ const wtPath = found ? found.path : await resolveSafeWorktreePath(name);
193
+ const { stdout } = await runGit(['-C', wtPath, 'push']);
194
+ return stdout;
195
+ }
196
+ export async function pullWorktree(name) {
197
+ const found = await getWorktreeByName(name);
198
+ const wtPath = found ? found.path : await resolveSafeWorktreePath(name);
199
+ const { stdout } = await runGit(['-C', wtPath, 'pull']);
200
+ return stdout;
201
+ }
@@ -2,11 +2,24 @@ import { promises as fs } from 'fs';
2
2
  import path from 'path';
3
3
  import matter from 'gray-matter';
4
4
  import Fuse from 'fuse.js';
5
- import { getGaitPath } from '../gait-path.js';
6
5
  export class FileStorageAdapter {
7
6
  basePath;
8
7
  constructor(basePath) {
9
- this.basePath = basePath || getGaitPath('proposals');
8
+ if (basePath) {
9
+ this.basePath = basePath;
10
+ }
11
+ else if (process.env.NODE_ENV === 'development' && process.env.GAIT_DEV_ROOT) {
12
+ // Dev mode: use project root .gait directory
13
+ this.basePath = process.env.GAIT_DEV_ROOT;
14
+ }
15
+ else if (process.env.GAIT_DATA_PATH) {
16
+ // Production mode: use GAIT_DATA_PATH (set by CLI)
17
+ this.basePath = path.join(process.env.GAIT_DATA_PATH, '.gait');
18
+ }
19
+ else {
20
+ // Fallback: use current directory .gait
21
+ this.basePath = '.gait';
22
+ }
10
23
  }
11
24
  async ensureDirectories() {
12
25
  const dirs = ['proposals', 'specs', 'flags', 'experiments', 'templates'];
@@ -0,0 +1,3 @@
1
+ import { Hono } from 'hono';
2
+ declare const app: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
3
+ export default app;
@@ -0,0 +1,175 @@
1
+ import { Hono } from 'hono';
2
+ import { getRepoStatus, listBranches, createBranch, deleteBranch, pushCurrent, pullCurrent, listWorktrees, addWorktree, removeWorktree, commitInWorktree, pushWorktree, pullWorktree, } from '../../../../lib/git.js';
3
+ const app = new Hono();
4
+ // Status
5
+ app.get('/status', async (c) => {
6
+ try {
7
+ const status = await getRepoStatus();
8
+ return c.json({ success: true, data: status });
9
+ }
10
+ catch (e) {
11
+ return c.json({ success: false, error: { message: e.message } }, 500);
12
+ }
13
+ });
14
+ // Branches
15
+ app.get('/branches', async (c) => {
16
+ try {
17
+ const branches = await listBranches();
18
+ return c.json({ success: true, data: branches });
19
+ }
20
+ catch (e) {
21
+ return c.json({ success: false, error: { message: e.message } }, 500);
22
+ }
23
+ });
24
+ app.post('/branches', async (c) => {
25
+ try {
26
+ const body = await c.req.json();
27
+ const name = String(body?.name);
28
+ const from = body?.from ? String(body.from) : 'main';
29
+ if (!name)
30
+ return c.json({ success: false, error: { message: 'name required' } }, 400);
31
+ await createBranch(name, from);
32
+ return c.json({ success: true, data: { created: name, from } });
33
+ }
34
+ catch (e) {
35
+ return c.json({ success: false, error: { message: e.message } }, 500);
36
+ }
37
+ });
38
+ app.delete('/branches/:branch', async (c) => {
39
+ try {
40
+ const name = c.req.param('branch');
41
+ await deleteBranch(name);
42
+ return c.json({ success: true, data: { deleted: name } });
43
+ }
44
+ catch (e) {
45
+ return c.json({ success: false, error: { message: e.message } }, 500);
46
+ }
47
+ });
48
+ // Commits (in current repo root)
49
+ app.post('/commits', async (c) => {
50
+ try {
51
+ const body = await c.req.json();
52
+ const message = String(body?.message || '');
53
+ const files = Array.isArray(body?.files) ? body.files.map(String) : undefined;
54
+ if (!message)
55
+ return c.json({ success: false, error: { message: 'message required' } }, 400);
56
+ // Use repo root, add files or all, then commit
57
+ // Reuse worktree commit logic with special name? Simpler: do add/commit at repo root using git.ts helpers
58
+ // Minimal inline since helpers are worktree-centric
59
+ const { runGit } = await import('../../../../lib/git.js');
60
+ if (files && files.length > 0) {
61
+ await runGit(['add', ...files]);
62
+ }
63
+ else {
64
+ await runGit(['add', '-A']);
65
+ }
66
+ await runGit(['commit', '-m', message]);
67
+ const { stdout } = await runGit(['rev-parse', 'HEAD']);
68
+ return c.json({ success: true, data: { message, files: files ?? null, commitHash: stdout.trim() } });
69
+ }
70
+ catch (e) {
71
+ return c.json({ success: false, error: { message: e.message } }, 500);
72
+ }
73
+ });
74
+ // Push / Pull (current)
75
+ app.post('/push', async (c) => {
76
+ try {
77
+ const result = await pushCurrent();
78
+ return c.json({ success: true, data: { result } });
79
+ }
80
+ catch (e) {
81
+ return c.json({ success: false, error: { message: e.message } }, 500);
82
+ }
83
+ });
84
+ app.post('/pull', async (c) => {
85
+ try {
86
+ const result = await pullCurrent();
87
+ return c.json({ success: true, data: { result } });
88
+ }
89
+ catch (e) {
90
+ return c.json({ success: false, error: { message: e.message } }, 500);
91
+ }
92
+ });
93
+ // Worktrees
94
+ app.get('/worktrees', async (c) => {
95
+ try {
96
+ const data = await listWorktrees();
97
+ return c.json({ success: true, data });
98
+ }
99
+ catch (e) {
100
+ return c.json({ success: false, error: { message: e.message } }, 500);
101
+ }
102
+ });
103
+ app.post('/worktrees', async (c) => {
104
+ try {
105
+ const body = await c.req.json();
106
+ const branch = String(body?.branch || '');
107
+ const from = body?.from ? String(body.from) : undefined;
108
+ if (!branch)
109
+ return c.json({ success: false, error: { message: 'branch required' } }, 400);
110
+ const added = await addWorktree(branch, from);
111
+ return c.json({ success: true, data: { added } });
112
+ }
113
+ catch (e) {
114
+ return c.json({ success: false, error: { message: e.message } }, 500);
115
+ }
116
+ });
117
+ app.get('/worktrees/:name', async (c) => {
118
+ try {
119
+ const name = c.req.param('name');
120
+ const all = await listWorktrees();
121
+ const found = all.find((w) => w.name === name);
122
+ if (!found)
123
+ return c.json({ success: false, error: { message: 'Not found' } }, 404);
124
+ return c.json({ success: true, data: found });
125
+ }
126
+ catch (e) {
127
+ return c.json({ success: false, error: { message: e.message } }, 500);
128
+ }
129
+ });
130
+ app.delete('/worktrees/:name', async (c) => {
131
+ try {
132
+ const name = c.req.param('name');
133
+ await removeWorktree(name);
134
+ return c.json({ success: true, data: { removed: name } });
135
+ }
136
+ catch (e) {
137
+ return c.json({ success: false, error: { message: e.message } }, 500);
138
+ }
139
+ });
140
+ app.post('/worktrees/:name/commit', async (c) => {
141
+ try {
142
+ const name = c.req.param('name');
143
+ const body = await c.req.json();
144
+ const message = String(body?.message || '');
145
+ const files = Array.isArray(body?.files) ? body.files.map(String) : undefined;
146
+ if (!message)
147
+ return c.json({ success: false, error: { message: 'message required' } }, 400);
148
+ const res = await commitInWorktree(name, message, files);
149
+ return c.json({ success: true, data: { worktree: name, message, files: files ?? null, ...res } });
150
+ }
151
+ catch (e) {
152
+ return c.json({ success: false, error: { message: e.message } }, 500);
153
+ }
154
+ });
155
+ app.post('/worktrees/:name/push', async (c) => {
156
+ try {
157
+ const name = c.req.param('name');
158
+ const result = await pushWorktree(name);
159
+ return c.json({ success: true, data: { worktree: name, result } });
160
+ }
161
+ catch (e) {
162
+ return c.json({ success: false, error: { message: e.message } }, 500);
163
+ }
164
+ });
165
+ app.post('/worktrees/:name/pull', async (c) => {
166
+ try {
167
+ const name = c.req.param('name');
168
+ const result = await pullWorktree(name);
169
+ return c.json({ success: true, data: { worktree: name, result } });
170
+ }
171
+ catch (e) {
172
+ return c.json({ success: false, error: { message: e.message } }, 500);
173
+ }
174
+ });
175
+ export default app;
package/dist/server.js CHANGED
@@ -64,6 +64,7 @@ import config from './routes/api/v1/config/index.js';
64
64
  import user from './routes/api/v1/user/index.js';
65
65
  import agents from './routes/api/v1/agents/index.js';
66
66
  import agentsById from './routes/api/v1/agents/[id]/index.js';
67
+ import git from './routes/api/v1/git/index.js';
67
68
  // Register API routes
68
69
  app.route('/api/v1/proposals', proposals);
69
70
  app.route('/api/v1/terminal/sessions', terminalSessions);
@@ -81,6 +82,7 @@ app.route('/api/v1/config', config);
81
82
  app.route('/api/v1/user', user);
82
83
  app.route('/api/v1/agents', agents);
83
84
  app.route('/api/v1/agents/:id', agentsById);
85
+ app.route('/api/v1/git', git);
84
86
  // Health check endpoint
85
87
  app.get('/health', (c) => {
86
88
  return c.json({ status: 'ok', timestamp: new Date().toISOString() });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lovelybunch/api",
3
- "version": "1.0.24",
3
+ "version": "1.0.27",
4
4
  "type": "module",
5
5
  "main": "dist/server-with-static.js",
6
6
  "exports": {
@@ -32,8 +32,8 @@
32
32
  "dependencies": {
33
33
  "@hono/node-server": "^1.13.7",
34
34
  "@hono/node-ws": "^1.0.6",
35
- "@lovelybunch/core": "^1.0.24",
36
- "@lovelybunch/types": "^1.0.24",
35
+ "@lovelybunch/core": "^1.0.27",
36
+ "@lovelybunch/types": "^1.0.27",
37
37
  "dotenv": "^17.2.1",
38
38
  "fuse.js": "^7.0.0",
39
39
  "gray-matter": "^4.0.3",