devsess 0.3.0 → 0.3.2

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.
@@ -8,7 +8,7 @@ import {
8
8
  resolveSiblingDir,
9
9
  runManagedSubprocess,
10
10
  runningSignalPath
11
- } from "../chunk-Z7T6KVWK.js";
11
+ } from "../chunk-UVQAAP2U.js";
12
12
 
13
13
  // src/async/index.ts
14
14
  import { Schema } from "effect";
@@ -129,9 +129,104 @@ var buildDevSessionsLayer = (rootDir) => Layer.effect(
129
129
  import { watch as fsWatch, realpathSync } from "fs";
130
130
  import { createRequire } from "module";
131
131
  import { dirname, join, resolve } from "path";
132
- import { Deferred, Effect as Effect2 } from "effect";
132
+ import { Deferred, Effect as Effect3 } from "effect";
133
133
  import { FileSystem as FileSystem2 } from "effect/FileSystem";
134
134
  import { Path as Path2 } from "effect/Path";
135
+
136
+ // src/dev/daemon-readiness.ts
137
+ import { createConnection } from "net";
138
+ import { StringDecoder } from "string_decoder";
139
+ import { Effect as Effect2, Exit, Schema } from "effect";
140
+ var RESPONSE_TIMEOUT_MS = 200;
141
+ var MAX_RESPONSE_BYTES = 1024 * 1024;
142
+ var DaemonResponse = Schema.fromJsonString(
143
+ Schema.Struct({
144
+ version: Schema.Literal(1),
145
+ requestId: Schema.NonEmptyString,
146
+ ok: Schema.Boolean,
147
+ result: Schema.optional(Schema.Unknown),
148
+ error: Schema.optional(Schema.String)
149
+ })
150
+ );
151
+ var sendReadiness = (identity, request) => Effect2.tryPromise({
152
+ try: () => new Promise((resolve2, reject) => {
153
+ const socket = createConnection(identity.socketPath);
154
+ const decoder = new StringDecoder("utf8");
155
+ let input = "";
156
+ let settled = false;
157
+ const finish = (complete) => {
158
+ if (settled) return;
159
+ settled = true;
160
+ clearTimeout(timer);
161
+ socket.destroy();
162
+ complete();
163
+ };
164
+ const timer = setTimeout(
165
+ () => finish(
166
+ () => reject(new Error("Daemon readiness request timed out"))
167
+ ),
168
+ RESPONSE_TIMEOUT_MS
169
+ );
170
+ socket.once(
171
+ "connect",
172
+ () => socket.write(`${JSON.stringify(request)}
173
+ `)
174
+ );
175
+ socket.on("data", (chunk) => {
176
+ input += decoder.write(chunk);
177
+ if (Buffer.byteLength(input) > MAX_RESPONSE_BYTES) {
178
+ finish(
179
+ () => reject(new Error("Daemon readiness response is too large"))
180
+ );
181
+ return;
182
+ }
183
+ const boundary = input.indexOf("\n");
184
+ if (boundary !== -1) finish(() => resolve2(input.slice(0, boundary)));
185
+ });
186
+ socket.once("error", (cause) => finish(() => reject(cause)));
187
+ socket.once(
188
+ "close",
189
+ () => finish(
190
+ () => reject(new Error("Daemon closed before acknowledging readiness"))
191
+ )
192
+ );
193
+ }),
194
+ catch: (cause) => new Error("Could not report readiness to daemon", { cause })
195
+ }).pipe(
196
+ Effect2.flatMap(Schema.decodeUnknownEffect(DaemonResponse)),
197
+ Effect2.flatMap(
198
+ (response) => response.requestId === request.requestId && response.ok ? Effect2.void : Effect2.fail(new Error("Daemon did not acknowledge readiness"))
199
+ )
200
+ );
201
+ var publishDaemonReadiness = (value) => Effect2.suspend(() => {
202
+ const socketPath = process.env.DEVSESS_SOCKET;
203
+ const runId = process.env.DEVSESS_RUN_ID;
204
+ const service = process.env.DEVSESS_SERVICE;
205
+ if (socketPath === void 0 || runId === void 0 || service === void 0)
206
+ return Effect2.void;
207
+ const identity = { socketPath, runId, service };
208
+ return Effect2.acquireRelease(
209
+ Schema.decodeUnknownEffect(Schema.Json)(value).pipe(
210
+ Effect2.flatMap(
211
+ (json) => sendReadiness(identity, {
212
+ version: 1,
213
+ requestId: crypto.randomUUID(),
214
+ method: "publish",
215
+ params: { runId, service, value: json }
216
+ })
217
+ ),
218
+ Effect2.exit
219
+ ),
220
+ (result) => Exit.isSuccess(result) ? sendReadiness(identity, {
221
+ version: 1,
222
+ requestId: crypto.randomUUID(),
223
+ method: "unpublish",
224
+ params: { runId, service }
225
+ }).pipe(Effect2.catch(() => Effect2.void)) : Effect2.void
226
+ ).pipe(Effect2.asVoid);
227
+ });
228
+
229
+ // src/dev/running-signal.ts
135
230
  var RUNNING_SIGNAL_FILE = ".data/running.json";
136
231
  var runningSignalPath = (dir) => join(dir, RUNNING_SIGNAL_FILE);
137
232
  var resolveSiblingDir = (spec, fromDir) => {
@@ -142,8 +237,8 @@ var resolveSiblingDir = (spec, fromDir) => {
142
237
  const pkgJsonPath = require2.resolve(`${spec}/package.json`);
143
238
  return dirname(realpathSync(pkgJsonPath));
144
239
  };
145
- var publishRunningSignal = (filePath, value) => Effect2.acquireRelease(
146
- Effect2.gen(function* () {
240
+ var publishRunningSignal = (filePath, value) => Effect3.acquireRelease(
241
+ Effect3.gen(function* () {
147
242
  const fs = yield* FileSystem2;
148
243
  const path = yield* Path2;
149
244
  const tmp = `${filePath}.tmp`;
@@ -151,52 +246,53 @@ var publishRunningSignal = (filePath, value) => Effect2.acquireRelease(
151
246
  yield* fs.writeFileString(tmp, JSON.stringify(value));
152
247
  yield* fs.rename(tmp, filePath);
153
248
  }),
154
- () => Effect2.gen(function* () {
249
+ () => Effect3.gen(function* () {
155
250
  const fs = yield* FileSystem2;
156
- yield* fs.remove(filePath).pipe(Effect2.catch(() => Effect2.void));
251
+ yield* fs.remove(filePath).pipe(Effect3.catch(() => Effect3.void));
157
252
  })
158
253
  );
159
- var awaitRunningSignal = (filePath, opts) => Effect2.scoped(
160
- Effect2.gen(function* () {
254
+ var awaitRunningSignal = (filePath, opts) => Effect3.scoped(
255
+ Effect3.gen(function* () {
161
256
  const fs = yield* FileSystem2;
162
257
  const path = yield* Path2;
163
258
  const dir = path.dirname(filePath);
164
259
  const filename = path.basename(filePath);
165
260
  const deferred = yield* Deferred.make();
166
- const tryRead = Effect2.gen(function* () {
261
+ const tryRead = Effect3.gen(function* () {
167
262
  if (!(yield* fs.exists(filePath))) return false;
168
- const raw = yield* fs.readFileString(filePath).pipe(Effect2.catch(() => Effect2.succeed(null)));
263
+ const raw = yield* fs.readFileString(filePath).pipe(Effect3.catch(() => Effect3.succeed(null)));
169
264
  if (raw == null) return false;
170
- const parsed = yield* Effect2.try(() => opts.parse(raw)).pipe(
171
- Effect2.catch(() => Effect2.succeed(null))
265
+ const parsed = yield* Effect3.try(() => opts.parse(raw)).pipe(
266
+ Effect3.catch(() => Effect3.succeed(null))
172
267
  );
173
268
  if (parsed == null) return false;
174
269
  yield* Deferred.succeed(deferred, parsed);
175
270
  return true;
176
271
  });
177
272
  yield* fs.makeDirectory(dir, { recursive: true });
178
- yield* Effect2.acquireRelease(
179
- Effect2.sync(
273
+ yield* Effect3.acquireRelease(
274
+ Effect3.sync(
180
275
  () => (
181
276
  // Watch parent dir — the file may not exist yet, and watching a missing file errors.
182
277
  fsWatch(dir, { recursive: false }, (eventType, eventFilename) => {
183
278
  if (eventFilename !== filename) return;
184
279
  if (eventType !== "rename" && eventType !== "change") return;
185
- Effect2.runFork(tryRead);
280
+ Effect3.runFork(tryRead);
186
281
  })
187
282
  )
188
283
  ),
189
- (watcher) => Effect2.sync(() => watcher.close())
284
+ (watcher) => Effect3.sync(() => watcher.close())
190
285
  );
191
286
  yield* tryRead;
192
287
  return yield* Deferred.await(deferred);
193
288
  })
194
289
  );
195
- var publishRunning = (value) => Effect2.gen(function* () {
290
+ var publishRunning = (value) => Effect3.gen(function* () {
196
291
  const sessions = yield* DevSessions;
197
292
  yield* publishRunningSignal(runningSignalPath(sessions.dir), value);
293
+ yield* publishDaemonReadiness(value);
198
294
  });
199
- var awaitRunning = (pkg) => Effect2.gen(function* () {
295
+ var awaitRunning = (pkg) => Effect3.gen(function* () {
200
296
  const sessions = yield* DevSessions;
201
297
  return yield* awaitRunningSignal(
202
298
  runningSignalPath(resolveSiblingDir(pkg, sessions.dir)),
@@ -205,7 +301,7 @@ var awaitRunning = (pkg) => Effect2.gen(function* () {
205
301
  });
206
302
 
207
303
  // src/dev/session-state.ts
208
- import { Data as Data2, Effect as Effect3 } from "effect";
304
+ import { Data as Data2, Effect as Effect4 } from "effect";
209
305
  import { FileSystem as FileSystem3 } from "effect/FileSystem";
210
306
  import { Path as Path3 } from "effect/Path";
211
307
  import * as S from "effect/Schema";
@@ -215,7 +311,7 @@ function getPath(session) {
215
311
  return session.path("sess.json");
216
312
  }
217
313
  function read(filePath) {
218
- return Effect3.gen(function* () {
314
+ return Effect4.gen(function* () {
219
315
  const fs = yield* FileSystem3;
220
316
  if (!(yield* fs.exists(filePath))) {
221
317
  return null;
@@ -227,21 +323,21 @@ var SessionState;
227
323
  ((SessionState2) => {
228
324
  function slot(schema) {
229
325
  return {
230
- read: (session) => Effect3.gen(function* () {
326
+ read: (session) => Effect4.gen(function* () {
231
327
  const filePath = yield* getPath(session);
232
328
  const content = yield* read(filePath);
233
329
  if (content == null) return null;
234
330
  return yield* S.decodeEffect(S.fromJsonString(schema))(content).pipe(
235
- Effect3.catchTag("SchemaError", () => Effect3.succeed(null))
331
+ Effect4.catchTag("SchemaError", () => Effect4.succeed(null))
236
332
  );
237
333
  }),
238
- write: (session, data) => Effect3.gen(function* () {
334
+ write: (session, data) => Effect4.gen(function* () {
239
335
  const fs = yield* FileSystem3;
240
336
  const path = yield* Path3;
241
337
  const filePath = yield* getPath(session);
242
338
  yield* fs.makeDirectory(path.dirname(filePath), { recursive: true });
243
339
  const existing = yield* read(filePath);
244
- const parsed = yield* Effect3.try({
340
+ const parsed = yield* Effect4.try({
245
341
  try: () => JSON.parse(existing ?? "{}"),
246
342
  catch: (cause) => new SessionStateError({
247
343
  message: `Failed to parse ${filePath} as JSON`,
@@ -257,7 +353,7 @@ var SessionState;
257
353
  })(SessionState || (SessionState = {}));
258
354
 
259
355
  // src/dev/sticky-port.ts
260
- import { Effect as Effect4 } from "effect";
356
+ import { Effect as Effect5 } from "effect";
261
357
  import * as S2 from "effect/Schema";
262
358
  import getPort from "get-port";
263
359
  var DEFAULT_NAME = "default";
@@ -267,13 +363,13 @@ var StickyPorts = SessionState.slot(
267
363
  port: S2.optional(S2.Number)
268
364
  })
269
365
  );
270
- var getStickyPort = (session, options) => Effect4.gen(function* () {
366
+ var getStickyPort = (session, options) => Effect5.gen(function* () {
271
367
  const name = options?.name ?? DEFAULT_NAME;
272
368
  const file = yield* StickyPorts.read(session);
273
369
  const ports = file?.ports ?? (file?.port !== void 0 ? { [DEFAULT_NAME]: file.port } : {});
274
370
  const preferred = ports[name];
275
371
  const exclude = Object.entries(ports).filter((entry) => entry[0] !== name).map((entry) => entry[1]);
276
- const port = yield* Effect4.promise(
372
+ const port = yield* Effect5.promise(
277
373
  async () => getPort({
278
374
  port: preferred !== void 0 ? [preferred] : void 0,
279
375
  ...exclude.length > 0 ? { exclude } : {}
@@ -284,27 +380,29 @@ var getStickyPort = (session, options) => Effect4.gen(function* () {
284
380
  });
285
381
 
286
382
  // src/dev/subprocess.ts
287
- import { Effect as Effect5 } from "effect";
383
+ import { Effect as Effect6 } from "effect";
288
384
  import { ChildProcess } from "effect/unstable/process";
289
- var runManagedSubprocess = (cmd, args, opts) => Effect5.gen(function* () {
385
+ var runManagedSubprocess = (cmd, args, opts) => Effect6.gen(function* () {
290
386
  const command = ChildProcess.make(cmd, args, {
387
+ // Keep children in the caller's group so its supervisor can signal them together.
388
+ detached: false,
291
389
  stdin: "inherit",
292
390
  stdout: "inherit",
293
391
  stderr: "inherit",
294
392
  env: { ...process.env, ...opts?.env ?? {} }
295
393
  });
296
394
  const label = [cmd, ...args].join(" ");
297
- const child = yield* Effect5.acquireRelease(
298
- Effect5.gen(function* () {
395
+ const child = yield* Effect6.acquireRelease(
396
+ Effect6.gen(function* () {
299
397
  const proc = yield* command;
300
- yield* Effect5.logInfo(`[dev] started: ${label} (pid=${proc.pid})`);
398
+ yield* Effect6.logInfo(`[dev] started: ${label} (pid=${proc.pid})`);
301
399
  return proc;
302
400
  }),
303
- (proc) => Effect5.gen(function* () {
304
- yield* Effect5.logInfo(`[dev] stopping: ${label} (pid=${proc.pid})`);
401
+ (proc) => Effect6.gen(function* () {
402
+ yield* Effect6.logInfo(`[dev] stopping: ${label} (pid=${proc.pid})`);
305
403
  yield* proc.kill().pipe(
306
- Effect5.catch(
307
- (err) => Effect5.logError(
404
+ Effect6.catch(
405
+ (err) => Effect6.logError(
308
406
  `[dev] failed to stop ${label} (pid=${proc.pid}): ${err}`
309
407
  )
310
408
  )
@@ -328,4 +426,4 @@ export {
328
426
  getStickyPort,
329
427
  runManagedSubprocess
330
428
  };
331
- //# sourceMappingURL=chunk-Z7T6KVWK.js.map
429
+ //# sourceMappingURL=chunk-UVQAAP2U.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/dev-sessions.ts","../src/dev/running-signal.ts","../src/dev/daemon-readiness.ts","../src/dev/session-state.ts","../src/dev/sticky-port.ts","../src/dev/subprocess.ts"],"sourcesContent":["import { Array as A, Context, Data, Effect, Layer, Option } from 'effect';\nimport { FileSystem } from 'effect/FileSystem';\nimport { Path } from 'effect/Path';\nimport type { PlatformError } from 'effect/PlatformError';\nimport { generateSlug } from 'random-word-slugs';\n\nnamespace DevSession {\n\ttype DevSessionInput = {\n\t\tname: string;\n\t\tlastModifiedAt: Date | null;\n\t\trootDir: string;\n\t\tpathJoin: (relativePath: string) => string;\n\t};\n\n\texport function make(input: DevSessionInput) {\n\t\treturn {\n\t\t\tname: input.name,\n\t\t\tlastModifiedAt: input.lastModifiedAt,\n\t\t\tpath: (relativePath: string) =>\n\t\t\t\tEffect.succeed(input.pathJoin(relativePath)),\n\t\t\ttoString: () => input.name,\n\t\t};\n\t}\n}\n\nexport type DevSession = ReturnType<typeof DevSession.make>;\n\nexport class DevSessions extends Context.Service<\n\tDevSessions,\n\t{\n\t\treadonly dir: string;\n\t\treadonly path: (relativePath: string) => string;\n\t\treadonly getSessions: Effect.Effect<Array<DevSession>, PlatformError>;\n\t\treadonly createSession: Effect.Effect<DevSession, PlatformError>;\n\t\treadonly getLatestOrCreate: Effect.Effect<DevSession, PlatformError>;\n\t}\n>()('devsess/DevSessions') {\n\t/**\n\t * `DevSessions` explicitly rooted at `rootDir`: `dir`/`path` resolve against `rootDir`\n\t * itself (e.g. `sessions.path('drizzle')` reaches a project's real `drizzle/` folder),\n\t * while session directories are namespaced under `<rootDir>/.data/sessions`.\n\t *\n\t * Deliberately does *not* also provide `CurrentSession` — a `Layer`'s build effect\n\t * runs as soon as it's provided, before anything downstream (e.g. `cli.Command.run`'s\n\t * argv parsing) gets a say. Bundling session resolution in here would create a\n\t * session for `--help`/`--version`/a bad flag too, since those never reach a command\n\t * handler at all. Provide `CurrentSession.layer` around the handler itself instead.\n\t */\n\tstatic readonly layerAt = (rootDir: string) => buildDevSessionsLayer(rootDir);\n\n\t/**\n\t * `DevSessions.layerAt` rooted at the auto-detected project root — the nearest\n\t * ancestor of `process.cwd()` containing a `package.json`.\n\t */\n\tstatic readonly layer: Layer.Layer<\n\t\tDevSessions,\n\t\tPlatformError | ProjectRootNotFoundError,\n\t\tFileSystem | Path\n\t> = Layer.unwrap(\n\t\tEffect.suspend(() =>\n\t\t\tEffect.map(findProjectRoot, (rootDir) => DevSessions.layerAt(rootDir)),\n\t\t),\n\t);\n}\n\n/**\n * Raised by `DevSessions.layer` when no ancestor of `searchedFrom` contains a\n * `package.json`. Failing loudly beats silently falling back to `process.cwd()` — a\n * wrong root means dev sessions get written to a surprising place.\n */\nexport class ProjectRootNotFoundError extends Data.TaggedError(\n\t'ProjectRootNotFoundError',\n)<{\n\treadonly searchedFrom: string;\n}> {}\n\n/** Walks up from `process.cwd()` to the nearest ancestor containing a `package.json`. */\nconst findProjectRoot = Effect.gen(function* () {\n\tconst fs = yield* FileSystem;\n\tconst path = yield* Path;\n\tconst startDir = process.cwd();\n\n\tconst walkUp = (\n\t\tdir: string,\n\t): Effect.Effect<string, PlatformError | ProjectRootNotFoundError> =>\n\t\tEffect.gen(function* () {\n\t\t\tif (yield* fs.exists(path.join(dir, 'package.json'))) {\n\t\t\t\treturn dir;\n\t\t\t}\n\t\t\tconst parent = path.dirname(dir);\n\t\t\tif (parent === dir) {\n\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\tnew ProjectRootNotFoundError({ searchedFrom: startDir }),\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn yield* walkUp(parent);\n\t\t});\n\n\treturn yield* walkUp(startDir);\n});\n\n/** The listing/creation logic shared by every `DevSessions` layer, parameterized on the literal directory session subdirs live under. */\nconst buildDevSessionsCore = (sessionsDir: string) =>\n\tEffect.gen(function* () {\n\t\tconst fs = yield* FileSystem;\n\t\tconst path = yield* Path;\n\n\t\tyield* Effect.logDebug(`DevSessions dir: ${sessionsDir}`);\n\n\t\tconst getSessions = Effect.gen(function* () {\n\t\t\tconst entries = yield* fs\n\t\t\t\t.readDirectory(sessionsDir)\n\t\t\t\t.pipe(Effect.catch(() => Effect.succeed([] as Array<string>)));\n\n\t\t\tconst possibleSessions = yield* Effect.all(\n\t\t\t\tentries.map((entry) =>\n\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\tconst stat = yield* fs.stat(path.join(sessionsDir, entry));\n\t\t\t\t\t\tif (stat.type !== 'Directory') return Option.none();\n\t\t\t\t\t\treturn Option.some(\n\t\t\t\t\t\t\tDevSession.make({\n\t\t\t\t\t\t\t\tname: entry,\n\t\t\t\t\t\t\t\tlastModifiedAt: Option.getOrNull(stat.mtime),\n\t\t\t\t\t\t\t\trootDir: sessionsDir,\n\t\t\t\t\t\t\t\tpathJoin: (relativePath: string) =>\n\t\t\t\t\t\t\t\t\tpath.join(sessionsDir, entry, relativePath),\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t\t{ concurrency: 'unbounded' },\n\t\t\t);\n\n\t\t\treturn A.getSomes(possibleSessions);\n\t\t});\n\n\t\tconst createSession = Effect.gen(function* () {\n\t\t\tconst slug = generateSlug(1, { partsOfSpeech: ['noun'] });\n\t\t\tyield* fs.makeDirectory(path.join(sessionsDir, slug), {\n\t\t\t\trecursive: true,\n\t\t\t});\n\t\t\treturn DevSession.make({\n\t\t\t\tname: slug,\n\t\t\t\tlastModifiedAt: null,\n\t\t\t\trootDir: sessionsDir,\n\t\t\t\tpathJoin: (relativePath: string) =>\n\t\t\t\t\tpath.join(sessionsDir, slug, relativePath),\n\t\t\t});\n\t\t});\n\n\t\tconst getLatestOrCreate = Effect.gen(function* () {\n\t\t\tyield* fs.makeDirectory(sessionsDir, { recursive: true });\n\n\t\t\tconst sessions = yield* getSessions;\n\t\t\tif (sessions.length > 0) {\n\t\t\t\tsessions.sort(\n\t\t\t\t\t(a, b) =>\n\t\t\t\t\t\t(b.lastModifiedAt?.getTime() ?? 0) -\n\t\t\t\t\t\t(a.lastModifiedAt?.getTime() ?? 0),\n\t\t\t\t);\n\t\t\t\tconst latest = sessions[0];\n\t\t\t\treturn latest as DevSession;\n\t\t\t}\n\n\t\t\treturn yield* createSession;\n\t\t});\n\n\t\treturn { getSessions, createSession, getLatestOrCreate };\n\t});\n\n/**\n * The one `DevSessions` layer constructor: `dir`/`path` resolve against `rootDir`\n * itself, while session directories are namespaced under `<rootDir>/.data/sessions` —\n * the library owns that layout, so every caller (`DevSessions.layerAt`, the async\n * facade's `createDevSessions`) means the same thing by `rootDir`.\n */\nconst buildDevSessionsLayer = (rootDir: string) =>\n\tLayer.effect(\n\t\tDevSessions,\n\t\tEffect.gen(function* () {\n\t\t\tconst path = yield* Path;\n\t\t\tconst sessionsDir = path.join(rootDir, '.data', 'sessions');\n\t\t\tconst core = yield* buildDevSessionsCore(sessionsDir);\n\t\t\treturn {\n\t\t\t\tdir: rootDir,\n\t\t\t\tpath: (relativePath: string) => path.join(rootDir, relativePath),\n\t\t\t\t...core,\n\t\t\t};\n\t\t}),\n\t);\n","import { watch as fsWatch, realpathSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { dirname, join, resolve } from 'node:path';\nimport { Deferred, Effect } from 'effect';\nimport { FileSystem } from 'effect/FileSystem';\nimport { Path } from 'effect/Path';\nimport { DevSessions } from '../dev-sessions';\nimport { publishDaemonReadiness } from './daemon-readiness';\n\nconst RUNNING_SIGNAL_FILE = '.data/running.json';\n\n/** Path to the running-signal file for a dev-session (or sibling package) directory. */\nexport const runningSignalPath = (dir: string) =>\n\tjoin(dir, RUNNING_SIGNAL_FILE);\n\n/**\n * Resolves `spec` to a directory: relative/absolute paths are resolved against\n * `fromDir`, anything else is treated as a package name and resolved via its\n * `package.json`.\n */\nexport const resolveSiblingDir = (spec: string, fromDir: string) => {\n\tif (spec.startsWith('.') || spec.startsWith('/')) {\n\t\treturn resolve(fromDir, spec);\n\t}\n\tconst require = createRequire(join(fromDir, 'package.json'));\n\tconst pkgJsonPath = require.resolve(`${spec}/package.json`);\n\treturn dirname(realpathSync(pkgJsonPath));\n};\n\n/** Atomically writes `value` as JSON to `filePath` and removes it on release. */\nexport const publishRunningSignal = (filePath: string, value: unknown) =>\n\tEffect.acquireRelease(\n\t\tEffect.gen(function* () {\n\t\t\tconst fs = yield* FileSystem;\n\t\t\tconst path = yield* Path;\n\t\t\tconst tmp = `${filePath}.tmp`;\n\t\t\tyield* fs.makeDirectory(path.dirname(filePath), { recursive: true });\n\t\t\t// Write to a temp file then rename atomically so readers never see a partial file.\n\t\t\tyield* fs.writeFileString(tmp, JSON.stringify(value));\n\t\t\tyield* fs.rename(tmp, filePath);\n\t\t}),\n\t\t() =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst fs = yield* FileSystem;\n\t\t\t\tyield* fs.remove(filePath).pipe(Effect.catch(() => Effect.void));\n\t\t\t}),\n\t);\n\n/** Watches parent directory for the signal file and resolves once it can be parsed. */\nexport const awaitRunningSignal = <T>(\n\tfilePath: string,\n\topts: { parse: (raw: string) => T },\n) =>\n\tEffect.scoped(\n\t\tEffect.gen(function* () {\n\t\t\tconst fs = yield* FileSystem;\n\t\t\tconst path = yield* Path;\n\t\t\tconst dir = path.dirname(filePath);\n\t\t\tconst filename = path.basename(filePath);\n\n\t\t\tconst deferred = yield* Deferred.make<T>();\n\n\t\t\tconst tryRead = Effect.gen(function* () {\n\t\t\t\tif (!(yield* fs.exists(filePath))) return false;\n\t\t\t\tconst raw = yield* fs\n\t\t\t\t\t.readFileString(filePath)\n\t\t\t\t\t.pipe(Effect.catch(() => Effect.succeed(null)));\n\t\t\t\tif (raw == null) return false;\n\t\t\t\tconst parsed = yield* Effect.try(() => opts.parse(raw)).pipe(\n\t\t\t\t\tEffect.catch(() => Effect.succeed(null)),\n\t\t\t\t);\n\t\t\t\tif (parsed == null) return false;\n\t\t\t\tyield* Deferred.succeed(deferred, parsed);\n\t\t\t\treturn true;\n\t\t\t});\n\n\t\t\t// fsWatch throws synchronously if `dir` doesn't exist yet — e.g. a sibling\n\t\t\t// package's dev script has never run — so ensure it's there first.\n\t\t\tyield* fs.makeDirectory(dir, { recursive: true });\n\n\t\t\tyield* Effect.acquireRelease(\n\t\t\t\tEffect.sync(() =>\n\t\t\t\t\t// Watch parent dir — the file may not exist yet, and watching a missing file errors.\n\t\t\t\t\tfsWatch(dir, { recursive: false }, (eventType, eventFilename) => {\n\t\t\t\t\t\tif (eventFilename !== filename) return;\n\t\t\t\t\t\tif (eventType !== 'rename' && eventType !== 'change') return;\n\t\t\t\t\t\tEffect.runFork(tryRead);\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t\t(watcher) => Effect.sync(() => watcher.close()),\n\t\t\t);\n\n\t\t\tyield* tryRead;\n\t\t\treturn yield* Deferred.await(deferred);\n\t\t}),\n\t);\n\n/**\n * Publishes `value` at the project root's running-signal file, so a sibling package's\n * dev script can `awaitRunning` it. Removed when the enclosing scope closes.\n */\nexport const publishRunning = (value: unknown) =>\n\tEffect.gen(function* () {\n\t\tconst sessions = yield* DevSessions;\n\t\tyield* publishRunningSignal(runningSignalPath(sessions.dir), value);\n\t\tyield* publishDaemonReadiness(value);\n\t});\n\n/**\n * Awaits the running-signal file of another package in the workspace (`pkg`, resolved\n * relative to the project root the same way `resolveSiblingDir` resolves any spec).\n */\nexport const awaitRunning = <T>(pkg: string) =>\n\tEffect.gen(function* () {\n\t\tconst sessions = yield* DevSessions;\n\t\treturn yield* awaitRunningSignal<T>(\n\t\t\trunningSignalPath(resolveSiblingDir(pkg, sessions.dir)),\n\t\t\t{ parse: (raw) => JSON.parse(raw) as T },\n\t\t);\n\t});\n","import { createConnection } from 'node:net';\nimport { StringDecoder } from 'node:string_decoder';\nimport { Effect, Exit, Schema } from 'effect';\n\nconst RESPONSE_TIMEOUT_MS = 200;\nconst MAX_RESPONSE_BYTES = 1024 * 1024;\n\nconst DaemonResponse = Schema.fromJsonString(\n\tSchema.Struct({\n\t\tversion: Schema.Literal(1),\n\t\trequestId: Schema.NonEmptyString,\n\t\tok: Schema.Boolean,\n\t\tresult: Schema.optional(Schema.Unknown),\n\t\terror: Schema.optional(Schema.String),\n\t}),\n);\n\ntype ServiceIdentity = {\n\treadonly socketPath: string;\n\treadonly runId: string;\n\treadonly service: string;\n};\n\nconst sendReadiness = (\n\tidentity: ServiceIdentity,\n\trequest: {\n\t\treadonly version: 1;\n\t\treadonly requestId: string;\n\t\treadonly method: 'publish' | 'unpublish';\n\t\treadonly params: {\n\t\t\treadonly runId: string;\n\t\t\treadonly service: string;\n\t\t\treadonly value?: Schema.Json;\n\t\t};\n\t},\n) =>\n\tEffect.tryPromise({\n\t\ttry: () =>\n\t\t\tnew Promise<string>((resolve, reject) => {\n\t\t\t\tconst socket = createConnection(identity.socketPath);\n\t\t\t\tconst decoder = new StringDecoder('utf8');\n\t\t\t\tlet input = '';\n\t\t\t\tlet settled = false;\n\t\t\t\tconst finish = (complete: () => void) => {\n\t\t\t\t\tif (settled) return;\n\t\t\t\t\tsettled = true;\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t\tsocket.destroy();\n\t\t\t\t\tcomplete();\n\t\t\t\t};\n\t\t\t\tconst timer = setTimeout(\n\t\t\t\t\t() =>\n\t\t\t\t\t\tfinish(() =>\n\t\t\t\t\t\t\treject(new Error('Daemon readiness request timed out')),\n\t\t\t\t\t\t),\n\t\t\t\t\tRESPONSE_TIMEOUT_MS,\n\t\t\t\t);\n\t\t\t\tsocket.once('connect', () =>\n\t\t\t\t\tsocket.write(`${JSON.stringify(request)}\\n`),\n\t\t\t\t);\n\t\t\t\tsocket.on('data', (chunk) => {\n\t\t\t\t\tinput += decoder.write(chunk);\n\t\t\t\t\tif (Buffer.byteLength(input) > MAX_RESPONSE_BYTES) {\n\t\t\t\t\t\tfinish(() =>\n\t\t\t\t\t\t\treject(new Error('Daemon readiness response is too large')),\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst boundary = input.indexOf('\\n');\n\t\t\t\t\tif (boundary !== -1) finish(() => resolve(input.slice(0, boundary)));\n\t\t\t\t});\n\t\t\t\tsocket.once('error', (cause) => finish(() => reject(cause)));\n\t\t\t\tsocket.once('close', () =>\n\t\t\t\t\tfinish(() =>\n\t\t\t\t\t\treject(new Error('Daemon closed before acknowledging readiness')),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}),\n\t\tcatch: (cause) =>\n\t\t\tnew Error('Could not report readiness to daemon', { cause }),\n\t}).pipe(\n\t\tEffect.flatMap(Schema.decodeUnknownEffect(DaemonResponse)),\n\t\tEffect.flatMap((response) =>\n\t\t\tresponse.requestId === request.requestId && response.ok\n\t\t\t\t? Effect.void\n\t\t\t\t: Effect.fail(new Error('Daemon did not acknowledge readiness')),\n\t\t),\n\t);\n\nexport const publishDaemonReadiness = (value: unknown) =>\n\tEffect.suspend(() => {\n\t\tconst socketPath = process.env.DEVSESS_SOCKET;\n\t\tconst runId = process.env.DEVSESS_RUN_ID;\n\t\tconst service = process.env.DEVSESS_SERVICE;\n\t\tif (\n\t\t\tsocketPath === undefined ||\n\t\t\trunId === undefined ||\n\t\t\tservice === undefined\n\t\t)\n\t\t\treturn Effect.void;\n\t\tconst identity = { socketPath, runId, service };\n\t\treturn Effect.acquireRelease(\n\t\t\tSchema.decodeUnknownEffect(Schema.Json)(value).pipe(\n\t\t\t\tEffect.flatMap((json) =>\n\t\t\t\t\tsendReadiness(identity, {\n\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\trequestId: crypto.randomUUID(),\n\t\t\t\t\t\tmethod: 'publish',\n\t\t\t\t\t\tparams: { runId, service, value: json },\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t\tEffect.exit,\n\t\t\t),\n\t\t\t(result) =>\n\t\t\t\tExit.isSuccess(result)\n\t\t\t\t\t? sendReadiness(identity, {\n\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\trequestId: crypto.randomUUID(),\n\t\t\t\t\t\t\tmethod: 'unpublish',\n\t\t\t\t\t\t\tparams: { runId, service },\n\t\t\t\t\t\t}).pipe(Effect.catch(() => Effect.void))\n\t\t\t\t\t: Effect.void,\n\t\t).pipe(Effect.asVoid);\n\t});\n","import { Data, Effect } from 'effect';\nimport { FileSystem } from 'effect/FileSystem';\nimport { Path } from 'effect/Path';\nimport * as S from 'effect/Schema';\nimport type { DevSession } from '../dev-sessions';\n\nexport class SessionStateError extends Data.TaggedError('SessionStateError')<{\n\tmessage: string;\n\tcause?: unknown;\n}> {}\n\nfunction getPath(session: DevSession) {\n\treturn session.path('sess.json');\n}\n\nfunction read(filePath: string) {\n\treturn Effect.gen(function* () {\n\t\tconst fs = yield* FileSystem;\n\t\tif (!(yield* fs.exists(filePath))) {\n\t\t\treturn null;\n\t\t}\n\t\treturn yield* fs.readFileString(filePath);\n\t});\n}\n\nexport namespace SessionState {\n\ttype Shape = S.Top;\n\n\texport function slot<T extends Shape>(schema: T) {\n\t\treturn {\n\t\t\tread: (session: DevSession) =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst filePath = yield* getPath(session);\n\t\t\t\t\tconst content = yield* read(filePath);\n\t\t\t\t\tif (content == null) return null;\n\t\t\t\t\treturn yield* S.decodeEffect(S.fromJsonString(schema))(content).pipe(\n\t\t\t\t\t\tEffect.catchTag('SchemaError', () => Effect.succeed(null)),\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\twrite: (session: DevSession, data: T['Type']) =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst fs = yield* FileSystem;\n\t\t\t\t\tconst path = yield* Path;\n\t\t\t\t\tconst filePath = yield* getPath(session);\n\t\t\t\t\tyield* fs.makeDirectory(path.dirname(filePath), { recursive: true });\n\t\t\t\t\tconst existing = yield* read(filePath);\n\t\t\t\t\tconst parsed = yield* Effect.try({\n\t\t\t\t\t\ttry: () => JSON.parse(existing ?? '{}') as Record<string, unknown>,\n\t\t\t\t\t\tcatch: (cause) =>\n\t\t\t\t\t\t\tnew SessionStateError({\n\t\t\t\t\t\t\t\tmessage: `Failed to parse ${filePath} as JSON`,\n\t\t\t\t\t\t\t\tcause,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t});\n\t\t\t\t\tconst merged = { ...parsed, ...(data as Record<string, unknown>) };\n\t\t\t\t\tyield* fs.writeFileString(filePath, JSON.stringify(merged));\n\t\t\t\t}),\n\t\t};\n\t}\n}\n","import { Effect } from 'effect';\nimport * as S from 'effect/Schema';\nimport getPort from 'get-port';\nimport type { DevSession } from '../dev-sessions';\nimport { SessionState } from './session-state';\n\nconst DEFAULT_NAME = 'default';\n\n/**\n * Reads both the current `{ ports: Record<string, number> }` shape and the legacy\n * top-level `{ port: number }` shape, so a session written before named ports existed\n * still yields its remembered port (as `default`). Writes only ever use `ports` —\n * the legacy `port` key is never touched again once the new shape is written.\n */\nconst StickyPorts = SessionState.slot(\n\tS.Struct({\n\t\tports: S.optional(S.Record(S.String, S.Number)),\n\t\tport: S.optional(S.Number),\n\t}),\n);\n\nexport const getStickyPort = (\n\tsession: DevSession,\n\toptions?: { name?: string },\n) =>\n\tEffect.gen(function* () {\n\t\tconst name = options?.name ?? DEFAULT_NAME;\n\n\t\tconst file = yield* StickyPorts.read(session);\n\t\tconst ports =\n\t\t\tfile?.ports ??\n\t\t\t(file?.port !== undefined ? { [DEFAULT_NAME]: file.port } : {});\n\n\t\tconst preferred = ports[name];\n\t\tconst exclude = Object.entries(ports)\n\t\t\t.filter((entry) => entry[0] !== name)\n\t\t\t.map((entry) => entry[1]);\n\n\t\tconst port = yield* Effect.promise(async () =>\n\t\t\tgetPort({\n\t\t\t\tport: preferred !== undefined ? [preferred] : undefined,\n\t\t\t\t...(exclude.length > 0 ? { exclude } : {}),\n\t\t\t}),\n\t\t);\n\n\t\tyield* StickyPorts.write(session, { ports: { ...ports, [name]: port } });\n\n\t\treturn port;\n\t});\n","import { Effect } from 'effect';\nimport { ChildProcess } from 'effect/unstable/process';\n\nexport const runManagedSubprocess = (\n\tcmd: string,\n\targs: string[],\n\topts?: { env?: Record<string, string> },\n) =>\n\tEffect.gen(function* () {\n\t\tconst command = ChildProcess.make(cmd, args, {\n\t\t\t// Keep children in the caller's group so its supervisor can signal them together.\n\t\t\tdetached: false,\n\t\t\tstdin: 'inherit',\n\t\t\tstdout: 'inherit',\n\t\t\tstderr: 'inherit',\n\t\t\tenv: { ...process.env, ...(opts?.env ?? {}) },\n\t\t});\n\n\t\tconst label = [cmd, ...args].join(' ');\n\n\t\t// Registers against the ambient scope, not a scope of its own — the\n\t\t// child must outlive this call (it doesn't resolve until the child\n\t\t// exits) and get killed only when the caller's scope closes.\n\t\tconst child = yield* Effect.acquireRelease(\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst proc = yield* command;\n\t\t\t\tyield* Effect.logInfo(`[dev] started: ${label} (pid=${proc.pid})`);\n\t\t\t\treturn proc;\n\t\t\t}),\n\t\t\t(proc) =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tyield* Effect.logInfo(`[dev] stopping: ${label} (pid=${proc.pid})`);\n\t\t\t\t\tyield* proc\n\t\t\t\t\t\t.kill()\n\t\t\t\t\t\t.pipe(\n\t\t\t\t\t\t\tEffect.catch((err) =>\n\t\t\t\t\t\t\t\tEffect.logError(\n\t\t\t\t\t\t\t\t\t`[dev] failed to stop ${label} (pid=${proc.pid}): ${err}`,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t}),\n\t\t);\n\n\t\treturn yield* child.exitCode;\n\t});\n"],"mappings":"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","names":["DevSession","Effect","FileSystem","Path","Effect","resolve","require","Effect","FileSystem","Path","Data","Effect","FileSystem","Path","SessionState","Effect","S","Effect","Effect"]}
@@ -0,0 +1,3 @@
1
+ import { Effect } from 'effect';
2
+ export declare const publishDaemonReadiness: (value: unknown) => Effect.Effect<void, never, import("effect/Scope").Scope>;
3
+ //# sourceMappingURL=daemon-readiness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon-readiness.d.ts","sourceRoot":"","sources":["../../src/dev/daemon-readiness.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAgB,MAAM,QAAQ,CAAC;AAuF9C,eAAO,MAAM,sBAAsB,UAAW,OAAO,6DAkClD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"running-signal.d.ts","sourceRoot":"","sources":["../../src/dev/running-signal.ts"],"names":[],"mappings":"AAGA,OAAO,EAAY,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAI9C,wFAAwF;AACxF,eAAO,MAAM,iBAAiB,QAAS,MAAM,WACd,CAAC;AAEhC;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,SAAU,MAAM,WAAW,MAAM,WAO9D,CAAC;AAEF,iFAAiF;AACjF,eAAO,MAAM,oBAAoB,aAAc,MAAM,SAAS,OAAO,wHAgBnE,CAAC;AAEH,uFAAuF;AACvF,eAAO,MAAM,kBAAkB,GAAI,CAAC,YACzB,MAAM,QACV;IAAE,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC,CAAA;CAAE,sFA4ClC,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,cAAc,UAAW,OAAO,sIAI1C,CAAC;AAEJ;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,CAAC,OAAO,MAAM,oGAOxC,CAAC"}
1
+ {"version":3,"file":"running-signal.d.ts","sourceRoot":"","sources":["../../src/dev/running-signal.ts"],"names":[],"mappings":"AAGA,OAAO,EAAY,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAK9C,wFAAwF;AACxF,eAAO,MAAM,iBAAiB,QAAS,MAAM,WACd,CAAC;AAEhC;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,SAAU,MAAM,WAAW,MAAM,WAO9D,CAAC;AAEF,iFAAiF;AACjF,eAAO,MAAM,oBAAoB,aAAc,MAAM,SAAS,OAAO,wHAgBnE,CAAC;AAEH,uFAAuF;AACvF,eAAO,MAAM,kBAAkB,GAAI,CAAC,YACzB,MAAM,QACV;IAAE,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC,CAAA;CAAE,sFA4ClC,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,cAAc,UAAW,OAAO,sIAK1C,CAAC;AAEJ;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,CAAC,OAAO,MAAM,oGAOxC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"subprocess.d.ts","sourceRoot":"","sources":["../../src/dev/subprocess.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGhC,eAAO,MAAM,oBAAoB,QAC3B,MAAM,QACL,MAAM,EAAE,SACP;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,0OAqCrC,CAAC"}
1
+ {"version":3,"file":"subprocess.d.ts","sourceRoot":"","sources":["../../src/dev/subprocess.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGhC,eAAO,MAAM,oBAAoB,QAC3B,MAAM,QACL,MAAM,EAAE,SACP;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,0OAuCrC,CAAC"}
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  getStickyPort,
8
8
  publishRunning,
9
9
  runManagedSubprocess
10
- } from "./chunk-Z7T6KVWK.js";
10
+ } from "./chunk-UVQAAP2U.js";
11
11
 
12
12
  // src/current-session.ts
13
13
  import { Context, Effect, Layer } from "effect";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devsess",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Isolated, managed dev servers — each worktree gets its own session, with its own port and its own database",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/fdarian/devsess#readme",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/dev-sessions.ts","../src/dev/running-signal.ts","../src/dev/session-state.ts","../src/dev/sticky-port.ts","../src/dev/subprocess.ts"],"sourcesContent":["import { Array as A, Context, Data, Effect, Layer, Option } from 'effect';\nimport { FileSystem } from 'effect/FileSystem';\nimport { Path } from 'effect/Path';\nimport type { PlatformError } from 'effect/PlatformError';\nimport { generateSlug } from 'random-word-slugs';\n\nnamespace DevSession {\n\ttype DevSessionInput = {\n\t\tname: string;\n\t\tlastModifiedAt: Date | null;\n\t\trootDir: string;\n\t\tpathJoin: (relativePath: string) => string;\n\t};\n\n\texport function make(input: DevSessionInput) {\n\t\treturn {\n\t\t\tname: input.name,\n\t\t\tlastModifiedAt: input.lastModifiedAt,\n\t\t\tpath: (relativePath: string) =>\n\t\t\t\tEffect.succeed(input.pathJoin(relativePath)),\n\t\t\ttoString: () => input.name,\n\t\t};\n\t}\n}\n\nexport type DevSession = ReturnType<typeof DevSession.make>;\n\nexport class DevSessions extends Context.Service<\n\tDevSessions,\n\t{\n\t\treadonly dir: string;\n\t\treadonly path: (relativePath: string) => string;\n\t\treadonly getSessions: Effect.Effect<Array<DevSession>, PlatformError>;\n\t\treadonly createSession: Effect.Effect<DevSession, PlatformError>;\n\t\treadonly getLatestOrCreate: Effect.Effect<DevSession, PlatformError>;\n\t}\n>()('devsess/DevSessions') {\n\t/**\n\t * `DevSessions` explicitly rooted at `rootDir`: `dir`/`path` resolve against `rootDir`\n\t * itself (e.g. `sessions.path('drizzle')` reaches a project's real `drizzle/` folder),\n\t * while session directories are namespaced under `<rootDir>/.data/sessions`.\n\t *\n\t * Deliberately does *not* also provide `CurrentSession` — a `Layer`'s build effect\n\t * runs as soon as it's provided, before anything downstream (e.g. `cli.Command.run`'s\n\t * argv parsing) gets a say. Bundling session resolution in here would create a\n\t * session for `--help`/`--version`/a bad flag too, since those never reach a command\n\t * handler at all. Provide `CurrentSession.layer` around the handler itself instead.\n\t */\n\tstatic readonly layerAt = (rootDir: string) => buildDevSessionsLayer(rootDir);\n\n\t/**\n\t * `DevSessions.layerAt` rooted at the auto-detected project root — the nearest\n\t * ancestor of `process.cwd()` containing a `package.json`.\n\t */\n\tstatic readonly layer: Layer.Layer<\n\t\tDevSessions,\n\t\tPlatformError | ProjectRootNotFoundError,\n\t\tFileSystem | Path\n\t> = Layer.unwrap(\n\t\tEffect.suspend(() =>\n\t\t\tEffect.map(findProjectRoot, (rootDir) => DevSessions.layerAt(rootDir)),\n\t\t),\n\t);\n}\n\n/**\n * Raised by `DevSessions.layer` when no ancestor of `searchedFrom` contains a\n * `package.json`. Failing loudly beats silently falling back to `process.cwd()` — a\n * wrong root means dev sessions get written to a surprising place.\n */\nexport class ProjectRootNotFoundError extends Data.TaggedError(\n\t'ProjectRootNotFoundError',\n)<{\n\treadonly searchedFrom: string;\n}> {}\n\n/** Walks up from `process.cwd()` to the nearest ancestor containing a `package.json`. */\nconst findProjectRoot = Effect.gen(function* () {\n\tconst fs = yield* FileSystem;\n\tconst path = yield* Path;\n\tconst startDir = process.cwd();\n\n\tconst walkUp = (\n\t\tdir: string,\n\t): Effect.Effect<string, PlatformError | ProjectRootNotFoundError> =>\n\t\tEffect.gen(function* () {\n\t\t\tif (yield* fs.exists(path.join(dir, 'package.json'))) {\n\t\t\t\treturn dir;\n\t\t\t}\n\t\t\tconst parent = path.dirname(dir);\n\t\t\tif (parent === dir) {\n\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\tnew ProjectRootNotFoundError({ searchedFrom: startDir }),\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn yield* walkUp(parent);\n\t\t});\n\n\treturn yield* walkUp(startDir);\n});\n\n/** The listing/creation logic shared by every `DevSessions` layer, parameterized on the literal directory session subdirs live under. */\nconst buildDevSessionsCore = (sessionsDir: string) =>\n\tEffect.gen(function* () {\n\t\tconst fs = yield* FileSystem;\n\t\tconst path = yield* Path;\n\n\t\tyield* Effect.logDebug(`DevSessions dir: ${sessionsDir}`);\n\n\t\tconst getSessions = Effect.gen(function* () {\n\t\t\tconst entries = yield* fs\n\t\t\t\t.readDirectory(sessionsDir)\n\t\t\t\t.pipe(Effect.catch(() => Effect.succeed([] as Array<string>)));\n\n\t\t\tconst possibleSessions = yield* Effect.all(\n\t\t\t\tentries.map((entry) =>\n\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\tconst stat = yield* fs.stat(path.join(sessionsDir, entry));\n\t\t\t\t\t\tif (stat.type !== 'Directory') return Option.none();\n\t\t\t\t\t\treturn Option.some(\n\t\t\t\t\t\t\tDevSession.make({\n\t\t\t\t\t\t\t\tname: entry,\n\t\t\t\t\t\t\t\tlastModifiedAt: Option.getOrNull(stat.mtime),\n\t\t\t\t\t\t\t\trootDir: sessionsDir,\n\t\t\t\t\t\t\t\tpathJoin: (relativePath: string) =>\n\t\t\t\t\t\t\t\t\tpath.join(sessionsDir, entry, relativePath),\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t\t{ concurrency: 'unbounded' },\n\t\t\t);\n\n\t\t\treturn A.getSomes(possibleSessions);\n\t\t});\n\n\t\tconst createSession = Effect.gen(function* () {\n\t\t\tconst slug = generateSlug(1, { partsOfSpeech: ['noun'] });\n\t\t\tyield* fs.makeDirectory(path.join(sessionsDir, slug), {\n\t\t\t\trecursive: true,\n\t\t\t});\n\t\t\treturn DevSession.make({\n\t\t\t\tname: slug,\n\t\t\t\tlastModifiedAt: null,\n\t\t\t\trootDir: sessionsDir,\n\t\t\t\tpathJoin: (relativePath: string) =>\n\t\t\t\t\tpath.join(sessionsDir, slug, relativePath),\n\t\t\t});\n\t\t});\n\n\t\tconst getLatestOrCreate = Effect.gen(function* () {\n\t\t\tyield* fs.makeDirectory(sessionsDir, { recursive: true });\n\n\t\t\tconst sessions = yield* getSessions;\n\t\t\tif (sessions.length > 0) {\n\t\t\t\tsessions.sort(\n\t\t\t\t\t(a, b) =>\n\t\t\t\t\t\t(b.lastModifiedAt?.getTime() ?? 0) -\n\t\t\t\t\t\t(a.lastModifiedAt?.getTime() ?? 0),\n\t\t\t\t);\n\t\t\t\tconst latest = sessions[0];\n\t\t\t\treturn latest as DevSession;\n\t\t\t}\n\n\t\t\treturn yield* createSession;\n\t\t});\n\n\t\treturn { getSessions, createSession, getLatestOrCreate };\n\t});\n\n/**\n * The one `DevSessions` layer constructor: `dir`/`path` resolve against `rootDir`\n * itself, while session directories are namespaced under `<rootDir>/.data/sessions` —\n * the library owns that layout, so every caller (`DevSessions.layerAt`, the async\n * facade's `createDevSessions`) means the same thing by `rootDir`.\n */\nconst buildDevSessionsLayer = (rootDir: string) =>\n\tLayer.effect(\n\t\tDevSessions,\n\t\tEffect.gen(function* () {\n\t\t\tconst path = yield* Path;\n\t\t\tconst sessionsDir = path.join(rootDir, '.data', 'sessions');\n\t\t\tconst core = yield* buildDevSessionsCore(sessionsDir);\n\t\t\treturn {\n\t\t\t\tdir: rootDir,\n\t\t\t\tpath: (relativePath: string) => path.join(rootDir, relativePath),\n\t\t\t\t...core,\n\t\t\t};\n\t\t}),\n\t);\n","import { watch as fsWatch, realpathSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { dirname, join, resolve } from 'node:path';\nimport { Deferred, Effect } from 'effect';\nimport { FileSystem } from 'effect/FileSystem';\nimport { Path } from 'effect/Path';\nimport { DevSessions } from '../dev-sessions';\n\nconst RUNNING_SIGNAL_FILE = '.data/running.json';\n\n/** Path to the running-signal file for a dev-session (or sibling package) directory. */\nexport const runningSignalPath = (dir: string) =>\n\tjoin(dir, RUNNING_SIGNAL_FILE);\n\n/**\n * Resolves `spec` to a directory: relative/absolute paths are resolved against\n * `fromDir`, anything else is treated as a package name and resolved via its\n * `package.json`.\n */\nexport const resolveSiblingDir = (spec: string, fromDir: string) => {\n\tif (spec.startsWith('.') || spec.startsWith('/')) {\n\t\treturn resolve(fromDir, spec);\n\t}\n\tconst require = createRequire(join(fromDir, 'package.json'));\n\tconst pkgJsonPath = require.resolve(`${spec}/package.json`);\n\treturn dirname(realpathSync(pkgJsonPath));\n};\n\n/** Atomically writes `value` as JSON to `filePath` and removes it on release. */\nexport const publishRunningSignal = (filePath: string, value: unknown) =>\n\tEffect.acquireRelease(\n\t\tEffect.gen(function* () {\n\t\t\tconst fs = yield* FileSystem;\n\t\t\tconst path = yield* Path;\n\t\t\tconst tmp = `${filePath}.tmp`;\n\t\t\tyield* fs.makeDirectory(path.dirname(filePath), { recursive: true });\n\t\t\t// Write to a temp file then rename atomically so readers never see a partial file.\n\t\t\tyield* fs.writeFileString(tmp, JSON.stringify(value));\n\t\t\tyield* fs.rename(tmp, filePath);\n\t\t}),\n\t\t() =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst fs = yield* FileSystem;\n\t\t\t\tyield* fs.remove(filePath).pipe(Effect.catch(() => Effect.void));\n\t\t\t}),\n\t);\n\n/** Watches parent directory for the signal file and resolves once it can be parsed. */\nexport const awaitRunningSignal = <T>(\n\tfilePath: string,\n\topts: { parse: (raw: string) => T },\n) =>\n\tEffect.scoped(\n\t\tEffect.gen(function* () {\n\t\t\tconst fs = yield* FileSystem;\n\t\t\tconst path = yield* Path;\n\t\t\tconst dir = path.dirname(filePath);\n\t\t\tconst filename = path.basename(filePath);\n\n\t\t\tconst deferred = yield* Deferred.make<T>();\n\n\t\t\tconst tryRead = Effect.gen(function* () {\n\t\t\t\tif (!(yield* fs.exists(filePath))) return false;\n\t\t\t\tconst raw = yield* fs\n\t\t\t\t\t.readFileString(filePath)\n\t\t\t\t\t.pipe(Effect.catch(() => Effect.succeed(null)));\n\t\t\t\tif (raw == null) return false;\n\t\t\t\tconst parsed = yield* Effect.try(() => opts.parse(raw)).pipe(\n\t\t\t\t\tEffect.catch(() => Effect.succeed(null)),\n\t\t\t\t);\n\t\t\t\tif (parsed == null) return false;\n\t\t\t\tyield* Deferred.succeed(deferred, parsed);\n\t\t\t\treturn true;\n\t\t\t});\n\n\t\t\t// fsWatch throws synchronously if `dir` doesn't exist yet — e.g. a sibling\n\t\t\t// package's dev script has never run — so ensure it's there first.\n\t\t\tyield* fs.makeDirectory(dir, { recursive: true });\n\n\t\t\tyield* Effect.acquireRelease(\n\t\t\t\tEffect.sync(() =>\n\t\t\t\t\t// Watch parent dir — the file may not exist yet, and watching a missing file errors.\n\t\t\t\t\tfsWatch(dir, { recursive: false }, (eventType, eventFilename) => {\n\t\t\t\t\t\tif (eventFilename !== filename) return;\n\t\t\t\t\t\tif (eventType !== 'rename' && eventType !== 'change') return;\n\t\t\t\t\t\tEffect.runFork(tryRead);\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t\t(watcher) => Effect.sync(() => watcher.close()),\n\t\t\t);\n\n\t\t\tyield* tryRead;\n\t\t\treturn yield* Deferred.await(deferred);\n\t\t}),\n\t);\n\n/**\n * Publishes `value` at the project root's running-signal file, so a sibling package's\n * dev script can `awaitRunning` it. Removed when the enclosing scope closes.\n */\nexport const publishRunning = (value: unknown) =>\n\tEffect.gen(function* () {\n\t\tconst sessions = yield* DevSessions;\n\t\tyield* publishRunningSignal(runningSignalPath(sessions.dir), value);\n\t});\n\n/**\n * Awaits the running-signal file of another package in the workspace (`pkg`, resolved\n * relative to the project root the same way `resolveSiblingDir` resolves any spec).\n */\nexport const awaitRunning = <T>(pkg: string) =>\n\tEffect.gen(function* () {\n\t\tconst sessions = yield* DevSessions;\n\t\treturn yield* awaitRunningSignal<T>(\n\t\t\trunningSignalPath(resolveSiblingDir(pkg, sessions.dir)),\n\t\t\t{ parse: (raw) => JSON.parse(raw) as T },\n\t\t);\n\t});\n","import { Data, Effect } from 'effect';\nimport { FileSystem } from 'effect/FileSystem';\nimport { Path } from 'effect/Path';\nimport * as S from 'effect/Schema';\nimport type { DevSession } from '../dev-sessions';\n\nexport class SessionStateError extends Data.TaggedError('SessionStateError')<{\n\tmessage: string;\n\tcause?: unknown;\n}> {}\n\nfunction getPath(session: DevSession) {\n\treturn session.path('sess.json');\n}\n\nfunction read(filePath: string) {\n\treturn Effect.gen(function* () {\n\t\tconst fs = yield* FileSystem;\n\t\tif (!(yield* fs.exists(filePath))) {\n\t\t\treturn null;\n\t\t}\n\t\treturn yield* fs.readFileString(filePath);\n\t});\n}\n\nexport namespace SessionState {\n\ttype Shape = S.Top;\n\n\texport function slot<T extends Shape>(schema: T) {\n\t\treturn {\n\t\t\tread: (session: DevSession) =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst filePath = yield* getPath(session);\n\t\t\t\t\tconst content = yield* read(filePath);\n\t\t\t\t\tif (content == null) return null;\n\t\t\t\t\treturn yield* S.decodeEffect(S.fromJsonString(schema))(content).pipe(\n\t\t\t\t\t\tEffect.catchTag('SchemaError', () => Effect.succeed(null)),\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\twrite: (session: DevSession, data: T['Type']) =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst fs = yield* FileSystem;\n\t\t\t\t\tconst path = yield* Path;\n\t\t\t\t\tconst filePath = yield* getPath(session);\n\t\t\t\t\tyield* fs.makeDirectory(path.dirname(filePath), { recursive: true });\n\t\t\t\t\tconst existing = yield* read(filePath);\n\t\t\t\t\tconst parsed = yield* Effect.try({\n\t\t\t\t\t\ttry: () => JSON.parse(existing ?? '{}') as Record<string, unknown>,\n\t\t\t\t\t\tcatch: (cause) =>\n\t\t\t\t\t\t\tnew SessionStateError({\n\t\t\t\t\t\t\t\tmessage: `Failed to parse ${filePath} as JSON`,\n\t\t\t\t\t\t\t\tcause,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t});\n\t\t\t\t\tconst merged = { ...parsed, ...(data as Record<string, unknown>) };\n\t\t\t\t\tyield* fs.writeFileString(filePath, JSON.stringify(merged));\n\t\t\t\t}),\n\t\t};\n\t}\n}\n","import { Effect } from 'effect';\nimport * as S from 'effect/Schema';\nimport getPort from 'get-port';\nimport type { DevSession } from '../dev-sessions';\nimport { SessionState } from './session-state';\n\nconst DEFAULT_NAME = 'default';\n\n/**\n * Reads both the current `{ ports: Record<string, number> }` shape and the legacy\n * top-level `{ port: number }` shape, so a session written before named ports existed\n * still yields its remembered port (as `default`). Writes only ever use `ports` —\n * the legacy `port` key is never touched again once the new shape is written.\n */\nconst StickyPorts = SessionState.slot(\n\tS.Struct({\n\t\tports: S.optional(S.Record(S.String, S.Number)),\n\t\tport: S.optional(S.Number),\n\t}),\n);\n\nexport const getStickyPort = (\n\tsession: DevSession,\n\toptions?: { name?: string },\n) =>\n\tEffect.gen(function* () {\n\t\tconst name = options?.name ?? DEFAULT_NAME;\n\n\t\tconst file = yield* StickyPorts.read(session);\n\t\tconst ports =\n\t\t\tfile?.ports ??\n\t\t\t(file?.port !== undefined ? { [DEFAULT_NAME]: file.port } : {});\n\n\t\tconst preferred = ports[name];\n\t\tconst exclude = Object.entries(ports)\n\t\t\t.filter((entry) => entry[0] !== name)\n\t\t\t.map((entry) => entry[1]);\n\n\t\tconst port = yield* Effect.promise(async () =>\n\t\t\tgetPort({\n\t\t\t\tport: preferred !== undefined ? [preferred] : undefined,\n\t\t\t\t...(exclude.length > 0 ? { exclude } : {}),\n\t\t\t}),\n\t\t);\n\n\t\tyield* StickyPorts.write(session, { ports: { ...ports, [name]: port } });\n\n\t\treturn port;\n\t});\n","import { Effect } from 'effect';\nimport { ChildProcess } from 'effect/unstable/process';\n\nexport const runManagedSubprocess = (\n\tcmd: string,\n\targs: string[],\n\topts?: { env?: Record<string, string> },\n) =>\n\tEffect.gen(function* () {\n\t\tconst command = ChildProcess.make(cmd, args, {\n\t\t\tstdin: 'inherit',\n\t\t\tstdout: 'inherit',\n\t\t\tstderr: 'inherit',\n\t\t\tenv: { ...process.env, ...(opts?.env ?? {}) },\n\t\t});\n\n\t\tconst label = [cmd, ...args].join(' ');\n\n\t\t// Registers against the ambient scope, not a scope of its own — the\n\t\t// child must outlive this call (it doesn't resolve until the child\n\t\t// exits) and get killed only when the caller's scope closes.\n\t\tconst child = yield* Effect.acquireRelease(\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst proc = yield* command;\n\t\t\t\tyield* Effect.logInfo(`[dev] started: ${label} (pid=${proc.pid})`);\n\t\t\t\treturn proc;\n\t\t\t}),\n\t\t\t(proc) =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tyield* Effect.logInfo(`[dev] stopping: ${label} (pid=${proc.pid})`);\n\t\t\t\t\tyield* proc\n\t\t\t\t\t\t.kill()\n\t\t\t\t\t\t.pipe(\n\t\t\t\t\t\t\tEffect.catch((err) =>\n\t\t\t\t\t\t\t\tEffect.logError(\n\t\t\t\t\t\t\t\t\t`[dev] failed to stop ${label} (pid=${proc.pid}): ${err}`,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t}),\n\t\t);\n\n\t\treturn yield* child.exitCode;\n\t});\n"],"mappings":"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","names":["DevSession","Effect","FileSystem","Path","require","Effect","FileSystem","Path","Data","Effect","FileSystem","Path","SessionState","Effect","S","Effect","Effect"]}