@denvig/sdk 0.7.0-alpha.4

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.
@@ -0,0 +1,764 @@
1
+ import { z } from "zod";
2
+
3
+ //#region src/lib/actions/types.d.ts
4
+ type Actions = Record<string, string[]>;
5
+ //#endregion
6
+ //#region src/schemas/config.d.ts
7
+ /**
8
+ * Global configuration for the system.
9
+ *
10
+ * This is located in ~/.denvig/config.yml but can be overridden by ENV.DENVIG_GLOBAL_CONFIG_PATH
11
+ */
12
+ declare const GlobalConfigSchema: z.ZodObject<{
13
+ projectPaths: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
14
+ quickActions: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodString>>>;
15
+ services: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
16
+ cwd: z.ZodOptional<z.ZodString>;
17
+ command: z.ZodString;
18
+ http: z.ZodOptional<z.ZodObject<{
19
+ port: z.ZodOptional<z.ZodNumber>;
20
+ domain: z.ZodOptional<z.ZodString>;
21
+ cnames: z.ZodOptional<z.ZodArray<z.ZodString>>;
22
+ secure: z.ZodOptional<z.ZodBoolean>;
23
+ }, z.core.$strip>>;
24
+ envFiles: z.ZodOptional<z.ZodArray<z.ZodString>>;
25
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
26
+ keepAlive: z.ZodOptional<z.ZodBoolean>;
27
+ startOnBoot: z.ZodOptional<z.ZodBoolean>;
28
+ }, z.core.$strip>>>;
29
+ experimental: z.ZodOptional<z.ZodObject<{
30
+ gateway: z.ZodOptional<z.ZodObject<{
31
+ enabled: z.ZodBoolean;
32
+ handler: z.ZodDefault<z.ZodEnum<{
33
+ nginx: "nginx";
34
+ }>>;
35
+ configsPath: z.ZodDefault<z.ZodString>;
36
+ }, z.core.$strip>>;
37
+ }, z.core.$strip>>;
38
+ }, z.core.$strip>;
39
+ type GlobalConfigSchema = z.infer<typeof GlobalConfigSchema>;
40
+ /**
41
+ * The per project configuration.
42
+ * This is usually loaded from ~/.denvig.yml or ~/.denvig/config.yml
43
+ *
44
+ * @example
45
+ * name: My Project
46
+ * actions:
47
+ * build:
48
+ * command: pnpm build
49
+ * clean:
50
+ * command: rf -rf dist
51
+ */
52
+ declare const ProjectConfigSchema: z.ZodObject<{
53
+ name: z.ZodOptional<z.ZodString>;
54
+ actions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
55
+ command: z.ZodString;
56
+ }, z.core.$strip>>>;
57
+ quickActions: z.ZodOptional<z.ZodArray<z.ZodString>>;
58
+ services: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
59
+ cwd: z.ZodOptional<z.ZodString>;
60
+ command: z.ZodString;
61
+ http: z.ZodOptional<z.ZodObject<{
62
+ port: z.ZodOptional<z.ZodNumber>;
63
+ domain: z.ZodOptional<z.ZodString>;
64
+ cnames: z.ZodOptional<z.ZodArray<z.ZodString>>;
65
+ secure: z.ZodOptional<z.ZodBoolean>;
66
+ }, z.core.$strip>>;
67
+ envFiles: z.ZodOptional<z.ZodArray<z.ZodString>>;
68
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
69
+ keepAlive: z.ZodOptional<z.ZodBoolean>;
70
+ startOnBoot: z.ZodOptional<z.ZodBoolean>;
71
+ }, z.core.$strip>>>;
72
+ }, z.core.$strip>;
73
+ type ProjectConfigSchema = z.infer<typeof ProjectConfigSchema>;
74
+ //#endregion
75
+ //#region src/lib/config.d.ts
76
+ type ConfigWithSourcePaths<C> = C & {
77
+ $sources: string[];
78
+ };
79
+ /**
80
+ * Load global config with the following precedence (highest to lowest):
81
+ * 1. Environment variables (DENVIG_PROJECT_PATHS, DENVIG_QUICK_ACTIONS)
82
+ * 2. ~/.denvig/config.yml
83
+ * 3. Default values
84
+ */
85
+ declare const getGlobalConfig: () => Promise<ConfigWithSourcePaths<GlobalConfigSchema>>;
86
+ //#endregion
87
+ //#region src/lib/services/launchctl.d.ts
88
+ /**
89
+ * Parsed output from launchctl print command.
90
+ */
91
+ type LaunchctlPrintOutput = {
92
+ pid?: number;
93
+ status: string;
94
+ label: string;
95
+ state: string;
96
+ lastExitCode?: number;
97
+ };
98
+ /**
99
+ * Item from launchctl list command.
100
+ */
101
+ type LaunchctlListItem = {
102
+ pid: number | '-';
103
+ status: number;
104
+ label: string;
105
+ };
106
+ /**
107
+ * Get the user domain for launchctl commands.
108
+ *
109
+ * @returns Domain string in format "gui/USER_ID"
110
+ */
111
+ declare function getUserDomain(): string;
112
+ /**
113
+ * Bootstrap a service (load and start).
114
+ *
115
+ * @param plistPath - Path to the plist file
116
+ * @returns Result with success status and output
117
+ */
118
+ declare function bootstrap(plistPath: string): Promise<{
119
+ success: boolean;
120
+ output: string;
121
+ }>;
122
+ /**
123
+ * Bootout a service (unload and stop).
124
+ *
125
+ * @param label - Service label
126
+ * @returns Result with success status and output
127
+ */
128
+ declare function bootout(label: string): Promise<{
129
+ success: boolean;
130
+ output: string;
131
+ }>;
132
+ /**
133
+ * Start a service (must be already bootstrapped).
134
+ *
135
+ * @param label - Service label
136
+ * @returns Result with success status and output
137
+ */
138
+ declare function start(label: string): Promise<{
139
+ success: boolean;
140
+ output: string;
141
+ }>;
142
+ /**
143
+ * Stop a service (keeps it bootstrapped).
144
+ *
145
+ * @param label - Service label
146
+ * @returns Result with success status and output
147
+ */
148
+ declare function stop(label: string): Promise<{
149
+ success: boolean;
150
+ output: string;
151
+ }>;
152
+ /**
153
+ * Enable a service so it can be started by launchd.
154
+ *
155
+ * @param label - Service label
156
+ * @returns Result with success status and output
157
+ */
158
+ declare function enable(label: string): Promise<{
159
+ success: boolean;
160
+ output: string;
161
+ }>;
162
+ /**
163
+ * Disable a service so launchd will not start it on login.
164
+ *
165
+ * @param label - Service label
166
+ * @returns Result with success status and output
167
+ */
168
+ declare function disable(label: string): Promise<{
169
+ success: boolean;
170
+ output: string;
171
+ }>;
172
+ /**
173
+ * Get service information.
174
+ *
175
+ * @param label - Service label
176
+ * @returns Parsed service info or null if not found
177
+ */
178
+ declare function print(label: string): Promise<LaunchctlPrintOutput | null>;
179
+ /**
180
+ * List all services matching a pattern.
181
+ *
182
+ * @param pattern - Optional pattern to filter services
183
+ * @returns Array of service items
184
+ */
185
+ declare function list(pattern?: string): Promise<LaunchctlListItem[]>;
186
+ declare const _default: {
187
+ bootstrap: typeof bootstrap;
188
+ bootout: typeof bootout;
189
+ enable: typeof enable;
190
+ disable: typeof disable;
191
+ start: typeof start;
192
+ stop: typeof stop;
193
+ print: typeof print;
194
+ list: typeof list;
195
+ getUserDomain: typeof getUserDomain;
196
+ };
197
+ //#endregion
198
+ //#region src/lib/project/git.d.ts
199
+ /** Run `git pull` in the given directory. */
200
+ declare const gitPull: (cwd: string) => Promise<boolean>;
201
+ /** Check if a git working tree has uncommitted changes. */
202
+ declare const isWorkingTreeDirty: (cwd: string) => Promise<boolean>;
203
+ type ProjectWorktree = {
204
+ /** Absolute path of the detached worktree's checkout. */path: string; /** Branch checked out in the detached worktree. */
205
+ branch: string;
206
+ };
207
+ //#endregion
208
+ //#region src/lib/project.d.ts
209
+ /**
210
+ * A project is the primary git checkout plus every detached worktree that
211
+ * descends from it. Its identity (`id`, `slug`, `refs`, `path`, `name`) is the
212
+ * primary checkout's.
213
+ *
214
+ * Everything path-sensitive (config, dependencies, actions, services) lives on
215
+ * a {@link Worktree}. Use `activeWorktree` for the checkout a command is acting
216
+ * on, `primaryWorktree` for the project root, or `worktree(branch)` to select a
217
+ * specific one.
218
+ */
219
+ declare class DenvigProject {
220
+ /** The primary checkout (`main`). Defines the project's identity. */
221
+ readonly primaryWorktree: Worktree;
222
+ /** Every checkout: the primary plus all detached worktrees. */
223
+ readonly worktrees: Worktree[];
224
+ /** The checkout this project instance is acting on. */
225
+ activeWorktree: Worktree;
226
+ private constructor();
227
+ /**
228
+ * Retrieve a project from any path inside it (the primary checkout or a
229
+ * detached worktree). The project's identity is rooted at the primary, and
230
+ * the checkout matching `projectPath` becomes the active worktree.
231
+ */
232
+ static retrieve(projectPath: string): Promise<DenvigProject>;
233
+ /** Select a worktree by branch. `main` resolves to the primary checkout. */
234
+ worktree(branch: string): Worktree | null;
235
+ /** Project identity, rooted at the primary checkout. */
236
+ get id(): string;
237
+ get slug(): string;
238
+ /**
239
+ * All identifiers for the project. See `projectRefs()` for the format
240
+ * of each ref (`id:`, `local:`, `github:`, `git:`).
241
+ */
242
+ get refs(): string[];
243
+ get name(): string;
244
+ /** Absolute path of the primary checkout. */
245
+ get path(): string;
246
+ }
247
+ //#endregion
248
+ //#region src/lib/projectInfo.d.ts
249
+ type ServiceStatus$1 = 'running' | 'stopped' | 'none';
250
+ type ProjectInfo = {
251
+ id: string;
252
+ slug: string;
253
+ name: string;
254
+ path: string;
255
+ refs: string[];
256
+ worktrees: ProjectWorktree[];
257
+ config: ProjectConfigSchema | null;
258
+ serviceStatus: ServiceStatus$1;
259
+ };
260
+ type GetProjectInfoOptions = {
261
+ /** Pre-fetched launchctl list to avoid repeated shell calls */launchctlList?: LaunchctlListItem[]; /** Include service status in the response (requires launchctl calls) */
262
+ includeServiceStatus?: boolean;
263
+ };
264
+ //#endregion
265
+ //#region src/types/responses.d.ts
266
+ /**
267
+ * Service information for display.
268
+ */
269
+ type ServiceInfo = {
270
+ name: string;
271
+ cwd: string;
272
+ command: string;
273
+ http?: {
274
+ port?: number;
275
+ domain?: string;
276
+ secure?: boolean;
277
+ };
278
+ startOnBoot?: boolean;
279
+ };
280
+ /**
281
+ * Result of a service operation.
282
+ */
283
+ type ServiceResult = {
284
+ name: string;
285
+ success: boolean;
286
+ message: string;
287
+ };
288
+ /**
289
+ * Status of a running service.
290
+ */
291
+ type ServiceStatus = {
292
+ name: string;
293
+ running: boolean;
294
+ pid?: number;
295
+ uptime?: string;
296
+ command: string;
297
+ cwd: string;
298
+ logs?: string[];
299
+ logPath: string;
300
+ lastExitCode?: number;
301
+ };
302
+ /**
303
+ * Project data included in service responses.
304
+ */
305
+ type ServiceProjectData = {
306
+ id: string;
307
+ slug: string;
308
+ name: string;
309
+ path: string;
310
+ };
311
+ /**
312
+ * Unified service response for all service commands.
313
+ * Used by list, status, start, stop, and restart commands.
314
+ */
315
+ type ServiceResponse = {
316
+ name: string;
317
+ project: ServiceProjectData;
318
+ status: 'running' | 'error' | 'stopped';
319
+ pid: number | null;
320
+ /**
321
+ * Canonical URL for the service. The domain URL when this service owns
322
+ * the gateway route, otherwise a direct `http://localhost:<port>` URL.
323
+ */
324
+ url: string | null;
325
+ /**
326
+ * Direct `http://localhost:<port>` URL when an effective port is known.
327
+ * Useful when the gateway route is held by another service (e.g. a
328
+ * sibling worktree) and `url` falls back to the localhost form already.
329
+ */
330
+ localUrl: string | null; /** Effective port the service is configured to listen on. */
331
+ port: number | null; /** Port declared in the service config, if any. */
332
+ configPort: number | null;
333
+ command: string;
334
+ cwd: string;
335
+ logPath: string;
336
+ envFiles: string[];
337
+ lastExitCode: number | null;
338
+ logs?: string[];
339
+ };
340
+ /**
341
+ * Version information for a dependency.
342
+ */
343
+ type DependencyVersion = {
344
+ resolved: string;
345
+ specifier: string;
346
+ source: string;
347
+ wanted?: string;
348
+ latest?: string;
349
+ };
350
+ /**
351
+ * A project dependency from deps:list command.
352
+ */
353
+ type Dependency = {
354
+ id: string;
355
+ name: string;
356
+ versions: DependencyVersion[];
357
+ ecosystem: string;
358
+ };
359
+ /**
360
+ * An outdated dependency from deps:outdated command.
361
+ */
362
+ type OutdatedDependency = Dependency & {
363
+ wanted: string;
364
+ latest: string;
365
+ specifier: string;
366
+ isDevDependency: boolean;
367
+ currentDate?: string;
368
+ wantedDate?: string;
369
+ latestDate?: string;
370
+ };
371
+ //#endregion
372
+ //#region src/lib/plugin.d.ts
373
+ /**
374
+ * Options for outdatedDependencies method
375
+ */
376
+ type OutdatedDependenciesOptions = {
377
+ /** Use cache for registry requests (default: true) */cache?: boolean;
378
+ /**
379
+ * How many levels of the dependency tree to include.
380
+ * 0 (default) = direct dependencies only.
381
+ * N > 0 = direct deps plus transitive dependencies up to depth N.
382
+ */
383
+ depth?: number;
384
+ };
385
+ /**
386
+ * Options for deduplicateDependencies method
387
+ */
388
+ type DeduplicateDependenciesOptions = {
389
+ /** Only analyze without applying changes (default: false) */dryRun?: boolean;
390
+ };
391
+ /**
392
+ * Details of a package that can be deduplicated.
393
+ */
394
+ type DeduplicateDetail = {
395
+ name: string;
396
+ versions: string[];
397
+ optimisedVersions: string[];
398
+ };
399
+ /**
400
+ * Result of a deduplication analysis/operation.
401
+ */
402
+ type DeduplicateResult = {
403
+ ecosystem: string;
404
+ totalDependencies: number;
405
+ optimisedDependencies: number;
406
+ removals: Record<string, string[]>;
407
+ details: DeduplicateDetail[];
408
+ applied: boolean;
409
+ };
410
+ //#endregion
411
+ //#region src/lib/project/worktree.d.ts
412
+ /**
413
+ * A single git checkout belonging to a project — either the primary checkout
414
+ * or a detached worktree. Everything path-sensitive (config, dependencies,
415
+ * actions, refs) lives here, since these all differ between checkouts.
416
+ *
417
+ * A worktree's `refs`, `id` and `slug` are derived from its own path, so they
418
+ * match the values the legacy `DenvigProject` produced for that checkout. This
419
+ * keeps service state keys (which are derived from these) stable across the
420
+ * project-owns-worktrees refactor.
421
+ */
422
+ declare class Worktree {
423
+ /** Absolute path of this checkout. */
424
+ readonly path: string;
425
+ /** Branch checked out here. The primary checkout always reports `main`. */
426
+ readonly branch: string;
427
+ /** True when this is the project's primary checkout. */
428
+ readonly isPrimary: boolean;
429
+ /** All identifiers for this checkout. See `projectRefs()` for the format. */
430
+ readonly refs: string[];
431
+ readonly slug: string;
432
+ readonly id: string;
433
+ config: ConfigWithSourcePaths<ProjectConfigSchema>;
434
+ private _rootFilesCache;
435
+ private constructor();
436
+ /** Retrieve a worktree by looking up its config and root files. */
437
+ static retrieve(path: string, branch: string, isPrimary: boolean): Promise<Worktree>;
438
+ get name(): string;
439
+ /** List of files in the root of this checkout. */
440
+ get rootFiles(): string[];
441
+ get packageManagers(): string[];
442
+ get primaryPackageManager(): string | null;
443
+ dependencies(): Promise<Dependency[]>;
444
+ outdatedDependencies(options?: OutdatedDependenciesOptions): Promise<OutdatedDependency[]>;
445
+ deduplicateDependencies(options?: DeduplicateDependenciesOptions): Promise<DeduplicateResult[]>;
446
+ /** All actions that can be run for this checkout. */
447
+ get actions(): Promise<Actions>;
448
+ /** All services defined in this checkout's configuration. */
449
+ get services(): Record<string, {
450
+ command: string;
451
+ cwd?: string | undefined;
452
+ http?: {
453
+ port?: number | undefined;
454
+ domain?: string | undefined;
455
+ cnames?: string[] | undefined;
456
+ secure?: boolean | undefined;
457
+ } | undefined;
458
+ envFiles?: string[] | undefined;
459
+ env?: Record<string, string> | undefined;
460
+ keepAlive?: boolean | undefined;
461
+ startOnBoot?: boolean | undefined;
462
+ }>;
463
+ /** Find all files recursively with a given name in this checkout. */
464
+ findFilesByName(fileName: string): Promise<string[]>;
465
+ }
466
+ //#endregion
467
+ //#region src/lib/formatters/tree-node.d.ts
468
+ /**
469
+ * A node in a tree structure for rendering. The shape is produced by logic in
470
+ * the SDK (e.g. dependency chains) and consumed by the CLI's tree renderer.
471
+ */
472
+ type TreeNode = {
473
+ name: string;
474
+ version: string;
475
+ children: TreeNode[]; /** Optional ANSI color applied to the entire `name version` body. */
476
+ color?: string; /** Optional preformatted suffix appended after the version. */
477
+ suffix?: string;
478
+ };
479
+ //#endregion
480
+ //#region src/lib/deps/tree.d.ts
481
+ /**
482
+ * A dependency entry with tree metadata for rendering.
483
+ */
484
+ type TreeDependencyEntry = {
485
+ name: string;
486
+ version: string;
487
+ ecosystem: string;
488
+ isDevDependency: boolean;
489
+ depth: number;
490
+ isLast: boolean;
491
+ hasChildren: boolean;
492
+ parentPath: boolean[];
493
+ dependencyType?: string;
494
+ };
495
+ /**
496
+ * Check if a source is from devDependencies section.
497
+ */
498
+ declare const isDevDependenciesSource: (source: string) => boolean;
499
+ /**
500
+ * Build a reverse dependency chain from a target dependency back to a direct dependency.
501
+ * Returns the chain as a tree structure starting from the root, or null if chain cannot be built.
502
+ */
503
+ declare const buildReverseChain: (targetName: string, targetVersion: string, source: string, depsMap: Map<string, Dependency>) => TreeNode | null;
504
+ //#endregion
505
+ //#region src/lib/services/manager.d.ts
506
+ type ServiceConfig = NonNullable<ProjectConfigSchema['services']>[string];
507
+ /**
508
+ * Minimal project shape required by ServiceManager.
509
+ * DenvigProject structurally satisfies this type.
510
+ */
511
+ type ServiceManagerProject = {
512
+ id: string;
513
+ slug: string;
514
+ name: string;
515
+ path: string;
516
+ config: {
517
+ services?: ProjectConfigSchema['services'];
518
+ };
519
+ };
520
+ /**
521
+ * Manager for project services.
522
+ */
523
+ declare class ServiceManager {
524
+ private project;
525
+ constructor(project: ServiceManagerProject);
526
+ /**
527
+ * List all services defined in the project configuration.
528
+ */
529
+ listServices(): Promise<ServiceInfo[]>;
530
+ /**
531
+ * Build environment variables for a service.
532
+ * This loads env files and merges with explicit env config.
533
+ * All env files are optional - missing files are silently skipped.
534
+ *
535
+ * @param options.port - Effective port for the service. When provided,
536
+ * overrides any port defined in config and is exported as `PORT` in
537
+ * the service environment.
538
+ */
539
+ buildServiceEnvironment(name: string, options?: {
540
+ port?: number;
541
+ }): Promise<{
542
+ success: true;
543
+ env: Record<string, string>;
544
+ } | {
545
+ success: false;
546
+ message: string;
547
+ }>;
548
+ /**
549
+ * Decide which port to run a service on.
550
+ *
551
+ * Resolution order:
552
+ * 1. If `forceRandom`, always allocate a fresh random port (preferring the
553
+ * previously-allocated one when free).
554
+ * 2. If state already records a port for this service, reuse it. State is
555
+ * authoritative once allocated so restarts stay on the same port and
556
+ * don't re-prompt about the config port being busy. Run
557
+ * `services teardown` to reset.
558
+ * 3. Otherwise try the config port — falling back to a random port and
559
+ * flagging `conflict: true` when it's already in use.
560
+ * 4. Otherwise (no config port, no state) allocate a random port.
561
+ */
562
+ resolveServicePort(name: string, options?: {
563
+ forceRandom?: boolean;
564
+ }): Promise<{
565
+ success: true;
566
+ port: number | undefined;
567
+ source: 'config' | 'allocated' | 'state' | 'none';
568
+ conflict: boolean;
569
+ configPort?: number;
570
+ } | {
571
+ success: false;
572
+ message: string;
573
+ }>;
574
+ /**
575
+ * Start a specific service.
576
+ *
577
+ * @param options.port - Pre-resolved port to use for this service. When
578
+ * omitted, the manager resolves the port itself, auto-allocating a
579
+ * random port if the config port is busy.
580
+ * @param options.claimDomain - When the service's configured domain is
581
+ * already claimed by a different project, this flag controls whether
582
+ * this start should replace the route as an override (`true`) or
583
+ * leave the existing route alone (`false`). When undefined and the
584
+ * domain has no existing owner, the route is registered as the
585
+ * natural owner (`defaultService: true`).
586
+ * @param options.reviveIfNotRunning - When the service is already
587
+ * bootstrapped with an unchanged plist but isn't currently running,
588
+ * bootout and bootstrap again to kick it (`true`, the default — what an
589
+ * explicit `start` wants). The reconciler passes `false`: a bootstrapped
590
+ * service's liveness is launchd's job (`KeepAlive` respawns it, one-shot
591
+ * services are meant to stay exited), so re-bootstrapping an unchanged
592
+ * plist is needless churn that fights launchd.
593
+ */
594
+ startService(name: string, options?: {
595
+ port?: number;
596
+ portResolved?: boolean;
597
+ claimDomain?: boolean;
598
+ reviveIfNotRunning?: boolean;
599
+ }): Promise<ServiceResult>;
600
+ /**
601
+ * Stop a specific service.
602
+ */
603
+ stopService(name: string): Promise<ServiceResult>;
604
+ /**
605
+ * Restart a specific service.
606
+ */
607
+ restartService(name: string, options?: {
608
+ port?: number;
609
+ portResolved?: boolean;
610
+ claimDomain?: boolean;
611
+ }): Promise<ServiceResult>;
612
+ /**
613
+ * Get the status of a specific service.
614
+ */
615
+ getServiceStatus(name: string): Promise<ServiceStatus | null>;
616
+ /**
617
+ * Start all services.
618
+ */
619
+ startAll(): Promise<ServiceResult[]>;
620
+ /**
621
+ * Stop all running services.
622
+ */
623
+ stopAll(): Promise<ServiceResult[]>;
624
+ /**
625
+ * Restart all services (only those currently bootstrapped).
626
+ */
627
+ restartAll(): Promise<ServiceResult[]>;
628
+ /**
629
+ * Teardown all services for this project.
630
+ * Stops all services, removes them from launchctl, and deletes plist files.
631
+ * @param options.removeLogs - Also remove log files (default: false)
632
+ */
633
+ teardownAll(options?: {
634
+ removeLogs?: boolean;
635
+ }): Promise<ServiceResult[]>;
636
+ /**
637
+ * Check if a service is bootstrapped (loaded in launchctl).
638
+ */
639
+ isServiceBootstrapped(name: string): Promise<boolean>;
640
+ /**
641
+ * Normalize a string for use in launchctl labels and filenames.
642
+ * Replaces special characters with safe alternatives.
643
+ */
644
+ private normalizeForLabel;
645
+ /**
646
+ * Get the service label for launchctl.
647
+ * Format: denvig.[projectId].[serviceName]
648
+ */
649
+ getServiceLabel(name: string): string;
650
+ /**
651
+ * Get the denvig directory path.
652
+ */
653
+ getDenvigHomeDir(): string;
654
+ /**
655
+ * Get the plist file path.
656
+ */
657
+ getPlistPath(name: string): string;
658
+ /**
659
+ * Get the service-specific directory.
660
+ * Format: ~/.denvig/services/[projectId].[serviceName]/
661
+ */
662
+ getServiceDir(name: string): string;
663
+ /**
664
+ * Get the service-specific log directory.
665
+ * Format: ~/.denvig/services/[projectId].[serviceName]/logs/
666
+ */
667
+ getServiceLogDir(name: string): string;
668
+ /**
669
+ * Get the path to the service wrapper script.
670
+ * Includes the project slug in the filename for github projects so Login Items
671
+ * shows a meaningful name (e.g. "denvig-marcqualie-myapp-api").
672
+ */
673
+ getServiceScriptPath(name: string): string;
674
+ /**
675
+ * Get the stable log path used by the plist StandardOutPath.
676
+ * This is a symlink that always points to the current timestamped log file.
677
+ * Format: ~/.denvig/services/[serviceId]/logs/latest.log
678
+ */
679
+ getStableLogPath(name: string): string;
680
+ /**
681
+ * Get the log file path (symlink to latest log for this host).
682
+ * Format: ~/.denvig/services/[serviceId]/logs/latest.[hostname].log
683
+ */
684
+ getLogPath(name: string, _type?: 'stdout' | 'stderr'): string;
685
+ /**
686
+ * Create a new timestamped log file and update the latest symlink.
687
+ * Returns the absolute path to the new log file.
688
+ */
689
+ createLogFile(name: string): Promise<string>;
690
+ /**
691
+ * Ensure denvig directories exist.
692
+ */
693
+ ensureDenvigDirectories(): Promise<void>;
694
+ /**
695
+ * Get recent log lines from a service.
696
+ */
697
+ getRecentLogs(name: string, lines: number): Promise<string[]>;
698
+ /**
699
+ * Resolve the absolute working directory for a service.
700
+ */
701
+ private resolveServiceCwd;
702
+ /**
703
+ * Get the configuration for a specific service.
704
+ */
705
+ getServiceConfig(name: string): ServiceConfig | undefined;
706
+ /**
707
+ * Rebuild all gateway nginx configs across all projects.
708
+ * Removes stale configs and regenerates from current service definitions.
709
+ */
710
+ reconfigureGateway(): Promise<void>;
711
+ /**
712
+ * Get the canonical URL where a service can be accessed. Returns the
713
+ * domain URL only when this service currently owns the gateway route for
714
+ * its configured domain; otherwise (or when no domain is configured)
715
+ * falls back to a direct `http://localhost:<port>` URL.
716
+ */
717
+ getServiceUrl(name: string): Promise<string | null>;
718
+ /**
719
+ * Get the direct localhost URL for a service (`http://localhost:<port>`),
720
+ * or null if there's no effective port yet.
721
+ */
722
+ getServiceLocalUrl(name: string): Promise<string | null>;
723
+ /**
724
+ * Get the effective runtime port for a service, considering state-tracked
725
+ * allocations first and falling back to the config port.
726
+ */
727
+ getEffectivePort(name: string): Promise<number | undefined>;
728
+ /**
729
+ * Check if a plist file exists for a service.
730
+ */
731
+ plistExists(name: string): Promise<boolean>;
732
+ /**
733
+ * Get a unified service response for a service.
734
+ * Returns null if the service is not found in configuration.
735
+ * @param name - Service name
736
+ * @param options.includeLogs - Whether to include recent logs (default: false)
737
+ * @param options.logLines - Number of log lines to include (default: 20)
738
+ * @param options.launchctlList - Pre-fetched launchctl list for batch operations (avoids N shell calls)
739
+ */
740
+ getServiceResponse(name: string, options?: {
741
+ includeLogs?: boolean;
742
+ logLines?: number;
743
+ launchctlList?: LaunchctlListItem[];
744
+ }): Promise<ServiceResponse | null>;
745
+ }
746
+ //#endregion
747
+ //#region src/lib/teardown.d.ts
748
+ type TeardownResult = {
749
+ success: boolean;
750
+ services: ServiceResult[];
751
+ logsRemoved: boolean;
752
+ };
753
+ type ProjectTeardownResult = TeardownResult & {
754
+ project: string;
755
+ };
756
+ type TeardownOptions = {
757
+ removeLogs?: boolean;
758
+ };
759
+ /**
760
+ * Teardown all denvig services globally (across all projects).
761
+ */
762
+ declare function teardownGlobal(options?: TeardownOptions): Promise<TeardownResult>;
763
+ //#endregion
764
+ export { _default as C, ProjectConfigSchema as D, GlobalConfigSchema as E, LaunchctlListItem as S, getGlobalConfig as T, ProjectInfo as _, TreeDependencyEntry as a, gitPull as b, TreeNode as c, DeduplicateResult as d, OutdatedDependenciesOptions as f, GetProjectInfoOptions as g, ServiceResponse as h, ServiceManagerProject as i, Worktree as l, OutdatedDependency as m, teardownGlobal as n, buildReverseChain as o, Dependency as p, ServiceManager as r, isDevDependenciesSource as s, ProjectTeardownResult as t, DeduplicateDependenciesOptions as u, ServiceStatus$1 as v, ConfigWithSourcePaths as w, isWorkingTreeDirty as x, DenvigProject as y };