@way_marks/cli 2.0.3 → 4.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.
@@ -83,7 +83,7 @@ function kebabCase(str) {
83
83
  .replace(/-+/g, '-')
84
84
  .replace(/^-|-$/g, '');
85
85
  }
86
- function generateClaudeMd(projectName, port) {
86
+ function generateClaudeMd(projectName) {
87
87
  return `---
88
88
  # ⚠️ WAYMARK ACTIVE — MANDATORY INSTRUCTIONS
89
89
 
@@ -135,9 +135,10 @@ Then restart Claude Code and try again."
135
135
 
136
136
  ## Dashboard
137
137
 
138
- All actions are visible at: http://localhost:${port}
139
- Approve pending actions there.
140
- Roll back any write there.
138
+ Pending and recent actions are visible in the
139
+ Waymark dashboard. Run \`npx @way_marks/cli status\`
140
+ to see the current dashboard URL for this project.
141
+ Approve pending actions there. Roll back any write there.
141
142
 
142
143
  ## This file was generated by Waymark
143
144
  Do not delete or modify this file.
@@ -208,7 +209,6 @@ async function run() {
208
209
  const projectName = kebabCase(path.basename(projectRoot));
209
210
  const mcpKey = `waymark-${projectName}`;
210
211
  const dbPath = path.join(projectRoot, '.waymark', 'waymark.db');
211
- const defaultPort = 3001;
212
212
  console.log(`Initializing Waymark in: ${projectRoot}`);
213
213
  // Step 1 — Detect project
214
214
  const hasPackageJson = fs.existsSync(path.join(projectRoot, 'package.json'));
@@ -263,7 +263,7 @@ async function run() {
263
263
  // Step 4 — Create/append CLAUDE.md (only if Claude selected)
264
264
  if (selectedPlatforms.includes('claude')) {
265
265
  const claudeMdPath = path.join(projectRoot, 'CLAUDE.md');
266
- const claudeMdContent = generateClaudeMd(projectName, defaultPort);
266
+ const claudeMdContent = generateClaudeMd(projectName);
267
267
  if (fs.existsSync(claudeMdPath)) {
268
268
  const existing = fs.readFileSync(claudeMdPath, 'utf8');
269
269
  if (existing.includes(WAYMARK_MARKER)) {
@@ -379,9 +379,9 @@ async function run() {
379
379
  if (selectedPlatforms.includes('claude')) {
380
380
  console.log(`│ ${pad('Next steps (Claude):')} │`);
381
381
  console.log(`│ ${pad('1. Run: npx @way_marks/cli start')} │`);
382
+ console.log(`│ ${pad(' (it will print the dashboard URL)')} │`);
382
383
  console.log(`│ ${pad('2. Restart Claude Code')} │`);
383
384
  console.log(`│ ${pad('3. Open project in Claude')} │`);
384
- console.log(`│ ${pad('4. Dashboard: http://localhost:3001')} │`);
385
385
  }
386
386
  if (selectedPlatforms.includes('copilot-cli')) {
387
387
  if (selectedPlatforms.includes('claude')) {
@@ -1,7 +1,58 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.run = run;
4
- const BASE = 'http://localhost:3001';
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ /**
40
+ * Resolve the dashboard URL for the current project by reading the live port
41
+ * out of `<cwd>/.waymark/config.json` (written by `waymark start`).
42
+ * Returns null when the project hasn't been started yet.
43
+ */
44
+ function resolveBaseUrl() {
45
+ const configPath = path.join(process.cwd(), '.waymark', 'config.json');
46
+ if (!fs.existsSync(configPath))
47
+ return null;
48
+ try {
49
+ const cfg = JSON.parse(fs.readFileSync(configPath, 'utf8'));
50
+ return cfg.port ? `http://localhost:${cfg.port}` : null;
51
+ }
52
+ catch {
53
+ return null;
54
+ }
55
+ }
5
56
  function parseIso(iso) {
6
57
  const normalized = iso.includes('T') ? iso : iso.replace(' ', 'T');
7
58
  const withZ = normalized.endsWith('Z') ? normalized : normalized + 'Z';
@@ -34,15 +85,20 @@ async function run() {
34
85
  const limit = limitIdx !== -1 ? parseInt(args[limitIdx + 1], 10) || 20 : 20;
35
86
  const pendingOnly = args.includes('--pending');
36
87
  const blockedOnly = args.includes('--blocked');
88
+ const base = resolveBaseUrl();
89
+ if (!base) {
90
+ console.log('Waymark is not running for this project. Start with: npx @way_marks/cli start');
91
+ return;
92
+ }
37
93
  let rows;
38
94
  try {
39
- const res = await fetch(`${BASE}/api/actions`);
95
+ const res = await fetch(`${base}/api/actions`);
40
96
  if (!res.ok)
41
97
  throw new Error('Bad response');
42
98
  rows = await res.json();
43
99
  }
44
100
  catch {
45
- console.log('Waymark is not running. Start with: npx @way_marks/cli start');
101
+ console.log(`Waymark is not reachable at ${base}. Start with: npx @way_marks/cli start`);
46
102
  return;
47
103
  }
48
104
  if (pendingOnly)
@@ -82,7 +82,7 @@ function findAvailablePort(preferred) {
82
82
  return Promise.resolve((0, registry_1.findAvailablePort)(preferred));
83
83
  }
84
84
  catch {
85
- // Fallback: old logic (Phase 1 compatibility)
85
+ // Fallback: kernel-level probe (registry corrupt or absent)
86
86
  return new Promise((resolve) => {
87
87
  const server = net.createServer();
88
88
  server.listen(preferred, () => {
@@ -90,8 +90,9 @@ function findAvailablePort(preferred) {
90
90
  server.close(() => resolve(port));
91
91
  });
92
92
  server.on('error', () => {
93
- if (preferred >= 4000) {
94
- console.error('No available ports found between 3001-4000. Stop other Waymark projects first.');
93
+ if (preferred >= registry_1.PORT_RANGE_END) {
94
+ console.error(`No available ports found between ${registry_1.PORT_RANGE_START}-${registry_1.PORT_RANGE_END}. ` +
95
+ `Stop other Waymark projects first.`);
95
96
  process.exit(1);
96
97
  }
97
98
  resolve(findAvailablePort(preferred + 1));
@@ -99,6 +100,37 @@ function findAvailablePort(preferred) {
99
100
  });
100
101
  }
101
102
  }
103
+ /**
104
+ * Probe whether `port` is currently free. We listen exactly the same way the
105
+ * real server does (no explicit host → all interfaces, dual-stack), so this
106
+ * matches what would happen at actual bind time and catches IPv4/IPv6
107
+ * dual-stack collisions.
108
+ */
109
+ function isPortFree(port) {
110
+ return new Promise((resolve) => {
111
+ const server = net.createServer();
112
+ server.once('error', () => resolve(false));
113
+ server.once('listening', () => server.close(() => resolve(true)));
114
+ server.listen(port);
115
+ });
116
+ }
117
+ /**
118
+ * Parse `--port <n>` from process.argv. Returns null when not provided.
119
+ * Validates the value is a positive integer < 65536. Exits with a readable
120
+ * error on garbage input rather than silently ignoring.
121
+ */
122
+ function parsePortFlag(argv) {
123
+ const idx = argv.indexOf('--port');
124
+ if (idx === -1)
125
+ return null;
126
+ const raw = argv[idx + 1];
127
+ const port = Number.parseInt(raw, 10);
128
+ if (!Number.isInteger(port) || port <= 0 || port >= 65536 || String(port) !== raw) {
129
+ console.error(`Invalid --port value: "${raw}". Expected an integer 1-65535.`);
130
+ process.exit(1);
131
+ }
132
+ return port;
133
+ }
102
134
  async function run() {
103
135
  const projectRoot = process.cwd();
104
136
  const configPath = path.join(projectRoot, 'waymark.config.json');
@@ -113,7 +145,7 @@ async function run() {
113
145
  try {
114
146
  const saved = JSON.parse(fs.readFileSync(pidFile, 'utf8'));
115
147
  if (isAlive(saved.api) || isAlive(saved.mcp)) {
116
- const port = saved.port || 3001;
148
+ const port = saved.port || registry_1.PORT_RANGE_START;
117
149
  console.log('Waymark is already running.');
118
150
  console.log(`Dashboard: http://localhost:${port}`);
119
151
  console.log('Run "npx @way_marks/cli stop" to stop it.');
@@ -124,9 +156,96 @@ async function run() {
124
156
  // stale/corrupt PID file — continue to start
125
157
  }
126
158
  }
127
- const port = await findAvailablePort(3001);
128
- const dbPath = path.join(projectRoot, '.waymark', 'waymark.db');
129
159
  const projectName = kebabCase(path.basename(projectRoot));
160
+ const dbPath = path.join(projectRoot, '.waymark', 'waymark.db');
161
+ // Load project config — used for the optional `port` pin.
162
+ let projectConfig = {};
163
+ try {
164
+ projectConfig = JSON.parse(fs.readFileSync(configPath, 'utf8'));
165
+ }
166
+ catch (err) {
167
+ console.error(`Failed to parse waymark.config.json: ${err instanceof Error ? err.message : String(err)}`);
168
+ process.exit(1);
169
+ }
170
+ // Port resolution precedence: --port flag > config.port > auto-allocate.
171
+ const flagPort = parsePortFlag(process.argv.slice(3));
172
+ const configPort = typeof projectConfig.port === 'number' ? projectConfig.port : null;
173
+ const pinnedPort = flagPort ?? configPort;
174
+ const pinnedSource = flagPort !== null ? 'flag' : configPort !== null ? 'config' : null;
175
+ let port;
176
+ if (pinnedPort !== null) {
177
+ if (!(await isPortFree(pinnedPort))) {
178
+ const existing = (0, registry_1.findProjectByPath)(projectRoot);
179
+ const owner = (() => {
180
+ // Best-effort: try to identify which Waymark project owns the port.
181
+ // We can't reach into other processes; just advise `waymark list`.
182
+ return null;
183
+ })();
184
+ console.error(`Port ${pinnedPort} is already in use ` +
185
+ `(pinned via ${pinnedSource === 'flag' ? '--port flag' : 'waymark.config.json'}).\n` +
186
+ ` → Run "npx @way_marks/cli list" to see other Waymark projects.\n` +
187
+ ` → Or remove the pin to auto-allocate from ${registry_1.PORT_RANGE_START}-${registry_1.PORT_RANGE_END}.`);
188
+ void existing;
189
+ void owner; // reserved for future "owner is project X" diagnostics
190
+ process.exit(1);
191
+ }
192
+ port = pinnedPort;
193
+ }
194
+ else {
195
+ // Migration notice: if this project's prior registry entry used a legacy port,
196
+ // the auto-allocator may pick a fresh modern port instead. Emit a one-line
197
+ // notice so the user understands why their bookmark might shift.
198
+ const prior = (0, registry_1.findProjectByPath)(projectRoot);
199
+ const newPort = await findAvailablePort(registry_1.PORT_RANGE_START);
200
+ if (prior &&
201
+ typeof prior.port === 'number' &&
202
+ prior.port < registry_1.LEGACY_PORT_BOUNDARY &&
203
+ newPort !== prior.port) {
204
+ console.log(`[waymark] Reallocating from legacy port :${prior.port} to :${newPort}.\n` +
205
+ ` Set "port": ${prior.port} in waymark.config.json to keep the old one.`);
206
+ }
207
+ port = newPort;
208
+ }
209
+ // Pre-flight: surface any project-id collision *before* spawning children,
210
+ // so we never leave orphan processes when registration would fail.
211
+ const colliding = (() => {
212
+ try {
213
+ // Probe by performing a fake registerProject() that we immediately undo
214
+ // would risk corrupting the file; instead read directly via findProjectByPath
215
+ // and check the registry's keying contract here.
216
+ const otherAtSamePath = (0, registry_1.findProjectByPath)(projectRoot);
217
+ if (otherAtSamePath && otherAtSamePath.id === projectName)
218
+ return null;
219
+ // Different path with same id → ask registry for the entry by id.
220
+ // findProjectByPath already returned null, so we need a different lookup.
221
+ // Use require-time access to the same module's getProject.
222
+ const reg = require('../registry');
223
+ const sameId = reg.getProject(projectName);
224
+ if (sameId &&
225
+ path.resolve(sameId.projectRoot) !== path.resolve(projectRoot) &&
226
+ ((sameId.mcp_pid != null && (() => { try {
227
+ process.kill(sameId.mcp_pid, 0);
228
+ return true;
229
+ }
230
+ catch {
231
+ return false;
232
+ } })()) ||
233
+ sameId.status === 'running')) {
234
+ return sameId;
235
+ }
236
+ return null;
237
+ }
238
+ catch {
239
+ return null;
240
+ }
241
+ })();
242
+ if (colliding) {
243
+ console.error(`Another running Waymark project named "${projectName}" is registered at ${colliding.projectRoot}.\n` +
244
+ `This start request is at ${projectRoot}.\n` +
245
+ ` → Stop the other project first ("npx @way_marks/cli stop" in ${colliding.projectRoot}),\n` +
246
+ ` → or rename one of the directories so the project ids differ.`);
247
+ process.exit(1);
248
+ }
130
249
  const nodeBin = process.execPath;
131
250
  const mcpBin = resolveServerBin('mcp');
132
251
  const apiBin = resolveServerBin('api');
@@ -181,6 +300,24 @@ async function run() {
181
300
  });
182
301
  }
183
302
  catch (err) {
303
+ if (err instanceof registry_1.ProjectIdCollisionError) {
304
+ // Race: another start landed between our pre-flight and registration.
305
+ // Tear down the children we just spawned so we don't leak processes.
306
+ try {
307
+ apiProc.pid && process.kill(apiProc.pid);
308
+ }
309
+ catch { }
310
+ try {
311
+ mcpProc.pid && process.kill(mcpProc.pid);
312
+ }
313
+ catch { }
314
+ try {
315
+ fs.unlinkSync(pidFile);
316
+ }
317
+ catch { }
318
+ console.error(err.message);
319
+ process.exit(1);
320
+ }
184
321
  console.warn('Warning: failed to register in global registry:', err instanceof Error ? err.message : String(err));
185
322
  // Continue anyway — registry is optional (backward compat)
186
323
  }
package/dist/index.js CHANGED
@@ -33,14 +33,19 @@ switch (command) {
33
33
  console.log('Usage: npx @way_marks/cli <init|start|stop|pause|resume|status|logs|list|open>');
34
34
  console.log('');
35
35
  console.log('Commands:');
36
- console.log(' init Set up Waymark in the current project');
37
- console.log(' start Start the Waymark dashboard and MCP server');
38
- console.log(' stop Stop the running Waymark servers');
39
- console.log(' pause Pause a project (keep port allocated)');
40
- console.log(' resume Resume a paused project');
41
- console.log(' status Show current Waymark status and pending count');
42
- console.log(' logs Show recent action log');
43
- console.log(' list List all registered Waymark projects');
44
- console.log(' open Open a project dashboard or start it');
36
+ console.log(' init Set up Waymark in the current project');
37
+ console.log(' start [--port <n>] Start the Waymark dashboard and MCP server');
38
+ console.log(' stop Stop the running Waymark servers');
39
+ console.log(' pause Pause a project (keep port allocated)');
40
+ console.log(' resume Resume a paused project');
41
+ console.log(' status Show current Waymark status and pending count');
42
+ console.log(' logs Show recent action log');
43
+ console.log(' list List all registered Waymark projects');
44
+ console.log(' open Open a project dashboard or start it');
45
+ console.log('');
46
+ console.log('Notes:');
47
+ console.log(' • Default port range is 47000-47999 (avoids collisions with dev servers).');
48
+ console.log(' • Pin a port per-project: add "port": 47100 to waymark.config.json.');
49
+ console.log(' • Override at runtime: waymark start --port 47200');
45
50
  process.exit(command ? 1 : 0);
46
51
  }
package/dist/registry.js CHANGED
@@ -45,6 +45,7 @@ var __importStar = (this && this.__importStar) || (function () {
45
45
  };
46
46
  })();
47
47
  Object.defineProperty(exports, "__esModule", { value: true });
48
+ exports.LEGACY_PORT_BOUNDARY = exports.PORT_RANGE_END = exports.PORT_RANGE_START = exports.ProjectIdCollisionError = void 0;
48
49
  exports.getRegistry = getRegistry;
49
50
  exports.registerProject = registerProject;
50
51
  exports.unregisterProject = unregisterProject;
@@ -96,11 +97,51 @@ function ensureRegistry() {
96
97
  function getRegistry() {
97
98
  return ensureRegistry();
98
99
  }
100
+ /**
101
+ * Error thrown when two projects with the same kebab-cased basename are running
102
+ * at different paths. Caller (start.ts) catches this and emits a user-facing
103
+ * message instead of silently overwriting the registry.
104
+ */
105
+ class ProjectIdCollisionError extends Error {
106
+ constructor(id, existingRoot, newRoot) {
107
+ super(`Another running Waymark project named "${id}" is registered at ${existingRoot}. ` +
108
+ `This start request is at ${newRoot}. ` +
109
+ `Stop the other project first ("npx @way_marks/cli stop" in ${existingRoot}), ` +
110
+ `or rename one of the directories so the project ids differ.`);
111
+ this.name = 'ProjectIdCollisionError';
112
+ this.id = id;
113
+ this.existingRoot = existingRoot;
114
+ this.newRoot = newRoot;
115
+ }
116
+ }
117
+ exports.ProjectIdCollisionError = ProjectIdCollisionError;
99
118
  /**
100
119
  * Register a project (called on `waymark start`)
120
+ *
121
+ * Surfaces a `ProjectIdCollisionError` when an entry with the same `id`
122
+ * already exists at a *different* path AND its process is still alive.
123
+ * Same-path re-registration (the resume case) overwrites silently.
124
+ * Stale entries (process gone) are also overwritten — caller will start fresh.
101
125
  */
102
126
  function registerProject(entry) {
103
127
  const registry = ensureRegistry();
128
+ const existing = registry.projects[entry.id];
129
+ if (existing && path.resolve(existing.projectRoot) !== path.resolve(entry.projectRoot)) {
130
+ const aliveByPid = existing.mcp_pid != null && (() => {
131
+ try {
132
+ process.kill(existing.mcp_pid, 0);
133
+ return true;
134
+ }
135
+ catch {
136
+ return false;
137
+ }
138
+ })();
139
+ const aliveByStatus = existing.status === 'running';
140
+ if (aliveByPid || aliveByStatus) {
141
+ throw new ProjectIdCollisionError(entry.id, existing.projectRoot, entry.projectRoot);
142
+ }
143
+ // Stale entry at a different path — fall through and overwrite.
144
+ }
104
145
  entry.startedAt = entry.startedAt || new Date().toISOString();
105
146
  entry.status = entry.status || 'running';
106
147
  entry.hostname = entry.hostname || os.hostname();
@@ -186,35 +227,64 @@ function listProjects(filter) {
186
227
  return entries;
187
228
  }
188
229
  /**
189
- * Find available port in the 3001-4000 range
190
- * (Phase 2 future: will be replaced by central port broker)
230
+ * Default port range for new Waymark projects.
231
+ *
232
+ * 47000-47999 is in the IANA "user ports" range and avoids collisions with the
233
+ * most common dev-server defaults (3000 Next.js, 3001 fallback, 5173 Vite,
234
+ * 4200 Angular, 8080 generic, 1337 Strapi, etc.). Existing projects on the
235
+ * legacy 3001-4000 range keep working until they're stopped — see start.ts
236
+ * for the migration notice.
191
237
  */
192
- function findAvailablePort(preferred = 3001) {
238
+ exports.PORT_RANGE_START = 47000;
239
+ exports.PORT_RANGE_END = 47999;
240
+ exports.LEGACY_PORT_BOUNDARY = 47000; // anything below this is "legacy"
241
+ /**
242
+ * Find an available port for a new Waymark instance.
243
+ *
244
+ * Order:
245
+ * 1. Reuse a freed port from the releasedPorts queue (when not in use).
246
+ * 2. Use `preferred` if free.
247
+ * 3. Scan 47000..47999 for the first free port.
248
+ */
249
+ function findAvailablePort(preferred = exports.PORT_RANGE_START) {
193
250
  const registry = ensureRegistry();
194
251
  const usedPorts = new Set(Object.values(registry.projects)
195
252
  .filter(p => p.status === 'running')
196
253
  .map(p => p.port));
197
- // Phase 4: Check if we have a released port to reuse first
254
+ // Reuse a released port if one is available but skip any legacy ports
255
+ // (< LEGACY_PORT_BOUNDARY) so the v3.1 migration cleanly transitions every
256
+ // project off the old range over time. Legacy ports are simply discarded.
198
257
  if (registry.releasedPorts && registry.releasedPorts.length > 0) {
199
- const releasedPort = registry.releasedPorts.shift();
200
- if (releasedPort && !usedPorts.has(releasedPort)) {
201
- // Save updated registry with shifted port
258
+ let mutated = false;
259
+ while (registry.releasedPorts.length > 0) {
260
+ const candidate = registry.releasedPorts.shift();
261
+ mutated = true;
262
+ if (candidate == null)
263
+ continue;
264
+ if (candidate < exports.LEGACY_PORT_BOUNDARY)
265
+ continue; // drop legacy
266
+ if (usedPorts.has(candidate))
267
+ continue;
268
+ registry.lastUpdated = new Date().toISOString();
269
+ fs.writeFileSync(REGISTRY_PATH, JSON.stringify(registry, null, 2) + '\n');
270
+ return candidate;
271
+ }
272
+ if (mutated) {
202
273
  registry.lastUpdated = new Date().toISOString();
203
274
  fs.writeFileSync(REGISTRY_PATH, JSON.stringify(registry, null, 2) + '\n');
204
- return releasedPort;
205
275
  }
206
276
  }
207
277
  // Check if preferred is available
208
278
  if (!usedPorts.has(preferred)) {
209
279
  return preferred;
210
280
  }
211
- // Find next available
212
- for (let port = 3001; port <= 4000; port++) {
281
+ // Find next available in the modern range
282
+ for (let port = exports.PORT_RANGE_START; port <= exports.PORT_RANGE_END; port++) {
213
283
  if (!usedPorts.has(port)) {
214
284
  return port;
215
285
  }
216
286
  }
217
- throw new Error('No available ports in range 3001-4000');
287
+ throw new Error(`No available ports in range ${exports.PORT_RANGE_START}-${exports.PORT_RANGE_END}. Stop other Waymark projects first.`);
218
288
  }
219
289
  /**
220
290
  * Clean up stale entries (processes that are dead but not unregistered)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@way_marks/cli",
3
- "version": "2.0.3",
3
+ "version": "4.0.0",
4
4
  "description": "Control what AI agents can do in your codebase",
5
5
  "author": "Waymark <hello@waymarks.dev>",
6
6
  "license": "MIT",
@@ -40,7 +40,7 @@
40
40
  ]
41
41
  },
42
42
  "dependencies": {
43
- "@way_marks/server": "0.5.2"
43
+ "@way_marks/server": "4.0.0"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@types/jest": "^30.0.0",