dev-cockpit 0.2.5 → 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../../src/mount/compose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,SAAS,UAAU,EAAE,EAC7B,IAAI,EAAE,oBAAoB,GACzB,MAAM,CAoBR"}
1
+ {"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../../src/mount/compose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,SAAS,UAAU,EAAE,EAC7B,IAAI,EAAE,oBAAoB,GACzB,MAAM,CAyBR"}
@@ -9,9 +9,22 @@
9
9
  */
10
10
  import type { MountEntry, MountSymlinkStrategy } from './types.js';
11
11
  export interface SymlinkReport {
12
- /** Symlinks created or already pointing at the right target (idempotent). */
12
+ /** Symlinks created from scratch or already pointing at the right target. */
13
13
  created: string[];
14
- /** A real (non-symlink) directory exists at the link path; left untouched. */
14
+ /**
15
+ * Install paths that previously held a real (non-symlink) directory — likely
16
+ * composer/npm-installed contents — that we removed and replaced with a
17
+ * symlink to the host clone. Surfaced separately so callers can log the
18
+ * destruction loudly: the previous contents are gone until `mount clear`
19
+ * runs the package manager again.
20
+ */
21
+ replaced: string[];
22
+ /**
23
+ * Entries that couldn't be applied — e.g. a real directory at the link path
24
+ * that resisted deletion (macOS `deny delete` ACL that survived even an ACL
25
+ * strip + retry), or `symlinkSync` failing for any other reason. Callers
26
+ * surface these to the user so they can intervene manually.
27
+ */
15
28
  skipped: string[];
16
29
  }
17
30
  export declare function applyManagedSymlinks(workspaceRoot: string, mounts: readonly MountEntry[], strategy: MountSymlinkStrategy): SymlinkReport;
@@ -1 +1 @@
1
- {"version":3,"file":"symlinks.d.ts","sourceRoot":"","sources":["../../src/mount/symlinks.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEnE,MAAM,WAAW,aAAa;IAC5B,6EAA6E;IAC7E,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,8EAA8E;IAC9E,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAgB,oBAAoB,CAClC,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,SAAS,UAAU,EAAE,EAC7B,QAAQ,EAAE,oBAAoB,GAC7B,aAAa,CA4Bf;AAED,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,SAAS,UAAU,EAAE,EAC7B,QAAQ,EAAE,oBAAoB,GAC7B,IAAI,CAWN;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC7B,KAAK,EAAE,UAAU,CAAC;CACnB;AAED,wBAAgB,oBAAoB,CAClC,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,SAAS,UAAU,EAAE,EAC7B,QAAQ,EAAE,oBAAoB,GAC7B,UAAU,EAAE,CAuBd"}
1
+ {"version":3,"file":"symlinks.d.ts","sourceRoot":"","sources":["../../src/mount/symlinks.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEnE,MAAM,WAAW,aAAa;IAC5B,6EAA6E;IAC7E,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB;;;;;;OAMG;IACH,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB;;;;;OAKG;IACH,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAgB,oBAAoB,CAClC,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,SAAS,UAAU,EAAE,EAC7B,QAAQ,EAAE,oBAAoB,GAC7B,aAAa,CAWf;AA+DD,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,SAAS,UAAU,EAAE,EAC7B,QAAQ,EAAE,oBAAoB,GAC7B,IAAI,CAWN;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC7B,KAAK,EAAE,UAAU,CAAC;CACnB;AAED,wBAAgB,oBAAoB,CAClC,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,SAAS,UAAU,EAAE,EAC7B,QAAQ,EAAE,oBAAoB,GAC7B,UAAU,EAAE,CAuBd"}
@@ -8,8 +8,21 @@
8
8
  export interface MountEntry {
9
9
  /** Absolute path on the host. */
10
10
  hostPath: string;
11
- /** Absolute path inside the container. */
12
- containerPath: string;
11
+ /**
12
+ * Absolute path inside the container. Required for `kind: 'bind'` (the
13
+ * default); omitted when `kind: 'symlink-only'`.
14
+ */
15
+ containerPath?: string;
16
+ /**
17
+ * Discriminator for how this mount is materialised.
18
+ *
19
+ * - `'bind'` (default): emit a docker-compose bind AND optionally manage
20
+ * an IDE-facing symlink via `MountSymlinkStrategy`.
21
+ * - `'symlink-only'`: no docker bind. Exists purely so the symlink
22
+ * strategy can place a host-side symlink (e.g. a wrapper-level
23
+ * `./project` symlink that redirects a pre-existing compose bind).
24
+ */
25
+ kind?: 'bind' | 'symlink-only';
13
26
  /**
14
27
  * Optional metadata attached by profiles (e.g. logical name, category,
15
28
  * source provenance). dev-cockpit treats this as opaque; profile hooks
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/mount/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,UAAU;IACzB,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,0CAA0C;IAC1C,aAAa,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,iBAAkB,SAAQ,YAAY;IACrD,6EAA6E;IAC7E,QAAQ,EAAE,UAAU,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,iEAAiE;IACjE,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED,MAAM,MAAM,mBAAmB,GAAG,CAChC,KAAK,EAAE,UAAU,EACjB,GAAG,EAAE;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,KAC3B,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,eAAe,GAAG,IAAI,CAAC;AAE9D,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CACvE"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/mount/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,UAAU;IACzB,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,cAAc,CAAC;IAC/B;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,iBAAkB,SAAQ,YAAY;IACrD,6EAA6E;IAC7E,QAAQ,EAAE,UAAU,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,iEAAiE;IACjE,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED,MAAM,MAAM,mBAAmB,GAAG,CAChC,KAAK,EAAE,UAAU,EACjB,GAAG,EAAE;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,KAC3B,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,eAAe,GAAG,IAAI,CAAC;AAE9D,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CACvE"}
package/docs/mount.md CHANGED
@@ -41,7 +41,9 @@ docker compose -f docker-compose.yml -f <stateDir>/dev-mount-overlay.yml up -d
41
41
 
42
42
  `<stateDir>` lives under `$XDG_STATE_HOME/<appName>/<workspace-hash>/`. Both files share that location, so anything cockpit knows about *this workspace's mounts* sits in one dir — clean wrapper repo, no per-developer artefacts to gitignore.
43
43
 
44
- Override the overlay path when the wrapper has its own conventions (workspace-relative or absolute):
44
+ ### Pointing the overlay at a path your compose chain already expects
45
+
46
+ If the project's compose chain auto-discovers overrides at a fixed path — e.g. a Makefile wildcard like `$(wildcard $(COMPOSE_DIR)/web/docker-compose.dev-link.yml)`, or a `docker compose -f` include — the stateDir default won't be found by that glob (it's outside the repo). Tell `mount` to write the overlay where the chain looks for it:
45
47
 
46
48
  ```yaml
47
49
  mount:
@@ -49,6 +51,8 @@ mount:
49
51
  manifestFile: dev-link.manifest.json
50
52
  ```
51
53
 
54
+ Relative paths resolve against the workspace root; absolute paths are honoured verbatim. The Makefile include path and `mount.overlayPath` are two ends of the same contract — keep them next to each other (both committed in the wrapper repo, or both in the per-user cockpit.yaml) so they move together.
55
+
52
56
  ## Mount sources
53
57
 
54
58
  Mounts come from two places, merged on `containerPath` (config wins on collision):
@@ -225,4 +229,4 @@ If your wrapper previously used a different manifest filename (e.g. a profile th
225
229
  1. **Adopt the new default**: run `mount` once. The new file replaces the legacy one (which is left orphaned in the state dir — safe to delete).
226
230
  2. **Keep the legacy filename**: set `config.mount.manifestFile: dev-link.manifest.json` in cockpit.yaml.
227
231
 
228
- Same applies to the overlay path — set `config.mount.overlayPath` if your wrapper expects a specific location for its compose stack.
232
+ Same applies to the overlay path — set `config.mount.overlayPath` if your wrapper expects a specific location for its compose stack. See "Pointing the overlay at a path your compose chain already expects" above.
@@ -54,7 +54,7 @@
54
54
  },
55
55
  "mount": {
56
56
  "$ref": "#/$defs/MountSettings",
57
- "description": "Overlay/manifest path overrides. Default overlay lives at <stateDir>/dev-mount-overlay.yml (out of the repo)."
57
+ "description": "Overlay/manifest path overrides. Default overlay lives at <stateDir>/dev-mount-overlay.yml (out of the repo). Set `overlayPath` when the project's compose chain (Makefile wildcard, compose -f include, etc.) expects the overlay at a fixed location."
58
58
  },
59
59
  "defaultPane": {
60
60
  "type": "string",
@@ -231,20 +231,31 @@
231
231
  },
232
232
  "Mount": {
233
233
  "type": "object",
234
- "required": ["hostPath", "containerPath"],
234
+ "required": ["hostPath"],
235
235
  "properties": {
236
236
  "hostPath": { "type": "string" },
237
- "containerPath": { "type": "string" },
237
+ "containerPath": { "type": "string", "description": "Absolute path inside the container. Required when kind='bind' (the default); omit for kind='symlink-only'." },
238
+ "kind": {
239
+ "type": "string",
240
+ "enum": ["bind", "symlink-only"],
241
+ "description": "How the mount is materialised. 'bind' (default) emits a docker-compose bind into the overlay. 'symlink-only' skips the docker bind — used when a host-side symlink (via Profile.mountSymlinks) is the only artefact, e.g. when redirecting a pre-existing compose bind to a dev clone."
242
+ },
238
243
  "meta": { "type": "object", "description": "Opaque to dev-cockpit core; consumed by profile hooks (e.g. awc reads meta.name and meta.type)." }
239
244
  },
240
- "additionalProperties": false
245
+ "additionalProperties": false,
246
+ "allOf": [
247
+ {
248
+ "if": { "not": { "properties": { "kind": { "const": "symlink-only" } }, "required": ["kind"] } },
249
+ "then": { "required": ["containerPath"] }
250
+ }
251
+ ]
241
252
  },
242
253
  "MountSettings": {
243
254
  "type": "object",
244
255
  "properties": {
245
256
  "overlayPath": {
246
257
  "type": "string",
247
- "description": "Override for the generated docker-compose overlay. Unset = <stateDir>/dev-mount-overlay.yml (recommended). Set values are workspace-relative; absolute paths honoured verbatim."
258
+ "description": "Override for the generated docker-compose overlay. Unset = <stateDir>/dev-mount-overlay.yml (out of the repo). Set this when the project's compose chain expects the overlay at a specific path — e.g. a wrapper Makefile wildcard or a `docker compose -f` include — that won't pick up the stateDir default. Relative values resolve against the workspace root; absolute paths honoured verbatim."
248
259
  },
249
260
  "manifestFile": {
250
261
  "type": "string",
@@ -140,3 +140,7 @@ defaultPane: repos # repos | output | health | help
140
140
  # profile:
141
141
  # myapp:
142
142
  # someKey: value
143
+
144
+ ## Mount overlay path override (optional) - tells the mount command where to write the overlay file.
145
+ mount:
146
+ overlayPath: docker/compose/web/docker-compose.dev-link.yml
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dev-cockpit",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "A reusable, domain-neutral terminal UI dev cockpit — tabbed pane shell, watcher streaming, optional Docker log tail with highlights, health framework with one-keystroke remediations, transition-only OS notifications, live-markdown Help. Profiles extend it with project-specific commands, repos, and health checks.",
5
5
  "license": "MIT",
6
6
  "repository": {